Quickstart Guide

Welcome to DirectTrajOpt.jl! This guide will get you up and running in minutes.

What is DirectTrajOpt?

DirectTrajOpt.jl solves trajectory optimization problems - finding optimal control sequences that drive a dynamical system from an initial state to a goal state while minimizing a cost function.

Installation

First, install the package:

using Pkg
Pkg.add("DirectTrajOpt")

You'll also need NamedTrajectories.jl for defining trajectories:

using DirectTrajOpt
using NamedTrajectories
using LinearAlgebra
using CairoMakie

A Minimal Example

Let's solve a simple problem: drive a 2D system from [0, 0] to [1, 0] with minimal control effort.

Step 1: Define the Trajectory

A trajectory contains your states, controls, and time information:

N = 50  # number of time steps
traj = NamedTrajectory(
    (
        x = randn(2, N),    # 2D state
        u = randn(1, N),    # 1D control
        Δt = fill(0.1, N),   # time step
    );
    timestep = :Δt,
    controls = :u,
    initial = (x = [0.0, 0.0],),
    final = (x = [1.0, 0.0],),
    bounds = (Δt = (0.05, 0.2), u = 1.0),
)
N = 50, (x = 1:2, u = 3:3, → Δt = 4:4)

Step 2: Define the Dynamics

Specify how your system evolves. For bilinear dynamics ẋ = (G₀ + u₁G₁) x:

G_drift = [-0.1 1.0; -1.0 -0.1]   # drift term
G_drives = [[0.0 1.0; 1.0 0.0]]   # control term
G = u -> G_drift + sum(u .* G_drives)

integrator = BilinearIntegrator(G, :x, :u, traj)
BilinearIntegrator: :x = exp(Δt G(:u)) :x  (dim = 2)

Step 3: Define the Objective

What do we want to minimize? Let's penalize control effort:

obj = QuadraticRegularizer(:u, traj, 1.0)
QuadraticRegularizer on :u (R = [1.0], all)

Step 4: Create and Solve

Combine everything into a problem and solve:

prob = DirectTrajOptProblem(traj, obj, integrator)
DirectTrajOptProblem
  Trajectory
    Timesteps: 50
    Duration:  4.9
    Knot dim:  4
    Variables: x (2), u (1), Δt (1)
    Controls:  u, Δt
  Objective: QuadraticRegularizer on :u (R = [1.0], all)
  Dynamics (1 integrators)
    BilinearIntegrator: :x = exp(Δt G(:u)) :x  (dim = 2)
  Constraints (4 total: 2 equality, 2 bounds)
    EqualityConstraint: "initial value of x"
    EqualityConstraint: "final value of x"
    BoundsConstraint: "bounds on Δt"
    BoundsConstraint: "bounds on u"

The problem summary shows the trajectory, objective, dynamics, and constraints:

prob
DirectTrajOptProblem
  Trajectory
    Timesteps: 50
    Duration:  4.9
    Knot dim:  4
    Variables: x (2), u (1), Δt (1)
    Controls:  u, Δt
  Objective: QuadraticRegularizer on :u (R = [1.0], all)
  Dynamics (1 integrators)
    BilinearIntegrator: :x = exp(Δt G(:u)) :x  (dim = 2)
  Constraints (4 total: 2 equality, 2 bounds)
    EqualityConstraint: "initial value of x"
    EqualityConstraint: "final value of x"
    BoundsConstraint: "bounds on Δt"
    BoundsConstraint: "bounds on u"
solve!(prob; max_iter = 100, verbose = false)
This is Ipopt version 3.14.19, running with linear solver MUMPS 5.8.2.

Number of nonzeros in equality constraint Jacobian...:      776
Number of nonzeros in inequality constraint Jacobian.:        0
Number of nonzeros in Lagrangian Hessian.............:     1254

Total number of variables............................:      196
                     variables with only lower bounds:        0
                variables with lower and upper bounds:      100
                     variables with only upper bounds:        0
