A greenhouse robot picks tomatoes with a planar two-link arm: the shoulder joint at the origin, a first link of length l1, an elbow, and a second link of length l2 ending in the picker (the hand). The joint angles are in radians and relative: t1 is the first link's angle from the +x axis, and t2 is the second link's angle from the direction of the first link. With x to the right and y up, the hand is at
The Jacobian J is the 2 \times 2 matrix of partial derivatives: row 0 holds \partial x / \partial t_1 and \partial x / \partial t_2, row 1 holds \partial y / \partial t_1 and \partial y / \partial t_2.
The firmware will later run on arms whose formula nobody wrote down, so it estimates J by central differences with a step h: to estimate column j, move joint j alone by +h and by -h, compute the hand position p^{+} and p^{-} both times, and take
Before trusting it, you test it on this arm. Write jacobian_check(l1, l2, t1, t2, h) that returns a tuple (estimate, error):
estimate: the central-difference Jacobian, as[[dx_dt1, dx_dt2], [dy_dt1, dy_dt2]];error: the largest absolute difference between an entry ofestimateand the same entry of the exact Jacobian.
Examples
Input: l1 = 2, l2 = 1, t1 = 0, t2 = math.pi / 2, h = 0.1
Output: ([[-0.99833417, -0.99833417], [1.99666833, 0.0]], 0.00333167)
Explanation: the exact Jacobian is [[-1, -1], [2, 0]]; the largest gap is in row 1, column 0.
Input: l1 = 0.4, l2 = 0.3, t1 = 0.5, t2 = -1.2, h = 0.5
Output: ([[0.00143357, 0.18531265], [0.55659932, 0.22001093]], 0.02388636)
Constraints
- answers are compared with a tolerance of
1e-6; do not round
Goals
- Estimate each column of a Jacobian by nudging one joint both ways
- Compare a numerical estimate with the exact derivatives entry by entry
- See the estimate's error shrink as the step gets smaller