Documentation
Integrate Repose
From an empty Copper project to a moving (simulated) arm, using only library components. If you only want to run a supported robot, the template is shorter; this page is for building your own application.
1. Depend on it
[dependencies]
repose = { git = "https://github.com/ReposeRobotics/repose", tag = "v0.7.1" }
cu29 = { version = "1.3.1", features = ["units"] }
cu-spatial-payloads = "1.3.0"Pre-1.0 there is no crates.io release, so pin a release tag. The umbrella re-exports everything (repose::kinematics, repose::motion_planning, …). Depend on single crates instead — same repo, same tag, e.g. repose-kinematics = { git = "…", tag = "v0.7.1" } — when you need only a prefix of the stack. RON type names are always the component crates' own paths, umbrella or not. Embedded target? Keep the default features off and enable std only where parsing happens (Architecture).
2. Wire the graph in RON
A complete goal → plan → time → follow → control loop needs no application code — this is the MuJoCo example's graph, trimmed to the essentials:
tasks: [
(id: "goal", type: "repose_motion_planning::CuJointGoalTask<6>",
config: {"goal": [{"revolute": 0.4}, {"revolute": -0.3}, {"revolute": 0.5},
{"revolute": 0.0}, {"revolute": 0.4}, {"revolute": 0.0}]}),
(id: "planner", type: "repose_joint_rrt_star::CuJointRrtStarTask<6>",
background: true, anytime: (time_budget_ms: 250.0, quality_target: 0.95),
resources: {"rng": "planner_rng.rng"},
config: {"chain": "igus_rebel", "collision_model": "igus_rebel",
"base_budget": 256, "refine_budget": 64}),
(id: "timing", type: "repose_motion_planning::CuPlanToTrajectoryTask<6, 1024>",
config: {"profile": "cubic", "sample_period": 0.02, "limits": { ... }}),
(id: "follower", type: "repose_trajectory::CuFollowTrajectoryTask<6, 1024>"),
(id: "controller", type: "repose_controller::CuControllerTask<6>",
config: {"tracking_error_limit": 0.5, "state_timeout": 0.2,
"rate_limit": {"max_speed": 1.5, "max_acceleration": 6.0}}),
],
resources: [(id: "planner_rng", provider: "cu_rng::CuRngBundle", config: {"seed": 42})]Connect them with cnx entries matching payload types (CuJointStatePayload<6> → CuJointPlanRequest<6> → CuJointPlanPath<6> → CuTrajectoryPayload<6, 1024> → CuTrajectoryFollowOutput<6> → CuJointCommandPayload<6>), and attach a bridge — MuJoCo, igus or UR — by its standard channels. Joint values in RON are typed: {"revolute": 0.4} radians, {"prismatic": 0.1} metres.
3. Bring your own robot
- Model it. Import URDF/SRDF at startup (Robot description) and pass
chain()/the collision model viafrom_params, or write"chain"/"collision_model"inline in RON (preset name, or a spec with exactlyNjoints / its shapes +safety_margin).Nmust match every task's type parameter. - Check capacities. Shape capacity
M, trajectoryMAX_POINTS, planner node caps and scene capacities are compile-time. Size them for your robot and paths; exhaustion is a reported status, not a panic — but it does fail the job. - Feed it state. Any bridge implementing the standard channels works; for a new device, write that bridge, not application glue.
4. Extend it
| Custom goal source | Publish CuJointPlanRequest<N> from your own task (perception, UI, sequencer) and drop CuJointGoalTask. |
| Custom planner | Implement CuJointPlanner, register one line in repose::planners (Motion planning). |
| Custom sequencing | Drive the library directly, like the template's runner: pre-flight every step with IK + collision checks, plan, parameterize, then stream — refusing to start if any step fails. |
| No Copper graph | Call the libraries in your own loop: forward_kinematics/inverse_kinematics_dls, check_configuration, a planner's begin/step/write_best, parameterize, payload.sample(..). Same code the tasks wrap. |