SimpleActuatorControlLoop

SimpleActuatorControlLoop is the reduced control loop for a single axis.
3.30–3.34

SimpleActuatorControlLoop is the reduced control loop for a single axis. It converts sensor readings into engineering units, switches between tracking the measurement and following a command, converts the result back into drive units, and watches four quantities for faults.

Use it for an axis whose drive closes its own position loop and which needs no torque handling.

This loop does not limit anything. There is no position limiter and no velocity limiter — whatever you write to inputPosition goes to the drive, converted. Whatever feeds this block is entirely responsible for keeping the commanded motion within what the machine can take. The full ActuatorControlLoop does clamp its setpoints.

Compared with the full loop it also has no torque path, no feedback controllers, no feedforward, no impedance mode and no jogging. If you need any of those, use ActuatorControlLoop.

flowchart LR
    i1(["inputPosition, inputVelocity, inputAcceleration"]) --> B["SimpleActuatorControlLoop"]
    i2(["motorPositionActual, motorVelocityActual"]) --> B
    i3(["gotoEngaged, doInstantSwitchToggle"]) --> B
    i4(["driveMode, disable"]) --> B
    B --> o1(["motorPositionTarget, motorVelocityTarget"])
    B --> o2(["actuatorPositionTarget, actuatorVelocityTarget, actuatorAccelerationTarget"])
    B --> o3(["actuatorPositionActual, actuatorVelocityActual"])
    B --> o4(["actuatorPositionError, actuatorVelocityError"])
    B --> o5(["…ActualFiltered outputs, gearboxGain, isEnabled"])
    B --> s1(["positionTransformation, velocityTransformation"])
    B --> s2(["engagedSwitch, actualVelocityFilter, motorBacklashCompensation"])
    B --> s3(["four window detectors"])

gotoEngaged decides whether the axis follows you or follows itself. While false, the target tracks the measured position so nothing jumps when the drive powers on. While true, it follows inputPosition. The transition is faded.

During that fade, actuatorVelocityTarget and actuatorAccelerationTarget do not match actuatorPositionTarget. They are correct before and after, and wrong in between, by an amount that grows with the gap between where the axis is and where you are commanding it. Match them before engaging.

Signals

Inputs

Path Unit Range Description
inputPosition actuator unit unbounded The commanded position. Followed only while engaged. Not limited by this block.
inputVelocity actuator unit per second unbounded The commanded velocity.
inputAcceleration actuator unit per second² unbounded The commanded acceleration.
motorPositionActual ticks unbounded From the drive.
motorVelocityActual ticks per second unbounded From the drive.
gotoEngaged - true or false Follow the input, or track the measured position.
doInstantSwitchToggle - true or false Make that transition a step instead of a fade.
driveMode - drive enumeration Which mode the drive is in. Recorded, but this loop has no torque routing to gate on it.
disable - true or false Disables the loop.

Outputs

Path Unit Description
motorPositionTarget ticks To the drive.
motorVelocityTarget ticks per second To the drive.
actuatorPositionTarget actuator unit What the loop decided, before conversion. Trace this first.
actuatorVelocityTarget actuator unit per second Wrong during an engage fade — see the callout above.
actuatorAccelerationTarget actuator unit per second² Same.
actuatorPositionActual actuator unit Where the axis is.
actuatorVelocityActual actuator unit per second From the drive, or derived from the position — see usePositionActualFilteredForVelocity.
actuatorPositionError actuator unit Target minus actual. The main health signal. Its exact definition depends on useAngleDiffForPositionError.
actuatorVelocityError actuator unit per second
actuatorPositionActualFiltered actuator unit The filtered measurements. These are what the loop tracks while idle, and what three of the four detectors watch.
actuatorVelocityActualFiltered actuator unit per second
actuatorAccelerationActualFiltered actuator unit per second²
gearboxGain - gearboxLoadSide ÷ gearboxMotorSide. Read it back to check the ratio.
isEnabled - The loop is running.

Parameters

Path Unit Default Range Effect
enable - — - Enables the loop.
gearboxLoadSide teeth — non-zero Load-side tooth count. Not checked for zero.
gearboxMotorSide teeth — non-zero Motor-side tooth count. Not checked for zero.
windowDetectorsEnable - — - Turns all four fault detectors on. Leave this on in service.
usePositionActualFilteredForVelocity - — - Derive the velocity from the position instead of taking the drive’s own velocity. Useful when the drive’s velocity is noisy or absent.
useAngleDiffForPositionError - — - For a rotary axis: compute the position error by the shortest angular path, so an axis near the wrap-around point does not report a full-turn error. It also switches the error to use the filtered position, which changes its noise and lag.
usePvaActualForCompensation - — - Has no effect in this loop. It selects a feedforward input, and this loop has no feedforward.

Everything else is in the sub-trees — the two transformations, the engage switch, the velocity filter, the backlash compensation, and the four window detectors. All parameters are persistent and survive a controller restart.

