step.motion.path.passes.velocity_profile ======================================== .. py:module:: step.motion.path.passes.velocity_profile .. autoapi-nested-parse:: Time-optimal velocity profiling pass. Generalises the executor's local warm-start (carry velocity only across the single adjacent same-type seam) into a GLOBAL forward/backward sweep over the whole compiled path. It computes, for every motion segment, the fastest feasible ENTRY and EXIT speed (m/s) such that the robot: * starts and ends at rest, * never exceeds a segment's cruise cap (``max_speed * speed_scale``) or, for arcs, the curvature cap ``v <= sqrt(lat_accel * R)``, * can always accelerate up to / decelerate down to the next constraint within a segment's length (the two-sweep feasibility), and * drops to a full stop at every REAL barrier — a turn (rotation in place), a direction reversal, a blocking inline side action, a deferred node, and the path's last segment. A sensor-bounded ``.until()`` leg's end is NOT an unconditional stop: when the next leg continues in the SAME direction the robot FLOWS THROUGH the sensor boundary (capped by ``sensor_carry_mps``) instead of braking to zero — "time- optimal on steroids" for the sensor-driven style. See :func:`_seam_speed_cap`. The speeds are stamped onto ``Segment.entry_speed_mps`` / ``exit_speed_mps``. The pass is PATH-PRESERVING — it changes only speed, never geometry — and is opt-in via ``optimize(steps).time_optimal()``. With the pass off the fields stay ``None`` and the executor's behaviour is byte-identical to before. Attributes ---------- .. autoapisummary:: step.motion.path.passes.velocity_profile.DEFAULT_MAX_SPEED_MPS step.motion.path.passes.velocity_profile.DEFAULT_ACCEL_MPS2 step.motion.path.passes.velocity_profile.DEFAULT_LATERAL_ACCEL_MPS2 step.motion.path.passes.velocity_profile.DEFAULT_SENSOR_CARRY_MPS Classes ------- .. autoapisummary:: step.motion.path.passes.velocity_profile.VelocityProfilePass Functions --------- .. autoapisummary:: step.motion.path.passes.velocity_profile.run_velocity_profile Module Contents --------------- .. py:data:: DEFAULT_MAX_SPEED_MPS :value: 1.0 .. py:data:: DEFAULT_ACCEL_MPS2 :value: 0.6 .. py:data:: DEFAULT_LATERAL_ACCEL_MPS2 :value: 0.5 .. py:data:: DEFAULT_SENSOR_CARRY_MPS :value: inf .. py:function:: run_velocity_profile(nodes: list[step.motion.path.ir.PathNode | None], *, max_speed_mps: float = DEFAULT_MAX_SPEED_MPS, accel_mps2: float = DEFAULT_ACCEL_MPS2, lateral_accel_mps2: float = DEFAULT_LATERAL_ACCEL_MPS2, sensor_carry_mps: float = DEFAULT_SENSOR_CARRY_MPS) -> list[step.motion.path.ir.PathNode | None] Stamp feasible entry/exit speeds onto every motion Segment via a global two-sweep. Returns a NEW node list (segments replaced); non-motion nodes are preserved in place. .. py:class:: VelocityProfilePass(max_speed_mps: float = DEFAULT_MAX_SPEED_MPS, accel_mps2: float = DEFAULT_ACCEL_MPS2, lateral_accel_mps2: float = DEFAULT_LATERAL_ACCEL_MPS2, sensor_carry_mps: float = DEFAULT_SENSOR_CARRY_MPS) Compiler pass: stamp a global time-optimal velocity profile (entry/exit speeds) onto the path. Path-preserving; opt-in via ``.time_optimal()``. .. py:attribute:: name :value: 'time_optimal' .. py:attribute:: max_speed_mps :value: 1.0 .. py:attribute:: accel_mps2 :value: 0.6 .. py:attribute:: lateral_accel_mps2 :value: 0.5 .. py:attribute:: sensor_carry_mps :value: inf .. py:method:: run(nodes: list[step.motion.path.ir.PathNode | None]) -> list[step.motion.path.ir.PathNode | None]