DirectTrajOpt.jl
DirectTrajOpt.jl is a framework for direct trajectory optimization via nonlinear programming. It converts continuous optimal control problems into finite-dimensional NLPs using direct transcription, then solves them with Ipopt.
Problem Formulation
DirectTrajOpt solves problems of the form:
\[\begin{align*} \underset{x_{1:N}, u_{1:N}}{\text{minimize}} \quad & J(x_{1:N}, u_{1:N}) \\ \text{subject to} \quad & f(x_{k+1}, x_k, u_k, \Delta t, t_k) = 0, \quad k = 1, \ldots, N-1\\ & c_k(x_k, u_k) \geq 0, \quad k = 1, \ldots, N \\ & x_1 = x_{\text{init}}, \quad x_N = x_{\text{goal}} \\ \end{align*}\]
where:
J(x, u)is the objective function to minimizef(.)represents system dynamics encoded via integratorsc(.)represents additional nonlinear constraintsxis the state trajectoryuis the control trajectory
Installation
using Pkg
Pkg.add("DirectTrajOpt")Quick Example
using DirectTrajOpt
using NamedTrajectories
# Define trajectory
traj = NamedTrajectory(
(x = randn(2, 50), u = randn(1, 50), Δt = fill(0.1, 50));
timestep=:Δt,
controls=:u,
initial=(x = [0.0, 0.0],),
final=(x = [1.0, 0.0],)
)
# Define dynamics: dx/dt = (A + u * B) * x
G_drift = [-0.1 1.0; -1.0 -0.1]
G_drives = [[0.0 1.0; 1.0 0.0]]
G = u -> G_drift + sum(u .* G_drives)
integrator = BilinearIntegrator(G, :x, :u, traj)
# Define objective
obj = QuadraticRegularizer(:u, traj, 1.0)
# Create and solve problem
prob = DirectTrajOptProblem(traj, obj, integrator)
solve!(prob; max_iter=100)Key Features
- Flexible dynamics: Define system evolution via bilinear, time-dependent, or derivative integrators
- Modular objectives: Combine cost terms with
+and*(regularization, minimum time, terminal cost, etc.) - Constraint support: Bounds, equality, nonlinear, symmetry, and L1 slack constraints
- Automatic differentiation: Sparse Jacobians and Hessians via ForwardDiff
- Solver callbacks: Monitor and control the optimization process
Contributing
Building Documentation
This package uses a shared Documenter config. First-time setup:
./docs/get_docs_utils.shBuild docs:
julia --project=docs docs/make.jlLive editing:
julia --project=docs -e '
using LiveServer, DirectTrajOpt, Revise
servedocs(
literate_dir="docs/literate",
skip_dirs=["docs/src/generated", "docs/src/assets/"],
skip_files=["docs/src/index.md"]
)'Note:
servedocswill loop if it watches generated files. Ensure all generated files are in the skip dirs/files args.