The Jacobian turns joint speeds into hand speed
The Jacobian is a small table of numbers that says how fast a robot hand moves when each joint turns at a given speed. A controller needs it to move the hand smoothly. For that it must know how every joint affects the hand.
In this lesson you estimate the Jacobian of the simulated two-joint arm by a small nudge, and use it to find the hand speed.
By the end of this lesson
Note
I can say how fast the hand moves when the joints turn, using a Jacobian estimated from a small step.
Key words
| Word | What it means |
|---|---|
| Jacobian | a table that links joint speeds to hand speed |
| Numerical estimate | an answer found by a small step instead of a formula |
| Step size | how small the nudge to a joint is |
| Singularity | an arm pose where the hand cannot move in some direction |
| Determinant | one number that is zero when a table cannot be reversed |
The cells students fill in are left blank in this preview.
Hand speed depends on the pose
Turn joint 1 at 10 degrees a second. How fast does the hand move? It depends on where the arm is. A stretched arm swings its hand fast, and a folded arm swings it slowly.
So there is no single number. For every pose there is a small table, the Jacobian, that turns joint speeds into hand speed.
Nudge one joint and watch the hand
You do not need a formula. Turn joint 1 a tiny bit forward, then a tiny bit back, and compare the two hand positions with forward kinematics.
The difference divided by the size of the whole change is how far the hand moves per degree of joint 1. This is a numerical estimate: a step instead of algebra.
Worked example: a 0.01 degree nudge
| Joint 1 | Hand x | Hand y |
|---|---|---|
| 29.99 | 2.59869 | 3.49955 |
| 30.01 | 2.59747 | 3.50045 |
| Difference | -0.00122 | 0.00091 |
| Divided by 0.02 | -0.0611 | 0.0453 |
The cells students fill in are left blank in this preview.
Estimate one column of the Jacobian with NumPy
docker exec jupyter python3 -c "import numpy as np; f = lambda a, b: np.array([3 * np.cos(np.radians(a)) + 2 * np.cos(np.radians(a + b)), 3 * np.sin(np.radians(a)) + 2 * np.sin(np.radians(a + b))]); print(np.round((f(30.01, 60) - f(29.99, 60)) / 0.02, 4))"Shown here, not run. Create a free account to press Run and type it into your own lab’s terminal.
Each joint gives one column of the table
The Run above prints two numbers, -0.0611 and 0.0453. They say that one degree of joint 1 moves the hand 0.0611 to the left and 0.0453 up.
Do the same for joint 2 and you have a second column. Together the two columns make a table with two rows, across and up, and two columns, joint 1 and joint 2.
Estimate a column in plain Python
import math
def hand(a1, a2):
t1 = math.radians(a1)
t2 = math.radians(a1 + a2)
return [3 * math.cos(t1) + 2 * math.cos(t2), 3 * math.sin(t1) + 2 * math.sin(t2)]
step = 0.01
before = hand(30 - step, 60)
after = hand(30 + step, 60)
dx = (after[0] - before[0]) / (2 * step)
dy = (after[1] - before[1]) / (2 * step)
print("hand moves per degree of joint 1:", round(dx, 4), round(dy, 4))
# Change step to 1 and press Run.
# The answer shifts a little. A bigger step is a rougher estimate.
A common mistake
Warning
Many people think a smaller step is always better. A step that is too large is a rough guess, but one that is far too small lets rounding errors drown the answer. A step of 0.01 degrees, taken on both sides, is a good choice for this arm.
Multiply the table by the joint speeds
With the Jacobian for the pose, the hand speed across is the first row times the joint speeds, added up. The hand speed up is the second row times the same speeds.
Take joint speeds of 10 and 20 degrees a second. The hand speed is then -1.309 across and 0.453 up, in length units a second.
Find hand speed from joint speeds
docker exec jupyter python3 -c "import numpy as np; f = lambda a, b: np.array([3 * np.cos(np.radians(a)) + 2 * np.cos(np.radians(a + b)), 3 * np.sin(np.radians(a)) + 2 * np.sin(np.radians(a + b))]); j = np.array([(f(30.01, 60) - f(29.99, 60)) / 0.02, (f(30, 60.01) - f(30, 59.99)) / 0.02]).T; print(np.round(j @ np.array([10, 20]), 3))"Shown here, not run. Create a free account to press Run and type it into your own lab’s terminal.
Hand speed from a table and joint speeds
jacobian = [[-0.0611, -0.0349], [0.0453, 0.0]]
speeds = [10, 20]
vx = jacobian[0][0] * speeds[0] + jacobian[0][1] * speeds[1]
vy = jacobian[1][0] * speeds[0] + jacobian[1][1] * speeds[1]
print("hand speed across:", round(vx, 3))
print("hand speed up:", round(vy, 3))
# Set both joint speeds to 0. What is the hand speed?
A stretched arm cannot move along itself
When the arm is fully straight, turning either joint moves the hand sideways only. No joint speed can move the hand along the arm. This is a singularity.
The determinant of the table, the top left times the bottom right minus the top right times the bottom left, is then 0. A controller watches it and slows down as it nears 0.
Going further
In start.ipynb, estimate the Jacobian at a1 = 0 and a2 = 0, then at a1 = 0 and a2 = 90. Print the determinant of each.
Which pose is a singularity, and what does the first row of its table show?