Integrator

Integrator accumulates its input over time, with a limiter on each side: the input can be bounded before it is integrated, and the output after.
3.30–3.34

Integrator accumulates its input over time, with a limiter on each side: the input can be bounded before it is integrated, and the output after. It is the building block the library makes motion from — an acceleration integrated into a velocity, a velocity into a position.

Two things set it apart from a plain accumulator. It has a throttle for approaching a singularity: as inputLimiterScaleFactor falls, motion is scaled down — but only while it is falling, so an operator can always jog back out. And its output limiter can be told to hold the output where it is rather than pulling it back to the bound.

flowchart LR
    i1(["input — the signal to integrate"]) --> B["Integrator"]
    i2(["reference — what a reset restores"]) --> B
    i3(["reset"]) --> B
    i4(["inputLimiterScaleFactor"]) --> B
    B --> o1(["output — the integral"])
    B --> o2(["inputLimiterIsActive — per channel"])
    B --> o3(["outputLimiterIsActive — per channel"])
    B --> o4(["anyInputLimiterIsActive"])
    B --> o5(["anyOutputLimiterIsActive"])

output grows by input × task period each cycle. The two …IsActive outputs are +1 at the upper bound, −1 at the lower and 0 when inactive, so they tell you which side is limiting, per channel. The two any… outputs are plain true/false across all channels.

The scale factor does two different things depending on whether that channel’s input limiter is on:

  • Input limiter on — it scales the bounds, symmetrically, always.
  • Input limiter off — it scales the input itself, but only while the factor is falling. Once it starts rising the scaling stops, so motion away from the trouble is never throttled.

Both limiters are off by default, and so the block is a plain integrator until you enable them. The output is not cleared when the controller starts — it resumes from wherever it was.

Signals

Inputs

Path Unit Range Description
input signal unit per second unbounded The signal to integrate. One element per channel. A reset writes zero here, so a trace shows zero on the reset cycle.
reference signal unit unbounded What the output is set to on a reset, per channel.
reset - - A rising value sets every channel’s output to its reference and zeroes input. It is a one-shot — the block clears it. Hold it true to pin the output at the reference.
inputLimiterScaleFactor - 0 – 1 in practice Scales either the input bounds or the input itself — see above. A single value for the whole block, even though the limiter enables are per channel. Negative values are used as their magnitude.

Outputs

Path Unit Description
output signal unit The integral, one element per channel. Not cleared by a controller stop or start — pulse reset if you need it at a known value.
inputLimiterIsActive - Per channel: +1 at the upper bound, −1 at the lower, 0 inactive.
outputLimiterIsActive - Same encoding for the output limiter.
anyInputLimiterIsActive - True while any channel’s input limiter is active.
anyOutputLimiterIsActive - True while any channel’s output limiter is active.

Parameters

Path Unit Default Range Effect
inputLimiterEnable - false per channel Bounds the input before integration. Off by default — and switching it off is what enables the singularity throttle.
inputLimiterMin signal unit per second −1.0 below the max, per channel Lower input bound, scaled by inputLimiterScaleFactor. Swapped with the max if inverted.
inputLimiterMax signal unit per second +1.0 above the min, per channel Upper input bound, scaled the same way.
outputLimiterEnable - false per channel Bounds the integral. Off by default, so the integral is unbounded until you set it.
outputLimiterMin signal unit −1.0 below the max, per channel
outputLimiterMax signal unit +1.0 above the min, per channel
outputLimiterClampDisable - false per channel Changes what hitting the bound means. False clamps the output onto the bound. True leaves it where it is and only forbids moving further past — so an output already outside is not yanked back.

All seven are persistent and survive a restart, and all are per channel. No parameters exist below this block.

Setup

  1. Link input from whatever you are integrating, and reference from the value a reset should restore — often the machine’s measured position.

  2. Leave both limiter enables false for a first pass. The block is then a plain integrator.

  3. Pulse reset and confirm every channel’s output jumps to its reference.

  4. Feed a known constant into input and confirm output ramps at that rate.

  5. Set outputLimiterMin and outputLimiterMax to the real travel, then set outputLimiterEnable true. Drive into a bound and confirm outputLimiterIsActive reads +1 or −1 for that channel.

    Step 5 stops the integral where you tell it to. If the output is already outside the band when you enable the limiter, it will jump to the bound — unless you set outputLimiterClampDisable, which holds it instead. Enable the limiter with the output inside the band.

  6. Only if you need the singularity throttle: leave inputLimiterEnable false and link inputLimiterScaleFactor from whatever measures how close the machine is to trouble.

