Background
Two independent reports (#406, #457) hit the same bug: IK.py's numerical solvers (ikine_LM and friends) unconditionally wrap the entire solved q vector to [-pi, pi] after convergence -- including prismatic joints, where the value is a translation distance, not an angle, and any revolute joint with a range wider than 180 degrees.
Confirmed still live (2026-08-25)
src/roboticstoolbox/robot/IK.py:317:
# Wrap q to be within +- 180 deg
# If your robot has larger than 180 deg range on a joint
# this line should be modified in incorporate the extra range
q = (q + np.pi) % (2 * np.pi) - np.pi
Applied unconditionally to every element of q, with no check for joint type. Reproduced #457's exact repro directly on current main: a 6-DOF robot with 3 prismatic + 3 revolute joints, q_in = [4, 0, 0, 0, pi/3, 0] comes back as q_out = [-2.28, 0, -0, 0, 1.05, -0] after the wrap -- 4 (a valid prismatic value, well within its qlim=[-10,10]) gets wrapped into [-pi,pi] as if it were an angle, and the resulting fkine(q_out) translation is wrong by the same amount.
#406's own report already identifies the fix location and confirms commenting out the wrap line resolves their case (though a real fix should be joint-type-aware, not just remove wrapping entirely -- revolute joints with a >180 deg physical range still need some handling, per the comment's own caveat).
Next steps
Make the wrap conditional on joint type -- only wrap elements corresponding to revolute joints (and ideally only those without an explicit wider qlim), leave prismatic joints untouched. ets/ets.structure (or equivalent per-joint type info) should already be available at this point in IK.py.
Originally reported: #406, #457.
Background
Two independent reports (#406, #457) hit the same bug:
IK.py's numerical solvers (ikine_LMand friends) unconditionally wrap the entire solvedqvector to[-pi, pi]after convergence -- including prismatic joints, where the value is a translation distance, not an angle, and any revolute joint with a range wider than 180 degrees.Confirmed still live (2026-08-25)
src/roboticstoolbox/robot/IK.py:317:Applied unconditionally to every element of
q, with no check for joint type. Reproduced #457's exact repro directly on currentmain: a 6-DOF robot with 3 prismatic + 3 revolute joints,q_in = [4, 0, 0, 0, pi/3, 0]comes back asq_out = [-2.28, 0, -0, 0, 1.05, -0]after the wrap --4(a valid prismatic value, well within itsqlim=[-10,10]) gets wrapped into[-pi,pi]as if it were an angle, and the resultingfkine(q_out)translation is wrong by the same amount.#406's own report already identifies the fix location and confirms commenting out the wrap line resolves their case (though a real fix should be joint-type-aware, not just remove wrapping entirely -- revolute joints with a >180 deg physical range still need some handling, per the comment's own caveat).
Next steps
Make the wrap conditional on joint type -- only wrap elements corresponding to revolute joints (and ideally only those without an explicit wider
qlim), leave prismatic joints untouched.ets/ets.structure(or equivalent per-joint type info) should already be available at this point inIK.py.Originally reported: #406, #457.