Documentation
Architecture
A Repose application is a Copper application. Repose supplies the manipulation components; Copper supplies the static graph, the message clock, logging and replay. There is no Repose runtime of its own.
The pipeline
One motion, end to end. Every arrow is a typed Copper message; every box is either a library call or a task named in RON.
- State. A bridge publishes
CuJointStatePayload<N>— measured positions, velocities and robot status — on itsjoint_statechannel. - Goal.
CuJointGoalTaskpairs the first ready state with a configured goal and emits oneCuJointPlanRequest. Your own source task can emit requests instead. - Plan. A planner task searches joint space for a collision-free path and publishes a
CuJointPlanPath— including on failure, with a status that names the reason. - Time.
CuPlanToTrajectoryTaskturns the geometric path into a timedCuTrajectoryPayloadinside the configured velocity and acceleration limits. - Follow.
CuFollowTrajectoryTasksamples that trajectory on the message clock and emits a setpoint each cycle. - Control.
CuControllerTaskcompares setpoint and measured state, applies the watchdog and rate limit, and emits the one command type every bridge carries:CuJointCommandPayload<N>. - Bridge. The bridge translates that payload to the robot (or simulator) and feeds measured state back. Swapping robots changes this box only.
Library or task?
Most crates ship both surfaces over the same code. Call the library when you drive the logic yourself — a pre-flight check, a test, a one-off IK solve. Use the task when Copper should drive it: the task owns scheduling, config from RON, freezing for replay, and publishing results as messages. Applications normally compose tasks and write no glue code; the MuJoCo example is a complete loop whose only application code is a test observer.
The rules everything follows
- Static over dynamic. Joint count and every capacity are const generics. A 6-axis arm is
CuKinematicChain<6>; a trajectory isCuTrajectoryPayload<6, 1024>. Sizes are checked at compile time, not at runtime. - Zero allocation on the hot path. Hot-path methods write into caller-owned
&mutbuffers and return a status. Nothing in a task cycle parses XML, looks names up, or grows a container. no_stdruntime,stdstartup. Runtime crates build withdefault-features = falsefor embedded targets. The onestd-only step — URDF/SRDF parsing — happens once at startup and produces the same fixed-size models.- Typed units. Public APIs use Copper SI types (
Angle,Length, velocities, accelerations). Joint values areCuJointPosition:Revolute(Angle),Prismatic(Length)orFixed— a metres-where-radians bug is a type error. - Failures are data. Fallible calls return
CuResult; planners and IK publish an explicit status (CuPlanStatus,CuIkStatus) instead of dropping the result. Library and task code never panics. - Deterministic. Sampling planners draw all randomness from the job seed (a Copper
CuRngresource), and Copper logs every message. Replaying the.copperlog reproduces the run, plan included. - Configured, not coded. Robot, models, planner, limits and speeds are RON config. Tasks never pick a robot implicitly:
chainis always given, as a preset name or an inline spec.
Where robots plug in
Bridges live outside the core workspace, in repose-bridges, and implement the vendor-neutral contract: the same four channels and session lifecycle for an igus ReBeL, a UR arm, URSim or MuJoCo. That is why the template's src/program.rs does not change when the robot does.