FAILURE MAP
← Case archive

FA-88056 / Inverse kinematics solvers / Open access

Wrist singularity is detected only at an exact zero · case 01

Nearly aligned wrist axes produce huge, noise-driven a and g values instead of the documented convention.

Verified by executionVariant 1 · 7 checks per implementationDownload source bundle ↓JSON ↗

ROOT CAUSE

The singular branch is guarded by sb == 0.0, so floating residue skips it.

VERIFIED REPAIR

Treat hypot(R02,R12) < 1e-9 as singular.

Unsuccessful approach: Handling only the upright case still sends near-inverted wrists to the generic branch.

Case contract

Input [R, flip]: R is a 3x3 wrist rotation R = Rz(a) Ry(b) Rz(g). Return [a,b,g] in degrees rounded to 4. With flip false b is in [0,180]; with flip true b is negative and a,g are shifted by 180 degrees. When hypot(R02,R12) < 1e-9 the wrist is singular: a=0 and b=0 (R22>0, g=atan2(R10,R00)) or b=180 (g=atan2(R01,-R00)).

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,flip=x
    sb=math.hypot(R[0][2],R[1][2])
    if sb==0.0:
        if R[2][2]>0: return [0.0,0.0,round(math.degrees(math.atan2(R[1][0],R[0][0])),4)]
        return [0.0,180.0,round(math.degrees(math.atan2(R[0][1],-R[0][0])),4)]
    if flip:
        b=math.atan2(-sb,R[2][2])
        a=math.atan2(-R[1][2],-R[0][2])
        g=math.atan2(-R[2][1],R[2][0])
    else:
        b=math.atan2(sb,R[2][2])
        a=math.atan2(R[1][2],R[0][2])
        g=math.atan2(R[2][1],-R[2][0])
    return [round(math.degrees(v),4) for v in (a,b,g)]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['generic no flip', [[[[0.04341204441673269, -0.8295983733257066, 0.5566703992264194], [0.9096158864219903, 0.26325835480968696, 0.32139380484326957], [-0.4131759111665348, 0.49240387650610395, 0.766044443118978]], False]], [30.0, 40.0, 50.0]], ['generic flip', [[[[0.04341204441673269, -0.8295983733257066, 0.5566703992264194], [0.9096158864219903, 0.26325835480968696, 0.32139380484326957], [-0.4131759111665348, 0.49240387650610395, 0.766044443118978]], True]], [-150.0, -40.0, -130.0]], ['large tilt no flip', [[[[-0.005813254051503125, 0.9237208365458508, 0.3830222215594891], [0.6941091380258464, 0.2794538206643772, -0.6634139481689384], [-0.7198463103929542, 0.2620026302293849, -0.6427876096865394]], False]], [-60.0, 130.0, 20.0]], ['large tilt flip', [[[[-0.005813254051503125, 0.9237208365458508, 0.3830222215594891], [0.6941091380258464, 0.2794538206643772, -0.6634139481689384], [-0.7198463103929542, 0.2620026302293849, -0.6427876096865394]], True]], [120.0, -130.0, -160.0]], ['near upright singular', [[[[0.5, -0.8660254037844386, 1.5818054920253123e-10], [0.8660254037844386, 0.5, 7.376080146430387e-11], [-1.429690024728532e-10, 1.0010797326181444e-10, 1.0]], False]], [0.0, 0.0, 60.0]], ['near inverted singular', [[[[-0.5, 0.8660254037844385, 1.718814073341628e-10], [0.8660254037844385, 0.5, 3.030732959515473e-11], [-5.969378631680947e-11, 1.6400732998718326e-10, -1.0]], False]], [0.0, 180.0, 60.0]], ['exact upright', [[[[0.766044443118978, -0.6427876096865393, 0.0], [0.6427876096865393, 0.766044443118978, 0.0], [-0.0, 0.0, 1.0]], False]], [0.0, 0.0, 40.0]]], [['large tilt flip', [[[[-0.005813254051503125, 0.9237208365458508, 0.3830222215594891], [0.6941091380258464, 0.2794538206643772, -0.6634139481689384], [-0.7198463103929542, 0.2620026302293849, -0.6427876096865394]], True]], [120.0, -130.0, -160.0]], ['near upright singular', [[[[0.5, -0.8660254037844386, 1.5818054920253123e-10], [0.8660254037844386, 0.5, 7.376080146430387e-11], [-1.429690024728532e-10, 1.0010797326181444e-10, 1.0]], False]], [0.0, 0.0, 60.0]], ['near inverted singular', [[[[-0.5, 0.8660254037844385, 1.718814073341628e-10], [0.8660254037844385, 0.5, 3.030732959515473e-11], [-5.969378631680947e-11, 1.6400732998718326e-10, -1.0]], False]], [0.0, 180.0, 60.0]], ['exact upright', [[[[0.766044443118978, -0.6427876096865393, 0.0], [0.6427876096865393, 0.766044443118978, 0.0], [-0.0, 0.0, 1.0]], False]], [0.0, 0.0, 40.0]], ['exact inverted', [[[[-0.766044443118978, 0.6427876096865393, 1.2246467991473532e-16], [0.6427876096865393, 0.766044443118978, 0.0], [-9.381338752702731e-17, 7.871877887341985e-17, -1.0]], True]], [0.0, 180.0, 40.0]], ['negative angles', [[[[-0.3209407678712127, -0.8147047612756303, -0.482962913144534], [0.44411428382689044, 0.3209407678712125, -0.8365163037378079], [0.8365163037378079, -0.4829629131445341, 0.25881904510252074]], False]], [-120.0, 75.0, -150.0]], ['negative angles flip', [[[[-0.3209407678712127, -0.8147047612756303, -0.482962913144534], [0.44411428382689044, 0.3209407678712125, -0.8365163037378079], [0.8365163037378079, -0.4829629131445341, 0.25881904510252074]], True]], [60.0, -75.0, 30.0]]], [['near inverted singular', [[[[-0.5, 0.8660254037844385, 1.718814073341628e-10], [0.8660254037844385, 0.5, 3.030732959515473e-11], [-5.969378631680947e-11, 1.6400732998718326e-10, -1.0]], False]], [0.0, 180.0, 60.0]], ['exact inverted', [[[[-0.766044443118978, 0.6427876096865393, 1.2246467991473532e-16], [0.6427876096865393, 0.766044443118978, 0.0], [-9.381338752702731e-17, 7.871877887341985e-17, -1.0]], True]], [0.0, 180.0, 40.0]], ['negative angles', [[[[-0.3209407678712127, -0.8147047612756303, -0.482962913144534], [0.44411428382689044, 0.3209407678712125, -0.8365163037378079], [0.8365163037378079, -0.4829629131445341, 0.25881904510252074]], False]], [-120.0, 75.0, -150.0]], ['negative angles flip', [[[[-0.3209407678712127, -0.8147047612756303, -0.482962913144534], [0.44411428382689044, 0.3209407678712125, -0.8365163037378079], [0.8365163037378079, -0.4829629131445341, 0.25881904510252074]], True]], [60.0, -75.0, 30.0]], ['tilt 90', [[[[0.49999999999999994, -0.49999999999999994, 0.7071067811865476], [-0.49999999999999994, 0.5000000000000001, 0.7071067811865475], [-0.7071067811865476, -0.7071067811865475, 6.123233995736766e-17]], False]], [45.0, 90.0, -45.0]], ['back quadrant', [[[[-0.08550503583141712, 0.515076844803523, -0.8528685319524432], [-0.984923155196477, 0.08550503583141716, 0.15038373318043521], [0.15038373318043524, 0.8528685319524432, 0.5000000000000001]], False]], [170.0, 60.0, 100.0]], ['inverted with roll', [[[[0.49999999999999983, -0.8660254037844387, 1.2246467991473532e-16], [-0.8660254037844387, -0.49999999999999983, 0.0], [6.123233995736764e-17, -1.0605752387249069e-16, -1.0]], False]], [0.0, 180.0, -120.0]]], [['generic no flip', [[[[0.04341204441673269, -0.8295983733257066, 0.5566703992264194], [0.9096158864219903, 0.26325835480968696, 0.32139380484326957], [-0.4131759111665348, 0.49240387650610395, 0.766044443118978]], False]], [30.0, 40.0, 50.0]], ['generic flip', [[[[0.04341204441673269, -0.8295983733257066, 0.5566703992264194], [0.9096158864219903, 0.26325835480968696, 0.32139380484326957], [-0.4131759111665348, 0.49240387650610395, 0.766044443118978]], True]], [-150.0, -40.0, -130.0]], ['near upright singular', [[[[0.5, -0.8660254037844386, 1.5818054920253123e-10], [0.8660254037844386, 0.5, 7.376080146430387e-11], [-1.429690024728532e-10, 1.0010797326181444e-10, 1.0]], False]], [0.0, 0.0, 60.0]], ['exact inverted', [[[[-0.766044443118978, 0.6427876096865393, 1.2246467991473532e-16], [0.6427876096865393, 0.766044443118978, 0.0], [-9.381338752702731e-17, 7.871877887341985e-17, -1.0]], True]], [0.0, 180.0, 40.0]], ['back quadrant', [[[[-0.08550503583141712, 0.515076844803523, -0.8528685319524432], [-0.984923155196477, 0.08550503583141716, 0.15038373318043521], [0.15038373318043524, 0.8528685319524432, 0.5000000000000001]], False]], [170.0, 60.0, 100.0]], ['inverted with roll', [[[[0.49999999999999983, -0.8660254037844387, 1.2246467991473532e-16], [-0.8660254037844387, -0.49999999999999983, 0.0], [6.123233995736764e-17, -1.0605752387249069e-16, -1.0]], False]], [0.0, 180.0, -120.0]], ['small tilt flip', [[[[0.34136939837363944, -0.9398073646785109, 0.015134435901338627], [0.9360020627702564, 0.34136939837363944, 0.08583165117743129], [-0.08583165117743129, -0.01513443590133862, 0.9961946980917455]], True]], [-100.0, -5.0, 170.0]]], [['generic no flip', [[[[0.04341204441673269, -0.8295983733257066, 0.5566703992264194], [0.9096158864219903, 0.26325835480968696, 0.32139380484326957], [-0.4131759111665348, 0.49240387650610395, 0.766044443118978]], False]], [30.0, 40.0, 50.0]], ['generic flip', [[[[0.04341204441673269, -0.8295983733257066, 0.5566703992264194], [0.9096158864219903, 0.26325835480968696, 0.32139380484326957], [-0.4131759111665348, 0.49240387650610395, 0.766044443118978]], True]], [-150.0, -40.0, -130.0]], ['large tilt no flip', [[[[-0.005813254051503125, 0.9237208365458508, 0.3830222215594891], [0.6941091380258464, 0.2794538206643772, -0.6634139481689384], [-0.7198463103929542, 0.2620026302293849, -0.6427876096865394]], False]], [-60.0, 130.0, 20.0]], ['large tilt flip', [[[[-0.005813254051503125, 0.9237208365458508, 0.3830222215594891], [0.6941091380258464, 0.2794538206643772, -0.6634139481689384], [-0.7198463103929542, 0.2620026302293849, -0.6427876096865394]], True]], [120.0, -130.0, -160.0]], ['near upright singular', [[[[0.5, -0.8660254037844386, 1.5818054920253123e-10], [0.8660254037844386, 0.5, 7.376080146430387e-11], [-1.429690024728532e-10, 1.0010797326181444e-10, 1.0]], False]], [0.0, 0.0, 60.0]], ['near inverted singular', [[[[-0.5, 0.8660254037844385, 1.718814073341628e-10], [0.8660254037844385, 0.5, 3.030732959515473e-11], [-5.969378631680947e-11, 1.6400732998718326e-10, -1.0]], False]], [0.0, 180.0, 60.0]], ['small tilt flip', [[[[0.34136939837363944, -0.9398073646785109, 0.015134435901338627], [0.9360020627702564, 0.34136939837363944, 0.08583165117743129], [-0.08583165117743129, -0.01513443590133862, 0.9961946980917455]], True]], [-100.0, -5.0, 170.0]]]]
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 fixtureActualExpectedOutcome
generic no flip[30.0, 40.0, 50.0][30.0, 40.0, 50.0]Passed
generic flip[-150.0, -40.0, -130.0][-150.0, -40.0, -130.0]Passed
large tilt no flip[-60.0, 130.0, 20.0][-60.0, 130.0, 20.0]Passed
large tilt flip[120.0, -130.0, -160.0][120.0, -130.0, -160.0]Passed
near upright singular[25.0, 0.0, 35.0][0.0, 0.0, 60.0]Failed
near inverted singular[10.0, 180.0, 70.0][0.0, 180.0, 60.0]Failed
exact upright[0.0, 0.0, 40.0][0.0, 0.0, 40.0]Passed

