Collision · repose-collision
Robot collision models
A robot collision model is the robot's body as spheres and capsules, each riding on one of the chain's joint frames. Together with the kinematic chain it is everything needed to place the robot in space at any configuration.
The type
CuRobotCollisionModel<N, M = N> holds up to M shapes for an N-joint chain. Several shapes can share a frame, so raise M above N when one capsule per link isn't enough (imported robots usually need it).
let m = Length::new::<meter>;
let shapes = [
// Upper arm on joint frame 1: capsule along its local z axis.
CuLinkShape::new(CuCollisionShape::Capsule(CuCapsule::new([m(0.0); 3], [m(0.0), m(0.0), m(0.3)], m(0.05))?), Some(1)),
// Tool on the last frame.
CuLinkShape::new(CuCollisionShape::Sphere(CuSphere::new([m(0.0), m(0.0), m(0.05)], m(0.04))?), Some(5)),
// Base column, not moving.
CuLinkShape::new(CuCollisionShape::Capsule(CuCapsule::new([m(0.0); 3], [m(0.0), m(0.0), m(0.1)], m(0.08))?), None),
];
let model = CuRobotCollisionModel::<6, 8>::new(&shapes, CuCollisionModelParams {
safety_margin: m(0.005),
skip_adjacent_links: true,
})?;Which frame is which
Frame i is the transform forward_frames reports for joint i: the joint's origin and its motion applied, so a shape on frame i turns with joint i. Put each link's shape on the joint that moves it. A shape that should stay put goes on None, the base frame.
Parameters: CuCollisionModelParams
safety_margin | A pair closer than this counts as a collision. Default 0.0; the ReBeL preset uses 5 mm. It applies to every pair: self, environment and attached. |
skip_adjacent_links | Default true. Don't check shapes on neighbouring frames (i and i ± 1) against each other. They touch at the joint by construction. Shapes on the same frame are never checked against each other. |
Fine-grained pair control
Adjacent-skipping is a blunt rule. For exact control, toggle individual pairs by shape index:
model.set_pair_enabled(0, 3, false)?; // shapes 0 and 3 can never meet: skip them
assert!(!model.is_pair_enabled(0, 3));Disabling pairs that are geometrically unable to collide makes checks faster. Disabling pairs that can collide hides real collisions, so only do it for pairs you've verified. An SRDF's disable_collisions list is applied this way on import.
Presets and RON
igus_rebel_collision_model() is the built-in ReBeL model: six shapes, one per joint frame, 5 mm margin, adjacent links skipped. In task config, CuCollisionModelSpec accepts the preset name or an inline model:
"collision_model": "igus_rebel""collision_model": {
"shapes": [
{"shape": {"capsule": {"a": [0.0, 0.0, 0.0], "b": [0.0, 0.0, 0.2], "radius": 0.05}}, "frame": 0},
{"shape": {"sphere": {"center": [0.0, 0.0, 0.05], "radius": 0.04}}, "frame": 5},
],
"safety_margin": 0.005,
}Omit frame for a base-frame shape. The spec is resolved against the task's N and M at startup, and a preset with a different joint count is rejected.
Reading a model back
shape_count() / link_shapes() | The active shapes. Their order defines the shape indices in contacts and exclusions. |
safety_margin() / set_safety_margin(..) | Read or change the margin at runtime. |
world_link_shapes(&frames, &mut out) | Every shape in world coordinates, for drawing the model over a camera image or a 3D view. |
Validating a new model
- Draw
world_link_shapesat a few configurations next to the robot's mesh. Every link must be covered. - Check home and the configurations your program uses: all must be collision-free with
CuCollisionEnv::EMPTY. A collision here usually means a pair that touches by construction and should be disabled. - Fold the arm toward itself until it would really hit: the check must report it before it happens.