step.motion.at_heading

Wait until the robot has turned a certain number of degrees.

Designed to run inside a parallel() branch alongside a turn step:

parallel(

turn_left(90), seq([wait_until_degrees(45), servo_open()]),

)

Multiple heading-triggered actions:

parallel(

turn_left(90), seq([wait_until_degrees(30), arm_lower()]), seq([wait_until_degrees(60), servo_open()]), seq([wait_until_degrees(85), servo_close()]),

)

Polls odometry heading at 100 Hz. Three origin modes are available — see HeadingOrigin for details.

Classes

HeadingOrigin

Reference point from which wait_until_degrees measures rotation.

WaitUntilDegrees

Wait until the robot has turned at least the given number of degrees.

Module Contents

class step.motion.at_heading.HeadingOrigin(*args, **kwds)

Bases: enum.Enum

Reference point from which wait_until_degrees measures rotation.

Choose the origin that matches where your degree target is counted from. All three modes use the same 100 Hz polling loop and stall detection — only the zero point differs.

Members

STEP_START

Degrees are counted from the heading at the moment wait_until_degrees itself starts executing.

Use this when wait_until_degrees is the first step in its seq() branch, i.e. there are no prior steps that could consume time while the turn is already progressing. This is the default.

Example — fires 45° after the step starts:

parallel([
    turn_left(90),
    seq([wait_until_degrees(45), servo(claw, 90)]),
])
TURN_START

Degrees are counted from the heading at the start of the concurrent turn step. TurnMotion.start() resets odometry to zero, so this origin is always zero regardless of when wait_until_degrees begins running.

Use this when earlier steps in the same seq() branch may have taken time while the turn was already progressing, and you still want the threshold to be measured from the turn’s own start, not from a later point in the branch.

Example — fires when the turn has reached 45° from its own start, even though prepare_arm() ran first:

parallel([
    turn_left(90),
    seq([prepare_arm(), wait_until_degrees(45, origin=HeadingOrigin.TURN_START), servo(claw, 90)]),
])
HEADING_REFERENCE

Degrees are counted from the global heading reference set by mark_heading_reference(). Uses the raw IMU heading (get_absolute_heading()), which is never reset by motion steps.

Use this when you want to trigger an action at a board-absolute heading rather than at an angle relative to the current turn. Requires mark_heading_reference() to have been called earlier in the mission.

Example — fires when the robot faces 45° from its mission-start heading, no matter how many turns have happened before:

mark_heading_reference()
# ... other motion ...
parallel([
    turn_left(90),
    seq([wait_until_degrees(45, origin=HeadingOrigin.HEADING_REFERENCE), servo(claw, 90)]),
])
STEP_START = 'step_start'
TURN_START = 'turn_start'
HEADING_REFERENCE = 'heading_reference'
class step.motion.at_heading.WaitUntilDegrees(degrees: float, origin: HeadingOrigin = HeadingOrigin.STEP_START)

Bases: step.Step

Wait until the robot has turned at least the given number of degrees.

Polls heading at 100 Hz and compares the angular distance from the chosen origin against the threshold. Designed to run inside a parallel() branch alongside a turn step, enabling actions to trigger at specific angles during a turn.

The origin (zero point) is controlled by the origin parameter — see HeadingOrigin for the three available modes.

Parameters:
  • degrees – Heading-change threshold in degrees (always positive).

  • origin – Which reference point to count degrees from. Defaults to HeadingOrigin.STEP_START.

Example:

from raccoon.step import parallel, seq
from raccoon.step.motion import turn_left, wait_until_degrees, HeadingOrigin
from raccoon.step.servo import servo

# Default: fires 45° after this step starts executing
parallel([
    turn_left(90),
    seq([wait_until_degrees(45), servo(claw, 90)]),
])

# TURN_START: fires at 45° from the turn's own start
parallel([
    turn_left(90),
    seq([prepare_arm(), wait_until_degrees(45, origin=HeadingOrigin.TURN_START), servo(claw, 90)]),
])

# HEADING_REFERENCE: fires at 45° from the global reference
parallel([
    turn_left(90),
    seq([wait_until_degrees(45, origin=HeadingOrigin.HEADING_REFERENCE), servo(claw, 90)]),
])