PVALimiter

PVALimiter shapes a position command so the motion it produces respects a position range, a velocity limit and an acceleration limit all at once.
Current release

PVALimiter shapes a position command so the motion it produces respects a position range, a velocity limit and an acceleration limit all at once. It outputs a matching position, velocity and acceleration, so whatever follows it gets a consistent set.

Its most useful behaviour is at the position limits. Instead of clamping the position — which arrives as a wall and demands an impossible deceleration — it works out, every cycle, the fastest it could be going and still stop in time, and holds the velocity below that. The axis decelerates into the limit and arrives at zero speed.

Deprecated — scheduled for removal. PvajLimiter is the only setpoint limiter that may be used for new work. It bounds the setpoint in jerk as well as position, velocity and acceleration, and its position guarantee holds with no tolerance where this block’s holds to about 1e-9. This block is kept only until the last machine is off it, and will then be deleted.

It is not a drop-in swap. The replacement has no input filter, so omega, beta and enablePVAInputs have no counterpart. Feed it the position setpoint directly and supply the derivatives on its own inputDot and inputDDot leaves, each behind its own switch. See PvajLimiter for the parameter reference.

flowchart LR
    i1(["input — position reference"]) --> B["PVALimiter"]
    i2(["inputDot — velocity reference"]) --> B
    i3(["inputDDot — acceleration reference"]) --> B
    i4(["disable"]) --> B
    B --> o1(["output — limited position"])
    B --> o2(["outputDot — limited velocity"])
    B --> o3(["outputDDot — limited acceleration"])
    B --> o4(["currentMaxVel — allowed velocity now"])
    B --> o5(["currentMinVel"])
    B --> o6(["pLimActive"])
    B --> o7(["vLimActive"])
    B --> o8(["aLimActive"])
    B --> o9(["state"])
    B --> o10(["inputFilt, inputFiltDot, inputFiltDDot"])
    B --> o11(["isEnabled"])

Approaching a limit, the allowed velocity is $\sqrt{2 \times \text{distance} \times \texttt{maxBrakingAcceleration}}$ — so at 0.1 m from the limit with a braking limit of 10, the axis may travel at 1.4 m/s. omega and beta set how hard the block chases the input: higher omega tracks more tightly, and beta 4 is heavily damped so it does not overshoot.

Keep maxBrakingAcceleration at or below maxAcceleration. The block sizes its approach speed on the braking figure but can only ever deliver the acceleration figure. Setting braking higher promises a stop the block cannot perform, and the axis overshoots the limit.

Every instance logs a warning at startup with default settings. omega ships at infinity, meaning “as fast as possible”, and the block corrects it to what the task rate allows — and says so in the log. It is expected.

Signals

Inputs

Path Unit Range Description
input m or rad unbounded The position reference to shape.
inputDot m/s or rad/s unbounded The velocity reference. Only used when enablePVAInputs is set; ignored otherwise.
inputDDot m/s² or rad/s² unbounded The acceleration reference. Same condition.
disable - - True bypasses the block: input passes straight to output. Use it for a runtime override; use enable for the configured intent.

Outputs

Path Unit Description
output m or rad The limited position. Starts from zero after every controller start and moves to the input under its own limits — a real commanded move if the input is not near zero.
outputDot m/s or rad/s The limited velocity. It is not updated while the block is bypassed, so it holds a stale value from before.
outputDDot m/s² or rad/s² The limited acceleration.
currentMaxVel m/s or rad/s The fastest the block will currently allow, given how close the axis is to the upper limit. The single most useful output for understanding why the axis slowed down.
currentMinVel m/s or rad/s The same toward the lower limit.
pLimActive - True while the position envelope is holding the velocity down.
vLimActive - True while the velocity limit is binding.
aLimActive - True while the acceleration limit is binding — but it is forced false whenever either of the other two is true, so it under-reports.
state - The same three flags again, grouped.
inputFilt, inputFiltDot, inputFiltDDot m, m/s, m/s² The block’s internal smoothed copy of the input. Only meaningful while enablePVAInputs is false.
isEnabled - True when enable is true and disable is false.

Parameters

Path Unit Default Range Effect
enable - true - False bypasses the block.
lowerLimit m or rad −1.0 below upperLimit The lowest position the output may reach.
upperLimit m or rad +1.0 above lowerLimit The highest.
maxVelocity m/s or rad/s 1.0 above 0 Speed limit. Negative values are used as their magnitude.
maxAcceleration m/s² or rad/s² 10.0 above 0 How hard the block may accelerate or decelerate in practice. Used as its magnitude.
maxBrakingAcceleration m/s² or rad/s² 10.0 at most maxAcceleration How hard the block assumes it can brake, when sizing the approach to a position limit. Set it at or below maxAcceleration — see Limits and errors.
omega rad/s infinity 0 up to a task-rate ceiling Tracking bandwidth. Higher follows the input more tightly. The infinite default means “as fast as the task rate allows” and is corrected at startup with a logged warning.
beta - 4.0 above 0 Tracking damping. 4 is heavily damped and does not overshoot. Lowering it makes the output chase harder and eventually ring.
enablePLim - true - Switches the position envelope and the hard position clamp on. False leaves only the velocity and acceleration limits.
enablePVAInputs - false - False: the block derives velocity and acceleration internally from input alone. True: it uses inputDot and inputDDot. This changes how the block tracks, not just what it reads — decide once and leave it.

All ten are persistent and survive a restart. No parameters exist below this block.

