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 & joints | CuKinematicChain<N>: N joint specifications plus a tool offset. The model of your robot. |
| Joint values & limits | CuJointPosition and its velocity, acceleration and jerk siblings, CuJointLimits, and the metric that makes radians and metres comparable. |
| Forward kinematics | Joint values → tool pose, and every intermediate link frame. |
| Jacobians | How joint velocities map to tool velocity, in the base or tool frame, plus manipulability. |
| Inverse kinematics | Tool pose → joint values, by damped least squares or pseudoinverse, with an explicit status. |
| Servoing | Differential IK: tool twist → joint velocities each cycle, damped near singularities and joint limits. |
| Copper tasks & payloads | The 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:
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 + statusThere 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.
Nis the number of joints and a const generic, so a 6-axis arm isCuKinematicChain<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
&mutbuffers. Non-finite inputs, wrong units and invalid specs are returned as errors. no_std. The crate builds withdefault-features = falsefor embedded targets.- Typed units. Lengths are
Length, angles areAngle, velocities are typed. A metres-where-radians mistake fails to compile or is rejected at runtime, never silently converted.
Quick start
[dependencies]
repose-kinematics = { git = "https://github.com/ReposeRobotics/repose", tag = "v0.7.1" }
cu29 = { version = "1.3", features = ["units"] }
cu-spatial-payloads = "1.3"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.