Hi fellow wiki editors!

To help newly registered users get more familiar with the wiki (and maybe older users too) there is now a {{Welcome to the wiki}} template. Have a look at it and feel free to add it to new users discussion pages (and perhaps your own).

I have tried to keep the template short, but meaningful. /Johan G

Difference between revisions of "Howto:Control the route manager in Nasal"

From FlightGear wiki
Jump to: navigation, search
m
(Switch to {{fg root file}} to fix the broken Gitorious link.)
 
(3 intermediate revisions by 2 users not shown)
Line 1: Line 1:
{{Stub}}
 
 
Last updated: 02/2012
 
 
 
This tutorial will document all the steps involved in creating a new Nasal module that constantly updates itself to control the [[Route manager]], [[Nasal]] is FlightGear's scripting language.
 
This tutorial will document all the steps involved in creating a new Nasal module that constantly updates itself to control the [[Route manager]], [[Nasal]] is FlightGear's scripting language.
  
Line 113: Line 109:
 
As you'll see, you could even create a small dialog file to repeatedly set the waypoint automatically to a set of specified coordinates.
 
As you'll see, you could even create a small dialog file to repeatedly set the waypoint automatically to a set of specified coordinates.
  
Just have a look at the implementation of the route manager dialog in $FG_ROOT/gui/dialogs/route-manager.xml: http://gitorious.org/fg/fgdata/blobs/master/gui/dialogs/route-manager.xml
+
Just have a look at the implementation of the route manager dialog in {{fg root file|gui/dialogs/route-manager.xml}}.
  
 
If you are interested, this could be used to create a realistic holding-pattern autoflight system, that even uses proper entry and exit procedures.
 
If you are interested, this could be used to create a realistic holding-pattern autoflight system, that even uses proper entry and exit procedures.
Line 119: Line 115:
  
  
= References =
+
[[Category:Nasal howto]]
 
+
[[Category:Howto]]
+
[[Category:Nasal]]
+

Latest revision as of 14:27, 10 March 2016

This tutorial will document all the steps involved in creating a new Nasal module that constantly updates itself to control the Route manager, Nasal is FlightGear's scripting language.

This tutorial is based on [[Howto: ]], you should fully understand that one first.

A system that constantly updates itself to control the route manager could for example be used to create an entirely scripted flight using Nasal.

When you take a look at the wiki, you'll see that the route manager can be controlled by setting properties: Route manager. The "input" or "control" property is /autopilot/route-manager/input - as you can see by referring to $FG_ROOT/gui/dialogs/route-manager.xml.

So the route manager dialog only provides a convenient interface, you could just as well use the property browser or Nasal directly.

Properties can be set from Nasal using the setprop() command: http://wiki.flightgear.org/Nasal#setprop.28.29

In order to set a property to a certain value/string, you just use a piece of code like the following:

 setprop("/my/property", "value");

Obviously, this needs to be loaded/run or otherwise invoked by fgfs, for example by using the built-in Nasal console.

So you need to set the next/active waypoint for the route manager using setprop:

 var control="/autopilot/route-manager/input";
 setprop(control, next);

Now you need to make sure that the undefined "next" variable actually contains sensible and comprehensible input for the route manager system (see the RM wiki page).

To work with a list of pre-defined coordinates, you could use a Nasal vector: http://wiki.flightgear.org/Nasal#Variables

The following piece of code declares and initializes an empty vector in Nasal:

var coordinates = [];

Now you need to fill in some valid waypoint data (comma separated values):

    var coordinates = ["SAU","OAK","SFO"];

Note that these are not GPS coordinates, but rather identifiers of VORs located near KSFO. But obviously, you could just as well use any other "fixes" supported by the route manager.

If you were to add these continuously to the RM, you would basically be flying a triangle between SAUSALITO VOR, OAKLAND VOR and SAN FRANCISCO VOR

Once you have your vector populated with some data, you can access individual elements by using a numeric INDEX into the vector using square brackets:

VECTOR[INDEX];

For example:

    var coordinates = ["SAU","OAK","SFO"];
    print ( coordinates[0] ); # will print SAU
    print ( coordinates[1] ); # will print OAK
    print ( coordinates[2] ); # will print SFO

Note that indexing starts at 0 and not at 1 !

Next, you would need to register a function that gets called during startup, so that it can keep setting the route manager, this is done using a _setlistener() call: http://wiki.flightgear.org/Nasal#setlistener.28.29

Note that the underscore (_) is important, because the low level function (not he wrapper) must be used here:

   _setlistener("/sim/signals/nasal-dir-initialized", myCode);

To ensure that your code gets called repeatedly, at a fixed rate - you need to use a settimer() call: http://wiki.flightgear.org/Nasal#settimer.28.29


As you can see at http://wiki.flightgear.org/Route_manager_internals there is even direct support for re-sequencing a route by setting the current-waypoint index to a different waypoint number in the route.

    # rm_control.nas (save in $FG_ROOT/Nasal)
    var mycode = func {
      print("running my route manager controller ");
       setprop("/autopilot/route-manager/input", "SFO");
      settimer(mycode, 5); # register a timer, invoke the "mycode" function again after 5 second
    }

    _setlistener("/sim/signals/nasal-dir-initialized", mycode);


When added to $FG_ROOT/Nasal/rm_control.nas, this piece of code will get called at 5 second intervals and keeps adding yet another "SFO" waypoint to the RM route.

Obviously, this is not yet very useful - but when you take another look at http://wiki.flightgear.org/Route_manager_internals#Signals you'll see that the RM system also emits so called "signals" by setting a certain property when specific events (such as route re-sequencing) occur. So you could now register a listener to this property and keep setting the property to the next "position" in the vector:

    # rm_control.nas (save in $FG_ROOT/Nasal)

    var pos = ['SAU','OAK','SFO']; # makes sense to start at KSFO with these defaults
    var index=0;

    var re_sequence = func {
      print("running my route manager controller ");
      setprop("/autopilot/route-manager/input", pos[index] );
      index=index+1;
      if (index > 2) index = 0; # reset index to 0 (wrap around)
    }

    _setlistener("/sim/signals/nasal-dir-initialized", re_sequence );
    _setlistener("/autopilot/route-manager/signals/sequenced", re_sequence);

To actually fly the "route", you obviously need to activate the route manager (from code, or by using the RM GUI dialog).

As you'll see, you could even create a small dialog file to repeatedly set the waypoint automatically to a set of specified coordinates.

Just have a look at the implementation of the route manager dialog in $FG_ROOT/gui/dialogs/route-manager.xml.

If you are interested, this could be used to create a realistic holding-pattern autoflight system, that even uses proper entry and exit procedures.