← Retour à l'app← Back to app
Making-of · Article technique & vulgarisation
Making-of · Technical & plain-language article

Comment on a ouvert une fenêtre en temps réel sur Mars

How we opened a real-time window onto Mars

Positions réelles des rovers, panoramas 360°, survols 3D du cratère Jezero, à partir de données publiques de la NASA, dans un navigateur.

Real rover positions, 360° panoramas, 3D flyovers of Jezero crater, from public NASA data, in a browser.

Baptiste Lemoigne · lemoigne.fr, projet ouvert & éducatifopen & educational project
Autoportrait de Perseverance à « Cheyava Falls » (PIA26344) · NASA/JPL-Caltech/MSSSPerseverance self-portrait at "Cheyava Falls" (PIA26344) · NASA/JPL-Caltech/MSSS

01L'idée en une phraseThe idea in one sentence

Avec Window to Mars, j'ai voulu ouvrir une fenêtre en temps réel sur la planète Mars : on y suit la position réelle des rovers (Perseverance, Curiosity) et de l'hélicoptère Ingenuity, on explore leurs panoramas 360°, et on survole le cratère Jezero en 3D, le tout à partir de données publiques de la NASA que j'ai assemblées dans un navigateur.

Mon principe directeur : ne rien inventer. Chaque position, chaque image, chaque relief vient d'une donnée scientifique réelle. Quand j'ai besoin d'une reconstruction (ciel, relief), je l'écris clairement dans les crédits.

With Window to Mars, I wanted to open a real-time window onto the planet Mars: you follow the actual positions of the rovers (Perseverance, Curiosity) and of the Ingenuity helicopter, explore their 360° panoramas, and fly over Jezero crater in 3D, all from public NASA data that I assembled inside a browser.

My guiding rule: invent nothing. Every position, image and landform comes from real scientific data. Whenever I need a reconstruction (sky, relief), I state it clearly in the credits.

02La pile techniqueThe tech stack

J'ai tout fait tourner dans le navigateur, sans serveur applicatif. Je télécharge une seule fois les données lourdes (panoramas de centaines de Mo) via des scripts Python, je les redimensionne, puis je les sers en statique. Le reste (fond de carte, imagerie des survols 3D), je le charge en direct depuis les serveurs de la NASA.

I run everything in the browser, with no application server. I download the heavy assets (panoramas of hundreds of MB) once via Python scripts, resize them, then serve them statically. The rest (base map, 3D-flyover imagery) I load live from NASA servers.

BriqueComponent OutilTool RôleRole
Carte 2D2D mapLeaflet 1.9Tuiles de Mars, projection, zoom, marqueursMars tiles, projection, zoom, markers
Viewer 360°360° viewerPannellum 2.5Panoramas équirectangulairesEquirectangular panoramas
3D temps réelReal-time 3DThree.js r128Globe d'intro + survols aériensIntro globe + aerial flyovers
Traitement imageImage processingCanvas APICiel, colorisation, assemblage de tuilesSky, colorization, tile stitching
TéléchargementsDownloadsPython + PillowPanoramas haute résolutionHigh-resolution panoramas

03Représenter Mars à plat : le casse-tête des projectionsShowing Mars flat: the projection puzzle

Mars est une sphère ; un écran est plat. Pour afficher une planète, il faut projeter la sphère sur un plan, et il existe plusieurs façons, incompatibles entre elles :

EPSG:4326 (« plate carrée ») : longitude = axe X, latitude = axe Y. Simple, mais déforme près des pôles. Web-Mercator : la projection des cartes web classiques, qui « étire » les hautes latitudes.

Le piège : deux couches dans deux projections différentes ne se superposent pas. Une image calée en Web-Mercator posée sur une carte en 4326 sera décalée. C'est le cœur du casse-tête du projet.

Mon choix : EPSG:4326, car la meilleure mosaïque nette de Mars (le CTX, ~5 m/px) est servie ainsi. La couche couleur HiRISE (25 cm/px), elle, est en Web-Mercator : je la recompose sur un canvas puis je la place aux bonnes coordonnées. Je comble les trous du CTX avec la mosaïque Viking (232 m/px).

