Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion docs/Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ OptimalControl = "5f98b655-cc9a-415a-b60e-744165666948"
OrdinaryDiffEq = "1dea7af3-3e70-54e6-95c3-0bf5283fa5ed"
Plots = "91a5bcdd-55d7-5caf-9e0b-520d859cae80"
Suppressor = "fd094767-a336-5f1f-9728-57cf17d0bbfb"
Tutorials = "cb10daa6-a5e5-4c25-a171-ae181b8ea3c9"

[compat]
DifferentiationInterface = "0.6"
Expand Down
2 changes: 1 addition & 1 deletion docs/make.jl
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ makedocs(;
sitename="Tutorials",
format=Documenter.HTML(;
repolink="https://" * repo_url,
prettyurls=true,
prettyurls=false,
size_threshold_ignore=[
""
],
Expand Down
4 changes: 2 additions & 2 deletions docs/src/tutorial-continuation.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ This usually gives better and faster convergence than solving each problem with

The most compact syntax to perform a discrete continuation is to use a function that returns the OCP for a given value of the continuation parameter, and solve a sequence of these problems. We illustrate this on a very basic double integrator with increasing fixed final time.

First we load the required packages
First we load the required packages:

```@example main
using OptimalControl
Expand All @@ -21,7 +21,7 @@ using Printf
using Plots
```

and write a function that returns the OCP for a given final time
and write a function that returns the OCP for a given final time:

```@example main
function ocp_T(T)
Expand Down
20 changes: 13 additions & 7 deletions docs/src/tutorial-discretisation.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ When calling `solve`, the option `disc_method=...` can be used to set the discre
In addition to the default implicit `:trapeze` method (aka Crank-Nicolson), other choices are available, namely implicit `:midpoint` and the Gauss-Legendre collocations with 2 and stages, `:gauss_legendre_2` and `:gauss_legendre_3`, of order 4 and 6 respectively.
Note that higher order methods will typically lead to larger NLP problems for the same number of time steps, and that accuracy will also depend on the smoothness of the problem.

As an example we will use the [Goddard problem](@ref tutorial-goddard)
As an example we will use the [Goddard problem](@ref tutorial-goddard).

```@example main
using OptimalControl # to define the optimal control problem and more
using NLPModelsIpopt # to solve the problem via a direct method
Expand Down Expand Up @@ -57,23 +58,28 @@ nothing # hide
```
Now let us compare different discretisations
```@example main
x_style = (legend=:none,)
p_style = (legend=:none,)

sol_trapeze = solve(ocp; tol=1e-8)
plot(sol_trapeze)
plt = plot(sol_trapeze; solution_label="trapeze", state_style=x_style, costate_style=p_style)

sol_midpoint = solve(ocp, disc_method=:midpoint; tol=1e-8)
plot!(sol_midpoint)
plot!(plt, sol_midpoint; solution_label="midpoint", state_style=x_style, costate_style=p_style);

sol_euler = solve(ocp, disc_method=:euler; tol=1e-8)
plot!(sol_euler)
plot!(plt, sol_euler; solution_label="euler", state_style=x_style, costate_style=p_style);

sol_euler_imp = solve(ocp, disc_method=:euler_implicit; tol=1e-8)
plot!(sol_euler_imp)
plot!(plt, sol_euler_imp; solution_label="euler implicit", state_style=x_style, costate_style=p_style);

sol_gl2 = solve(ocp, disc_method=:gauss_legendre_2; tol=1e-8)
plot!(sol_gl2)
plot!(plt, sol_gl2; solution_label="gauss legendre 2", state_style=x_style, costate_style=p_style);

sol_gl3 = solve(ocp, disc_method=:gauss_legendre_3; tol=1e-8)
plot!(sol_gl3)
plot!(plt, sol_gl3; solution_label="gauss legendre 3", state_style=x_style, costate_style=p_style);

plot(plt, size=(800, 800))
```

## Large problems and AD backend
Expand Down
28 changes: 11 additions & 17 deletions docs/src/tutorial-goddard.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,9 @@ $v(t) \leq v_{\max}$. The initial state is fixed while only the final mass is pr
as well as constrained arcs due to the path constraint on the velocity (see below).

We import the [OptimalControl.jl](https://control-toolbox.org/OptimalControl.jl) package to define the optimal control problem and
[NLPModelsIpopt.jl](https://github.com/JuliaSmoothOptimizers/NLPModelsIpopt.jl) to solve it.
We import the [Plots.jl](https://github.com/JuliaPlots/Plots.jl) package to plot the solution.
The [OrdinaryDiffEq.jl](https://github.com/SciML/OrdinaryDiffEq.jl) package is used to
[NLPModelsIpopt.jl](https://jso.dev/NLPModelsIpopt.jl) to solve it.
We import the [Plots.jl](https://docs.juliaplots.org) package to plot the solution.
The [OrdinaryDiffEq.jl](https://docs.sciml.ai/OrdinaryDiffEq) package is used to
define the shooting function for the indirect method and the [MINPACK.jl](https://github.com/sglyon/MINPACK.jl) package permits to solve the shooting equation.

```@example main
Expand Down Expand Up @@ -119,15 +119,11 @@ bang arc with maximal control, followed by a singular arc, then by a boundary ar
arc is with zero control. Note that the switching function vanishes along the singular and
boundary arcs.

!!! tip "Interactions with an optimal control solution"

Please check [`state`](@ref), [`costate`](@ref), [`control`](@ref) and [`variable`](@ref) to get data from the solution. The functions `state`, `costate` and `control` return functions of time and `variable` returns a vector. The function [`time_grid`](@ref) returns the discretized time grid returned by the solver.

```@example main
t = time_grid(direct_sol)
x = state(direct_sol)
u = control(direct_sol)
p = costate(direct_sol)
t = time_grid(direct_sol) # the time grid as a vector
x = state(direct_sol) # the state as a function of time
u = control(direct_sol) # the control as a function of time
p = costate(direct_sol) # the costate as a function of time

H1 = Lift(F1) # H1(x, p) = p' * F1(x)
φ(t) = H1(x(t), p(t)) # switching function
Expand Down Expand Up @@ -193,9 +189,7 @@ as well as the associated multiplier for the *order one* state constraint on the

which is the reason why we use the `@Lie` macro to compute Poisson brackets below.

With the help of the [differential geometry primitives](https://control-toolbox.org/CTBase.jl/stable/api-diffgeom.html)
from [CTBase.jl](https://control-toolbox.org/OptimalControl.jl/stable/api-ctbase.html),
these expressions are straightforwardly translated into Julia code:
With the help of differential geometry primitives, these expressions are straightforwardly translated into Julia code:

```@example main
# Controls
Expand Down Expand Up @@ -284,11 +278,11 @@ We aggregate the data to define the initial guess vector.

### MINPACK.jl

We can use [NonlinearSolve.jl](https://github.com/SciML/NonlinearSolve.jl) package or, instead, the
We can use [NonlinearSolve.jl](https://docs.sciml.ai/NonlinearSolve) package or, instead, the
[MINPACK.jl](https://github.com/sglyon/MINPACK.jl) package to solve
the shooting equation. To compute the Jacobian of the shooting function we use the
[DifferentiationInterface.jl](https://gdalle.github.io/DifferentiationInterface.jl/DifferentiationInterface) package with
[ForwardDiff.jl](https://github.com/JuliaDiff/ForwardDiff.jl) backend.
[DifferentiationInterface.jl](https://juliadiff.org/DifferentiationInterface.jl/DifferentiationInterface) package with
[ForwardDiff.jl](https://juliadiff.org/ForwardDiff.jl) backend.

```@setup main
using NonlinearSolve # interface to NLE solvers
Expand Down
7 changes: 5 additions & 2 deletions docs/src/tutorial-iss.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,14 @@
In this tutorial we present the indirect simple shooting method on a simple example.

Let us start by importing the necessary packages.
We import the [OptimalControl.jl](https://control-toolbox.org/OptimalControl.jl) package to define the optimal control problem.
We import the [Plots.jl](https://docs.juliaplots.org) package to plot the solution.
The [OrdinaryDiffEq.jl](https://docs.sciml.ai/OrdinaryDiffEq) package is used to define the shooting function for the indirect method and the [MINPACK.jl](https://github.com/sglyon/MINPACK.jl) package permits to solve the shooting equation.


```@example main
using OptimalControl # to define the optimal control problem and its flow
using OrdinaryDiffEq # to get the Flow function from OptimalControl
using NonlinearSolve # interface to NLE solvers
using MINPACK # NLE solver: use to solve the shooting equation
using Plots # to plot the solution
```
Expand Down Expand Up @@ -154,7 +157,7 @@ nothing # hide

### MINPACK.jl

We can use [NonlinearSolve.jl](https://github.com/SciML/NonlinearSolve.jl) package or, instead, [MINPACK.jl](https://github.com/sglyon/MINPACK.jl) to solve the shooting equation. To compute the Jacobian of the shooting function we use [DifferentiationInterface.jl](https://gdalle.github.io/DifferentiationInterface.jl/DifferentiationInterface) with [ForwardDiff.jl](https://github.com/JuliaDiff/ForwardDiff.jl) backend.
We can use [NonlinearSolve.jl](https://docs.sciml.ai/NonlinearSolve) package or, instead, [MINPACK.jl](https://github.com/sglyon/MINPACK.jl) to solve the shooting equation. To compute the Jacobian of the shooting function we use [DifferentiationInterface.jl](https://juliadiff.org/DifferentiationInterface.jl/DifferentiationInterface) with [ForwardDiff.jl](https://juliadiff.org/ForwardDiff.jl) backend.

```@setup main
using MINPACK
Expand Down
2 changes: 1 addition & 1 deletion docs/src/tutorial-lqr-basic.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ and the initial condition

We aim to solve this optimal control problem for different values of $t_f$.
First, we need to import the [OptimalControl.jl](https://control-toolbox.org/OptimalControl.jl) package to define the
optimal control problem and [NLPModelsIpopt.jl](jso.dev/NLPModelsIpopt.jl) to solve it.
optimal control problem and [NLPModelsIpopt.jl](https://jso.dev/NLPModelsIpopt.jl) to solve it.
We also need to import the [Plots.jl](https://docs.juliaplots.org) package to plot the solution.

```@example main
Expand Down
12 changes: 6 additions & 6 deletions docs/src/tutorial-nlp.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ CurrentModule = OptimalControl
We describe here some more advanced operations related to the discretized optimal control problem.
When calling `solve(ocp)` three steps are performed internally:

- first, the OCP is discretized into a DOCP (a nonlinear optimization problem) with [`direct_transcription`](@ref),
- then, this DOCP is solved (with the internal function [`solve_docp`](@ref)),
- finally, a functional solution of the OCP is rebuilt from the solution of the discretized problem, with [`OptimalControlSolution`](@ref).
- first, the OCP is discretized into a DOCP (a nonlinear optimization problem),
- then, this DOCP is solved with a nonlinear programming (NLP) solver, which returns a solution of the discretized problem,
- finally, a functional solution of the OCP is rebuilt from the solution of the discretized problem.

These steps can also be done separately, for instance if you want to use your own NLP solver.

Expand Down Expand Up @@ -55,7 +55,7 @@ We can now use the solver of our choice to solve it.

## Resolution of the NLP problem

For a first example we use the `ipopt` solver from [NLPModelsIpopt.jl](https://github.com/JuliaSmoothOptimizers/NLPModelsIpopt.jl) package to solve the NLP problem.
For a first example we use the `ipopt` solver from [NLPModelsIpopt.jl](https://jso.dev/NLPModelsIpopt.jl) package to solve the NLP problem.

```@example main
using NLPModelsIpopt
Expand All @@ -82,14 +82,14 @@ nlp_sol = madnlp(nlp)

## Initial guess

An initial guess, including warm start, can be passed to [`direct_transcription`](@ref) the same way as for `solve`.
An initial guess, including warm start, can be passed to [`direct_transcription`](https://control-toolbox.org/OptimalControl.jl/stable/dev-ctdirect.html#CTDirect.direct_transcription-Tuple{Model,%20Vararg{Any}}) the same way as for `solve`.

```@example main
docp, nlp = direct_transcription(ocp; init=sol)
nothing # hide
```

It can also be changed after the transcription is done, with [`set_initial_guess`](@ref).
It can also be changed after the transcription is done, with [`set_initial_guess`](https://control-toolbox.org/OptimalControl.jl/stable/dev-ctdirect.html#CTDirect.set_initial_guess-Tuple{CTDirect.DOCP,%20Any,%20Any}).

```@example main
set_initial_guess(docp, nlp, sol)
Expand Down
Loading