Total number of equality constraints.................:       98
Total number of inequality constraints...............:        0
        inequality constraints with only lower bounds:        0
   inequality constraints with lower and upper bounds:        0
        inequality constraints with only upper bounds:        0

iter    objective    inf_pr   inf_du lg(mu)  ||d||  lg(rg) alpha_du alpha_pr  ls
   0  1.1395896e-01 3.99e+00 1.08e+16   0.0 0.00e+00    -  0.00e+00 0.00e+00   0
   1  1.1013395e-01 3.99e+00 4.46e-01  -2.1 3.67e+15    -  3.92e-17 3.92e-17s 78
   2  2.0519496e-01 2.24e+00 2.11e+00  -0.4 3.92e+00    -  9.74e-01 4.45e-01f  1
   3  1.4075449e-01 1.61e-01 2.19e+00  -0.9 1.58e+00    -  5.14e-01 1.00e+00h  1
   4  1.2875431e-01 7.33e-02 2.96e+00  -0.6 2.74e+00    -  3.72e-01 5.55e-01h  1
   5  2.2291392e-01 3.99e-02 1.61e+00  -1.1 1.36e+00    -  4.82e-01 4.95e-01h  1
   6  3.2021500e-01 2.61e-02 4.57e+00  -1.1 2.45e+00    -  6.44e-01 3.90e-01h  1
   7  5.4102455e-01 1.24e-02 1.55e+01  -1.2 1.20e+00    -  9.95e-01 5.70e-01h  1
   8  7.0035150e-01 7.46e-03 3.51e+01  -1.4 4.42e-01   0.0 1.00e+00 3.99e-01h  1
   9  7.5659013e-01 6.85e-03 5.10e+01  -0.5 1.09e+01  -0.5 1.00e+00 6.98e-02h  1
iter    objective    inf_pr   inf_du lg(mu)  ||d||  lg(rg) alpha_du alpha_pr  ls
  10  7.8464744e-01 6.57e-03 5.16e+02   0.3 1.24e+01    -  1.00e+00 4.00e-02h  1
  11  8.6454916e-01 5.47e-03 6.77e+03   0.6 2.79e+00    -  1.00e+00 1.51e-01h  1
  12  9.1031736e-01 5.19e-03 5.81e+04  -4.0 3.32e+00    -  3.50e-02 4.93e-02h  1
  13  9.1461374e-01 5.15e-03 2.26e+05   0.4 1.01e+00    -  1.00e+00 6.85e-03h  1
  14  9.2157030e-01 5.08e-03 1.64e+07  -0.3 5.74e-01    -  1.00e+00 1.37e-02h  1
  15  9.2165371e-01 5.08e-03 1.03e+11   1.5 2.41e+00    -  1.00e+00 1.59e-04h  1
  16  9.2165356e-01 5.08e-03 1.01e+09   2.7 1.36e-06  11.4 9.90e-01 1.00e+00f  1
  17  9.2723061e-01 5.08e-03 1.51e+09   2.7 2.67e+04    -  3.66e-05 3.74e-05h  1
  18r 9.2723061e-01 5.08e-03 9.95e+02   2.4 0.00e+00    -  0.00e+00 3.89e-07R  5
  19r 9.2723717e-01 4.78e-03 1.08e+01  -3.7 2.53e-01    -  9.89e-01 9.80e-01f  1
