explainer
Analytical inverse kinematics: find both arm configurations for a target
Derive both joint-angle solutions for a two-link robot arm, check them with forward kinematics, and identify unreachable targets and merged boundary branches.
What you will learn
- Derive the elbow and shoulder angles for a planar arm with two revolute joints.
- Count distinct geometric solutions inside, on, and outside the reachable annulus.
- Verify each analytical branch through forward kinematics.
- Explain normalized angles and the merging of boundary branches.
- Separate numerical roundoff handling from joint limits and physical feasibility.
Before you start
A robot arm with links of 2 m and 1 m can reach the point (2, 1) m in two distinct configurations. One uses shoulder and elbow angles of (0°, 90°). The other uses approximately (53.130102°, −90°). Both put the tip at the requested position, but they give the tool different headings.
Analytical inverse kinematics finds joint configurations through explicit equations. For this arm, a geometric derivation gives every position solution. We will calculate both branches, check their endpoints, and identify the targets for which neither branch exists.
Ask for a position in a specified frame
Use a planar arm with two revolute joints, often called a 2R arm. Its shoulder stays at the world origin. The world x-axis points right and y-axis points up. Positive rotations turn counterclockwise, with +z out of the page.
The first link has length L₁ = 2 m and the second has length L₂ = 1 m. Shoulder angle θ₁ is measured from +x. Elbow angle θ₂ is relative to the first link, so the second link's absolute heading is θ₁ + θ₂.
The forward position map is:
x = 2 cos θ₁ + cos(θ₁ + θ₂)
y = 2 sin θ₁ + sin(θ₁ + θ₂)
The factors 2 and 1 are lengths in meters. Trigonometric calculations use radians; the experiment also reports degrees for reading the configurations.
Forward kinematics takes angles and returns a position. Inverse kinematics takes a position and asks for angles. MathWorks develops this same two-link forward map and solves its two inverse branches.
Our request specifies position only. It does not prescribe an independent tool heading. A position solution therefore need not satisfy a grasp that also requires a particular orientation. For a learned robot policy, this distinction matters when a predicted target contains more task requirements than its IK calculation enforces.
Check the reachable annulus first
Let r = √(x² + y²) be the target's distance from the shoulder. The two links can span distances from their length difference to their length sum:
|L₁ − L₂| ≤ r ≤ L₁ + L₂
1 m ≤ r ≤ 3 m
The position workspace is a closed annulus, a disk with a central hole. Folding the 1 m link back along the 2 m link leaves the tip 1 m from the shoulder. Extending both links puts it 3 m away.
With unrestricted revolute joints and configurations identified modulo full turns, the exact geometric counts are:
| Target radius | Distinct position solutions |
|---|---|
| r < 1 m or r > 3 m | Zero |
| r = 1 m or r = 3 m | One merged branch |
| 1 m < r < 3 m | Two branches |
Modern Robotics derives these zero, one, and two solution cases for the planar arm. This count describes our unequal link lengths. An equal-length arm reaching its own shoulder would have a different degeneracy, so we do not extend this table to that model.
Joint stops or obstacles can remove otherwise geometric solutions. The robot workspace lesson develops those distinctions.
Derive the two elbow angles
A shoulder rotation preserves distance. Before that rotation, the tip has coordinates (2 + cos θ₂, sin θ₂), in meters. Squaring and adding eliminates θ₁:
r² = (2 + cos θ₂)² + sin² θ₂ = 5 + 4 cos θ₂
c₂ = cos θ₂ = (x² + y² − 5) / 4
Here the squared lengths use m², so c₂ is dimensionless. The general form is c₂ = (r² − L₁² − L₂²)/(2L₁L₂). It is the cosine-law relationship used in Carnegie Mellon's two-link derivation. That page measures its shoulder from a different zero axis; keep our stated angle convention when using the formulas below.
A real angle needs −1 ≤ c₂ ≤ 1. In the strict interior, the two possible sine values give two elbow branches:
s₂ = ±√(1 − c₂²)
θ₂ = atan2(s₂, c₂)
The positive sign gives the positive-elbow branch; the negative sign gives the negative-elbow branch. These names refer to the joint angle. Rotating the entire arm can move either elbow above or below the target, so a fixed screen location is a poor branch definition.
Recover the shoulder angle with atan2
The target vector is a shoulder rotation of the vector just used in the radius calculation:
[x; y] = R(θ₁)[2 + c₂; s₂]
θ₁ = atan2(y, x) − atan2(s₂, 2 + c₂)
Semicolons separate the entries of each column. The first atan2 gives the target bearing. The second gives the tip's bearing relative to link 1. Their difference supplies the shoulder angle.
Use atan2(y, x) with that argument order. It keeps the signs of both coordinates and distinguishes quadrants; the ratio y/x alone cannot do that. For our link lengths, 2 + c₂ is always positive on the reachable domain. The target also stays away from the origin because r ≥ 1 m, so these bearing calculations have valid nonzero vectors.
Calculate θ₁ once for each signed s₂. Reusing the first shoulder angle for both elbow signs generally produces an incorrect second endpoint.
Reach (2, 1) with two configurations
For (x, y) = (2, 1) m, the squared radius is 5 m². Therefore c₂ = 0 and s₂ = ±1, giving θ₂ = ±90°.
The target bearing is atan2(1, 2) ≈ 26.565051°. The relative bearing is either +26.565051° or −26.565051°:
| Branch | Shoulder θ₁ | Elbow θ₂ | Elbow position in meters | Tool heading |
|---|---|---|---|---|
| Positive elbow | 0° | 90° | (2, 0) | 90° |
| Negative elbow | 53.130102° | −90° | (1.2, 1.6) | −36.869898° |
For the first branch, the link displacements are (2, 0) m and (0, 1) m. They add to (2, 1) m.
For the second, the first link contributes (1.2, 1.6) m. The second contributes (0.8, −0.6) m, a vector of length 1 m. Again, the sum is (2, 1) m. This independent forward check confirms both configurations without relying on how they look in a plot.
Define the residual as target − forward position. Its Euclidean norm is zero for an exact solution; a floating-point calculation can leave a small numerical remainder. Different tool headings remain valid because the requested task only fixed position.
Track branches through boundaries and angle wrapping
At the outer boundary, c₂ = 1 and θ₂ = 0. The two signs of s₂ both give zero, so the branches coincide. Target (3, 0) m has the single configuration (0°, 0°).
At the inner boundary, c₂ = −1 and the elbow folds through half a turn. The angles +180° and −180° identify the same joint orientation. Target (1, 0) m therefore has one configuration, displayed as (0°, −180°).
We normalize each joint angle and tool heading to [−180°, 180°). A display can jump across that interval's seam while the physical configuration changes continuously. Target (−2, 1) m, for example, has a negative-elbow solution displayed as (−180°, −90°). An equivalent shoulder angle is +180°.
This identification assumes unrestricted revolute joints. A real joint's winding, cable routing, or mechanical stops can make equivalent geometric orientations different permitted states. Normalization is a representation choice, not a plan for moving between configurations.
Inside the annulus near a boundary, two branches still exist. At (2.99, 0) m they are approximately (−3.305665°, 9.928063°) and (3.305665°, −9.928063°). They meet only at the exact boundary. The position Jacobian has determinant L₁L₂ sin θ₂, which vanishes at the straight and folded configurations. This connects branch merging to the loss of a position-velocity direction.
Inspect both configurations and their forward checks
Start with Worked target and compare the two tool headings. Then select Reflected target. Both solutions reflect across the x-axis, and their elbow signs exchange under that reflection.
Compare Near outer boundary with Outer boundary to see two configurations become one. Inner boundary shows why opposite half-turn angle labels must count as the same orientation. Too close, Too far, and At the origin return no joint configurations.
Finally, choose Negative x target to inspect angle wrapping. Every displayed branch includes its forward position and residual, so the branch check remains available even when two arm drawings nearly overlap.
Handle roundoff without inventing a reachable target
The exact formula requires c₂ in [−1, 1]. Floating-point arithmetic can put a value intended to lie on a boundary slightly outside that interval. Taking its square root directly would fail.
The experiment uses an explicit dimensionless tolerance of 10⁻¹² on c₂:
- Compute the raw c₂ from the original target.
- Return no solution if c₂ is outside [−1, 1] by more than that tolerance.
- If it is outside by at most the tolerance, clamp to the nearest endpoint and report a roundoff adjustment.
- Keep every interior c₂ unchanged, then calculate the branches and check them against the original target.
For the sine magnitude, the calculation uses √((1 − c₂)(1 + c₂)), an equivalent factored expression that avoids subtracting a separately rounded square near either endpoint.
A clamped result is a numerical boundary convention. It does not prove that an exactly specified point outside the annulus is geometrically reachable. The residual retains the original target, so a small boundary adjustment can leave a nonzero check. Six-decimal readouts may round that remainder to zero.
The tolerance handles arithmetic; it does not represent camera uncertainty, link calibration, or collision clearance. It also never snaps an interior target to a boundary merely because two displayed angles look alike.
An analytical solution completes this unrestricted position calculation. Executing it still requires selecting a permitted branch and checking joint limits, collisions, and the path from the current configuration. The collision checking lesson uses a translating disk to show how clear endpoints can hide a collision between them. A numerical IK solver is useful when the mechanism or task does not admit a convenient explicit solution, but it needs its own convergence and feasibility checks.
Reproduce the calculation in Python
This standard-library example calculates the same branches, angle convention, and forward residuals for finite target coordinates. adjusted records an outward roundoff clamp. The formatting function suppresses negative zero in the printed values.
from math import atan2, cos, degrees, fmod, hypot, pi, sin, sqrt
def wrap(angle):
angle = fmod(angle, 2 * pi)
if angle >= pi:
angle -= 2 * pi
if angle < -pi:
angle += 2 * pi
return 0.0 if angle == 0 else angle
def solve(x, y):
raw_c = (x * x + y * y - 5) / 4
tolerance = 1e-12
if raw_c < -1 - tolerance or raw_c > 1 + tolerance:
return [], False
c = min(1.0, max(-1.0, raw_c))
s = sqrt(max(0.0, (1 - c) * (1 + c)))
solutions = []
for sign in ([1] if s == 0 else [1, -1]):
elbow = wrap(atan2(sign * s, c))
shoulder = wrap(atan2(y, x) - atan2(sign * s, 2 + c))
px = 2 * cos(shoulder) + cos(shoulder + elbow)
py = 2 * sin(shoulder) + sin(shoulder + elbow)
solutions.append((shoulder, elbow, hypot(x - px, y - py)))
return solutions, c != raw_c
def show(number):
return f"{0.0 if abs(number) < 0.0000005 else number:.6f}"
for target in [(2, 1), (3, 0), (1, 0), (0.5, 0)]:
solutions, adjusted = solve(*target)
print(f"target={target}, branches={len(solutions)}, adjusted={adjusted}")
for shoulder, elbow, error in solutions:
angles = f"({show(degrees(shoulder))}, {show(degrees(elbow))})"
print(f" angles_deg={angles}, residual_m={show(error)}")
Expected output:
target=(2, 1), branches=2, adjusted=False
angles_deg=(0.000000, 90.000000), residual_m=0.000000
angles_deg=(53.130102, -90.000000), residual_m=0.000000
target=(3, 0), branches=1, adjusted=False
angles_deg=(0.000000, 0.000000), residual_m=0.000000
target=(1, 0), branches=1, adjusted=False
angles_deg=(0.000000, -180.000000), residual_m=0.000000
target=(0.5, 0), branches=0, adjusted=False
The small nonzero floating-point remainders round to six decimal places. The branch equations themselves use their full calculated angles in each forward check.
Try it yourself
Exercise 1. Find both configurations for target (2, −1) m. Give the shoulder angle, elbow angle, and tool heading for each branch. Explain how reflection relates these solutions to the worked example.
Show the reflected-target solution
The radius and c₂ stay unchanged, so θ₂ is still ±90°. The target bearing is now −26.565051°.
For the positive-elbow branch, θ₁ = −26.565051° − 26.565051° = −53.130102°. Its tool heading is 36.869898°.
For the negative-elbow branch, θ₁ = −26.565051° − (−26.565051°) = 0°. Its tool heading is −90°.
Reflecting a configuration across x negates both joint angles. The original positive-elbow solution becomes the reflected negative-elbow solution, and the original negative-elbow solution becomes the reflected positive-elbow solution. Both forward positions are (2, −1) m.
Exercise 2. How many configurations reach (−1, 0) m? Give the normalized joint angles and verify the tip position. Then decide whether (−0.5, 0) m has any solution under the same model.
Show the inner-boundary and central-hole solution
At (−1, 0) m, r = 1 m and c₂ = −1. The elbow is folded, and the two branches merge. Normalizing the shoulder and elbow gives (−180°, −180°).
The first link contributes (−2, 0) m. The second link's angle is −360°, equivalent to 0°, so it contributes (1, 0) m. Their sum is (−1, 0) m, and the normalized tool heading is 0°.
The target (−0.5, 0) m lies inside the 1 m hole. Its raw c₂ is −1.1875, outside the real cosine domain by much more than the roundoff tolerance. It has no geometric solution.
Sources and further study
- Modern Robotics: Inverse Kinematics of Open Chains develops the planar-arm geometric solution and its zero, one, and two solution cases.
- Carnegie Mellon: Two Link Kinematics derives the cosine-law geometry. Its shoulder zero-axis convention differs from this lesson's +x convention.
- MathWorks: Derive and Apply Inverse Kinematics to Two-Link Robot Arm shows the planar forward equations, symbolic inverse branches, and a forward/inverse calculation workflow.
Continue with robot workspaces to examine what changes when a reachability question includes joint bounds or a required tool orientation.