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, traj, :x, :u)
BilinearIntegrator{Main.var"#2#3"}(Main.var"#2#3"(), [1, 2], [3], 4, 4, 2, 1)

Step 3: Define the Objective

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

obj = QuadraticRegularizer(:u, traj, 1.0)
Objective(L, ∇L, ∂²L, ∂²L_structure)

Step 4: Create and Solve

Combine everything into a problem and solve:

prob = DirectTrajOptProblem(traj, obj, integrator)
solve!(prob; max_iter=100, verbose=false)
This is Ipopt version 3.14.19, running with linear solver MUMPS 5.8.1.

Number of nonzeros in equality constraint Jacobian...:      484
Number of nonzeros in inequality constraint Jacobian.:        0
Number of nonzeros in Lagrangian Hessian.............:      539

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.3671066e-01 5.05e+00 8.23e-02   0.0 0.00e+00    -  0.00e+00 0.00e+00   0
   1  1.6665787e-01 1.33e-01 8.98e-01  -1.4 3.61e+00    -  9.80e-01 1.00e+00h  1
   2  9.5249007e-02 7.48e-02 1.12e+00  -1.4 3.06e+00    -  3.75e-01 6.30e-01f  1
   3  1.1831689e-01 4.50e-02 7.61e-01  -1.8 3.30e+00    -  3.45e-01 3.99e-01h  1
   4  1.4049129e-01 3.84e-02 1.04e+00  -1.2 9.04e-01   0.0 6.47e-01 1.49e-01h  1
   5  2.1864453e-01 1.98e-02 7.43e-01  -2.2 1.57e+00    -  4.59e-01 4.82e-01h  1
   6  2.5959686e-01 1.52e-02 6.30e-01  -2.9 4.83e+00    -  1.93e-01 2.35e-01h  1
   7  3.1610254e-01 1.19e-02 4.85e-01  -2.2 1.64e+00    -  2.73e-01 2.22e-01h  1
   8  3.7276026e-01 1.00e-02 8.04e-01  -1.4 6.37e-01  -0.5 6.14e-01 1.62e-01h  1
   9  4.5609188e-01 8.16e-03 3.24e+00  -1.0 4.12e+00  -1.0 6.88e-01 1.96e-01h  1
iter    objective    inf_pr   inf_du lg(mu)  ||d||  lg(rg) alpha_du alpha_pr  ls
  10  4.8587229e-01 8.07e-03 8.59e+00  -0.8 3.72e+00    -  8.66e-01 7.15e-02h  1
  11  6.6762544e-01 5.10e-03 4.95e+01  -0.9 1.75e+00    -  1.00e+00 3.74e-01h  1
  12  7.2831317e-01 4.69e-03 1.29e+02  -0.4 6.09e+00    -  2.56e-01 8.07e-02h  1
  13  7.5251482e-01 4.65e-03 1.06e+03   0.6 1.42e+01    -  9.75e-01 7.90e-03h  1
  14  7.9202003e-01 4.45e-03 1.53e+04   1.4 3.80e+00    -  1.00e+00 4.18e-02h  1
  15  8.1772964e-01 4.32e-03 2.49e+05   2.1 7.75e+00    -  1.00e+00 2.91e-02h  1
  16  8.3737418e-01 4.28e-03 5.41e+06   2.7 9.56e+00    -  1.00e+00 1.11e-02h  1
  17  8.5432766e-01 4.20e-03 3.44e+07   2.7 9.70e+00    -  2.17e-01 1.82e-02h  1
  18  8.6557694e-01 4.16e-03 3.96e+07  -2.0 1.04e+01    -  1.03e-02 9.99e-03h  1
  19  8.7794597e-01 4.15e-03 5.48e+07   2.7 4.20e+02    -  1.56e-04 1.98e-04h  1
