RateLimiter

RateLimiter caps how fast a signal may change.
3.30–3.34

RateLimiter caps how fast a signal may change. Where a limiter bounds a signal’s value, this bounds its slope: the output follows the input wherever it can, and ramps toward it at no more than rateLimit per second wherever it cannot.

Use it to take a step out of a command — a mode switch, a new setpoint typed in by an operator, a discontinuous reference — without a filter’s lag. Below the rate limit the output is the input exactly. Only when the limit binds does the block do anything at all.

flowchart LR
    i1(["input — signal to slew"]) --> B["RateLimiter"]
    i2(["disable"]) --> B
    B --> o1(["output — rate-limited signal"])
    B --> o2(["isLimiting — per channel"])
    B --> o3(["isEnabled"])

rateLimit is in units per second, so a step of height $H$ takes $H/$rateLimit seconds to follow. The setting keeps its meaning across task rates — unlike the sample-counted blocks, nothing needs rescaling if the task period changes.

Disabling this block lets the signal jump. The output snaps to the input on the same cycle. That is the one thing not to do while the machine is moving — raise rateLimit instead until it no longer binds.

After a controller start the output ramps up from zero, taking input ÷ rateLimit seconds to catch up.

Signals

Inputs

Path Unit Range Description
input signal unit unbounded The signal to slew. One element per channel; the channel count is fixed by the machine configuration.
disable - - True bypasses the block: input passes straight to output, as a step. Use it for a runtime override from a supervisor; use enable for the configured intent.

Outputs

Path Unit Description
output signal unit The rate-limited signal, one element per channel. Equals input exactly whenever the input’s slope is inside the limit, and while bypassed. Starts from zero after every controller start and is not cleared by a stop.
isLimiting - True per channel on cycles where the output was actually clamped. It is exact — no false positives.
isEnabled - True when enable is true and disable is false. A single value for the whole block.

Parameters

Path Unit Default Range Effect
enable - true - Ships on. False bypasses the block, letting the signal step.
rateLimit signal unit per second 1.0 0 upward, per channel The fastest the output may change. Lower is gentler and slower to follow. 0 freezes the output where it is. Not checked — a negative value makes the output run away.

Both are persistent and survive a controller restart. rateLimit is per channel. No parameters exist below this block.

Setup

  1. Work out the fastest change the consumer can accept, in units per second. That is your rateLimit — it is a property of the machine, not of the signal.

  2. Set rateLimit for every channel. The default of 1.0 is a placeholder.

  3. Set enable true and confirm isEnabled reads true.

  4. Step the input and time how long output takes to catch up. It should be the step height divided by rateLimit.

  5. Move the input at a normal working speed and confirm output tracks it exactly, with isLimiting reading false.

    Step 5 is the check that the limit is not in your way. If isLimiting is true during normal motion, the limit is shaping every move and not just the steps — raise it until it only bites on the discontinuities.

  6. Trace every element of input, output and isLimiting. Rates are per channel.

Tuning

  1. Set the rate from the machine, not from the signal. It is the slope the consumer downstream can absorb.
  2. Confirm it does not bind during normal motion, per Setup step 5. A rate limiter that is always active has become a slow ramp generator.
  3. Lower it only until steps are absorbed comfortably. Every reduction also delays genuine fast movements.
  4. If you need smoothing as well as slope limiting, add a filter — this block only bounds the slope, and leaves corners at the start and end of every ramp.
  5. If the corners themselves are a problem, you need acceleration limiting, not rate limiting. A PVA limiter bounds the rate of the rate.
  6. Nothing here needs re-checking after a task-rate change. The rate is in units per second and keeps its meaning.

Response to a unit step at three rate limits: a rate of 10 reaches 1 in0.1 s, a rate of 2 in 0.5 s, and the default rate of 1 takes a fullsecond.

Read the rate off the slope of any ramp.

Symptom Cause Action
The output ramps up from zero for a while after every start Expected: the output starts at zero and slews to the input Gate the consumer for input ÷ rateLimit seconds, or bypass for one cycle to seed it
The output jumped when the block was bypassed Expected: bypassing assigns the input directly Raise rateLimit until it no longer binds, then bypass
The output froze and will not move rateLimit is 0 for that channel Set a positive rate
The output runs away in one direction rateLimit is negative Set it positive, then bypass for one cycle to re-seed the output
isLimiting is true during ordinary motion The rate is too low for normal moves Raise it, per Tuning step 2
Motion is slower than commanded everywhere Same cause Raise the rate
Steps still reach the consumer enable is false, disable is true, or the rate is far above the step’s slope Read isEnabled; lower rateLimit
The output has sharp corners at the start and end of each ramp Expected: this block bounds slope only, not acceleration Use a PVA limiter if the corners matter
A sine wave came out as a triangle Expected: the rate limit is below the sine’s peak slope Raise the rate above 2π × frequency × amplitude
One channel slews differently from the others Expected: rateLimit is per channel Check every element
The behaviour changed after a task-rate change Not possible — the rate is in units per second Look elsewhere in the loop
The output stuck at a non-numeric value A non-numeric input latched into the output, which then poisons every bound Bypass the block for one cycle to clear it, then fix the source
The block resumed from an old value after a restart Expected: the output is not cleared by a stop Bypass for one cycle at start

A starting point for slewing a position command that may move at 0.5 units per second:

enable    = true
rateLimit = 0.5

Limits and errors

Limit Set by What happens Reported
rateLimit non-negative Nothing Not checked. A negative value makes the output decrease every cycle without bound. Only bypassing the block or a restart clears it Not reported
rateLimit = 0 Fixed Freezes the output at its current value. This is legitimate and is the way to hold a signal isLimiting reads true
output slope rateLimit while enabled Bounded exactly, with no overshoot and no lag inside the bound isLimiting, per channel
output value Nothing Unbounded — this block limits slope, not magnitude. Follow it with a limiter if the value needs a bound Not reported
Disabled behaviour Fixed Exact pass-through, so the output steps to the input Not reported
Output state Nothing Not cleared at start or stop. There is no reset input — bypassing for one cycle is the only way to re-seed it Not reported
Non-numeric input Nothing Latches permanently: once the output is non-numeric every bound derived from it is too. Bypass for one cycle to clear Not reported
Task rate Independent rateLimit is in units per second and keeps its meaning at any task period Not applicable
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).