Un radar créé par des parents pour leur tout-petit qui adore les avions
(jacobbartlett.substack.com)- Après que sa fille de deux ans s’est prise de passion pour les avions, l’auteur a créé en quelques soirées Aviator, une app iOS qui affiche les avions alentour comme un radar sur téléphone
- FlightRadar24 montre la position des avions sur une carte, mais il fallait encore déterminer dans quelle direction regarder dans le ciel réel et quels avions seraient faciles à repérer pour un enfant
- L’app combine les informations de direction de Core Location, l’API REST non commerciale d’OpenSky Network, les annotations MapKit et une interface SwiftUI pour afficher les avions en fonction de l’orientation de l’appareil
- Après avoir vérifié, lors des tests du MVP, que les vrais avions correspondaient à l’affichage dans l’app, l’auteur a ajouté le masquage de la carte, l’agrandissement des avions à basse altitude, une animation de radar, un effet CRT, du son, de l’haptique et des réglages de couleur
- L’app finale a été publiée sur l’App Store ; parmi les améliorations envisagées figurent les niveaux de zoom, l’API avancée d’OpenSky, l’affichage des pays de départ et d’arrivée, l’amélioration des shaders Metal, des filtres de distance et d’altitude, ainsi qu’un « zany mode »
De l’observation des avions aux exigences de l’app
- La fille de l’auteur attendait avec impatience un vol de trois heures lors d’un voyage à l’étranger pendant l’été et, après l’embarquement, a pu visiter le cockpit grâce à l’équipage, ce qui l’a rendue encore plus passionnée par les avions
- Par la suite, elle demandait souvent qu’on lui trouve des avions dans le ciel, au point qu’il s’est retrouvé à la porter sur ses épaules pendant une heure dans le jardin pour chercher des avions dans le ciel du soir
- FlightRadar24 montrait la position des avions sur une carte, mais l’utilisateur devait lui-même faire la correspondance avec la direction à regarder dans le ciel réel
- Sur une carte en deux dimensions, un Learjet à 40 000 pieds et un Airbus venant tout juste de décoller de London City Airport peuvent paraître similaires, alors que dans le ciel réel, un gros avion à basse altitude est plus facile à repérer
- Ce dont une enfant de deux ans avait besoin n’était pas d’interpréter une carte, mais simplement de trouver des avions
- Le problème initial se résumait à trois points
- Alignement de la direction : la position des avions devait correspondre à la direction réelle dans le ciel en fonction de l’orientation de l’appareil
- Représentation de la taille : la taille affichée à l’écran devait varier selon l’altitude de l’avion
- Utilisabilité : l’app ne devait pas être un outil professionnel de suivi des vols, mais ressembler à un jouet rétro
Conception initiale d’Aviator
- L’idée de l’app était d’« afficher les vols alentour sur un radar », et le projet a été baptisé Aviator
- Les exigences principales étaient au nombre de trois
- Quand l’appareil tourne, l’écran tourne avec lui afin que les avions apparaissent dans la bonne direction
- La taille à l’écran varie selon l’altitude de l’avion
- L’app donne une impression de jouet rétro amusant, adapté à un enfant
- La gestion de l’orientation utilise les mises à jour de heading de l’API iOS Core Location
- La direction de l’appareil est récupérée dans
didUpdateHeadingdeCLLocationManagerDelegate - La valeur de direction est transmise aux vues SwiftUI via
CurrentValueSubjectde Combine
- La direction de l’appareil est récupérée dans
- Les données aériennes proviennent d’OpenSky Network
- Une API REST simple fournit des données aériennes en temps réel dans une zone de latitude et de longitude donnée
- L’usage non commercial est gratuit
- L’idée était d’appeler l’endpoint toutes les quelques secondes pour obtenir un balayage radar réaliste
- Les données de localisation sont obtenues via Core Location, puis une zone de latitude et longitude autour de la position de l’utilisateur est interrogée
- Dans l’idée initiale, l’auteur voulait utiliser latitude ±1 degré et une précision de position de 0,1 degré, soit environ 10 km, afin de suffisamment brouiller la position de l’utilisateur
- Dans l’exemple de code réel de l’API, il utilise une zone de 0,5 degré de latitude et 1 degré de longitude afin d’obtenir un carré approximatif aux latitudes du Royaume-Uni
- Comme l’API OpenSky Network est limitée à un usage non commercial et que l’app n’est pas non plus un service commercial, l’auteur utilise dans SwiftUI une simple structure MV, en isolant seulement les services clés comme l’API et la localisation
PoC : validation de l’orientation, des données aériennes et de la carte
- Le PoC de direction utilise un singleton
LocationManagerpour gérer la demande d’autorisation de localisation, la configuration du delegate et le démarrage des mises à jour de heading - La vue SwiftUI s’abonne à
rotationAngleSubjectvia.onReceiveet implémente un effet de rotation façon boussole en plaçant des rectangles en cercle - Sur l’appareil de test, l’app réagissait bien aux changements de position réels, mais comme l’animation traitait 0 degré et 360 degrés comme des valeurs distinctes, un glitch visuel faisait faire un tour complet aux rectangles lors du passage par le nord vrai
- L’API REST OpenSky renvoie un tableau de vols régionaux au moyen d’une requête
GETavec une zone de latitude et longitude- L’endpoint d’exemple consiste à ajouter les paramètres
lamin,lamax,lomin,lomaxàstates/all - La documentation de l’API REST est bien faite, mais la réponse n’ayant pas de clés, il fallait parser les champs JSON dans l’ordre
- Les champs
icao24,callsign,origin_country,time_position,last_contact,longitude,latitude, etc. sont décodés avecUnkeyedContainerde Swift
- L’endpoint d’exemple consiste à ajouter les paramètres
- La première tentative de rendu des avions consistait à placer une image SF Symbol
airplaneen multipliant la différence de latitude et de longitude entre la position de l’utilisateur et celle de l’avion par une échelle d’écran fixe- La distance réelle représentée par 1 degré de latitude ou de longitude varie selon l’emplacement, ce qui ne pouvait pas être précis
- Cela restait toutefois utile comme point de départ
- Pour vérifier la précision, une
MapSwiftUI a été placée en arrière-plan, avec les avions et la boussole superposés- Comparés à la projection de FlightRadar, le nombre d’avions et les clusters correspondaient à peu près, mais les positions étaient assez décalées
- L’auteur est ensuite passé à un rendu direct des avions sous forme d’annotations sur la carte
MVP : annotations MapKit et test utilisateur
- En ciblant iOS 17, l’auteur a utilisé la fonctionnalité d’annotations cartographiques de MapKit pour afficher des marqueurs en forme d’avion à leurs coordonnées géographiques réelles
FlightMapViewdessine les annotations d’avions au-dessus deMap(position:)et désactive les interactions avec la carte via.allowsHitTesting(false)pour l’usage radar- Le redimensionnement basé sur l’altitude appliquait d’abord une échelle logarithmique qui faisait apparaître les avions les plus hauts plus grands
- Le
true_trackde l’avion et l’orientation de l’utilisateur fournie par Core Location sont combinés pour orienter correctement l’icône de l’avion
- Le
- Lors du premier test utilisateur du MVP, l’auteur et sa fille ont effectivement trouvé un avion, et confirmé que l’avion affiché dans l’app était visible dans le ciel réel
- Après le test, deux corrections sont apparues nécessaires
- Le redimensionnement était inversé : pour mettre en avant les avions faciles à repérer à l’œil nu dans le ciel, les avions à basse altitude devaient être plus grands
- Sa fille voulait seulement voir les avions, pas la carte ; il fallait donc supprimer la carte afin de réduire le bruit visuel
- La formule d’échelle corrigée est
min(2, max(4.7 - log10(flight.geo_altitude + 1), 0.7))- Lors de scans du ciel local, elle donnait des valeurs de 0,7 à 2,0, avec une bonne répartition à l’écran
Création de l’interface radar
- L’API OpenSky renvoie parfois des timeouts, des
502 Bad Gatewayou des réponses 200 contenant des données null- Comme il s’agit d’une API gratuite non commerciale sans SLA, l’auteur a ajouté une logique de retry de base côté client
- Le lendemain, elle a bien fonctionné toute la journée et semblait globalement correcte en dehors de certains créneaux à fort trafic
- Pour masquer la carte réelle, l’auteur a utilisé un overlay
MapPolygon- Il s’agit à l’origine d’un overlay destiné à mettre en évidence une zone de carte, mais il a été détourné pour couvrir la carte tout en conservant les annotations d’avions
- Les overlays d’Apple étant dessinés au-dessus de la carte et sous les annotations, le résultat souhaité était obtenu
- L’écran radar est implémenté avec des lignes, des cercles concentriques et un gradient angulaire rotatif de 20 degrés de largeur
- L’effet de ligne radar a ensuite été simplifié avec un gradient angulaire à 360 degrés
- Un gradient allant du vert au transparent puis au noir est mis en rotation pour donner l’impression d’un balayage et d’une rémanence
- L’auteur estime qu’une approche « grug-brained » fonctionne souvent mieux
- Lorsque l’appareil était tourné rapidement, des morceaux de carte apparaissaient dans les coins de l’écran ; ce artefact visuel a été résolu avec un reverse mask qui couvre en noir l’extérieur de la vue radar
Mise en produit : effet CRT, son, réglages, App Store
- Pour renforcer l’impression de jouet rétro, l’auteur a ajouté un effet d’écran CRT
- Il utilise la prise en charge intégrée des shaders Metal dans
colorEffectd’iOS 17 - Le shader applique une valeur de scanline aux pixels non noirs
- Un paramètre
timepermet de faire remonter rapidement les scanlines pour donner un aspect dynamique
- Il utilise la prise en charge intégrée des shaders Metal dans
- Afin de vérifier que la publication sur l’App Store était acceptable au regard des règles d’OpenSky Network, l’auteur les a contactés et a reçu une réponse en moins de 20 minutes
- Pour l’expérience radar et l’accessibilité, des sons système et du retour haptique ont été ajoutés lors des mises à jour des vols
AudioServicesPlaySystemSound(1052)produit un son beep-boopsensoryFeedback(.levelChange, trigger:)de SwiftUI est utilisé
- Comme le son pouvait devenir agaçant, l’auteur a ajouté des réglages basés sur
@AppStoragesilent: mode silencieuxshowMap: permet de désactiver l’overlay radar et de voir la carte en dessoususerColor: sélection de la couleur du radar via le sélecteur de couleur SwiftUI
- Ayant arrêté son abonnement Midjourney, l’auteur a utilisé le générateur gratuit non commercial de Gencraft pour créer une mascotte Aviator inspirée de sa fille portant un casque d’aviateur
- En se réinscrivant à l’Apple Developer Program, il a payé 79 £ et préparé la distribution sur l’App Store
- Même si l’app cible uniquement iOS 17, il fallait fournir des captures d’écran iPhone 6,5 pouces et 5,5 pouces
- Le dernier iPhone 5,5 pouces, l’iPhone 8 Plus, étant limité à iOS 16, il a exporté les captures d’écran aux deux tailles avec AppScreens
- L’app est disponible sur l’App Store, et le lien de téléchargement est Aviator — Radar on your Phone
Candidats pour les prochaines versions
- L’auteur est satisfait du résultat de ce side project réalisé en quelques soirées, et coder un jouet pour sa fille a été l’une de ses expériences de programmation les plus agréables depuis longtemps
- Les fonctionnalités candidates pour une prochaine version sont les suivantes
- Ajouter un niveau de zoom de la carte pour limiter le radar aux avions les plus proches
- Afficher les hélicoptères, les satellites et la catégorie de taille des avions via l’API avancée d’OpenSky Network
- Ajouter un toggle pour afficher les pays de départ et d’arrivée sur les avions
- Améliorer l’effet d’écran CRT avec des shaders Metal plus avancés
- Refactorer les contrôles en une modale progressive-disclosure extractible et redimensionnable
- Implémenter des filtres avec sliders de distance et d’altitude pour masquer, par exemple, les avions bas et lointains
- Implémenter un zany mode qui affiche des ovnis, des insectes géants et des extraterrestres sur le radar
1 commentaires
Avis de Hacker News
Super travail, et l’article est très bon. C’est intéressant de voir à quel point la conception du dispositif d’affichage radar original imprègne fortement ce projet.
L’enfant n’aura peut-être jamais l’occasion de toucher un ASR-9 avec affichage PPI, encore moins un vrai CRT, mais beaucoup d’efforts ont été consacrés à le simuler.
C’est sans doute aussi parce qu’ils aiment le skeuomorphisme, mais il semble aussi que l’écran radar d’origine synthétise très bien la question : « y a-t-il quelque chose dans le ciel, et où se trouve-t-il par rapport à moi ? »
Les UI actuelles d’observation du ciel semblent s’orienter vers les informations contextuelles, les liens vers des services externes et les espaces publicitaires, au point de perdre leur capacité à répondre simplement à cette question.
La distance de la cible était représentée par sa distance au centre, et son azimut par l’angle sur le pourtour du cercle.
Cela dit, la partie qui imite le balayage était peut-être un choix de conception discutable, et les couleurs vives ainsi que l’arrière-plan sans carte semblent parfaitement convenir, car ils concentrent l’attention sur l’intention de l’écran.
On voyait aussi que le suivi à la boussole, quand on tourne avec le téléphone en main, brisait l’illusion du balayage.
https://github.com/sky-map-team/stardroid
Je comprends tous les éléments techniques liés et j’exploite même ma propre station ADSB, mais pointer la caméra vers le ciel et voir les métadonnées des avions dans le champ de vision reste impressionnant.
Excellent. Je l’ajoute à ma liste de choses à fabriquer un jour.
Dans le même esprit, j’ai créé un carnet de vol pour mon fils de 5 ans, en commençant quand il était bébé. À chaque vol, je lui fais demander au personnel de cabine si le commandant peut écrire dedans.
On y consigne la ligne, le type d’appareil et ce qui s’est passé, et les équipages adorent vraiment ce genre de chose. On a pu visiter le cockpit et les espaces de repos de l’équipage, et les messages écrits ont toujours été adorables.
Chaque fois qu’on le lui rend, il affiche un immense sourire ; je le recommande vivement aux jeunes passionnés d’avions.
J’aime le fait que la modification de la couleur d’affichage fasse partie des fonctionnalités indispensables de la première version. Ça montre une compréhension très solide des besoins du public cible.
Un enfant de 3 ans aime n’importe quel jouet doté d’un sélecteur de couleur.
Il suffit d’imaginer l’excitation irrationnelle qu’on ressent quand on dépasse 250 de karma sur HN.
Même aujourd’hui, si je le montre à un enfant, la première chose qui l’intéresse, c’est de choisir la couleur, et c’est aussi bon pour la motricité fine.
Le passage disant que « nous avions tellement survendu le voyage en avion que l’enfant a été surpris de devoir prendre un taxi jusqu’à l’aéroport. Il pensait pouvoir marcher directement de la maison jusqu’à l’avion » est vraiment adorable, drôle, et compréhensible.
https://www.architecturendesign.net/john-travoltas-house-is-...
Dans le passage où le personnel de cabine, voyant un petit passionné d’avions tout mignon, l’emmène visiter le cockpit, porter des combinaisons orange de la NASA assorties est un passeport pour tous les cockpits.
Les équipages sont encore plus excités que les enfants, et c’est aussi très pratique pour repérer les enfants à l’aéroport.
L’article An app can be a home cooked meal, qui raconte une réplique de l’application de réseau social ratée Tapstack réservée à la famille, est aussi pertinent.
https://www.robinsloan.com/notes/home-cooked-app/
Bien sûr, devenir viral ne fait pas de mal non plus.
J’ai deux petits regrets.
Quand les points des avions bougent après avoir été dessinés, ça casse un peu l’immersion. Ce serait plus réaliste si le point était « peint » par le balayage, puis restait fixe jusqu’au balayage suivant.
Pour encore plus de réalisme, on pourrait aussi extrapoler à partir des points de données précédents afin que chaque avion se déplace de manière cohérente à chaque balayage.
La seconde pourrait même être plus simple. Comme l’API renvoie la vitesse de vol, on peut la calculer avec un seul point de données.
Comme activité sympa à faire avec sa fille, c’est bien d’aller sur une route, un parking ou dans un parc situé à l’extrémité de la piste de l’aéroport international le plus proche, côté atterrissage.
En général, cela dépend de la direction du vent, donc il faut s’adapter, se garer et regarder les avions arriver pour atterrir.
L’enfant peut voir sur son radar quel avion arrive, et nous avons utilisé flightradar24.
Les enfants étaient complètement fascinés en voyant à quel point les gros jets en approche descendaient près du sol, et on peut facilement y passer des heures. Il a fallu négocier parce qu’ils ne voulaient pas partir, voulant voir si le prochain avion serait plus gros ou plus proche.
Parmi les avions multimoteurs à voilure fixe de taille inférieure ou égale à celle d’un Airbus A318, seuls ceux disposant d’une certification spéciale de l’appareil et de l’équipage pour effectuer une approche à 5,5° peuvent y opérer.
https://www.youtube.com/watch?v=yZIDFgpT0-o
https://en.wikipedia.org/wiki/London_City_Airport
Cette app a un problème : sa page indique clairement 4 ans et plus, alors que l’utilisateur cible a 2 ans.
Beau travail.
Excellent.
Petite question de détail : les scopes radar CRT avaient-ils vraiment une ligne de balayage ? J’aurais pensé qu’il s’agissait d’écrans vectoriels.
Concernant la liste des fonctionnalités supplémentaires, comme c’est une app d’observation d’avions, ce serait sympa que toucher un point affiche le type d’avion pendant quelques secondes.
Grâce à la persistance du phosphore, les forts échos radar restaient brièvement visibles à l’écran. Si, pendant ce temps, le radar faisait au moins un tour, le même avion apparaissait comme un nouveau point légèrement déplacé, autrement dit un « plot ».
On pouvait aussi marquer les plots à l’écran avec un feutre pour en faire une « track ».
Il existait aussi des écrans spéciaux où une caméra de cinéma était braquée sur l’écran radar pour enregistrer plusieurs heures d’échos radar et les rejouer ensuite.
Par exemple, il existe un enregistrement en lecture accélérée des avions du Pacte de Varsovie pendant la révolution tchécoslovaque de 1968 : https://youtu.be/rAUodXI4LPw?t=622
À l’origine, les écrans radar balayaient radialement depuis le centre vers l’extérieur. Le timing du balayage était prédéterminé pour mettre la distance à l’échelle, et le signal d’intensité du faisceau était tout simplement le signal d’écho radar amplifié.
Ainsi, les échos plus forts apparaissaient comme des « blips » plus visibles sur un écran à longue persistance.
Ce qui est intéressant, c’est que, pour faire balayer le faisceau radar autour de l’écran CRT, tout l’ensemble émetteur du tube cathodique était entraîné par un moteur synchronisé avec l’antenne radar rotative.
Cette rotation devait toujours correspondre à la vitesse et à la direction de l’antenne radar, sinon les blips apparaissaient au mauvais endroit.
Les lignes fixes de relèvement et de distance étaient imprimées sur le tube CRT lui-même ou sur un cache transparent. Ces écrans ont été utilisés pendant des décennies, peut-être même jusque dans les années 1980 ou au début des années 1990.
Les versions plus récentes pouvaient balayer indépendamment les directions X/Y avec une électronique simple, afin d’éviter le complexe ensemble rotatif d’émission du faisceau.
Plus de détails : https://en.wikipedia.org/wiki/Radar_display#Plan_position_in...
L’angle pouvait être produit soit en faisant tourner physiquement les plaques de déviation, soit en calculant électroniquement sin/cos et en les appliquant aux plaques de déviation X/Y.
L’amplitude du signal de retour pilotait directement le courant du faisceau, si bien que les cibles avec un écho plus important apparaissaient plus lumineuses.
Il y avait aussi un effet de tube à mémoire : il ne fonctionnait pas comme le mode bistable des écrans vectoriels X-Y à tube à mémoire des premiers ordinateurs, mais plutôt comme le mode de persistance variable de certains oscilloscopes.
Cette caractéristique a aussi eu des conséquences liées aux premières tentatives de conception d’avions furtifs comme le SR-71 ou le XB-70.
Le courant du faisceau des tubes radar était réglé de façon à ce que les « blips » s’accumulent sur plusieurs balayages, et en général un blip se déplaçait de moins que son propre diamètre entre deux balayages.
Mais si la surface équivalente radar de l’avion était intrinsèquement faible et que celui-ci était si rapide que le blip se déplaçait d’une plus grande distance entre deux balayages, l’opérateur radar pouvait interpréter ces petits blips fantômes comme du bruit, surtout dans une situation confuse avec de nombreuses cibles.