Tuning

  1. Decide per channel whether you want the input limiter or the throttle. They are alternatives, selected by inputLimiterEnable, and they behave quite differently.
  2. Use the input limiter when the input has a hard rate bound that always applies. The scale factor then narrows those bounds symmetrically.
  3. Use the throttle when a supervisor computes a closeness measure — a manipulability figure near a singularity, say — and motion should fade out as it falls. Because the throttle releases as soon as the factor rises, motion out of the region is never slowed.
  4. Set the output limiter from the real travel, not from what the signal happens to do.
  5. Choose outputLimiterClampDisable deliberately. Clamping is right for a bound the output must sit exactly on; holding is right where being pulled back to the bound would itself be a disturbance.
  6. Pulse reset after every controller start if the integral must begin from a known value.
  7. Nothing here needs re-checking after a task-rate change.

Integrated output as the scale factor dips to 0.2 and recovers: with thelimiter off the output is throttled only while the factor falls and runs freelyas it rises, and with the limiter on it is clipped in bothdirections.

Read the asymmetry off the gap between the two output curves during the rise.

Symptom Cause Action
The output resumed from an old value after a restart Expected: the integral is not cleared at start Pulse reset after every start
The output drifts over a long session Expected: it is an integrator with no output bound unless you set one Set outputLimiterEnable and its bounds
The output jumped to the bound when the limiter was enabled Expected: it was already outside the band Enable with the output inside, or set outputLimiterClampDisable
The output is stuck outside its bound Expected with outputLimiterClampDisable set: it holds rather than pulling back Clear that parameter if you want it clamped onto the bound
The output moves differently on the way down than on the way up for the same scale factor Expected: the throttle applies only while the factor is falling This is what lets you jog back out
The throttle does nothing That channel’s inputLimiterEnable is true, so the factor scales the bounds instead Switch the input limiter off to get the throttle
The scale factor throttles some channels and scales bounds on others Expected: the factor is global and the limiter enables are per channel Make the enables consistent across channels
The throttle stayed on after the factor stopped falling Expected: it releases only on a rising factor, not a steady one Raise the factor slightly to release it
input reads zero on a trace You are looking at a reset cycle — a reset zeroes the input Read it on a non-reset cycle
A limit reads back swapped Expected: an inverted pair is corrected Write the lower value to the min
reset had to be written again for a second reset Expected: it is a one-shot Write it true again, or hold it to pin the output
One channel limits and the others do not Expected: every limit and both enables are per channel Check each element
The integral went non-numeric and stayed there A non-numeric input accumulated into the output Pulse reset with a finite reference
I cannot tell whether the throttle is engaged The block does not publish it Compare the scale factor’s direction between cycles

A starting point for integrating a velocity into a position bounded to ±0.5, with the throttle available:

inputLimiterEnable        = false
outputLimiterEnable       = true
outputLimiterMin          = -0.5
outputLimiterMax          = 0.5
outputLimiterClampDisable = false

Limits and errors

Limit Set by What happens Reported
input inputLimiterMin/Max × inputLimiterScaleFactor, while inputLimiterEnable is set Clamped before integration inputLimiterIsActive (+1/−1/0), anyInputLimiterIsActive
input, with the limiter off inputLimiterScaleFactor, only while it is falling Scaled proportionally. Never scaled while the factor rises Not reported — the latch is not published
output outputLimiterMin/Max, while outputLimiterEnable is set Clamped onto the bound, or held where it is when outputLimiterClampDisable is set. Unbounded when the limiter is off, which is the default outputLimiterIsActive, anyOutputLimiterIsActive
Limit ordering Fixed An inverted min/max pair is swapped in place Silently; read both back
inputLimiterScaleFactor Sign forced Used as its magnitude Not reported
Throttle state Not published Whether the throttle is engaged cannot be read from the parameter tree Not reported
Integral state reset Restored from reference. Not cleared by a controller stop or start Not reported
Non-numeric input Nothing Accumulates and latches. reset clears it if reference is finite Not reported
Channel count Machine configuration Fixed once the controller starts Not reported

The block raises no errors or warnings and logs nothing. Every failure above shows as a value on a trace, not as a message.


Verified against motorcortex-control3 3.30.0 (bc348fd).