This page introduces Aligator, a trajectory optimization library implementing ProxDDP and FDDP algorithms for robotics. It covers the library's architecture, core components, and solver implementations. For specific subsystems, see: Getting Started, Core Concepts, ProxDDP Solver, FDDP Solver, Problem Modeling, Linear Algebra Subsystem (GAR), and Advanced Features.
Sources: README.md1-27 CHANGELOG.md1-489
Aligator is a C++ library with Python bindings for constrained trajectory optimization. It implements two main solvers: SolverProxDDPTpl<Scalar> (Proximal Differential Dynamic Programming with augmented Lagrangian constraint handling) and SolverFDDPTpl<Scalar> (Feasible Differential Dynamic Programming). The library handles complex robotic systems with constraints, manifold state spaces (via ManifoldAbstractTpl<Scalar>), and contacts, integrating with Pinocchio for rigid-body dynamics.
Primary applications include motion generation, model-predictive control (MPC), optimal estimation, and planning for legged robots and manipulators.
Sources: README.md9-27 package.xml3-7 include/aligator/solvers/proxddp/solver-proxddp.hpp27-34 include/aligator/solvers/fddp/solver-fddp.hpp23-28
Aligator provides:
Solver Algorithms: Two main solvers implementing state-of-the-art trajectory optimization algorithms:
SolverProxDDPTpl - Proximal Differential Dynamic Programming with augmented Lagrangian constraint handlingSolverFDDPTpl - Feasible Differential Dynamic ProgrammingModular Problem Formulation: Stage-by-stage problem definition through StageModelTpl, supporting:
CostStackTplConstraintStackTplAdvanced State Spaces: Support for manifolds and Lie groups through ManifoldAbstractTpl, including:
VectorSpaceTpl)Parallel Computation: OpenMP-based parallelization with gar::ParallelRiccatiSolver for solving linear-quadratic subproblems
Pinocchio Integration: Deep integration with the Pinocchio rigid-body dynamics library for robotic applications
Dual Language Support: Full-featured Python API built on C++ implementation using Boost.Python and eigenpy
Sources: README.md:17-31, include/aligator/solvers/proxddp/solver-proxddp.hpp:27-34, include/aligator/solvers/fddp/solver-fddp.hpp:24-27
System Architecture Diagram
Architecture Overview: Aligator implements a layered architecture with four main subsystems. The User Interface Layer provides Python bindings (via Boost.Python and eigenpy) and C++ templates instantiated for double scalar type. The Problem Definition Layer uses TrajOptProblemTpl<Scalar> as the main container, holding multiple StageModelTpl<Scalar> instances that define per-timestep dynamics, costs, and constraints. The Solver Layer implements SolverProxDDPTpl<Scalar> (augmented Lagrangian method) and SolverFDDPTpl<Scalar> (feasibility-preserving method), which iteratively solve the nonlinear trajectory optimization problem. The Linear Algebra Backend (GAR) provides specialized Riccati solvers (gar::ProximalRiccatiSolver, gar::ParallelRiccatiSolver, gar::RiccatiSolverDense) that efficiently solve the linear-quadratic subproblems arising in each DDP iteration.
Sources: include/aligator/core/traj-opt-problem.hpp1-100 include/aligator/core/stage-model.hpp1-150 include/aligator/solvers/proxddp/solver-proxddp.hpp35-183 include/aligator/solvers/fddp/solver-fddp.hpp28-96 include/aligator/gar/riccati-base.hpp1-50 README.md19-31
Data Flow and Object Ownership
Object Relationships: User code creates a TrajOptProblemTpl<Scalar> containing a vector stages_ of shared_ptr<StageModelTpl<Scalar>> instances. When solver.setup(problem) is called, the solver allocates WorkspaceTpl<Scalar> and ResultsTpl<Scalar> instances as member variables. During problem.evaluate(), function values and derivatives are cached in TrajOptDataTpl<Scalar> (stored in workspace_.problem_data), which contains StageDataTpl<Scalar> objects for each stage. The solver operates on workspace_ to compute trajectory updates, storing final solutions in results_.
Sources: include/aligator/core/traj-opt-problem.hpp1-100 include/aligator/core/stage-model.hpp1-150 include/aligator/solvers/proxddp/solver-proxddp.hpp35-183 include/aligator/solvers/proxddp/workspace.hpp27-132 include/aligator/solvers/proxddp/results.hpp1-50
ProxDDP Solver Execution Flow
Algorithm Flow: SolverProxDDPTpl<Scalar>::run() implements a two-level optimization algorithm. The outer augmented Lagrangian loop (tracking results_.al_iter) adjusts the penalty parameter mu_penal_ via setAlmPenalty() solver-proxddp.hxx326-328 and tolerances via updateTolsOnFailure() solver-proxddp.hxx313-317/updateTolsOnSuccess() solver-proxddp.hxx319-323 Each outer iteration calls innerLoop() solver-proxddp.hxx552-698 which performs DDP iterations:
problem.evaluate() computes costs and dynamics into workspace_.problem_dataproblem.computeDerivatives() computes Jacobians and HessiansLagrangianDerivatives::compute() computes gradients Lxs, Lus accounting for multiplierscomputeMultipliers() solver-proxddp.hxx217-315 updates multiplier estimates lams_plus, vs_pluscomputeProjectedJacobians() solver-proxddp.hxx23-67 applies constraint set projectionsupdateLQSubproblem() solver-proxddp.hxx731-802 builds the LQ approximation in workspace_.lqr_problemlinear_solver_->backward() performs Riccati recursion to compute value functionslinear_solver_->forward() computes primal-dual steps dxs, dus, dvs, dlamsforwardPass() solver-proxddp.hxx533-549 performs linesearch evaluating the augmented Lagrangian merit functionresults_.xs, results_.us, results_.lams, results_.vsConvergence is checked via results_.dual_infeas (stationarity) and results_.prim_infeas (constraint violation).
Sources: include/aligator/solvers/proxddp/solver-proxddp.hxx156-802 include/aligator/solvers/proxddp/solver-proxddp.hpp98-241
| Solver Class | Algorithm | Constraint Handling | Primary Use Case |
|---|---|---|---|
SolverProxDDPTpl | Proximal DDP | Augmented Lagrangian with proximal terms | General constrained trajectory optimization |
SolverFDDPTpl | Feasible DDP | Maintains feasibility via specialized rollout | Problems with strict feasibility requirements |
The GAR (Generalized Algebraic Riccati) subsystem provides three implementations of gar::RiccatiSolverBase<Scalar>, selectable via the LQSolverChoice enum:
| Solver Class | Enum Value | Description | Configuration |
|---|---|---|---|
gar::ProximalRiccatiSolver<Scalar> | LQSolverChoice::SERIAL | Serial Riccati backward-forward passes | Default, single-threaded |
gar::ParallelRiccatiSolver<Scalar> | LQSolverChoice::PARALLEL | Parallel Riccati with problem decomposition | Requires linear_solver_choice = PARALLEL and setNumThreads(n) before setup() |
gar::RiccatiSolverDense<Scalar> | LQSolverChoice::STAGEDENSE | Stage-wise dense formulation using Bunch-Kaufman | Special problem structures |
The solver is instantiated in SolverProxDDPTpl::setup() solver-proxddp.hxx170-195 based on linear_solver_choice. All three inherit from gar::RiccatiSolverBase<Scalar> providing the interface:
backward(mu) - backward Riccati recursion computing value functionsforward(dxs, dus, dvs, dlams) - forward pass computing trajectory correctionsgetFeedforward(i), getFeedback(i) - access computed gainsSources: include/aligator/solvers/proxddp/solver-proxddp.hpp25-26 include/aligator/solvers/proxddp/solver-proxddp.hxx170-195 bindings/python/src/expose-solver-prox.cpp67-71 include/aligator/gar/riccati-base.hpp1-50
Aligator uses allocator-aware design for high-performance memory management:
| Component | Type | Purpose |
|---|---|---|
mimalloc_resource | Custom memory resource | Wraps mimalloc allocator (introduced v0.17.0) |
polymorphic_allocator | C++17 PMR allocator | Propagates through allocator-aware containers |
ArenaMatrix<VectorXs> | Allocator-aware matrix wrapper | Manages Eigen matrix-like objects with custom allocation |
WorkspaceTpl<Scalar> | Allocator-aware workspace | Constructor takes allocator_type argument |
gar::LqrProblemTpl<Scalar> | Allocator-aware LQR data | Stores knots with custom allocator |
The SolverProxDDPTpl<Scalar> owns a mimalloc_resource memory_resource_ and polymorphic_allocator allocator_ solver-proxddp.hpp176-177 which are passed to workspace_ and lqr_problem constructors solver-proxddp.hxx156-165
Parallel Execution: Enable parallel Riccati solver with:
The setNumThreads() method solver-proxddp.hxx97-106 sets num_threads_ and calls omp::set_default_options(). In setup(), if PARALLEL is selected, a gar::ParallelRiccatiSolver<Scalar> is instantiated solver-proxddp.hxx176-188 decomposing the problem into parallel "legs" solved via OpenMP. Thread affinity is controlled via OMP_PLACES and OMP_NUM_THREADS environment variables (see doc/advanced-user-guide.md80-156).
Sources: CHANGELOG.md22-23 CHANGELOG.md74-99 CHANGELOG.md152-157 include/aligator/solvers/proxddp/solver-proxddp.hpp176-177 include/aligator/solvers/proxddp/solver-proxddp.hxx97-106 include/aligator/solvers/proxddp/solver-proxddp.hxx156-195 doc/advanced-user-guide.md55-156
Aligator provides dual-language interfaces with full feature parity:
C++ API: Template library with explicit instantiations for context::Scalar (typically double). Users include headers from <aligator/...> and link against libaligator.so. Template instantiations are controlled by ALIGATOR_ENABLE_TEMPLATE_INSTANTIATION (see include/aligator/solvers/proxddp/solver-proxddp.hpp351-353).
Python API: Built using Boost.Python and eigenpy, exposed through the aligator Python module:
| Python Class | C++ Template | Binding File |
|---|---|---|
aligator.SolverProxDDP | SolverProxDDPTpl<Scalar> | bindings/python/src/expose-solver-prox.cpp114-195 |
aligator.SolverFDDP | SolverFDDPTpl<Scalar> | bindings/python/src/expose-solver-fddp.cpp73-82 |
aligator.TrajOptProblem | TrajOptProblemTpl<Scalar> | (exposed in problem bindings) |
aligator.StageModel | StageModelTpl<Scalar> | (exposed in core bindings) |
Bindings use visitor pattern (defined in bindings/python/include/aligator/python/solvers.hpp14-59) to reduce boilerplate:
SolverVisitor<SolverType> - exposes common solver interface (verbose, max_iters, callbacks, etc.)PrintableVisitor<T> - adds __str__ and __repr__ methodsCopyableVisitor<T> - adds __copy__ method (introduced v0.16.0)Data conversion between NumPy arrays and Eigen matrices is handled automatically by eigenpy CHANGELOG.md86-89
Sources: README.md94-99 bindings/python/src/expose-solver-prox.cpp58-211 bindings/python/src/expose-solver-fddp.cpp16-83 bindings/python/include/aligator/python/solvers.hpp14-59 CHANGELOG.md86-92
Aligator uses CMake as its build system with optional Pixi package management:
Required Dependencies:
Optional Dependencies:
BUILD_WITH_PINOCCHIO_SUPPORT)BUILD_CROCODDYL_COMPAT)The library can be built with cmake directly or using pixi run test for reproducible builds with dependency management via pixi.toml and pixi.lock.
Sources: README.md:68-80, README.md:33-67, package.xml:13-20, CHANGELOG.md:113-114
Refresh this wiki
This wiki was recently refreshed. Please wait 6 days to refresh again.