30 min

Singularities: where the arm loses a direction

Poses where the Jacobian's columns line up, one direction of hand motion disappears, and any solver that keeps asking for it commands joint speeds no motor can deliver.

Where you are. You can build the Jacobian and read its columns as “what each joint buys the hand right now”. This lesson is about the poses where two columns quietly become one, and a whole direction of motion goes missing.

The last two degrees

Stand up and hold a pen out in front of you at arm’s length, elbow almost locked. A couple of degrees of bend left in it, no more.

Sweep the pen sideways, twenty centimetres each way, at a comfortable pace. Easy. Your shoulder does the work and the pen goes exactly where you send it.

Now try the same twenty centimetres straight away from you and back, at the same pace. Two things go wrong at once. You have almost no room left; and the room you do have is strangely expensive. Those last couple of degrees of straightening buy you almost no reach at all, so to move outward at any speed your elbow has to move far faster than your shoulder ever did on the sideways sweep. Then you hit straight, and outward stops existing.

Nothing about your arm changed between the two attempts. Same joints, same muscles, same request for a steady comfortable pace. Sideways was free the whole time. Outward had a price that climbed as you approached straight, and at straight it went to infinity, because at straight there is no more outward.

A robot arm has the same problem in the same place. What it does not have is your instinct to stop asking.

The idea in one paragraph

At most poses the Jacobian’s two columns point in genuinely different directions, so between them the joints can push the hand any way you like. At some poses they line up. When they do, every combination of joint speeds sends the hand along one single line, and a whole direction of motion has dropped out of the arm’s vocabulary. That pose is a singularity, and for the two-link arm one number detects it: detJ=l1l2sinθ2\det J = l_1 l_2 \sin\theta_2, which hits zero exactly when the elbow is straight (θ2=0\theta_2 = 0) or folded back on itself (θ2=180\theta_2 = 180^{\circ}). At the singularity the missing direction is simply gone, and there is nothing to argue about. The neighbourhood is where the damage happens, because there the direction is technically still available, at an exchange rate that climbs without limit, and a solver that keeps asking for it will keep being told yes.

The columns close like scissors

Put the arm at θ1=0\theta_1 = 0 so it stretches out along the x axis, and start straightening the elbow.

From the previous lesson, both columns are perpendicular to something specific: column one to the base-to-hand line, column two to link two. As the elbow straightens, those two segments swing into line with each other. Two segments in line have parallel perpendiculars. So the columns line up too, and they do it at exactly the rate the elbow closes.

both columns drawn from the hand, all three panels to the same scale · θ1 = 0 throughout column 1 column 2 back toward the base θ2 = 60° det J = 0.61 · 35.8° apart θ2 = 20° det J = 0.24 · 11.8° apart θ2 = 5° det J = 0.061 · 2.9° apart the shaded area is |det J|: the hand motion two joints of motion buys
Three panels showing the two Jacobian columns as the elbow straightens: at 60 degrees they are 35.8 degrees apart and span a wide area, at 20 degrees 11.8 degrees, and at 5 degrees only 2.9 degrees, leaving a sliver

Wider than the screen; scroll it sideways.

The shaded area in that figure is not decoration. The determinant of a 2 by 2 matrix is the area of the parallelogram its columns span, so detJ\det J is a direct measure of how much hand motion two units of joint motion can buy between them. Wide parallelogram, capable arm. Sliver, arm in trouble. Zero, arm has lost a direction.

One number, and it only watches one joint

Work the determinant out of the formula from the previous lesson and almost everything cancels:

detJ=l1l2sinθ2\det J = l_1 \cdot l_2 \cdot \sin\theta_2

Checked against numpy.linalg.det over 10,000 random configurations, the largest disagreement was 4.2e-16, which is floating point noise.

Read the formula and two things jump out. It is zero exactly when sinθ2\sin\theta_2 is zero, so at θ2=0\theta_2 = 0 and θ2=180\theta_2 = 180^{\circ} and nowhere else. And θ1\theta_1 does not appear at all: sweeping the shoulder through its whole range at a fixed elbow angle changes detJ\det J by less than 1e-15, which is to say not at all. The shoulder only spins the picture. Every singularity of this arm is decided by the elbow alone.

Which direction goes missing

