Advanced Metal Research
GitHub Contact AMR

The real-time core

On this page
  1. Three builds of one controller
  2. Drives: CiA402 in cyclic synchronous position
  3. Bringing an axis up
  4. The motion start gate
  5. The final output permit
  6. Stop, Halt and expiry
  7. Limits and interpolation
  8. Faults and recovery
  9. Home and anchors
  10. Brakes
  11. Collision watchdog
  12. Telemetry
  13. What the core does not do
  14. Related pages

rosie-rt-core is the cyclic controller at the bottom of RosieOS. It is a C++17 process that talks EtherCAT to the servo drives, runs a fixed-period loop, and owns two things nothing else in the system can override: the drive state and the final output permit. Applications never talk to it directly. They go through rt-control, which reaches the core over a private IPC channel (a Unix socket plus shared-memory rings). That channel is internal and not a public API.

rt-control and the real-time core: clients reach the core only through rt-control; the core's cycle ends in a final output permit; the hardware E-stop chain acts on the drives directly. CLIENTS OLP server, motion servers, pendant, rtctl, your code Go SDK, C++ client, or plain HTTP HTTP/JSON, jog frames (local socket or mutual TLS) PUBLIC CONTROL API rt-control Lease and fence, handles, jog lane, events, telemetry private IPC: Unix socket and shared memory (internal) REAL-TIME CORE rosie-rt-core (rosie-rt-core-sim in simulation) Read feedbackPDOs, faults Readiness andstart gate Trajectory orjog target Final outputpermit Controlword is zeroed when the lease is invalid or a safety fault is latched. Motion is permitted only while permitted, armed and fault-free. EtherCAT (IgH), CiA402 cyclic synchronous position DRIVES AND I/O Servo drives, one per axis; cell I/O terminal Torch-class outputs are always refused Hardware E-stop and safety chain acts on drive power directly; not software observed as a drive input: diagnostic only
Every command reaches the core through rt-control. The hardware E-stop chain sits outside the software.

Warning

The core enforces limits and readiness, but it is not a safety system. The hardware E-stop is the only emergency stop; RosieOS has no software E-stop. The core reads the drives' digital inputs and external-enable state for diagnostics only, never as a safety decision. Only planned weld programs pass the planner's collision and limit check before loading; jog, Home and point-list moves rely on the checks on this page. See the safety model.

Three builds of one controller#

BinaryBuildUse
rosie-rt-coremake live, with IgH EtherCAT libethercatReal drives. Refuses to start unless the kernel is PREEMPT_RT and an RT CPU and FIFO priority are configured. It locks its memory at startup.
rosie-rt-core-simmake simThe same state machine and loop against a simulated bus. This is what the quickstart and the offline programming "Simulate" path run.
rosie-rt-core-ipcmake ipc-onlyIPC-only validation, with no EtherCAT.

All three read one compiled configuration (from rtctl compile). The cycle period is cycle_ns in the machine configuration: 250 µs to 10 ms. The shipped templates use 1 ms (1 kHz). The configuration reference lists every field.

Drives: CiA402 in cyclic synchronous position#

Each axis is a CiA402 (DS402) servo drive running in cyclic synchronous position (CSP, mode 8). Every cycle the core reads each drive's statusword, position and error code, and writes a controlword and a target position (plus a target velocity where one is mapped). Status reports the decoded state per axis:

CodeDS402 state
0Unknown
1Not ready to switch on
2Switch on disabled
3Ready to switch on
4Switched on
5Operation enabled
6Quick stop active
7Fault reaction active
8Fault

Motion is only possible in Operation enabled, with fresh feedback, CSP mode and no drive error.

Bringing an axis up#

The order is always the same. Each step is an rt-control call made under a grant (see Control authority).

  1. Home, if the axis requires it (require_home in Describe) and has no valid Home. home runs the drive's native homing, then leaves the axis disabled. Alternatively, restore_anchor re-establishes Home from a saved absolute-encoder anchor without moving.
  2. Enable the axes with enable and an axis mask. The drives move through the DS402 states to Operation enabled.
  3. Arm the core with arm.
  4. Wait for readiness. Poll Status until every axis you will move reports readiness: "ready".
  5. Start motion: a trajectory, a program or a jog session.

readiness names the first gate an axis fails, in this order: faulted, mode_mismatch, home_required, coordinate_invalid, not_enabled, not_operation_enabled, brake_wait, then ready. The table in Error codes says what to do about each.

The motion start gate#

Every Start (trajectory, program or jog) is decided inside the core, not in rt-control. The core refuses to start unless all of these hold:

  • no trajectory, jog or commissioning is already active (otherwise mode_conflict)
  • the request carries the current generation and has not been cancelled
  • the lease is valid and the core is armed
  • the bus is ready and no safety fault is latched (safety_fault_mask == 0)
  • the verified configuration epoch is current, and every requested axis is configured and configuration-verified
  • every requested axis that requires Home has valid Home evidence
  • limits are valid, every requested axis is in CSP mode and enabled
  • every requested axis is in Operation enabled with fresh feedback
  • the first point is continuous with the held position
  • no axis that is outside its limits would move further outward (outside_limits_outward)

