SetpointGenerator4thOrder

SetpointGenerator4thOrder generates a motion profile bounded in four derivatives: velocity, acceleration, jerk and snap.
3.30–3.34

SetpointGenerator4thOrder generates a motion profile bounded in four derivatives: velocity, acceleration, jerk and snap. Bounding the fourth means jerk itself ramps instead of stepping, which is what a machine with a lightly damped structure needs — a stepped jerk rings it, a ramped one does not.

It moves to a position, or holds a velocity as a jog, and switches between the two while running.

flowchart LR
    i1(["command/start"]) --> B["SetpointGenerator4thOrder"]
    i2(["command/abort"]) --> B
    i3(["command/type"]) --> B
    i4(["command/jogVelocity"]) --> B
    p1(["targetProfile/position, velocity, acceleration, jerk, snap"]) --> B
    B --> o1(["outputProfile/position, velocity, acceleration, jerk, snap"])
    B --> o2(["status/isDone, isAborted"])
    B --> o3(["status/isMovingToPosition, isMovingToVelocity, isAtConstantVelocity"])
    B --> o4(["status/currentSample, currentIndex"])
    B --> o5(["calc/sampleArray, snapArray, numberOfSamples, totalTime"])

The four numbers under targetProfile other than position are bounds, not targets. The generator uses as much of each as it needs and no more, so a short move may never reach any of them.

Two things about this block will catch you out. Read them before using it.

command/start must be held true for the whole move. It is not a pulse. Clearing it mid-move aborts the move as soon as the axis reaches its cruise speed.

command/abort only works in jog mode. To abort a position move, clear command/start. And an abort of either kind only takes effect during a constant-speed phase — requested during acceleration or braking, it waits. This is not an emergency stop.

Signals

Inputs

Path Unit Range Description
command/start - true or false Starts a position move, and must stay true until it finishes. The block clears it when the move ends.
command/abort - true or false Aborts a jog only. Ignored during a position move. Cleared by the block once acted on.
command/type - 0, 1, 2 0 relative, 1 absolute, 2 velocity (jog). See the table below.
command/jogVelocity axis unit per second any The jog target speed. Only read every hundredth cycle, and only while the axis is at constant speed, so a jog change can take that long to act.

Outputs

Path Unit Description
outputProfile/position axis unit The setpoint to follow. Held where it stopped when a move ends.
outputProfile/velocity axis unit per second Its speed — feed this to a feedforward path.
outputProfile/acceleration axis unit per second² Its acceleration.
outputProfile/jerk axis unit per second³ Its jerk. Continuous, which is the point of this block.
outputProfile/snap axis unit per second⁴ The driving quantity, which steps between sixteen fixed values.
status/isDone - The move has finished. Reads false until the first move completes, including straight after a restart.
status/isAborted - The last move was aborted rather than completed.
status/isMovingToPosition - A position move is running.
status/isMovingToVelocity - A jog is running.
status/isAtConstantVelocity - Acceleration, jerk and snap are all zero. An abort can only act while this is true.
status/currentSample - How many cycles into the profile the axis is.
status/currentIndex - Which of the eighteen profile segments is playing, 0 to 17.
calc/numberOfSamples - How many cycles the whole move will take.
calc/totalTime s How long it will take. Check this after starting — a very small bound makes it enormous.
calc/sampleArray - How many cycles each profile segment lasts. Diagnostic. Shows 17 of the 18 segments.
calc/snapArray axis unit per second⁴ The snap value of each segment. Diagnostic. Shows 17 of the 18.

Parameters

Path Unit Default Range Effect
targetProfile/position axis unit 0.0 unbounded The target. Absolute or relative depending on command/type. In relative mode a value of exactly 0 is refused.
targetProfile/velocity axis unit per second 0.5 above 0 Speed bound. A zero refuses the move.
targetProfile/acceleration axis unit per second² 5 above 0 Acceleration bound. A zero refuses the move.
targetProfile/jerk axis unit per second³ 100 above 0 Jerk bound. A zero refuses the move.
targetProfile/snap axis unit per second⁴ 1000 above 0 Snap bound — how fast jerk may change. This is the parameter that makes the profile gentle. A zero refuses the move.

All five are persistent and survive a controller restart. Negative values are used as their magnitude. No parameters exist below this block.

command/type What the machine does What targetProfile/position means
0 RELATIVE Moves a given distance from where it is The distance to travel. Exactly 0 is refused
1 ABSOLUTE Moves to a given position — the default The position to arrive at
2 VELOCITY Jogs at command/jogVelocity until aborted Not used

