Skip to content

Analytical FK backward: 9x faster gradient computation#70

Merged
LemonPi merged 3 commits into
masterfrom
johnson/analytical-fk-backward
Apr 15, 2026
Merged

Analytical FK backward: 9x faster gradient computation#70
LemonPi merged 3 commits into
masterfrom
johnson/analytical-fk-backward

Conversation

@LemonPi

@LemonPi LemonPi commented Apr 15, 2026

Copy link
Copy Markdown
Member

Summary

  • Replace autograd's graph-based backward through forward_kinematics_tensor with an analytical geometric Jacobian, yielding ~9x faster gradient computation on GPU and ~2.7x on CPU
  • The change is transparent — forward_kinematics_tensor(th) automatically uses the analytical backward when th.requires_grad=True. No API changes for existing callers
  • Extract _fk_impl as a standalone FK function and add _FKAnalyticalBackward custom autograd Function
  • Compatible with torch.compile and torch.vmap
  • Add analytical_grad=False escape hatch for callers that need higher-order gradients (create_graph=True) or gradients w.r.t. chain parameters
  • Add 3 new tests validating gradient correctness against finite differences (revolute-only, mixed revolute+prismatic, batched)
  • Bump version to 0.10.0

Benchmark (RTX 4070, H=10000 configs, 30-DOF robot)

Forward only Forward + backward (autograd) Forward + backward (analytical)
GPU 5.6ms 70.8ms 8.3ms
CPU 64.8ms 247.5ms 92.9ms

How it works

The analytical backward computes d(loss)/d(joint_angles) directly from the geometric Jacobian rather than replaying the autograd computation graph. For each DOF j, it sums contributions from all descendant links using a precomputed ancestor mask:

  • Revolute: d(loss)/d(q_j) = z_j · Σ_l (τ_l + (t_l - o_j) × ∂L/∂t_l)
  • Prismatic: d(loss)/d(q_j) = z_j · Σ_l ∂L/∂t_l

where τ_l captures the rotation gradient and the cross product term captures the translation gradient.

Breaking changes

The analytical backward only computes gradients w.r.t. joint angles. Two features from the old autograd path are not supported by default:

  • Higher-order gradients (create_graph=True)
  • Gradients w.r.t. chain parameters (e.g., link offsets for calibration)

Both are restored by passing analytical_grad=False to forward_kinematics_tensor.

Test plan

  • All 51 tests pass (48 existing + 3 new gradient correctness tests)
  • Gradient correctness validated against finite differences at float64
  • No regression on forward-only (no-grad) performance
  • torch.compile and torch.vmap compatibility verified

🤖 Generated with Claude Code

LemonPi and others added 2 commits April 15, 2026 15:12
Replace autograd's graph-based backward through forward_kinematics_tensor
with an analytical geometric Jacobian. The change is transparent — the
analytical backward is used automatically when th.requires_grad=True.

- Extract _fk_impl as standalone FK function
- Add _FKAnalyticalBackward custom autograd Function
- Precompute DOF-to-frame mapping and ancestor masks at chain init
- Compatible with torch.compile and torch.vmap
- Add 3 tests validating gradient correctness against finite differences
- Bump version to 0.10.0

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Allows callers to opt out of the analytical backward by passing
analytical_grad=False, falling back to standard autograd. This restores
support for higher-order gradients (create_graph=True) and gradients
w.r.t. chain parameters when needed.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@LemonPi LemonPi force-pushed the johnson/analytical-fk-backward branch from 38cfef7 to d9c64c5 Compare April 15, 2026 22:53
Move FK computation out of autograd.Function.forward() so apply() only
receives plain tensors. The old design passed bfs_levels (list[Tensor])
through apply(), which torch._dynamo (PyTorch 2.4+) cannot trace.

New design: compute FK on th.detach() first, then use the Function purely
to attach the analytical backward — all apply() args are plain tensors.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@LemonPi LemonPi force-pushed the johnson/analytical-fk-backward branch from d9c64c5 to 7a67ac2 Compare April 15, 2026 23:10
@LemonPi LemonPi merged commit b22e68b into master Apr 15, 2026
4 checks passed
@LemonPi LemonPi deleted the johnson/analytical-fk-backward branch April 15, 2026 23:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant