Step 3
Angles, atan2 & 2-D rotation
Turn a rover to face beacons the short way round, and rotate what it sees into the world.
Radians and directions
Angles in code are in radians: a full turn is rad (360°), so 1 rad is about 57.3°. np.degrees and np.radians convert.
The unit vector at angle , measured counter-clockwise from the axis, is . Going the other way, np.arctan2(y, x) gives the angle of the vector . Plain can't tell from ; atan2 looks at both signs, so it is right in every quadrant.
Wrapping
Headings of 179° and −179° are only 2° apart, but subtracting them gives 358°. A rover told to turn 358° spins almost all the way round. Wrapping adds or subtracts whole turns until an angle lies in , which is the short way: 358° becomes −2°.
Rotating in 2-D
Rotating a vector by multiplies it by the rotation matrix
Its columns are where the and axes end up. The same matrix moves readings between frames. The rover's pose is : its position and heading in the world. In the rover's own frame, points straight ahead and to its left. A beacon seen at range and bearing (from straight ahead, counter-clockwise) is at in the rover's frame, and in the world at
Rotate, then shift. Step 5 does the same in 3-D.
Pick & Place, step 1 aims the arm's base at the cup with the same atan2.
Your task
- Implement
rot2(theta)(a 2×2 np.array) andwrap(angle). - For each beacon in
world.beacons, inphase(f"beacon {k}"), find its direction from the rover with atan2 and turn to face it the short way:rover.turn(wrap(target - theta)).rover.poseis the rover's true pose . - Implement
beacon_to_world(pose, r, bearing), returning the beacon's world . The starter compares it with the map after every turn.
The rover starts somewhere new on every run.