Problem 240328 · medium · Robotics · Level 02 Motion

The Telescoping Boom

forward kinematics · prismatic joint · revolute joint · angle wrapping

Robot joints come in two basic kinds. A revolute joint turns: its value is an angle. A prismatic joint slides: its value is a distance, like a telescope pulled out. A fruit-picking arm combines both: a turning shoulder, a telescoping boom, a turning wrist.

The arm is planar, its base at the origin, pointing along +x before the first part. x points right and y up; angles are in radians, counter-clockwise. From base to hand, the arm is a list parts; each part is one of:

  • ("R", angle, length): a revolute joint that turns the current direction by angle (relative to the direction so far), followed by a rigid link of length in the new direction;
  • ("P", extension): a prismatic joint, a telescoping link that reaches extension further along the current direction, without turning (0 means fully retracted).

Write chain_pose(parts) that returns the hand's pose (x, y, heading): the position at the end of the last part, and the current direction there, measured from +x and wrapped into (-\pi, \pi] (whole turns of 2\pi added or subtracted; a direction along -x is \pi, never -\pi).

Examples

Input:  parts = [("R", math.pi / 2, 1), ("P", 0.5), ("R", -math.pi / 2, 0.3)]
Output: (0.3, 1.5, 0.0)
Explanation: the shoulder points the first link up to (0, 1); the boom slides
0.5 further up, to (0, 1.5); the wrist turns back to +x and adds 0.3.

Input:  parts = [("P", 2), ("R", math.pi / 2, 1), ("P", 0)]
Output: (2.0, 1.0, 1.57079633)
Explanation: a rail first carries the arm 2 along +x.

Input:  parts = [("R", 3.0, 0.5), ("P", 0.25), ("R", 2.0, 0.4)]
Output: (-0.6290295, -0.2777297, -1.28318531)
Explanation: the turns add up to 5.0 radians, which is 5.0 - 2 * pi once wrapped.

Constraints

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

Goals

  • Treat a sliding joint as a link whose length is the joint value
  • Walk a chain that mixes turning and sliding joints
  • Return the hand's heading wrapped into $(-\pi, \pi]$
Starting Python…