Fixing Presets

From FlightGear wiki
Jump to: navigation, search

The Problem

One important use of FlightGear is as a pilot training aid, and one huge thing that instructors like to do is setup in-air starts so you can practice a lot of approaches in a short amount of time (that's one of the key benefits of a simulator over a real airplane.)[1]

It's quite common to want to start a flight simulator on a 5 or 7 or 10 mile approach so you can practice ILS landing. The start-offset-m value I believe was added later to account for the difference in aircraft sie. A starting position that works well to place the C172 at the end of the runway, might put the back half of the 747 off the end of the runway. [2]

Unfortunately, the addition of Presets has caused a plethora of problems and many regressions, including breaking support for Reset & re-init, but also for saving/loading and resuming flights:

The original reset was a simple kludge that worked fine for a simple program; now that FlightGear is a lot more sophisticated, we need to refactor a bit rather than just holding things together with scotch tape and bubble gum.

The problem is that right now we have two different approaches - a lot of stuff is handled cleanly in individual modules' update() methods, but a lot of stuff is still handled by hundreds of lines of BASIC-like, hard-to-read spaghetti code in main.cxx and fg_init.cxx (forget OO, it's not even functional programming).

That was the right idea to get started - I'm not a fan of wasting time on an initial OO design that you won't end up using -- but now we need to finish cleaning it up. We need to make this a high priority.[3]|

The position init code is a little complex, to allow for starting on a carrier and some other cases, and ideally we would do it from script, but unfortunately there's some technical limitations on doing that. (Not insurmountable, but not quick either). Adding more cases to the position-init code is certainly doable - one suggestion I made some time ago, is when MP is active, to default to starting at a free parking position instead of on a runway. (When no startup position is provided at all). This would avoid people accidentally starting on the runway in MP events, which would be a big usability win.

When no parking positions are defined, AI traffic defaults to the 'airport centre' location. Selection a taxiway parallel to the active runway is possible, but for complex airport layouts I can imagine many ways this logic could fail. Personally I think it would be more robust to stick to picking parking positions, and otherwise using the airport centre, because it would encourage people to add the parking position data :)

I anyone wants to work on this, it would be a self-contained function in position-init code, just ask here for any questions. All the pieces certainly exist - the taxiways, parking locations and runways for the airport are all accessible.[4]

  1. Curtis Olson (2010-11-01). [Flightgear-devel] Fwd: in air starts and all preset control/trim settings broke.
  2. Curtis Olson (Aug 25th, 2008). Re: [Flightgear-devel] Startup position offsets (fg_init).
  3. David Megginson (Thu, 06 Jun 2002 05:03:39 -0700). Crash on "Reset" function..
  4. James Turner (2013-11-12 10:32:27). Aircraft positioning on the runway.

Status (03/2015)

