Optimisation de trajectoire pour une mission Ariane 5 Ludovic Goudenège Janvier 2015 Je n’ai malheureusement pas la possibilité d’être présent pour cette séance et j’espère que vous pourrez travailler en autonomie avec les informations supplémentaires que je vais vous donner via ce document. De plus, afin d’évaluer votre travail, je vous demanderai de rédiger un compte-rendu de la séance à me rendre en fin de séance. Il s’agit de répondre aux questions de cette feuille et de rédiger les codes MATLAB correspondants. Envoyez moi l’ensemble de vos codes sous forme d’une archive par mail à cette adresse : [email protected] Il est recommandé de travailler en binôme, mais vous pouvez aussi travailler seul ou même à trois suivant la parité des élèves présents. Les absents à cette séance ne seront pas pénalisés et ce compte-rendu me permettra surtout de vérifier que vous avez acquis les compétences nécessaires avant la véritable séance d’examen. Ce document reprenant essentiellement les différentes étapes clés du projet, vous pouvez également profiter de cette séance pour commencer à rédiger votre présentation pour l’examen en vous inspirant du plan proposé ici. 1 1.1 Coder les fonctions de bases Calculer la force En début de projet, vous avez été amenés à rédiger des fonctions diverses et variées. Certaines se révèlent sans doute inutiles maintenant, ou bien leur code n’est sans doute pas très optimisé pour la vitesse. Je vous propose donc de trouver un moyen d’écrire une fonction (qui soit un minimum optimisée) pour calculer la trajectoire. Lors des premières séances, vous avez codé les fonctions de base suivantes : masse, beta, isp, poids et poussee. Elles ont pour prototype la forme suivante : function m = masse(t) % t est un scalaire, et m est un scalaire. function b = beta(t) % t est un scalaire, et b est un scalaire. function i = isp(t) % t est un scalaire, et i est un scalaire. function W = poids(m,r) % m est un scalaire (la masse), et r est un vecteur colonne 2D (la position). % W est un vecteur colonne 2D qui contient la force ‘‘poids’’. function T = poussee(bi,u) % bi est un scalaire (le produit beta * isp), et u est un angle dans [0, pi]. % T est un vecteur colonne 2D qui contient la force ‘‘poussee’’. Malheureusement dans ces fonctions il existe des redondances. Par exemple dans les trois premières il y a les mêmes tests if else pour décider si on est dans la phase 1, 2 ou 3. IL faudrait trouver un moyen d’éviter de faire plusieurs fois les mêmes tests. Pour cela, il suffit de coder une 1 seule fonction qui rassemble les précédentes. Question 1 : Coder une seule fonction force globale selon le prototype suivant : function F % t est un % et u est % F est un % la somme = force_globale(t,r,u) scalaire, r est un vecteur colonne 2D (la position) un angle dans [0, pi]. vecteur colonne 2D qui contient du ‘‘poids’’ et de la ‘‘poussee’’. Dans les fonctions de base, on a appris à utiliser des variables globales, afin d’éviter de les passer en paramètres, mais les variables globales ont tendance à ralentir l’exécution d’un programme. Dans votre fonction force globale, vous avez certainement encore fait appel aux variables globales du problème. Question 2 : Coder une deuxième fonction force selon le prototype suivant : function F % t est un % et u est % F est un % la somme = force(t,r,u) scalaire, r est un vecteur colonne 2D (la position) un angle dans [0, pi]. vecteur colonne 2D qui contient du ‘‘poids’’ et de la ‘‘poussee’’. mais sans utiliser de variables globales (i.e. mettre toutes les constantes du problème (masseBooster, debitEtage1, etc avec leur valeur explicite)). Question 3 : Comment savoir quelle fonction est la plus efficace ? Quel test mettriez-vous en place pour tester la rapidité des deux fonctions ? Quelle fonction vous semble alors la plus rapide entre force globale et force ? On veut ensuite coder la fonction f qui représente l’équation différentielle de la dynamique y 0 = f (t, y), où y est un vecteur colonne 4D (2 dimensions pour r la position et deux dimensions pour v la vitesse). Elle s’écrit sous la forme f: R × R4 → (t, y) = (t, y1 , y2 , y3 , y4 ) 7→ R4 (y3 , y4 , force(t,[y(1);y(2)])/masse(t)). La fonction dynamic suivante : function y = dynamic(t, x, u ) % t est un scalaire, x est un vecteur colonne 4D (position et vitesse) % et u est un angle entre 0 et pi. m=masse(t); F=force(t, x(1:2,1), u); y=[x(3:4,1);F/m]; qui code la fonction f en MATLAB n’est pas optimisée car elle fait appel à masse et force et donc encore une fois, il y a doublement des tests pour le choix des phases 1, 2 ou 3. Question 4 : Écrivez une version optimisée de dynamic en gardant le même prototype. function y = dynamic(t, x, u ) % t est un scalaire, x est un vecteur colonne 4D (position et vitesse) % et u est un angle entre 0 et pi. 2 3 3 2.5 2.5 2 2 1.5 1.5 1 1 0.5 0.5 0 0 0 500 1000 1500 0 (a) Commande à 12 valeurs 500 1000 1500 (b) Commande à 6 valeurs Figure 1: Deux commandes u possibles. 1.2 La commande de la fusée Le troisième paramètre de la fonction dynamic est u l’angle de la commande. On supposera que cet angle reste entre 0 et π. Sur la figure 1, vous pouvez voir le tracé de deux commandes possibles sur la période de poussée [0, 1500]. La commande est constante par morceaux. On peut imaginer en effet que les ingénieurs orientent les moteurs dans une certaine direction et ne modifie cette direction qu’à certains instants donnés. Ici les ingénieurs ont décidé de donner une valeur à la commande toutes les 125 secondes, ce qui donne 12 valeurs au cours du temps. Le deuxième exemple de commande ne prend que 6 valeurs changeantes toutes les 250 secondes. On dit que la commande peut être encodée sur 6 (ou 12) valeurs. C’est-à-dire qu’on se représente la commande par un vecteur uvect de taille 6 (ou 12, disons N com dans le cas général). Mais la commande est en réalité une fonction du temps. Question 5 : Coder une fonction commande qui a le prototype suivant : function u=commande(t,uvect) % t est un scalaire, uvect est un vecteur de taille Ncom. % u est la valeur de la commande au temps t obtenue par uvect. Ncom=length(uvect); permettant de calculer la valeur de la commande (encodée par uvect) a n’importe quel instant t. Remarque 1.1 Attention cette fonction doit être capable de s’adapter à la taille de uvect. En particulier si uvect est de taille 1, la commande est une fonction constante. Si uvect est de taille 3, alors la commande ne change de valeurs que toutes les 500 secondes. Remarque 1.2 Attention pour éviter les effet de bords, on dira que si t ≤ 0 on a u=uvect(1) et si t ≥ 1500 on a u=uvect(Ncom). 1.3 Résoudre l’équation de la dynamique Lors des séances précédentes, vous avez du coder un schéma d’Euler pour résoudre les équations différentielles du premier ordre de la forme y 0 = f (t, y). Afin que tout le monde possède le même type de fonction, je vous propose de coder de nouveau ce schéma en utilisant un prototype donné. Question 6 : Coder une fonction euler (qui permet de résoudre l’équation de la dynamique en utilisant le schéma d’Euler et la fonction dynamique) avec le prototype suivant : 3 function Traj = euler(Y0, ti, tf, N, uvect) % Schema d’Euler pour l’equation y’ = strf(y) % Y0 est la donnee initiale, c’est un vecteur colonne de dimension 4. % ti et tf sont les instants de debut et de fin. % N est le nombre de pas de temps : [Y0, Y1, Y2] represente 3 pas de temps. % uvect est un vecteur de taille Ncom qui represente la commande. % Traj est une matrice de taille 4 x N qui contient toute la trajectoire % c’est-a-dire la position r et la vitesse v pour les N instants entre ti et tf. A ce stade du TP, vous devriez pouvoir appeler les deux commandes suivantes dans la console MATLAB : > Traj = euler([RTerre;0;0;(2*pi*RTerre/TTerre)], 0, 1500, 100, [0.98,3.14,1.62]); > plot(Traj(1,:),Traj(2,:)) qui utilise une commande uvect de 3 valeurs [0.98, 3.14, 1.62] et qui résoud la dynamique avec un schéma d’Euler utilisant 100 pas de temps entre 0 et 1500 secondes. Vous devriez obtenir le dessin suivant 6 x 10 10 9 8 7 6 5 4 3 2 1 0 4 4.5 5 5.5 6 6.5 7 6 x 10 Figure 2: Trajectoire obtenue avec la commande uvect=[0.98,3.14,1.62]. 2 Optimisation de trajectoire Afin de visualiser ce résultat, je vous propose de tracer sur la figure 3 la Terre (courbe bleue), la trajectoire elliptique des satellites obtenue par la simulation (courbe rouge), l’orbite GEO finalement atteinte (courbe magenta) ainsi que les trajectoires optimales (courbe verte et cyan). J’indique également les instants terminaux des trois phases lorsqu’il y a largage de moteurs. Vous trouverez en annexe de cette feuille la fonction trace courbes qui permet de tracer tout ceci. Remarquez que souvent les satellites reviennent s’écraser sur Terre. Ce n’est pas vraiment un problème, car un fois à leur périgée, ils sont envoyés sur l’orbite GEO. Il peut aussi arriver que la commande envoie les satellites sur des trajectoires paraboliques ou hyperboliques. Ces cas doivent être écartés par le programme. Je vous propose d’écrire maintenat la fonction qui va mesurer la qualité de la trajectoire bleue obtenue. Remarquez que la commande n’a pas besoin d’être très complexe pour obtenir une trajectoire assez satisfaisante. La commande qui n’a que 6 valeurs est tout à fait acceptable. Question 7 : Coder une fonction quality ellipse qui va mesurer la qualité d’une trajectoire elliptique avec le prototype suivant : function Q = quality_ellipse(uvect) % uvect est un vecteur de taille Ncom qui represente la commande. 4 7 x 10 4 3 2 1 0 Terre Trajectoire numerique Largage Booster Largage Etage 1 Largage Etage 2 et Satellites Ellipse numerique Orbite GEO numérique Ellipse optimale Orbite GEO optimale −1 −2 −3 −4 −5 −4 −3 −2 −1 0 1 2 3 4 5 7 x 10 (a) Commande à 12 valeurs 7 x 10 4 3 2 1 0 −1 Terre Trajectoire numerique Largage Booster Largage Etage 1 Largage Etage 2 et Satellites Ellipse numerique Orbite GEO numérique Ellipse optimale Orbite GEO optimale −2 −3 −4 −5 −4 −3 −2 −1 0 1 2 3 4 5 7 x 10 (b) Commande à 6 valeurs 7 x 10 6 4 2 0 Terre Trajectoire numerique Largage Booster Largage Etage 1 Largage Etage 2 et Satellites Ellipse numerique Orbite GEO numérique Ellipse optimale Orbite GEO optimale −2 −4 −6 −1 −0.8 −0.6 −0.4 −0.2 0 0.2 0.4 0.6 0.8 1 8 x 10 (c) Commande à 3 valeurs Figure 3: Trajectoires obtenues avec les commandes uvect de la figure 1 et uvect= [0.98,3.14,1.62]. 5 Traj = euler([RTerre;0;0;(2*pi*RTerre/TTerre)], 0, 1500, 100, uvect); ... ... Remarque 2.1 Remarquez que je fais un appel à la fonction euler avec ti = 0, tf = 1500 et pour 100 pas de temps. J’obtiens la matrice Traj qui contient toute la trajectoire. Il faut maintenant extraire de cette trajectoire les points finaux, et calculer l’ellipse sur laquelle vont se trouver les satellites. Notamment la valeur du demi-grand axe a et de l’excentricité e. Les formules sont données dans les transparents de la description du projet. On pourra par exemple considérer une fonction quality ellipse sous la forme quality ellipse : RN com → R+ uvect 7→ (1 − a/aGT O)2 + (1 − e/eGT O)2 . Cette fonction accorde autant d’importance au demi-grand axe qu’à l’ecentricité. Mais d’autres choix sont possibles. De plus, votre fonction devra être capable de renvoyer une valeur lorsque les satellites se retrouvent sur des trajectoires paraboliques ou hyperboliques. Il s’agira de renvoyer une valeur importante qui pourra être facilement repérée par la suite. On obtiendrait par exemple la fonction RN com quality ellipse : uvect → R + (1 − a/aGT O)2 +(1 − e/eGT O)2 7 → 109 si la trajectoire est elliptique si la trajectoire est parabolique ou hyperbolique i.e. (e ≥ 1) Question 8 : Coder aussi une fonction quality geo qui va mesurer la qualité de la trajectoire circulaire GEO finalement obtenue avec le prototype suivant : function Q = quality_geo(uvect) % uvect est un vecteur de taille Ncom qui represente la commande. Traj = euler([RTerre;0;0;(2*pi*RTerre/TTerre)], 0, 1500, 100, uvect); ... ... Si on note rGEO = aGTO(1+eGTO), et r le rayon de la trajectoire numérique obtenue (qui est simplement r = a(1 + e)), on pourra par exemple considérer une fonction quality geo sous la forme RN com → R+ quality geo : uvect 7→ (r − rGEO)2 . Le but avoué du projet est d’optimiser l’une ou l’autre de ces deux fonctions (à votre convenance) en mettant en place des algorithmes numériques. Dans un premier temps, on pourra se restreindre à des commandes de taille (3, 6 et 12) afin de vérifier la capacité des algorithmes à trouver un minimum acceptable dans un temps de calcul raisonnable. 2.1 Algorithme déterministe de descente Lorsqu’on cherche à minimiser une fonction, en supposant qu’elle a suffisamment de régularité et qu’on a accès à une approximation du point où est atteint le minimum, plusieurs algorithmes sont envisageables. Il s’agit d’algorithmes de descente. Ces algorithmes ont par contre le défaut général de rester piégés dans les minimums locaux, et ils peuvent très bien rater un minimum global si le point de départ est mal choisi. Sur la figure 4, on illustre le fonctionnement d’un algorithme de descente. On choisit un point de départ (point rouge), on calcule une direction de descente ainsi qu’une vitesse de descente, ce qui fournit un nouveau point (vert). Et on itère le processus. Toute la difficulté consiste à correctement choisir la direction de descente (si N com = 12, la direction est un choix difficile car on se déplace 6 1.5 1 0.5 0 −0.5 −1 −0.5 0 0.5 1 1.5 2 Figure 4: Algorithme de descente. dans un espace à 12 dimensions) ainsi que la vitesse de façon à ne descendre ni trop vite, ni trop lentement. Remarquez que la vitesse au point vert est sensiblement trop grande car on a raté le minimum et on a failli passer la bosse de droite, au risque que l’algo termine sa course vers +∞. De manière générale, un algorithme de descente sur une fonction Q (par exemple quality geo ou quality ellipse) s’écrit sous la forme suivante : function xnew=descente(x0) xnew = x0+1; tolerance = 0.01; while abs(xnew-x0) > tolerance x0 = xnew; d = direction(Q,x0) v = vitesse(Q,x0) xnew = x0 + d * v; end lorsqu’on n’utilise qu’un seul point x0 . Ou sous la forme suivante : function xnew=descente(x0,x1) tolerance = 0.01; while abs(x1-x0) > tolerance d = direction(Q,x0,x1) v = vitesse(Q,x0,x1) xnew = x1 + d * v; x0=x1; x1=xnew; end lorsqu’on utilise deux points x0 et x1 . La direction et la vitesse peuvent dépendre des points x0 , x1 et bien sûr de la fonction Q. L’algorithme de Newton est un algorithme à un point qui fait le choix suivant : d = −(Q0 (x0 ))−1 et v = Q(x0 ). Il est très efficace mais il nécessite de savoir calculer la différentielle de la fonction Q (ce qui n’est evidemment pas le cas pour nos fonctions quality geo et quality ellipse). Question 9 : Coder l’algorithme de Newton sur la fonction Q: R+ x → R 7→ x + 2 . x L’algorithme de la sécante s’inspire de l’algorithme de Newton. C’est un algorithme à deux x0 − x1 points où d = et v = Q(x0 ). Q(x1 ) − Q(x0 ) 7 Question 10 : Coder l’algorithme de la sécante sur la fonction R+ Q: x → R 7→ x + 2 . x √ √ Question 11 : Le minimum de Q est 2 2 qui est atteint au point x∗ = 2. Combien d’itérations sont nécessaires avec l’algorithme de Newton et l’algorithme de la sécante pour approcher x∗ à 10−3 près ? à 10−6 près ? Question 12 : Coder l’algorithme de la séquence sur les fonctions quality geo et quality ellipse pour une commande uvect de taille 3. Remarque 2.2 Attention la direction d est bien un vecteur de taille 3, et la vitesse est un scalaire. La figure 5 vous donne un aperçu de la qualité de la trajectoire qu’on peut obtenir avec cet algorithme si on choisit correctement le point de départ. 7 x 10 4 3 2 1 0 Terre Trajectoire numerique Largage Booster Largage Etage 1 Largage Etage 2 et Satellites Ellipse numerique Orbite GEO numérique Ellipse optimale Orbite GEO optimale −1 −2 −3 −4 −5 −4 −3 −2 −1 0 1 2 3 4 5 7 x 10 Figure 5: Trajectoire obtenue par l’algorithme de la sécante sur une commande de taille 3. 2.2 Algorithme stochastique d’exploration Lorsque la dimension de l’espace à explorer est trop importante, les algorithmes de descente ne sont pas toujours les plus efficaces. On a parfois besoin d’explorer une large zone de l’espace en un minimum d’itérations de façon à pouvoir éviter tous les minimums locaux. On essayera donc en premier lieu de coder un algorithme d’exploration pour trouver un bon point de départ pour ensuite lancer un algorithme de descente qui convergera rapidement vers la solution exacte. La plupart des algorithmes d’exploration repose sur un tirage de points de l’espace aléatoire, on parle d’algorithmes stochastiques. On tire littéralement des points de l’espace sans aucune corrélation entre eux, et on décide de ne garder que le meilleur. Un algorithme stochastique d’exploration s’écrit sous la forme générale suivante : function xbest=exploration(M) % M est un entier. C’est le nombre de points qu’on va explorer. cpt = 1; xbest=random(); while (cpt < M) cpt = cpt+1; x = random(); if Q(x) < Q(xbest) xbest = x; end end 8 La fonction random va bien sûr dépendre du problème et elle doit s’adapter à la dimension. Elle peut utiliser la commande MATLAB rand() qui renvoie un nombre aléatoire, ou encore la fonction rand(Ncom,1) qui renvoie un vecteur colonne de taille Ncom (rand(1,Ncom) renvoie un vecteur ligne). Lorsque les points admissibles ne sont pas dans un espace borné (comme R+ ), il faudra d’abord se restreindre à un sous-espace borné (comme [0, 2] par exemple). Question 13 : Coder un algorithme d’exploration stochastique de l’intervalle [0, 2] sur la fonction Q: R+ x → R 7→ x + 2 . x Question 14 : Combien d’itérations sont nécessaires pour approcher x∗ à 10−3 près ? à 10−6 près ? Question 15 : Coder un algorithme qui mélange exploration stochastique et algorithme de descente afin d’optimiser les fonctions quality geo et quality ellipse. Question 16 : Chercher les trajectoires optimales pour Ncom = 3, 6 ou 12. 2.3 Algorithme génétique Si vous arrivez à ce point de la feuille durant votre séance en autonomie, je vous conseille d’aller explorer Internet, on peut y trouver de nombreuses versions d’algorithmes génétiques. Ils reposent essentiellement sur un mélange savant entre algorithmes d’explorations stochastiques et algorithmes de descente en utilisant une nombre important de points, on parle d’une population de points. De tels algorithmes sont particulièrment intéressants lorsque l’espace à explorer est de taille très importante. Ils seront par exemple efficaces lorsque Ncom vaut 12 ou même 100. IIs seront l’objet de la dernière séance de TP. 3 Annexe function trace_courbes(Traj) % Trace la trajectoire des satellites % et d’autres courbes astronomiques. N = length(Traj); aGTO = 24535.135*10^3; % demi grand axe eGTO = 0.7185206032; % excentricite RTerre = 6378.137*10^3; % rayon de la Terre MTerre = 5.9736*10^24; % masse de la Terre mu = 6.67384*10^(-11)*MTerre; % G*MTerre % Calcul des parametres de la trajectoire. r=Traj(1:2,:); v=Traj(3:4,:); rfin = r(:,N);rXfin = rfin(1);rYfin = rfin(2); vfin = v(:,N);vXfin = vfin(1);vYfin = vfin(2); normv2 = vXfin*vXfin+vYfin*vYfin; normr2 = rXfin*rXfin+rYfin*rYfin; normr = sqrt(normr2); p = (rXfin*vYfin-rYfin*vXfin)^2/mu; k = normv2/2-mu/normr; a = 1/( 2/normr - normv2/mu ); e = sqrt( 1 + 2*p*k/mu); 9 cGTO = aGTO*eGTO; distancelargage = sqrt(rXfin^2+rYfin^2); XGTO = cGTO+aGTO*cos(linspace(-pi,pi,100)); YGTO = aGTO*sqrt(1-eGTO^2)*sin(linspace(-pi,pi,100)); if (a>0) && (e<1) % Ellipse c = a*e; p = a*(1-e*e); X = c+a*cos(linspace(-pi,pi,100)); Y = a*sqrt(1-e^2)*sin(linspace(-pi,pi,100)); % Calcul de l’angle theta0. delta = sqrt((e*distancelargage)^2 - (p-distancelargage)^2)/p; thetalargage = atan((-vXfin+rXfin*delta)/(vYfin-rYfin*delta)); theta0 = -pi/2+thetalargage - acos((p/distancelargage-1)/e); else disp(’La trajectoire n’’est pas une ellipse’) theta0=0; X = 0; Y = 0; end figure(1) clf hold on % Dessin de la Terre. plot([linspace(-1,1,100),fliplr(linspace(-1,1,100))]*RTerre,... [sqrt(1-linspace(-1,1,100).^2)*RTerre,... -sqrt(1-linspace(-1,1,100).^2)*RTerre],’b’) % Dessin de la trajectoire numrique plot(r(1,:),r(2,:),’k’) plot(r(1,ceil(125/(1500/N))),r(2,ceil(125/(1500/N))),’ks’) plot(r(1,ceil(500/(1500/N))),r(2,ceil(500/(1500/N))),’ko’) plot(rXfin,rYfin,’k*’) % Dessin de l’ellipse obtenue numriquement plot(cos(theta0)*X-sin(theta0)*Y,... sin(theta0)*X+cos(theta0)*Y,’r’) plot((c+a)*cos(linspace(-pi,pi,100)),... (c+a)*sin(linspace(-pi,pi,100)),’m’) % Dessin de la trajectoire optimale des satellites. plot(cos(theta0)*XGTO-sin(theta0)*YGTO,... sin(theta0)*XGTO+cos(theta0)*YGTO,’g’) plot((cGTO+aGTO)*cos(linspace(-pi,pi,100)),... (cGTO+aGTO)*sin(linspace(-pi,pi,100)),’c’) axis equal legend(’Terre’,’Trajectoire numerique’,... ’Largage Booster’,’Largage Etage 1’,... ’Largage Etage 2 et Satellites’,’Ellipse numerique’,... ’Orbite GEO numerique’,... ’Ellipse optimale’,’Orbite GEO optimale’,... ’Location’,’Best’) 10