step.motion.spline_path

Spline path motion step — smooth curved path through waypoints.

Classes

SplinePath

Drive along a centripetal Catmull-Rom spline through waypoints.

Functions

spline(→ SplinePath)

Drive along a smooth curved path through a series of waypoints.

Module Contents

class step.motion.spline_path.SplinePath(waypoints: list[tuple[float, Ellipsis]], speed: float, absolute_heading: bool = False, final_heading_deg: float | None = None)

Bases: step.motion.motion_step.MotionStep

Drive along a centripetal Catmull-Rom spline through waypoints.

Supports two waypoint formats: - 2-tuples (forward_cm, left_cm): heading follows spline tangent. - 3-tuples (forward_cm, left_cm, heading_deg): explicit heading at each

waypoint, linearly interpolated vs arc-length. Omni drivetrains only.

on_start(robot: raccoon.robot.api.GenericRobot) None
on_update(robot: raccoon.robot.api.GenericRobot, dt: float) bool
step.motion.spline_path.spline(*waypoints: tuple[float, Ellipsis], speed: float = 1.0, absolute_heading: bool = False, final_heading: float | None = None) SplinePath

Drive along a smooth curved path through a series of waypoints.

The robot follows a centripetal Catmull-Rom spline that passes through every waypoint with continuous velocity. A trapezoidal velocity profile on arc-length provides smooth acceleration and deceleration along the path, while a heading PID keeps the robot oriented along the curve.

Waypoints are specified relative to the robot’s pose when the step starts. Two formats are supported:

  • 2-tuples (forward_cm, left_cm): heading automatically follows the spline tangent. Works on both differential and omni drivetrains.

  • 3-tuples (forward_cm, left_cm, heading_deg): explicit heading at each waypoint, linearly interpolated along the path. Omni drivetrains only — raises ValueError on differential bots.

Absolute heading mode (absolute_heading=True): the heading PID computes its error against the IMU’s absolute heading (get_absolute_heading()) which is never reset by odometry resets. The absolute heading at the start of the step is captured and used as an offset so that waypoint headings are still expressed relative to the robot’s facing direction at the start — the convention is unchanged. Use this when the spline is chained after other motions that reset odometry and you need heading tracking to remain stable.

Final heading (final_heading): the heading the robot should be facing when it arrives at the last waypoint, in degrees. The robot smoothly rotates from its start heading to this target heading as it follows the path (linear interpolation by arc-length). Ignored when 3-tuple waypoints are used (per-waypoint headings take precedence). When absolute_heading=True, final_heading is interpreted as an absolute heading relative to the heading reference (same convention as drive_forward(heading=…)). When absolute_heading=False, final_heading is relative to the robot’s start orientation (0 = keep facing forward, 90 = face 90° CCW at the end).

Prerequisites:

Drive characterization (auto_tune or characterize_drive) must have been run so that axis constraints are populated. mark_heading_reference() required when using absolute_heading=True with final_heading.

Parameters:
  • *waypoints – Two or more waypoints as tuples. forward_cm is centimeters ahead of the start position (positive = forward). left_cm is centimeters to the left (positive = left). Optional heading_deg is the desired heading in degrees (0 = initial heading, positive = CCW).

  • speed – Fraction of maximum speed, 0.0 to 1.0 (default 1.0).

  • absolute_heading – If True, compute heading error against the absolute IMU heading instead of the reset-relative heading (default False).

  • final_heading – Optional desired heading in degrees at the end of the path. Relative to start orientation when absolute_heading=False; absolute (heading-reference-based) when absolute_heading=True. Default None (no heading target).

Returns:

A SplinePath step configured for the described curved path.

Raises:
  • ValueError – If fewer than 2 waypoints or inconsistent tuple sizes.

  • ValueError – If explicit headings (3-tuples) are used on a non-omni drivetrain.

Example:

from raccoon.step.motion import spline

# S-curve around an obstacle (heading follows tangent)
spline((30, 0), (50, 15), (50, 30), (30, 30))

# Gentle curve at half speed
spline((40, 0), (60, 20), speed=0.5)

# Arrive facing 90° left of start orientation
spline((30, 0), (50, 20), final_heading=90)

# Omni: curve while rotating to face 90° left at the end
spline((30, 0, 0), (50, 15, 45), (50, 30, 90))

# After an odometry reset, keep heading stable against the IMU
spline((30, 0), (50, 20), absolute_heading=True)

# Absolute heading + arrive facing north (heading reference = north)
spline((30, 0), (50, 20), absolute_heading=True, final_heading=0)