Skip to content

Commit 96a080d

Browse files
committed
Standardize free times tutorials: rename examples, add context, comment imports
1 parent ffb4509 commit 96a080d

3 files changed

Lines changed: 69 additions & 48 deletions

File tree

docs/src/tutorial-free-times-final-initial.md

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,23 @@
11
# [Free initial and final times](@id tutorial-free-times-final-initial)
22

3+
```@meta
4+
Draft = false
5+
```
6+
7+
This tutorial is part of a series on optimal control problems with free time variables.
8+
See also: [Free final time](@ref tutorial-free-times-final) and [Free initial time](@ref tutorial-free-times-initial).
9+
310
In this tutorial, we consider an optimal control problem with the initial and final times as free variables, that is there are parts of the variable to be optimized. The required packages for the tutorial are:
411

5-
```@example both_time
6-
using OptimalControl
7-
using NLPModelsIpopt
8-
using Plots
12+
```@example free-both-times
13+
using OptimalControl # Main package
14+
using NLPModelsIpopt # Direct solver
15+
using Plots # Visualization
916
```
1017

1118
The problem we consider is the following:
1219

13-
```@example both_time
20+
```@example free-both-times
1421
1522
@def ocp begin
1623
@@ -40,17 +47,17 @@ nothing # hide
4047

4148
We now solve the problem using a direct method.
4249

43-
```@example both_time
50+
```@example free-both-times
4451
sol = solve(ocp; grid_size=100)
4552
nothing # hide
4653
```
4754

48-
```@example both_time
55+
```@example free-both-times
4956
sol # hide
5057
```
5158

5259
And plot the solution.
5360

54-
```@example both_time
61+
```@example free-both-times
5562
plot(sol)
5663
```

docs/src/tutorial-free-times-final.md

Lines changed: 27 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,29 @@
11
# [Optimal control problem with free final time](@id tutorial-free-times-final)
22

3+
```@meta
4+
Draft = false
5+
```
6+
7+
This tutorial is part of a series on optimal control problems with free time variables.
8+
See also: [Free initial time](@ref tutorial-free-times-initial) and [Free initial and final times](@ref tutorial-free-times-final-initial).
9+
310
In this tutorial, we study an **optimal control problem with a free final time** `tf`. The following packages are required:
411

5-
```@example main-free-final
6-
using LinearAlgebra: norm
7-
using NLPModelsIpopt
8-
using NonlinearSolve
9-
using OptimalControl
10-
using OrdinaryDiffEq
11-
using Plots
12-
using Printf
12+
```@example free-final-time
13+
using LinearAlgebra: norm # For vector norm
14+
using NLPModelsIpopt # Direct solver
15+
using NonlinearSolve # Indirect solver
16+
using OptimalControl # Main package
17+
using OrdinaryDiffEq # ODE integration
18+
using Plots # Visualization
19+
using Printf # Formatted output
1320
```
1421

1522
## Definition of the problem
1623

1724
We consider the following setup:
1825

19-
```@example main-free-final
26+
```@example free-final-time
2027
t0 = 0 # Initial time
2128
x0 = [0, 0] # Initial state
2229
xf = [1, 0] # Desired final state
@@ -69,14 +76,14 @@ To improve convergence of the direct solver, we constrain `tf` as follows:
6976

7077
We then solve the optimal control problem with a direct method, using an automatic handling of the free final time:
7178

72-
```@example main-free-final
79+
```@example free-final-time
7380
sol = solve(ocp; grid_size=100)
7481
nothing # hide
7582
```
7683

7784
The solution can be visualized as:
7885

