Problem 131810 · medium · Robotics · Level 01 Poses and Frames

One Notch per Tick

angle difference · angle wrapping · rate limit · control loop · while loops

A rover's camera mast is driven by a motor that can turn it by at most max_step radians per control tick. To point the camera at a new heading target, the controller runs this loop, one pass per tick, until the mast faces the target:

  1. Work out the shortest signed turn d from the mast's heading to target: the angle in -\pi < d \le \pi that, added to the heading, gives the target's direction (positive is counter-clockwise). When the target is exactly opposite, d is +\pi.
  2. If abs(d) <= max_step, the mast moves the rest of the way: its heading becomes exactly target, and the loop ends after this tick.
  3. Otherwise it turns by max_step in the direction of d (counter-clockwise if d > 0, clockwise if d < 0), and the new heading is wrapped to (-\pi, \pi].

Headings are in radians, counter-clockwise from the world's +x axis, wrapped to (-\pi, \pi]. The mast starts at heading current.

Write pan_headings(current, target, max_step) that returns the list of the mast's headings after each tick, the last one being target. If the mast already faces the target (current == target), no tick is needed: return [].

Examples

Input:  current = 0.0, target = 1.0, max_step = 0.3
Output: [0.3, 0.6, 0.9, 1.0]

Input:  current = 3.0, target = -3.0, max_step = 0.1
Output: [3.1, -3.083185307179586, -3.0]
Explanation: the short way from 3.0 to -3.0 is counter-clockwise through pi (0.283 radians).
After 3.1 the next notch, 3.2, is past pi and wraps to 3.2 - 2*pi = -3.083. The last 0.083
is within one notch.

Input:  current = 0.0, target = 3.141592653589793, max_step = 1.0
Output: [1.0, 2.0, 3.0, 3.141592653589793]
Explanation: the target is exactly opposite, so the mast turns counter-clockwise.

Constraints

  • answers are compared with a tolerance of 1e-6; do not round

Goals

  • Recompute the shortest signed turn to a target on every tick
  • Limit each step of a turn and stop exactly on the target
  • Wrap a heading that crosses the $\pm\pi$ boundary while turning
Starting Python…