# Joint Calibration Log Using simple basis change: `R_delta_robot = R_basis @ R_delta_xr @ R_basis.T` Decomposition order for shoulders: YXZ Euler (matches URDF: pitch(Y), roll(X), yaw(Z)) ## l_shoulder_pitch (joint 15) - DONE - Robot motion: sine ±0.6 rad, period 8s (arm forward/backward) - XR parent-child: chest -> l_upper - **Result**: Y component (YXZ Euler) correlates positively with robot motion - Robot +0.57 → XR Y ≈ +0.3 to +0.6 - Robot -0.58 → XR Y ≈ -1.0 to -1.1 - **Sign**: `SIGN_SH_L[0] = +1` (CORRECT, same sign) - Note: X (roll) had constant negative offset (~-0.4 to -0.8), likely natural arm rotation during pitch motion ## l_shoulder_roll (joint 16) - DONE - Robot motion: sine ±0.6 rad, period 8s (arm out to left side) - XR parent-child: chest -> l_upper - **Result**: Z component (YXZ Euler) correlates with robot roll, NOT X - Robot +0.60 → Z ≈ +0.93 to +1.23 - Robot -0.60 → Z ≈ +0.05 (can't push arm into body) - **Sign**: +1 (same sign) - **Important**: This means YXZ Euler order may be wrong, or axis assignment needs swapping (roll=Z, yaw=X?) ## l_shoulder_yaw (joint 17) - DONE - Robot motion: sine ±0.4 rad, period 8s (upper arm twist inward/outward) - XR parent-child: chest -> l_upper - **Result**: X component (YXZ Euler) correlates negatively with robot yaw - Robot +0.40 → X ≈ -0.90 to -0.98 - Robot -0.40 → X ≈ -0.001 to -0.09 - **Sign**: -1 (inverted) ### LEFT SHOULDER SUMMARY - Pitch → Y component of YXZ, sign +1 - Roll → Z component of YXZ, sign +1 - Yaw → X component of YXZ, sign -1 - **Effective Euler order is YZX, not YXZ!** - Code fix: `as_euler('YZX')` gives (pitch, roll, yaw) directly, with yaw negated ## l_elbow (joint 18) - DONE - Robot motion: sine ±0.7 rad, period 8s (elbow bend/extend) - XR parent-child: l_upper -> l_lower - **Result**: Z component (YXZ Euler) correlates positively with robot elbow - Robot +0.69 → Z ≈ +0.82 to +0.92 - Robot -0.69 → Z ≈ -0.65 to -0.93 - **Sign**: +1 (same sign) - Note: Currently code extracts Y[0] for elbow, should use Z[2] ## r_shoulder_pitch (joint 22) - DONE - Robot motion: sine ±0.6 rad, period 8s (right arm forward/backward) - XR parent-child: chest -> r_upper - **Result**: Y component (YXZ Euler) has weak positive correlation - Large constant offset (~0.8 rad) - user's arm drifted forward - Robot +0.6 → Y ≈ 0.92, Robot -0.6 → Y ≈ 0.76 (difference ~0.16) - **Sign**: +1 (same as left, weak signal) - **Note**: Right arm Quest tracking is significantly weaker than left ## r_shoulder_roll (joint 23) - DONE - Robot motion: sine ±0.6 rad, period 8s (right arm out to side) - XR parent-child: chest -> r_upper - **Result**: Z component (YXZ Euler) correlates (weak/intermittent signal) - Robot -0.60 (arm out) → Z ≈ -0.82 to -0.96 (strong cycles) - Robot +0.60 (arm in) → Z ≈ +0.07 - **Sign**: +1 (same sign) - **Note**: Very noisy, right arm Quest tracking weak ## r_shoulder_yaw (joint 24) - SKIPPED - Assumed same as left: X component, sign -1 (right arm tracking too weak for subtle yaw) ## r_elbow (joint 25) - DONE - Robot motion: sine ±0.7 rad, period 8s (right elbow bend) - XR parent-child: r_upper -> r_lower - **Result**: ALL axes near zero (max ±0.07 despite ±0.7 robot motion) - Quest right arm tracking is extremely weak - barely detects elbow bend - **Assumed**: Same mapping as left elbow (Z component, sign +1) ## EXTENT TUNING ### l_shoulder_pitch (joint 15) - Backward (positive): +0.8 rad (+45.8 deg) — OK - Forward (negative): -2.4 rad (-137.5 deg) — OK - Note: positive = backward, negative = forward for this joint - Settings: amplitude=1.6, offset=-0.8 ### l_shoulder_roll (joint 16) - Inward (negative): ~0 rad (0 deg) — just touching body, no clipping - Outward (positive): +1.585 rad (+91 deg) — arm straight out to side - Settings: amplitude=0.8, offset=0.785 - Note: needs outward bias to avoid body clipping ### l_shoulder_yaw (joint 17) - Inward (positive): +1.15 rad (+66 deg) - Outward (negative): -1.15 rad (-66 deg) - Settings: amplitude=1.15, offset=0.0 - Note: clips into body at rest pose but OK since other joints move arm away in practice ### l_elbow (joint 18) - Extend (negative): -0.8 rad (-45.8 deg) - Bend (positive): +1.33 rad (+76.2 deg) - Settings: amplitude=1.065, offset=0.265 - Note: positive = bend, negative = extend (opposite of label in joint_test.py) ### l_wrist_roll (joint 19) - Palm down (positive): +1.35 rad (+77.3 deg) - Palm up (negative): -1.35 rad (-77.3 deg) - Settings: amplitude=1.35, offset=0.0 - Note: positive = palm down, negative = palm up (opposite of label) ### l_wrist_pitch (joint 20) - Wrist down (positive): +0.8 rad (+45.8 deg) - Wrist up (negative): -0.8 rad (-45.8 deg) - Settings: amplitude=0.8, offset=0.0 - Directions confirmed correct ### l_wrist_yaw (joint 21) - Inward (negative): -1.28 rad (-73 deg) - Outward (positive): +0.5 rad (+29 deg) - Settings: amplitude=0.89, offset=-0.39 - Note: negative = inward, positive = outward ## OVERALL AXIS MAPPING SUMMARY After `R_basis @ R_delta @ R_basis.T` + `as_euler('YXZ')` → (Y, X, Z): ### Shoulder (chest → upper_arm) — parent roughly upright: - Robot pitch (Y joint) = Y component [0], sign +1 - Robot roll (X joint) = Z component [2], sign +1 - Robot yaw (Z joint) = X component [1], sign -1 ### Elbow (upper_arm → lower_arm) — parent hangs down: - Robot pitch (Y joint) = Z component [2], sign +1 - Note: axis mapping differs from shoulder because parent orientation differs ### Why axes differ per joint: The basis change `R_basis @ R_delta @ R_basis.T` treats the delta as if in XR world-aligned frame, but the delta is in the PARENT's local frame. When the parent hangs down (upper arm), its local axes are rotated ~90° from world, causing the axis mapping to shift.