Getting started

Basic example

Compute where the tool of an igus ReBeL is for a set of joint angles, then solve back to joint angles from that pose. Then run the same kinematics as a Copper task.

Forward and inverse kinematics

Put this in src/main.rs:

src/main.rs
use cu_repose::kinematics::{CuIkParams, CuIkStatus, CuJointPosition, igus_rebel_chain};
use cu_spatial_payloads::Transform3D;
use cu29::prelude::*;
use cu29::units::si::{angle::radian, f64::Angle};

fn main() -> CuResult<()> {
    // 6-DOF igus ReBeL; the joint count is part of the type.
    let chain = igus_rebel_chain();

    // Forward kinematics: joint positions -> tool pose, written in place.
    let q: [CuJointPosition; 6] =
        [0.0, 0.4, 0.8, 0.0, 0.6, 0.0].map(|r| Angle::new::<radian>(r).into());
    let mut tool = Transform3D::<f64>::identity();
    chain.forward_kinematics(&q, &mut tool)?;

    // Inverse kinematics: back from that pose, seeded nearby.
    let seed: [CuJointPosition; 6] =
        [0.1, 0.3, 0.7, 0.1, 0.5, 0.1].map(|r| Angle::new::<radian>(r).into());
    let mut solution = seed;
    let status = chain.inverse_kinematics_dls(&tool, &seed, &CuIkParams::default(), &mut solution)?;

    match status {
        CuIkStatus::Converged { iterations, .. } => println!("IK converged in {iterations} iterations"),
        other => println!("IK did not converge: {other:?}"),
    }
    Ok(())
}
shell
cargo run
# IK converged in 5 iterations

What just happened

  • Typed units. Joint values are CuJointPositions built from SI Angles, so radians and metres can't be mixed up.
  • In-place outputs. forward_kinematics and inverse_kinematics_dls write into buffers you own and allocate nothing, so they are safe in a real-time loop.
  • Explicit status. IK reports Converged with its error, or the best configuration it reached, rather than failing silently.

As a Copper task

In an application you don't call the library by hand. You add its task to the graph in copperconfig.ron and pick the robot by preset name:

copperconfig.ron
(
    id: "fk",
    type: "cu_kinematics::CuForwardKinematicsTask<6>",
    config: {"chain": "igus_rebel"},
),

Tasks never pick a robot implicitly: chain is either a preset name or an inline list of exactly N joint specifications.

Next steps

The MuJoCo ReBeL example wires the whole pipeline — goal, RRT* planner, timing, follower and controller — against a simulated arm, configured entirely in RON.