Straighten the elbow completely, θ=(0,0)\theta = (0^{\circ}, 0^{\circ}), and print the matrix:

J=[0.00.01.70.7]J = \begin{bmatrix} 0.0 & 0.0 \\ 1.7 & 0.7 \end{bmatrix}

Every entry in the top row is zero, so every hand velocity this arm can produce has zero x component. With the arm laid out along x, that means the hand can still be swung sideways by either joint, at different rates, but nothing either joint can do moves the hand along the arm’s own axis. Two joints, one usable direction of motion. The singular values are 1.8385 and exactly 0, and the rank is 1.

θ2 = 0 · the arm is fully straight · det J = l1·l2·sin θ2 = 0 joint 1 joint 2 no bend left: θ2 = 0 hand l1 l2 lost direction no joint velocity moves the hand along its own axis still free perpendicular to the arm: both columns of J point here 2 joints, but only 1 direction of motion: a whole degree of freedom is gone
A two-link arm stretched fully straight: the hand can still move perpendicular to the arm, but no joint velocity moves it along the arm's own axis

Wider than the screen; scroll it sideways.

That is what “loses a direction” means literally. It is not that the direction becomes hard. It is that the set of achievable hand velocities, which is normally the whole plane, has collapsed to a line.

The neighbourhood is the dangerous part

At the singularity you get a clean refusal. Just before it, you get something worse: a yes, with a bill attached.

Walk the elbow in toward straight and ask, at each pose, for two things. Move the hand outward along the arm at 0.1 m/s, and move it sideways across the arm at 0.1 m/s. Both are perfectly ordinary requests. Here is what each costs in joint speed:

θ2\theta_2hand is this far inside the rimcolumns apartdetJ\det Joutward at 0.1 m/ssideways at 0.1 m/s
90°479 mm55.0°0.7000.14 rad/s0.100 rad/s
30°56.1 mm17.7°0.3500.46 rad/s0.100 rad/s
10°6.27 mm5.9°0.1221.39 rad/s0.100 rad/s
1.57 mm2.9°0.0612.78 rad/s0.100 rad/s
0.25 mm1.2°0.0246.96 rad/s0.100 rad/s
0.063 mm0.6°0.01213.91 rad/s0.100 rad/s
0.1°0.001 mm0.06°0.0012139.15 rad/s0.100 rad/s

Two readings, and the second is the one people miss.

The outward column doubles every time θ2\theta_2 halves, and keeps on doubling. That is the exchange rate collapsing, and the mechanism is visible in the arithmetic: solving Jθ˙=vJ\,\dot{\theta} = \mathbf{v} divides by detJ\det J, so as the determinant shrinks the answer grows, without any ceiling to stop at. Coming at the same fact from the other side, at θ2=90\theta_2 = 90^{\circ} one degree of elbow buys 9.97 mm of extra reach; at θ2=1\theta_2 = 1^{\circ} a whole degree of elbow buys 0.063 mm.

The sideways column does not move. Not approximately - 0.100 rad/s in every single row, to three decimals. The largest singular value barely shifts either, from 1.30 to 1.84 across the whole approach. The arm is not getting worse. It is getting worse at exactly one thing, and it stays completely healthy at everything else right up to the moment the one thing disappears.

Both rims, same story

The other zero of sinθ2\sin\theta_2 is θ2=180\theta_2 = 180^{\circ}: the elbow folded right back, link two lying along link one, hand pulled in to l1l2=0.3|l_1 - l_2| = 0.3 from the base. Print the matrix there, again with θ1=0\theta_1 = 0, and it is [000.30.7]\begin{bmatrix} 0 & 0 \\ 0.3 & -0.7 \end{bmatrix} - rank 1 again, singular values 0.7616 and 0, determinant 8.6e-17. The lost direction is once again along the arm.

Those two elbow angles are exactly the two rims of the reachable ring from the workspace lesson. That is not a coincidence, and it generalises in one direction only: the boundary of a workspace is always singular, because being on a boundary means there is a direction you cannot go. The converse is false. A six-axis industrial arm has singularities sitting in the open middle of its workspace - the notorious one is the wrist singularity, where two wrist axes line up and the arm loses a rotational direction while standing somewhere entirely reachable.

