Axes and errors
The virtual axis kinematics, plus how backlash, pitch error and repeatability are modelled.
Kinematics
A trapezoidal velocity profile by default; S-curve (seven-segment, jerk limited) optional.
For a target x_t:
t_acc = v_max / a_max
x_acc = ½ · a_max · t_acc²
if |Δx| < 2·x_acc → triangular profile, peak velocity sqrt(a_max·|Δx|)
else → trapezoid, constant-velocity segment (|Δx| − 2·x_acc) / v_max
The S-curve adds jerk-limited transitions at both ends of each ramp, costing roughly
2·a_max/j_max in total time.
Worth having trainees compare the two: for the same move the S-curve is slower on paper but settles far sooner, because residual vibration is smaller. That is why precise machines are often deliberately slow.
Commanded position ≠ actual position
The virtual axis superposes four terms:
x_actual = x_cmd + e_backlash(dir) + e_pitch(x_cmd) + e_random
Backlash e_backlash
Lost motion on reversal. Modelled as a direction-dependent offset:
after a direction change the actual position lags the command by b (2.4 µm by default)
until accumulated travel exceeds b, after which it tracks normally.
This is the root cause of bidirectional accuracy being much worse than unidirectional accuracy. If every calibration pose is approached from the same direction, backlash is completely hidden — and only shows up on the line, during reciprocating motion. Lab 3 exists for exactly this.
Pitch error e_pitch
A systematic error along travel, stored as a table with linear interpolation:
"pitchErrorTable": [
{ "posMm": 0, "errUm": 0.0 },
{ "posMm": 50, "errUm": 1.8 },
{ "posMm": 100, "errUm": 2.6 },
{ "posMm": 150, "errUm": 1.1 },
{ "posMm": 200, "errUm": -0.4 }
]On a real machine this table comes from a laser interferometer. Here you write it yourself, which makes it possible to verify that your compensation actually removes it.
Repeatability e_random
Zero-mean Gaussian with σ = repeatUm / 3 (repeatability quoted at 3σ). Sampled independently
on each move, so the same commanded position visited ten times gives ten different actual
positions — exactly as on real hardware.
Limits, homing, e-stop
| Behaviour | Model |
|---|---|
| Soft limit | Command outside travel is refused with E2101; no motion |
| Hard limit | Decelerate and stop at the switch, raise an alarm, manual reset required |
| Homing | Runs the configured sequence (limit + index, or absolute encoder) in realistic time |
| E-stop | Immediate deceleration at a_estop (10× a_max by default); reset required |
Homing defines the origin of the machine frame M, exactly as on real hardware. Homing repeatability therefore feeds into every calibration downstream, which is why it is worth measuring on its own (Lab 3 does).
Multi-axis motion
Two-axis linear interpolation plans on the resultant velocity, so the path is a straight line
rather than X-then-Y. Stage squareness error (X and Y not exactly perpendicular) enters as a
small angle ε:
x_actual = x_cmd
y_actual = y_cmd + x_cmd · tan(ε) ε defaults to 80 µrad
That explains a familiar symptom: single-axis moves are accurate, diagonals are not. C6
stage geometry calibration exists to solve for ε and compensate it.
Where to change these
Devices → Virtual devices → Axis → Error model, or the machine configuration:
{ "id": "axisX", "type": "axis", "driver": "virtual", "params": {
"travelMm": 200, "vMaxMmS": 200, "aMaxMmS2": 2000, "profile": "trapezoid",
"backlashUm": 2.4, "repeatUm": 3.0, "squarenessUrad": 80,
"pitchErrorTable": [ ... ]
}}Teaching tip: set backlashUm to 50 and let trainees discover for themselves why moving
back is less accurate than moving forward. It lands better than ten explanations.