SetpointGenerator

SetpointGenerator turns a step change in a target into a smooth profiled move.
3.30–3.34

SetpointGenerator turns a step change in a target into a smooth profiled move. Write a new number to input and the output travels there while respecting velocity, acceleration and jerk limits — and publishes the matching velocity and acceleration as it goes, so a feedforward path can use them.

The move time is computed, not configured. You give it the limits; it works out the fastest move that respects them.

flowchart LR
    i1(["input — the target value"]) --> B["SetpointGenerator"]
    i2(["timeScaleFactor"]) --> B
    i3(["timeScaleFactorDot"]) --> B
    B --> o1(["output — profiled position"])
    B --> o2(["outputDot — velocity"])
    B --> o3(["outputDDot — acceleration"])
    B --> o4(["done"])
    B --> o5(["numTargets — how many are queued"])

timeScaleFactor stretches the profile’s clock while it runs — 0.5 makes the move take twice as long at half the velocity and a quarter of the acceleration. That is what a jog-override wheel needs. timeScaleFactorDot lets the override itself be turned smoothly.

All three limits default to 0, and a generator with a zero limit refuses every target. Nothing moves, an error is logged once, and no output changes to tell you why. Set maxVel, maxAcc and maxJerk before anything else.

An unachievable target is discarded, not clamped. The generator keeps the previous target and carries on. That is the safe failure, but it is silent apart from that one log line.

Signals

Inputs

Path Unit Range Description
input signal unit unbounded The target. A change starts a new move; writing the same value again does nothing. If the move cannot be profiled with the current limits, the target is discarded and the previous one kept.
timeScaleFactor - above 0 Stretches or compresses the profile’s clock while it runs. 1 is normal speed, 0.5 is half speed, 0 freezes the move. Not checked.
timeScaleFactorDot 1/s any How fast timeScaleFactor is itself changing, so an override can be turned without a jolt.

Outputs

Path Unit Description
output signal unit The profiled value on its way to the target.
outputDot signal unit per second Its velocity — feed this to a feedforward path.
outputDDot signal unit per second² Its acceleration.
done - True when the profile has finished. It starts true, so a freshly started generator reports done before it has done anything.
numTargets - How many targets are queued. Writing a new target while a move is running adds to the queue rather than replacing it.

Parameters

Path Unit Default Range Effect
maxVel signal unit per second 0.0 above 0 Velocity limit. A zero here makes every target be refused. Negative values are used as their magnitude and written back.
maxAcc signal unit per second² 0.0 above 0 Acceleration limit. Same treatment.
maxJerk signal unit per second³ 0.0 above 0 Jerk limit. Only used by the jerk-limited profile, but still needs a value.
faderType - 0 0 or 1 Which profile shape. See the table below.
delayTime s 0.0 0 upward How long to wait after a new target before the move starts.
applyTimeScaleToDelay - — - Whether timeScaleFactor stretches the delay as well as the move.
maxTargets - 10 1 upward How many targets may be queued at once.
faderType What the machine does Parameters that matter
0 QUINTIC Position, velocity and acceleration all start and end at zero. The smoothest shape, and the default maxVel, maxAcc
1 JERK_LIMITED Reaches the acceleration and velocity limits and holds them, so the move is faster for the same limits, with a slightly harsher start all three limits

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

Setup

  1. Set maxVel, maxAcc and maxJerk first. They default to 0, and a generator with a zero limit refuses every target you give it.

  2. Leave faderType at 0 for a first pass — the quintic profile is the gentler of the two.

  3. Have your application seed the generator at the machine’s current position before enabling anything downstream, so the first move does not start from zero.

  4. Write a small target to input and watch output travel there. Confirm done goes false at the start and true at the end.

    Step 4 moves the machine. The generator will use the full velocity and acceleration you configured, immediately. Start with a small target and limits well below the machine’s capability.

  5. Check outputDot peaks at or below maxVel, and outputDDot at or below maxAcc.

  6. Write a second target while the first move is running and watch numTargets. The moves queue rather than replacing each other.

Tuning

  1. Set the three limits from the machine, not from the move you want. They are what the mechanics can take.
  2. Choose the profile shape from what the machine minds more. Quintic is smoother and slower; jerk-limited reaches the limits and holds them, so it is faster for the same numbers.
  3. Time a move and compare it against what the limits imply. If it is slower than expected, the quintic shape is the reason — switch to jerk-limited.
  4. Use delayTime when several axes should start together after a common trigger.
  5. Use timeScaleFactor for a speed override. Ramp it with timeScaleFactorDot rather than stepping it, or the move’s velocity jumps.
  6. Raise maxTargets if your application streams targets faster than the moves complete. Watch numTargets to see whether the queue is filling.
  7. Nothing here needs re-checking after a task-rate change — but note the block captures the task period once at startup, so if the rate changes while running, restart the controller.

The two profile shapes over one fade time: the quintic eases in and outthroughout, and the two jerk-limited settings reach a constant slope in themiddle.

Read how much of the move is spent at constant speed off the straight section in the middle.

Symptom Cause Action
Nothing moves and no output changes A limit is 0 — the default — so every target is refused Set maxVel, maxAcc and maxJerk
A new target had no effect Either it was refused, or it is the same value as the last one Check the limits; the generator only reacts to a change
An error about invalid settings appeared once The limits cannot produce a valid profile Fix the limits; the previous target is still in force
done reads true before the first move Expected: it starts true Wait for it to go false after a target is written
The move is slower than the limits suggest Expected with the quintic profile, which eases throughout Set faderType to 1
The start of a move is harsher than expected Expected with the jerk-limited profile, which pushes to its limits Set faderType to 0
The move takes the wrong time after a task-rate change The block captured the task period at startup Restart the controller
A limit reads back as a positive number after writing a negative one Expected: the magnitude is used Write positive values
The move froze part-way timeScaleFactor is 0 Set it above 0
The velocity jumped when the override was changed timeScaleFactor was stepped Ramp it, using timeScaleFactorDot
Targets are being dropped The queue is full — check numTargets against maxTargets Raise maxTargets, or write targets less often
The first move went to the wrong place The generator was not seeded at the machine’s position Have the application seed it before enabling
I cannot change the jerk-limited profile’s shape Those two shape factors are not exposed Only the two profile types are selectable
I need this on several axes Not possible — this block is single channel Use one instance per axis

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

maxVel                = 0.5
maxAcc                = 5.0
maxJerk               = 50.0
faderType             = 0
delayTime             = 0.0
maxTargets            = 10

Limits and errors

Limit Set by What happens Reported
maxVel, maxAcc, maxJerk above 0 Nothing Not checked, and all three default to 0. A zero limit makes every target be refused Logged once when the settings first become invalid; no output changes
Target achievability Checked on every change A target that cannot be profiled is discarded and the previous one kept — the generator keeps running on the last valid profile Logged once on the transition. No output flag
output The profile Reaches the target exactly. Velocity and acceleration stay inside their limits Not reported
Limit signs Fixed Negative limits are used as their magnitude and written back Read the values back
timeScaleFactor Nothing Not checked. 0 freezes the move and a negative value is not guarded Not reported
Profile shape factors Not exposed The jerk-limited shape’s two factors are fixed and cannot be configured Not applicable
Task period Captured at startup Read once when the controller starts. A task-rate change while running is not picked up and the move takes the wrong time Not reported
Target queue maxTargets Targets written while a move is running are queued, up to this depth numTargets
Channel count Fixed One channel per instance, always Not reported

The block logs one error when the limit set first becomes invalid. Every other condition above shows as a value on a trace, or not at all.


Verified against motorcortex-control3 3.30.0 (bc348fd).