Board index FlightGear Development Nasal

Event Management module for post 3.2

Nasal is the scripting language of FlightGear.

Event Management module for post 3.2

Postby Hooray » Thu Jun 12, 2014 4:59 pm

galvedro wrote:For this first "drop" I didn't design the trigger engine to be usable by other sim systems. Actually, it was only after I evolved the design to what it is today, and I read about the missions/adventures, that I realized that the Failure Manager was not much more than a generic Event/Trigger loop and some decorations. :oops:

I don't know what Philosopher has in mind for the NavDisplay, but I am pretty sure that we can do something that works for both systems, AND missions/adventures, AND AI agents, AND you name it :D

I would suggest to have a discussion to see what is needed and target that for 3.3. We can certainly take part of my code as a starting point, but we should now start to focus on stabilizing the features we already have, I think.


Currently, the ND code is fairly simple: it's just a foreach() loop that is iterating through a hash with a handful of fields that run predicates and some true() false() callbacks based on the result of the predicate() run. That is how most ND layers and groups/elements are updated. It is a rather simple and even crude method, but at least it allows us to easily keep certain ND logic separate.

Originally, the whole thing was to be found in $FG_ROOT/Nasal/canvas/map/navdisplay.mfd - there's some kind of monster hash at the top of the file that contains fields for each element of the ND (except for stuff that is still explicitly handled by the update() method that Gijs, Hyde and Soitanen have been adding to. Recently, we've moved this hash to "navdisplay.styles". I am not in any way attached to this setup, I just wanted to establish the separation here - I don't care if the hash stays or goes away, or if I have to use a sed script to turn it into a fancy XML file.

For the ND, my mid-term goal is to identify the main building blocks required to allow people easily customizing the existing ND, but also use it as a "template" for new NDs, i.e. specific to certain aircraft. We arrived at the hash-based setup simply because it was straightforward and it allowed non-coders to easily add new features without having to "grok" the full thing. In a primitive way, it is very much intended to work like a plugin/module system: add a new hash, understand a handful of fields, and people can easily add new features to the ND or change styling/fonts etc.

Conceptually, this really means that we only need to encapsulate the concept of having "predicates" that can be also triggered via timers/listeners, possibly in a chained fashion - very much like a simple state machine framework, where callbacks may trigger other callbacks based on some evaluated condition.

Extracting this functionality would allow us to use such a module in a variety of places, including missions/adventures, but also the ND and MapStructure code.
And I am very motivated to see this generalized, so will be glad to adopt such a framework in the ND/MS code.
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: 11326
Joined: Tue Mar 25, 2008 8:40 am

Re: Event Management module for post 3.2

Postby galvedro » Fri Jun 13, 2014 11:59 am

I still need to see the ND code to see how you have it set up, but I will dump some thoughts right away.

The failure manager currently manages two types of triggers: synchronous and asynchronous. Synchronous triggers need a polling loop which the failure manager provides. The FM asks triggers every 10s "have you fired?", the trigger checks its conditions and respond "yes" or "no". Simple thing. If I understood correctly, this sounds pretty similar to the predicate evaluation loop you talk about.

Asynchronous triggers provide the necessary mechanisms to detect the fire condition by themselves, so the poll loop is not needed. They use listeners and/or timers internally, so they take the initiative and notify when they fire. Needless to say, these are better for performance and more scalable.

I extract two conclussions from my experience with the failure manager:

1. It is of course preferable to write async triggers whenever possible, and it is often possible but perhaps difficult.
2. Checking for arbitrary conditions in the property tree is not easy to accomplish asynchronously and usually requires polling (think speed, altitude, position, fuel levels, etc). I poll every 10s to keep the load low, but I would prefer triggers to fire as soon as the right conditions are met.

If we are thinking in a framework that could be used globaly by different systems, I think we should evaluate the option of extending the timers/listeners framework, perhaps creating a unified interface for all of them. After all, a timer is a "timeout trigger", a listener is a "property access trigger", an AltitudeTrigger is a "property in range trigger", etc...