Why inverse kinematics blows up nearby

Everything so far has been forward: joints in, hand out. Inverse kinematics needs the other direction, which means solving Jθ˙=vJ\,\dot{\theta} = \mathbf{v} for θ˙\dot{\theta}. For a 2 by 2 the inverse carries 1/detJ1 / \det J out front, so as the determinant heads for zero the entries of the inverse head for infinity. The table above is that fraction, in engineering units.

At exactly θ2=0\theta_2 = 0, numpy.linalg.solve raises LinAlgError: Singular matrix. That is the friendly failure: loud, immediate, and at the one pose you will almost never land on exactly.

What the damping term buys

The standard fix is one line. Instead of inverting JJ, solve a slightly softened system:

Δθ=J(JJ+λ2I)1e\Delta\theta = J^{\top}\left(J J^{\top} + \lambda^2 I\right)^{-1}\mathbf{e}

In plain words: add a small constant to the quantity you are about to divide by, so a nearly-zero direction produces a bounded step instead of an unbounded one. With λ=0\lambda = 0 this is the raw pseudo-inverse. With λ\lambda around 0.01 the solver gives up a little accuracy in the strong directions in exchange for never demanding an impossible one.

Here is what that costs and what it saves. Same solver, same start at θ=(0.3,0.5)\theta = (0.3, 0.5), step scale 0.5, 100 iterations, aimed at a target 50 mm past the outer rim - a target no arm with these links can reach:

λ=0\lambda = 0λ=0.01\lambda = 0.01
largest single step22.42 rad2.50 rad
where the joints endedθ1=457\theta_1 = -457^{\circ}, θ2=+1315\theta_2 = +1315^{\circ}θ1=6\theta_1 = -6^{\circ}, θ2=+15\theta_2 = +15^{\circ}
where the hand endedr=0.831r = 0.831, behind the baser=1.685r = 1.685, stretched at the rim
distance to the target2.449 m0.065 m

start θ = (0.3, 0.5) · step 0.5 · 100 iterations · target 50 mm out of reach the outer rim · det J = 0 arm straight, r = 1.70 base target 50 mm past the rim λ = 0.01 · damped largest step 2.50 rad · parks 0.065 m short λ = 0 · undamped largest step 22.42 rad ends behind the base, 2.45 m off an unreachable target has no answer · the useful behaviour is to stretch toward it and stop, and that is what the damping term buys
The same solver aimed at a target 50 millimetres past the rim: damped it parks on the rim pointing at the target, undamped it winds the joints through several turns and ends up behind the base

Wider than the screen; scroll it sideways.

The undamped run did not merely move violently. It finished pointing away from the target, on the far side of the base, 2.449 m from a goal that was 50 mm out of reach when it started. The damped run stretched toward the target and stopped, 0.065 m short of something nothing could get closer than 0.050 to. One solver degraded; the other detonated.

What you actually do about it

Four moves, roughly in order of how much they cost you.

Keep the task off the rim. Free, and it solves most of the problem. Plan the working area a comfortable margin inside the boundary, and do not design a task whose motion runs radially out to the edge.

Damp. One line, as above. The largest step the solver can ever ask for becomes 1/(2λ)1/(2\lambda) times the error, so pick λ\lambda from the joint step you are prepared to command rather than by feel. The next lesson builds the whole solver around it.

Watch a number at runtime. detJ\det J works for square Jacobians; the smallest singular value works generally; the condition number, the ratio of largest to smallest, is the most readable of the three because it is dimensionless. In the table above it runs 2.4 at θ2=90\theta_2 = 90^{\circ}, 27.6 at 10°, 277 at 1°, and 2767 at a tenth of a degree. A threshold on that ratio is a usable guard: refuse the command, or slow the commanded motion, before the motors do the refusing for you.

Add a joint. A seven-axis arm reaching in three dimensions has one more joint than the task needs, which leaves a whole family of joint motions that move the hand nowhere at all. That family is room to reconfigure the elbow away from a bad pose without disturbing the hand, and it is the reason research arms have seven joints rather than six.

Review

A direction drops out of the arm’s vocabulary

