Rêves d'Espace

Un site sur l'actualité spatiale : les vols habités, les lancements, l'exploration de l'espace, les grandes missions actuelles et futures

Mars

Calculer la trajectoire d’Ingenuity grâce à ses photos

Aurélien Genin est étudiant en ingénierie et passionné de spatial. Il a dernièrement partagé sur son compte Twitter son calcul de la trajectoire de l’hélicoptère martien Ingenuity lors de ses 9 vols. Et j’ai trouvé cela tellement intéressant et ingénieux que je lui ai proposé de vous présenter son travail directement sur le blog.

L’hélicoptère Ingenuity de la NASA décolle et atterrit dans cette vidéo capturée le 19 avril 2021 par Mastcam-Z, un imageur à bord du rover Perseverance. Cette vidéo ne présente que les moments du décollage et de l’atterrissage et non des images de l’hélicoptère en vol stationnaire pendant environ 30 secondes (crédit NASA/JPL-Caltech/ASU/MSSS)

Beaucoup de missions spatiales, en particulier gouvernementales, ont fait le choix de publier gratuitement un maximum de données. C’est le cas du programme européen Copernicus mais aussi des missions martiennes de la NASA. En particulier, les images prises par les différents atterrisseurs et rovers posés sur la planète rouge sont accessibles à tout un chacun. Et ce libre accès a un énorme avantage : tout le monde peut s’amuser avec ces photos et ces données ! Vous avez peut-être déjà vu le superbe travail de Thomas Appéré qui retouche les photos de ces missions et en fait généralement de magnifiques panoramas.

Un peu dans le même esprit, mais avec une idée peut-être plus technique qu’esthétique, j’ai eu envie d’utiliser les images prises par Ingenuity, le petit hélicoptère amené par Perseverance sur Mars, pour essayer de retracer son parcours lors de ses vols. L’objectif était de pouvoir juxtaposer la vidéo vue depuis l’hélicoptère et sa position en direct sur l’image prise en orbite par l’instrument HiRISE de MRO (Mars Reconnaissance Orbiter).

Une image contenant extérieur

Description générée automatiquement
Photo orbitale composite du terrain survolé lors du vol 9 d’Ingenuity à partir d’images de MRO et de Mars Express (NASA/JPL/UArizona/ESA)
Photo prise par la NavCam d’Ingenuity lors de son vol 9 le 05/07/2021 (NASA/JPL-Caltech)

Pour ce faire, j’ai procédé en plusieurs étapes. Tout d’abord, comment peut-on déduire la trajectoire à partir de ces photos ? L’idéal aurait été de coller chaque photo prise par Ingenuity sur l’image orbitale puis de simplement les relier. A la main, ça se fait dans une certaine mesure (ce que j’ai essayé plus pour m’amuser au début), mais avec une centaine de photos par vol, l’automatisation et la programmation deviennent des étapes obligatoires. Et pour automatiser cette détection, quand les deux images sont si différentes (pas les mêmes couleurs, pas la même distance, pas la même résolution…), c’est quasiment mission impossible. L’autre option, que j’ai finalement choisie, est d’utiliser la reconnaissance d’images pour traquer le déplacement d’Ingenuity par rapport au sol martien à partir des photos prises par sa caméra de navigation (NavCam). 

Tentative de recollement à la main des images d’Ingenuity sur l’image HiRIse de MRO pour le vol 9