A combined approach, providing low level support in the core and an abstraction on top in Nasal could work well for this. Low level, performance critical stuff like polling the proptree would be done down in the core, and Nasal would be involved in higher level semantics that do not impact performance as much.
galvedro
 
Posts: 145
Joined: Mon Oct 07, 2013 12:55 pm
Location: Sweden

Re: Event Management module for post 3.2

Postby Hooray » Fri Jun 13, 2014 12:14 pm

galvedro wrote in Fri Jun 13, 2014 11:59 am:I still need to see the ND code to see how you have it set up, but I will dump some thoughts right away.


Originally, it was a single monolithic update() method that would basically be called at frame rate using a settimer/maketimer callback.
When things were restructured, the conditional parts of this huge method were moved into predicates that reside in a huge hash: https://gitorious.org/fg/fgdata/source/ ... styles#L14
Meanwhile, the update() method has been inflated again due to some logic that wasn't added to the hash, e.g. see: https://gitorious.org/fg/fgdata/source/ ... y.mfd#L476

The meat of it still is in update(), and those "layers" are fairly boring meanwhile because they're separately managed by Philosopher's MapStructure framework.

But individual ND elements (canvas groups) are basically SVG-driven, i.e. SVG elements that are looked up and then updated/animated via timers and listeners: https://gitorious.org/fg/fgdata/source/ ... tyles#L183

The actual code evaluating each SVG predicate is still called via the update() method, but it's just a foreach loop with a few lines:
https://gitorious.org/fg/fgdata/source/ ... d#L760-769

None of this is set in stone, and we're actually looking forward to generalizing this some more.

If we are thinking in a framework that could be used globaly by different systems, I think we should evaluate the option of extending the timers/listeners framework, perhaps creating a unified interface for all of them. After all, a timer is a "timeout trigger", a listener is a "property access trigger", an AltitudeTrigger is a "property in range trigger", etc...

that sounds like a good idea, and it touches ideas that Zakalawe once raised regarding "listener objects": viewtopic.php?f=30&t=21185

A combined approach, providing low level support in the core and an abstraction on top in Nasal could work well for this. Low level, performance critical stuff like polling the proptree would be done down in the core, and Nasal would be involved in higher level semantics that do not impact performance as much.

Yes, sounds like something where cppbind should come in very handy - certainly worthwhile to explore post 3.2 :D
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: 11326
Joined: Tue Mar 25, 2008 8:40 am

Re: Event Management module for post 3.2

Postby Hooray » Fri Jun 13, 2014 2:10 pm

If we are thinking in a framework that could be used globaly by different systems, I think we should evaluate the option of extending the timers/listeners framework, perhaps creating a unified interface for all of them. After all, a timer is a "timeout trigger", a listener is a "property access trigger", an AltitudeTrigger is a "property in range trigger", etc...


FWIW:

Subject: Calculating pitch angle for V/S - <atan> explresion
Torsten wrote:There is no such thing like
if /some/property greaterthan 180 or /some/property lessthan -180 then
writetoconsole "property /some/property out of bounds"
endif

We have a feature request to implement this on a global scope to properties itself, not limited to the A/P system. But I'm a little stuck with some issues/questions while implementing this and put it in my backlog for now.

What you can do for input and output properties representig periodic values (like heading) is to normalize them into a given range:
Code: Select all
  <periodic>
     <min>-180</min>
     <max>180</max>
  </periodic>

will transform a value of -190 to +170 for example. But that's probably not what you asked for.
You can clamp output values by adding <min> and/or <max> elements. But I don't think, that's what you asked for, too ;-)
Torsten
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: 11326
Joined: Tue Mar 25, 2008 8:40 am


Return to Nasal

Who is online

Users browsing this forum: No registered users and 2 guests