Board index FlightGear Development New features

Automated Checklist Execution

Discussion and requests for new features. Please note that FlightGear developers are volunteers and may or may not be able to consider these requests.

Automated Checklist Execution

Postby sanhozay » Fri May 01, 2015 9:27 am

As part of the development of the Lockheed 1049h Constellation, I created a comprehensive set of checklists based on the crew operating manual with other items added sufficient to take the aircraft through all stages of flight. Rather than hand-code an autostart script I wrote a more generic script to run checklist bindings in sequence. This script is now available in FGDATA and can be used on other aircraft:

Wiki: Automated Checklist Execution

If you are thinking about writing an autostart menu, you might want to consider using this script and driving the autostart from the checklists. It's not restricted to autostart, you can essentially run any sequence of checklists from any piece of Nasal code.

You can see the script in action in the latest Lockheed 1049h. Note that you need a recent copy of FGDATA for this to work. The autostart in this case is intelligent enough to run different checklist sequences depending on whether you are starting on a runway, at the terminal or in the air and also uses automated checklist execution to run an "After Landing" checklist from a keyboard shortcut during that busy time of rollout and taxi.
sanhozay
 
Posts: 1207
Joined: Thu Dec 26, 2013 12:57 pm
Location: EGNM
Callsign: G-SHOZ
Version: Git
OS: Ubuntu 16.04

Re: Automated Checklist Execution

Postby Hooray » Fri May 01, 2015 5:39 pm

I've been looking at the implementation of some the checklists involved here, and I think it would be a good idea to localize any custom Nasal blocks, and instead introduce custom fgcommands using the addcommand() API - basically the reason being that there could be an aircraft-specific API using fgcommands for starting engines, instead of having aircraft-specific "Nasal blobs" in each checklist file. A while ago, this was actually discussed on the devel list, too. In other words, an "fgcommand" (implemented in Nasal) would help better isolate checklists from aircraft specifics.

For instance, here's a common snippet of code that could be easily generalized, and provided, as a custom fgcommand:

http://sourceforge.net/p/flightgear/fga ... ngines.xml
Code: Select all
        setprop("controls/engines/engine[1]/starter", 1);
        var t = maketimer(3.0, func {
          setprop("controls/engines/engine[1]/starter", 0);
        });
        t.singleShot = 1;
        t.start()


This is basically boilerplate code that is found in a few other places, with only the "index" being different for each engine obviously.
So I would suggest to establish a best practice and introduce/register a dedicated fgcommand for such generic snippets, and use properties for parameterizing those: http://wiki.flightgear.org/Nasal_librar ... mand.28.29

The other concern here being that we want to fully support reset/re-init and saving/loading flights at some point, as well as switching aircraft sooner or later. So it does make sense to generalize checklists and get rid of any non-generic Nasal snippets, and introduce "fgcommands" as the shim layer in between aircraft specifics and checklists.

A simple function generator could be used for creating the corresponding helper functions automatically:

Code: Select all
var func = makeEngineStarterCb = func(index) {

return func() {
        var node = "controls/engines/engine[" ~ index ~ "]/starter";
        setprop(node, 1);
        var t = maketimer(3.0, func {
          setprop(node, 0);
        });
        t.singleShot = 1;
        t.start()
};
}


which would mean that aircraft specific APIs would live in the aircraft namespace, and would not need to be part of the checklists themselves, i.e. those could simply be referring to an "abstract" fgcommand instead:

Code: Select all
addcommand("aircraft.startEngine0", makeEngineStarterCb(index:0));
addcommand("aircraft.startEngine1", makeEngineStarterCb(index:1));


Which translates into less work for people wanting to reuse/maintain existing checklists, because aircraft specific code would live in *.nas files, while checklists would primarily contain fgcommands as "pointers" for functionality maintained elsewhere - as can be seen, such a checklist should be pretty straightforward to port to other aircraft, too - even without adding tons of spaghetti code to the checklist.xml files.

Basically, if we want to ensure that checklists become the foundation for enforcing the DRY-principle, we need to ensure that they're mostly aircraft-agnostic and ideally "declarative", i.e. contain as little hard-coded Nasal assumptions as possible, and delegate such stuff to aircraft specific Nasal modules.
Please don't send support requests by PM, instead post your questions on the forum so that all users can contribute and benefit
Thanks & all the best,
Hooray
Help write next month's newsletter !
pui2canvas | MapStructure | Canvas Development | Programming resources
Hooray
 
Posts: 12707
Joined: Tue Mar 25, 2008 9:40 am
Pronouns: THOU

Re: Automated Checklist Execution

Postby sanhozay » Sat May 02, 2015 10:13 am

Thanks for those suggestions. I'll play around with those ideas.

Writing checklists is a mind-numbing process (and I pay tribute to Mark Kraus, who did most of the leg work on the Connie, allowing me to restructure and extend using the crew operating manual). Externalizing nasal bindings would certainly help a little but the real barrier to the DRY principle is the way the checklist XML is structured. This is not a criticism of that, because I think the checklist system is great, it's just an observation ...

Consider landing lights as the worst example. They are off, then on for takeoff, then off, then on for landing, then off again. These don't need Nasal bindings, just property-assign, but as things stand have to be written five times. The marker section is boilerplate, and the bindings and conditions are boilerplate for two states: off or on. The Connie has 250 lines of XML just for landing lights. I could reduce that by making fgcommands ("landing_lights_off", "landing_lights_on"), but the markers are still repeated. I guess I could also make additional properties to deal with the conditions but these have to be computed at a sensible rate because they are only used for checklists.

I did tinker around with a Groovy DSL which went something like this:

Code: Select all
declare ON value 1
declare OFF value 0