Cette caméra est déjà utilisée par l’hélicoptère lui-même pendant ses vols pour compléter les données de ses capteurs et ainsi connaître plus précisément sa position et son orientation. Elle prend plusieurs dizaines d’images par seconde, mais seule une fraction est renvoyée sur Terre (entre 1 et 3 par seconde suivant les vols). Et c’est à partir de cette fraction que je vais reconstruire la trajectoire d’Ingenuity ! J’ai parlé de reconnaissance d’images, mais concrètement, qu’est-ce que cela veut dire et à quoi cela va-t-il me servir ? Tout le défi ici est que je dispose d’une séquence d’images, et uniquement à partir de ces dernières, je dois trouver un moyen de calculer le déplacement de l’hélicoptère par rapport au sol. Pour ça, il va falloir que je trouve le déplacement du sol entre deux photos, mais aussi le déplacement de l’ombre (qui sera celui d’Ingenuity) pour compenser les effets de rotation de l’hélicoptère qui fausseraient la trajectoire finale. J’ai donc décidé d’utiliser la librairie OpenCV pour Python qui permet très facilement de travailler sur des images et d’y faire de la reconnaissance de motifs.

La première étape, qui m’a notamment permis de me familiariser avec cette nouvelle librairie, a été de chercher à repérer Ingenuity sur chaque image. Pour ce faire, c’est très simple ! On donne au programme un « motif » et il va chercher ce qui y ressemble le plus dans l’image. Ici, le motif est tout bêtement une photo de l’ombre d’Ingenuity. Pour être plus précis, gagner du temps de calcul et éviter les fausses détections, on peut rajouter ce qu’on appelle une ROI (Region Of Interest). Cette zone délimite l’endroit où le programme va chercher le motif défini. En regardant les photos prises par l’hélicoptère, on remarque en effet que l’ombre n’est jamais très éloignée du centre et on évite ainsi que le programme ne prenne un caillou pour Ingenuity. Avec ce premier programme, on peut donc obtenir très facilement et très fidèlement (on va revenir sur ce point un peu plus tard…) la position de l’ombre d’Ingenuity sur toutes les images !

« Où est Ingenuity ? » En bleu, là où mon programme a trouvé le petit hélicoptère et en vert, la ROI

Le problème suivant est un peu plus complexe : Trouver le déplacement du sol entre deux images. Mon idée est de refaire un petit peu pareil. On va chercher des cibles au sol sur une image et demander à ce même programme de les retrouver sur l’image suivante. En mesurant le déplacement de celles-ci on va pouvoir connaître le déplacement du sol. Oui mais voilà, cette solution cache en fait plusieurs problèmes. Le premier étant, comment sélectionne-t-on ces cibles ? Au hasard ? Trop souvent le programme va prendre une zone totalement grise et donc impossible à retrouver sur la photo d’après. Il faut donc être plus malin ! 

Il est assez logique de voir que ce qui fait une bonne cible est un changement brusque de luminosité : Il est bien plus simple de suivre un caillou sur plusieurs images que le milieu d’une étendue de régolithe. Pour traduire cette idée dans mon programme de génération de cibles, j’ai donc commencé par un traitement sur les images pour faire apparaître ces changements brusques (Laplacian sur l’image ci-dessous).

Traitement d’images en plusieurs étapes et recherches des différentes cibles.
Les images en bas seront celles utilisées pour la recherche sur l’image suivante.

J’en ai aussi profité pour légèrement les flouter pour éviter d’être parasité par le bruit et le grain de l’image et être sûr de bien sélectionner des objets visibles sur le sol. Enfin, le dernier souci est cette ombre d’Ingenuity ! Sur toutes les photos, ce serait une cible parfaite avec la méthode décrite ci-dessus (et c’est pourquoi mon programme précédent la retrouve si bien), mais ce n’est pas une cible intéressante ici. Il faut donc la masquer, ce que je fais aussi petit à petit pour les autres afin de générer autant de cibles que voulu.

Vive les cailloux ! En bleu, les cibles que mon programme juge intéressantes

Maintenant que nous avons des cibles au sol, il ne reste plus qu’à les retrouver sur l’image suivante. Et pour cela, on fait exactement comme pour trouver l’ombre d’Ingenuity ! On utilise les images de ces cibles comme motifs sur l’image suivante. Il faut juste bien faire attention à agrandir un peu la ROI car le sol a bougé entre temps (et heureusement, c’est ce qu’on cherchait à mesurer).

