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.8 minute read
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"])
outputgrows byinput× task period each cycle. The two…IsActiveoutputs 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 twoany…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
-
Link
inputfrom whatever you are integrating, andreferencefrom the value a reset should restore — often the machine’s measured position. -
Leave both limiter enables false for a first pass. The block is then a plain integrator.
-
Pulse
resetand confirm every channel’soutputjumps to itsreference. -
Feed a known constant into
inputand confirmoutputramps at that rate. -
Set
outputLimiterMinandoutputLimiterMaxto the real travel, then setoutputLimiterEnabletrue. Drive into a bound and confirmoutputLimiterIsActivereads +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. -
Only if you need the singularity throttle: leave
inputLimiterEnablefalse and linkinputLimiterScaleFactorfrom whatever measures how close the machine is to trouble.
Tuning
- Decide per channel whether you want the input limiter or the
throttle. They are alternatives, selected by
inputLimiterEnable, and they behave quite differently. - Use the input limiter when the input has a hard rate bound that always applies. The scale factor then narrows those bounds symmetrically.
- 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.
- Set the output limiter from the real travel, not from what the signal happens to do.
- Choose
outputLimiterClampDisabledeliberately. 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. - Pulse
resetafter every controller start if the integral must begin from a known value. - Nothing here needs re-checking after a task-rate change.
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).