SHA-256 / da2192c5c01fd9d6f44bfc3095ef66483e0eb1c1aec4485f5a2c0e1f12195d04

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,flip=x
    sb=math.hypot(R[0][2],R[1][2])
    if sb<1e-9 and R[2][2]>0:
        if R[2][2]>0: return [0.0,0.0,round(math.degrees(math.atan2(R[1][0],R[0][0])),4)]
        return [0.0,180.0,round(math.degrees(math.atan2(R[0][1],-R[0][0])),4)]
    if flip:
        b=math.atan2(-sb,R[2][2])
        a=math.atan2(-R[1][2],-R[0][2])
        g=math.atan2(-R[2][1],R[2][0])
    else:
        b=math.atan2(sb,R[2][2])
        a=math.atan2(R[1][2],R[0][2])
        g=math.atan2(R[2][1],-R[2][0])
    return [round(math.degrees(v),4) for v in (a,b,g)]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['generic no flip', [[[[0.04341204441673269, -0.8295983733257066, 0.5566703992264194], [0.9096158864219903, 0.26325835480968696, 0.32139380484326957], [-0.4131759111665348, 0.49240387650610395, 0.766044443118978]], False]], [30.0, 40.0, 50.0]], ['generic flip', [[[[0.04341204441673269, -0.8295983733257066, 0.5566703992264194], [0.9096158864219903, 0.26325835480968696, 0.32139380484326957], [-0.4131759111665348, 0.49240387650610395, 0.766044443118978]], True]], [-150.0, -40.0, -130.0]], ['large tilt no flip', [[[[-0.005813254051503125, 0.9237208365458508, 0.3830222215594891], [0.6941091380258464, 0.2794538206643772, -0.6634139481689384], [-0.7198463103929542, 0.2620026302293849, -0.6427876096865394]], False]], [-60.0, 130.0, 20.0]], ['large tilt flip', [[[[-0.005813254051503125, 0.9237208365458508, 0.3830222215594891], [0.6941091380258464, 0.2794538206643772, -0.6634139481689384], [-0.7198463103929542, 0.2620026302293849, -0.6427876096865394]], True]], [120.0, -130.0, -160.0]], ['near upright singular', [[[[0.5, -0.8660254037844386, 1.5818054920253123e-10], [0.8660254037844386, 0.5, 7.376080146430387e-11], [-1.429690024728532e-10, 1.0010797326181444e-10, 1.0]], False]], [0.0, 0.0, 60.0]], ['near inverted singular', [[[[-0.5, 0.8660254037844385, 1.718814073341628e-10], [0.8660254037844385, 0.5, 3.030732959515473e-11], [-5.969378631680947e-11, 1.6400732998718326e-10, -1.0]], False]], [0.0, 180.0, 60.0]], ['exact upright', [[[[0.766044443118978, -0.6427876096865393, 0.0], [0.6427876096865393, 0.766044443118978, 0.0], [-0.0, 0.0, 1.0]], False]], [0.0, 0.0, 40.0]]], [['large tilt flip', [[[[-0.005813254051503125, 0.9237208365458508, 0.3830222215594891], [0.6941091380258464, 0.2794538206643772, -0.6634139481689384], [-0.7198463103929542, 0.2620026302293849, -0.6427876096865394]], True]], [120.0, -130.0, -160.0]], ['near upright singular', [[[[0.5, -0.8660254037844386, 1.5818054920253123e-10], [0.8660254037844386, 0.5, 7.376080146430387e-11], [-1.429690024728532e-10, 1.0010797326181444e-10, 1.0]], False]], [0.0, 0.0, 60.0]], ['near inverted singular', [[[[-0.5, 0.8660254037844385, 1.718814073341628e-10], [0.8660254037844385, 0.5, 3.030732959515473e-11], [-5.969378631680947e-11, 1.6400732998718326e-10, -1.0]], False]], [0.0, 180.0, 60.0]], ['exact upright', [[[[0.766044443118978, -0.6427876096865393, 0.0], [0.6427876096865393, 0.766044443118978, 0.0], [-0.0, 0.0, 1.0]], False]], [0.0, 0.0, 40.0]], ['exact inverted', [[[[-0.766044443118978, 0.6427876096865393, 1.2246467991473532e-16], [0.6427876096865393, 0.766044443118978, 0.0], [-9.381338752702731e-17, 7.871877887341985e-17, -1.0]], True]], [0.0, 180.0, 40.0]], ['negative angles', [[[[-0.3209407678712127, -0.8147047612756303, -0.482962913144534], [0.44411428382689044, 0.3209407678712125, -0.8365163037378079], [0.8365163037378079, -0.4829629131445341, 0.25881904510252074]], False]], [-120.0, 75.0, -150.0]], ['negative angles flip', [[[[-0.3209407678712127, -0.8147047612756303, -0.482962913144534], [0.44411428382689044, 0.3209407678712125, -0.8365163037378079], [0.8365163037378079, -0.4829629131445341, 0.25881904510252074]], True]], [60.0, -75.0, 30.0]]], [['near inverted singular', [[[[-0.5, 0.8660254037844385, 1.718814073341628e-10], [0.8660254037844385, 0.5, 3.030732959515473e-11], [-5.969378631680947e-11, 1.6400732998718326e-10, -1.0]], False]], [0.0, 180.0, 60.0]], ['exact inverted', [[[[-0.766044443118978, 0.6427876096865393, 1.2246467991473532e-16], [0.6427876096865393, 0.766044443118978, 0.0], [-9.381338752702731e-17, 7.871877887341985e-17, -1.0]], True]], [0.0, 180.0, 40.0]], ['negative angles', [[[[-0.3209407678712127, -0.8147047612756303, -0.482962913144534], [0.44411428382689044, 0.3209407678712125, -0.8365163037378079], [0.8365163037378079, -0.4829629131445341, 0.25881904510252074]], False]], [-120.0, 75.0, -150.0]], ['negative angles flip', [[[[-0.3209407678712127, -0.8147047612756303, -0.482962913144534], [0.44411428382689044, 0.3209407678712125, -0.8365163037378079], [0.8365163037378079, -0.4829629131445341, 0.25881904510252074]], True]], [60.0, -75.0, 30.0]], ['tilt 90', [[[[0.49999999999999994, -0.49999999999999994, 0.7071067811865476], [-0.49999999999999994, 0.5000000000000001, 0.7071067811865475], [-0.7071067811865476, -0.7071067811865475, 6.123233995736766e-17]], False]], [45.0, 90.0, -45.0]], ['back quadrant', [[[[-0.08550503583141712, 0.515076844803523, -0.8528685319524432], [-0.984923155196477, 0.08550503583141716, 0.15038373318043521], [0.15038373318043524, 0.8528685319524432, 0.5000000000000001]], False]], [170.0, 60.0, 100.0]], ['inverted with roll', [[[[0.49999999999999983, -0.8660254037844387, 1.2246467991473532e-16], [-0.8660254037844387, -0.49999999999999983, 0.0], [6.123233995736764e-17, -1.0605752387249069e-16, -1.0]], False]], [0.0, 180.0, -120.0]]], [['generic no flip', [[[[0.04341204441673269, -0.8295983733257066, 0.5566703992264194], [0.9096158864219903, 0.26325835480968696, 0.32139380484326957], [-0.4131759111665348, 0.49240387650610395, 0.766044443118978]], False]], [30.0, 40.0, 50.0]], ['generic flip', [[[[0.04341204441673269, -0.8295983733257066, 0.5566703992264194], [0.9096158864219903, 0.26325835480968696, 0.32139380484326957], [-0.4131759111665348, 0.49240387650610395, 0.766044443118978]], True]], [-150.0, -40.0, -130.0]], ['near upright singular', [[[[0.5, -0.8660254037844386, 1.5818054920253123e-10], [0.8660254037844386, 0.5, 7.376080146430387e-11], [-1.429690024728532e-10, 1.0010797326181444e-10, 1.0]], False]], [0.0, 0.0, 60.0]], ['exact inverted', [[[[-0.766044443118978, 0.6427876096865393, 1.2246467991473532e-16], [0.6427876096865393, 0.766044443118978, 0.0], [-9.381338752702731e-17, 7.871877887341985e-17, -1.0]], True]], [0.0, 180.0, 40.0]], ['back quadrant', [[[[-0.08550503583141712, 0.515076844803523, -0.8528685319524432], [-0.984923155196477, 0.08550503583141716, 0.15038373318043521], [0.15038373318043524, 0.8528685319524432, 0.5000000000000001]], False]], [170.0, 60.0, 100.0]], ['inverted with roll', [[[[0.49999999999999983, -0.8660254037844387, 1.2246467991473532e-16], [-0.8660254037844387, -0.49999999999999983, 0.0], [6.123233995736764e-17, -1.0605752387249069e-16, -1.0]], False]], [0.0, 180.0, -120.0]], ['small tilt flip', [[[[0.34136939837363944, -0.9398073646785109, 0.015134435901338627], [0.9360020627702564, 0.34136939837363944, 0.08583165117743129], [-0.08583165117743129, -0.01513443590133862, 0.9961946980917455]], True]], [-100.0, -5.0, 170.0]]], [['generic no flip', [[[[0.04341204441673269, -0.8295983733257066, 0.5566703992264194], [0.9096158864219903, 0.26325835480968696, 0.32139380484326957], [-0.4131759111665348, 0.49240387650610395, 0.766044443118978]], False]], [30.0, 40.0, 50.0]], ['generic flip', [[[[0.04341204441673269, -0.8295983733257066, 0.5566703992264194], [0.9096158864219903, 0.26325835480968696, 0.32139380484326957], [-0.4131759111665348, 0.49240387650610395, 0.766044443118978]], True]], [-150.0, -40.0, -130.0]], ['large tilt no flip', [[[[-0.005813254051503125, 0.9237208365458508, 0.3830222215594891], [0.6941091380258464, 0.2794538206643772, -0.6634139481689384], [-0.7198463103929542, 0.2620026302293849, -0.6427876096865394]], False]], [-60.0, 130.0, 20.0]], ['large tilt flip', [[[[-0.005813254051503125, 0.9237208365458508, 0.3830222215594891], [0.6941091380258464, 0.2794538206643772, -0.6634139481689384], [-0.7198463103929542, 0.2620026302293849, -0.6427876096865394]], True]], [120.0, -130.0, -160.0]], ['near upright singular', [[[[0.5, -0.8660254037844386, 1.5818054920253123e-10], [0.8660254037844386, 0.5, 7.376080146430387e-11], [-1.429690024728532e-10, 1.0010797326181444e-10, 1.0]], False]], [0.0, 0.0, 60.0]], ['near inverted singular', [[[[-0.5, 0.8660254037844385, 1.718814073341628e-10], [0.8660254037844385, 0.5, 3.030732959515473e-11], [-5.969378631680947e-11, 1.6400732998718326e-10, -1.0]], False]], [0.0, 180.0, 60.0]], ['small tilt flip', [[[[0.34136939837363944, -0.9398073646785109, 0.015134435901338627], [0.9360020627702564, 0.34136939837363944, 0.08583165117743129], [-0.08583165117743129, -0.01513443590133862, 0.9961946980917455]], True]], [-100.0, -5.0, 170.0]]]]
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 fixtureActualExpectedOutcome
generic no flip[30.0, 40.0, 50.0][30.0, 40.0, 50.0]Passed
generic flip[-150.0, -40.0, -130.0][-150.0, -40.0, -130.0]Passed
large tilt no flip[-60.0, 130.0, 20.0][-60.0, 130.0, 20.0]Passed
large tilt flip[120.0, -130.0, -160.0][120.0, -130.0, -160.0]Passed
near upright singular[0.0, 0.0, 60.0][0.0, 0.0, 60.0]Passed
near inverted singular[10.0, 180.0, 70.0][0.0, 180.0, 60.0]Failed
exact upright[0.0, 0.0, 40.0][0.0, 0.0, 40.0]Passed

