step.motion.spline_path¶
Spline path motion step — smooth curved path through waypoints.
Classes¶
Drive along a centripetal Catmull-Rom spline through waypoints. |
Functions¶
|
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.MotionStepDrive 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.
- 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 — raisesValueErroron 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). Whenabsolute_heading=True,final_headingis interpreted as an absolute heading relative to the heading reference (same convention asdrive_forward(heading=…)). Whenabsolute_heading=False,final_headingis relative to the robot’s start orientation (0 = keep facing forward, 90 = face 90° CCW at the end).- Prerequisites:
Drive characterization (
auto_tuneorcharacterize_drive) must have been run so that axis constraints are populated.mark_heading_reference()required when usingabsolute_heading=Truewithfinal_heading.
- Parameters:
*waypoints – Two or more waypoints as tuples.
forward_cmis centimeters ahead of the start position (positive = forward).left_cmis centimeters to the left (positive = left). Optionalheading_degis 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) whenabsolute_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)