Setup

  1. Configure the transformations first, under positionTransformation and velocityTransformation. Nothing else can be checked until the axis reports its position correctly.

  2. Set gearboxLoadSide and gearboxMotorSide, and read gearboxGain back.

  3. With the drive disabled, move the axis by hand and confirm actuatorPositionActual reads correctly over a long move.

  4. Confirm whatever feeds inputPosition has its own limits. This block has none.

  5. Set the four window detectors' levels from a trace of normal operation, and set windowDetectorsEnable true.

  6. For a rotary axis that wraps, set useAngleDiffForPositionError true.

  7. Leave gotoEngaged false and enable the drive. Confirm actuatorPositionTarget tracks actuatorPositionActual and the axis does not move.

  8. Feed inputPosition the axis’s current measured position, then set gotoEngaged true.

    Step 8 hands the axis to your setpoint source, with nothing between them but a unit conversion. If inputPosition does not match where the axis is, the loop will move it there over the fade, at whatever rate the fade implies.

  9. Move slowly and watch actuatorPositionError.

Tuning

  1. There are no gains here — the drive closes the loop. The tuning is in the measurement chain and the fault levels.
  2. Set the measurement filtering under positionTransformation/actualLP1Filter from the noise you see. Lower cut-off is smoother and laggier.
  3. Choose the velocity source. If the drive reports velocity cleanly, use it; if not, set usePositionActualFilteredForVelocity and take the derivative of the filtered position instead.
  4. Set the engage fade time under engagedSwitch/fadeInTime from how abruptly you are willing to take control. Longer is gentler, and longer also means the velocity and acceleration targets are wrong for longer.
  5. Set the backlash compensation only if the drivetrain has measurable backlash, and only after the position reads correctly.
  6. Set the four detector levels from the error you actually see, with margin.
  7. Watch actuatorPositionError through a full working cycle before declaring the axis commissioned.

Engaging with and without the instant toggle. The faded transition takes thetarget smoothly from the measured position to the commanded one; the instanttoggle steps it.

The step is what you get with doInstantSwitchToggle true. Use it only when the two values already match.

Symptom Cause Action
The axis jumped when engaging inputPosition did not match the measured position, and nothing limits the difference Match them before engaging
The axis stepped rather than faded doInstantSwitchToggle is true Set it false
The axis moved further or faster than intended This block has no limiters Limit the source that feeds inputPosition
Nothing moves when engaged enable is false or disable is true Check isEnabled
The velocity target looks wrong during engaging Expected in this version: it does not match the position target during the fade Match the values before engaging, or shorten the fade
A rotary axis reports a full-turn error The position error is not using the shortest angular path Set useAngleDiffForPositionError
The position error got smoother when I set that flag Expected: it also switches to the filtered position Nothing, but be aware the signal changed
The velocity is noisy The drive’s velocity is noisy Set usePositionActualFilteredForVelocity and tune the filter
A fault will not clear The window detectors latch. The reset is not on this block Assert resetErrors on the parent’s state input — it clears every axis at once
usePvaActualForCompensation does nothing Expected: there is no feedforward in this loop Use the full loop if you need feedforward
Everything is scaled wrongly The gearbox ratio, or the transformations Read gearboxGain back; check the transformations first
The loop misbehaves after writing a gearbox value A zero tooth count is not refused Read both back
I need torque control, feedforward, or jogging Not in this loop Use ActuatorControlLoop
I need the setpoints limited here Not in this loop Use ActuatorControlLoop, or limit upstream

A starting point once the transformations are correct:

gearboxLoadSide                      = <from the drivetrain>
gearboxMotorSide                     = <from the drivetrain>
windowDetectorsEnable                = true
usePositionActualFilteredForVelocity = false
useAngleDiffForPositionError         = false   (true for a rotary axis)

Limits and errors

Limit Set by What happens Reported
Setpoint limiting None Nothing in this block clamps position, velocity or acceleration. The commanded value reaches the drive converted Not reported
Fault detection The four window detector sub-trees Latching warning and error flags on the position error, position, velocity and acceleration Each detector’s noError
Fault reset The parent’s state input This block has no reset path of its own. Inside AxesControl the reset arrives through its state channel and clears every actuator at once Not reported
Engage transition The engage switch sub-tree Faded, unless doInstantSwitchToggle. The velocity and acceleration targets do not match the position target during the fade Not reported
Position error definition useAngleDiffForPositionError Plain subtraction, or the shortest angular path — and the second also switches to the filtered measurement Not reported
Gearbox ratio Nothing A zero tooth count is not refused and makes the conversion invalid gearboxGain
Values that are not numbers Nothing Not checked anywhere in this block Not reported
usePvaActualForCompensation Fixed Inert. There is no feedforward here for it to select Not reported
driveMode Fixed Recorded but not acted on — there is no torque path to route Not reported
Feature set Fixed No torque, no controllers, no feedforward, no impedance, no jogging, no limiters Not applicable
Axis count Fixed One axis per instance, always Not reported

This block logs nothing itself. The transducers below it log during referencing. Every other condition above shows as a value on a trace, or not at all.


Verified against motorcortex-control3 3.30.0 (bc348fd).