Setup

  1. Set the four bounds from what the machine can take. All four have non-zero defaults, so the block will move without being configured — check them before you start it.

  2. Set command/type to 0 for a first move, so the distance is relative to wherever the axis already is.

  3. Set targetProfile/position to a small distance.

  4. Set command/start true and leave it true.

    Step 4 moves the machine, immediately and at the bounds you configured. Set them well below the machine’s capability first, and use a distance you can afford to overshoot.

  5. Watch status/isMovingToPosition go true, then status/isDone go true when it arrives. The block clears command/start itself.

  6. Read calc/totalTime and check it against the distance and the speed bound. A much larger number means a bound is far smaller than you meant.

  7. Confirm outputProfile/position ends exactly at the target. It should be exact, not close.

Tuning

  1. Set targetProfile/velocity and targetProfile/acceleration first — they are what the machine’s mechanics allow.
  2. Set targetProfile/jerk to what the drivetrain tolerates. Lower means gentler load reversals.
  3. Set targetProfile/snap last, and use it to trade smoothness against move time. It is the only bound the third-order generators do not have, and the reason to use this block at all.
  4. Run a move and watch outputProfile/jerk. With snap bounded it ramps between levels; the flatter the ramps, the gentler the move.
  5. If the machine rings at a known frequency, lower targetProfile/snap until the ringing stops. Every reduction lengthens the move.
  6. Compare calc/totalTime before and after each change, so you can see what the smoothness cost.
  7. Short moves take longer than the bounds imply. Every profile segment is rounded up to a whole cycle, which matters most when the move is only a few cycles long.

Acceleration at the start of a move. A second-order profile stepsacceleration straight to its limit; a third-order profile ramps it, so jerksteps; a fourth-order profile eases it in, so jerk iscontinuous.

The gentler the curve leaves zero, the less the machine is excited — and the longer the move takes.

Symptom Cause Action
The move stopped part-way command/start was cleared, which aborts Hold command/start true for the whole move
command/abort did nothing It only aborts a jog Clear command/start to stop a position move
An abort did not act for a while Aborts only take effect at constant speed Expected. Do not use this as an emergency stop
The axis stopped in the wrong place after an abort An abort plays out the braking half, wherever that ends Expected. The stopping point is not predictable
Nothing moved and an error was logged A bound is 0, or a relative move of exactly 0 was requested Set all four bounds above 0
The same error keeps repeating The block retries every hundredth cycle Fix the bound or the move type
The first absolute move went to the wrong place The block starts from position 0, and cannot be told the machine’s real position from the parameter tree Use relative moves, or drive the block from an application
status/isDone reads false after a restart Expected: it only becomes true when a move finishes Run one move
calc/totalTime is enormous A bound is far smaller than intended Check all four
A short move took much longer than expected Each segment is rounded up to a whole cycle Expected. It matters only for very short moves
A jog change took a long time to act Jog targets are read every hundredth cycle, at constant speed only Expected
The machine rings during acceleration targetProfile/snap is too high Lower it
The move is smooth but too slow A bound is limiting it — read calc/totalTime Raise snap first, then jerk
calc/snapArray shows 17 entries, not 18 Expected: the last segment is not published The missing entry is always 0
A bound reads back positive after writing a negative one Expected: the magnitude is used Write positive values
I need this on several axes Not possible — this block is single axis Use one instance per axis

A starting point for an axis that may move at 0.5 units per second:

targetProfile/velocity     = 0.5
targetProfile/acceleration = 5.0
targetProfile/jerk         = 100.0
targetProfile/snap         = 1000.0
command/type               = 1

Limits and errors

Limit Set by What happens Reported
The four bounds targetProfile Respected exactly. The profile uses as much of each as it needs; a short move reaches none of them calc/totalTime and calc/numberOfSamples
A bound of 0 Nothing The move is refused and the output does not change Logged, and repeated every hundredth cycle while it persists
A relative move of exactly 0 Checked Refused as an incorrect move command Logged, and repeated
Bound signs Fixed Negative bounds are used as their magnitude Read the values back
A very small bound Nothing Accepted, and produces an enormous move time calc/totalTime
Arrival The profile The move lands exactly on the target, not within a rounding error outputProfile/position
Segment durations Fixed Rounded up to whole cycles, so short moves take longer than the bounds imply calc/totalTime
Position move abort command/start Clearing it aborts, but only once the axis is at constant speed status/isAborted
Jog abort command/abort Aborts, but only once the axis is at constant speed status/isAborted
Abort stopping point Nothing The braking half plays out and the axis stops wherever it ends. Not the target, and not predicted Not reported
Starting position Not settable from the tree An absolute move always starts from 0 unless the block is driven from an application Not reported
Jog latency Fixed A new jog target is read every hundredth cycle, at constant speed only Not reported
Axis count Fixed One axis per instance, always Not reported

The block logs an error, repeatedly, when a bound is 0 or the move command is not valid. Every other condition above shows as a value on a trace, or not at all.


Verified against motorcortex-control3 3.30.0 (bc348fd).