Mars is a sphere; a screen is flat. To display a planet you must project the sphere onto a plane, and there are several, mutually incompatible ways:

EPSG:4326 ("plate carrée"): longitude = X axis, latitude = Y axis. Simple, but distorts near the poles. Web-Mercator: the projection of classic web maps, which "stretches" high latitudes.

The catch: two layers in two different projections don't line up. An image aligned in Web-Mercator laid over a 4326 map will be offset. This is the heart of the project's puzzle.

My choice: EPSG:4326, because the sharpest Mars mosaic (CTX, ~5 m/px) is served that way. The HiRISE color layer (25 cm/px) is in Web-Mercator: I recompose it on a canvas then place it at the right coordinates. I fill CTX gaps with the Viking mosaic (232 m/px).

04Les cartes essayées puis abandonnéesMaps we tried and dropped

J'ai exploré beaucoup de sources. Voici l'historique honnête de mes essais, impasses comprises, souvent le plus instructif.

I explored many sources. Here's the honest history of what I tried, dead ends included, often the most instructive part.

SourceSource VerdictVerdict RaisonReason
Mosaïque CTXCTX mosaic ~5 m/pxNette, fiable, servie en 4326, CORS ouvertSharp, reliable, served in 4326, CORS-open
HiRISE couleurHiRISE color 25 cm/pxRésolution exceptionnelle (corridor + texture 3D)Outstanding resolution (corridor + 3D texture)
Viking MDIM21Comble les trous du CTX (couleur globale)Fills CTX gaps (global color)
MNT MOLA globalGlobal MOLA DEMTrop grossier : Jezero ≈ 3 pixels de largeToo coarse: Jezero ≈ 3 pixels wide
Trek subset / WMTS DEMEndpoints en 404, pas de CORS en direct404 endpoints, no live CORS
MNT HiRISE de JezeroJezero HiRISE DEMFichier source unique de ~10 GoSingle ~10 GB source file
Panoramas FU BerlinFU Berlin panoramasFormat tuiles non récupérable + reconstructions protégées (droits)Tile format not retrievable + copyrighted reconstructions
La leçon clé : le relief fin de Jezero (un vrai MNT HiRISE) n'est pas récupérable proprement en ligne. J'ai donc reconstruit un relief plausible à partir de l'ombrage de l'imagerie, que je crédite honnêtement comme reconstruction, pas comme altimétrie mesurée.Key lesson: the fine relief of Jezero (a real HiRISE DEM) isn't cleanly retrievable online. So I reconstructed a plausible relief from the imagery's own shading, which I honestly credit as a reconstruction, not measured elevation.

05Tracer les déplacements des trois explorateursTracing the three explorers

Trois engins, trois jeux de coordonnées réelles : Perseverance (64 étapes, sols 13→1921), Curiosity (61 étapes, sols 3→4957), Ingenuity (73 vols, 0→72).

Un tracé joli sans le fausser

Relier des points par des segments droits donne un tracé anguleux. J'utilise donc une spline de Catmull-Rom centripète : une courbe qui passe exactement par tous les points réels, mais avec des transitions douces, et qui, en version « centripète », évite les boucles et dépassements dans les virages serrés (piège classique des Bézier naïves). Le tracé est joli mais fidèle : jamais je ne fais passer l'engin là où il n'est pas allé.

Three craft, three sets of real coordinates: Perseverance (64 waypoints, sols 13→1921), Curiosity (61 waypoints, sols 3→4957), Ingenuity (73 flights, 0→72).

A pretty trace without falsifying it

Joining points with straight segments looks jagged. So I use a centripetal Catmull-Rom spline: a curve passing exactly through every real point, but with smooth transitions, and, in its "centripetal" form, avoiding loops and overshoot on sharp turns (a classic trap of naive Béziers). The trace is pretty but faithful: I never route the craft through a place it didn't visit.

06Les panoramas 360°The 360° panoramas

