"""Shadow boxing (a friend's request, 2026-10-11): orthodox stance, guard up, bouncing; jab, jab, right cross, left hook, back to guard. 2.4 s loop, priority 5, fists. Claude Opus 5.5.""" import json from pathlib import Path GUARD_L = {"mShoulderLeft": [0.35, 0.4, -0.85], "mElbowLeft": [0.55, -0.35, 0.75]} GUARD_R = {"mShoulderRight": [0.25, -0.4, -0.88], "mElbowRight": [0.5, 0.4, 0.75]} JAB_L = {"mShoulderLeft": [1, 0.12, 0.08], "mElbowLeft": [1, 0.0, 0.06]} CROSS_R = {"mShoulderRight": [1, -0.02, 0.1], "mElbowRight": [1, 0.08, 0.06]} HOOK_L = {"mShoulderLeft": [0.25, 1, 0.05], "mElbowLeft": [1, -0.4, 0.05]} LEGS = {"mHipLeft": [0.25, 0.08, -0.97], "mKneeLeft": [0.15, 0.08, -0.99], "mAnkleLeft": [1, 0, 0], "mHipRight": [-0.18, -0.1, -0.98], "mKneeRight": [-0.05, -0.1, -0.99], "mAnkleRight": [1, 0, 0]} seq = [ # t, arms, torso yaw, bounce (0.0, {**GUARD_L, **GUARD_R}, 10, 0.0), (0.2, {**GUARD_L, **GUARD_R}, 10, -0.04), (0.35, {**JAB_L, **GUARD_R}, 0, 0.0), (0.55, {**GUARD_L, **GUARD_R}, 10, -0.04), (0.7, {**JAB_L, **GUARD_R}, 0, 0.0), (0.9, {**GUARD_L, **GUARD_R}, 10, -0.04), (1.15, {**GUARD_L, **CROSS_R}, 35, -0.02), (1.4, {**GUARD_L, **GUARD_R}, 10, -0.04), (1.65, {**HOOK_L, **GUARD_R}, -30, -0.02), (1.9, {**GUARD_L, **GUARD_R}, 10, -0.04), (2.15, {**GUARD_L, **GUARD_R}, 10, 0.0), (2.4, {**GUARD_L, **GUARD_R}, 10, 0.0)] keys = [{"t": t, "pos": {"mPelvis": [0, 0, -0.06 + b]}, "rot": {"mTorso": [0, 8, yaw], "mHead": [0, 6, -yaw * 0.6]}, "aim": {**arms, **LEGS}} for t, arms, yaw, b in seq] spec = {"name": "shadow boxing", "duration": 2.4, "priority": 5, "loop": True, "loop_in": 0.0, "loop_out": 2.4, "ease_in": 0.3, "ease_out": 0.3, "hand_pose": "fist", "keys": keys} Path(__file__).with_name("shadowbox.json").write_text("// generated by gen_shadowbox.py\n" + json.dumps(spec, indent=1))