iter    objective    inf_pr   inf_du lg(mu)  ||d||  lg(rg) alpha_du alpha_pr  ls
  20r 9.2758099e-01 9.62e-04 3.83e+00  -4.0 3.69e-02    -  9.48e-01 9.06e-01f  1
  21  9.2844942e-01 9.61e-04 6.63e+00  -4.0 7.04e+00    -  7.95e-03 1.04e-03h  1
  22  9.3992605e-01 9.56e-04 1.17e+03  -0.8 1.50e+01    -  8.65e-01 5.67e-03f  1
  23  9.4127715e-01 9.53e-04 2.39e+05  -0.4 2.91e+00    -  1.00e+00 2.83e-03h  1
  24  9.4205143e-01 9.51e-04 1.23e+08  -0.3 4.38e-01    -  1.00e+00 1.90e-03h  1
  25  9.4207348e-01 9.86e-04 1.23e+08   0.0 6.94e-02    -  1.41e-02 1.41e-02s 16
  26  9.4207367e-01 9.86e-04 1.27e+13   0.0 6.77e-02    -  1.00e+00 1.82e-05h  1
  27  9.4207247e-01 1.27e-03 1.26e+11   0.0 3.22e-02    -  9.90e-01 1.56e-02h  7
  28  9.4207247e-01 1.26e-03 9.21e+08   0.0 1.68e-06  10.9 9.93e-01 1.00e+00f  1
  29  9.4207251e-01 1.27e-03 8.96e+11   0.0 3.16e-02    -  1.00e+00 1.39e-03h  1
iter    objective    inf_pr   inf_du lg(mu)  ||d||  lg(rg) alpha_du alpha_pr  ls
  30  9.4207253e-01 1.27e-03 7.90e+09   0.0 3.77e-02    -  9.90e-01 1.22e-04f 14
  31  9.4207254e-01 1.25e-03 2.47e+05   0.0 9.55e-06  10.4 1.00e+00 1.00e+00f  1
  32r 9.4207254e-01 1.25e-03 9.99e+02  -0.7 0.00e+00    -  0.00e+00 3.42e-07R 10
  33r 9.4127747e-01 1.17e-03 6.93e+02  -0.5 8.17e-03    -  9.90e-01 2.42e-01f  1
  34r 8.0990232e-01 3.59e-03 3.04e+01  -0.8 1.31e-01    -  7.33e-01 1.00e+00f  1
  35r 8.4538476e-01 6.11e-03 5.66e-02  -1.9 2.00e-02    -  1.00e+00 1.00e+00f  1
  36r 9.1534277e-01 4.98e-03 2.53e-01  -3.2 6.64e-02    -  9.84e-01 1.00e+00f  1
  37r 9.4008073e-01 4.76e-03 1.51e-02  -4.0 4.12e-02    -  1.00e+00 1.00e+00f  1
  38r 9.4135905e-01 4.75e-03 3.81e-05  -4.0 1.81e-03    -  1.00e+00 1.00e+00h  1

Number of Iterations....: 38

                                   (scaled)                 (unscaled)
Objective...............:   9.4136115577734664e-09    9.4136115577734658e-01
Dual infeasibility......:   3.8194983858375053e-05    3.8194983858375053e+03
Constraint violation....:   4.7481906442041885e-03    4.7481906442041885e-03
Variable bound violation:   0.0000000000000000e+00    0.0000000000000000e+00
Complementarity.........:   1.0000000077516868e-04    1.0000000077516868e+04
Overall NLP error.......:   4.7481906442041885e-03    3.8194983858375053e+03


Number of objective function evaluations             = 171
Number of objective gradient evaluations             = 33
Number of equality constraint evaluations            = 171
Number of inequality constraint evaluations          = 0
Number of equality constraint Jacobian evaluations   = 42
Number of inequality constraint Jacobian evaluations = 0
Number of Lagrangian Hessian evaluations             = 39
Total seconds in IPOPT                               = 7.181

EXIT: Converged to a point of local infeasibility. Problem may be infeasible.

Step 5: Access the Solution

Let's look at the results.

plot(prob.trajectory)
Example block output

The optimized trajectory is stored in prob.trajectory:

println("Final state: ", prob.trajectory.x[:, end])
println("Control norm: ", norm(prob.trajectory.u))
Final state: [1.0, 0.0]
Control norm: 6.862105471786601

What You Can Do

  • Multiple objectives: Combine regularization, minimum time, terminal costs
  • Flexible dynamics: Linear, bilinear, time-dependent systems
  • Add constraints: Bounds, path constraints, custom nonlinear constraints
  • Smooth controls: Penalize derivatives for smooth, implementable controls
  • Free time: Optimize trajectory duration

This page was generated using Literate.jl.