Perseverance, Mastcam-Z (52 panoramas) : les panoramas 360° officiels, sols 3 à 1775, de vraies photos NASA affichées telles quelles.

Curiosity, Mastcam (25 panoramas) : j'en ai recensé sur toute la mission, du sol 2 (atterrissage) au sol 4741, avec Rocknest (« milliard de pixels »), dune de Namib, Murray Buttes, Vera Rubin Ridge, Glen Torridon (« 1,8 milliard de pixels »)… J'identifie chacun par son numéro PIA, je le géolocalise par interpolation sur le tracé réel, et je le récupère en haute résolution (originaux > 29 000 px) via un script multi-sources.

Perseverance, Mastcam-Z (52 panoramas): the official 360° panoramas, sols 3 to 1775, real NASA photos shown as-is.

Curiosity, Mastcam (25 panoramas): I compiled these across the whole mission, from sol 2 (landing) to sol 4741, with Rocknest (the "billion-pixel"), Namib Dune, Murray Buttes, Vera Rubin Ridge, Glen Torridon (the "1.8-billion-pixel")… I identify each by its PIA number, geolocate it by interpolation on the real track, and fetch it in high resolution (originals > 29,000 px) via a multi-source script.

Panorama 360° de Curiosity
Exemple de panorama Mastcam de Curiosity. Crédit : NASA/JPL-Caltech/MSSS.
Example Curiosity Mastcam panorama. Credit: NASA/JPL-Caltech/MSSS.

07Ingenuity : vraies photos + survols 3D « maison »Ingenuity: real photos + home-made 3D flyovers

Ingenuity est un hélicoptère : il n'a jamais pris de panoramas 360° au sol. J'ai donc combiné, dans sa section, 5 vraies photos aériennes couleur (caméra RTE, géolocalisées par vol) et 8 survols aériens 360° que j'ai reconstruits en 3D.

Comment je fabrique un survol