At most poses the Jacobian’s two columns point in genuinely different directions, so between them the joints can push the hand any way you like. At some poses they line up, and then every combination of joint speeds sends the hand along one single line: a whole direction of motion has dropped out of the arm’s vocabulary. That pose is a singularity. For the two-link arm one number detects it, the determinant of the Jacobian, which is the product of the link lengths and the sine of the elbow angle, and it hits zero exactly when the elbow is straight or folded back on itself. The determinant of a two by two matrix is the area of the parallelogram its columns span, so it measures directly how much hand motion two units of joint motion can buy. Wide parallelogram, capable arm. Sliver, arm in trouble.

The neighbourhood is where the damage happens

At the singularity you get a clean refusal. Just before it you get something worse: a yes, with a bill attached. Walk the elbow in toward straight and ask for a tenth of a metre per second outward along the arm. At ninety degrees of elbow that costs fourteen hundredths of a radian per second. At five degrees it costs two point seven eight. At a tenth of a degree it costs one hundred and thirty-nine. The cost doubles every time the elbow angle halves, and keeps doubling, because solving for joint speed divides by the determinant. Now the reading people miss: sideways motion costs exactly one tenth of a radian per second in every single row. The arm is not getting worse. It is getting worse at exactly one thing, and it stays completely healthy at everything else right up to the moment that one thing disappears.

It is invisible from outside, and there are four answers

None of this is visible from outside. Five degrees from straight, the hand sits one and a half millimetres short of the rim and the arm simply looks straight; it tracks sideways motion perfectly while tracking outward motion at nearly twenty times the joint speed the same request cost with the elbow bent. Put a real limit on the motors and the impossibility does not arrive as an exception. It arrives as saturated motors, a growing tracking error, and a log full of nothing. Four answers, in order of what they cost. Keep the task off the rim, which is free and solves most of it. Damp, choosing the damping factor from the largest joint step you are prepared to command. Watch a number at runtime; the condition number is the most readable because it is dimensionless, running from about two at a bent elbow to nearly three thousand near straight. Or add a joint, which is why research arms have seven.

Check yourself

1. Why is being near a singularity operationally worse than being exactly at one?

At the singularity the direction is gone and everything says so: the determinant is zero, the rank drops, numpy.linalg.solve throws. A solver has to handle it. Near the singularity the direction is still technically available, so nothing complains - the arithmetic simply returns an enormous joint velocity and the code passes it along. That is the regime in which real hardware gets whipped, and it is why damping exists for the neighbourhood rather than for the point.

2. detJ=l1l2sinθ2\det J = l_1 l_2 \sin\theta_2 does not contain θ1\theta_1. What does that tell you about where this arm’s singularities live?

That they depend only on the elbow. Sweeping the shoulder through its full range at a fixed elbow angle leaves the determinant unchanged to 1.7e-16, so θ1\theta_1 only rotates the whole picture about the base. The singular configurations are θ2=0\theta_2 = 0 and θ2=180\theta_2 = 180^{\circ}, and in workspace terms those are two circles: the outer rim at l1+l2l_1 + l_2 and the inner rim at l1l2|l_1 - l_2|. Everything between them is non-singular, and the shoulder angle never has an opinion on it.

3. At θ2 = 5° the arm tracks sideways motion perfectly and outward motion twenty times more expensively than before. Why does only one direction degrade?

Because only one direction is losing its supply. The set of hand velocities the joints can produce is an ellipse, and approaching the singularity squashes it along one axis while leaving the other alone: the smallest singular value falls from 0.538 to 0.033 while the largest moves only from 1.30 to 1.84. The squashed axis is the arm’s own axis. So the sideways request keeps costing 0.100 rad/s at every pose in the table, and the outward request goes from 0.14 to 2.78 rad/s over the same span.

4. An IK solver returns a joint configuration with no error, but the hand does not move outward when you command it to. Where would you look?

At detJ\det J, or better the condition number, at the pose you are in. A pseudo-inverse asked for a lost direction returns the minimum-norm best effort, which at a singularity is zero motion, and it reports success while doing it. So “no error and no motion” is the exact signature of a collapsed axis. Confirm by asking for the perpendicular direction: if that works and the radial one does not, you are on a rim. The fix is not in the solver, it is in the plan that put the hand there.

5. What does the λ² term actually change, and what does it cost?