Setup

  1. Set lowerLimit and upperLimit to the axis’s real travel.

  2. Set maxVelocity and maxAcceleration from the machine.

  3. Set maxBrakingAcceleration equal to or below maxAcceleration. Equal is the normal choice.

  4. Leave omega alone. It corrects itself at startup and logs that it did.

  5. Leave beta at 4 and enablePVAInputs false for a first pass.

  6. Set enable true. Command a small move well inside the limits and confirm output follows input closely with all three flags false.

  7. Command a fast move and watch vLimActive and aLimActive go true in turn.

  8. Command a move that runs into a position limit. Watch currentMaxVel fall as the axis approaches, and confirm the axis arrives at the limit with outputDot at zero.

    Step 8 drives the axis into its travel limit deliberately. Do it at low speed first, and confirm the deceleration is inside what the machine can take before repeating it at full speed.

Tuning

  1. Set the three machine limits first — position, velocity, acceleration. They are properties of the hardware.
  2. Keep braking at or below acceleration, per Setup step 3. This is the one parameter relationship the block does not check and it is the one that causes overshoot.
  3. Leave omega at its default unless the output visibly lags the input during ordinary moves. It is already as fast as the task rate allows.
  4. Lower beta only if the block is too slow to catch a fast input. Below about 1 it starts to overshoot, which for a limiter is the wrong direction.
  5. Use enablePVAInputs when your source already produces a consistent position, velocity and acceleration — a setpoint generator, say. It lets the block follow without having to infer the derivatives, so it tracks much more closely. Do not switch it at runtime.
  6. Watch currentMaxVel during a limit approach. It is the envelope, and it tells you directly whether maxBrakingAcceleration is set sensibly: a larger value gives a steeper, later deceleration.
  7. If you need jerk limited as well, this block does not do it — use a PVAJ limiter.

Highest allowed velocity against distance to the position limit, at threebraking accelerations: each curve is a square root rising from zero at thelimit, and all three flatten at the velocitylimit.

Read the allowed speed at any distance off the curve for your braking setting.

Symptom Cause Action
A warning about omega at every startup Expected: the default is infinity and the block corrects it Ignore it, or set a finite omega
The axis overshoots its position limit maxBrakingAcceleration is higher than maxAcceleration Set it at or below the acceleration limit
The axis stops well short of the limit and creeps in maxBrakingAcceleration is very low, so the envelope is conservative Raise it, up to maxAcceleration
The axis slows down and nothing seems to be limiting The position envelope is active — check pLimActive and currentMaxVel This is the block working as designed
aLimActive never goes true Expected: it is suppressed whenever the position or velocity limit is also active Watch all three flags together
The output lags the input during ordinary moves omega too low, or beta too high Leave omega alone and try enablePVAInputs if your source provides derivatives
The output overshoots the input beta too low Raise it back toward 4
Tracking changed when enablePVAInputs was switched Expected: it changes how the block tracks, not just what it reads Choose one mode and keep it
inputDot and inputDDot seem to be ignored Expected: they are only read when enablePVAInputs is true Set that parameter
The axis made a move immediately after a restart Expected: the output starts at zero and travels to the input under its limits Command the machine’s actual position first, or gate the consumer
The velocity output is wrong just after re-enabling Expected: outputDot is not updated while bypassed and resumes from a stale value Re-enable at rest
The position stopped at the limit but the velocity output is not zero The hard backstop clamped the position without zeroing the velocity — the envelope did not do its job Check maxBrakingAcceleration against maxAcceleration
Motion is jerky at the start and end of moves Expected: this block bounds acceleration, not jerk Use a PVAJ limiter
A non-numeric value latched into the outputs The block holds state and there is no reset Bypass the block for one cycle to recover the position; restart to clear the velocity

A starting point for an axis with 1 m of travel, 1 m/s and 10 m/s² on a 1 ms task:

enable                 = true
lowerLimit             = -0.5
upperLimit             = 0.5
maxVelocity            = 1.0
maxAcceleration        = 10.0
maxBrakingAcceleration = 10.0
beta                   = 4.0
enablePLim             = true
enablePVAInputs        = false

Limits and errors

Limit Set by What happens Reported
maxBrakingAcceleration at most maxAcceleration Nothing Not checked. A higher braking figure makes the block approach the limit faster than it can stop, and the axis overshoots Not reported
output position lowerLimit, upperLimit while enablePLim is set Bounded two ways: the velocity envelope decelerates the axis in, and a hard clamp catches anything the envelope missed. The clamp does not zero the velocity, so the two outputs can disagree on that cycle pLimActive
outputDot maxVelocity, and the position envelope Bounded by whichever is lower vLimActive, currentMaxVel, currentMinVel
outputDDot maxAcceleration Clamped aLimActive, but it is suppressed whenever the position or velocity limit is also active
Jerk Nothing Not limited. Acceleration can step Not reported
omega Task rate and beta Corrected to a stable value at startup and on every cycle. The infinite default always triggers this Logged as a warning each time it corrects
beta, maxVelocity, maxAcceleration, maxBrakingAcceleration Sign forced Negative values are used as their magnitude Not reported; read them back
Zero acceleration limits Fixed Either at exactly zero forces the allowed velocity to zero, stopping the axis where it stands pLimActive
Block state Nothing The output position and velocity are not cleared at start and there is no reset input. Bypassing recovers the position but not the velocity Not reported
Channel count Fixed One axis per instance. Use the plural block for several Not reported

The block logs a warning whenever it corrects omega or beta — which with the default settings happens once at startup for every instance. Every other failure above shows as a value on a trace, not as a message.


Verified against motorcortex-control3 3.32.1 (340db23).