1. Texture = imagerie réelle. À l'ouverture, je vais chercher en direct les tuiles HiRISE couleur (25 cm/px) autour du point de vol et je les assemble (~2,3 km de terrain).
2. Relief = reconstruit depuis l'ombrage. Le vrai MNT n'étant pas accessible, je dérive un relief basse fréquence de la luminance (l'ombrage encode les pentes), que je lisse pour éviter tout faux pic.
3. Rendu = Three.js. Terrain drapé, lumière rasante (bump map), ciel martien, brume d'horizon ; caméra à l'altitude du vol, regard 360°.

Mon cheminement : j'ai d'abord utilisé la mosaïque CTX (~5 m/px), trop pixelisée. Puis je suis passé à la HiRISE (25 cm/px), ~20× plus de détail, au prix d'une zone plus resserrée. Résultat : rides éoliennes, strates du delta et champs de blocs deviennent nets.

Ingenuity is a helicopter: it never took ground-level 360° panoramas. So in its section I combined 5 real color aerial photos (RTE camera, geolocated by flight) and 8 aerial 360° flyovers that I reconstructed in 3D.

How I build a flyover

1. Texture = real imagery. On opening, I fetch live the HiRISE color tiles (25 cm/px) around the flight point and stitch them (~2.3 km of terrain).
2. Relief = reconstructed from shading. Since the real DEM isn't reachable, I derive a low-frequency relief from luminance (shading encodes slopes), which I smooth to avoid false peaks.
3. Rendering = Three.js. Draped terrain, raking light (bump map), Martian sky, horizon haze; camera at flight altitude, 360° look-around.

My path of choices: I first used the CTX mosaic (~5 m/px), too pixelated. Then I switched to HiRISE (25 cm/px), ~20× more detail, at the cost of a tighter footprint. The result: aeolian ripples, delta strata and boulder fields become crisp.

08Reconstruire un ciel martienRebuilding a Martian sky

Les panoramas de la NASA arrivent souvent avec un cache noir en haut (la caméra ne photographie pas le zénith). J'ai écrit une fonction qui détecte ce cache, échantillonne la vraie couleur du ciel au-dessus de l'horizon, la remplace par un dégradé beige/rosé cohérent, et bouche colonne par colonne les trous résiduels. Enfin, je fais démarrer la vue centrée sur le sol/l'horizon pour mettre en avant le paysage réel.

NASA panoramas often arrive with a black matte at the top (the camera doesn't shoot the zenith). I wrote a function that detects it, samples the true sky color above the horizon, replaces it with a coherent beige/pink gradient, and fills residual holes column by column. Finally, I open the view centered on the ground/horizon to foreground the real landscape.

09Crédits & sourcesCredits & sources

Toute l'imagerie provient de missions publiques. La NASA est créditée comme source ; ces crédits n'impliquent aucun endossement du projet par la NASA ou ses partenaires.

All imagery comes from public missions. NASA is credited as the source; these credits imply no endorsement of the project by NASA or its partners.

CTX, NASA/JPL/MSSS/The Murray Lab (Caltech) · HiRISE, NASA/JPL/Univ. Arizona · Viking MDIM21, NASA/USGS · MOLA, NASA/GSFC · Mastcam-Z, NASA/JPL-Caltech/ASU/MSSS · Mastcam & Navcam, NASA/JPL-Caltech/MSSS · Ingenuity RTE, NASA/JPL-Caltech

10Licence, éthique & démarche éducativeLicense, ethics & educational mission

Window to Mars est un projet ouvert, à visée éducative : je veux rendre l'exploration de Mars accessible à partir de données scientifiques réelles. Trois principes ont guidé chacune de mes décisions :

1. Fidélité aux données. Je n'invente ni position, ni image, ni relief.
2. Transparence des reconstructions. Je crédite explicitement le ciel et le relief 3D comme des reconstructions.
3. Respect du travail d'autrui. J'ai renoncé aux panoramas de FU Berlin plutôt que de ré-héberger le travail 3D d'une autre équipe.

Le sol martien, un choix personnel. Scientifiquement, chaque mission compte ses « sols » (jours martiens) à partir de son atterrissage : le jour de l'arrivée sur Mars est le sol 0, et chaque mission a donc son propre sol 0. Il n'existe pas de « sol universel ». Pour Window to Mars, j'ai fait un choix arbitraire et personnel : en tant que créateur, j'ai ancré l'horloge martienne de l'application sur ma propre date de naissance, le 26 mai 1982. Le sol affiché est donc le nombre de jours martiens écoulés depuis ma naissance, une signature discrète.
Conception assistée par IA. J'ai conçu et développé ce projet avec l'aide de Claude (Anthropic), modèle Claude Opus 4.8, qui a contribué à l'exploration des sources de données. La direction artistique, la stratégie de développement, une partie du code et la mise au point des reconstructions sont de moi. Les décisions finales et la responsabilité du projet restent les miennes.

Window to Mars is an open, educational project: I want to make the exploration of Mars accessible from real scientific data. Three principles guided every one of my decisions:

1. Faithfulness to the data. I invent no position, image or landform.
2. Transparency about reconstructions. I explicitly credit the sky and 3D relief as reconstructions.
3. Respect for others' work. I gave up FU Berlin's panoramas rather than re-host another team's 3D work.

The Martian sol, a personal choice. Scientifically, each mission counts its "sols" (Martian days) from its landing: the day of arrival on Mars is sol 0, so every mission has its own sol 0. There is no "universal sol". For Window to Mars, I made an arbitrary, personal choice: as the creator, I anchored the app's Martian clock to my own birth date, 26 May 1982. The sol shown is therefore the number of Martian days elapsed since I was born, a quiet signature.
AI-assisted design. I designed and built this project with the help of Claude (Anthropic), model Claude Opus 4.8, which contributed to exploring the data sources. The art direction, development strategy, part of the code and refining the reconstructions are my own. The final decisions and responsibility for the project remain mine.
« Une fenêtre ouverte sur une autre planète. »
"A window open onto another planet."
Baptiste Lemoigne · lemoigne.fr · Window to Mars