It is a pleasure to announce the new major release of OptimalControl.jl (v2.0.0). Designed to solve optimal control problems on ODEs, the package features:
- a friendly DSL
- both direct (optimisation) and indirect (aka. shooting) methods
- solving on GPU — now as simple as
solve(ocp, :gpu) - a bunch of examples: tutorials, applications and collection of problems
What’s new in v2.0
More solvers, more flexibility
OptimalControl.jl now supports 5 nonlinear optimization solvers (Ipopt, MadNLP, Uno, MadNCL, Knitro) with 12 total solving methods combining different discretization schemes, modelers, and execution backends (CPU/GPU). See the solve manual for the complete list.
GPU solving is now streamlined — just specify :gpu:
sol = solve(ocp, :gpu) # Automatically uses ExaModels + MadNLP on GPU (with cuDSS)
Learn more in the GPU solving guide.
Control-free problems
A new feature allows solving optimal control problems without control variables — useful for parameter estimation and optimization of constant parameters in dynamical systems. For instance, finding the minimal pulsation \omega for a harmonic oscillator:
ocp = @def begin
ω ∈ R, variable # pulsation to optimize
t ∈ [0, 1], time
x = (q, v) ∈ R², state
q(0) == 1.0
v(0) == 0.0
q(1) == 0.0 # final condition
ẋ(t) == [v(t), -ω^2 * q(t)]
ω^2 → min # minimize pulsation
end
sol = solve(ocp)
See the control-free problems example for parameter estimation and optimization applications.
Initial guess with @init macro
Initial guesses can now be constructed with the new @init macro, providing a cleaner and more intuitive syntax:
init = @init ocp begin
x(t) := [1-t, 0]
u(t) := 0
end
sol = solve(ocp; init=init)
Check out the initial guess manual for details.
Differential geometry tools documentation
OptimalControl.jl includes differential geometry operators for analyzing Hamiltonian systems and computing singular controls. These tools are now fully documented in v2.0. The @Lie macro provides convenient syntax for Poisson and Lie brackets:
# Define Hamiltonian functions directly
H0(x, p) = p[1] * x[2] + p[2] * x[1]
H1(x, p) = x[1]^2 + p[2]^2
# Compute Poisson brackets with @Lie macro
H01 = @Lie {H0, H1}
# Evaluate at a point
H01([1, 2], [3, 4])
See the differential geometry tools manual and the singular control example.
Direct and indirect methods throughout
All examples in the documentation now systematically feature both direct and indirect approaches, demonstrating the versatility of the package. See for instance the double integrator energy and time minimisation examples.
Comprehensive documentation rewrite
The documentation has been completely rewritten with new manuals covering:
- Solve options and advanced routing
- GPU solving
- Initial guess construction
- Differential geometry tools
- Control-free problems
The friendly DSL you know
Give it a try, and if ever the syntax below does not look familiar enough
…
ocp = @def begin
t ∈ [0, 1], time
x ∈ R², state
u ∈ R, control
x(0) == [-1, 0]
x(1) == [0, 0]
x₂(t) ≤ 1.2
ẋ(t) == [x₂(t), u(t)]
0.5∫(u(t)^2) → min
end
… ask your favorite AI to translate the math for you!
About control-toolbox
OptimalControl.jl is part of the control-toolbox ecosystem, which brings together Julia packages for mathematical control and its applications:
- OptimalControl.jl - Tools to model and solve optimal control problems with a friendly DSL
- OptimalControlProblems.jl - Curated collection of benchmark problems
- CTBenchmarks.jl - Benchmarking suite (under construction)
Acknowledgments
We would like to thank all contributors for their work on this package!
Contributing
Contributions are welcome! Whether you want to report bugs, suggest features, or contribute code, feel free to open an issue or start a discussion on GitHub.
Tags: optimization control #optimalcontrol nlp gpu julia