step.motion.path.passes.corner_cut

Corner-cut pass — round a corner between two straight legs with an arc.

Two corner shapes are cut, both trimming cut_m from each straight leg:

  • Turn cornerlinear + turn + linear (the legs share an axis and direction; the heading rotates by the turn angle). Becomes linear + arc + linear with R = cut_m / tan(|θ| / 2). Works for forward AND strafe legs (a strafe + turn + strafe corner yields a lateral arc).

  • Crab cornerlinear(Forward) + linear(Lateral) (or vice-versa) with NO turn between: a holonomic base changes travel direction by 90° WITHOUT rotating. Becomes linear + crab_arc + linear — a constant-heading quarter circle of radius R = cut_m (tan 45° = 1) that blends the body velocity from one leg’s direction into the other’s.

Only triples/pairs with known endpoints and no conditions are eligible. SideAction and deferred-placeholder (None) entries act as barriers; background / ephemeral parallel-branch side actions are skipped over (they run concurrently with the motion) and re-emitted around the arc.

Classes

CornerCutPass

Compiler pass that rounds turn corners (arcs) and crab corners (crab arcs).

Functions

try_corner_arc(→ tuple[step.motion.path.ir.Segment, ...)

Return (new_lin1, arc, new_lin2) for a turn corner, or None.

try_crab_arc(→ tuple[step.motion.path.ir.Segment, ...)

Return (new_lin1, crab_arc, new_lin2) for a crab corner, or None.

run_corner_cut(→ list[step.motion.path.ir.PathNode | None])

Replace turn corners with arcs and crab corners with crab arcs.

Module Contents

step.motion.path.passes.corner_cut.try_corner_arc(lin1: step.motion.path.ir.Segment, turn: step.motion.path.ir.Segment, lin2: step.motion.path.ir.Segment, cut_m: float, cut_until: bool = False) tuple[step.motion.path.ir.Segment, step.motion.path.ir.Segment, step.motion.path.ir.Segment] | None

Return (new_lin1, arc, new_lin2) for a turn corner, or None.

Geometry: cutting cut_m from each leg at the corner requires an arc of radius R = cut_m / tan(|θ| / 2). Both linears must be the same axis and direction (the heading rotates by the turn angle, so the path deflects by exactly θ) and have enough distance to accommodate the cut. A pair of lateral (strafe) legs yields a lateral arc; forward legs a drive arc.

The entry leg must be a known, trimmable distance. With cut_until the EXIT leg may instead be a sensor-bounded .until() leg (kept untrimmed).

step.motion.path.passes.corner_cut.try_crab_arc(lin1: step.motion.path.ir.Segment, lin2: step.motion.path.ir.Segment, cut_m: float, cut_until: bool = False) tuple[step.motion.path.ir.Segment, step.motion.path.ir.Segment, step.motion.path.ir.Segment] | None

Return (new_lin1, crab_arc, new_lin2) for a crab corner, or None.

A crab corner is two perpendicular straight legs (one Forward, one Lateral) with NO turn between them: a holonomic base changes travel direction by 90° at constant heading. The fillet is a quarter circle of radius R = cut_m / tan(45°) = cut_m; the executor’s CrabArcAdapter sweeps the body velocity from lin1’s direction into lin2’s.

The entry leg must be a known, trimmable distance. With cut_until the EXIT leg may instead be a sensor-bounded .until() leg (kept untrimmed) — e.g. drive_backward(18) + strafe_left().until(over_line).

step.motion.path.passes.corner_cut.run_corner_cut(nodes: list[step.motion.path.ir.PathNode | None], cut_m: float, cut_until: bool = False) list[step.motion.path.ir.PathNode | None]

Replace turn corners with arcs and crab corners with crab arcs.

At each position a linear+turn+linear turn corner is tried first, then a linear+linear crab corner. Non-blocking (background / ephemeral) side actions between the legs are skipped over for the match and re-emitted concurrently with the arc. Blocking side actions and deferred placeholders are barriers.

With cut_until the EXIT leg of a corner may be a sensor-bounded .until() leg (kept untrimmed, runs from the arc’s end until its condition). The entry leg always needs a known, trimmable distance.

class step.motion.path.passes.corner_cut.CornerCutPass(cut_m: float, cut_until: bool = False)

Compiler pass that rounds turn corners (arcs) and crab corners (crab arcs).

name = 'corner_cut'
cut_m
cut_until = False
run(nodes: list[step.motion.path.ir.PathNode | None]) list[step.motion.path.ir.PathNode | None]