Skip to content
Snippets Groups Projects
Commit 20706a59 authored by Olivier Cots's avatar Olivier Cots
Browse files

foo

parent 47bef088
Branches
No related tags found
No related merge requests found
%% Cell type:markdown id:660275fc tags: %% Cell type:markdown id:660275fc tags:
<div style="display:flex"> <div style="display:flex">
<img <img
src="https://gitlab.irit.fr/toc/etu-n7/controle-optimal/-/raw/master/ressources/Logo-toulouse-inp-N7.png" src="https://gitlab.irit.fr/toc/etu-n7/controle-optimal/-/raw/master/ressources/Logo-toulouse-inp-N7.png"
height="100" height="100"
> >
<img <img
src="https://gitlab.irit.fr/toc/etu-n7/controle-optimal/-/raw/master/ressources/ship.jpg" src="https://gitlab.irit.fr/toc/etu-n7/controle-optimal/-/raw/master/ressources/ship.jpg"
style="display: block; style="display: block;
margin-left: auto; margin-left: auto;
margin-right: auto; margin-right: auto;
width: 50%;" width: 50%;"
> >
</div> </div>
# Problème de navigation, une approche [MPC](https://en.wikipedia.org/wiki/Model_predictive_control) # Problème de navigation, une approche [MPC](https://en.wikipedia.org/wiki/Model_predictive_control)
- Date : 2025 - Date : 2025
- Durée approximative : inconnue - Durée approximative : inconnue
On considère un navire dans un courant constant $w=(w_x,w_y)$, $\|w\| \lt 1$. On considère un navire dans un courant constant $w=(w_x,w_y)$, $\|w\| \lt 1$.
[L'angle de cap](https://fr.wikipedia.org/wiki/Cap_(navigation)) est contrôlé, amenant aux équations différentielles suivantes : [L'angle de cap](https://fr.wikipedia.org/wiki/Cap_(navigation)) est contrôlé, amenant aux équations différentielles suivantes :
$$ \begin{array}{rcl} $$ \begin{array}{rcl}
\dot{x}(t) &=& w_x+\cos\theta(t),\quad t \in [0,t_f]\\ \dot{x}(t) &=& w_x+\cos\theta(t),\quad t \in [0,t_f]\\
\dot{y}(t) &=& w_y+\sin\theta(t),\\ \dot{y}(t) &=& w_y+\sin\theta(t),\\
\dot{\theta}(t) &=& u(t). \dot{\theta}(t) &=& u(t).
\end{array} $$ \end{array} $$
La vitesse angulaire est limitée et normalisée : $\|u(t)\| \leq 1$. Il y a des conditions aux limites au temps initial $t = 0$ et au temps final $t = t_f$, sur la position $(x,y)$ et sur l'angle $\theta$. L'objectif est de minimiser le temps final. Ce sujet est inspiré de ce [TP](https://github.com/pns-mam/commande/tree/main/tp3) dont le problème vient d'une collaboration entre l'Université Côte d'Azur et l'entreprise française [CGG](https://www.cgg.com) qui s'intéresse aux manoeuvres optimales de très gros navires pour la prospection marine. La vitesse angulaire est limitée et normalisée : $\|u(t)\| \leq 1$. Il y a des conditions aux limites au temps initial $t = 0$ et au temps final $t = t_f$, sur la position $(x,y)$ et sur l'angle $\theta$. L'objectif est de minimiser le temps final. Ce sujet est inspiré de ce [TP](https://github.com/pns-mam/commande/tree/main/tp3) dont le problème vient d'une collaboration entre l'Université Côte d'Azur et l'entreprise française [CGG](https://www.cgg.com) qui s'intéresse aux manoeuvres optimales de très gros navires pour la prospection marine.
✏️ **Exercice 1.** On supposera $p^0 = -1$, on se place dans le cas normal. ✏️ **Exercice 1.** On supposera $p^0 = -1$, on se place dans le cas normal.
1. Ecrire le problème de contrôle optimal sous la forme de Mayer. 1. Ecrire le problème de contrôle optimal sous la forme de Mayer.
2. Donner le pseudo-hamiltonien $H(q, p, u)$, où $q = (x, y, \theta)$ et $p = (p_x, p_y, p_\theta)$. 2. Donner le pseudo-hamiltonien $H(q, p, u)$, où $q = (x, y, \theta)$ et $p = (p_x, p_y, p_\theta)$.
3. Calculer l'équation adjointe, c'est-à-dire vérifiée par le vecteur adjoint $p$, donnée par le principe du maximum de Pontryagin. 3. Calculer l'équation adjointe, c'est-à-dire vérifiée par le vecteur adjoint $p$, donnée par le principe du maximum de Pontryagin.
4. Calculer le contrôle maximisant en fonction de $p_\theta$ (on pourra l'écrire comme une [fonction multivaluée](https://fr.wikipedia.org/wiki/Fonction_multivaluée)). 4. Puisque le temps final $t_f$ est libre, nous avons une condition sur le pseudo-hamiltonien à ce temps-ci. Donner la condition vérifiée par $H(q(t_f), p(t_f), u(t_f))$.
5. Calculer le contrôle singulier, c'est-à-dire celui permettant de vérifier $p_\theta(t) = 0$ sur un intervalle de temps non réduit à un singleton. 5. Calculer le contrôle maximisant en fonction de $p_\theta$ (on pourra l'écrire comme une [fonction multivaluée](https://fr.wikipedia.org/wiki/Fonction_multivaluée)).
6. Calculer le contrôle singulier, c'est-à-dire celui permettant de vérifier $p_\theta(t) = 0$ sur un intervalle de temps non réduit à un singleton. Utiliser le fait que le pseudo-hamiltonien est constant le long de l'extrémale pour conclure.
%% Cell type:markdown id:a68c170f tags: %% Cell type:markdown id:a68c170f tags:
## Données du problème ## Données du problème
%% Cell type:code id:8dd6f718 tags: %% Cell type:code id:8dd6f718 tags:
``` julia ``` julia
using OptimalControl, NLPModelsIpopt, Plots, OrdinaryDiffEq, LinearAlgebra, Plots.PlotMeasures using OptimalControl, NLPModelsIpopt, Plots, OrdinaryDiffEq, LinearAlgebra, Plots.PlotMeasures
t0 = 0. t0 = 0.
x0 = 0. x0 = 0.
y0 = 0. y0 = 0.
θ0 = π/7 θ0 = π/7
xf = 4. xf = 4.
yf = 7. yf = 7.
θf = -π/2 θf = -π/2
function current(x, y) # current as a function of position function current(x, y) # current as a function of position
ε = 1e-1 ε = 1e-1
w = [ 0.6, 0.4 ] w = [ 0.6, 0.4 ]
δw = ε * [ y, -x ] / sqrt(1+x^2+y^2) δw = ε * [ y, -x ] / sqrt(1+x^2+y^2)
w = w + δw w = w + δw
if (w[1]^2 + w[2]^2 >= 1) if (w[1]^2 + w[2]^2 >= 1)
error("|w| >= 1") error("|w| >= 1")
end end
return w return w
end end
# #
function plot_state!(plt, x, y, θ; color=1) function plot_state!(plt, x, y, θ; color=1)
plot!(plt, [x], [y], marker=:circle, legend=false, color=color, markerstrokecolor=color, markersize=5, z_order=:front) plot!(plt, [x], [y], marker=:circle, legend=false, color=color, markerstrokecolor=color, markersize=5, z_order=:front)
quiver!(plt, [x], [y], quiver=([cos(θ)], [sin(θ)]), color=color, linewidth=2, z_order=:front) quiver!(plt, [x], [y], quiver=([cos(θ)], [sin(θ)]), color=color, linewidth=2, z_order=:front)
return plt return plt
end end
function plot_current!(plt; current=current, N=10, scaling=1) function plot_current!(plt; current=current, N=10, scaling=1)
for x range(xlims(plt)..., N) for x range(xlims(plt)..., N)
for y range(ylims(plt)..., N) for y range(ylims(plt)..., N)
w = scaling*current(x, y) w = scaling*current(x, y)
quiver!(plt, [x], [y], quiver=([w[1]], [w[2]]), color=:black, linewidth=0.5, z_order=:back) quiver!(plt, [x], [y], quiver=([w[1]], [w[2]]), color=:black, linewidth=0.5, z_order=:back)
end end
end end
return plt return plt
end end
# on affiche dans le plan de phase augmenté les conditions aux limites et le courant # on affiche dans le plan de phase augmenté les conditions aux limites et le courant
plt = plot( plt = plot(
xlims=(-2, 6), xlims=(-2, 6),
ylims=(-1, 8), ylims=(-1, 8),
size=(600, 600), size=(600, 600),
aspect_ratio=1, aspect_ratio=1,
xlabel="x", xlabel="x",
ylabel="y", ylabel="y",
title="Conditions aux limites", title="Conditions aux limites",
leftmargin=5mm, leftmargin=5mm,
bottommargin=5mm, bottommargin=5mm,
) )
plot_state!(plt, x0, y0, θ0; color=2) plot_state!(plt, x0, y0, θ0; color=2)
plot_state!(plt, xf, yf, θf; color=2) plot_state!(plt, xf, yf, θf; color=2)
plot_current!(plt) plot_current!(plt)
``` ```
%% Cell type:code id:8b4c8930 tags: %% Cell type:code id:8b4c8930 tags:
``` julia ``` julia
function plot_trajectory!(plt, t, x, y, θ; N=5) # N : nombre de points où l'on va afficher θ function plot_trajectory!(plt, t, x, y, θ; N=5) # N : nombre de points où l'on va afficher θ
# trajectoire # trajectoire
plot!(plt, x.(t), y.(t), legend=false, color=1, linewidth=2, z_order=:front) plot!(plt, x.(t), y.(t), legend=false, color=1, linewidth=2, z_order=:front)
if N > 0 if N > 0
# longueur du trajet # longueur du trajet
s = 0 s = 0
for i 2:length(t) for i 2:length(t)
s += norm([x(t[i]), y(t[i])] - [x(t[i-1]), y(t[i-1])]) s += norm([x(t[i]), y(t[i])] - [x(t[i-1]), y(t[i-1])])
end end
# intervalle de longueur # intervalle de longueur
Δs = s/(N+1) Δs = s/(N+1)
tis = [] tis = []
s = 0 s = 0
for i 2:length(t) for i 2:length(t)
s += norm([x(t[i]), y(t[i])] - [x(t[i-1]), y(t[i-1])]) s += norm([x(t[i]), y(t[i])] - [x(t[i-1]), y(t[i-1])])
if s > Δs && length(tis) < N if s > Δs && length(tis) < N
push!(tis, t[i]) push!(tis, t[i])
s = 0 s = 0
end end
end end
# affichage des points intermédiaires # affichage des points intermédiaires
for ti tis for ti tis
plot_state!(plt, x(ti), y(ti), θ(ti); color=1) plot_state!(plt, x(ti), y(ti), θ(ti); color=1)
end end
end end
return plt return plt
end; end;
``` ```
%% Cell type:markdown id:0403331e tags: %% Cell type:markdown id:0403331e tags:
## Solveur (OptimalControl) ## Solveur (OptimalControl)
✏️ **Exercice 2.** Coder le problème de contrôle optimal ci-dessous. ✏️ **Exercice 2.** Coder le problème de contrôle optimal ci-dessous.
On pourra s'insiprer du problème de la [rame de métro à temps minimal](https://control-toolbox.org/OptimalControl.jl/stable/tutorial-double-integrator-time.html) décrit dans la documentation du package OptimalControl pour définir notre problème de manoeuvre de navire ci-après. On pourra s'insiprer du problème de la [rame de métro à temps minimal](https://control-toolbox.org/OptimalControl.jl/stable/tutorial-double-integrator-time.html) décrit dans la documentation du package OptimalControl pour définir notre problème de manoeuvre de navire ci-après.
%% Cell type:code id:a1933e2c tags: %% Cell type:code id:a1933e2c tags:
``` julia ``` julia
function solve(t0, x0, y0, θ0, xf, yf, θf, w; function solve(t0, x0, y0, θ0, xf, yf, θf, w;
grid_size=300, tol=1e-8, max_iter=500, print_level=4, display=true) grid_size=300, tol=1e-8, max_iter=500, print_level=4, display=true)
# --------------------------------------- # ---------------------------------------
# Définition du problème : TO UPDATE # Définition du problème : TO UPDATE
ocp = @def begin ocp = @def begin
end end
# --------------------------------------- # ---------------------------------------
# Initialisation # Initialisation
tf_init = 1.5*norm([xf, yf]-[x0, y0]) tf_init = 1.5*norm([xf, yf]-[x0, y0])
x_init(t) = [ x0, y0, θ0 ] * (tf_init-t)/(tf_init-t0) + [xf, yf, θf] * (t-t0)/(tf_init-t0) x_init(t) = [ x0, y0, θ0 ] * (tf_init-t)/(tf_init-t0) + [xf, yf, θf] * (t-t0)/(tf_init-t0)
u_init = (θf - θ0) / (tf_init-t0) u_init = (θf - θ0) / (tf_init-t0)
init = (state=x_init, control=u_init, variable=tf_init) init = (state=x_init, control=u_init, variable=tf_init)
# Résolution # Résolution
sol = OptimalControl.solve(ocp; sol = OptimalControl.solve(ocp;
init=init, init=init,
grid_size=grid_size, grid_size=grid_size,
tol=tol, tol=tol,
max_iter=max_iter, max_iter=max_iter,
print_level=print_level, print_level=print_level,
display=display, display=display,
disc_method=:euler, disc_method=:euler,
) )
# Récupération des données utiles # Récupération des données utiles
t = time_grid(sol) t = time_grid(sol)
q = state(sol) q = state(sol)
x = t -> q(t)[1] x = t -> q(t)[1]
y = t -> q(t)[2] y = t -> q(t)[2]
θ = t -> q(t)[3] θ = t -> q(t)[3]
u = control(sol) u = control(sol)
tf = variable(sol) tf = variable(sol)
return t, x, y, θ, u, tf, iterations(sol), sol.solver_infos.constraints_violation return t, x, y, θ, u, tf, iterations(sol), sol.solver_infos.constraints_violation
end; end;
``` ```
%% Cell type:markdown id:cc8547d2 tags: %% Cell type:markdown id:cc8547d2 tags:
## Première résolution ## Première résolution
On considère ici un vent constant et on résout une première fois le problème. On considère ici un vent constant et on résout une première fois le problème.
%% Cell type:code id:ffea082a tags: %% Cell type:code id:ffea082a tags:
``` julia ``` julia
# ----------------------------------------------------------------------------------------------------------- # -----------------------------------------------------------------------------------------------------------
t, x, y, θ, u, tf, iter, cons = solve(t0, x0, y0, θ0, xf, yf, θf, current(x0, y0); display=false); t, x, y, θ, u, tf, iter, cons = solve(t0, x0, y0, θ0, xf, yf, θf, current(x0, y0); display=false);
println("Iterations : ", iter) println("Iterations : ", iter)
println("Constraints violation : ", cons) println("Constraints violation : ", cons)
println("tf : ", tf) println("tf : ", tf)
# ----------------------------------------------------------------------------------------------------------- # -----------------------------------------------------------------------------------------------------------
# affichage # affichage
# trajectoire # trajectoire
plt_q = plot(xlims=(-2, 6), ylims=(-1, 8), aspect_ratio=1, xlabel="x", ylabel="y") plt_q = plot(xlims=(-2, 6), ylims=(-1, 8), aspect_ratio=1, xlabel="x", ylabel="y")
plot_state!(plt_q, x0, y0, θ0; color=2) plot_state!(plt_q, x0, y0, θ0; color=2)
plot_state!(plt_q, xf, yf, θf; color=2) plot_state!(plt_q, xf, yf, θf; color=2)
plot_current!(plt_q; current=(x, y) -> current(x0, y0)) plot_current!(plt_q; current=(x, y) -> current(x0, y0))
plot_trajectory!(plt_q, t, x, y, θ) plot_trajectory!(plt_q, t, x, y, θ)
# contrôle # contrôle
plt_u = plot(t, u; color=1, legend=false, linewidth=2, xlabel="t", ylabel="u") plt_u = plot(t, u; color=1, legend=false, linewidth=2, xlabel="t", ylabel="u")
# #
plot(plt_q, plt_u; plot(plt_q, plt_u;
layout=(1, 2), layout=(1, 2),
size=(1200, 600), size=(1200, 600),
leftmargin=5mm, leftmargin=5mm,
bottommargin=5mm, bottommargin=5mm,
plot_title="Simulation courant constant" plot_title="Simulation courant constant"
) )
``` ```
%% Cell type:markdown id:827b18d5 tags: %% Cell type:markdown id:827b18d5 tags:
## Simulation du système réel ## Simulation du système réel
Dans la simulation précédente, nous faisons l'hypothèse que le courant est constant. Cependant, d'un point de vue pratique le courant dépend de la position $(x, y)$. Etant donné un modèle de courant, donné par la fonction `current`, nous pouvons simuler la trajectoire réelle du navire, pourvu que l'on ait la condition initiale et le contrôle au cours du temps. Dans la simulation précédente, nous faisons l'hypothèse que le courant est constant. Cependant, d'un point de vue pratique le courant dépend de la position $(x, y)$. Etant donné un modèle de courant, donné par la fonction `current`, nous pouvons simuler la trajectoire réelle du navire, pourvu que l'on ait la condition initiale et le contrôle au cours du temps.
%% Cell type:code id:25422e2e tags: %% Cell type:code id:25422e2e tags:
``` julia ``` julia
function realistic_trajectory(tf, t0, x0, y0, θ0, u, current; abstol=1e-12, reltol=1e-12, saveat=[]) function realistic_trajectory(tf, t0, x0, y0, θ0, u, current; abstol=1e-12, reltol=1e-12, saveat=[])
function rhs!(dq, q, dummy, t) function rhs!(dq, q, dummy, t)
x, y, θ = q x, y, θ = q
w = current(x, y) w = current(x, y)
dq[1] = w[1]+cos(θ) dq[1] = w[1]+cos(θ)
dq[2] = w[2]+sin(θ) dq[2] = w[2]+sin(θ)
dq[3] = u(t) dq[3] = u(t)
end end
q0 = [ x0, y0, θ0 ] q0 = [ x0, y0, θ0 ]
tspan = (t0, tf) tspan = (t0, tf)
ode = ODEProblem(rhs!, q0, tspan) ode = ODEProblem(rhs!, q0, tspan)
sol = OrdinaryDiffEq.solve(ode, Tsit5(), abstol=abstol, reltol=reltol, saveat=saveat) sol = OrdinaryDiffEq.solve(ode, Tsit5(), abstol=abstol, reltol=reltol, saveat=saveat)
t = sol.t t = sol.t
x = t -> sol(t)[1] x = t -> sol(t)[1]
y = t -> sol(t)[2] y = t -> sol(t)[2]
θ = t -> sol(t)[3] θ = t -> sol(t)[3]
return t, x, y, θ return t, x, y, θ
end; end;
``` ```
%% Cell type:code id:da61110e tags: %% Cell type:code id:da61110e tags:
``` julia ``` julia
# trajectoire réaliste # trajectoire réaliste
t, x, y, θ = realistic_trajectory(tf, t0, x0, y0, θ0, u, current) t, x, y, θ = realistic_trajectory(tf, t0, x0, y0, θ0, u, current)
# ----------------------------------------------------------------------------------------------------------- # -----------------------------------------------------------------------------------------------------------
# affichage # affichage
# trajectoire # trajectoire
plt_q = plot(xlims=(-2, 6), ylims=(-1, 8), aspect_ratio=1, xlabel="x", ylabel="y") plt_q = plot(xlims=(-2, 6), ylims=(-1, 8), aspect_ratio=1, xlabel="x", ylabel="y")
plot_state!(plt_q, x0, y0, θ0; color=2) plot_state!(plt_q, x0, y0, θ0; color=2)
plot_state!(plt_q, xf, yf, θf; color=2) plot_state!(plt_q, xf, yf, θf; color=2)
plot_current!(plt_q; current=current) plot_current!(plt_q; current=current)
plot_trajectory!(plt_q, t, x, y, θ) plot_trajectory!(plt_q, t, x, y, θ)
plot_state!(plt_q, x(tf), y(tf), θ(tf); color=3) plot_state!(plt_q, x(tf), y(tf), θ(tf); color=3)
# contrôle # contrôle
plt_u = plot(t, u; color=1, legend=false, linewidth=2, xlabel="t", ylabel="u") plt_u = plot(t, u; color=1, legend=false, linewidth=2, xlabel="t", ylabel="u")
# #
plot(plt_q, plt_u; plot(plt_q, plt_u;
layout=(1, 2), layout=(1, 2),
size=(1200, 600), size=(1200, 600),
leftmargin=5mm, leftmargin=5mm,
bottommargin=5mm, bottommargin=5mm,
plot_title="Simulation avec modèle de courant" plot_title="Simulation avec modèle de courant"
) )
``` ```
%% Cell type:markdown id:503bd360 tags: %% Cell type:markdown id:503bd360 tags:
## Approche MPC ## Approche MPC
En pratique, nous n'avons pas à l'avance les données réelles du courant sur l'ensemble du trajet, c'est pourquoi nous allons recalculer régulièrement le contrôle optimal. L'idée est de mettre à jour le contrôle optimal à intervalle de temps régulier en prenant en compte le courant à la position où le navire se trouve. On est donc amener à résoudre un certain nombre de problème à courant constant, avec celui-ci mis réguilièremet à jour. Ceci est une introduction aux méthodes dites MPC, pour "Model Predictive Control" en anglais. En pratique, nous n'avons pas à l'avance les données réelles du courant sur l'ensemble du trajet, c'est pourquoi nous allons recalculer régulièrement le contrôle optimal. L'idée est de mettre à jour le contrôle optimal à intervalle de temps régulier en prenant en compte le courant à la position où le navire se trouve. On est donc amener à résoudre un certain nombre de problème à courant constant, avec celui-ci mis réguilièremet à jour. Ceci est une introduction aux méthodes dites MPC, pour "Model Predictive Control" en anglais.
%% Cell type:code id:563c73fd tags: %% Cell type:code id:563c73fd tags:
``` julia ``` julia
Nmax = 20 # nombre d'itérations max de la méthode MPC Nmax = 20 # nombre d'itérations max de la méthode MPC
ε = 1e-1 # rayon sur la condition finale pour stopper les calculs ε = 1e-1 # rayon sur la condition finale pour stopper les calculs
Δt = 1.0 # pas de temps fixe de la méthode MPC Δt = 1.0 # pas de temps fixe de la méthode MPC
P = 300 # nombre de points de discrétisation pour le solveur P = 300 # nombre de points de discrétisation pour le solveur
t1 = t0 t1 = t0
x1 = x0 x1 = x0
y1 = y0 y1 = y0
θ1 = θ0 θ1 = θ0
data = [] data = []
N = 1 N = 1
stop = false stop = false
while !stop while !stop
# on récupère le courant à la position actuelle # on récupère le courant à la position actuelle
w = current(x1, y1) w = current(x1, y1)
# on résout le problème # on résout le problème
t, x, y, θ, u, tf, iter, cons = solve(t1, x1, y1, θ1, xf, yf, θf, w; grid_size=P, display=false); t, x, y, θ, u, tf, iter, cons = solve(t1, x1, y1, θ1, xf, yf, θf, w; grid_size=P, display=false);
# calcul du temps suivant # calcul du temps suivant
if (t1+Δt < tf) if (t1+Δt < tf)
t2 = t1+Δt t2 = t1+Δt
else else
t2 = tf t2 = tf
println("t2=tf: ", t2) println("t2=tf: ", t2)
stop = true stop = true
end end
# on stocke les données: le temps initial courant, le temps suivant, le contrôle # on stocke les données: le temps initial courant, le temps suivant, le contrôle
push!(data, (t2, t1, x(t1), y(t1), θ(t1), u, tf)) push!(data, (t2, t1, x(t1), y(t1), θ(t1), u, tf))
# on met à jour les paramètres de la méthode MPC: on simule la réalité # on met à jour les paramètres de la méthode MPC: on simule la réalité
t, x, y, θ = realistic_trajectory(t2, t1, x1, y1, θ1, u, current) t, x, y, θ = realistic_trajectory(t2, t1, x1, y1, θ1, u, current)
t1 = t2 t1 = t2
x1 = x(t1) x1 = x(t1)
y1 = y(t1) y1 = y(t1)
θ1 = θ(t1) θ1 = θ(t1)
# on calcule la distance à la position cible # on calcule la distance à la position cible
distance = norm([ x1, y1, θ1 ] - [ xf, yf, θf ]) distance = norm([ x1, y1, θ1 ] - [ xf, yf, θf ])
println("N: ", N, "\t distance: ", distance, "\t iterations: ", iter, "\t constraints: ", cons, "\t tf: ", tf) println("N: ", N, "\t distance: ", distance, "\t iterations: ", iter, "\t constraints: ", cons, "\t tf: ", tf)
if !((distance > ε) && (N < Nmax)) if !((distance > ε) && (N < Nmax))
stop = true stop = true
end end
# #
N += 1 N += 1
end end
``` ```
%% Cell type:markdown id:edd803b2 tags: %% Cell type:markdown id:edd803b2 tags:
## Affichage ## Affichage
%% Cell type:code id:d0292a49 tags: %% Cell type:code id:d0292a49 tags:
``` julia ``` julia
# trajectoire # trajectoire
plt_q = plot(xlims=(-2, 6), ylims=(-1, 8), aspect_ratio=1, xlabel="x", ylabel="y") plt_q = plot(xlims=(-2, 6), ylims=(-1, 8), aspect_ratio=1, xlabel="x", ylabel="y")
# condition finale # condition finale
plot_state!(plt_q, xf, yf, θf; color=2) plot_state!(plt_q, xf, yf, θf; color=2)
# courant # courant
plot_current!(plt_q; current=current) plot_current!(plt_q; current=current)
# contrôle # contrôle
plt_u = plot(xlabel="t", ylabel="u") plt_u = plot(xlabel="t", ylabel="u")
N = 1 N = 1
for d data for d data
# #
t2, t1, x1, y1, θ1, u, tf = d t2, t1, x1, y1, θ1, u, tf = d
# calcule de la trajectoire réelle # calcule de la trajectoire réelle
t, x, y, θ = realistic_trajectory(t2, t1, x1, y1, θ1, u, current) t, x, y, θ = realistic_trajectory(t2, t1, x1, y1, θ1, u, current)
# trajectoire # trajectoire
plot_state!(plt_q, x1, y1, θ1; color=2) plot_state!(plt_q, x1, y1, θ1; color=2)
plot_trajectory!(plt_q, t, x, y, θ; N=0) plot_trajectory!(plt_q, t, x, y, θ; N=0)
# contrôle # contrôle
plot!(plt_u, t, u; color=1, legend=false, linewidth=2) plot!(plt_u, t, u; color=1, legend=false, linewidth=2)
N += 1 N += 1
end end
plot_state!(plt_q, x(tf), y(tf), θ(tf); color=3) plot_state!(plt_q, x(tf), y(tf), θ(tf); color=3)
# #
plot(plt_q, plt_u; plot(plt_q, plt_u;
layout=(1, 2), layout=(1, 2),
size=(1200, 600), size=(1200, 600),
leftmargin=5mm, leftmargin=5mm,
bottommargin=5mm, bottommargin=5mm,
plot_title="Simulation avec modèle de courant" plot_title="Simulation avec modèle de courant"
) )
``` ```
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment