FlightGear — visualiseur 3D pour SITL¶
Quand la carte 2D de Cockpit ou QGC ne suffit plus — pour s'entraîner à reconnaître l'attitude visuelle, valider une mission de scouting au-dessus d'un terrain réel, ou faire des démos — on branche FlightGear comme renderer 3D synchronisé sur SITL.
⚠️ macOS 26 (Tahoe) : la cask Homebrew est MORTE. FlightGear 2024.1.5 (la dernière release stable, ce que
brew install --cask flightgearinstalle) bundle un vieux Qt qui hang dans-[NSApplication run]au tout premier pas d'init sur macOS 26.3+. Aucun reinstall / clean-home / flag ne corrige ça (diagnostic : sample montre le main thread bloqué dansflightgear::initApp → libqcocoa → NSApplication run, jamais de fenêtre,fgfs.logà 0 octet). Sur macOS 26, FG doit être buildé depuis les sources contre un Qt moderne — voir § Build depuis les sources.
Build depuis les sources (macOS 26)¶
Chaîne à 3 étages — tout s'installe dans un prefix local
~/Project/bascanada/fgfs-local. Build complet ≈ 10 min sur M-series
(ninja, Release, 8 cœurs). Repos clonés en sibling de my_fleet/.
| Dép | Source | Note |
|---|---|---|
| Qt 6.11 | brew install qtbase qtdeclarative qtsvg |
Qt moderne = compatible macOS 26 (c'est le fix) |
| OSG fork | gitlab.com/flightgear/openscenegraph branche next |
FG refuse l'OSG upstream (FATAL_ERROR). brew unlink open-scene-graph sinon ses headers gagnent dans l'include path |
| SimGear | gitlab.com/flightgear/simgear branche next |
doit matcher la version FG (2024.2) |
| FlightGear | gitlab.com/flightgear/flightgear branche next |
patché (voir § Patch FPS) |
| FGData | gitlab.com/flightgear/fgdata branche next (~4 GB) |
doit matcher le binaire — la FGData 2024.1.5 crash le renderer next (FGClouds::captureSnapshot SIGSEGV, shaders manquants) |
cd ~/Project/bascanada
# 1. OSG fork
git clone --depth 1 -b next https://gitlab.com/flightgear/openscenegraph.git osg-fork
brew unlink open-scene-graph # critique : sinon headers upstream gagnent
cmake -S osg-fork -B osg-fork/build -G Ninja -DCMAKE_BUILD_TYPE=Release \
-DCMAKE_INSTALL_PREFIX=$HOME/Project/bascanada/fgfs-local \
-DCMAKE_OSX_ARCHITECTURES=arm64 -DBUILD_OSG_APPLICATIONS=OFF \
-DBUILD_OSG_EXAMPLES=OFF -DOSG_USE_QT=OFF \
-DCMAKE_PREFIX_PATH="/opt/homebrew/opt/jpeg-turbo;/opt/homebrew/opt/libpng"
ninja -C osg-fork/build install # plugin osgdb_imageio = JPEG/PNG sur macOS
# 2. SimGear
git clone --depth 1 -b next https://gitlab.com/flightgear/simgear.git
cmake -S simgear -B simgear/build -G Ninja -DCMAKE_BUILD_TYPE=RelWithDebInfo \
-DCMAKE_INSTALL_PREFIX=$HOME/Project/bascanada/fgfs-local \
-DCMAKE_OSX_ARCHITECTURES=arm64 -DENABLE_TESTS=OFF \
-DCMAKE_PREFIX_PATH="$HOME/Project/bascanada/fgfs-local;/opt/homebrew/opt/qtbase;/opt/homebrew/opt/qtdeclarative;/opt/homebrew/opt/qtsvg;/opt/homebrew/opt/openal-soft;/opt/homebrew/opt/jpeg-turbo;/opt/homebrew/opt/libpng"
ninja -C simgear/build install
# 3. FlightGear (patché)
git clone --depth 1 -b next https://gitlab.com/flightgear/flightgear.git
# … appliquer le patch FPS (voir section dédiée) …
cmake -S flightgear -B flightgear/build -G Ninja -DCMAKE_BUILD_TYPE=RelWithDebInfo \
-DCMAKE_INSTALL_PREFIX=$HOME/Project/bascanada/fgfs-local \
-DCMAKE_OSX_ARCHITECTURES=arm64 -DENABLE_TESTS=OFF \
-DCMAKE_PREFIX_PATH="$HOME/Project/bascanada/fgfs-local;/opt/homebrew/opt/qtbase;/opt/homebrew/opt/openal-soft;/opt/homebrew/opt/jpeg-turbo;/opt/homebrew/opt/libpng" \
-DQT_ADDITIONAL_PACKAGES_PREFIX_PATH="/opt/homebrew/opt/qtdeclarative;/opt/homebrew/opt/qtsvg"
ninja -C flightgear/build # binaire : build/src/Main/FlightGear.app/Contents/MacOS/FlightGear
# 4. FGData matchée
git clone --depth 1 -b next https://gitlab.com/flightgear/fgdata.git fgdata-next
Le Makefile racine pointe déjà FG_BIN / FG_ROOT sur ce build + cette
FGData, et lance avec un FG_HOME dédié (~/.fgfs/fghome-next) pour éviter
la modale de migration de paramètres (next détecte l'autosave 2024.1.5
et bloque le démarrage en attendant un clic — fatal en headless).
Prérequis (legacy, Intel/macOS ≤15) :
setup-macos.md§6 — bootstrap de FGDATA cask. Sur macOS 26, ignorer : utiliser le build sources ci-dessus.
Comment c'est branché¶
┌─────────────────┐ UDP 5503 (FDM) ┌──────────────┐
│ ArduPilot SITL │ ────────────────▶ │ FlightGear │
│ (arduplane) │ native_fdm │ (fgfs) │
│ TCP 5760 ◀──── MAVLink ── Cockpit/QGC (renderer 3D)
└─────────────────┘ └──────────────┘
- SITL reste l'autorité physique. C'est lui qui calcule l'attitude, la vitesse, la position. Il émet des paquets FlightGear native FDM sur UDP 5503 quand on lui passe
--enable-fgview. - FlightGear est strictement un viewer. Il lit le FDM externe et rend la scène. Il ne touche pas à la physique.
- MAVLink reste séparé sur TCP 5760 → ton Cockpit ou QGC fonctionne en parallèle exactement comme avant.
Ça veut dire que FG ne change rien aux comportements de vol — c'est juste une fenêtre 3D supplémentaire. Tu peux le fermer / rouvrir sans perturber SITL.
Lancement rapide¶
Premier lancement : 30–90 s. FlightGear télécharge la scenery de la Rive-Sud via TerraSync (~50–200 MB pour le tile w074n45). Les lancements suivants sont quasi instantanés (scenery en cache local).
Lancement manuel (debug)¶
Si tu veux voir ce que fait le Makefile, ou changer des paramètres :
# Terminal 1 — SITL avec FDM out
cd ~/Project/bascanada/ardupilot
sim_vehicle.py -v ArduPlane --no-mavproxy --enable-fgview \
-l 45.5175,-73.4170,27,245
# Terminal 2 — FlightGear viewer
/Applications/FlightGear.app/Contents/MacOS/FlightGear \
--fg-root="$HOME/.fgfs/fgdata" \
--native-fdm=socket,in,10,,5503,udp \
--fdm=external \
--aircraft=Rascal110-JSBSim \
--fg-aircraft=$HOME/Project/bascanada/ardupilot/Tools/autotest/aircraft \
--airport=CYHU \
--enable-terrasync \
--geometry=1280x800 \
--disable-sound
--fg-rootest obligatoire sur macOS — la cask ne bundle pas FGDATA, donc FG ne le trouve pas par lui-même. Sans ce flag, le binaire s'initialise puis sort silencieusement (RSS reste à ~30 KB, pas de fenêtre).Symlink pour éviter l'espace dans le path : FGDATA s'extrait dans
~/Library/Application Support/FlightGear/fgdata/mais l'espace blanc dansApplication Supportfait parfois bloquer FG. On symlinke vers~/.fgfs/fgdata(path "propre") et c'est cette cible qu'on passe à--fg-root. Voir setup-macos.md §6.b.Note macOS : sur Linux le simulateur est
fgfs. Sur macOS il est packagé comme l'exécutable principal du.appet renomméFlightGear. Les flags CLI restent identiques.
Les flags clés :
| Flag | Rôle |
|---|---|
--fg-root=... |
Chemin vers FGDATA (obligatoire sur cask macOS) |
--native-fdm=socket,in,10,,5503,udp |
Reçoit le FDM de SITL sur UDP 5503 à 10 Hz |
--fdm=external |
Désactive la physique interne de FG, prend le FDM externe |
--aircraft=Rascal110-JSBSim |
Modèle 3D de l'avion (déjà fourni par ArduPilot) |
--fg-aircraft=... |
Dossier où FG cherche les modèles custom (Tools/autotest/aircraft) |
--airport=CYHU |
Saint-Hubert — vue initiale + scenery prioritaire |
--enable-terrasync |
Téléchargement auto de scenery via le réseau |
Pourquoi CYHU (Saint-Hubert) comme point de spawn ?¶
| Critère | CYHU |
|---|---|
| ICAO | CYHU |
| Coords | 45.5175°N, 73.4170°W |
| Élévation | 27 m / 90 ft |
| Piste principale | 06L/24R, 2 100 m asphalte |
| Distance de Montréal | ~12 km du centre-ville, plein cœur Rive-Sud |
| Scenery FG | Tile w074n45 — couvre Longueuil, Brossard, St-Hubert, Boucherville |
| Type | Aéroport commercial régional + GA — bien modélisé dans la base FG |
C'est l'aéroport de référence Rive-Sud, présent dans la base d'aéroports FG par défaut. Pas besoin de l'ajouter manuellement.
Le heading de spawn est 245° (piste 24R westerly takeoff) — orientation par défaut sous les vents dominants ouest/sud-ouest.
Autres points d'intérêt à survoler après spawn¶
| Endroit | Lat, Lon | Note |
|---|---|---|
| Pont Jacques-Cartier | 45.523°, -73.546° | Survol urbain Montréal — beau visuel |
| Mont Saint-Bruno | 45.555°, -73.330° | Élévation 218 m, terrain vallonné |
| Île Sainte-Hélène | 45.518°, -73.531° | Parc Jean-Drapeau + La Ronde |
| Boisé Du Tremblay | 45.567°, -73.422° | Forêt urbaine Longueuil — analogue scouting |
| Bassin de Chambly | 45.450°, -73.290° | Plan d'eau au sud — terrain Pour test boat plus tard |
Tous ces points sont dans le tile w074n45, donc accessibles dès que la scenery initiale est cachée.
Changer de point de spawn¶
Édite la variable dans le Makefile :
Pour d'autres régions du Québec :
| Région | Aéroport | Coords (lat,lon,alt,hdg) |
|---|---|---|
| Mirabel (Nord MTL) | CYMX | 45.6800,-74.0386,82,290 |
| Trois-Rivières | CYRQ | 46.3525,-72.6794,60,230 |
| Québec / Jean-Lesage | CYQB | 46.7911,-71.3933,72,300 |
| Sherbrooke | CYSC | 45.4386,-71.6911,241,230 |
| Sept-Îles | CYZV | 50.2233,-66.2656,55,090 |
| Mont-Tremblant / La Macaza | CYTM | 46.4094,-74.7800,265,210 |
Et change --airport=CYHU dans le Makefile en conséquence.
Performance attendue sur Apple Silicon (M1 Pro)¶
| Phase | Comportement |
|---|---|
fgfs startup à froid |
30-90 s (TerraSync télécharge w074n45) |
fgfs startup à chaud (scenery cachée) |
10-20 s |
| Steady-state FPS | 30-60 FPS @ 1280×800 |
| RAM utilisée | ~1.5-2.5 GB |
| GPU usage | modéré sur GPU Apple Silicon intégrée |
Si tu vois la scenery se construire en patchwork (tiles qui pop-in pendant le vol), c'est TerraSync qui télécharge en arrière-plan. Normal au premier survol d'une zone.
Pipeline vidéo : caméra FG dans Cockpit¶
But : afficher la vue 3D de FG comme un flux caméra dans Cockpit (la GCS web Blue Robotics), pour un feeling FPV / démos, sans Gazebo.
FG ──/screenshot MJPEG──▶ go2rtc ──RTSP/WebRTC──▶ Cockpit
:5400 (httpd, intégré) :8554 / :8555 (go2rtc embarqué)
- FG : le serveur
--httpdexpose/screenshot/?stream=1en MJPEG (multipart/x-mixed-replace) — infra déjà dans FG, pas un ajout. - go2rtc (
~/.local/bin/go2rtc, binaire Go, configtools/video-pipeline/go2rtc.yaml) ingère le MJPEG et le ré-émet en RTSP + WebRTC. - Cockpit n'accepte QUE WebRTC ou RTSP (pas MJPEG direct), mais sa build Electron embarque go2rtc : on lui donne l'URL RTSP, son go2rtc interne fait RTSP→WebRTC.
Workflow¶
make fpv # = SITL plane + FG (3D + MJPEG) + go2rtc
make fpv-down # arrête go2rtc + FG (SITL reste)
make go2rtc # go2rtc seul (si FG déjà lancé)
Puis dans Cockpit : VideoPlayer widget → config → add RTSP stream →
rtsp://127.0.0.1:8554/fg. (Cette étape est manuelle dans l'UI Electron.)
Vérif sans Cockpit (go2rtc ressort une frame du flux) :
Patch FPS (maxfps)¶
FG plafonne le stream screenshot à 8 fps en dur
(ScreenshotCallback::_min_delta_tick = 1.0/8.0 dans
src/Network/http/ScreenshotUriHandler.cxx). Patch local appliqué sur le
clone next : param query ?maxfps=N (clampé 1–60, défaut 8,
rétro-compatible). URL complète :
http://127.0.0.1:5400/screenshot/?stream=1&type=jpg&maxfps=30.
Candidat MR upstream — voir docs/dev/upstream-contributions.md.
⚠️ Le fps réel = min(maxfps, taux de rendu FG). La boucle de rendu FG est throttlée par macOS quand sa fenêtre est en arrière-plan/occluded (contexte GL ralenti) → on retombe à ~8 fps même avec
maxfps=30. Pour le vrai débit : garder la fenêtre FG au premier plan, ou désactiver le throttle de frame. Pas un bug du patch — une limite du rendu.✅ Bug
ImageCompressorUAF — corrigé.ImageCompressionTasktenait unStringReadyListener*brut vers unConnectionDatalibéré quand le client se déconnecte pendant qu'une frame est en file → le thread compresseur déréférençait du mémoire libérée → SIGSEGV (ScreenshotUriHandler.cxx:129). Fix :SGSharedPtr<SGReferenced> listenerRefdans la task qui épingle le listener vivant jusqu'à fin de compression. Validé : FG survit >288s avec consommateur continu (crashait avant à ~168s). Candidat MR upstream.⚠️ macOS termine FG après quelques minutes (process lifecycle, pas un crash :
runningboardd proc_exit, AutomaticTermination, pas de crash report). Pire si la fenêtre perd le focus (App Nap). Mitigations appliquées sur le bundle buildé :NSSupportsAutomaticTermination=NO+NSSupportsSuddenTermination=NO(Info.plist),defaults write org.flightgear.mac-develop NSAppSleepDisabled -bool YES, et lancement wrappécaffeinate -idans le Makefile. Garder la fenêtre FG au premier plan reste le plus fiable pour les sessions longues.
Limitations à connaître¶
a) Le Rascal n'est pas le Swordfish¶
Le modèle 3D affiché est le Rascal 110 (modèle générique ArduPilot fourni). Ce n'est pas visuellement un AtomRC Swordfish 1200. Pour le vol et la physique, ça ne change rien (SITL fait toute la physique sur son propre modèle paramétrique). C'est juste que tu verras un Rascal voler à l'écran.
Modéliser un Swordfish 3D pour FG = projet à part entière (XML + meshes) qui n'apporte aucune valeur fonctionnelle. Pas dans le scope.
b) Pas de pilote dans le cockpit¶
Vu de l'extérieur, c'est cohérent (drone autonome). Si tu veux la vue cockpit (v dans FG), tu vois un cockpit Rascal qui n'a rien à voir avec ton avion. Reste à l'extérieur (vue tower, chase, etc.).
c) Retour caméra : FG → Cockpit via go2rtc (✅ marche)¶
FG ne simule pas la caméra Pi du fleet-companion (capteur réaliste, gimbal, CV → ça reste Phase 4+ Gazebo). Mais on peut utiliser la vue 3D de FG comme un faux flux FPV dans Cockpit — voir § Pipeline vidéo.
d) Le vent FG ne se synchronise pas avec SITL¶
FG a son propre modèle de vent qui n'influe sur rien (il prend le FDM externe). Pour simuler du vent, c'est côté SITL :
# Dans MAVProxy ou via paramètres :
param set SIM_WIND_SPD 5 # 5 m/s
param set SIM_WIND_DIR 270 # ouest
L'avion réagira dans SITL, et tu verras FG le rendre.
Vues utiles en vol¶
Une fois en vol, raccourcis FG :
| Touche | Vue |
|---|---|
v |
Cycle: cockpit / tower / chase / fly-by |
V (shift+v) |
Vue précédente |
x / X |
Zoom in / out |
Ctrl+v |
Reset vue |
p |
Pause (mais SITL continue — désynchro temporaire) |
Esc |
Quit FG (proprement) |
Vue tower = cool pour voir l'avion décoller et tourner autour du field. Vue chase = caméra qui suit l'avion en queue. Vue fly-by = caméra fixe qui regarde l'avion passer (très bon pour démos vidéo).
Cycle de dev typique avec FG¶
make fg # lance SITL @ CYHU + FG
# (laisser FG en arrière-plan, garder en focus Cockpit pour le pilotage)
make cockpit # ouvre Cockpit pour piloter via UI/manette
# … session de vol …
make fg-down # ferme FG quand tu n'as plus besoin du visuel
make down # arrête SITL
FG est optionnel — tu peux faire toute ta session sans, et juste l'ouvrir quand tu veux valider un décollage ou un atterrissage visuellement.
Troubleshooting¶
| Symptôme | Cause probable | Fix |
|---|---|---|
✗ FlightGear introuvable au make fg |
Cask pas installé | brew install --cask flightgear |
✗ FGDATA introuvable au make fg |
FGDATA pas bootstrap | Suivre setup-macos.md §6.b (download 1.88 GB) |
| Process FG démarre mais reste à RSS=30 KB, pas de fenêtre | --fg-root pas passé ou pointe sur dir vide |
Vérifier que ~/Library/Application Support/FlightGear/fgdata/ existe et contient Aircraft/, Airports/, etc. |
| FG s'ouvre mais aucun avion visible | SITL pas démarré avec --enable-fgview |
make plane-down && make plane-fg |
| FG s'ouvre mais l'avion ne bouge pas | SITL n'a pas armé / pas de takeoff | Arme depuis Cockpit, mode TAKEOFF |
| Scenery très moche / patchwork | TerraSync en cours de download | Attendre 1-2 min, refaire un survol |
| Pas de scenery du tout (terrain plat vert) | TerraSync désactivé | Vérifier --enable-terrasync dans le flag |
| FG crash au startup | Modèle Rascal pas trouvé | Vérifier $AP_TOOLS/aircraft/Rascal/ existe |
| FPS très bas (<10) | GPU saturée par autre app | Fermer Cockpit pendant test FG seul ; ou réduire --geometry |
lsof -i :5503 montre rien |
SITL pas en mode FG | Démarrer avec make plane-fg pas make plane |
| FG affiche bonne scenery mais ailleurs (KSFO) | --airport=CYHU mal passé |
Vérifier le flag dans le Makefile |
Stocker la scenery en local (offline)¶
TerraSync écrit dans ~/.fgfs/TerraSync/ par défaut. Une fois la scenery Rive-Sud chargée :
On peut backup ce dossier pour avoir la scenery offline (utile sur le terrain sans réseau).
Pourquoi pas Gazebo, X-Plane, RealFlight ?¶
| Alternative | Pourquoi pas pour Fleet |
|---|---|
| Gazebo | Macros support macOS rugueux ; orienté ROS2 (pas notre stack) ; vraiment utile pour caméra simulée (Phase 4+) |
| X-Plane | Commercial. Bridge ArduPilot existe mais pas OSS. |
| RealFlight Evolution | Commercial + Windows only. |
| JSBSim viewer | Pas un vrai viewer 3D — c'est juste les graphs FDM. |
| AirSim | Archivé par Microsoft 2024. |
FG = OSS, mature, Apple Silicon native, scenery monde entier, intégré nativement à ArduPilot depuis 10+ ans. C'est le bon choix pour la Phase 0.5–1.
Références¶
- ArduPilot SITL with FlightGear — https://ardupilot.org/dev/docs/sitl-with-flightgear.html
- FlightGear download — https://www.flightgear.org/download/
- TerraSync (scenery server) — https://scenery.flightgear.org/
- Rascal 110 model README —
$ARDUPILOT/Tools/autotest/aircraft/Rascal/README.Rascal