FA-88091 / Inverse kinematics solvers / Open access
Delta towers are placed at 0, 120 and 240 degrees · case 01
Carriage heights belong to a rotated tower layout, so moves in y tilt the effector.
ROOT CAUSE
The tower table starts at the x axis instead of at 90 degrees.
VERIFIED REPAIR
Place towers at 90, 210 and 330 degrees in that order.
Unsuccessful approach: Listing the 330 degree tower second keeps positions right but swaps two carriage outputs.
Case contract
Input [R,e,L,x,y,z,hmax]: linear delta printer, towers at 90, 210 and 330 degrees (in that output order) on radius R, effector joints offset e toward the centre so the effective radius is R-e, diagonal rods of length L. Carriage height is z+sqrt(L^2-dx^2-dy^2); a negative radicand returns "unreachable", a carriage above hmax returns "out-of-travel". Return heights rounded to 4.
Why this case matters
Inverse kinematics code turns task-space goals into joint commands; a wrong branch, sign, limit or update order sends a real arm to the wrong pose.
1 / The failure
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
import math
N = 1
observations = []
def solve(x):
R,e,L,px,py,pz,hmax=x
r=R-e
S=math.sqrt(3.0)/2.0
hs=[]
for tx,ty in [(r,0.0),(-r/2,r*S),(-r/2,-r*S)]:
q=L*L-(px-tx)**2-(py-ty)**2
if q<0: return 'unreachable'
h=pz+math.sqrt(q)
if h>hmax: return 'out-of-travel'
hs.append(round(h,4))
return hs
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['centre', [[10, 2, 12, 0, 0, 5, 40]], [13.9443, 13.9443, 13.9443]], ['off centre', [[10, 2, 12, 2, -3, 5, 40]], [9.3589, 12.9553, 15.8955]], ['rod horizontal at tower one', [[10, 2, 10, 0, -2, 0, 40]], [0.0, 6.9282, 6.9282]], ['beyond rod reach', [[10, 2, 10, 0, -3, 0, 40]], 'unreachable'], ['carriage exactly at top', [[12, 0, 13, 0, 0, 2, 7]], [7.0, 7.0, 7.0]], ['carriage over top', [[12, 0, 13, 0, 0, 2.5, 7]], 'out-of-travel'], ['toward tower two', [[10, 1, 15, -4, -2, 3, 40]], [12.3808, 17.2952, 11.9245]]], [['rod horizontal at tower one', [[10, 2, 10, 0, -2, 0, 40]], [0.0, 6.9282, 6.9282]], ['carriage exactly at top', [[12, 0, 13, 0, 0, 2, 7]], [7.0, 7.0, 7.0]], ['carriage over top', [[12, 0, 13, 0, 0, 2.5, 7]], 'out-of-travel'], ['toward tower two', [[10, 1, 15, -4, -2, 3, 40]], [12.3808, 17.2952, 11.9245]], ['toward tower three', [[10, 1, 15, 4, -2, 3, 40]], [12.3808, 11.9245, 17.2952]], ['high z low travel', [[10, 2, 12, 0, 0, 25, 30]], 'out-of-travel'], ['no effector offset', [[8, 0, 12, 1, 1, 2, 40]], [11.6954, 9.4929, 11.1573]]], [['toward tower two', [[10, 1, 15, -4, -2, 3, 40]], [12.3808, 17.2952, 11.9245]], ['toward tower three', [[10, 1, 15, 4, -2, 3, 40]], [12.3808, 11.9245, 17.2952]], ['high z low travel', [[10, 2, 12, 0, 0, 25, 30]], 'out-of-travel'], ['no effector offset', [[8, 0, 12, 1, 1, 2, 40]], [11.6954, 9.4929, 11.1573]], ['large offset', [[12, 5, 11, -1, 2, 4, 40]], [13.7468, 12.07, 10.3934]], ['asymmetric point', [[10, 2, 12, 3, 4, 1, 40]], 'unreachable'], ['negative z', [[10, 2, 12, -2, 1, -3, 40]], [6.5394, 6.7321, 3.2679]]], [['centre', [[10, 2, 12, 0, 0, 5, 40]], [13.9443, 13.9443, 13.9443]], ['off centre', [[10, 2, 12, 2, -3, 5, 40]], [9.3589, 12.9553, 15.8955]], ['rod horizontal at tower one', [[10, 2, 10, 0, -2, 0, 40]], [0.0, 6.9282, 6.9282]], ['toward tower three', [[10, 1, 15, 4, -2, 3, 40]], [12.3808, 11.9245, 17.2952]], ['no effector offset', [[8, 0, 12, 1, 1, 2, 40]], [11.6954, 9.4929, 11.1573]], ['asymmetric point', [[10, 2, 12, 3, 4, 1, 40]], 'unreachable'], ['negative z', [[10, 2, 12, -2, 1, -3, 40]], [6.5394, 6.7321, 3.2679]]], [['off centre', [[10, 2, 12, 2, -3, 5, 40]], [9.3589, 12.9553, 15.8955]], ['rod horizontal at tower one', [[10, 2, 10, 0, -2, 0, 40]], [0.0, 6.9282, 6.9282]], ['beyond rod reach', [[10, 2, 10, 0, -3, 0, 40]], 'unreachable'], ['carriage exactly at top', [[12, 0, 13, 0, 0, 2, 7]], [7.0, 7.0, 7.0]], ['carriage over top', [[12, 0, 13, 0, 0, 2.5, 7]], 'out-of-travel'], ['no effector offset', [[8, 0, 12, 1, 1, 2, 40]], [11.6954, 9.4929, 11.1573]], ['large offset', [[12, 5, 11, -1, 2, 4, 40]], [13.7468, 12.07, 10.3934]]]]
for label, args, expected in fixtures[N-1]:
check(label, solve(*args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
| Boundary fixture | Actual | Expected | Outcome |
|---|---|---|---|
| centre | [13.9443, 13.9443, 13.9443] | [13.9443, 13.9443, 13.9443] | Passed |
| off centre | [14.9499, 8.071, 14.6213] | [9.3589, 12.9553, 15.8955] | Failed |
| rod horizontal at tower one | [5.6569, 2.0706, 7.7274] | [0.0, 6.9282, 6.9282] | Failed |
| beyond rod reach | unreachable | unreachable | Passed |
| carriage exactly at top | [7.0, 7.0, 7.0] | [7.0, 7.0, 7.0] | Passed |
| carriage over top | out-of-travel | out-of-travel | Passed |
| toward tower two | [10.2111, 14.35, 16.8267] | [12.3808, 17.2952, 11.9245] | Failed |
SHA-256 / 12ff18f225d08242c09ac6e0d06e4d5ba293ccb5f3cade864dc12bf8884d279f
2 / The unsuccessful fix
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
import math
N = 1
observations = []
def solve(x):
R,e,L,px,py,pz,hmax=x
r=R-e
S=math.sqrt(3.0)/2.0
hs=[]
for tx,ty in [(0.0,r),(r*S,-r/2),(-r*S,-r/2)]:
q=L*L-(px-tx)**2-(py-ty)**2
if q<0: return 'unreachable'
h=pz+math.sqrt(q)
if h>hmax: return 'out-of-travel'
hs.append(round(h,4))
return hs
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['centre', [[10, 2, 12, 0, 0, 5, 40]], [13.9443, 13.9443, 13.9443]], ['off centre', [[10, 2, 12, 2, -3, 5, 40]], [9.3589, 12.9553, 15.8955]], ['rod horizontal at tower one', [[10, 2, 10, 0, -2, 0, 40]], [0.0, 6.9282, 6.9282]], ['beyond rod reach', [[10, 2, 10, 0, -3, 0, 40]], 'unreachable'], ['carriage exactly at top', [[12, 0, 13, 0, 0, 2, 7]], [7.0, 7.0, 7.0]], ['carriage over top', [[12, 0, 13, 0, 0, 2.5, 7]], 'out-of-travel'], ['toward tower two', [[10, 1, 15, -4, -2, 3, 40]], [12.3808, 17.2952, 11.9245]]], [['rod horizontal at tower one', [[10, 2, 10, 0, -2, 0, 40]], [0.0, 6.9282, 6.9282]], ['carriage exactly at top', [[12, 0, 13, 0, 0, 2, 7]], [7.0, 7.0, 7.0]], ['carriage over top', [[12, 0, 13, 0, 0, 2.5, 7]], 'out-of-travel'], ['toward tower two', [[10, 1, 15, -4, -2, 3, 40]], [12.3808, 17.2952, 11.9245]], ['toward tower three', [[10, 1, 15, 4, -2, 3, 40]], [12.3808, 11.9245, 17.2952]], ['high z low travel', [[10, 2, 12, 0, 0, 25, 30]], 'out-of-travel'], ['no effector offset', [[8, 0, 12, 1, 1, 2, 40]], [11.6954, 9.4929, 11.1573]]], [['toward tower two', [[10, 1, 15, -4, -2, 3, 40]], [12.3808, 17.2952, 11.9245]], ['toward tower three', [[10, 1, 15, 4, -2, 3, 40]], [12.3808, 11.9245, 17.2952]], ['high z low travel', [[10, 2, 12, 0, 0, 25, 30]], 'out-of-travel'], ['no effector offset', [[8, 0, 12, 1, 1, 2, 40]], [11.6954, 9.4929, 11.1573]], ['large offset', [[12, 5, 11, -1, 2, 4, 40]], [13.7468, 12.07, 10.3934]], ['asymmetric point', [[10, 2, 12, 3, 4, 1, 40]], 'unreachable'], ['negative z', [[10, 2, 12, -2, 1, -3, 40]], [6.5394, 6.7321, 3.2679]]], [['centre', [[10, 2, 12, 0, 0, 5, 40]], [13.9443, 13.9443, 13.9443]], ['off centre', [[10, 2, 12, 2, -3, 5, 40]], [9.3589, 12.9553, 15.8955]], ['rod horizontal at tower one', [[10, 2, 10, 0, -2, 0, 40]], [0.0, 6.9282, 6.9282]], ['toward tower three', [[10, 1, 15, 4, -2, 3, 40]], [12.3808, 11.9245, 17.2952]], ['no effector offset', [[8, 0, 12, 1, 1, 2, 40]], [11.6954, 9.4929, 11.1573]], ['asymmetric point', [[10, 2, 12, 3, 4, 1, 40]], 'unreachable'], ['negative z', [[10, 2, 12, -2, 1, -3, 40]], [6.5394, 6.7321, 3.2679]]], [['off centre', [[10, 2, 12, 2, -3, 5, 40]], [9.3589, 12.9553, 15.8955]], ['rod horizontal at tower one', [[10, 2, 10, 0, -2, 0, 40]], [0.0, 6.9282, 6.9282]], ['beyond rod reach', [[10, 2, 10, 0, -3, 0, 40]], 'unreachable'], ['carriage exactly at top', [[12, 0, 13, 0, 0, 2, 7]], [7.0, 7.0, 7.0]], ['carriage over top', [[12, 0, 13, 0, 0, 2.5, 7]], 'out-of-travel'], ['no effector offset', [[8, 0, 12, 1, 1, 2, 40]], [11.6954, 9.4929, 11.1573]], ['large offset', [[12, 5, 11, -1, 2, 4, 40]], [13.7468, 12.07, 10.3934]]]]
for label, args, expected in fixtures[N-1]:
check(label, solve(*args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
| Boundary fixture | Actual | Expected | Outcome |
|---|---|---|---|
| centre | [13.9443, 13.9443, 13.9443] | [13.9443, 13.9443, 13.9443] | Passed |
| off centre | [9.3589, 15.8955, 12.9553] | [9.3589, 12.9553, 15.8955] | Failed |
| rod horizontal at tower one | [0.0, 6.9282, 6.9282] | [0.0, 6.9282, 6.9282] | Passed |
| beyond rod reach | unreachable | unreachable | Passed |
| carriage exactly at top | [7.0, 7.0, 7.0] | [7.0, 7.0, 7.0] | Passed |
| carriage over top | out-of-travel | out-of-travel | Passed |
| toward tower two | [12.3808, 11.9245, 17.2952] | [12.3808, 17.2952, 11.9245] | Failed |
SHA-256 / 262912104f0fc8492bb91343c8a9ba20a572e8bce1a677841424f116a4d41995
3 / The verified repair
Exit 0"""Failure Map reference implementation. Python standard library only."""
import json
import math
N = 1
observations = []
def solve(x):
R,e,L,px,py,pz,hmax=x
r=R-e
S=math.sqrt(3.0)/2.0
hs=[]
for tx,ty in [(0.0,r),(-r*S,-r/2),(r*S,-r/2)]:
q=L*L-(px-tx)**2-(py-ty)**2
if q<0: return 'unreachable'
h=pz+math.sqrt(q)
if h>hmax: return 'out-of-travel'
hs.append(round(h,4))
return hs
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['centre', [[10, 2, 12, 0, 0, 5, 40]], [13.9443, 13.9443, 13.9443]], ['off centre', [[10, 2, 12, 2, -3, 5, 40]], [9.3589, 12.9553, 15.8955]], ['rod horizontal at tower one', [[10, 2, 10, 0, -2, 0, 40]], [0.0, 6.9282, 6.9282]], ['beyond rod reach', [[10, 2, 10, 0, -3, 0, 40]], 'unreachable'], ['carriage exactly at top', [[12, 0, 13, 0, 0, 2, 7]], [7.0, 7.0, 7.0]], ['carriage over top', [[12, 0, 13, 0, 0, 2.5, 7]], 'out-of-travel'], ['toward tower two', [[10, 1, 15, -4, -2, 3, 40]], [12.3808, 17.2952, 11.9245]]], [['rod horizontal at tower one', [[10, 2, 10, 0, -2, 0, 40]], [0.0, 6.9282, 6.9282]], ['carriage exactly at top', [[12, 0, 13, 0, 0, 2, 7]], [7.0, 7.0, 7.0]], ['carriage over top', [[12, 0, 13, 0, 0, 2.5, 7]], 'out-of-travel'], ['toward tower two', [[10, 1, 15, -4, -2, 3, 40]], [12.3808, 17.2952, 11.9245]], ['toward tower three', [[10, 1, 15, 4, -2, 3, 40]], [12.3808, 11.9245, 17.2952]], ['high z low travel', [[10, 2, 12, 0, 0, 25, 30]], 'out-of-travel'], ['no effector offset', [[8, 0, 12, 1, 1, 2, 40]], [11.6954, 9.4929, 11.1573]]], [['toward tower two', [[10, 1, 15, -4, -2, 3, 40]], [12.3808, 17.2952, 11.9245]], ['toward tower three', [[10, 1, 15, 4, -2, 3, 40]], [12.3808, 11.9245, 17.2952]], ['high z low travel', [[10, 2, 12, 0, 0, 25, 30]], 'out-of-travel'], ['no effector offset', [[8, 0, 12, 1, 1, 2, 40]], [11.6954, 9.4929, 11.1573]], ['large offset', [[12, 5, 11, -1, 2, 4, 40]], [13.7468, 12.07, 10.3934]], ['asymmetric point', [[10, 2, 12, 3, 4, 1, 40]], 'unreachable'], ['negative z', [[10, 2, 12, -2, 1, -3, 40]], [6.5394, 6.7321, 3.2679]]], [['centre', [[10, 2, 12, 0, 0, 5, 40]], [13.9443, 13.9443, 13.9443]], ['off centre', [[10, 2, 12, 2, -3, 5, 40]], [9.3589, 12.9553, 15.8955]], ['rod horizontal at tower one', [[10, 2, 10, 0, -2, 0, 40]], [0.0, 6.9282, 6.9282]], ['toward tower three', [[10, 1, 15, 4, -2, 3, 40]], [12.3808, 11.9245, 17.2952]], ['no effector offset', [[8, 0, 12, 1, 1, 2, 40]], [11.6954, 9.4929, 11.1573]], ['asymmetric point', [[10, 2, 12, 3, 4, 1, 40]], 'unreachable'], ['negative z', [[10, 2, 12, -2, 1, -3, 40]], [6.5394, 6.7321, 3.2679]]], [['off centre', [[10, 2, 12, 2, -3, 5, 40]], [9.3589, 12.9553, 15.8955]], ['rod horizontal at tower one', [[10, 2, 10, 0, -2, 0, 40]], [0.0, 6.9282, 6.9282]], ['beyond rod reach', [[10, 2, 10, 0, -3, 0, 40]], 'unreachable'], ['carriage exactly at top', [[12, 0, 13, 0, 0, 2, 7]], [7.0, 7.0, 7.0]], ['carriage over top', [[12, 0, 13, 0, 0, 2.5, 7]], 'out-of-travel'], ['no effector offset', [[8, 0, 12, 1, 1, 2, 40]], [11.6954, 9.4929, 11.1573]], ['large offset', [[12, 5, 11, -1, 2, 4, 40]], [13.7468, 12.07, 10.3934]]]]
for label, args, expected in fixtures[N-1]:
check(label, solve(*args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
| Boundary fixture | Actual | Expected | Outcome |
|---|---|---|---|
| centre | [13.9443, 13.9443, 13.9443] | [13.9443, 13.9443, 13.9443] | Passed |
| off centre | [9.3589, 12.9553, 15.8955] | [9.3589, 12.9553, 15.8955] | Passed |
| rod horizontal at tower one | [0.0, 6.9282, 6.9282] | [0.0, 6.9282, 6.9282] | Passed |
| beyond rod reach | unreachable | unreachable | Passed |
| carriage exactly at top | [7.0, 7.0, 7.0] | [7.0, 7.0, 7.0] | Passed |
| carriage over top | out-of-travel | out-of-travel | Passed |
| toward tower two | [12.3808, 17.2952, 11.9245] | [12.3808, 17.2952, 11.9245] | Passed |
SHA-256 / c6bf90e742116c0d9b0cc691005a49700433274da03a32efd488a7d003b1e77b
Verification & scope
Deterministic planar or low-dimensional teaching model with a stipulated convention; not a general robotics library. This reproducer isolates one failure mechanism. Results cover the supplied fixtures. Variants within a family share a test contract and should remain grouped when constructing evaluation splits. Related mechanisms with a shared evaluation_group must also remain together; these controlled models are not independent production incidents.
Observations recorded using Python 3.12.14 at 2026-09-29T14:51:04.939915+00:00.
Case digest / 2b95b0d1db3d70f831a7b273f0740a259c9896a0d4ff352cd8567df6d2bbf35e