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).

rust
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_marginA 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_linksDefault 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:

rust
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:

preset
"collision_model": "igus_rebel"
inline
"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

  1. Draw world_link_shapes at a few configurations next to the robot's mesh. Every link must be covered.
  2. 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.
  3. Fold the arm toward itself until it would really hit: the check must report it before it happens.

API reference