iter    objective    inf_pr   inf_du lg(mu)  ||d||  lg(rg) alpha_du alpha_pr  ls
  20r 8.7794597e-01 4.15e-03 9.62e+02   2.7 0.00e+00    -  0.00e+00 4.29e-07R  4
  21r 8.7793918e-01 3.09e-03 1.02e+01  -3.5 5.41e-01    -  9.89e-01 9.87e-01f  1
  22  8.8103032e-01 3.07e-03 1.02e+01  -4.0 4.26e-01    -  5.94e-02 5.37e-03h  1
  23  8.9996319e-01 3.05e-03 5.31e+01  -0.9 1.83e+01    -  4.19e-03 6.85e-03f  1
  24  9.1523305e-01 3.04e-03 1.73e+02  -1.3 1.60e+01    -  2.70e-02 5.44e-03h  1
  25  9.2396982e-01 3.03e-03 2.48e+03  -2.0 1.53e+02    -  7.28e-03 2.16e-03h  1
  26  9.3949895e-01 3.03e-03 1.37e+05   0.4 3.18e+02    -  1.00e+00 1.66e-03f  1
  27  9.4007252e-01 3.02e-03 3.34e+08   1.1 1.54e+01    -  1.00e+00 2.79e-04h  1
  28  9.4722088e-01 1.40e-03 3.26e+06   2.7 1.83e+00    -  9.90e-01 5.66e-01f  1
  29  9.4743226e-01 1.40e-03 6.99e+08   2.7 3.77e+01    -  5.25e-02 9.15e-05h  1
iter    objective    inf_pr   inf_du lg(mu)  ||d||  lg(rg) alpha_du alpha_pr  ls
  30r 9.4743226e-01 1.40e-03 9.97e+02   2.7 0.00e+00    -  0.00e+00 4.66e-07R  9
  31r 9.4742734e-01 1.70e-03 1.02e+01  -3.5 5.39e-01    -  9.90e-01 9.88e-01f  1
  32r 9.4726387e-01 1.20e-03 6.61e+00  -4.0 1.95e-02    -  9.69e-01 9.02e-01f  1
  33  9.4732486e-01 1.20e-03 1.48e+04  -1.1 8.83e-02    -  9.99e-01 1.36e-04h  1
  34  9.4097932e-01 1.22e-03 2.18e+01  -1.3 6.36e-01    -  1.00e+00 1.00e+00f  1
  35  9.4118311e-01 1.22e-03 4.73e+06  -0.5 2.49e+00    -  1.00e+00 2.31e-04h  1
  36  9.4119085e-01 1.22e-03 7.46e+10  -0.1 6.86e-01    -  1.00e+00 6.28e-05h  1
  37  9.4085399e-01 3.71e-01 7.65e+10  -0.1 2.27e+00    -  1.78e-01 1.78e-01s 20
  38  9.4086223e-01 3.71e-01 2.59e+08  -0.8 3.33e-03  10.9 1.00e+00 1.00e+00s 22
  39r 9.4086223e-01 3.71e-01 1.00e+03  -0.4 0.00e+00  11.3 0.00e+00 4.77e-07R 22
iter    objective    inf_pr   inf_du lg(mu)  ||d||  lg(rg) alpha_du alpha_pr  ls
  40r 9.4046082e-01 9.95e-02 9.67e+02   1.1 1.80e+02    -  1.47e-01 1.52e-03f  1
  41  9.4054066e-01 9.94e-02 5.20e+03  -1.5 3.85e-01    -  6.50e-01 1.58e-04h  1
  42  9.4065351e-01 9.94e-02 1.99e+07  -1.5 4.07e-01    -  7.21e-01 1.87e-04h  1
  43r 9.4065351e-01 9.94e-02 1.00e+03  -1.0 0.00e+00    -  0.00e+00 4.55e-07R  3
  44r 9.4063390e-01 2.41e-02 9.43e+02  -0.2 9.06e+01    -  9.39e-01 1.21e-03f  1
  45r 9.4063390e-01 2.41e-02 9.99e+02  -1.5 0.00e+00    -  0.00e+00 2.70e-07R  6
  46r 8.4489168e-01 8.49e-03 9.42e+02   0.8 2.02e+01    -  1.00e+00 1.56e-03f  1
  47  8.9770884e-01 7.68e-03 8.45e+00  -1.5 2.38e-01    -  7.12e-01 1.02e-01h  1
  48  9.2272857e-01 7.39e-03 7.30e+01  -1.5 1.23e+00    -  4.13e-01 3.70e-02h  1
  49  9.3993317e-01 7.25e-03 1.56e+03  -1.5 5.02e-01    -  3.95e-01 1.93e-02h  1