Recherche des cibles sur les deux images En haut, les cibles générées sur l’image 1 et en bas, les mêmes trouvées sur l’image 2

Une fois qu’on a obtenu cette correspondance, il ne reste plus qu’à moyenner ces différents déplacements et à le soustraire au déplacement de l’ombre. On obtient alors le vrai déplacement d’Ingenuity par rapport au sol entre ces deux images ! Du moins, ça se serait dans un monde parfait. Dans les faits, toutes les cibles ne sont pas toujours bien retrouvées. Il faut donc détecter et supprimer les vecteurs aberrants. J’ai choisi la solution la plus simple : Je ne garde que les 4 ou 5 vecteurs qui sont bien alignés entre eux. Cette méthode a des défauts (elle empêche de détecter les rotations d’Ingenuity par exemple), mais elle suffit amplement pour ce que je veux faire ici.

A fond vers la gauche ! En bleu, le déplacement d’Ingenuity entre deux images ; en vert, les vecteurs de déplacement du terrain conservés ; en rouge, une aberration

Si on récapitule un peu : mon programme arrive à trouver l’ombre d’Ingenuity, sélectionne des cibles intéressantes au sol, trace leur déplacement entre deux images et enfin en déduit le mouvement de l’hélicoptère !

Il ne reste plus qu’une chose à faire : Coller tous ces déplacements les uns à la suite des autres et on aura ainsi la trajectoire globale d’Ingenuity pendant un de ses vols. Et une fois que tout cela fonctionnait sur un vol, il était temps de vérifier si le programme s’adaptait bien à un autre. Mis à part des petits réglages sur les ROI (pour gérer des grosses rotations comme lors du vol 6) ou sur le nombre de cibles (pour gérer les dunes où il y a assez peu de cibles contrastées), tout marche très bien ! J’ai donc pu, à partir des photos prises par la NavCam d’Ingenuity, retracer cette carte montrant tous les vols du petit hélicoptère martien.

Every Ingenuity flights so far
Carte des différents vols d’Ingenuity retracés grâce aux photos prises en vol. En blanc, la trajectoire au sol du rover Perseverance

Enfin, puisque mon programme me donne une correspondance entre la position d’Ingenuity sur l’image HiRISE (à condition de lui fixer le point de départ et d’arrivée) et la photo prise par la NavCam, il est possible de réaliser mon objectif initial, c’est-à-dire obtenir une vidéo avec le suivi depuis l’orbite en même temps que celui à bord de l’hélicoptère !

Vidéo du vol 9 d’Ingenuity avec suivi en direct sur l’image HiRISE.
Les autres vols (5 à 8) sont disponibles en Gif sur Flickr (Gif après téléchargement).

Toute cette petite aventure m’a donc permis d’apprendre à utiliser cette puissante librairie de travail d’images qu’est OpenCV et de jouer un petit peu plus avec les données d’Ingenuity. Pour la suite, j’essaierai peut-être de prendre en compte les rotations et phases de décollage et atterrissage de l’hélicoptère afin de déduire sa position en 3D toujours uniquement à partir des photos de sa NavCam. Mais ça, c’est une autre histoire.

Le code public utilisé par Aurélien : https://github.com/AstroAure/Ingenuity-Trajectory

Pour savoir où est Ingenuity et Perseverance sur le sol martien : https://mars.nasa.gov/maps/location/?mission=M20&site=NOW

Récapitulatif des vols d’Ingenuity à ce jour

Vol n°SolDateDistance horizontaleDistance verticaleVitesse maxDurée
mètresmètresm/ssecondes
15819 avril03039.1
26122 avril450.551.9
36425 avril1005280.3
46930 avril26653.5116.9
5767 mai129102108.2
69122 mai215104139.9
71078 juin10610462.8
812021 juin16010477.4
91335 juillet625105166.4

Laisser un commentaire

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.