An AX=XB hand-eye solver only runs once your pose set is complete, so the failure lands on the sample that crosses the tool's minimum — and the culprit is almost never that last sample alone. The dual-quaternion method behind most AX=XB solvers needs robot motions that rotate about clearly different axes and through angles well above detection noise. When the motions between samples spin about near-parallel axes, or just a few degrees, the underlying system loses rank and the tool returns nothing, or worse, a quietly wrong calibration. Here you get the causes in order of probability, a test you can run on samples you already captured, a worked diagnosis of a failed four-pose set, and the re-plan numbers.
Why a complete pose set can still fail
Hand-eye calibration solves for one fixed transform X between the robot flange and the camera. Between two samples the flange moves by a rotation-and-translation A, and the calibration target moves by a rotation-and-translation B in the camera's view; every motion pair must satisfy AX = XB. The solver builds the rotation part from each motion's screw — its rotation axis and angle. Two facts decide success. If every motion rotates about the same axis, infinitely many X satisfy the equations and the system is rank-deficient: the classic parallel-axis degeneracy of AX=XB. And the axis direction is estimated from noisy target detections, so its error grows roughly as detection noise divided by the rotation angle. Near-parallel motions at small angles fail even though each sample, inspected alone, looks fine.
Causes in order of probability
- Degenerate motion geometry. Every motion rotates about nearly the same axis, rotations are only a few degrees, or two samples are near-duplicates with near-zero motion between them. This is the likely cause when the solver fails on the first complete set with an error such as "Solver failed to return a calibration".
- One bad target detection. A sample with the target half out of view, glare on a glossy board, or blur from a robot that had not settled corrupts one motion pair.
- Frames crossed. A target pose paired with the wrong flange pose, or base and tool frames swapped, breaks the pairing the solver needs — see the wrong robot frame fix if your samples mix tool-side and base-side frames.
- Convention mismatch. Quaternion order (x, y, z, w) versus (w, x, y, z), and millimetre versus metre inputs, turn valid data into garbage; the orientation-error fix covers the quaternion side.
- A mount that moved. If the camera or the target shifted between samples, no single X exists and no solver can converge.
Test each cause before you re-capture
The cheapest screen uses one identity: each flange motion and its camera-frame target motion must rotate through the same angle θ. Compute θ from each quaternion and compare pairs:
Pairs matching within about 1° clear the detection and the pairing for that motion; a pair off by several degrees flags causes 2 or 3. Then check geometry: extract each motion's axis as n = (x, y, z)/√(x² + y² + z²) and compute the angle between two axes as acos(n1 · n2). Axis angles near 0°, or motions with θ near 0°, are cause 1. If your tool prints 4×4 matrices instead of quaternions, the quaternion-to-transform conversion is a two-line rearrangement. Finally, open each sample's target-detection overlay: the target must be fully in view with cleanly drawn axes, and your tool's quaternion order and units must match its input documentation.
Worked example: three motions from a failed four-pose set
Inputs are illustrative quaternions in (x, y, z, w) order, the kind of values your pose pane lists, for the flange motions of an eye-to-hand capture with four poses: pose 1→2 gives (0, 0, 0.3007, 0.9537); pose 2→3 gives (0.0226, 0, 0.2578, 0.9659); pose 3→4 gives (0.0523, 0, 0, 0.9986). The rule: θ = 2 · atan2(vector norm, w), the axis is the normalized vector part, and the angle between two axes is acos of their dot product. Worked in degrees:
- Motion 1: norm = 0.3007, θ = 2 × atan2(0.3007, 0.9537) = 2 × 17.5° = 35.0°, axis (0, 0, 1).
- Motion 2: norm = √(0.0226² + 0.2578²) = √0.0670 = 0.2588, θ = 2 × atan2(0.2588, 0.9659) = 2 × 15.0° = 30.0°, axis (0.0873, 0, 0.9961).
- Motion 3: norm = 0.0523, θ = 2 × atan2(0.0523, 0.9986) = 2 × 3.0° = 6.0°, axis (1, 0, 0).
Axis separation between motions 1 and 2: dot product 0 × 0.0873 + 1 × 0.9961 = 0.9961, so acos(0.9961) ≈ 5°.
Result: motions 1 and 2 rotate through healthy 35° and 30° but about axes only 5° apart, so they supply one axis direction, not two. Motion 3 points 90° away but rotates only 6°; with 0.5° of detection noise its axis is tilted by about (0.5 ÷ 6) × 57.3 ≈ 5°, barely usable. The set holds fewer than two reliable axis directions — rank-deficient, hence the failure.
Decision: re-plan two motions. Keep motion 1. Replace motion 2 with a rotation about an axis at least 20° from tool Z, for example 30° about (0.64, 0, 0.77), which sits about 40° from Z. Grow motion 3 from 6° to at least 15°. After re-capture, confirm each new camera-frame motion shows the same angle as its flange motion, then run the solver: with three motions spanning axes 20° or more apart, it returns a solution.
Re-plan the pose set: the numbers that fix it
Plan the geometry before you jog the robot:
- 8-12 poses, giving 7-11 motions, so one weak detection cannot dominate the solution.
- Every motion rotates at least 15°; 20-60° is comfortable. Below about 10° the axis estimate degrades as noise ÷ angle: the same 0.5° detection noise that tilts a 30° motion's axis by about 1° tilts a 6° motion's by about 5°.
- Axes at least 20° apart, pairwise. Exactly parallel axes are unsolvable, and near-parallel pairs waste a motion.
- Translation in every motion. Two poses that differ only by spinning the target about its own axis are near-duplicates for the position part.
- Target fully in view at a steady distance in every pose; the target-size guide tells you how big the board must be for the poses you plan.
- Settled robot: wait out the settle time before each capture so the camera-frame pose is not caught mid-motion.
For a wrist camera, spread the poses across wrist tilts about two different tool axes; the companion piece on eye-in-hand pose selection lists robot positions that work. For a static camera, rotate the flange the same way and record the pairs with the sample-once capture workflow so no sample needs a second visit to the cell.
Keep the hardware from moving under the solve
While you are at the cell: the static camera must not move relative to the world between samples, and the target must not shift on its mount. On a bench rig, bolt the camera to a heavy stand rather than a light tripod, and lock the lens focus so it cannot drift mid-capture, as described in the focus-lock calibration guide. A stand with real mass and a wide base also survives the occasional bumped cable:
- Type
- Camera stands
Checklist before you run the solver again
- Geometry: every motion ≥ 15°; every pair of motion axes ≥ 20° apart; 8 or more poses; translation present in each motion. These keep the system full-rank and the noise averaged.
- Data: θ of the flange motion equals θ of its camera-frame partner within about 1° for every pair; no motion near 0°; quaternion order and units confirmed once against the tool's input documentation.
- Set-up: sensor configuration matches reality (wrist camera = eye-in-hand, static camera = eye-to-hand); every detection overlay inspected; camera and target mounts tight; focus locked.
- Bench rig: camera bolted to a rigid stand, not handheld — browse the camera stands or spec one in the stand configurator.
When re-planning will not help
If θ of the flange motion and θ of the camera-frame motion disagree by the same few degrees on every pair, the camera model itself is off: fix the intrinsics first and re-capture, because pose quality dominates the solve — the intrinsics and pose guide walks that order. If the camera is a factory-calibrated stereo or profiler unit from the 3D sensors family, re-solve by hand only after its vendor calibration checks out. And if every test above passes and the solver still refuses a set that meets the numbers, send the pose pairs to us through the contact page — the raw values usually expose the culprit in one read. More fixes for 3D set-up live on the 3D vision topic page.
Questions
How many poses does an AX=XB hand-eye calibration need?
Three motions are the mathematical minimum, which means four poses. Plan 8-12 poses instead: with 7-11 motions, detection noise averages out and one weak pair cannot dominate. The count matters less than the geometry — twelve poses about one axis still fail, while four poses with three well-separated 20-45° motions solve cleanly.
Why does the solver fail on the fifth sample rather than an earlier one?
The tool runs the solver only once the pose set is large enough to solve, so the first complete set triggers the first attempt. The failure belongs to the whole set, not to that sample. Adding a sixth and seventh pose in the same motion style cannot help; judge the axis directions and rotation angles of the motions you already captured.
Must the robot motion and the camera-frame motion rotate through the same angle?
Yes. Conjugating a rotation by the fixed hand-eye transform preserves its angle, so each flange motion and the target motion recorded in the camera frame must show the same θ, typically within about 1°. A bigger mismatch points at a bad detection, crossed frames, or a capture taken before the robot finished moving.
Can I hand-eye calibrate with translation-only motions?
No. With pure translations both rotations are the identity, the rotation equations vanish, and nothing constrains the rotation part of X. At least two motions with clearly different, non-parallel rotation axes are required; extra translation-heavy poses then improve the position result on top of that rotation base.