iter    objective    inf_pr   inf_du lg(mu)  ||d||  lg(rg) alpha_du alpha_pr  ls
  50  9.4063084e-01 7.25e-03 1.15e+06  -1.5 1.68e+00    -  5.84e-01 7.73e-04h  1
  51  9.4067767e-01 7.25e-03 1.90e+10  -1.5 8.58e-01    -  1.00e+00 6.00e-05h  1
  52r 9.4067767e-01 7.25e-03 1.00e+03  -1.5 0.00e+00    -  0.00e+00 4.96e-07R 20
  53r 9.4058920e-01 2.11e-03 3.06e+02   0.1 4.46e+00    -  9.91e-01 5.02e-03f  1
  54  9.4061227e-01 2.11e-03 3.42e+04  -1.0 1.08e-01    -  1.00e+00 5.84e-05h  1
  55  9.4066115e-01 2.11e-03 2.72e+08  -1.2 5.35e-01    -  5.46e-01 6.81e-05h  1
  56r 9.4066115e-01 2.11e-03 1.00e+03  -1.2 0.00e+00    -  0.00e+00 3.01e-07R 16
  57r 9.3989382e-01 9.12e-04 4.03e+01  -0.0 1.15e+00    -  9.90e-01 5.26e-02f  1
  58  9.4005877e-01 9.12e-04 4.70e+03  -0.9 1.13e-01    -  9.98e-01 4.22e-04h  1
  59  9.4043430e-01 9.11e-04 9.06e+06  -0.6 5.32e-01    -  1.00e+00 5.14e-04h  1
iter    objective    inf_pr   inf_du lg(mu)  ||d||  lg(rg) alpha_du alpha_pr  ls
  60r 9.4043430e-01 9.11e-04 1.00e+03   1.8 0.00e+00    -  0.00e+00 3.58e-07R  5
  61r 9.2429815e-01 1.49e-03 9.30e+00   0.2 6.90e-02    -  9.91e-01 1.00e+00f  1
  62r 9.1035966e-01 1.36e-03 1.31e+02  -1.5 1.75e-02    -  9.95e-01 7.07e-01f  1
  63r 9.3373456e-01 1.46e-03 3.18e+02  -4.0 3.53e-02    -  8.71e-01 4.60e-01f  1
  64r 7.7173779e-01 7.79e-03 4.08e+01  -1.4 4.82e-01    -  9.02e-01 9.24e-01f  1
  65r 8.0923154e-01 1.13e-02 4.90e+01  -1.6 3.82e-01    -  1.00e+00 5.04e-01f  1
  66r 8.9132251e-01 1.19e-02 1.58e-01  -2.3 1.81e-01    -  1.00e+00 9.90e-01f  1
  67r 9.2094218e-01 1.25e-02 2.75e-01  -3.3 6.65e-02    -  9.99e-01 1.00e+00f  1
  68r 9.2570027e-01 1.25e-02 5.10e-01  -4.0 3.21e-02    -  1.00e+00 1.00e+00f  1
  69r 9.2585720e-01 1.25e-02 2.51e-02  -4.0 2.15e-02    -  1.00e+00 1.00e+00h  1
iter    objective    inf_pr   inf_du lg(mu)  ||d||  lg(rg) alpha_du alpha_pr  ls
  70r 9.2607961e-01 1.25e-02 2.02e-03  -4.0 1.65e-02    -  1.00e+00 1.00e+00h  1
  71r 9.2609906e-01 1.25e-02 2.55e-05  -4.0 1.29e-03    -  1.00e+00 1.00e+00h  1

Number of Iterations....: 71

                                   (scaled)                 (unscaled)
Objective...............:   9.2609920239966959e-01    9.2609920239966959e-01
Dual infeasibility......:   1.9996498124209516e-01    1.9996498124209516e-01
Constraint violation....:   1.2450478196233175e-02    1.2450478196233175e-02
Variable bound violation:   0.0000000000000000e+00    0.0000000000000000e+00
Complementarity.........:   1.0000000075047487e-04    1.0000000075047487e-04
Overall NLP error.......:   1.9996498124209516e-01    1.9996498124209516e-01


Number of objective function evaluations             = 203
Number of objective gradient evaluations             = 61
Number of equality constraint evaluations            = 203
Number of inequality constraint evaluations          = 0
Number of equality constraint Jacobian evaluations   = 81
Number of inequality constraint Jacobian evaluations = 0
Number of Lagrangian Hessian evaluations             = 72
Total seconds in IPOPT                               = 7.644

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.844892533463705

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.