| This article or section contains out-of-date information
| The FlightGear forum has a
subforum related to: AI Scripting
Development & Issues
- 1 Introduction
- 2 User Information
- 3 Developer Information
- 4 Related content
FlightGear has a number of more or less independently operating systems for simulating semi-intelligent interaction with the environment, so called AI Systems. Because there often times exists some confusion regarding to which system does what, one should take notice of the differences between them: The major distinction is that between an older ATC/AI system, and a newer AIModels system. The AIModels system can, in turn, be controlled in at least three different ways; directly, using a script, through the multiplayer system, and through a subsystem known as the traffic manager.
The AIModels system is described in the remainder of the article.
Multiplayer controlled traffic
See Howto: Multiplayer for the main article about this subject.
FlightGear's multiplayer system also makes use of the AIModels subsystem.
Traffic Manager controlled traffic
See Interactive Traffic for the main article about this subject.
Traffic Manager controlled input to the AIModels subsystem is also known as Interactive Traffic.
Enabling and Disabling the AI Traffic System
To enable/disable the AI traffic system:
- FlightGear 2.2.0 and above
- Flightgear 2.0.0 and older
To enable/disable the AIModels system, use
Finding Existing Scenarios
You can find a description of the standard FG demo scenarios at AI Scenarios.
There is no central repository for scenarios, but e.g. FGUK has a larger set of scenarios for download.
In order to use AI objects it is necessary to load one or more scenario files. There are several ways to select scenarios.
- set it in preferences.xml file
- use commandline parameters
- load/unload through AI menu at runtime
Set Scenarios in preferences.xml file
The preferences.xml file has an entry that looks like this:
<ai> <enabled type="bool">true</enabled> <scenarios-enabled type="bool" userarchive="y">true</scenarios-enabled> <scenario>aircraft_demo</scenario> </ai>
The above bit of XML enables the AI system and selects a scenario file called aircraft_demo.xml.
Load Scenarios with command line parameters
It is possible to load scenarios with commandline parameters.
The value of the --ai-scenario parameter is the filename of the scenario xml file in "data/AI" directory. If necessary the --ai-scenario parameter can be repeated to load multiple scenarios.
Load Scenarios at runtime
In newer FG versions it is also possible to load/unload scenarios at runtime with the menu entry "AI/Traffic and Scenario Settings".
Starting with FlightGear version 0.9.4 you can place AI objects in the "FlightGear world". They are defined in a "scenario" XML file. The scenario file must be in the "data/AI" directory. There are several different types of AI objects.
NB: there is a similar description in $FG_ROOT/Docs/AI_doc.html.
Types of AI Objects
|carrier||The aircraft carrier AI object is based on the "ship" object but is much more complicated. See the scenario file called "data/AI/nimitz_demo.xml" for details. User information can be found at Howto:Carrier|
|submodels|| AI ballistic objects that emanate from, fall from, or launch from the user aircraft. They are presently used to model smoke, contrails, flares, tracers, bombs, drop tanks and flight path markers.
Submodels are controlled by the submodel manager. The manager reads a submodel configuration file at the start of the sim session. This configuration file is written by the aircraft author and defines all the submodels for that particular aircraft.
As an example examine the submodels file in the Aircraft/737-300 directory. This file creates two submodels which will become the airplane's left and right engine contrails. Each contrail needs its own submodel definition because the contrails begin at different locations. Each contrail consists of a train of individual "puff" models that are released in rapid succession as long as the "trigger" property is true. We ensure an unlimited supply of puffs by setting the "count" parameter to -1. The individual puffs, being AIBallistic objects, will follow their own ballistic paths once released. In this case we have used the "bouyancy" parameter to negate gravity in the ballistic path. The puffs have been given a life span of eight seconds. At cruising speed the 737 will thus have about 400 puffs behind it at any moment.
See Submodels for the main article about this subject. See also $FG_ROOT/Docs/README.submodels. It gives a good idea about how to create submodel files, what parameters are available and how to use them, and also the type of research needed to make sure the information and models are accurate historically.
|wingman||See Howto:Add_wingmen for the main article about this subject.|
AI objects have some things in common:
- They have a location in the "FlightGear world"
- They can have an associated exterior 3D model
- They can move according to an internal FDM (flight dynamics model).
Details regarding each object (e.g. available properties) can be found in the source files in $FLIGHTGEAR_SRC/src/AIModel/. e.g.
AIStorm.hxx . Common properties are in
AIBase. Look for section
private: in the file to find the properties and related comments. E.g. to get additional information like the units to be used:
double diameter; // diameter of turbulence zone, in nm
Even though you might not be familiar with programming, the information is readable (and more up to date than the information e.g. on this page).
Scenario File definition
The scenario file contains one entry for each AI object. The entry specifies what kind of object to create, what its initial conditions will be, and optionally (for aircraft and ships) a flight plan. The entry for a sailboat could look like this:
<entry> <type>ship</type> <model>models/geometry/sailboat.xml</model> <speed-ktas type="double">12.0</speed-ktas> <altitude-ft type="double">0.0</altitude-ft> <longitude type="double">-122.33333</longitude> <latitude type="double">37.61667</latitude> <heading type="double">20.0</heading> <rudder type="double">-3.0</rudder> </entry>
- XML tags are case-sensitive.
- Introducing certain characters into the XML file, even as part of a comment, will cause the file to choke. These include &, <, and --.
Most of the parameters are self-explanatory. The "type" of object can be one of Types_of_AI_Objects (see above).
The rest of the items give the AI object a model, a starting location, and a starting speed and direction. You use the <model> item to give the object any valid exterior model. You can even make the ship look like an airplane if you want! Note that the speed of the AI object is true airspeed, and since AI aircraft and ships don't feel wind or current then this also the ground speed. The "ship" type can also have a <rudder> value specified, which will cause the ship to move in a circle (Tip Use small values, five degrees or less, and right rudder is positive). Here is an example of how to create an aircraft AI object:
<!-- puts an A-4 north of KSFO, orbiting at 7000 ft --> <entry> <type>aircraft</type> <class>light</class> <model>Aircraft/a4/Models/a4-blue.xml</model> <speed-ktas type="double">320.0</speed-ktas> <altitude-ft type="double">7000.0</altitude-ft> <longitude type="double">-122.6</longitude> <latitude type="double">37.9</latitude> <heading type="double">210.0</heading> <bank type="double">-15.0</bank> </entry>
It looks much the same as the ship AI code. There are two differences, the <class> item and the <bank> item.
classspecifies the type of aircraft and its flight characteristics/performance. You can find the allowed values for this property in fgdata/AI/Aircraft/performancedb.xml.
If the class is set to "tanker" and the airplane actually is configured to be a tanker, than it will allow you to refuel if you can get close behind it (see also Howto:Aerial_refueling).
bankis of course similar to the ship's rudder. In the above example the A-4 will be orbiting to the left at 15 degrees of bank. Negative values are left, positive values right (for
pitchnegative is nose down).
You can also create a ship or airplane with a flight plan. In this case the object will follow the flight plan, and then delete itself when it reaches the end. The flight plans are kept in fgdata/AI/FlightPlans. To create an airplane with a flightplan do this:
<entry> <type>aircraft</type> <class>jet-transport</class> <model>Aircraft/737/Models/737.xml</model> <flightplan>ksfo_ils28l.xml</flightplan> </entry>
To make a thunderstorm, use this:
<!-- puts a thunderstorm overhead OSI (Woodside VOR) --> <entry> <type>storm</type> <model>Models/Geometry/thunderstorm.xml</model> <speed-ktas type="double">20.0</speed-ktas> <altitude-ft type="double">4000.0</altitude-ft> <latitude type="double">37.3917</latitude> <longitude type="double">-122.2817</longitude> <heading type="double">90</heading> </entry>
There's not much to it. No, they don't turn :) To create a thermal, use this:
<entry> <type>thermal</type> <latitude type="double">37.61633</latitude> <longitude type="double">-122.38334</longitude> <strength-fps type="double">8.33</strength-fps> <diameter-ft type="double">4000</diameter-ft> <height-msl>6000</height-msl> <model>Models/Geometry/thermalcap.xml</model> </entry>
The AI thermals don't move, they are invisible, and they don't "lean" downwind. The <strength-fps> defines the maximum vertical velocity of the airmass at the center of the thermal. The strength decreases to zero at the thermal's edge. A model can be assigned to the thermal, and usually this will be a small cloud to mark the thermal's location. To create a sink, just give a "thermal" a negative strength, and give it a null model. Please see the demo scenario (thermal_demo.xml) for examples.
A ballistic AI object starts with an initial azimuth, elevation and speed, then follows a ballistic path from there (with air resistance and wind included). Try this:
<entry> <type>ballistic</type> <model>Models/Geometry/rocket.xml</model> <speed-fps type="double">500.0</speed-fps> <altitude-ft type="double">50.0</altitude-ft> <longitude type="double">-122.39</longitude> <latitude type="double">37.62</latitude> <heading type="double">200.0</heading> <azimuth type="double">70.0</azimuth> <elevation type="double">45.0</elevation> </entry>
Note that the speed is now in feet per second.
The AI storm objects can be displayed on weather radar. See fgdata/Aircraft/Instruments/wxradar.xml for details. The AI aircraft objects can be displayed on radar. See fgdata/Aircraft/Instruments/radar.xml for details.
You can make your own AI scenario file, called say my_scenario.xml, and cut/paste entries from the other scenario files to build an AI scenario as complicated as you like.
The following how-to shows you how to animate a tail-dragger airplane so that its pitch attitude looks proper for the AI aircraft's airpeed. This is not needed for aircraft with tricycle landing gear.
Using Interpolation Tables
Interpolation tables are very handy for effecting animations that are non-linear in relation to the property they are referenced to.
They save the use of factors, offsets and min/max values.
For example; relating flap extension to airspeed of an AI model. Typically an aircraft will extend flaps on final approach to control Indicated Airspeed (IAS) and stall speed to affect a low speed controlled landing. Upon touchdown the extra lift efficiency introduced by the flaps is no longer required or desirable, hence the flaps will be retracted ASAP after touch down.
This is relatively simple in a sim aircraft as the
/surface-positions/flap-pos-norm property is a normalised indicator of the flap setting chosen by the pilot.
AI aircraft have no pilots to control flaps nor does the flight plan
<flaps-down>true/false</flaps-down> parameter effect the /AI property tree parameter, a relationship to the IAS is the next best choice.
To effect this relationship (IAS/flap-position) using factors/offsets and min/max would be quite difficult and non-intuitive. Using interpolation tables allows the following scenario to be setup very easily and intuitively:
|Stall (no flaps)||50 KIAS|
|Flaps||0, 10, 20, 30 deg|
|10° flaps||90 KIAS|
|20° flaps||70 KIAS|
|30° flaps||60 KIAS|
|Flare & touch down||50 KIAS|
|Retract flaps||45 KIAS|
|less than 45||0|
When the pilot extends the flaps "one notch" they will extend to "10°" etc. In the property tree, these 4 steps will typically be normalised to 0.00, 0.33, 0.66, 1.00. This will differ from aircraft to aircraft. If the aircraft does not have equal extensions for each "notch" of flaps, the values observed may be; 0.00, 0.10, 0.30, 0.66, 1.00. Modeling this non-linear extension using "factor, offset, min/max" would be extremely difficult if not impossible. Modeling it using interpolation tables is very easy, as you shall see.
For sim animations, the actual physical rotation of the control surface in the real world needs to be researched; this may reveal a linear or non-linear relationship between "nominal flap extension indicator" and physical rotation of the surface. That is, "10 degrees of flap" might only involve rotating the flap surface 5 degrees around its axis in the wing structure. In our 0,10,20,30 scenarios, assuming a linear relationship, 30 degrees of flap would result in the flap being rotated 15 degrees around its wing axis. Therefore the normalised /surface-positions/flap-pos-norm property would have a factor of 15 applied to the rotate animation
The way to change a linear relationship that uses "factor, offset, min/max" in the sim animation to a interpolation table in the AI animation is best understood by examining how "factor, offset, min/max" approach works:
- Take normalised value of the flaps (0=retracted, 1=extended)
- Apply the factor.
- Apply the offset
- Apply the min/max values
factor = 60 offset = -30 min = -10 max = 10
These figures are nonsense but are used to illustrate a point:
flaps retracted (0°) = 0 * 60 + -30 = -30; min = -10, so = -10 flaps extended (10°) = 0.33 * 60 + -30 = -10.2; min = -10, so = -10 flaps extended (20°) = 0.66 * 60 + -30 = 9.6 flaps extended (30°) = 1.00 * 60 + -30 = 30; max = 10, so = 10
More realistically, offset and min/max are not used for flaps, only a factor.
Say 27°, this represents the maximum rotation of the 3D component in the model around its defined axis.
flaps retracted(0°) = 0 x 27 = 0 flaps extended(10°) = 0.33 x 27 = 9 flaps extended(20°) = 0.66 x 27 = 18 flaps extended(30°) = 1.00 x 27 = 27
From this it can be seen that the 3D object will be rotated 0°, 9°, 18° & 27° to represent the 0°, 10°, 20° & 30° deployment of the flaps.
Relating this back to the speeds above:
|IAS (kt)||<rotate> value|
This gives a stepped effect, where the movement is limited to 1 kt of airspeed. That is the 3-D object will linearly move from 9° to 18° while the aircraft looses speed from 70 knots to 69 knots. This behaviour will make the need for an upper and lower limit of a stepped value obvious.
A simplified table:
|IAS (kt)||<rotate> value|
This will cause the flaps to start extending at the rate of 1/45 x 27 degrees per knot of airspeed gained until 45 knots when the rate of change will adjust to the new gradient. This is not how flaps behave, but can be used to good effect with "tail dragger" animations where at a certain IAS the tail starts rising, maybe at an increasing rate, until flying attitude is reached when it stops rising any further. The tail rising is not a stepped function of IAS.
Now we have the basic ideas behind interpolation tables, the question is how are they implemented…answer;…easy ….an example of the stepped flaps animation above
<interpolation> <entry><ind>0.000></ind><dep>0.000</dep></entry> <entry><ind>44.00></ind><dep>0.000</dep></entry> <entry><ind>45.00></ind><dep>27.00</dep></entry> <entry><ind>59.00></ind><dep>27.00</dep></entry> <entry><ind>59.00></ind><dep>27.00</dep></entry> <entry><ind>60.00></ind><dep>18.00</dep></entry> <entry><ind>69.00></ind><dep>18.00</dep></entry> <entry><ind>70.00></ind><dep>9.000</dep></entry> <entry><ind>89.00></ind><dep>9.000</dep></entry> <entry><ind>90.00></ind><dep>0.000</dep></entry> <entry><ind>100.0></ind><dep>0.000</dep></entry> </interpolation>