Use discrete dynamics Jacobians in solvers#179
Conversation
Differentiate the integrated discrete dynamics map for first-order Jacobians and pass the resulting STM directly through the DDP solvers. Add RK4 regressions that compare getJacobians against finite differences of getDiscreteDynamics and guard against Euler-style rescaling.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 3020bbb607
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| consistent = (A_ad - A_fd).cwiseAbs().maxCoeff() <= 1e-5 * jac_scale && | ||
| (B_ad - B_fd).cwiseAbs().maxCoeff() <= 1e-5 * jac_scale; | ||
| } | ||
| discrete_autodiff_status_ = consistent ? 1 : -1; |
There was a problem hiding this comment.
Synchronize the autodiff status cache
When enable_parallel is set, the solver precompute paths call getJacobians() from multiple std::async workers on the same DynamicalSystem instance. This new mutable cache is read and then written during first-use initialization without an atomic, mutex, or std::once_flag, so the first parallel backward pass can data-race while deciding between autodiff and finite-difference Jacobians; that is undefined behavior and can produce inconsistent derivative paths or be flagged by thread sanitizers.
Useful? React with 👍 / 👎.
Summary
This PR makes the first-order dynamics Jacobian contract discrete:
getJacobians()now returns Jacobians of the integrated mapx_{k+1} = F(x_k, u_k), and solver backward passes consume those matrices directly as the state-transition linearization.Changes
getDiscreteDynamics()and a finite-difference fallback when the autodiff discrete map is not usable.CDDPSolverBaseprecomputation plus CLDDP, LogDDP, and MSIPDDP direct Jacobian consumers to use the returned discrete STM directly instead of applyingI + dt * Fxanddt * Fu.getDiscreteDynamics()and guard against Euler-style rescaling.Test Plan
cmake --build build2 --parallel 4make testfrom/home/astomodynamics/naiten_ws/cddp-cpp/build2(153/153passed)Related Issues
None.
How to Test
Run the CMake build, then run
make testfrom the generated build directory.Screenshots/Videos
Not applicable.
Additional Notes
This PR fixes the first-order STM contract. The existing second-order dynamics Hessian path still follows the prior continuous-dynamics Hessian approximation, so a future change should make full DDP second-order terms discrete as well.