SHA-256 / 6b9bfb4f3ba79b6518d5dd8788877b09e5030f5de9932ec0020c12c02f670e78

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,flip=x
    sb=math.hypot(R[0][2],R[1][2])
    if sb<1e-9:
        if R[2][2]>0: return [0.0,0.0,round(math.degrees(math.atan2(R[1][0],R[0][0])),4)]
        return [0.0,180.0,round(math.degrees(math.atan2(R[0][1],-R[0][0])),4)]
    if flip:
        b=math.atan2(-sb,R[2][2])
        a=math.atan2(-R[1][2],-R[0][2])
        g=math.atan2(-R[2][1],R[2][0])
    else:
        b=math.atan2(sb,R[2][2])
        a=math.atan2(R[1][2],R[0][2])
        g=math.atan2(R[2][1],-R[2][0])
    return [round(math.degrees(v),4) for v in (a,b,g)]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['generic no flip', [[[[0.04341204441673269, -0.8295983733257066, 0.5566703992264194], [0.9096158864219903, 0.26325835480968696, 0.32139380484326957], [-0.4131759111665348, 0.49240387650610395, 0.766044443118978]], False]], [30.0, 40.0, 50.0]], ['generic flip', [[[[0.04341204441673269, -0.8295983733257066, 0.5566703992264194], [0.9096158864219903, 0.26325835480968696, 0.32139380484326957], [-0.4131759111665348, 0.49240387650610395, 0.766044443118978]], True]], [-150.0, -40.0, -130.0]], ['large tilt no flip', [[[[-0.005813254051503125, 0.9237208365458508, 0.3830222215594891], [0.6941091380258464, 0.2794538206643772, -0.6634139481689384], [-0.7198463103929542, 0.2620026302293849, -0.6427876096865394]], False]], [-60.0, 130.0, 20.0]], ['large tilt flip', [[[[-0.005813254051503125, 0.9237208365458508, 0.3830222215594891], [0.6941091380258464, 0.2794538206643772, -0.6634139481689384], [-0.7198463103929542, 0.2620026302293849, -0.6427876096865394]], True]], [120.0, -130.0, -160.0]], ['near upright singular', [[[[0.5, -0.8660254037844386, 1.5818054920253123e-10], [0.8660254037844386, 0.5, 7.376080146430387e-11], [-1.429690024728532e-10, 1.0010797326181444e-10, 1.0]], False]], [0.0, 0.0, 60.0]], ['near inverted singular', [[[[-0.5, 0.8660254037844385, 1.718814073341628e-10], [0.8660254037844385, 0.5, 3.030732959515473e-11], [-5.969378631680947e-11, 1.6400732998718326e-10, -1.0]], False]], [0.0, 180.0, 60.0]], ['exact upright', [[[[0.766044443118978, -0.6427876096865393, 0.0], [0.6427876096865393, 0.766044443118978, 0.0], [-0.0, 0.0, 1.0]], False]], [0.0, 0.0, 40.0]]], [['large tilt flip', [[[[-0.005813254051503125, 0.9237208365458508, 0.3830222215594891], [0.6941091380258464, 0.2794538206643772, -0.6634139481689384], [-0.7198463103929542, 0.2620026302293849, -0.6427876096865394]], True]], [120.0, -130.0, -160.0]], ['near upright singular', [[[[0.5, -0.8660254037844386, 1.5818054920253123e-10], [0.8660254037844386, 0.5, 7.376080146430387e-11], [-1.429690024728532e-10, 1.0010797326181444e-10, 1.0]], False]], [0.0, 0.0, 60.0]], ['near inverted singular', [[[[-0.5, 0.8660254037844385, 1.718814073341628e-10], [0.8660254037844385, 0.5, 3.030732959515473e-11], [-5.969378631680947e-11, 1.6400732998718326e-10, -1.0]], False]], [0.0, 180.0, 60.0]], ['exact upright', [[[[0.766044443118978, -0.6427876096865393, 0.0], [0.6427876096865393, 0.766044443118978, 0.0], [-0.0, 0.0, 1.0]], False]], [0.0, 0.0, 40.0]], ['exact inverted', [[[[-0.766044443118978, 0.6427876096865393, 1.2246467991473532e-16], [0.6427876096865393, 0.766044443118978, 0.0], [-9.381338752702731e-17, 7.871877887341985e-17, -1.0]], True]], [0.0, 180.0, 40.0]], ['negative angles', [[[[-0.3209407678712127, -0.8147047612756303, -0.482962913144534], [0.44411428382689044, 0.3209407678712125, -0.8365163037378079], [0.8365163037378079, -0.4829629131445341, 0.25881904510252074]], False]], [-120.0, 75.0, -150.0]], ['negative angles flip', [[[[-0.3209407678712127, -0.8147047612756303, -0.482962913144534], [0.44411428382689044, 0.3209407678712125, -0.8365163037378079], [0.8365163037378079, -0.4829629131445341, 0.25881904510252074]], True]], [60.0, -75.0, 30.0]]], [['near inverted singular', [[[[-0.5, 0.8660254037844385, 1.718814073341628e-10], [0.8660254037844385, 0.5, 3.030732959515473e-11], [-5.969378631680947e-11, 1.6400732998718326e-10, -1.0]], False]], [0.0, 180.0, 60.0]], ['exact inverted', [[[[-0.766044443118978, 0.6427876096865393, 1.2246467991473532e-16], [0.6427876096865393, 0.766044443118978, 0.0], [-9.381338752702731e-17, 7.871877887341985e-17, -1.0]], True]], [0.0, 180.0, 40.0]], ['negative angles', [[[[-0.3209407678712127, -0.8147047612756303, -0.482962913144534], [0.44411428382689044, 0.3209407678712125, -0.8365163037378079], [0.8365163037378079, -0.4829629131445341, 0.25881904510252074]], False]], [-120.0, 75.0, -150.0]], ['negative angles flip', [[[[-0.3209407678712127, -0.8147047612756303, -0.482962913144534], [0.44411428382689044, 0.3209407678712125, -0.8365163037378079], [0.8365163037378079, -0.4829629131445341, 0.25881904510252074]], True]], [60.0, -75.0, 30.0]], ['tilt 90', [[[[0.49999999999999994, -0.49999999999999994, 0.7071067811865476], [-0.49999999999999994, 0.5000000000000001, 0.7071067811865475], [-0.7071067811865476, -0.7071067811865475, 6.123233995736766e-17]], False]], [45.0, 90.0, -45.0]], ['back quadrant', [[[[-0.08550503583141712, 0.515076844803523, -0.8528685319524432], [-0.984923155196477, 0.08550503583141716, 0.15038373318043521], [0.15038373318043524, 0.8528685319524432, 0.5000000000000001]], False]], [170.0, 60.0, 100.0]], ['inverted with roll', [[[[0.49999999999999983, -0.8660254037844387, 1.2246467991473532e-16], [-0.8660254037844387, -0.49999999999999983, 0.0], [6.123233995736764e-17, -1.0605752387249069e-16, -1.0]], False]], [0.0, 180.0, -120.0]]], [['generic no flip', [[[[0.04341204441673269, -0.8295983733257066, 0.5566703992264194], [0.9096158864219903, 0.26325835480968696, 0.32139380484326957], [-0.4131759111665348, 0.49240387650610395, 0.766044443118978]], False]], [30.0, 40.0, 50.0]], ['generic flip', [[[[0.04341204441673269, -0.8295983733257066, 0.5566703992264194], [0.9096158864219903, 0.26325835480968696, 0.32139380484326957], [-0.4131759111665348, 0.49240387650610395, 0.766044443118978]], True]], [-150.0, -40.0, -130.0]], ['near upright singular', [[[[0.5, -0.8660254037844386, 1.5818054920253123e-10], [0.8660254037844386, 0.5, 7.376080146430387e-11], [-1.429690024728532e-10, 1.0010797326181444e-10, 1.0]], False]], [0.0, 0.0, 60.0]], ['exact inverted', [[[[-0.766044443118978, 0.6427876096865393, 1.2246467991473532e-16], [0.6427876096865393, 0.766044443118978, 0.0], [-9.381338752702731e-17, 7.871877887341985e-17, -1.0]], True]], [0.0, 180.0, 40.0]], ['back quadrant', [[[[-0.08550503583141712, 0.515076844803523, -0.8528685319524432], [-0.984923155196477, 0.08550503583141716, 0.15038373318043521], [0.15038373318043524, 0.8528685319524432, 0.5000000000000001]], False]], [170.0, 60.0, 100.0]], ['inverted with roll', [[[[0.49999999999999983, -0.8660254037844387, 1.2246467991473532e-16], [-0.8660254037844387, -0.49999999999999983, 0.0], [6.123233995736764e-17, -1.0605752387249069e-16, -1.0]], False]], [0.0, 180.0, -120.0]], ['small tilt flip', [[[[0.34136939837363944, -0.9398073646785109, 0.015134435901338627], [0.9360020627702564, 0.34136939837363944, 0.08583165117743129], [-0.08583165117743129, -0.01513443590133862, 0.9961946980917455]], True]], [-100.0, -5.0, 170.0]]], [['generic no flip', [[[[0.04341204441673269, -0.8295983733257066, 0.5566703992264194], [0.9096158864219903, 0.26325835480968696, 0.32139380484326957], [-0.4131759111665348, 0.49240387650610395, 0.766044443118978]], False]], [30.0, 40.0, 50.0]], ['generic flip', [[[[0.04341204441673269, -0.8295983733257066, 0.5566703992264194], [0.9096158864219903, 0.26325835480968696, 0.32139380484326957], [-0.4131759111665348, 0.49240387650610395, 0.766044443118978]], True]], [-150.0, -40.0, -130.0]], ['large tilt no flip', [[[[-0.005813254051503125, 0.9237208365458508, 0.3830222215594891], [0.6941091380258464, 0.2794538206643772, -0.6634139481689384], [-0.7198463103929542, 0.2620026302293849, -0.6427876096865394]], False]], [-60.0, 130.0, 20.0]], ['large tilt flip', [[[[-0.005813254051503125, 0.9237208365458508, 0.3830222215594891], [0.6941091380258464, 0.2794538206643772, -0.6634139481689384], [-0.7198463103929542, 0.2620026302293849, -0.6427876096865394]], True]], [120.0, -130.0, -160.0]], ['near upright singular', [[[[0.5, -0.8660254037844386, 1.5818054920253123e-10], [0.8660254037844386, 0.5, 7.376080146430387e-11], [-1.429690024728532e-10, 1.0010797326181444e-10, 1.0]], False]], [0.0, 0.0, 60.0]], ['near inverted singular', [[[[-0.5, 0.8660254037844385, 1.718814073341628e-10], [0.8660254037844385, 0.5, 3.030732959515473e-11], [-5.969378631680947e-11, 1.6400732998718326e-10, -1.0]], False]], [0.0, 180.0, 60.0]], ['small tilt flip', [[[[0.34136939837363944, -0.9398073646785109, 0.015134435901338627], [0.9360020627702564, 0.34136939837363944, 0.08583165117743129], [-0.08583165117743129, -0.01513443590133862, 0.9961946980917455]], True]], [-100.0, -5.0, 170.0]]]]
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 fixtureActualExpectedOutcome
generic no flip[30.0, 40.0, 50.0][30.0, 40.0, 50.0]Passed
generic flip[-150.0, -40.0, -130.0][-150.0, -40.0, -130.0]Passed
large tilt no flip[-60.0, 130.0, 20.0][-60.0, 130.0, 20.0]Passed
large tilt flip[120.0, -130.0, -160.0][120.0, -130.0, -160.0]Passed
near upright singular[0.0, 0.0, 60.0][0.0, 0.0, 60.0]Passed
near inverted singular[0.0, 180.0, 60.0][0.0, 180.0, 60.0]Passed
exact upright[0.0, 0.0, 40.0][0.0, 0.0, 40.0]Passed

SHA-256 / c290c0d285c4fd9bfc9baa6855278dc503a6b234aa887d6b0722af833a7ebcdb

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.559726+00:00.

Case digest / de472333afc816365998c6cd7d0bd0002029efdbbe7e09963ea93c197bf7e952