flight-planning-and-navigation
Setting up Automated Flight Missions and Challenges in Flightgear
Table of Contents
Introduction to FlightGear Automated Missions
FlightGear is one of the most capable open-source flight simulators available, offering a detailed physics engine, realistic aircraft models, and a thriving community of developers and enthusiasts. Among its most powerful features is the ability to design and run automated flight missions and challenges. These allow you to script everything from a simple cross-country flight to complex, multi-phase scenarios that test navigation, fuel management, and emergency response skills. Whether you are a student pilot practicing instrument approaches, an instructor creating training modules, or a simulation enthusiast building a virtual air race, FlightGear’s mission system provides the flexibility you need.
This guide will walk you through the entire process: from understanding the underlying XML-based mission structure, to writing your first mission, adding objective-driven challenges, running missions from the command line or GUI, and finally sharing your creations with the community. By the end, you’ll be able to build missions that are as educational as they are engaging.
Getting Started with Automated Missions
FlightGear’s mission system is built around XML files that define every aspect of a flight scenario. These files reside in the Missions/ subdirectory under your FlightGear data folder (commonly $FG_ROOT/Missions/). You can create a new mission file with any text editor – no special tools are required, though an XML-aware editor will help with syntax highlighting.
A mission file typically contains the following core elements:
- Aircraft – the specific model to be used (e.g.,
737-300,c172p,Piper-J3-Cub). You can also let the mission override the user’s current plane. - Start location – an ICAO airport code, a lat/lon pair, or a named heliport.
- Waypoints – a sequence of navigational fixes that define the route. These can be airports, NAVAIDs, or custom coordinates.
- Weather conditions – either a specific METAR string or a set of parameters (visibility, cloud layers, wind).
- Time of day – can be set to dawn, noon, dusk, or a specific UTC time.
- Objectives and triggers – the key to making missions interactive. These can test altitude, speed, timing, or proximity to waypoints.
To begin, create a file called my_first_mission.xml in your $FG_ROOT/Missions/ folder. Open it and write the basic XML skeleton:
<?xml version="1.0"?>
<PropertyList>
<mission>
<name>My First Mission</name>
<description>A simple flight from Seattle to Portland</description>
</mission>
</PropertyList>
Note: The top-level element is <PropertyList> (FlightGear uses property lists for many configuration files). Inside that, a <mission> tag holds all mission data.
Creating a Basic Mission
Let’s expand the skeleton into a workable mission. We’ll set the aircraft to a Cessna 172, start at Seattle-Tacoma International (KSEA), fly to Portland International (KPDX) via a waypoint over Mount St. Helens, and apply real-world weather.
Adding Aircraft and Start Location
Inside <mission>, add:
<aircraft>c172p</aircraft>
<start>
<airport>KSEA</airport>
<runway>16R</runway>
<altitude>0</altitude> <!-- on the ground -->
</start>
You can also specify a lat/lon offset if you want to start in the air. For example, to start at 3,000 feet over KSEA:
<start>
<lat>47.4489</lat>
<lon>-122.3093</lon>
<altitude>3000</altitude>
<heading>180</heading>
</start>
Defining Waypoints
Waypoints are arranged under <route>. Each waypoint can be an ICAO code, a named fix, or explicit coordinates. A simple route with three legs might look like this:
<route>
<wp>
<type>airport</type>
<id>KSEA</id>
</wp>
<wp>
<type>latlon</type>
<lat>46.1912</lat>
<lon>-122.1956</lon>
</wp>
<wp>
<type>airport</type>
<id>KPDX</id>
</wp>
</route>
For visual navigation, you can add a <name> to each waypoint (e.g., “Mount St. Helens VOR”).
Setting Weather and Time
Add weather inside <environment>:
<environment>
<metar>KSEA 161553Z 27010KT 10SM SCT045 12/07 A2998</metar>
<time>2025-03-16T15:55:00Z</time>
</environment>
Alternatively, you can use discrete parameters:
<environment>
<visibility>10</visibility>
<wind>
<speed>10</speed>
<direction>270</direction>
</wind>
<clouds>
<layer>
<altitude>4500</altitude>
<coverage>scattered</coverage>
</layer>
</clouds>
<time>12:00:00</time>
</environment>
Complete Basic Mission Example
Here’s the full file (my_first_mission.xml):
<?xml version="1.0"?>
<PropertyList>
<mission>
<name>Seattle to Portland – VFR</name>
<description>Fly a Cessna 172 from KSEA to KPDX via Mount St. Helens. Visual conditions expected.</description>
<aircraft>c172p</aircraft>
<start>
<airport>KSEA</airport>
<runway>16R</runway>
<altitude>0</altitude>
</start>
<route>
<wp>
<type>airport</type>
<id>KSEA</id>
<name>Departure</name>
</wp>
<wp>
<type>latlon</type>
<lat>46.1912</lat>
<lon>-122.1956</lon>
<name>Mount St. Helens</name>
</wp>
<wp>
<type>airport</type>
<id>KPDX</id>
<name>Arrival</name>
</wp>
</route>
<environment>
<metar>KSEA 161553Z 27010KT 10SM SCT045 12/07 A2998</metar>
<time>2025-03-16T15:55:00Z</time>
</environment>
</mission>
</PropertyList>
This mission will load with the Cessna on runway 16R at KSEA, with the weather set to a real observation. The route is pre‑defined, but the pilot must navigate manually. To make it truly automated, you can add a flight director that follows the route – but that’s a separate feature (autopilot coupling).
Adding Challenges and Objectives
A mission without objectives is just a scenic flight. Challenges turn it into a test of skill. FlightGear supports several built‑in goal types, and you can create custom ones using the property tree and Nasal scripting. Here are the most common:
Altitude Challenge
Require the pilot to stay within a certain altitude band. Add a <objectives> section:
<objectives>
<objective>
<type>altitude</type>
<min>2000</min>
<max>4000</max>
<description>Maintain altitude between 2,000 and 4,000 feet MSL</description>
<fail_on_exit>true</fail_on_exit>
</objective>
</objectives>
If the pilot goes above 4,000 or below 2,000, the mission fails (or you can set <fail_on_exit>false to just log a penalty).
Time Limit Objective
Useful for races or fuel‑conservation tests:
<objective>
<type>time</type>
<max_seconds>3600</max_seconds> <!-- 1 hour -->
<description>Complete the flight within 60 minutes</description>
</objective>
Time is measured from mission start. If the mission ends (e.g., by landing at the destination) after the limit, it fails.
Navigation Accuracy
Check how close the aircraft passes to each waypoint. This is done with a navigation accuracy objective:
<objective>
<type>nav_accuracy</type>
<radius>1.0</radius> <!-- nautical miles -->
<waypoints_included>Mount St. Helens</waypoints_included>
<description>Pass within 1 NM of Mount St. Helens waypoint</description>
</objective>
You can list multiple waypoints to check sequentially.
Landing Challenge
For a final challenge, require a smooth landing:
<objective>
<type>landing</type>
<max_vertical_speed>200</max_vertical_speed> <!-- ft/min -->
<max_bank>5</max_bank> <!-- degrees -->
<description>Perform a smooth landing at KPDX (V/S < 200 fpm, bank < 5°)</description>
</objective>
Multi‑Objective Missions
Combine several objectives for a richer experience. The mission will track all of them simultaneously. For example, a training mission might include: maintain altitude, hit three waypoints within a 2 NM radius, and land with a vertical speed under 150 fpm. The mission can be set to “pass” only if all objectives are met.
Here’s a complete objectives block for the Seattle–Portland mission:
<objectives>
<objective>
<type>nav_accuracy</type>
<radius>2.0</radius>
<waypoints_included>Mount St. Helens</waypoints_included>
<description>Pass within 2 NM of Mount St. Helens</description>
</objective>
<objective>
<type>landing</type>
<max_vertical_speed>200</max_vertical_speed>
<max_bank>5</max_bank>
<description>Smooth landing at KPDX</description>
</objective>
<objective>
<type>time</type>
<max_seconds>5400</max_seconds> <!-- 1.5 hours – generous for a 172 -->
<description>Complete the flight within 90 minutes</description>
</objective>
</objectives>
Automating and Running Missions
Once your mission file is saved, you can launch it in several ways.
Command‑Line Launch
The most reliable method is using the --mission option:
fgfs --mission=Missions/my_first_mission.xml
You can also specify a full path. Other useful command‑line flags include --ai-scenario (to add AI traffic) and --prop:/sim/startup/status=manual if you want to control engine start.
GUI Launch (Mission Selector)
FlightGear includes a Mission Selector dialog (available from the “Mission” menu in the launcher). It scans the Missions/ directory and displays mission names and descriptions. Simply select one and press “Fly”. Missions placed in subdirectories are also found.
Automated Flight without Pilot Input
If you want the mission to fly itself (for testing or as a “flight director” demonstration), you can enable the autopilot to follow the route. Add the following to the mission file:
<autopilot>true</autopilot>
This activates the route‑following autopilot (if the aircraft has one). Not all models support this; the 747‑400 and A320 do. For the Cessna 172, the default autopilot can only hold heading and altitude – not full route navigation – so this may not work without a custom Nasal script.
Advanced Mission Design – Nasal Scripting
For missions beyond what built‑in objectives offer, Nasal is your gateway. Nasal is FlightGear’s embedded scripting language, able to read and write any property in the property tree, play sounds, spawn aircraft, and control simulation state. You can attach a Nasal script to a mission via the <scripts> section:
<scripts>
<script>Missions/my_mission_script.nas</script>
</scripts>
With Nasal you can create dynamic challenges such as:
- Engine failure after a set time or at a random waypoint.
- Score points for each successful waypoint, with bonus for altitude windows.
- Interactive ATC communication (via command dialog).
- Spawn AI aircraft as “competitors” in an air race.
- Conditional mission phases – for example, after landing, load a new set of objectives for a second leg.
Here’s a minimal Nasal example that prints a message when the aircraft passes within 0.5 NM of the first waypoint:
var wp0 = getprop("mission/route/wp[0]");
var lat = getprop("position/lat-deg");
var lon = getprop("position/lon-deg");
var dist = geo.distance(lat, lon, wp0.lat, wp0.lon) * 0.000539957; # convert meters to NM
if (dist < 0.5) {
print("You passed waypoint 1!");
}
For a deeper dive, see the Nasal scripting language page. Writing a full tutorial on Nasal is beyond this article, but the community has many example scripts in the Missions/ directory of the base package.
Testing and Debugging Your Missions
Even a simple mission can have subtle bugs – an incorrect XML syntax, a missing closing tag, or a waypoint that doesn’t exist in the nav database. Use these strategies to troubleshoot:
- Check the console output. Run FlightGear from a terminal and watch for errors. Missions that fail to load will print an error message like “Failed to load mission: ...”.
- Use the property browser. Press
Ctrl+Pin‑sim to open the property browser. Look under/sim/missionto see the loaded mission data and objective states. - Validate XML syntax. Use an online XML validator or an editor with syntax checking before loading.
- Test waypoint coordinates. A waypoint at 47.0, -122.0 might be over water – ensure it’s reachable. You can verify coordinates in FlightGear’s map dialog (
Ctrl+M). - Simplify first. Start with a mission that has only a start location and no objectives. Once that loads correctly, gradually add waypoints, weather, and objectives.
- Search the forums. Many common issues have been discussed on the FlightGear community forum. Use the “missions” tag.
Sharing Your Missions with the Community
Once you’ve created a polished mission, consider sharing it. The FlightGear community maintains a large repository of user‑contributed missions. Here’s how to contribute:
- Package your mission as a single XML file (or a zip with any Nasal scripts). Include a clear name and description inside the XML so the Mission Selector shows useful info.
- Upload to the FlightGear forum or the wiki. The Missions wiki page has a list of user missions and a template for adding new ones.
- Submit to the base package – mission files that are widely useful may be included in future releases. Contact the development team via the mailing list or forum.
- License your mission under GPLv2+ (the same license as FlightGear) to allow others to modify and redistribute.
Conclusion
Automated flight missions in FlightGear transform the simulator from a passive “fly anywhere” tool into an engaging, goal‑driven learning platform. By mastering the XML mission format and adding objectives, you can create scenarios that range from basic VFR navigation practice to complex multi‑phase challenges with real‑time scoring and scripting. The combination of built‑in objective types and the full power of Nasal scripting gives you virtually unlimited possibilities.
Start small: write a mission that places you on a runway, defines a simple route, and sets one objective (like hitting a waypoint). Once it works, add weather, time pressure, and landing challenges. As you grow comfortable, explore Nasal to add dynamic events. And always share your results – the FlightGear community thrives on user‑created content. Now open your text editor, create that first .xml file, and take to the skies with a purpose. Happy flying!