Cquote1.png reset and reposition now use the same codepath (something I've been working towards for many months). They do a full control reset, but after that, a full initial state restore. (it would be possible to support a 'nearby' re-position that doesn't touch the tile-manager, AI manager, or so on, and just re-inits the FDM - but that's something for the future, if people want it)
Cquote1.png we already saved all the initial state at the end of the main init - but Nasal scripts run before that state is saved - so running presets-commit then confuses things mightily. What I do now, is special case position changes (presets-commit) that happen during startup, and skip the reset path entirely, since it's unnecessary. This gives us:
  • Nasal can merrily re-init during startup if it chooses
  • control values specified on the command line, -set files or config survive the init process

Cquote1.png Reposition and reset from the GUI both work, and will give you the state as specified in the -set & config files, and command line. Since reposition from the GUI *is a* reset (now), some properties may change that previously did not, but I can't imagine a situation where the old behaviour was better - since we already wiped the FDM and control state regardless.
Cquote1.png Reposition and reset from the GUI both work, and will give you the state as specified in the -set & config files, and command line. Since reposition from the GUI *is a* reset (now), some properties may change that previously did not, but I can't imagine a situation where the old behaviour was better - since we already wiped the FDM and control state regardless.


At one point we decided that it would be useful to reset the aircraft position to someplace else while running FlightGear. JSBSim was modified so if it sensed that any of the position properties where changed it would retrim to those values. This was a start, but the problem was that we were using the same set of properties to report fdm position/orientation as we were using to request a change. This turned out to be a little hard to work with, especially if you wanted to change several parameters ... you got reset 1 time for each parameter you changed.

So somewhere along the line we came up with a /presets property tree. The idea is that you can fill the tree with all the preset pameters you want to set. Then call for either an on-ground reset or an in-air reset.

I think the approach itself is very sound, however, it's the implimentation spread across a couple different FDM's and a lot of various code changes that has become a bit complicated.

There's a /sim/presets area in the property manager which is where all the FDM initial conditions can be batched up. Things like:

  • airport-id (i.e. KSFO)
  • runway (i.e. 1R)
  • offset-distance (i.e. 7 miles out)
  • altitude (i.e. 2000')
  • glideslope (i.e. on a 3 degree glide slope)
  • airspeed (i.e. 90 kts)

We setup a facility to define initial conditions in the /sim/presets property tree. This way we can setup our position *request* without needed to change the actual current position. This currently isn't setup to accept an initial pitch, but as far as I know the individual FDM's aren't either.

You can set altitude, heading, speed (see --vc=kts option) as well as various offsets to runways and navaids.

You can set any or all of these and when you are satisfied, choose the Presets->Commit menu option (or its corresponding fgcommand).

Please note that there is a lot of complexity in this task and a lot of interdependencies with other pieces of the program. We might be able to hide or move or rearrange the complexity, but it's always going to be a little tricky.

The way this was intended to work is that if you want to start on the ground, you should set the altitude to -9999. Exposing the raw /sim/presets properties to the end user leaves a lot of room for them to make mistakes.

Under the hood


Cquote1.png It is probably helpful to review the presets code that sorts out all the different preset options depending on the values in this tree. That will give you an idea of what values you should leave empty, and what values to set to -9999.0 (for example) in order to effect the right startup mode. (The logic is a bit complex, so have patience when you work your way through that code.) Note, it appears (as best as I can see) that in air startups are broke and probably haven't worked for a while with JSBSim and YASim.
— Curtis Olson (Jan 26th, 2010). Re: [Flightgear-devel] Setting position via property tree.
(powered by Instant-Cquotes)

Here's my current hypothesis: when FlightGear is reset, some modules are replaced with new ones (the old ones may or may not be deleted, but are never unbound). We end up with all kinds of dangling references, especially (but not exclusively) for bound properties, and eventually things grind to a halt.

If I'm right, the property module makes the crash happen sooner, but the crash *will* happen one way or another, and there are probably some nasty memory leaks in there as well. Remember that reset has always caused occasional unexplained, hard-to-reproduce crashes.

The long-term fix is to finish the cleanup of main.cxx and fg_init.cxx so that all initialization code is moved out to the subsystems, and the subsystems themselves are kept in a single, ordered list so that they can be managed easily and transparently. It should not be

necessary to delete and replace any subsystems on a reset, with the exception of the FDM, since all can adjust their state as required.[1]
— David Megginson

I believe the problems started when developers that didn't 'use the reset function often' started making changes to the 'basic' program flow.

ie this roughly corresponds to the introduction of the BFI

Hopefully once we get 'reset' working again developers will test 'reset' before submitting their changes in the future so we don't repeat this quagmire

IMHO it became a kludge because and ONLY because it was 'ignored' by some in their development efforts and I kept trying to retrofit it back in on top of a program that was being changed rapidly by some who apparently didn't care about the requirements of the 'reset' functionality.

IMHO being able to pause, restart with initial conditions, restart with arbritray conditions is a good < should I say basic > test of a well designed simulation. ie one that is controlable As such IMHO and I realize that this may not be your opinion, getting 'restart' working again AND KEEPING it working is a necessary thing todo.

It shouldn't be that difficult in that it only requires that you return the individual parts of the simulation to their initial conditions. It is a GOOD exercise in that it illustrates the interdependencies of the program by rewarding you with a 'hard crash' if you do not understand them.[2]
— Norman Vine
Cquote1.png There's also more to the problem. If we're restoring a saved flight then everything's fine, since all of the FDM state is already valid. If, on the other hand, we're starting in the air, then we need a general trimming routine like the one Tony wrote for JSBSim and LaRCsim to avoid violent oscillations at startup.[3]
— David Megginson
Cquote1.png I've actually added a general reinit facility for FlightGear subsystems, but most subsystems haven't been modified to support it yet. In time, we should be able to reinitialize anything - 3D models, keyboard bindings, radio frequencies, or even scenery - without stopping the program. [4]
— David Megginson


Unfortunately, while the presets hierarchy brought some benefits, it also broke saving and restoring flights. I think that it's time to consider doing away with the presets hierarchy, and trying something like this:

1. Make an in-memory copy of the property tree that we can revert to when the user wants to reset; we could even keep a stack of reset points, if that was useful to anyone.

2. Add a few /sim/startup properties to indicate what information should be used for position, orientation, etc. For example,

  • /sim/startup/init/position-type : (latlon,airport,navaid,runway)
  • /sim/startup/init/altitude-type : (msl,agl,glidepath)
  • /sim/startup/init/orientation-type : (rph,runway)
  • /sim/startup/init/time-type : (utc,local,sunpos)
I'm sure that people can think of a better classification. From this point on, then, our initialization code can simply look at these to decide whether to initialize based on the airport, etc.[5]
— David Megginson

Cquote1.png Write the initial conditions directly into the main property tree. We would need to hold onto a few properties to say which setting to use (say, for location), but this system in general should work much better, since cannot predict what properties any given vehicle might need to preserve on a reset. Essentially, a reset is nothing more than an in-memory save/restore.[6]
— David Megginson

I think that we can do that more cleanly by allowing operation on a second property tree. Here's what I'm suggesting:

1. Set up the initial property tree (from preferences, the command line, etc.) before running any cycles. 2. Make a deep copy of that tree that can be restored. With a reset: you should end up with exactly what you started with.

We can provide fgcommands for partial copies from the backup tree -- in that case, it is simply a matter of a few bytes of XML glue (menu, keyboard, etc.) for each kind of reset.[7]
— David Megginson
Cquote1.png Yes, reset and save/restore are a bit broken in FlightGear right now. I'll try to fix them when I have a chance, but it will require a bit of refactoring (removing Curt's initial-state stuff, for example).[8]
— David Megginson
Cquote1.png I suspect the sensible thing to do would be to define
  • a reset function, and
  • a locate (or relocate) function, separate from reset.

That way the reset function could make a structured reference to the locate function if it wants to ... while other folks could call the locate function without getting mixed up with all the

other reset-related functionality.[9]
— John Denker

Cquote1.png Physics says it ought to work: I start out (on the ground or

in the air) with a reasonable power setting and reasonable trim settings, I can give myself a new altitude, a new XY position, a new heading, and/or a new airspeed ... and it just works. Try it sometime.

The garbage-in-garbage-out principle applies: If you relocate yourself into the air before starting the engines, you'll have a few moments of excitement dealing with the consequences. Similarly, if you dictate a new airspeed that is inconsistent with your elevator trim setting, you'll get some additional excitement.

It should be particularly obvious that air-to-air relocation

should just work. Air "here" looks a lot like air "there".[10]
— John Denker
  1. David Megginson (Wed, 05 Jun 2002 08:00:36 -0700). Crash on "Reset" function..
  2. Norman Vine (Wed, 05 Jun 2002 15:48:34 -0700). Crash on reset.
  3. David Megginson (Mon, 18 Nov 2002 14:44:41 -0800). Presets menu.
  4. David Megginson (Fri, 24 Jan 2003 04:41:29 -0800). GUI.
  5. David Megginson (Fri, 19 Sep 2003 13:07:52 -0700). Beyond presets.
  6. David Megginson (Mon, 24 Nov 2003 08:50:37 -0800). Re: Helicopters: wow!.
  7. David Megginson (Mon, 24 Nov 2003 08:50:37 -0800). Re: Helicopters: wow!.
  8. David Megginson (Mon, 24 Nov 2003 07:22:13 -0800). Re: Helicopters: wow!.
  9. John Denker (Sun, 07 Jan 2007 09:20:14 -0800). location-in-air.
  10. John Denker (Sun, 07 Jan 2007 10:54:48 -0800). location-in-air.