79-
```@example main-free-final
86+
```@example free-final-time
8087
plt = plot(sol; label="direct", size=(800, 600))
8188
```
8289

@@ -116,7 +123,7 @@ p_1(t)=1, \quad p_2(t)=1-t, \quad p^0=-1, \quad t_1 = 1, \quad t_f = 2.
116123

117124
We can now compare the direct numerical solution with this theoretical result:
118125

119-
```@example main-free-final
126+
```@example free-final-time
120127
tf = variable(sol)
121128
u = control(sol)
122129
p = costate(sol)
@@ -138,7 +145,7 @@ The numerical results match the theoretical solution almost exactly.
138145

139146
We now solve the same problem using an **indirect method** (shooting approach). We begin by defining the pseudo-Hamiltonian and the switching function.
140147

141-
```@example main-free-final
148+
```@example free-final-time
142149
# Pseudo-Hamiltonian
143150
H(x, p, u) = p[1]*x[2] + p[2]*u
144151
@@ -150,7 +157,7 @@ nothing # hide
150157

151158
Define the flows corresponding to the two control laws $u=+1$ and $u=-1$:
152159

153-
```@example main-free-final
160+
```@example free-final-time
154161
const u_pos = 1
155162
const u_neg = -1
156163
@@ -162,7 +169,7 @@ nothing # hide
162169

163170
The **shooting function** enforces the final and switching conditions:
164171

165-
```@example main-free-final
172+
```@example free-final-time
166173
function shoot!(s, p0, t1, tf)
167174
x_t0 = x0
168175
p_t0 = p0
@@ -183,7 +190,7 @@ nothing # hide
183190

184191
To help the nonlinear solver converge, we build a good initial guess from the direct solution:
185192

186-
```@example main-free-final
193+
```@example free-final-time
187194
t = time_grid(sol)
188195
x = state(sol)
189196
p = costate(sol)
@@ -205,9 +212,9 @@ println("\n‖s‖ (initial guess) = ", norm(s), "\n")
205212

206213
We can now solve the system using an **indirect shooting method**:
207214

208-
```@example main-free-final
215+
```@example free-final-time
209216
# Aggregated nonlinear system
210-
shoot!(s, ξ, λ) = shoot!(s, ξ[1:2], ξ[3], ξ[4])
217+
shoot!(s, ξ, _) = shoot!(s, ξ[1:2], ξ[3], ξ[4])
211218
212219
# Define the problem and initial guess
213220
ξ_guess = [p0..., t1, tf]
@@ -218,13 +225,13 @@ indirect_sol = solve(prob; show_trace=Val(true), abstol=1e-8, reltol=1e-8)
218225
nothing # hide
219226
```
220227

221-
```@example main-free-final
228+
```@example free-final-time
222229
indirect_sol # hide
223230
```
224231

225232
Finally, we compare the indirect solution to the direct one:
226233

227-
```@example main-free-final
234+
```@example free-final-time
228235
p0 = indirect_sol.u[1:2]
229236
t1 = indirect_sol.u[3]
230237
tf = indirect_sol.u[4]

docs/src/tutorial-free-times-initial.md

Lines changed: 27 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
11
# [Optimal control problem with free initial time](@id tutorial-free-times-initial)
22

3+
```@meta
4+
Draft = false
5+
```
6+
7+
This tutorial is part of a series on optimal control problems with free time variables.
8+
See also: [Free final time](@ref tutorial-free-times-final) and [Free initial and final times](@ref tutorial-free-times-final-initial).
9+
310
In this tutorial, we study a **minimum-time optimal control problem with free initial time** $t_0$ (negative). The goal is to determine the latest possible starting time so that the system reaches a fixed final state at $t_f = 0$.
411

512
The system is the classic **double integrator**:
@@ -9,21 +16,21 @@ The system is the classic **double integrator**:
916
- Objective: maximize $t_0$ (equivalently minimize $-t_0$)
1017
- Dynamics: $\dot{x}_1 = x_2, \ \dot{x}_2 = u$
1118

12-
```@example initial_time
13-
using LinearAlgebra: norm
14-
using OptimalControl
15-
using NLPModelsIpopt
16-
using NonlinearSolve
17-
using OrdinaryDiffEq
18-
using Plots
19-
using Printf
19+
```@example free-initial-time
20+
using LinearAlgebra: norm # For vector norm
21+
using OptimalControl # Main package
22+
using NLPModelsIpopt # Direct solver
23+
using NonlinearSolve # Indirect solver
24+
using OrdinaryDiffEq # ODE integration
25+
using Plots # Visualization
26+
using Printf # Formatted output
2027
```
2128

