Collision · repose-collision

Shapes & distances

All collision geometry in Repose is built from two primitives. Every query between them returns an exact signed distance.

Primitives

CuSphere { center, radius }A ball. center: [Length; 3], radius: Length.
CuCapsule { a, b, radius }A sphere swept along the segment from a to b: a cylinder with hemispherical caps. A capsule with a == b is a sphere.
CuCollisionShapeSphere(CuSphere) or Capsule(CuCapsule). What models, scenes and checks take.
rust
let m = Length::new::<meter>;
let ball = CuSphere::new([m(0.4), m(0.0), m(0.3)], m(0.05))?;
let post = CuCapsule::new([m(0.6), m(0.2), m(0.0)], [m(0.6), m(0.2), m(0.8)], m(0.04))?;
let shapes = [CuCollisionShape::Sphere(ball), CuCollisionShape::Capsule(post)];

The constructors reject non-finite coordinates and negative radii. shape.validate() does the same for shapes you build as struct literals or deserialize.

metres
{"sphere": {"center": [0.4, 0.0, 0.3], "radius": 0.05}}
{"capsule": {"a": [0.6, 0.2, 0.0], "b": [0.6, 0.2, 0.8], "radius": 0.04}}

Signed distance

rust
let d = shape_signed_distance(&a, &b);      // Length: surface to surface

Positive means a gap of that size, zero means touching, negative means penetration by that depth. The specialised functions sphere_sphere_signed_distance, capsule_sphere_signed_distance and capsule_capsule_signed_distance are what it dispatches to. Capsule-capsule reduces to the closest points between two segments, minus both radii.

shapes_violate_margin(a, b, margin) is the predicate checks use: true when the distance is strictly below margin.

Approximating real geometry

  • Links: one capsule from joint to joint, radius covering the housing. Add a second capsule for an offset motor housing.
  • Tables and walls: a large sphere far below the surface approximates a plane locally, or tile capsules along the edge you can reach.
  • Boxes: capsules along the edges or spheres at the corners, sized so the union encloses the box. Over-approximate: a planner refusing a tight gap is better than a collision.
  • Margins: add your positioning uncertainty to the model's safety_margin rather than inflating every shape.

Shapes on frames

Robot and attached shapes live in a joint frame instead of the world. CuLinkShape { shape, frame } pairs a shape with a frame index (Some(i) for joint frame i, None for the base). CuLinkShape::transform_shape(..) moves a local shape into world coordinates given that frame's transform.

API reference