{"abstract":"Joint deltas are rotated into the wrong space and the arm drifts sideways.","category":"Inverse kinematics solvers","checks":7,"contract":"Input [l1,l2,q1,q2,tx,ty,lam,maxstep], angles in degrees, maxstep in radians. Perform one damped least squares step dq = J^T (J J^T + lam^2 I)^-1 e with e = target - fk(q), scale dq so its Euclidean norm is at most maxstep, and return the updated [q1,q2] in degrees rounded to 4 places; a near-singular damped matrix (|det|<1e-12) returns \"singular\".","evaluation_group":"w2-inverse_kinematics_solvers-damped-least-squares-step","failed_approach":"Transposing only the first component leaves the second joint update using a row of J.","family":"w2-inverse_kinematics_solvers-damped-least-squares-step-jacobian-transpose-product","id":"FA-87921","implementations":{"attempt":{"sha256":"858b79300f5b41fdd7a5865ff59c78b97df4a2105b5a63275b10b4686873f9d2","source":"\"\"\"Failure Map reference implementation. Python standard library only.\"\"\"\nimport json\nimport math\nN = 1\nobservations = []\ndef solve(x):\n    l1,l2,q1,q2,tx,ty,lam,maxstep=x\n    a=math.radians(q1)\n    b=math.radians(q1+q2)\n    ex=tx-(l1*math.cos(a)+l2*math.cos(b))\n    ey=ty-(l1*math.sin(a)+l2*math.sin(b))\n    j11=-l1*math.sin(a)-l2*math.sin(b)\n    j12=-l2*math.sin(b)\n    j21=l1*math.cos(a)+l2*math.cos(b)\n    j22=l2*math.cos(b)\n    m11=j11*j11+j12*j12+lam*lam\n    m12=j11*j21+j12*j22\n    m22=j21*j21+j22*j22+lam*lam\n    det=m11*m22-m12*m12\n    if abs(det)<1e-12: return 'singular'\n    w1=(m22*ex-m12*ey)/det\n    w2=(-m12*ex+m11*ey)/det\n    d1=j11*w1+j21*w2\n    d2=j21*w1+j22*w2\n    n=math.hypot(d1,d2)\n    if n>maxstep and n>0: d1,d2=d1*maxstep/n,d2*maxstep/n\n    return [round(q1+math.degrees(d1),4),round(q2+math.degrees(d2),4)]\ndef check(label, actual, expected):\n    observations.append({\"check\": label, \"actual\": actual, \"expected\": expected, \"passed\": actual == expected})\nfixtures = [[['small correction', [[1, 1, 30, 45, 1.0, 1.4, 0.1, 1.0]], [22.9688, 62.7571]], ['large correction clamped', [[1, 1, 0, 90, -1.5, 0.5, 0.1, 0.2]], [-1.7958, 101.3176]], ['straight arm damped', [[1, 1, 0, 0, 1.5, 0.5, 0.5, 1.0]], [10.9135, 5.4567]], ['undamped singular', [[1, 1, 0, 0, 1.5, 0.5, 0.0, 1.0]], 'singular'], ['heavy damping', [[2, 1, 20, 60, 1, 2, 2.0, 1.0]], [31.2311, 68.0501]], ['already on target', [[1, 1, 0, 90, 1, 1, 0.1, 1.0]], [0.0, 90.0]], ['negative angles', [[1.5, 1, -40, -70, 1, -1.5, 0.2, 0.5]], [-22.919, -92.471]]], [['large correction clamped', [[1, 1, 0, 90, -1.5, 0.5, 0.1, 0.2]], [-1.7958, 101.3176]], ['heavy damping', [[2, 1, 20, 60, 1, 2, 2.0, 1.0]], [31.2311, 68.0501]], ['already on target', [[1, 1, 0, 90, 1, 1, 0.1, 1.0]], [0.0, 90.0]], ['negative angles', [[1.5, 1, -40, -70, 1, -1.5, 0.2, 0.5]], [-22.919, -92.471]], ['tiny step budget', [[1, 1, 10, 20, 0, 1.8, 0.05, 0.01]], [9.7971, 20.5358]], ['long upper arm', [[3, 1, 60, -30, 1, 3, 0.3, 0.3]], [66.6639, -45.8444]], ['target behind', [[1, 1, 45, 45, -1.2, -0.4, 0.2, 2.0]], [2.6992, 151.4982]]], [['straight arm damped', [[1, 1, 0, 0, 1.5, 0.5, 0.5, 1.0]], [10.9135, 5.4567]], ['tiny step budget', [[1, 1, 10, 20, 0, 1.8, 0.05, 0.01]], [9.7971, 20.5358]], ['long upper arm', [[3, 1, 60, -30, 1, 3, 0.3, 0.3]], [66.6639, -45.8444]], ['target behind', [[1, 1, 45, 45, -1.2, -0.4, 0.2, 2.0]], [2.6992, 151.4982]], ['lightly damped folded', [[1, 1, 30, 170, 0.5, 0.2, 0.01, 0.5]], [1.4116, 171.8446]], ['mid budget', [[2, 2, -120, 60, -1, -2, 0.1, 0.4]], [-133.1333, 78.7821]], ['upper reach', [[1, 2, 90, -45, -1, 2.5, 0.05, 1.5]], [151.7219, -104.8057]]], [['small correction', [[1, 1, 30, 45, 1.0, 1.4, 0.1, 1.0]], [22.9688, 62.7571]], ['large correction clamped', [[1, 1, 0, 90, -1.5, 0.5, 0.1, 0.2]], [-1.7958, 101.3176]], ['heavy damping', [[2, 1, 20, 60, 1, 2, 2.0, 1.0]], [31.2311, 68.0501]], ['lightly damped folded', [[1, 1, 30, 170, 0.5, 0.2, 0.01, 0.5]], [1.4116, 171.8446]], ['mid budget', [[2, 2, -120, 60, -1, -2, 0.1, 0.4]], [-133.1333, 78.7821]], ['upper reach', [[1, 2, 90, -45, -1, 2.5, 0.05, 1.5]], [151.7219, -104.8057]], ['unit damping', [[1, 1, 15, 15, 0.2, 1.9, 1.0, 1.0]], [44.712, 37.4827]]], [['small correction', [[1, 1, 30, 45, 1.0, 1.4, 0.1, 1.0]], [22.9688, 62.7571]], ['large correction clamped', [[1, 1, 0, 90, -1.5, 0.5, 0.1, 0.2]], [-1.7958, 101.3176]], ['straight arm damped', [[1, 1, 0, 0, 1.5, 0.5, 0.5, 1.0]], [10.9135, 5.4567]], ['undamped singular', [[1, 1, 0, 0, 1.5, 0.5, 0.0, 1.0]], 'singular'], ['heavy damping', [[2, 1, 20, 60, 1, 2, 2.0, 1.0]], [31.2311, 68.0501]], ['negative angles', [[1.5, 1, -40, -70, 1, -1.5, 0.2, 0.5]], [-22.919, -92.471]], ['unit damping', [[1, 1, 15, 15, 0.2, 1.9, 1.0, 1.0]], [44.712, 37.4827]]]]\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":"07e8bc1646c8480e09fdf5a32489df3379531129424b26003d140728fdf1c051","source":"\"\"\"Failure Map reference implementation. Python standard library only.\"\"\"\nimport json\nimport math\nN = 1\nobservations = []\ndef solve(x):\n    l1,l2,q1,q2,tx,ty,lam,maxstep=x\n    a=math.radians(q1)\n    b=math.radians(q1+q2)\n    ex=tx-(l1*math.cos(a)+l2*math.cos(b))\n    ey=ty-(l1*math.sin(a)+l2*math.sin(b))\n    j11=-l1*math.sin(a)-l2*math.sin(b)\n    j12=-l2*math.sin(b)\n    j21=l1*math.cos(a)+l2*math.cos(b)\n    j22=l2*math.cos(b)\n    m11=j11*j11+j12*j12+lam*lam\n    m12=j11*j21+j12*j22\n    m22=j21*j21+j22*j22+lam*lam\n    det=m11*m22-m12*m12\n    if abs(det)<1e-12: return 'singular'\n    w1=(m22*ex-m12*ey)/det\n    w2=(-m12*ex+m11*ey)/det\n    d1=j11*w1+j12*w2\n    d2=j21*w1+j22*w2\n    n=math.hypot(d1,d2)\n    if n>maxstep and n>0: d1,d2=d1*maxstep/n,d2*maxstep/n\n    return [round(q1+math.degrees(d1),4),round(q2+math.degrees(d2),4)]\ndef check(label, actual, expected):\n    observations.append({\"check\": label, \"actual\": actual, \"expected\": expected, \"passed\": actual == expected})\nfixtures = [[['small correction', [[1, 1, 30, 45, 1.0, 1.4, 0.1, 1.0]], [22.9688, 62.7571]], ['large correction clamped', [[1, 1, 0, 90, -1.5, 0.5, 0.1, 0.2]], [-1.7958, 101.3176]], ['straight arm damped', [[1, 1, 0, 0, 1.5, 0.5, 0.5, 1.0]], [10.9135, 5.4567]], ['undamped singular', [[1, 1, 0, 0, 1.5, 0.5, 0.0, 1.0]], 'singular'], ['heavy damping', [[2, 1, 20, 60, 1, 2, 2.0, 1.0]], [31.2311, 68.0501]], ['already on target', [[1, 1, 0, 90, 1, 1, 0.1, 1.0]], [0.0, 90.0]], ['negative angles', [[1.5, 1, -40, -70, 1, -1.5, 0.2, 0.5]], [-22.919, -92.471]]], [['large correction clamped', [[1, 1, 0, 90, -1.5, 0.5, 0.1, 0.2]], [-1.7958, 101.3176]], ['heavy damping', [[2, 1, 20, 60, 1, 2, 2.0, 1.0]], [31.2311, 68.0501]], ['already on target', [[1, 1, 0, 90, 1, 1, 0.1, 1.0]], [0.0, 90.0]], ['negative angles', [[1.5, 1, -40, -70, 1, -1.5, 0.2, 0.5]], [-22.919, -92.471]], ['tiny step budget', [[1, 1, 10, 20, 0, 1.8, 0.05, 0.01]], [9.7971, 20.5358]], ['long upper arm', [[3, 1, 60, -30, 1, 3, 0.3, 0.3]], [66.6639, -45.8444]], ['target behind', [[1, 1, 45, 45, -1.2, -0.4, 0.2, 2.0]], [2.6992, 151.4982]]], [['straight arm damped', [[1, 1, 0, 0, 1.5, 0.5, 0.5, 1.0]], [10.9135, 5.4567]], ['tiny step budget', [[1, 1, 10, 20, 0, 1.8, 0.05, 0.01]], [9.7971, 20.5358]], ['long upper arm', [[3, 1, 60, -30, 1, 3, 0.3, 0.3]], [66.6639, -45.8444]], ['target behind', [[1, 1, 45, 45, -1.2, -0.4, 0.2, 2.0]], [2.6992, 151.4982]], ['lightly damped folded', [[1, 1, 30, 170, 0.5, 0.2, 0.01, 0.5]], [1.4116, 171.8446]], ['mid budget', [[2, 2, -120, 60, -1, -2, 0.1, 0.4]], [-133.1333, 78.7821]], ['upper reach', [[1, 2, 90, -45, -1, 2.5, 0.05, 1.5]], [151.7219, -104.8057]]], [['small correction', [[1, 1, 30, 45, 1.0, 1.4, 0.1, 1.0]], [22.9688, 62.7571]], ['large correction clamped', [[1, 1, 0, 90, -1.5, 0.5, 0.1, 0.2]], [-1.7958, 101.3176]], ['heavy damping', [[2, 1, 20, 60, 1, 2, 2.0, 1.0]], [31.2311, 68.0501]], ['lightly damped folded', [[1, 1, 30, 170, 0.5, 0.2, 0.01, 0.5]], [1.4116, 171.8446]], ['mid budget', [[2, 2, -120, 60, -1, -2, 0.1, 0.4]], [-133.1333, 78.7821]], ['upper reach', [[1, 2, 90, -45, -1, 2.5, 0.05, 1.5]], [151.7219, -104.8057]], ['unit damping', [[1, 1, 15, 15, 0.2, 1.9, 1.0, 1.0]], [44.712, 37.4827]]], [['small correction', [[1, 1, 30, 45, 1.0, 1.4, 0.1, 1.0]], [22.9688, 62.7571]], ['large correction clamped', [[1, 1, 0, 90, -1.5, 0.5, 0.1, 0.2]], [-1.7958, 101.3176]], ['straight arm damped', [[1, 1, 0, 0, 1.5, 0.5, 0.5, 1.0]], [10.9135, 5.4567]], ['undamped singular', [[1, 1, 0, 0, 1.5, 0.5, 0.0, 1.0]], 'singular'], ['heavy damping', [[2, 1, 20, 60, 1, 2, 2.0, 1.0]], [31.2311, 68.0501]], ['negative angles', [[1.5, 1, -40, -70, 1, -1.5, 0.2, 0.5]], [-22.919, -92.471]], ['unit damping', [[1, 1, 15, 15, 0.2, 1.9, 1.0, 1.0]], [44.712, 37.4827]]]]\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":"c85ddc5103ffb8b285e88b82d455e1ea0214360a7ced1144b482a1b603956c41","source":"\"\"\"Failure Map reference implementation. Python standard library only.\"\"\"\nimport json\nimport math\nN = 1\nobservations = []\ndef solve(x):\n    l1,l2,q1,q2,tx,ty,lam,maxstep=x\n    a=math.radians(q1)\n    b=math.radians(q1+q2)\n    ex=tx-(l1*math.cos(a)+l2*math.cos(b))\n    ey=ty-(l1*math.sin(a)+l2*math.sin(b))\n    j11=-l1*math.sin(a)-l2*math.sin(b)\n    j12=-l2*math.sin(b)\n    j21=l1*math.cos(a)+l2*math.cos(b)\n    j22=l2*math.cos(b)\n    m11=j11*j11+j12*j12+lam*lam\n    m12=j11*j21+j12*j22\n    m22=j21*j21+j22*j22+lam*lam\n    det=m11*m22-m12*m12\n    if abs(det)<1e-12: return 'singular'\n    w1=(m22*ex-m12*ey)/det\n    w2=(-m12*ex+m11*ey)/det\n    d1=j11*w1+j21*w2\n    d2=j12*w1+j22*w2\n    n=math.hypot(d1,d2)\n    if n>maxstep and n>0: d1,d2=d1*maxstep/n,d2*maxstep/n\n    return [round(q1+math.degrees(d1),4),round(q2+math.degrees(d2),4)]\ndef check(label, actual, expected):\n    observations.append({\"check\": label, \"actual\": actual, \"expected\": expected, \"passed\": actual == expected})\nfixtures = [[['small correction', [[1, 1, 30, 45, 1.0, 1.4, 0.1, 1.0]], [22.9688, 62.7571]], ['large correction clamped', [[1, 1, 0, 90, -1.5, 0.5, 0.1, 0.2]], [-1.7958, 101.3176]], ['straight arm damped', [[1, 1, 0, 0, 1.5, 0.5, 0.5, 1.0]], [10.9135, 5.4567]], ['undamped singular', [[1, 1, 0, 0, 1.5, 0.5, 0.0, 1.0]], 'singular'], ['heavy damping', [[2, 1, 20, 60, 1, 2, 2.0, 1.0]], [31.2311, 68.0501]], ['already on target', [[1, 1, 0, 90, 1, 1, 0.1, 1.0]], [0.0, 90.0]], ['negative angles', [[1.5, 1, -40, -70, 1, -1.5, 0.2, 0.5]], [-22.919, -92.471]]], [['large correction clamped', [[1, 1, 0, 90, -1.5, 0.5, 0.1, 0.2]], [-1.7958, 101.3176]], ['heavy damping', [[2, 1, 20, 60, 1, 2, 2.0, 1.0]], [31.2311, 68.0501]], ['already on target', [[1, 1, 0, 90, 1, 1, 0.1, 1.0]], [0.0, 90.0]], ['negative angles', [[1.5, 1, -40, -70, 1, -1.5, 0.2, 0.5]], [-22.919, -92.471]], ['tiny step budget', [[1, 1, 10, 20, 0, 1.8, 0.05, 0.01]], [9.7971, 20.5358]], ['long upper arm', [[3, 1, 60, -30, 1, 3, 0.3, 0.3]], [66.6639, -45.8444]], ['target behind', [[1, 1, 45, 45, -1.2, -0.4, 0.2, 2.0]], [2.6992, 151.4982]]], [['straight arm damped', [[1, 1, 0, 0, 1.5, 0.5, 0.5, 1.0]], [10.9135, 5.4567]], ['tiny step budget', [[1, 1, 10, 20, 0, 1.8, 0.05, 0.01]], [9.7971, 20.5358]], ['long upper arm', [[3, 1, 60, -30, 1, 3, 0.3, 0.3]], [66.6639, -45.8444]], ['target behind', [[1, 1, 45, 45, -1.2, -0.4, 0.2, 2.0]], [2.6992, 151.4982]], ['lightly damped folded', [[1, 1, 30, 170, 0.5, 0.2, 0.01, 0.5]], [1.4116, 171.8446]], ['mid budget', [[2, 2, -120, 60, -1, -2, 0.1, 0.4]], [-133.1333, 78.7821]], ['upper reach', [[1, 2, 90, -45, -1, 2.5, 0.05, 1.5]], [151.7219, -104.8057]]], [['small correction', [[1, 1, 30, 45, 1.0, 1.4, 0.1, 1.0]], [22.9688, 62.7571]], ['large correction clamped', [[1, 1, 0, 90, -1.5, 0.5, 0.1, 0.2]], [-1.7958, 101.3176]], ['heavy damping', [[2, 1, 20, 60, 1, 2, 2.0, 1.0]], [31.2311, 68.0501]], ['lightly damped folded', [[1, 1, 30, 170, 0.5, 0.2, 0.01, 0.5]], [1.4116, 171.8446]], ['mid budget', [[2, 2, -120, 60, -1, -2, 0.1, 0.4]], [-133.1333, 78.7821]], ['upper reach', [[1, 2, 90, -45, -1, 2.5, 0.05, 1.5]], [151.7219, -104.8057]], ['unit damping', [[1, 1, 15, 15, 0.2, 1.9, 1.0, 1.0]], [44.712, 37.4827]]], [['small correction', [[1, 1, 30, 45, 1.0, 1.4, 0.1, 1.0]], [22.9688, 62.7571]], ['large correction clamped', [[1, 1, 0, 90, -1.5, 0.5, 0.1, 0.2]], [-1.7958, 101.3176]], ['straight arm damped', [[1, 1, 0, 0, 1.5, 0.5, 0.5, 1.0]], [10.9135, 5.4567]], ['undamped singular', [[1, 1, 0, 0, 1.5, 0.5, 0.0, 1.0]], 'singular'], ['heavy damping', [[2, 1, 20, 60, 1, 2, 2.0, 1.0]], [31.2311, 68.0501]], ['negative angles', [[1.5, 1, -40, -70, 1, -1.5, 0.2, 0.5]], [-22.919, -92.471]], ['unit damping', [[1, 1, 15, 15, 0.2, 1.9, 1.0, 1.0]], [44.712, 37.4827]]]]\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-damped-least-squares-step-jacobian-transpose-product","generated_at":"2026-09-29T14:51:03.268799+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":"Compute dq_i as the dot product of column i of J with w.","root_cause":"dq is formed as J w rather than J^T w, mixing row and column indices.","sha256":"3fb6ed297da2f8f6a5744718b382e011ecc7a48fbc5d7d0bba1023074a113a86","title":"Joint update multiplies by J instead of J transpose · case 01","variant":1,"variant_policy":"Five numbered records share a model and may reuse boundary fixtures.","verification":{"attempt":{"elapsed_ms":41.86,"exit_code":1,"observations":[{"actual":[22.9688,-1.6826],"check":"small correction","expected":[22.9688,62.7571],"passed":false},{"actual":[-1.7958,78.6824],"check":"large correction clamped","expected":[-1.7958,101.3176],"passed":false},{"actual":[2.7916,-57.2277],"check":"straight arm damped","expected":[10.9135,5.4567],"passed":false},{"actual":"singular","check":"undamped singular","expected":"singular","passed":true},{"actual":[31.2311,42.4839],"check":"heavy damping","expected":[31.2311,68.0501],"passed":false},{"actual":[0.0,90.0],"check":"already on target","expected":[0.0,90.0],"passed":true},{"actual":[-22.919,-91.3142],"check":"negative angles","expected":[-22.919,-92.471],"passed":false}],"passed":false,"stderr":"","stdout":"{\"observations\": [{\"check\": \"small correction\", \"actual\": [22.9688, -1.6826], \"expected\": [22.9688, 62.7571], \"passed\": false}, {\"check\": \"large correction clamped\", \"actual\": [-1.7958, 78.6824], \"expected\": [-1.7958, 101.3176], \"passed\": false}, {\"check\": \"straight arm damped\", \"actual\": [2.7916, -57.2277], \"expected\": [10.9135, 5.4567], \"passed\": false}, {\"check\": \"undamped singular\", \"actual\": \"singular\", \"expected\": \"singular\", \"passed\": true}, {\"check\": \"heavy damping\", \"actual\": [31.2311, 42.4839], \"expected\": [31.2311, 68.0501], \"passed\": false}, {\"check\": \"already on target\", \"actual\": [0.0, 90.0], \"expected\": [0.0, 90.0], \"passed\": true}, {\"check\": \"negative angles\", \"actual\": [-22.919, -91.3142], \"expected\": [-22.919, -92.471], \"passed\": false}], \"passed\": false}\n"},"broken":{"elapsed_ms":42.625,"exit_code":1,"observations":[{"actual":[80.863,18.6227],"check":"small correction","expected":[22.9688,62.7571],"passed":false},{"actual":[10.3977,85.1833],"check":"large correction clamped","expected":[-1.7958,101.3176],"passed":false},{"actual":[0.0,-57.2958],"check":"straight arm damped","expected":[10.9135,5.4567],"passed":false},{"actual":"singular","check":"undamped singular","expected":"singular","passed":true},{"actual":[35.3946,42.4839],"check":"heavy damping","expected":[31.2311,68.0501],"passed":false},{"actual":[0.0,90.0],"check":"already on target","expected":[0.0,90.0],"passed":true},{"actual":[-19.1511,-89.6475],"check":"negative angles","expected":[-22.919,-92.471],"passed":false}],"passed":false,"stderr":"","stdout":"{\"observations\": [{\"check\": \"small correction\", \"actual\": [80.863, 18.6227], \"expected\": [22.9688, 62.7571], \"passed\": false}, {\"check\": \"large correction clamped\", \"actual\": [10.3977, 85.1833], \"expected\": [-1.7958, 101.3176], \"passed\": false}, {\"check\": \"straight arm damped\", \"actual\": [0.0, -57.2958], \"expected\": [10.9135, 5.4567], \"passed\": false}, {\"check\": \"undamped singular\", \"actual\": \"singular\", \"expected\": \"singular\", \"passed\": true}, {\"check\": \"heavy damping\", \"actual\": [35.3946, 42.4839], \"expected\": [31.2311, 68.0501], \"passed\": false}, {\"check\": \"already on target\", \"actual\": [0.0, 90.0], \"expected\": [0.0, 90.0], \"passed\": true}, {\"check\": \"negative angles\", \"actual\": [-19.1511, -89.6475], \"expected\": [-22.919, -92.471], \"passed\": false}], \"passed\": false}\n"},"fixed":{"elapsed_ms":39.745,"exit_code":0,"observations":[{"actual":[22.9688,62.7571],"check":"small correction","expected":[22.9688,62.7571],"passed":true},{"actual":[-1.7958,101.3176],"check":"large correction clamped","expected":[-1.7958,101.3176],"passed":true},{"actual":[10.9135,5.4567],"check":"straight arm damped","expected":[10.9135,5.4567],"passed":true},{"actual":"singular","check":"undamped singular","expected":"singular","passed":true},{"actual":[31.2311,68.0501],"check":"heavy damping","expected":[31.2311,68.0501],"passed":true},{"actual":[0.0,90.0],"check":"already on target","expected":[0.0,90.0],"passed":true},{"actual":[-22.919,-92.471],"check":"negative angles","expected":[-22.919,-92.471],"passed":true}],"passed":true,"stderr":"","stdout":"{\"observations\": [{\"check\": \"small correction\", \"actual\": [22.9688, 62.7571], \"expected\": [22.9688, 62.7571], \"passed\": true}, {\"check\": \"large correction clamped\", \"actual\": [-1.7958, 101.3176], \"expected\": [-1.7958, 101.3176], \"passed\": true}, {\"check\": \"straight arm damped\", \"actual\": [10.9135, 5.4567], \"expected\": [10.9135, 5.4567], \"passed\": true}, {\"check\": \"undamped singular\", \"actual\": \"singular\", \"expected\": \"singular\", \"passed\": true}, {\"check\": \"heavy damping\", \"actual\": [31.2311, 68.0501], \"expected\": [31.2311, 68.0501], \"passed\": true}, {\"check\": \"already on target\", \"actual\": [0.0, 90.0], \"expected\": [0.0, 90.0], \"passed\": true}, {\"check\": \"negative angles\", \"actual\": [-22.919, -92.471], \"expected\": [-22.919, -92.471], \"passed\": true}], \"passed\": true}\n"}},"verified":true,"visibility":"public"}