A first point that does not match the held position within one count is refused as a start discontinuity. There is one exception: when Home, the configuration and the encoders are all qualified, a small offset (within the axis's completion tolerance) is closed with a bounded alignment move before the plan's own time starts. The plan's samples and identity do not change.

The final output permit#

Passing the start gate is not the last check. On every cycle, before it writes to the drives, the core applies a final output permit:

  • The controlword is forced to zero whenever the lease is not valid or any safety fault is latched.
  • Motion is permitted only while the final permit holds, the core is armed and no safety fault is set.
  • Cell I/O outputs are also ANDed with the permit, so they fall back to their safe state together with motion.

This is why lease expiry and Stop take effect within a cycle, whatever the client is doing.

Stop, Halt and expiry#

TriggerCore behaviour
stop, lease expiry, authority or connection lossOutputs are inhibited immediately. Active motion and handles are retired.
haltDecelerates to an enabled hold, using the trajectory's declared acceleration or the jog acceleration. Each ramp step is checked against the target-lead bound.
Jog input expires or end_jogThe jog ramps down within the jog acceleration and holds; a ramp that cannot stay within its bounds inhibits instead.
A fault latchesOutputs are inhibited, the core disarms and motion is cancelled.

None of these is an emergency stop, and no receipt proves standstill.

Limits and interpolation#

The core admits trajectories only inside each axis's limits, in logical units (rad or m). For robot axes, the travel and velocity limits come from the robot's URDF and the acceleration limits from its planning configuration. Machine configuration cannot override them. Each axis in Describe says what is checked:

  • Position and velocity are always checked (declared), including the peaks of each interpolated segment.
  • Acceleration is checked on samples when the axis declares max_acceleration, otherwise it is not_declared.
  • Jerk is never checked (unsupported).

Between points the core interpolates with cubic Hermite when both points carry a velocity, and linearly otherwise (hermite_position_with_velocity, linear_without). After the last sample it holds the final position with zero velocity and waits for feedback to settle within completion_tolerance by completion_timeout_ns (hold_last_sample_then_settle). No curve is ever clipped or retimed: a violation is refused.

An axis that is outside its limits (after a configuration change, for example) may still be enabled and armed to hold. It may move back inward, but any motion that increases the excursion is refused with outside_limits_outward.

Faults and recovery#

The core latches execution faults as bits in core.execution_fault_reasons, with the affected axes, and sets safety_fault_mask. Each bit has a recovery class:

Recovery classMeaning
reset_clearsreset_fault clears it.
reset_after_condition_clearsRemove the cause first, then reset_fault.
rehome_requiredAfter reset_fault, Home (or a qualified anchor restore) is required on the affected axes.
restart_requiredReset cannot clear it; the core must be restarted after investigation.

The full bit table (start discontinuity, position rate, cycle deadline, target lead, following error, coordinate reference, drive readiness, bus transport, brake hold, PDO mapping, collision watchdog, cell I/O and more) is in Execution fault bits. The code marks this recovery policy as unverified on hardware.

To recover, read recovery_status (it changes nothing), remove the cause, then call reset_fault on an inhibited, idle machine. reset_fault is labelled interim: it decides the whole reset at once (any persisting condition refuses it with fault_persists), it never starts motion or grants Home, and a submitted reset ends your session. Acquire again afterwards.

Home and anchors#

Home is per axis. home_valid_mask in Status shows which axes have valid Home evidence, and home_epoch increments whenever that evidence changes. Some faults (rehome_required) and some trust losses invalidate Home.

When rt-control's environment sets ROSIE_RT_ANCHOR_DIR, a successful Home also saves an anchor per axis: the relation between the absolute encoder and the command frame, bound to the pair, configuration and drive identity. After a restart, restore_anchor can re-establish Home from those anchors without moving, but only if every identity still matches and the core independently agrees with the saved evidence. Otherwise it refuses (anchor_missing, anchor_identity_mismatch, anchor_source_invalid, anchor_disagrees) and you Home again.

Brakes#

Holding brakes are drive-managed: the core does not command a brake output. It applies the configured release and hold delays, and the axis reports brake_wait until the release delay has passed. Unless a "brake released" signal is mapped, the reported brake state (BRAKE_APPLIED, BRAKE_RELEASED, …) is a timer estimate, not confirmation of the physical brake. If an axis moves while it should be held, the core latches brake_hold, which needs a restart.

Collision watchdog#

Each axis can arm a watchdog on drive torque and following error. It trips when either quantity strictly exceeds its bound for a configured number of consecutive cycles (2..1000); a single sample never trips it. A trip latches fault bit 12 (collision_watchdog), and Stop inhibits the whole group. Recovery is explicit and needs fresh feedback below both bounds.

The watchdog is off unless the axis or its drive profile declares thresholds, and compiling a configuration without it prints a warning per axis. The thresholds in the shipped examples are marked unverified starting values. This is a torque and tracking trip, not collision avoidance: collision checking against the cell model happens only in the weld planner.

Telemetry#

Every cycle the core captures one record per axis into a shared-memory ring: positions, targets, statuswords, error codes, torque, following error, validity flags, fault masks and the authority generations. Retention is telemetry.retention_ms in the machine configuration (default 100 s, up to one hour, within a 2 GiB mapping). rt-control publishes the ring through GET /v1/telemetry; see Events and telemetry.

What the core does not do#

  • No Cartesian motion. The core works in joint space only. Cartesian jog and moves are resolved to joint velocities or joint trajectories by the motion servers and the offline programming server.
  • No simulation gate. The core admits any trajectory or .rdt program that passes its own limit, continuity and identity checks. The collision and limit verification of planned weld programs happens earlier, in the weld planner: every planned weld program is verified against the cell model, collision and joint limits, and can be replayed in simulation, before it can be loaded onto the robot.
  • No torch output. Torch-class cell outputs are refused at every level.
  • No software E-stop. The hardware E-stop chain acts on drive power directly.