{"abstract":"Task steps are skewed whenever the Jacobian rows are correlated.","category":"Inverse kinematics solvers","checks":7,"contract":"Input [lengths(3), q(3 deg), target, qc(3 deg), k]: planar 3R arm, position task only. One step dq = J+ e + (I - J+ J) z, J+ = J^T (J J^T)^-1, e = target - fk(q), z = k*(qc-q) in radians. Return the updated q in degrees rounded to 4, or \"singular\" when |det(J J^T)|<1e-12.","evaluation_group":"w2-inverse_kinematics_solvers-null-space-redundancy","failed_approach":"Swapping the diagonal entries is the inverse of a different matrix.","family":"w2-inverse_kinematics_solvers-null-space-redundancy-gram-inverse","id":"FA-88191","implementations":{"attempt":{"sha256":"25915092c19e0674c27b9b2fe5e49159c48402e12aaff3c2480a3666bfe0f7b7","source":"\"\"\"Failure Map reference implementation. Python standard library only.\"\"\"\nimport json\nimport math\nN = 1\nobservations = []\ndef solve(x):\n    ls,q,t,qc,k=x\n    qr=[math.radians(v) for v in q]\n    cum=[sum(qr[:i+1]) for i in range(3)]\n    px=sum(ls[i]*math.cos(cum[i]) for i in range(3))\n    py=sum(ls[i]*math.sin(cum[i]) for i in range(3))\n    J=[[-sum(ls[j]*math.sin(cum[j]) for j in range(i,3)) for i in range(3)],\n       [sum(ls[j]*math.cos(cum[j]) for j in range(i,3)) for i in range(3)]]\n    a=sum(v*v for v in J[0])\n    b=sum(J[0][i]*J[1][i] for i in range(3))\n    c=sum(v*v for v in J[1])\n    det=a*c-b*b\n    if abs(det)<1e-12: return 'singular'\n    inv=[[a/det,-b/det],[-b/det,c/det]]\n    P=[[J[0][i]*inv[0][0]+J[1][i]*inv[1][0],J[0][i]*inv[0][1]+J[1][i]*inv[1][1]] for i in range(3)]\n    e=[t[0]-px,t[1]-py]\n    z=[k*math.radians(qc[i]-q[i]) for i in range(3)]\n    N=[[(1.0 if i==j else 0.0)-sum(P[i][r]*J[r][j] for r in range(2)) for j in range(3)] for i in range(3)]\n    dq=[P[i][0]*e[0]+P[i][1]*e[1]+sum(N[i][j]*z[j] for j in range(3)) for i in range(3)]\n    return [round(q[i]+math.degrees(dq[i]),4) for i in range(3)]\ndef check(label, actual, expected):\n    observations.append({\"check\": label, \"actual\": actual, \"expected\": expected, \"passed\": actual == expected})\nfixtures = [[['task only', [[[1, 1, 1], [20, 30, 40], [1.5, 1.5], [20, 30, 40], 0.0]], [-9.6761, 48.859, 73.9791]], ['centering only', [[[1, 1, 1], [20, 30, 40], [1.0911, 2.3209], [0, 0, 0], 0.5]], [23.38, 40.6501, 42.2202]], ['task and centering', [[[1, 1, 1], [10, 40, -20], [2, 1], [0, 30, 30], 0.3]], [-62.5399, 148.4425, -29.151]], ['straight arm singular', [[[1, 1, 1], [0, 0, 0], [2, 1], [0, 0, 0], 0.5]], 'singular'], ['unequal links', [[[2, 1, 0.5], [30, -45, 60], [1.5, 1], [0, 0, 0], 0.2]], [87.5837, -214.0176, 178.4237]], ['negative config', [[[1, 1.5, 0.7], [-30, -20, -60], [1, -2], [0, 10, -10], 1.0]], [-7.4068, -55.9156, -92.0392]], ['strong centering', [[[1, 1, 1], [60, 60, 60], [-1, 1.5], [0, 0, 0], 2.0]], [43.7121, 92.5758, 40.7197]]], [['centering only', [[[1, 1, 1], [20, 30, 40], [1.0911, 2.3209], [0, 0, 0], 0.5]], [23.38, 40.6501, 42.2202]], ['unequal links', [[[2, 1, 0.5], [30, -45, 60], [1.5, 1], [0, 0, 0], 0.2]], [87.5837, -214.0176, 178.4237]], ['negative config', [[[1, 1.5, 0.7], [-30, -20, -60], [1, -2], [0, 10, -10], 1.0]], [-7.4068, -55.9156, -92.0392]], ['strong centering', [[[1, 1, 1], [60, 60, 60], [-1, 1.5], [0, 0, 0], 2.0]], [43.7121, 92.5758, 40.7197]], ['behind base', [[[1, 1, 1], [120, 30, 20], [-2, 0.5], [90, 0, 0], 0.4]], [75.3463, 86.5441, 80.8124]], ['small error', [[[1.2, 0.8, 0.5], [45, -30, 15], [1.6, 1.1], [45, -30, 15], 0.0]], [102.7802, -138.4201, 15.5818]], ['asymmetric centre', [[[1, 1, 1], [5, 80, -40], [1.2, 1.9], [10, 20, 30], 0.8]], [-22.1921, 110.3115, 3.6813]]], [['task only', [[[1, 1, 1], [20, 30, 40], [1.5, 1.5], [20, 30, 40], 0.0]], [-9.6761, 48.859, 73.9791]], ['centering only', [[[1, 1, 1], [20, 30, 40], [1.0911, 2.3209], [0, 0, 0], 0.5]], [23.38, 40.6501, 42.2202]], ['task and centering', [[[1, 1, 1], [10, 40, -20], [2, 1], [0, 30, 30], 0.3]], [-62.5399, 148.4425, -29.151]], ['straight arm singular', [[[1, 1, 1], [0, 0, 0], [2, 1], [0, 0, 0], 0.5]], 'singular'], ['behind base', [[[1, 1, 1], [120, 30, 20], [-2, 0.5], [90, 0, 0], 0.4]], [75.3463, 86.5441, 80.8124]], ['small error', [[[1.2, 0.8, 0.5], [45, -30, 15], [1.6, 1.1], [45, -30, 15], 0.0]], [102.7802, -138.4201, 15.5818]], ['asymmetric centre', [[[1, 1, 1], [5, 80, -40], [1.2, 1.9], [10, 20, 30], 0.8]], [-22.1921, 110.3115, 3.6813]]], [['task only', [[[1, 1, 1], [20, 30, 40], [1.5, 1.5], [20, 30, 40], 0.0]], [-9.6761, 48.859, 73.9791]], ['centering only', [[[1, 1, 1], [20, 30, 40], [1.0911, 2.3209], [0, 0, 0], 0.5]], [23.38, 40.6501, 42.2202]], ['task and centering', [[[1, 1, 1], [10, 40, -20], [2, 1], [0, 30, 30], 0.3]], [-62.5399, 148.4425, -29.151]], ['straight arm singular', [[[1, 1, 1], [0, 0, 0], [2, 1], [0, 0, 0], 0.5]], 'singular'], ['unequal links', [[[2, 1, 0.5], [30, -45, 60], [1.5, 1], [0, 0, 0], 0.2]], [87.5837, -214.0176, 178.4237]], ['negative config', [[[1, 1.5, 0.7], [-30, -20, -60], [1, -2], [0, 10, -10], 1.0]], [-7.4068, -55.9156, -92.0392]], ['strong centering', [[[1, 1, 1], [60, 60, 60], [-1, 1.5], [0, 0, 0], 2.0]], [43.7121, 92.5758, 40.7197]]], [['straight arm singular', [[[1, 1, 1], [0, 0, 0], [2, 1], [0, 0, 0], 0.5]], 'singular'], ['unequal links', [[[2, 1, 0.5], [30, -45, 60], [1.5, 1], [0, 0, 0], 0.2]], [87.5837, -214.0176, 178.4237]], ['negative config', [[[1, 1.5, 0.7], [-30, -20, -60], [1, -2], [0, 10, -10], 1.0]], [-7.4068, -55.9156, -92.0392]], ['strong centering', [[[1, 1, 1], [60, 60, 60], [-1, 1.5], [0, 0, 0], 2.0]], [43.7121, 92.5758, 40.7197]], ['behind base', [[[1, 1, 1], [120, 30, 20], [-2, 0.5], [90, 0, 0], 0.4]], [75.3463, 86.5441, 80.8124]], ['small error', [[[1.2, 0.8, 0.5], [45, -30, 15], [1.6, 1.1], [45, -30, 15], 0.0]], [102.7802, -138.4201, 15.5818]], ['asymmetric centre', [[[1, 1, 1], [5, 80, -40], [1.2, 1.9], [10, 20, 30], 0.8]], [-22.1921, 110.3115, 3.6813]]]]\nfor label, args, expected in fixtures[N-1]:\n    check(label, solve(*args), expected)\nprint(json.dumps({\"observations\": observations, \"passed\": all(x[\"passed\"] for x in observations)}, ensure_ascii=False))\nraise SystemExit(0 if all(x[\"passed\"] for x in observations) else 1)\n"},"broken":{"sha256":"d2a2912b2f55971416f7a93660e226b0470897873df84bab4a6ec494645677cf","source":"\"\"\"Failure Map reference implementation. Python standard library only.\"\"\"\nimport json\nimport math\nN = 1\nobservations = []\ndef solve(x):\n    ls,q,t,qc,k=x\n    qr=[math.radians(v) for v in q]\n    cum=[sum(qr[:i+1]) for i in range(3)]\n    px=sum(ls[i]*math.cos(cum[i]) for i in range(3))\n    py=sum(ls[i]*math.sin(cum[i]) for i in range(3))\n    J=[[-sum(ls[j]*math.sin(cum[j]) for j in range(i,3)) for i in range(3)],\n       [sum(ls[j]*math.cos(cum[j]) for j in range(i,3)) for i in range(3)]]\n    a=sum(v*v for v in J[0])\n    b=sum(J[0][i]*J[1][i] for i in range(3))\n    c=sum(v*v for v in J[1])\n    det=a*c-b*b\n    if abs(det)<1e-12: return 'singular'\n    inv=[[c/det,b/det],[b/det,a/det]]\n    P=[[J[0][i]*inv[0][0]+J[1][i]*inv[1][0],J[0][i]*inv[0][1]+J[1][i]*inv[1][1]] for i in range(3)]\n    e=[t[0]-px,t[1]-py]\n    z=[k*math.radians(qc[i]-q[i]) for i in range(3)]\n    N=[[(1.0 if i==j else 0.0)-sum(P[i][r]*J[r][j] for r in range(2)) for j in range(3)] for i in range(3)]\n    dq=[P[i][0]*e[0]+P[i][1]*e[1]+sum(N[i][j]*z[j] for j in range(3)) for i in range(3)]\n    return [round(q[i]+math.degrees(dq[i]),4) for i in range(3)]\ndef check(label, actual, expected):\n    observations.append({\"check\": label, \"actual\": actual, \"expected\": expected, \"passed\": actual == expected})\nfixtures = [[['task only', [[[1, 1, 1], [20, 30, 40], [1.5, 1.5], [20, 30, 40], 0.0]], [-9.6761, 48.859, 73.9791]], ['centering only', [[[1, 1, 1], [20, 30, 40], [1.0911, 2.3209], [0, 0, 0], 0.5]], [23.38, 40.6501, 42.2202]], ['task and centering', [[[1, 1, 1], [10, 40, -20], [2, 1], [0, 30, 30], 0.3]], [-62.5399, 148.4425, -29.151]], ['straight arm singular', [[[1, 1, 1], [0, 0, 0], [2, 1], [0, 0, 0], 0.5]], 'singular'], ['unequal links', [[[2, 1, 0.5], [30, -45, 60], [1.5, 1], [0, 0, 0], 0.2]], [87.5837, -214.0176, 178.4237]], ['negative config', [[[1, 1.5, 0.7], [-30, -20, -60], [1, -2], [0, 10, -10], 1.0]], [-7.4068, -55.9156, -92.0392]], ['strong centering', [[[1, 1, 1], [60, 60, 60], [-1, 1.5], [0, 0, 0], 2.0]], [43.7121, 92.5758, 40.7197]]], [['centering only', [[[1, 1, 1], [20, 30, 40], [1.0911, 2.3209], [0, 0, 0], 0.5]], [23.38, 40.6501, 42.2202]], ['unequal links', [[[2, 1, 0.5], [30, -45, 60], [1.5, 1], [0, 0, 0], 0.2]], [87.5837, -214.0176, 178.4237]], ['negative config', [[[1, 1.5, 0.7], [-30, -20, -60], [1, -2], [0, 10, -10], 1.0]], [-7.4068, -55.9156, -92.0392]], ['strong centering', [[[1, 1, 1], [60, 60, 60], [-1, 1.5], [0, 0, 0], 2.0]], [43.7121, 92.5758, 40.7197]], ['behind base', [[[1, 1, 1], [120, 30, 20], [-2, 0.5], [90, 0, 0], 0.4]], [75.3463, 86.5441, 80.8124]], ['small error', [[[1.2, 0.8, 0.5], [45, -30, 15], [1.6, 1.1], [45, -30, 15], 0.0]], [102.7802, -138.4201, 15.5818]], ['asymmetric centre', [[[1, 1, 1], [5, 80, -40], [1.2, 1.9], [10, 20, 30], 0.8]], [-22.1921, 110.3115, 3.6813]]], [['task only', [[[1, 1, 1], [20, 30, 40], [1.5, 1.5], [20, 30, 40], 0.0]], [-9.6761, 48.859, 73.9791]], ['centering only', [[[1, 1, 1], [20, 30, 40], [1.0911, 2.3209], [0, 0, 0], 0.5]], [23.38, 40.6501, 42.2202]], ['task and centering', [[[1, 1, 1], [10, 40, -20], [2, 1], [0, 30, 30], 0.3]], [-62.5399, 148.4425, -29.151]], ['straight arm singular', [[[1, 1, 1], [0, 0, 0], [2, 1], [0, 0, 0], 0.5]], 'singular'], ['behind base', [[[1, 1, 1], [120, 30, 20], [-2, 0.5], [90, 0, 0], 0.4]], [75.3463, 86.5441, 80.8124]], ['small error', [[[1.2, 0.8, 0.5], [45, -30, 15], [1.6, 1.1], [45, -30, 15], 0.0]], [102.7802, -138.4201, 15.5818]], ['asymmetric centre', [[[1, 1, 1], [5, 80, -40], [1.2, 1.9], [10, 20, 30], 0.8]], [-22.1921, 110.3115, 3.6813]]], [['task only', [[[1, 1, 1], [20, 30, 40], [1.5, 1.5], [20, 30, 40], 0.0]], [-9.6761, 48.859, 73.9791]], ['centering only', [[[1, 1, 1], [20, 30, 40], [1.0911, 2.3209], [0, 0, 0], 0.5]], [23.38, 40.6501, 42.2202]], ['task and centering', [[[1, 1, 1], [10, 40, -20], [2, 1], [0, 30, 30], 0.3]], [-62.5399, 148.4425, -29.151]], ['straight arm singular', [[[1, 1, 1], [0, 0, 0], [2, 1], [0, 0, 0], 0.5]], 'singular'], ['unequal links', [[[2, 1, 0.5], [30, -45, 60], [1.5, 1], [0, 0, 0], 0.2]], [87.5837, -214.0176, 178.4237]], ['negative config', [[[1, 1.5, 0.7], [-30, -20, -60], [1, -2], [0, 10, -10], 1.0]], [-7.4068, -55.9156, -92.0392]], ['strong centering', [[[1, 1, 1], [60, 60, 60], [-1, 1.5], [0, 0, 0], 2.0]], [43.7121, 92.5758, 40.7197]]], [['straight arm singular', [[[1, 1, 1], [0, 0, 0], [2, 1], [0, 0, 0], 0.5]], 'singular'], ['unequal links', [[[2, 1, 0.5], [30, -45, 60], [1.5, 1], [0, 0, 0], 0.2]], [87.5837, -214.0176, 178.4237]], ['negative config', [[[1, 1.5, 0.7], [-30, -20, -60], [1, -2], [0, 10, -10], 1.0]], [-7.4068, -55.9156, -92.0392]], ['strong centering', [[[1, 1, 1], [60, 60, 60], [-1, 1.5], [0, 0, 0], 2.0]], [43.7121, 92.5758, 40.7197]], ['behind base', [[[1, 1, 1], [120, 30, 20], [-2, 0.5], [90, 0, 0], 0.4]], [75.3463, 86.5441, 80.8124]], ['small error', [[[1.2, 0.8, 0.5], [45, -30, 15], [1.6, 1.1], [45, -30, 15], 0.0]], [102.7802, -138.4201, 15.5818]], ['asymmetric centre', [[[1, 1, 1], [5, 80, -40], [1.2, 1.9], [10, 20, 30], 0.8]], [-22.1921, 110.3115, 3.6813]]]]\nfor label, args, expected in fixtures[N-1]:\n    check(label, solve(*args), expected)\nprint(json.dumps({\"observations\": observations, \"passed\": all(x[\"passed\"] for x in observations)}, ensure_ascii=False))\nraise SystemExit(0 if all(x[\"passed\"] for x in observations) else 1)\n"},"fixed":{"sha256":"2d5cec270683ca06a09674580ce1d3b81b6f8e23e3f10e4553c893fdaa4d2cdc","source":"\"\"\"Failure Map reference implementation. Python standard library only.\"\"\"\nimport json\nimport math\nN = 1\nobservations = []\ndef solve(x):\n    ls,q,t,qc,k=x\n    qr=[math.radians(v) for v in q]\n    cum=[sum(qr[:i+1]) for i in range(3)]\n    px=sum(ls[i]*math.cos(cum[i]) for i in range(3))\n    py=sum(ls[i]*math.sin(cum[i]) for i in range(3))\n    J=[[-sum(ls[j]*math.sin(cum[j]) for j in range(i,3)) for i in range(3)],\n       [sum(ls[j]*math.cos(cum[j]) for j in range(i,3)) for i in range(3)]]\n    a=sum(v*v for v in J[0])\n    b=sum(J[0][i]*J[1][i] for i in range(3))\n    c=sum(v*v for v in J[1])\n    det=a*c-b*b\n    if abs(det)<1e-12: return 'singular'\n    inv=[[c/det,-b/det],[-b/det,a/det]]\n    P=[[J[0][i]*inv[0][0]+J[1][i]*inv[1][0],J[0][i]*inv[0][1]+J[1][i]*inv[1][1]] for i in range(3)]\n    e=[t[0]-px,t[1]-py]\n    z=[k*math.radians(qc[i]-q[i]) for i in range(3)]\n    N=[[(1.0 if i==j else 0.0)-sum(P[i][r]*J[r][j] for r in range(2)) for j in range(3)] for i in range(3)]\n    dq=[P[i][0]*e[0]+P[i][1]*e[1]+sum(N[i][j]*z[j] for j in range(3)) for i in range(3)]\n    return [round(q[i]+math.degrees(dq[i]),4) for i in range(3)]\ndef check(label, actual, expected):\n    observations.append({\"check\": label, \"actual\": actual, \"expected\": expected, \"passed\": actual == expected})\nfixtures = [[['task only', [[[1, 1, 1], [20, 30, 40], [1.5, 1.5], [20, 30, 40], 0.0]], [-9.6761, 48.859, 73.9791]], ['centering only', [[[1, 1, 1], [20, 30, 40], [1.0911, 2.3209], [0, 0, 0], 0.5]], [23.38, 40.6501, 42.2202]], ['task and centering', [[[1, 1, 1], [10, 40, -20], [2, 1], [0, 30, 30], 0.3]], [-62.5399, 148.4425, -29.151]], ['straight arm singular', [[[1, 1, 1], [0, 0, 0], [2, 1], [0, 0, 0], 0.5]], 'singular'], ['unequal links', [[[2, 1, 0.5], [30, -45, 60], [1.5, 1], [0, 0, 0], 0.2]], [87.5837, -214.0176, 178.4237]], ['negative config', [[[1, 1.5, 0.7], [-30, -20, -60], [1, -2], [0, 10, -10], 1.0]], [-7.4068, -55.9156, -92.0392]], ['strong centering', [[[1, 1, 1], [60, 60, 60], [-1, 1.5], [0, 0, 0], 2.0]], [43.7121, 92.5758, 40.7197]]], [['centering only', [[[1, 1, 1], [20, 30, 40], [1.0911, 2.3209], [0, 0, 0], 0.5]], [23.38, 40.6501, 42.2202]], ['unequal links', [[[2, 1, 0.5], [30, -45, 60], [1.5, 1], [0, 0, 0], 0.2]], [87.5837, -214.0176, 178.4237]], ['negative config', [[[1, 1.5, 0.7], [-30, -20, -60], [1, -2], [0, 10, -10], 1.0]], [-7.4068, -55.9156, -92.0392]], ['strong centering', [[[1, 1, 1], [60, 60, 60], [-1, 1.5], [0, 0, 0], 2.0]], [43.7121, 92.5758, 40.7197]], ['behind base', [[[1, 1, 1], [120, 30, 20], [-2, 0.5], [90, 0, 0], 0.4]], [75.3463, 86.5441, 80.8124]], ['small error', [[[1.2, 0.8, 0.5], [45, -30, 15], [1.6, 1.1], [45, -30, 15], 0.0]], [102.7802, -138.4201, 15.5818]], ['asymmetric centre', [[[1, 1, 1], [5, 80, -40], [1.2, 1.9], [10, 20, 30], 0.8]], [-22.1921, 110.3115, 3.6813]]], [['task only', [[[1, 1, 1], [20, 30, 40], [1.5, 1.5], [20, 30, 40], 0.0]], [-9.6761, 48.859, 73.9791]], ['centering only', [[[1, 1, 1], [20, 30, 40], [1.0911, 2.3209], [0, 0, 0], 0.5]], [23.38, 40.6501, 42.2202]], ['task and centering', [[[1, 1, 1], [10, 40, -20], [2, 1], [0, 30, 30], 0.3]], [-62.5399, 148.4425, -29.151]], ['straight arm singular', [[[1, 1, 1], [0, 0, 0], [2, 1], [0, 0, 0], 0.5]], 'singular'], ['behind base', [[[1, 1, 1], [120, 30, 20], [-2, 0.5], [90, 0, 0], 0.4]], [75.3463, 86.5441, 80.8124]], ['small error', [[[1.2, 0.8, 0.5], [45, -30, 15], [1.6, 1.1], [45, -30, 15], 0.0]], [102.7802, -138.4201, 15.5818]], ['asymmetric centre', [[[1, 1, 1], [5, 80, -40], [1.2, 1.9], [10, 20, 30], 0.8]], [-22.1921, 110.3115, 3.6813]]], [['task only', [[[1, 1, 1], [20, 30, 40], [1.5, 1.5], [20, 30, 40], 0.0]], [-9.6761, 48.859, 73.9791]], ['centering only', [[[1, 1, 1], [20, 30, 40], [1.0911, 2.3209], [0, 0, 0], 0.5]], [23.38, 40.6501, 42.2202]], ['task and centering', [[[1, 1, 1], [10, 40, -20], [2, 1], [0, 30, 30], 0.3]], [-62.5399, 148.4425, -29.151]], ['straight arm singular', [[[1, 1, 1], [0, 0, 0], [2, 1], [0, 0, 0], 0.5]], 'singular'], ['unequal links', [[[2, 1, 0.5], [30, -45, 60], [1.5, 1], [0, 0, 0], 0.2]], [87.5837, -214.0176, 178.4237]], ['negative config', [[[1, 1.5, 0.7], [-30, -20, -60], [1, -2], [0, 10, -10], 1.0]], [-7.4068, -55.9156, -92.0392]], ['strong centering', [[[1, 1, 1], [60, 60, 60], [-1, 1.5], [0, 0, 0], 2.0]], [43.7121, 92.5758, 40.7197]]], [['straight arm singular', [[[1, 1, 1], [0, 0, 0], [2, 1], [0, 0, 0], 0.5]], 'singular'], ['unequal links', [[[2, 1, 0.5], [30, -45, 60], [1.5, 1], [0, 0, 0], 0.2]], [87.5837, -214.0176, 178.4237]], ['negative config', [[[1, 1.5, 0.7], [-30, -20, -60], [1, -2], [0, 10, -10], 1.0]], [-7.4068, -55.9156, -92.0392]], ['strong centering', [[[1, 1, 1], [60, 60, 60], [-1, 1.5], [0, 0, 0], 2.0]], [43.7121, 92.5758, 40.7197]], ['behind base', [[[1, 1, 1], [120, 30, 20], [-2, 0.5], [90, 0, 0], 0.4]], [75.3463, 86.5441, 80.8124]], ['small error', [[[1.2, 0.8, 0.5], [45, -30, 15], [1.6, 1.1], [45, -30, 15], 0.0]], [102.7802, -138.4201, 15.5818]], ['asymmetric centre', [[[1, 1, 1], [5, 80, -40], [1.2, 1.9], [10, 20, 30], 0.8]], [-22.1921, 110.3115, 3.6813]]]]\nfor label, args, expected in fixtures[N-1]:\n    check(label, solve(*args), expected)\nprint(json.dumps({\"observations\": observations, \"passed\": all(x[\"passed\"] for x in observations)}, ensure_ascii=False))\nraise SystemExit(0 if all(x[\"passed\"] for x in observations) else 1)\n"}},"limitations":"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.","method":"Deterministic executable model with adversarial boundary fixtures.","provenance":{"created_by":"Failure Map","dependencies":"Python standard library","family":"w2-inverse_kinematics_solvers-null-space-redundancy-gram-inverse","generated_at":"2026-09-29T14:51:05.865987+00:00","license":"CC0-1.0","python":"3.12.14","seed":1,"split":"open-access"},"relevance":"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.","repair":"Use [[c,-b],[-b,a]]/det.","root_cause":"The inverse of [[a,b],[b,c]] is written with +b off the diagonal.","sha256":"71cf41c26f5d622cd6f9805e60579a6106f1b4ac0156fc19a2327a4e38a0bfb7","title":"Pseudo-inverse uses a 2x2 inverse with the wrong off-diagonal sign · case 01","variant":1,"variant_policy":"Five numbered records share a model and may reuse boundary fixtures.","verification":{"attempt":{"elapsed_ms":43.053,"exit_code":1,"observations":[{"actual":[63.9671,83.6361,79.3254],"check":"task only","expected":[-9.6761,48.859,73.9791],"passed":false},{"actual":[184.2502,204.5182,150.516],"check":"centering only","expected":[23.38,40.6501,42.2202],"passed":false},{"actual":[-585.6195,-223.9154,-210.8146],"check":"task and centering","expected":[-62.5399,148.4425,-29.151],"passed":false},{"actual":"singular","check":"straight arm singular","expected":"singular","passed":true},{"actual":[-366.0645,-226.02,15.5946],"check":"unequal links","expected":[87.5837,-214.0176,178.4237],"passed":false},{"actual":[-466.2598,-440.7608,-256.7118],"check":"negative config","expected":[-7.4068,-55.9156,-92.0392],"passed":false},{"actual":[35.8081,120.7197,72.8157],"check":"strong centering","expected":[43.7121,92.5758,40.7197],"passed":false}],"passed":false,"stderr":"","stdout":"{\"observations\": [{\"check\": \"task only\", \"actual\": [63.9671, 83.6361, 79.3254], \"expected\": [-9.6761, 48.859, 73.9791], \"passed\": false}, {\"check\": \"centering only\", \"actual\": [184.2502, 204.5182, 150.516], \"expected\": [23.38, 40.6501, 42.2202], \"passed\": false}, {\"check\": \"task and centering\", \"actual\": [-585.6195, -223.9154, -210.8146], \"expected\": [-62.5399, 148.4425, -29.151], \"passed\": false}, {\"check\": \"straight arm singular\", \"actual\": \"singular\", \"expected\": \"singular\", \"passed\": true}, {\"check\": \"unequal links\", \"actual\": [-366.0645, -226.02, 15.5946], \"expected\": [87.5837, -214.0176, 178.4237], \"passed\": false}, {\"check\": \"negative config\", \"actual\": [-466.2598, -440.7608, -256.7118], \"expected\": [-7.4068, -55.9156, -92.0392], \"passed\": false}, {\"check\": \"strong centering\", \"actual\": [35.8081, 120.7197, 72.8157], \"expected\": [43.7121, 92.5758, 40.7197], \"passed\": false}], \"passed\": false}\n"},"broken":{"elapsed_ms":43.644,"exit_code":1,"observations":[{"actual":[-127.8864,-55.956,11.5466],"check":"task only","expected":[-9.6761,48.859,73.9791],"passed":false},{"actual":[437.1093,270.1021,109.709],"check":"centering only","expected":[23.38,40.6501,42.2202],"passed":false},{"actual":[312.8385,262.7011,101.2166],"check":"task and centering","expected":[-62.5399,148.4425,-29.151],"passed":false},{"actual":"singular","check":"straight arm singular","expected":"singular","passed":true},{"actual":[1190.7623,255.8642,310.5094],"check":"unequal links","expected":[87.5837,-214.0176,178.4237],"passed":false},{"actual":[-795.4526,-475.2061,-53.5538],"check":"negative config","expected":[-7.4068,-55.9156,-92.0392],"passed":false},{"actual":[997.7274,849.5834,320.7197],"check":"strong centering","expected":[43.7121,92.5758,40.7197],"passed":false}],"passed":false,"stderr":"","stdout":"{\"observations\": [{\"check\": \"task only\", \"actual\": [-127.8864, -55.956, 11.5466], \"expected\": [-9.6761, 48.859, 73.9791], \"passed\": false}, {\"check\": \"centering only\", \"actual\": [437.1093, 270.1021, 109.709], \"expected\": [23.38, 40.6501, 42.2202], \"passed\": false}, {\"check\": \"task and centering\", \"actual\": [312.8385, 262.7011, 101.2166], \"expected\": [-62.5399, 148.4425, -29.151], \"passed\": false}, {\"check\": \"straight arm singular\", \"actual\": \"singular\", \"expected\": \"singular\", \"passed\": true}, {\"check\": \"unequal links\", \"actual\": [1190.7623, 255.8642, 310.5094], \"expected\": [87.5837, -214.0176, 178.4237], \"passed\": false}, {\"check\": \"negative config\", \"actual\": [-795.4526, -475.2061, -53.5538], \"expected\": [-7.4068, -55.9156, -92.0392], \"passed\": false}, {\"check\": \"strong centering\", \"actual\": [997.7274, 849.5834, 320.7197], \"expected\": [43.7121, 92.5758, 40.7197], \"passed\": false}], \"passed\": false}\n"},"fixed":{"elapsed_ms":43.062,"exit_code":0,"observations":[{"actual":[-9.6761,48.859,73.9791],"check":"task only","expected":[-9.6761,48.859,73.9791],"passed":true},{"actual":[23.38,40.6501,42.2202],"check":"centering only","expected":[23.38,40.6501,42.2202],"passed":true},{"actual":[-62.5399,148.4425,-29.151],"check":"task and centering","expected":[-62.5399,148.4425,-29.151],"passed":true},{"actual":"singular","check":"straight arm singular","expected":"singular","passed":true},{"actual":[87.5837,-214.0176,178.4237],"check":"unequal links","expected":[87.5837,-214.0176,178.4237],"passed":true},{"actual":[-7.4068,-55.9156,-92.0392],"check":"negative config","expected":[-7.4068,-55.9156,-92.0392],"passed":true},{"actual":[43.7121,92.5758,40.7197],"check":"strong centering","expected":[43.7121,92.5758,40.7197],"passed":true}],"passed":true,"stderr":"","stdout":"{\"observations\": [{\"check\": \"task only\", \"actual\": [-9.6761, 48.859, 73.9791], \"expected\": [-9.6761, 48.859, 73.9791], \"passed\": true}, {\"check\": \"centering only\", \"actual\": [23.38, 40.6501, 42.2202], \"expected\": [23.38, 40.6501, 42.2202], \"passed\": true}, {\"check\": \"task and centering\", \"actual\": [-62.5399, 148.4425, -29.151], \"expected\": [-62.5399, 148.4425, -29.151], \"passed\": true}, {\"check\": \"straight arm singular\", \"actual\": \"singular\", \"expected\": \"singular\", \"passed\": true}, {\"check\": \"unequal links\", \"actual\": [87.5837, -214.0176, 178.4237], \"expected\": [87.5837, -214.0176, 178.4237], \"passed\": true}, {\"check\": \"negative config\", \"actual\": [-7.4068, -55.9156, -92.0392], \"expected\": [-7.4068, -55.9156, -92.0392], \"passed\": true}, {\"check\": \"strong centering\", \"actual\": [43.7121, 92.5758, 40.7197], \"expected\": [43.7121, 92.5758, 40.7197], \"passed\": true}], \"passed\": true}\n"}},"verified":true,"visibility":"public"}