2229
## Problem definition
2330

2431
We consider the following setup:
2532

26-
```@example initial_time
33+
```@example free-initial-time
2734
tf = 0 # Fixed final time
2835
x0 = [0, 0] # Initial state
2936
xf = [1, 0] # Final state
@@ -67,14 +74,14 @@ To improve convergence of the direct solver, we constrain `t0` as follows:
6774

6875
We solve the problem using a **direct transcription method**:
6976

70-
```@example initial_time
77+
```@example free-initial-time
7178
sol = solve(ocp; grid_size=100)
7279
nothing # hide
7380
```
7481

7582
The solution can be visualized:
7683

77-
```@example initial_time
84+
```@example free-initial-time
7885
plt = plot(sol; label="direct", size=(800, 600))
7986
```
8087

@@ -112,7 +119,7 @@ p(t_0) = (1,1), \quad p(t_f) = (1,-1), \quad t_1=-1, \quad t_0=-2, \quad p^0=-1.
112119

113120
We can now compare the direct numerical solution with this theoretical result:
114121

115-
```@example initial_time
122+
```@example free-initial-time
116123
t0 = variable(sol)
117124
u = control(sol)
118125
p = costate(sol)
@@ -134,7 +141,7 @@ The numerical results match the theoretical solution almost exactly.
134141

135142
We now solve the PMP system numerically using an **indirect method** (shooting approach), using the direct solution as an initial guess.
136143

137-
```@example initial_time
144+
```@example free-initial-time
138145
# Pseudo-Hamiltonian
139146
H(x, p, u) = p[1]*x[2] + p[2]*u
140147
@@ -146,7 +153,7 @@ nothing # hide
146153

147154
Define the flows corresponding to the two control laws $u=+1$ and $u=-1$:
148155

149-
```@example initial_time
156+
```@example free-initial-time
150157
const u_pos = 1
151158
const u_neg = -1
152159
@@ -163,7 +170,7 @@ The **shooting function** enforces:
163170
- Switching condition ($p_2(t_1) = 0$)
164171
- Hamiltonian normalization at initial time
165172

166-
```@example initial_time
173+
```@example free-initial-time
167174
function shoot!(s, p0, t1, t0)
168175
x_t0 = x0
169176
p_t0 = p0
@@ -184,7 +191,7 @@ nothing # hide
184191

185192
To help the nonlinear solver converge, we build a good initial guess from the direct solution:
186193

187-
```@example initial_time
194+
```@example free-initial-time
188195
t = time_grid(sol)
189196
x = state(sol)
190197
p = costate(sol)
@@ -206,9 +213,9 @@ println("\n‖s‖ (initial guess) = ", norm(s), "\n")
206213

207214
We can now solve the system using an **indirect shooting method**:
208215

209-
```@example initial_time
216+
```@example free-initial-time
210217
# Aggregated nonlinear system
211-
shoot!(s, ξ, λ) = shoot!(s, ξ[1:2], ξ[3], ξ[4])
218+
shoot!(s, ξ, _) = shoot!(s, ξ[1:2], ξ[3], ξ[4])
212219
213220
# Define the problem and initial guess
214221
ξ_guess = [p0..., t1, t0]
@@ -219,13 +226,13 @@ indirect_sol = solve(prob; show_trace=Val(true), abstol=1e-8, reltol=1e-8)
219226
nothing # hide
220227
```
221228

222-
```@example initial_time
229+
```@example free-initial-time
223230
indirect_sol # hide
224231
```
225232

226233
Compare **indirect and direct solutions**:
227234

228-
```@example initial_time
235+
```@example free-initial-time
229236
p0 = indirect_sol.u[1:2]
230237
t1 = indirect_sol.u[3]
231238
t0 = indirect_sol.u[4]

0 commit comments

Comments
 (0)