{"abstract":"Every joint is commanded 2*offset away from the intended angle.","category":"Inverse kinematics solvers","checks":7,"contract":"Input [geo,off,dirs,ratio,lines,lims], all per-joint lists: IK joint angles (degrees) become encoder counts per joint as counts = floor(dirs*(geo-off)*ratio/360*lines*4 + 0.5) (quadrature gives 4 counts per line, half rounds up). lims holds inclusive [lo,hi] count limits; the first violating joint returns [\"limit\", i, counts].","contract_signature":"x","evaluation_group":"w2-inverse_kinematics_solvers-joint-actuator-mapping","failed_approach":"off - geo flips the direction of every joint.","family":"w2-inverse_kinematics_solvers-joint-actuator-mapping-zero-offset-sign","id":"FA-88296","implementations":{"attempt":{"sha256":"170e38353c774411ccb30abaee76afc47b1722dbc5d63b81cfe4325a17765d16","source":"\"\"\"Failure Map reference implementation. Python standard library only.\"\"\"\nimport json\nimport math\nN = 1\nobservations = []\ndef solve(x):\n    geo,off,dirs,ratio,lines,lims=x\n    out=[]\n    for i in range(len(geo)):\n        m=dirs[i]*(off[i]-geo[i])*ratio[i]\n        cnt=math.floor(m/360.0*lines[i]*4+0.5)\n        lo,hi=lims[i]\n        if cnt<lo or cnt>hi: return ['limit',i,cnt]\n        out.append(cnt)\n    return out\ndef check(label, actual, expected):\n    observations.append({\"check\": label, \"actual\": actual, \"expected\": expected, \"passed\": actual == expected})\nfixtures = [[['two joints nominal', [[[10, 20], [5, -5], [1, -1], [50, 30], [100, 100], [[-100000, 100000], [-100000, 100000]]]], [278, -833]], ['half count rounding up', [[[45], [0], [1], [1], [5], [[-10, 10]]]], [3]], ['negative fractional count', [[[-45], [0], [1], [1], [5.4], [[-10, 10]]]], [-3]], ['negative half rounds up', [[[-45], [0], [1], [1], [11], [[-10, 10]]]], [-5]], ['reversed joint with offset', [[[30], [90], [-1], [2], [180], [[-10000, 10000]]]], [240]], ['limit exceeded', [[[90, 0], [0, 0], [1, 1], [100, 1], [1000, 1000], [[-1000, 1000], [-10, 10]]]], ['limit', 0, 100000]], ['within limit exactly', [[[0, 9], [0, 0], [1, 1], [1, 1], [10, 10], [[-1, 1], [-1, 1]]]], [0, 1]]], [['half count rounding up', [[[45], [0], [1], [1], [5], [[-10, 10]]]], [3]], ['reversed joint with offset', [[[30], [90], [-1], [2], [180], [[-10000, 10000]]]], [240]], ['limit exceeded', [[[90, 0], [0, 0], [1, 1], [100, 1], [1000, 1000], [[-1000, 1000], [-10, 10]]]], ['limit', 0, 100000]], ['within limit exactly', [[[0, 9], [0, 0], [1, 1], [1, 1], [10, 10], [[-1, 1], [-1, 1]]]], [0, 1]], ['three joint arm', [[[45, -30, 12], [0, 10, -3], [1, -1, 1], [100, 80, 50], [500, 500, 256], [[-1000000, 1000000], [-1000000, 1000000], [-1000000, 1000000]]]], [25000, 17778, 2133]], ['gear down joint', [[[180, 45], [0, 0], [1, 1], [0.5, 4], [100, 100], [[-100000, 100000], [-100000, 100000]]]], [100, 200]], ['offset makes negative', [[[10], [40], [1], [3], [360], [[-5000, 5000]]]], [-360]]], [['two joints nominal', [[[10, 20], [5, -5], [1, -1], [50, 30], [100, 100], [[-100000, 100000], [-100000, 100000]]]], [278, -833]], ['negative fractional count', [[[-45], [0], [1], [1], [5.4], [[-10, 10]]]], [-3]], ['three joint arm', [[[45, -30, 12], [0, 10, -3], [1, -1, 1], [100, 80, 50], [500, 500, 256], [[-1000000, 1000000], [-1000000, 1000000], [-1000000, 1000000]]]], [25000, 17778, 2133]], ['gear down joint', [[[180, 45], [0, 0], [1, 1], [0.5, 4], [100, 100], [[-100000, 100000], [-100000, 100000]]]], [100, 200]], ['offset makes negative', [[[10], [40], [1], [3], [360], [[-5000, 5000]]]], [-360]], ['motor degrees small counts large', [[[5], [0], [1], [100], [1000], [[-5000, 5000]]]], ['limit', 0, 5556]], ['geo within range counts out', [[[20], [0], [1], [50], [100], [[-100, 1000]]]], ['limit', 0, 1111]]], [['two joints nominal', [[[10, 20], [5, -5], [1, -1], [50, 30], [100, 100], [[-100000, 100000], [-100000, 100000]]]], [278, -833]], ['half count rounding up', [[[45], [0], [1], [1], [5], [[-10, 10]]]], [3]], ['negative fractional count', [[[-45], [0], [1], [1], [5.4], [[-10, 10]]]], [-3]], ['negative half rounds up', [[[-45], [0], [1], [1], [11], [[-10, 10]]]], [-5]], ['reversed joint with offset', [[[30], [90], [-1], [2], [180], [[-10000, 10000]]]], [240]], ['offset makes negative', [[[10], [40], [1], [3], [360], [[-5000, 5000]]]], [-360]], ['geo within range counts out', [[[20], [0], [1], [50], [100], [[-100, 1000]]]], ['limit', 0, 1111]]], [['two joints nominal', [[[10, 20], [5, -5], [1, -1], [50, 30], [100, 100], [[-100000, 100000], [-100000, 100000]]]], [278, -833]], ['negative half rounds up', [[[-45], [0], [1], [1], [11], [[-10, 10]]]], [-5]], ['reversed joint with offset', [[[30], [90], [-1], [2], [180], [[-10000, 10000]]]], [240]], ['limit exceeded', [[[90, 0], [0, 0], [1, 1], [100, 1], [1000, 1000], [[-1000, 1000], [-10, 10]]]], ['limit', 0, 100000]], ['within limit exactly', [[[0, 9], [0, 0], [1, 1], [1, 1], [10, 10], [[-1, 1], [-1, 1]]]], [0, 1]], ['three joint arm', [[[45, -30, 12], [0, 10, -3], [1, -1, 1], [100, 80, 50], [500, 500, 256], [[-1000000, 1000000], [-1000000, 1000000], [-1000000, 1000000]]]], [25000, 17778, 2133]], ['gear down joint', [[[180, 45], [0, 0], [1, 1], [0.5, 4], [100, 100], [[-100000, 100000], [-100000, 100000]]]], [100, 200]]]]\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":"868d836e18df7b9f4516857d87217b6e4556916127828400cbf63ec1504c1a40","source":"\"\"\"Failure Map reference implementation. Python standard library only.\"\"\"\nimport json\nimport math\nN = 1\nobservations = []\ndef solve(x):\n    geo,off,dirs,ratio,lines,lims=x\n    out=[]\n    for i in range(len(geo)):\n        m=dirs[i]*(geo[i]+off[i])*ratio[i]\n        cnt=math.floor(m/360.0*lines[i]*4+0.5)\n        lo,hi=lims[i]\n        if cnt<lo or cnt>hi: return ['limit',i,cnt]\n        out.append(cnt)\n    return out\ndef check(label, actual, expected):\n    observations.append({\"check\": label, \"actual\": actual, \"expected\": expected, \"passed\": actual == expected})\nfixtures = [[['two joints nominal', [[[10, 20], [5, -5], [1, -1], [50, 30], [100, 100], [[-100000, 100000], [-100000, 100000]]]], [278, -833]], ['half count rounding up', [[[45], [0], [1], [1], [5], [[-10, 10]]]], [3]], ['negative fractional count', [[[-45], [0], [1], [1], [5.4], [[-10, 10]]]], [-3]], ['negative half rounds up', [[[-45], [0], [1], [1], [11], [[-10, 10]]]], [-5]], ['reversed joint with offset', [[[30], [90], [-1], [2], [180], [[-10000, 10000]]]], [240]], ['limit exceeded', [[[90, 0], [0, 0], [1, 1], [100, 1], [1000, 1000], [[-1000, 1000], [-10, 10]]]], ['limit', 0, 100000]], ['within limit exactly', [[[0, 9], [0, 0], [1, 1], [1, 1], [10, 10], [[-1, 1], [-1, 1]]]], [0, 1]]], [['half count rounding up', [[[45], [0], [1], [1], [5], [[-10, 10]]]], [3]], ['reversed joint with offset', [[[30], [90], [-1], [2], [180], [[-10000, 10000]]]], [240]], ['limit exceeded', [[[90, 0], [0, 0], [1, 1], [100, 1], [1000, 1000], [[-1000, 1000], [-10, 10]]]], ['limit', 0, 100000]], ['within limit exactly', [[[0, 9], [0, 0], [1, 1], [1, 1], [10, 10], [[-1, 1], [-1, 1]]]], [0, 1]], ['three joint arm', [[[45, -30, 12], [0, 10, -3], [1, -1, 1], [100, 80, 50], [500, 500, 256], [[-1000000, 1000000], [-1000000, 1000000], [-1000000, 1000000]]]], [25000, 17778, 2133]], ['gear down joint', [[[180, 45], [0, 0], [1, 1], [0.5, 4], [100, 100], [[-100000, 100000], [-100000, 100000]]]], [100, 200]], ['offset makes negative', [[[10], [40], [1], [3], [360], [[-5000, 5000]]]], [-360]]], [['two joints nominal', [[[10, 20], [5, -5], [1, -1], [50, 30], [100, 100], [[-100000, 100000], [-100000, 100000]]]], [278, -833]], ['negative fractional count', [[[-45], [0], [1], [1], [5.4], [[-10, 10]]]], [-3]], ['three joint arm', [[[45, -30, 12], [0, 10, -3], [1, -1, 1], [100, 80, 50], [500, 500, 256], [[-1000000, 1000000], [-1000000, 1000000], [-1000000, 1000000]]]], [25000, 17778, 2133]], ['gear down joint', [[[180, 45], [0, 0], [1, 1], [0.5, 4], [100, 100], [[-100000, 100000], [-100000, 100000]]]], [100, 200]], ['offset makes negative', [[[10], [40], [1], [3], [360], [[-5000, 5000]]]], [-360]], ['motor degrees small counts large', [[[5], [0], [1], [100], [1000], [[-5000, 5000]]]], ['limit', 0, 5556]], ['geo within range counts out', [[[20], [0], [1], [50], [100], [[-100, 1000]]]], ['limit', 0, 1111]]], [['two joints nominal', [[[10, 20], [5, -5], [1, -1], [50, 30], [100, 100], [[-100000, 100000], [-100000, 100000]]]], [278, -833]], ['half count rounding up', [[[45], [0], [1], [1], [5], [[-10, 10]]]], [3]], ['negative fractional count', [[[-45], [0], [1], [1], [5.4], [[-10, 10]]]], [-3]], ['negative half rounds up', [[[-45], [0], [1], [1], [11], [[-10, 10]]]], [-5]], ['reversed joint with offset', [[[30], [90], [-1], [2], [180], [[-10000, 10000]]]], [240]], ['offset makes negative', [[[10], [40], [1], [3], [360], [[-5000, 5000]]]], [-360]], ['geo within range counts out', [[[20], [0], [1], [50], [100], [[-100, 1000]]]], ['limit', 0, 1111]]], [['two joints nominal', [[[10, 20], [5, -5], [1, -1], [50, 30], [100, 100], [[-100000, 100000], [-100000, 100000]]]], [278, -833]], ['negative half rounds up', [[[-45], [0], [1], [1], [11], [[-10, 10]]]], [-5]], ['reversed joint with offset', [[[30], [90], [-1], [2], [180], [[-10000, 10000]]]], [240]], ['limit exceeded', [[[90, 0], [0, 0], [1, 1], [100, 1], [1000, 1000], [[-1000, 1000], [-10, 10]]]], ['limit', 0, 100000]], ['within limit exactly', [[[0, 9], [0, 0], [1, 1], [1, 1], [10, 10], [[-1, 1], [-1, 1]]]], [0, 1]], ['three joint arm', [[[45, -30, 12], [0, 10, -3], [1, -1, 1], [100, 80, 50], [500, 500, 256], [[-1000000, 1000000], [-1000000, 1000000], [-1000000, 1000000]]]], [25000, 17778, 2133]], ['gear down joint', [[[180, 45], [0, 0], [1, 1], [0.5, 4], [100, 100], [[-100000, 100000], [-100000, 100000]]]], [100, 200]]]]\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-joint-actuator-mapping-zero-offset-sign","generated_at":"2026-09-29T14:51:06.833532+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.","root_cause":"The mapping uses geo+off although the offset is the geometric angle of the encoder zero.","sha256":"fc2e12763be307c1209f8d7556042c3896a55b420511e54fb6ee0faef2a474ac","title":"Joint zero offset is added instead of removed · case 01","variant":1,"variant_policy":"Five numbered records share a model and may reuse boundary fixtures.","verified":true,"visibility":"public","verification":{"attempt":{"elapsed_ms":41.052,"exit_code":1,"observations":[{"actual":[-278,833],"check":"two joints nominal","expected":[278,-833],"passed":false},{"actual":[-2],"check":"half count rounding up","expected":[3],"passed":false},{"actual":[3],"check":"negative fractional count","expected":[-3],"passed":false},{"actual":[6],"check":"negative half rounds up","expected":[-5],"passed":false},{"actual":[-240],"check":"reversed joint with offset","expected":[240],"passed":false},{"actual":["limit",0,-100000],"check":"limit exceeded","expected":["limit",0,100000],"passed":false},{"actual":[0,-1],"check":"within limit exactly","expected":[0,1],"passed":false}],"passed":false,"stderr":"","stdout":"{\"observations\": [{\"check\": \"two joints nominal\", \"actual\": [-278, 833], \"expected\": [278, -833], \"passed\": false}, {\"check\": \"half count rounding up\", \"actual\": [-2], \"expected\": [3], \"passed\": false}, {\"check\": \"negative fractional count\", \"actual\": [3], \"expected\": [-3], \"passed\": false}, {\"check\": \"negative half rounds up\", \"actual\": [6], \"expected\": [-5], \"passed\": false}, {\"check\": \"reversed joint with offset\", \"actual\": [-240], \"expected\": [240], \"passed\": false}, {\"check\": \"limit exceeded\", \"actual\": [\"limit\", 0, -100000], \"expected\": [\"limit\", 0, 100000], \"passed\": false}, {\"check\": \"within limit exactly\", \"actual\": [0, -1], \"expected\": [0, 1], \"passed\": false}], \"passed\": false}\n"},"broken":{"elapsed_ms":41.125,"exit_code":1,"observations":[{"actual":[833,-500],"check":"two joints nominal","expected":[278,-833],"passed":false},{"actual":[3],"check":"half count rounding up","expected":[3],"passed":true},{"actual":[-3],"check":"negative fractional count","expected":[-3],"passed":true},{"actual":[-5],"check":"negative half rounds up","expected":[-5],"passed":true},{"actual":[-480],"check":"reversed joint with offset","expected":[240],"passed":false},{"actual":["limit",0,100000],"check":"limit exceeded","expected":["limit",0,100000],"passed":true},{"actual":[0,1],"check":"within limit exactly","expected":[0,1],"passed":true}],"passed":false,"stderr":"","stdout":"{\"observations\": [{\"check\": \"two joints nominal\", \"actual\": [833, -500], \"expected\": [278, -833], \"passed\": false}, {\"check\": \"half count rounding up\", \"actual\": [3], \"expected\": [3], \"passed\": true}, {\"check\": \"negative fractional count\", \"actual\": [-3], \"expected\": [-3], \"passed\": true}, {\"check\": \"negative half rounds up\", \"actual\": [-5], \"expected\": [-5], \"passed\": true}, {\"check\": \"reversed joint with offset\", \"actual\": [-480], \"expected\": [240], \"passed\": false}, {\"check\": \"limit exceeded\", \"actual\": [\"limit\", 0, 100000], \"expected\": [\"limit\", 0, 100000], \"passed\": true}, {\"check\": \"within limit exactly\", \"actual\": [0, 1], \"expected\": [0, 1], \"passed\": true}], \"passed\": false}\n"}},"member_only":{"stages":["fixed"],"fields":["implementations.fixed","verification.fixed","harness","repair"],"note":"The verified repair, its recorded checks, the repair description, and the scoring harness are available to members."}}