Kinematics · repose-kinematics

Kinematics

repose-kinematics is the foundation of Repose. It describes a serial robot arm as a fixed-size chain of joints and answers the geometric questions every other crate asks: where is the tool, how does it move when the joints move, and which joint values put it where I want.

What is in the crate

Chains & jointsCuKinematicChain<N>: N joint specifications plus a tool offset. The model of your robot.
Joint values & limitsCuJointPosition and its velocity, acceleration and jerk siblings, CuJointLimits, and the metric that makes radians and metres comparable.
Forward kinematicsJoint values → tool pose, and every intermediate link frame.
JacobiansHow joint velocities map to tool velocity, in the base or tool frame, plus manipulability.
Inverse kinematicsTool pose → joint values, by damped least squares or pseudoinverse, with an explicit status.
ServoingDifferential IK: tool twist → joint velocities each cycle, damped near singularities and joint limits.
Copper tasks & payloadsThe FK, IK and servo tasks, and the joint-state payload every bridge speaks.

The mental model

Everything in the crate hangs off one value, the chain. You build it once (from a preset, inline RON, or a URDF import) and then ask it questions. Every question writes its answer into a buffer you own and returns a CuResult:

one chain, five questions
input                 CuKinematicChain<N> method        output
────────────────────  ──────────────────────────────    ───────────────────────
joint values q        forward_kinematics                tool pose
joint values q        forward_frames                    every link frame + tool
joint values q        geometric_jacobian / body_…       6×N Jacobian
target pose + seed    inverse_kinematics_dls            joint values + CuIkStatus
tool twist + q        differential_ik                   joint velocities + status

There is no hidden state. The chain is Copy, holds no heap memory, and every method takes &self. Two calls with the same inputs give the same output, which is what makes Repose runs replayable.

Design rules

  • Fixed size. N is the number of joints and a const generic, so a 6-axis arm is CuKinematicChain<6> and a Jacobian is [[f64; 6]; 6]. A mismatch between chain, payloads and tasks is a compile error.
  • Serial chains only. One path from base to tool. Branching or closed-loop mechanisms are out of scope.
  • No allocation, no panics. Results go into &mut buffers. Non-finite inputs, wrong units and invalid specs are returned as errors.
  • no_std. The crate builds with default-features = false for embedded targets.
  • Typed units. Lengths are Length, angles are Angle, velocities are typed. A metres-where-radians mistake fails to compile or is rejected at runtime, never silently converted.

Quick start

Cargo.toml
[dependencies]
repose-kinematics = { git = "https://github.com/ReposeRobotics/repose", tag = "v0.7.1" }
cu29 = { version = "1.3", features = ["units"] }
cu-spatial-payloads = "1.3"
src/main.rs
use cu_spatial_payloads::Transform3D;
use cu29::units::si::{angle::radian, f64::Angle};
use repose_kinematics::{igus_rebel_chain, CuIkParams, CuJointPosition};

let chain = igus_rebel_chain();
let q: [CuJointPosition; 6] = [0.0, 0.4, 0.8, 0.0, 0.6, 0.0]
    .map(|r| Angle::new::<radian>(r).into());

// Forward: joints -> tool pose.
let mut pose = Transform3D::<f64>::identity();
chain.forward_kinematics(&q, &mut pose)?;

// Inverse: tool pose -> joints, starting from a seed.
let seed = [Angle::new::<radian>(0.0).into(); 6];
let mut solution = seed;
let status = chain.inverse_kinematics_dls(&pose, &seed, &CuIkParams::default(), &mut solution)?;
assert!(status.is_converged());

Check the exact Copper crate versions against the version table. If you use the umbrella repose crate, the same types are under repose::kinematics.

API reference