{"abstract":"After an unreachable waypoint a branch change is no longer counted as a flip.","category":"Inverse kinematics solvers","checks":7,"contract":"Input [l1,l2,q0,targets,maxjump]: planar 2R arm with continuous joints following a list of targets from joint state q0 (degrees). For each target compute the elbow +/- solutions; unreachable targets append \"hold\". Choose the solution with the smallest max wrapped joint change from the previous state; if that change exceeds maxjump append \"jump\" and keep the state. Otherwise unwrap the solution to lie within 180 of the previous angles, append it (3 decimals) and count a flip whenever the elbow sign differs from the last accepted one. Return [outputs, flips].","evaluation_group":"w2-inverse_kinematics_solvers-trajectory-branch-continuity","failed_approach":"Resetting the joint state to q0 on dropout makes the next choice relative to the home pose.","family":"w2-inverse_kinematics_solvers-trajectory-branch-continuity-dropout-state-reset","id":"FA-88236","implementations":{"attempt":{"sha256":"90fd397e6f2676e1fe1ee6268dc449f37dd46dcd2da043ee8d195aff2a4fc246","source":"\"\"\"Failure Map reference implementation. Python standard library only.\"\"\"\nimport json\nimport math\nN = 1\nobservations = []\ndef solve(x):\n    l1,l2,q0,targets,maxjump=x\n    prev=list(q0)\n    out=[]\n    flips=0\n    branch=None\n    for px,py in targets:\n        c=(px*px+py*py-l1*l1-l2*l2)/(2*l1*l2)\n        if abs(c)>1.0:\n            out.append('hold')\n            prev=list(q0)\n            continue\n        sols=[]\n        for sgn in (1,-1):\n            s=sgn*math.sqrt(1-c*c)\n            t2=math.degrees(math.atan2(s,c))\n            t1=math.degrees(math.atan2(py,px)-math.atan2(l2*s,l1+l2*c))\n            sols.append([sgn,t1,t2])\n        def dist(sol):\n            return max(abs((sol[1]-prev[0]+180.0)%360.0-180.0),abs((sol[2]-prev[1]+180.0)%360.0-180.0))\n        best=min(sols,key=dist)\n        if dist(best)>maxjump:\n            out.append('jump')\n            continue\n        if branch is not None and best[0]!=branch: flips+=1\n        branch=best[0]\n        t1=prev[0]+((best[1]-prev[0]+180.0)%360.0-180.0)\n        t2=prev[1]+((best[2]-prev[1]+180.0)%360.0-180.0)\n        prev=[t1,t2]\n        out.append([round(t1,3),round(t2,3)])\n    return [out,flips]\ndef check(label, actual, expected):\n    observations.append({\"check\": label, \"actual\": actual, \"expected\": expected, \"passed\": actual == expected})\nfixtures = [[['smooth arc', [[1, 1, [0, 90], [[1, 1], [0.9, 1.1], [0.8, 1.2]], 30]], [[[0.0, 90.0], [5.997, 89.427], [12.456, 87.708]], 0]], ['seam crossing', [[1, 1, [170, 20], [[-1.5, 0.3], [-1.5, -0.3], [-1.4, -0.6]], 40]], [['jump', 'jump', 'jump'], 0]], ['multi-turn start', [[1, 1, [360, 90], [[1, 1], [1.1, 0.9]], 30]], [[[360.0, 90.0], [354.576, 89.427]], 0]], ['dropout in middle', [[1, 1, [0, 90], [[1, 1], [3, 0], [0.9, 1.1]], 30]], [[[0.0, 90.0], 'hold', [5.997, 89.427]], 0]], ['dropout then branch change', [[1, 1, [0, 60], [[1.5, 0.8], [3, 3], [1.6, -0.6]], 200]], [[[-3.716, 63.577], 'hold', [-51.862, 62.613]], 0]], ['large jump rejected', [[1, 1, [0, 90], [[1, 1], [-1, -1], [1, 0.9]], 20]], [[[0.0, 90.0], 'jump', [-5.738, 95.451]], 0]], ['dropout across branch change', [[1, 1, [-93, 83], [[1.9, -0.3], [3, 3], [-1.5, -1.3]], 120]], [[[-24.867, 31.788], 'hold', [-132.051, -14.07]], 1]]], [['dropout in middle', [[1, 1, [0, 90], [[1, 1], [3, 0], [0.9, 1.1]], 30]], [[[0.0, 90.0], 'hold', [5.997, 89.427]], 0]], ['dropout then branch change', [[1, 1, [0, 60], [[1.5, 0.8], [3, 3], [1.6, -0.6]], 200]], [[[-3.716, 63.577], 'hold', [-51.862, 62.613]], 0]], ['large jump rejected', [[1, 1, [0, 90], [[1, 1], [-1, -1], [1, 0.9]], 20]], [[[0.0, 90.0], 'jump', [-5.738, 95.451]], 0]], ['jump exactly at limit', [[2, 1, [0, 0], [[3, 0], [2, 1]], 90]], [[[0.0, 0.0], [0.0, 90.0]], 0]], ['flip through straight', [[1, 1, [0, 30], [[1.9, 0.3], [2, 0], [1.9, -0.3], [1.8, -0.6]], 60]], [[[-6.922, 31.788], [0.0, 0.0], [-24.867, 31.788], [-36.87, 36.87]], 0]], ['start near down branch', [[1, 1, [60, -60], [[1.2, 1.0], [1.3, 0.9]], 50]], [[[78.451, -77.291], [72.456, -75.522]], 0]], ['down to up flip', [[1, 1, [69, -23], [[0.3, -0.8], [1.9, -0.9], [0.1, 0.9]], 164]], [[[-4.734, -129.42], 'hold', [20.581, -233.843]], 1]]], [['jump exactly at limit', [[2, 1, [0, 0], [[3, 0], [2, 1]], 90]], [[[0.0, 0.0], [0.0, 90.0]], 0]], ['flip through straight', [[1, 1, [0, 30], [[1.9, 0.3], [2, 0], [1.9, -0.3], [1.8, -0.6]], 60]], [[[-6.922, 31.788], [0.0, 0.0], [-24.867, 31.788], [-36.87, 36.87]], 0]], ['start near down branch', [[1, 1, [60, -60], [[1.2, 1.0], [1.3, 0.9]], 50]], [[[78.451, -77.291], [72.456, -75.522]], 0]], ['big jump budget', [[1, 1.5, [0, 0], [[-1, 1.5], [1.5, -1], [0.5, 2]], 360]], [[[67.38, 90.0], [-90.0, 90.0], [32.65, 70.529]], 0]], ['negative seam elbow', [[1, 1, [-170, -20], [[-1.5, -0.3], [-1.5, 0.3], [-1.3, 0.8]], 45]], [['jump', 'jump', 'jump'], 0]], ['all unreachable', [[1, 1, [0, 0], [[3, 3], [0, 5]], 30]], [['hold', 'hold'], 0]], ['dropout near base', [[1, 1, [146, 142], [[-0.1, -1.0], [3, 3], [-0.3, 0.2]], 120]], [[[204.455, 119.67], 'hold', [225.924, 200.772]], 1]]], [['big jump budget', [[1, 1.5, [0, 0], [[-1, 1.5], [1.5, -1], [0.5, 2]], 360]], [[[67.38, 90.0], [-90.0, 90.0], [32.65, 70.529]], 0]], ['negative seam elbow', [[1, 1, [-170, -20], [[-1.5, -0.3], [-1.5, 0.3], [-1.3, 0.8]], 45]], [['jump', 'jump', 'jump'], 0]], ['all unreachable', [[1, 1, [0, 0], [[3, 3], [0, 5]], 30]], [['hold', 'hold'], 0]], ['jump then recover', [[1, 1, [0, 120], [[0.2, 1.0], [1.8, 0.2], [0.3, 1.0]], 60]], [[[19.347, 118.685], 'jump', [14.768, 117.065]], 0]], ['second target flips', [[1.5, 1, [0, 45], [[2, 1.2], [2.2, -0.4]], 150]], [[[13.925, 43.114], [-31.604, 54.315]], 0]], ['dropout across branch change', [[1, 1, [-93, 83], [[1.9, -0.3], [3, 3], [-1.5, -1.3]], 120]], [[[-24.867, 31.788], 'hold', [-132.051, -14.07]], 1]], ['down to up flip', [[1, 1, [69, -23], [[0.3, -0.8], [1.9, -0.9], [0.1, 0.9]], 164]], [[[-4.734, -129.42], 'hold', [20.581, -233.843]], 1]]], [['jump then recover', [[1, 1, [0, 120], [[0.2, 1.0], [1.8, 0.2], [0.3, 1.0]], 60]], [[[19.347, 118.685], 'jump', [14.768, 117.065]], 0]], ['second target flips', [[1.5, 1, [0, 45], [[2, 1.2], [2.2, -0.4]], 150]], [[[13.925, 43.114], [-31.604, 54.315]], 0]], ['dropout across branch change', [[1, 1, [-93, 83], [[1.9, -0.3], [3, 3], [-1.5, -1.3]], 120]], [[[-24.867, 31.788], 'hold', [-132.051, -14.07]], 1]], ['down to up flip', [[1, 1, [69, -23], [[0.3, -0.8], [1.9, -0.9], [0.1, 0.9]], 164]], [[[-4.734, -129.42], 'hold', [20.581, -233.843]], 1]], ['wide sweep flips', [[1, 1, [-5, -54], [[0.1, -1.7], [0.7, 1.5], [-1.2, 0.5]], 154]], [[[-55.005, -63.256], [30.841, 68.284], [107.922, 98.917]], 1]], ['rejected then flip', [[1, 1, [171, 101], [[0.8, -1.3], [0.8, 0.7], [0.2, -1.1]], 56]], [['jump', 'jump', [224.293, 112.024]], 0]], ['rejection mid sweep', [[1, 1, [37, 154], [[0.4, 1.3], [-0.5, -0.6], [-0.8, 1.4]], 82]], [[[25.747, 94.301], 'jump', [83.474, 72.542]], 0]]]]\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":"352c9bd9edbb74a5ba034d409ce2e1d85999f991a452248a6814f78b540d43b2","source":"\"\"\"Failure Map reference implementation. Python standard library only.\"\"\"\nimport json\nimport math\nN = 1\nobservations = []\ndef solve(x):\n    l1,l2,q0,targets,maxjump=x\n    prev=list(q0)\n    out=[]\n    flips=0\n    branch=None\n    for px,py in targets:\n        c=(px*px+py*py-l1*l1-l2*l2)/(2*l1*l2)\n        if abs(c)>1.0:\n            out.append('hold')\n            branch=None\n            continue\n        sols=[]\n        for sgn in (1,-1):\n            s=sgn*math.sqrt(1-c*c)\n            t2=math.degrees(math.atan2(s,c))\n            t1=math.degrees(math.atan2(py,px)-math.atan2(l2*s,l1+l2*c))\n            sols.append([sgn,t1,t2])\n        def dist(sol):\n            return max(abs((sol[1]-prev[0]+180.0)%360.0-180.0),abs((sol[2]-prev[1]+180.0)%360.0-180.0))\n        best=min(sols,key=dist)\n        if dist(best)>maxjump:\n            out.append('jump')\n            continue\n        if branch is not None and best[0]!=branch: flips+=1\n        branch=best[0]\n        t1=prev[0]+((best[1]-prev[0]+180.0)%360.0-180.0)\n        t2=prev[1]+((best[2]-prev[1]+180.0)%360.0-180.0)\n        prev=[t1,t2]\n        out.append([round(t1,3),round(t2,3)])\n    return [out,flips]\ndef check(label, actual, expected):\n    observations.append({\"check\": label, \"actual\": actual, \"expected\": expected, \"passed\": actual == expected})\nfixtures = [[['smooth arc', [[1, 1, [0, 90], [[1, 1], [0.9, 1.1], [0.8, 1.2]], 30]], [[[0.0, 90.0], [5.997, 89.427], [12.456, 87.708]], 0]], ['seam crossing', [[1, 1, [170, 20], [[-1.5, 0.3], [-1.5, -0.3], [-1.4, -0.6]], 40]], [['jump', 'jump', 'jump'], 0]], ['multi-turn start', [[1, 1, [360, 90], [[1, 1], [1.1, 0.9]], 30]], [[[360.0, 90.0], [354.576, 89.427]], 0]], ['dropout in middle', [[1, 1, [0, 90], [[1, 1], [3, 0], [0.9, 1.1]], 30]], [[[0.0, 90.0], 'hold', [5.997, 89.427]], 0]], ['dropout then branch change', [[1, 1, [0, 60], [[1.5, 0.8], [3, 3], [1.6, -0.6]], 200]], [[[-3.716, 63.577], 'hold', [-51.862, 62.613]], 0]], ['large jump rejected', [[1, 1, [0, 90], [[1, 1], [-1, -1], [1, 0.9]], 20]], [[[0.0, 90.0], 'jump', [-5.738, 95.451]], 0]], ['dropout across branch change', [[1, 1, [-93, 83], [[1.9, -0.3], [3, 3], [-1.5, -1.3]], 120]], [[[-24.867, 31.788], 'hold', [-132.051, -14.07]], 1]]], [['dropout in middle', [[1, 1, [0, 90], [[1, 1], [3, 0], [0.9, 1.1]], 30]], [[[0.0, 90.0], 'hold', [5.997, 89.427]], 0]], ['dropout then branch change', [[1, 1, [0, 60], [[1.5, 0.8], [3, 3], [1.6, -0.6]], 200]], [[[-3.716, 63.577], 'hold', [-51.862, 62.613]], 0]], ['large jump rejected', [[1, 1, [0, 90], [[1, 1], [-1, -1], [1, 0.9]], 20]], [[[0.0, 90.0], 'jump', [-5.738, 95.451]], 0]], ['jump exactly at limit', [[2, 1, [0, 0], [[3, 0], [2, 1]], 90]], [[[0.0, 0.0], [0.0, 90.0]], 0]], ['flip through straight', [[1, 1, [0, 30], [[1.9, 0.3], [2, 0], [1.9, -0.3], [1.8, -0.6]], 60]], [[[-6.922, 31.788], [0.0, 0.0], [-24.867, 31.788], [-36.87, 36.87]], 0]], ['start near down branch', [[1, 1, [60, -60], [[1.2, 1.0], [1.3, 0.9]], 50]], [[[78.451, -77.291], [72.456, -75.522]], 0]], ['down to up flip', [[1, 1, [69, -23], [[0.3, -0.8], [1.9, -0.9], [0.1, 0.9]], 164]], [[[-4.734, -129.42], 'hold', [20.581, -233.843]], 1]]], [['jump exactly at limit', [[2, 1, [0, 0], [[3, 0], [2, 1]], 90]], [[[0.0, 0.0], [0.0, 90.0]], 0]], ['flip through straight', [[1, 1, [0, 30], [[1.9, 0.3], [2, 0], [1.9, -0.3], [1.8, -0.6]], 60]], [[[-6.922, 31.788], [0.0, 0.0], [-24.867, 31.788], [-36.87, 36.87]], 0]], ['start near down branch', [[1, 1, [60, -60], [[1.2, 1.0], [1.3, 0.9]], 50]], [[[78.451, -77.291], [72.456, -75.522]], 0]], ['big jump budget', [[1, 1.5, [0, 0], [[-1, 1.5], [1.5, -1], [0.5, 2]], 360]], [[[67.38, 90.0], [-90.0, 90.0], [32.65, 70.529]], 0]], ['negative seam elbow', [[1, 1, [-170, -20], [[-1.5, -0.3], [-1.5, 0.3], [-1.3, 0.8]], 45]], [['jump', 'jump', 'jump'], 0]], ['all unreachable', [[1, 1, [0, 0], [[3, 3], [0, 5]], 30]], [['hold', 'hold'], 0]], ['dropout near base', [[1, 1, [146, 142], [[-0.1, -1.0], [3, 3], [-0.3, 0.2]], 120]], [[[204.455, 119.67], 'hold', [225.924, 200.772]], 1]]], [['big jump budget', [[1, 1.5, [0, 0], [[-1, 1.5], [1.5, -1], [0.5, 2]], 360]], [[[67.38, 90.0], [-90.0, 90.0], [32.65, 70.529]], 0]], ['negative seam elbow', [[1, 1, [-170, -20], [[-1.5, -0.3], [-1.5, 0.3], [-1.3, 0.8]], 45]], [['jump', 'jump', 'jump'], 0]], ['all unreachable', [[1, 1, [0, 0], [[3, 3], [0, 5]], 30]], [['hold', 'hold'], 0]], ['jump then recover', [[1, 1, [0, 120], [[0.2, 1.0], [1.8, 0.2], [0.3, 1.0]], 60]], [[[19.347, 118.685], 'jump', [14.768, 117.065]], 0]], ['second target flips', [[1.5, 1, [0, 45], [[2, 1.2], [2.2, -0.4]], 150]], [[[13.925, 43.114], [-31.604, 54.315]], 0]], ['dropout across branch change', [[1, 1, [-93, 83], [[1.9, -0.3], [3, 3], [-1.5, -1.3]], 120]], [[[-24.867, 31.788], 'hold', [-132.051, -14.07]], 1]], ['down to up flip', [[1, 1, [69, -23], [[0.3, -0.8], [1.9, -0.9], [0.1, 0.9]], 164]], [[[-4.734, -129.42], 'hold', [20.581, -233.843]], 1]]], [['jump then recover', [[1, 1, [0, 120], [[0.2, 1.0], [1.8, 0.2], [0.3, 1.0]], 60]], [[[19.347, 118.685], 'jump', [14.768, 117.065]], 0]], ['second target flips', [[1.5, 1, [0, 45], [[2, 1.2], [2.2, -0.4]], 150]], [[[13.925, 43.114], [-31.604, 54.315]], 0]], ['dropout across branch change', [[1, 1, [-93, 83], [[1.9, -0.3], [3, 3], [-1.5, -1.3]], 120]], [[[-24.867, 31.788], 'hold', [-132.051, -14.07]], 1]], ['down to up flip', [[1, 1, [69, -23], [[0.3, -0.8], [1.9, -0.9], [0.1, 0.9]], 164]], [[[-4.734, -129.42], 'hold', [20.581, -233.843]], 1]], ['wide sweep flips', [[1, 1, [-5, -54], [[0.1, -1.7], [0.7, 1.5], [-1.2, 0.5]], 154]], [[[-55.005, -63.256], [30.841, 68.284], [107.922, 98.917]], 1]], ['rejected then flip', [[1, 1, [171, 101], [[0.8, -1.3], [0.8, 0.7], [0.2, -1.1]], 56]], [['jump', 'jump', [224.293, 112.024]], 0]], ['rejection mid sweep', [[1, 1, [37, 154], [[0.4, 1.3], [-0.5, -0.6], [-0.8, 1.4]], 82]], [[[25.747, 94.301], 'jump', [83.474, 72.542]], 0]]]]\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":"0d31775f491bb73e426b3499143a6d9837a2a5619ef734a6e749a347c27e19c9","source":"\"\"\"Failure Map reference implementation. Python standard library only.\"\"\"\nimport json\nimport math\nN = 1\nobservations = []\ndef solve(x):\n    l1,l2,q0,targets,maxjump=x\n    prev=list(q0)\n    out=[]\n    flips=0\n    branch=None\n    for px,py in targets:\n        c=(px*px+py*py-l1*l1-l2*l2)/(2*l1*l2)\n        if abs(c)>1.0:\n            out.append('hold')\n            continue\n        sols=[]\n        for sgn in (1,-1):\n            s=sgn*math.sqrt(1-c*c)\n            t2=math.degrees(math.atan2(s,c))\n            t1=math.degrees(math.atan2(py,px)-math.atan2(l2*s,l1+l2*c))\n            sols.append([sgn,t1,t2])\n        def dist(sol):\n            return max(abs((sol[1]-prev[0]+180.0)%360.0-180.0),abs((sol[2]-prev[1]+180.0)%360.0-180.0))\n        best=min(sols,key=dist)\n        if dist(best)>maxjump:\n            out.append('jump')\n            continue\n        if branch is not None and best[0]!=branch: flips+=1\n        branch=best[0]\n        t1=prev[0]+((best[1]-prev[0]+180.0)%360.0-180.0)\n        t2=prev[1]+((best[2]-prev[1]+180.0)%360.0-180.0)\n        prev=[t1,t2]\n        out.append([round(t1,3),round(t2,3)])\n    return [out,flips]\ndef check(label, actual, expected):\n    observations.append({\"check\": label, \"actual\": actual, \"expected\": expected, \"passed\": actual == expected})\nfixtures = [[['smooth arc', [[1, 1, [0, 90], [[1, 1], [0.9, 1.1], [0.8, 1.2]], 30]], [[[0.0, 90.0], [5.997, 89.427], [12.456, 87.708]], 0]], ['seam crossing', [[1, 1, [170, 20], [[-1.5, 0.3], [-1.5, -0.3], [-1.4, -0.6]], 40]], [['jump', 'jump', 'jump'], 0]], ['multi-turn start', [[1, 1, [360, 90], [[1, 1], [1.1, 0.9]], 30]], [[[360.0, 90.0], [354.576, 89.427]], 0]], ['dropout in middle', [[1, 1, [0, 90], [[1, 1], [3, 0], [0.9, 1.1]], 30]], [[[0.0, 90.0], 'hold', [5.997, 89.427]], 0]], ['dropout then branch change', [[1, 1, [0, 60], [[1.5, 0.8], [3, 3], [1.6, -0.6]], 200]], [[[-3.716, 63.577], 'hold', [-51.862, 62.613]], 0]], ['large jump rejected', [[1, 1, [0, 90], [[1, 1], [-1, -1], [1, 0.9]], 20]], [[[0.0, 90.0], 'jump', [-5.738, 95.451]], 0]], ['dropout across branch change', [[1, 1, [-93, 83], [[1.9, -0.3], [3, 3], [-1.5, -1.3]], 120]], [[[-24.867, 31.788], 'hold', [-132.051, -14.07]], 1]]], [['dropout in middle', [[1, 1, [0, 90], [[1, 1], [3, 0], [0.9, 1.1]], 30]], [[[0.0, 90.0], 'hold', [5.997, 89.427]], 0]], ['dropout then branch change', [[1, 1, [0, 60], [[1.5, 0.8], [3, 3], [1.6, -0.6]], 200]], [[[-3.716, 63.577], 'hold', [-51.862, 62.613]], 0]], ['large jump rejected', [[1, 1, [0, 90], [[1, 1], [-1, -1], [1, 0.9]], 20]], [[[0.0, 90.0], 'jump', [-5.738, 95.451]], 0]], ['jump exactly at limit', [[2, 1, [0, 0], [[3, 0], [2, 1]], 90]], [[[0.0, 0.0], [0.0, 90.0]], 0]], ['flip through straight', [[1, 1, [0, 30], [[1.9, 0.3], [2, 0], [1.9, -0.3], [1.8, -0.6]], 60]], [[[-6.922, 31.788], [0.0, 0.0], [-24.867, 31.788], [-36.87, 36.87]], 0]], ['start near down branch', [[1, 1, [60, -60], [[1.2, 1.0], [1.3, 0.9]], 50]], [[[78.451, -77.291], [72.456, -75.522]], 0]], ['down to up flip', [[1, 1, [69, -23], [[0.3, -0.8], [1.9, -0.9], [0.1, 0.9]], 164]], [[[-4.734, -129.42], 'hold', [20.581, -233.843]], 1]]], [['jump exactly at limit', [[2, 1, [0, 0], [[3, 0], [2, 1]], 90]], [[[0.0, 0.0], [0.0, 90.0]], 0]], ['flip through straight', [[1, 1, [0, 30], [[1.9, 0.3], [2, 0], [1.9, -0.3], [1.8, -0.6]], 60]], [[[-6.922, 31.788], [0.0, 0.0], [-24.867, 31.788], [-36.87, 36.87]], 0]], ['start near down branch', [[1, 1, [60, -60], [[1.2, 1.0], [1.3, 0.9]], 50]], [[[78.451, -77.291], [72.456, -75.522]], 0]], ['big jump budget', [[1, 1.5, [0, 0], [[-1, 1.5], [1.5, -1], [0.5, 2]], 360]], [[[67.38, 90.0], [-90.0, 90.0], [32.65, 70.529]], 0]], ['negative seam elbow', [[1, 1, [-170, -20], [[-1.5, -0.3], [-1.5, 0.3], [-1.3, 0.8]], 45]], [['jump', 'jump', 'jump'], 0]], ['all unreachable', [[1, 1, [0, 0], [[3, 3], [0, 5]], 30]], [['hold', 'hold'], 0]], ['dropout near base', [[1, 1, [146, 142], [[-0.1, -1.0], [3, 3], [-0.3, 0.2]], 120]], [[[204.455, 119.67], 'hold', [225.924, 200.772]], 1]]], [['big jump budget', [[1, 1.5, [0, 0], [[-1, 1.5], [1.5, -1], [0.5, 2]], 360]], [[[67.38, 90.0], [-90.0, 90.0], [32.65, 70.529]], 0]], ['negative seam elbow', [[1, 1, [-170, -20], [[-1.5, -0.3], [-1.5, 0.3], [-1.3, 0.8]], 45]], [['jump', 'jump', 'jump'], 0]], ['all unreachable', [[1, 1, [0, 0], [[3, 3], [0, 5]], 30]], [['hold', 'hold'], 0]], ['jump then recover', [[1, 1, [0, 120], [[0.2, 1.0], [1.8, 0.2], [0.3, 1.0]], 60]], [[[19.347, 118.685], 'jump', [14.768, 117.065]], 0]], ['second target flips', [[1.5, 1, [0, 45], [[2, 1.2], [2.2, -0.4]], 150]], [[[13.925, 43.114], [-31.604, 54.315]], 0]], ['dropout across branch change', [[1, 1, [-93, 83], [[1.9, -0.3], [3, 3], [-1.5, -1.3]], 120]], [[[-24.867, 31.788], 'hold', [-132.051, -14.07]], 1]], ['down to up flip', [[1, 1, [69, -23], [[0.3, -0.8], [1.9, -0.9], [0.1, 0.9]], 164]], [[[-4.734, -129.42], 'hold', [20.581, -233.843]], 1]]], [['jump then recover', [[1, 1, [0, 120], [[0.2, 1.0], [1.8, 0.2], [0.3, 1.0]], 60]], [[[19.347, 118.685], 'jump', [14.768, 117.065]], 0]], ['second target flips', [[1.5, 1, [0, 45], [[2, 1.2], [2.2, -0.4]], 150]], [[[13.925, 43.114], [-31.604, 54.315]], 0]], ['dropout across branch change', [[1, 1, [-93, 83], [[1.9, -0.3], [3, 3], [-1.5, -1.3]], 120]], [[[-24.867, 31.788], 'hold', [-132.051, -14.07]], 1]], ['down to up flip', [[1, 1, [69, -23], [[0.3, -0.8], [1.9, -0.9], [0.1, 0.9]], 164]], [[[-4.734, -129.42], 'hold', [20.581, -233.843]], 1]], ['wide sweep flips', [[1, 1, [-5, -54], [[0.1, -1.7], [0.7, 1.5], [-1.2, 0.5]], 154]], [[[-55.005, -63.256], [30.841, 68.284], [107.922, 98.917]], 1]], ['rejected then flip', [[1, 1, [171, 101], [[0.8, -1.3], [0.8, 0.7], [0.2, -1.1]], 56]], [['jump', 'jump', [224.293, 112.024]], 0]], ['rejection mid sweep', [[1, 1, [37, 154], [[0.4, 1.3], [-0.5, -0.6], [-0.8, 1.4]], 82]], [[[25.747, 94.301], 'jump', [83.474, 72.542]], 0]]]]\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-trajectory-branch-continuity-dropout-state-reset","generated_at":"2026-09-29T14:51:06.257743+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":"Leave the branch and joint state untouched on \"hold\".","root_cause":"The \"hold\" path clears the remembered branch, so the next accepted solution is treated as the first.","sha256":"3ba038332d80cae89632e0fb54adb4398ebb38267ce0986d88a3f687c7e1526d","title":"Trajectory dropout forgets the elbow branch · case 01","variant":1,"variant_policy":"Five numbered records share a model and may reuse boundary fixtures.","verification":{"attempt":{"elapsed_ms":39.305,"exit_code":1,"observations":[{"actual":[[[0.0,90.0],[5.997,89.427],[12.456,87.708]],0],"check":"smooth arc","expected":[[[0.0,90.0],[5.997,89.427],[12.456,87.708]],0],"passed":true},{"actual":[["jump","jump","jump"],0],"check":"seam crossing","expected":[["jump","jump","jump"],0],"passed":true},{"actual":[[[360.0,90.0],[354.576,89.427]],0],"check":"multi-turn start","expected":[[[360.0,90.0],[354.576,89.427]],0],"passed":true},{"actual":[[[0.0,90.0],"hold",[5.997,89.427]],0],"check":"dropout in middle","expected":[[[0.0,90.0],"hold",[5.997,89.427]],0],"passed":true},{"actual":[[[-3.716,63.577],"hold",[-51.862,62.613]],0],"check":"dropout then branch change","expected":[[[-3.716,63.577],"hold",[-51.862,62.613]],0],"passed":true},{"actual":[[[0.0,90.0],"jump",[-5.738,95.451]],0],"check":"large jump rejected","expected":[[[0.0,90.0],"jump",[-5.738,95.451]],0],"passed":true},{"actual":[[[-24.867,31.788],"hold",[-146.121,14.07]],0],"check":"dropout across branch change","expected":[[[-24.867,31.788],"hold",[-132.051,-14.07]],1],"passed":false}],"passed":false,"stderr":"","stdout":"{\"observations\": [{\"check\": \"smooth arc\", \"actual\": [[[0.0, 90.0], [5.997, 89.427], [12.456, 87.708]], 0], \"expected\": [[[0.0, 90.0], [5.997, 89.427], [12.456, 87.708]], 0], \"passed\": true}, {\"check\": \"seam crossing\", \"actual\": [[\"jump\", \"jump\", \"jump\"], 0], \"expected\": [[\"jump\", \"jump\", \"jump\"], 0], \"passed\": true}, {\"check\": \"multi-turn start\", \"actual\": [[[360.0, 90.0], [354.576, 89.427]], 0], \"expected\": [[[360.0, 90.0], [354.576, 89.427]], 0], \"passed\": true}, {\"check\": \"dropout in middle\", \"actual\": [[[0.0, 90.0], \"hold\", [5.997, 89.427]], 0], \"expected\": [[[0.0, 90.0], \"hold\", [5.997, 89.427]], 0], \"passed\": true}, {\"check\": \"dropout then branch change\", \"actual\": [[[-3.716, 63.577], \"hold\", [-51.862, 62.613]], 0], \"expected\": [[[-3.716, 63.577], \"hold\", [-51.862, 62.613]], 0], \"passed\": true}, {\"check\": \"large jump rejected\", \"actual\": [[[0.0, 90.0], \"jump\", [-5.738, 95.451]], 0], \"expected\": [[[0.0, 90.0], \"jump\", [-5.738, 95.451]], 0], \"passed\": true}, {\"check\": \"dropout across branch change\", \"actual\": [[[-24.867, 31.788], \"hold\", [-146.121, 14.07]], 0], \"expected\": [[[-24.867, 31.788], \"hold\", [-132.051, -14.07]], 1], \"passed\": false}], \"passed\": false}\n"},"broken":{"elapsed_ms":41.626,"exit_code":1,"observations":[{"actual":[[[0.0,90.0],[5.997,89.427],[12.456,87.708]],0],"check":"smooth arc","expected":[[[0.0,90.0],[5.997,89.427],[12.456,87.708]],0],"passed":true},{"actual":[["jump","jump","jump"],0],"check":"seam crossing","expected":[["jump","jump","jump"],0],"passed":true},{"actual":[[[360.0,90.0],[354.576,89.427]],0],"check":"multi-turn start","expected":[[[360.0,90.0],[354.576,89.427]],0],"passed":true},{"actual":[[[0.0,90.0],"hold",[5.997,89.427]],0],"check":"dropout in middle","expected":[[[0.0,90.0],"hold",[5.997,89.427]],0],"passed":true},{"actual":[[[-3.716,63.577],"hold",[-51.862,62.613]],0],"check":"dropout then branch change","expected":[[[-3.716,63.577],"hold",[-51.862,62.613]],0],"passed":true},{"actual":[[[0.0,90.0],"jump",[-5.738,95.451]],0],"check":"large jump rejected","expected":[[[0.0,90.0],"jump",[-5.738,95.451]],0],"passed":true},{"actual":[[[-24.867,31.788],"hold",[-132.051,-14.07]],0],"check":"dropout across branch change","expected":[[[-24.867,31.788],"hold",[-132.051,-14.07]],1],"passed":false}],"passed":false,"stderr":"","stdout":"{\"observations\": [{\"check\": \"smooth arc\", \"actual\": [[[0.0, 90.0], [5.997, 89.427], [12.456, 87.708]], 0], \"expected\": [[[0.0, 90.0], [5.997, 89.427], [12.456, 87.708]], 0], \"passed\": true}, {\"check\": \"seam crossing\", \"actual\": [[\"jump\", \"jump\", \"jump\"], 0], \"expected\": [[\"jump\", \"jump\", \"jump\"], 0], \"passed\": true}, {\"check\": \"multi-turn start\", \"actual\": [[[360.0, 90.0], [354.576, 89.427]], 0], \"expected\": [[[360.0, 90.0], [354.576, 89.427]], 0], \"passed\": true}, {\"check\": \"dropout in middle\", \"actual\": [[[0.0, 90.0], \"hold\", [5.997, 89.427]], 0], \"expected\": [[[0.0, 90.0], \"hold\", [5.997, 89.427]], 0], \"passed\": true}, {\"check\": \"dropout then branch change\", \"actual\": [[[-3.716, 63.577], \"hold\", [-51.862, 62.613]], 0], \"expected\": [[[-3.716, 63.577], \"hold\", [-51.862, 62.613]], 0], \"passed\": true}, {\"check\": \"large jump rejected\", \"actual\": [[[0.0, 90.0], \"jump\", [-5.738, 95.451]], 0], \"expected\": [[[0.0, 90.0], \"jump\", [-5.738, 95.451]], 0], \"passed\": true}, {\"check\": \"dropout across branch change\", \"actual\": [[[-24.867, 31.788], \"hold\", [-132.051, -14.07]], 0], \"expected\": [[[-24.867, 31.788], \"hold\", [-132.051, -14.07]], 1], \"passed\": false}], \"passed\": false}\n"},"fixed":{"elapsed_ms":40.733,"exit_code":0,"observations":[{"actual":[[[0.0,90.0],[5.997,89.427],[12.456,87.708]],0],"check":"smooth arc","expected":[[[0.0,90.0],[5.997,89.427],[12.456,87.708]],0],"passed":true},{"actual":[["jump","jump","jump"],0],"check":"seam crossing","expected":[["jump","jump","jump"],0],"passed":true},{"actual":[[[360.0,90.0],[354.576,89.427]],0],"check":"multi-turn start","expected":[[[360.0,90.0],[354.576,89.427]],0],"passed":true},{"actual":[[[0.0,90.0],"hold",[5.997,89.427]],0],"check":"dropout in middle","expected":[[[0.0,90.0],"hold",[5.997,89.427]],0],"passed":true},{"actual":[[[-3.716,63.577],"hold",[-51.862,62.613]],0],"check":"dropout then branch change","expected":[[[-3.716,63.577],"hold",[-51.862,62.613]],0],"passed":true},{"actual":[[[0.0,90.0],"jump",[-5.738,95.451]],0],"check":"large jump rejected","expected":[[[0.0,90.0],"jump",[-5.738,95.451]],0],"passed":true},{"actual":[[[-24.867,31.788],"hold",[-132.051,-14.07]],1],"check":"dropout across branch change","expected":[[[-24.867,31.788],"hold",[-132.051,-14.07]],1],"passed":true}],"passed":true,"stderr":"","stdout":"{\"observations\": [{\"check\": \"smooth arc\", \"actual\": [[[0.0, 90.0], [5.997, 89.427], [12.456, 87.708]], 0], \"expected\": [[[0.0, 90.0], [5.997, 89.427], [12.456, 87.708]], 0], \"passed\": true}, {\"check\": \"seam crossing\", \"actual\": [[\"jump\", \"jump\", \"jump\"], 0], \"expected\": [[\"jump\", \"jump\", \"jump\"], 0], \"passed\": true}, {\"check\": \"multi-turn start\", \"actual\": [[[360.0, 90.0], [354.576, 89.427]], 0], \"expected\": [[[360.0, 90.0], [354.576, 89.427]], 0], \"passed\": true}, {\"check\": \"dropout in middle\", \"actual\": [[[0.0, 90.0], \"hold\", [5.997, 89.427]], 0], \"expected\": [[[0.0, 90.0], \"hold\", [5.997, 89.427]], 0], \"passed\": true}, {\"check\": \"dropout then branch change\", \"actual\": [[[-3.716, 63.577], \"hold\", [-51.862, 62.613]], 0], \"expected\": [[[-3.716, 63.577], \"hold\", [-51.862, 62.613]], 0], \"passed\": true}, {\"check\": \"large jump rejected\", \"actual\": [[[0.0, 90.0], \"jump\", [-5.738, 95.451]], 0], \"expected\": [[[0.0, 90.0], \"jump\", [-5.738, 95.451]], 0], \"passed\": true}, {\"check\": \"dropout across branch change\", \"actual\": [[[-24.867, 31.788], \"hold\", [-132.051, -14.07]], 1], \"expected\": [[[-24.867, 31.788], \"hold\", [-132.051, -14.07]], 1], \"passed\": true}], \"passed\": true}\n"}},"verified":true,"visibility":"public"}