with ("controls/lighting") {
    define "Landing Lights" properties: ["landing-left", "landing-right", "landing-extend-left", "landing-extend-right"]
    define "Beacon" properties: ["beacon"]
}

mark landing_lights at: [0.1234, 0.1234, 0.1234, 2.0]
mark beacon at: [0.2234, 0.2234, 0.2234]

checklist("Before Starting Engines") {
    check landing_lights set OFF
    check beacon set OFF
}

checklist("Before Takeoff") {
    check landing_lights set ON
}

...

checklist("After Landing") {
    check landing_lights set OFF
}

It spat out a frightening amount of nicely formatted XML (with all the markers, conditions and bindings) but it started to stretch the capabilities of a Groovy DSL when it came to working with the different conditions and bindings. My idea was to have standard definitions of lights and so on that were included from another DSL script, so the aircraft-specific stuff would be the markers and the checklists and overrides of standard definitions, e.g. for the Connie it has these extendable landing lights.

So I hit a brick wall and put it to one side. I still think it's a good idea, not just for checklists but also for property rules. The XML representation is very verbose for all these types of things.
sanhozay
 
Posts: 1207
Joined: Thu Dec 26, 2013 12:57 pm
Location: EGNM
Callsign: G-SHOZ
Version: Git
OS: Ubuntu 16.04

Re: Automated Checklist Execution

Postby Hooray » Sat May 02, 2015 2:06 pm

The Groovy DSL idea looks interesting - and I guess Philosopher would love to learn more about this (him being intimately familiar with Nasal internals and "meta programming" using fancy Nasal constructs to create DSLs).

A while ago, I actually came up with a UI for creating wizards in a declarative fashion, a system which would also work for creating checklists in a semi-automated fashion - and using the new Canvas UI, it would even be much more flexible:

http://wiki.flightgear.org/Aircraft_Generation_Wizard
Image

I am only mentioning this, because this ended up using some of Andy Ross'es code for template based coding, analogous to how php files may contain html and php constructs for templating stuff - which is how the dialog above is created, i.e. treated as a PropertyList-encoded XML file that happens to contain Nasal sections that are evaluated before the dialog is "created" - which basically means that a little template can be used to create arbitrary combinations of wizard "pages". This was all based on Andy's code integrating Nasal as an apache module, as per the demo at: https://github.com/andyross/nasal/blob/ ... /test.nhtm and the underlying Nasal handling code at: https://github.com/andyross/nasal/blob/ ... andler.nas

Like you say, supporting something like that would be really useful in quite a few places, and would not add any performance-critical code, because it's mainly about template coding, i.e. the PropertyTree will just be procedurally created based on using a handful of Nasal constructs, which should be useful for redundant markup
Please don't send support requests by PM, instead post your questions on the forum so that all users can contribute and benefit
Thanks & all the best,
Hooray
Help write next month's newsletter !
pui2canvas | MapStructure | Canvas Development | Programming resources
Hooray
 
Posts: 12707
Joined: Tue Mar 25, 2008 9:40 am
Pronouns: THOU

Re: Automated Checklist Execution

Postby sanhozay » Sun May 03, 2015 1:21 pm

OK, I've externalized the engine start into a Nasal file:

Code: Select all
var start_selected_engine = func()
{
    var selected = getprop("controls/switches/engine-start-select") or 0;
    if (selected < 1 or selected > 4) return;

    var engines = props.globals.getNode("controls/engines");
    var engine = engines.getChild("engine", selected - 1);
    var starter = engine.getNode("starter");

    starter.setValue(1);
    var t = maketimer(3.0, func {
        starter.setValue(0);
    });
    t.singleShot = 1;
    t.start()
}

I don't need a function generator because the starter should fire on the selected engine, based on the starter select.

Clearly, this improves the maintainability of the checklist because the engine start function is defined in one place instead of four but I'm not seeing a particular advantage with making a command. I can have:

Code: Select all
addcommand("Lockheed1049h.start-selected-engine", start_selected_engine);

and
Code: Select all
<binding>
  <command>Lockheed1049h.start-selected-engine</command>
</binding>

Or I can use a Nasal binding that just calls the function:

Code: Select all
<binding>
  <command>nasal</command>
  <script>Lockheed1049h.start_selected_engine();</script>
</binding>

Am I missing something in terms of the advantage of a command as opposed to calling the function? If I wanted to pass parameters to the function, it would be easier using the function than the command.
sanhozay
 
Posts: 1207
Joined: Thu Dec 26, 2013 12:57 pm
Location: EGNM
Callsign: G-SHOZ
Version: Git
OS: Ubuntu 16.04

Re: Automated Checklist Execution

Postby Hooray » Sun May 03, 2015 6:10 pm

the command binding above would need to be fixed up/edited to be directly usable elsewhere (other aircraft), whereas a dedicated fgcommand could be aircraft agnostic, and would just need to be re-implemented/provided by a single Nasal file - in other words, it would be possible to make checklists fairly self-contained and generic.

I was really just thinking in terms of code reuse and long term maintenance, so this was more an idea than necessarily a recommendation - with one of the goals being that people can more easily reuse the XML/bindings part of checklists, without those containing tons of Nasal space dependencies, and especially "code blobs".
Please don't send support requests by PM, instead post your questions on the forum so that all users can contribute and benefit
Thanks & all the best,
Hooray
Help write next month's newsletter !
pui2canvas | MapStructure | Canvas Development | Programming resources
Hooray
 
Posts: 12707
Joined: Tue Mar 25, 2008 9:40 am
Pronouns: THOU


Return to New features

Who is online

Users browsing this forum: No registered users and 3 guests