It changes the amplification applied to each direction. Undamped, a direction whose singular value is σ\sigma gets amplified by 1/σ1/\sigma, which runs away as σ\sigma falls. Damped, it gets σ/(σ2+λ2)\sigma / (\sigma^2 + \lambda^2), which rises, peaks at 1/(2λ)1/(2\lambda) when σ\sigma equals λ\lambda, and then falls back toward zero. Measured at λ=0.01\lambda = 0.01: a strong direction with σ=1.84\sigma = 1.84 is amplified 0.544 either way, indistinguishable. A weak one with σ=0.00066\sigma = 0.00066 would be amplified 1505 times undamped, and is amplified 6.6 times damped.

So the cost is not spread across the arm; it lands entirely on the directions that were about to hurt you, and it is paid as motion you do not get. λ\lambda is chosen from the largest joint step you are willing to command, because 1/(2λ)1/(2\lambda) is exactly that cap.

6. Your task needs the hand to travel radially outward to within 1 mm of the workspace rim. Argue against the task, with numbers.

The last millimetre of reach lives inside about θ2=4\theta_2 = 4^{\circ}, where the exchange rate is roughly 3.5 rad/s of joint speed per 0.1 m/s of outward hand motion, climbing to 13.9 rad/s at θ2=1\theta_2 = 1^{\circ} and without limit after that. With joints capped at one revolution per second the outer 0.31 mm becomes unreachable at that speed regardless of the controller. And an arm that reaches its target only when fully straight has no margin left: any calibration error, any link flex, any thermal drift pushes the target outside the workspace entirely, at which point the solver stalls on the boundary with residual error. Longer links, or a repositioned base, cost far less than fighting this.

Do this

Open code/ik_2link.py with jacobian_analytic already filled in from the previous lesson.

1. Walk the determinant to zero. Print detJ\det J at θ2=90,30,10,5,1,0.1,0\theta_2 = 90^{\circ}, 30^{\circ}, 10^{\circ}, 5^{\circ}, 1^{\circ}, 0.1^{\circ}, 0^{\circ} and confirm it matches l1l2sinθ2l_1 l_2 \sin\theta_2 each time. Then print it again at four different values of θ1\theta_1 for each of those elbow angles, and watch it not move.

2. Price the two directions. At each of those poses solve Jθ˙=vJ\,\dot{\theta} = \mathbf{v} twice, once for v=(0.1,0)\mathbf{v} = (0.1, 0) and once for v=(0,0.1)\mathbf{v} = (0, 0.1), with θ1=0\theta_1 = 0 so the arm lies along x. Print the largest joint speed each requires. You are reproducing the table above; the point is to feel that one column runs away while the other never budges. At θ2=0\theta_2 = 0 exactly, np.linalg.solve will throw - catch it and print what np.linalg.pinv returns instead.

3. Measure the amplification directly. Take the Jacobian at θ2=0.1\theta_2 = 0.1^{\circ}, run its SVD, and feed each left-singular direction through the damped step J(JJ+λ2I)1eJ^{\top}\left(J J^{\top} + \lambda^2 I\right)^{-1}\mathbf{e} at λ=0.01\lambda = 0.01. Compare the length of what comes back against 1/σ1/\sigma and against σ/(σ2+λ2)\sigma / (\sigma^2 + \lambda^2). The strong direction should come back at 0.544 both ways; the weak one at 6.6 damped against 1505 undamped. Seeing those four numbers next to each other is the fastest way to internalise what damping actually touches.

Then note what you have not done: nothing here made an unreachable target reachable, and nothing warned you when one arrived. That job belongs to a reachability check, and building the solver that needs it is the next lesson.

Solution: solutions/ik_2link.py.

What you can now do

You can compute detJ\det J for a 2-link arm, say which physical direction of motion disappears when it hits zero and why, and locate both singular configurations from the elbow angle alone. You can describe the neighbourhood around a singularity in the terms that matter - one direction degrading without limit while everything else stays healthy - and put numbers on it. You can explain what a damping term changes in a least-squares IK step, what it costs, and what it does not fix.

What you can now do

You can compute det J for a pose, say which direction of motion is being lost and why, recognise the dangerous neighbourhood around a singularity, and explain what a damping term buys you.