step.motion.heading_reference ============================= .. py:module:: step.motion.heading_reference Classes ------- .. autoapisummary:: step.motion.heading_reference.MarkHeadingReference Functions --------- .. autoapisummary:: step.motion.heading_reference.turn_to_heading_right step.motion.heading_reference.turn_to_heading_left Module Contents --------------- .. py:class:: MarkHeadingReference(origin_offset_deg: float = 0.0, positive_direction: Literal['left', 'right'] = 'left') Bases: :py:obj:`step.Step` Mark the current IMU heading as a reference point for absolute turns. Captures the robot's current absolute IMU heading and stores it as a reference. Subsequent calls to :func:`turn_to_heading_right` and :func:`turn_to_heading_left` will compute turn angles relative to this stored reference, enabling absolute heading control even after the robot has moved and turned through other motion steps. The reference uses the raw IMU heading which is unaffected by odometry resets that occur during normal motion steps. Multiple calls overwrite the previous reference. Place this step right after ``wait_for_light()`` so the heading origin is captured before the robot moves. :param origin_offset_deg: Offset in degrees added to the captured heading. Use this to define a consistent board-relative origin regardless of the robot's physical starting rotation. For example, if the robot always starts angled 30° clockwise from "forward on the board", pass ``origin_offset_deg=-30`` so that 0° means "forward on the board". :param positive_direction: Which physical direction is treated as positive for subsequent ``turn_to_heading_left`` and ``turn_to_heading_right`` calls. ``"left"`` (default) means counter-clockwise angles are positive, matching the standard mathematical convention. ``"right"`` flips the sign so clockwise angles are positive. Example:: from raccoon.step.motion import mark_heading_reference, turn_to_heading_right # Capture heading origin right after wait-for-light mark_heading_reference() # ... robot drives around ... # Turn to face 90 degrees clockwise from origin turn_to_heading_right(90) # With offset: robot starts 30° CW from board forward mark_heading_reference(origin_offset_deg=-30) # Positive direction is clockwise (right) mark_heading_reference(positive_direction="right") .. py:function:: turn_to_heading_right(degrees: float, speed: float = 1.0, force_direction: Literal['left', 'right'] | None = None) -> step.logic.defer.Defer Turn to face a heading measured clockwise from the origin. Computes the absolute target heading as ``origin - degrees`` (since clockwise is the negative direction), then turns via the shortest path. The actual turn direction (left or right) is chosen automatically to minimize rotation — only the target angle convention is clockwise. Use ``force_direction`` to override the automatic shortest-path choice when obstacles prevent turning in one direction. Requires :func:`mark_heading_reference` to have been called earlier in the mission. :param degrees: Angle in degrees clockwise from the heading origin. Must be positive. For example, 90 means "face 90° to the right of origin". :param speed: Fraction of max angular speed, 0.0 to 1.0 (default 1.0). :param force_direction: ``"left"`` or ``"right"`` to force the physical turn direction regardless of shortest path, or ``None`` (default) for automatic shortest-path selection. :returns: A deferred step that computes and executes the turn at runtime. :raises RuntimeError: If no heading reference has been set. Example:: from raccoon.step.motion import mark_heading_reference, turn_to_heading_right # Capture origin after wait-for-light mark_heading_reference() drive_forward(30) # Face 90° clockwise from where we started (shortest path) turn_to_heading_right(90) # Force turning right even if left would be shorter turn_to_heading_right(30, force_direction="right") # Return to origin heading turn_to_heading_right(0) .. py:function:: turn_to_heading_left(degrees: float, speed: float = 1.0, force_direction: Literal['left', 'right'] | None = None) -> step.logic.defer.Defer Turn to face a heading measured counter-clockwise from the origin. Computes the absolute target heading as ``origin + degrees`` (since counter-clockwise is the positive direction), then turns via the shortest path. The actual turn direction (left or right) is chosen automatically to minimize rotation — only the target angle convention is counter-clockwise. Use ``force_direction`` to override the automatic shortest-path choice when obstacles prevent turning in one direction. Requires :func:`mark_heading_reference` to have been called earlier in the mission. :param degrees: Angle in degrees counter-clockwise from the heading origin. Must be positive. For example, 90 means "face 90° to the left of origin". :param speed: Fraction of max angular speed, 0.0 to 1.0 (default 1.0). :param force_direction: ``"left"`` or ``"right"`` to force the physical turn direction regardless of shortest path, or ``None`` (default) for automatic shortest-path selection. :returns: A deferred step that computes and executes the turn at runtime. :raises RuntimeError: If no heading reference has been set. Example:: from raccoon.step.motion import mark_heading_reference, turn_to_heading_left # Capture origin after wait-for-light mark_heading_reference() drive_forward(30) # Face 90° counter-clockwise from where we started turn_to_heading_left(90) # Force turning right to avoid obstacle on the left turn_to_heading_left(45, force_direction="right") # Return to origin heading turn_to_heading_left(0)