Board index FlightGear Development Nasal

Nasal based Independant Ramp Marshall

Nasal is the scripting language of FlightGear.

Nasal based Independant Ramp Marshall

Postby omega95 » Tue Aug 06, 2013 6:41 am

Hey, I've been working on a ramp marshall script (currently, it only moves 1 ramp marshall) - see the video below. :)

(Note that the ramp marshall is a modification of waldo from the bluebird - I redressed him, modeled a headset and glow sticks)

Early Development Animation Test


Aircraft Guidance Test at WSSS B8


That was a prototype only to test the general script and the animations. I'm working on a larger system similar to the animated jetways (but that looked like it had a lot of unecessary code in it) to generalize this and make the animations independant. I made some progress and had a lot of questions but figured them out myself so far. I suppose I could ask more questions here then?

Oh, and how exactly can I (would you want to have this?) add this to fgdata for the next release? So far, it only works with the WSSS Airport I'm working on, but with this system completed, you should be able to place the marshalls anywhere (at any airport) using the ufo and use a converter script to convert the stg into the xml file that contains the data. :)

Lol, I already ran into trouble... Here's the function I wrote that loads the ramps at a given airport from xml file -

Code: Select all
var load_ramps = func(icao) {

   var xml_file = getprop("/sim/fg-root") ~ "/AI/Airports/" ~ icao ~ "/ramps.xml";
   
   var rampsTree = "/airports/"~icao~"/ramps";
   
   setprop(rampsTree~"/loaded", 1); # Set Loaded flag so flightgear doesn't load again
   
   io.read_properties(xml_file, rampsTree);
   if(rampsTree == nil) {return;}
   
   var ramps = props.globals.getNode(rampsTree).getChildren();
   
   foreach(ramp; ramps) {
      # General Runtime XML
      var index = ramp.getIndex();
      var base_model = getprop("/sim/fg-root") ~ "/Models/Airport/Ramp/ramp.xml";
      
      var tmp = ramps.getNode("models",1).getNode("model", 1);
      tmp.getNode("path", 1).setValue(base_model);
      
      var tree = rampsTree ~ "/ramp[" ~ index ~ "]/";
      
      var params = tmp.getNode("overlay", 1).getNode("params", 1);
      params.getNode("left-arm-x", 1).setValue(tree~"left-arm-x");
      params.getNode("left-arm-outer-x", 1).setValue(tree~"left-arm-outer-x");
      params.getNode("left-arm-z", 1).setValue(tree~"left-arm-z");
      params.getNode("right-arm-x", 1).setValue(tree~"right-arm-x");
      params.getNode("right-arm-outer-x", 1).setValue(tree~"right-arm-outer-x");
      params.getNode("right-arm-z", 1).setValue(tree~"right-arm-z");
      params.getNode("toggle-ramp-marshall-script").setValue("ramp.toggle_marshall(" ~ index ~ ");");
      
      var model_path = getprop("/sim/fg-home") ~ "/state/ramp-" ~ index ~ ".xml";
      
      io.write_properties(model_path, tmp.getPath());
      
      # Add model to FlightGear
      addModel(model_path, ramp.getNode("latitude-deg").getValue(), ramp.getNode("longitude-deg").getValue(), ramp.getNode("altitude-m").getValue(), ramp.getNode("heading-deg").getValue());
   }

}


I get the error: non-objects have no members at this line - var tmp = ramps.getNode("models",1).getNode("model", 1);
I'm not very familiar with the props class, I just looked at it from plausible.org earlier today. I was wondering how I can get/create the tree "/airports/WSSS/ramps/models/model/" and put the limb positions and toggle script in there.

Thanks a lot!
Merlion Virtual Airlines - the experience of a flight time...
Get high quality aircraft, airports, video tutorials or development tools from my hangar.
omega95
 
Posts: 1222
Joined: Sat Jul 30, 2011 1:59 am
Location: -unknown-
Callsign: MIA0001, OM-EGA
IRC name: omega95
Version: 2.12 git
OS: Ubuntu 13.04

Re: Nasal based Independant Ramp Marshall

Postby Flyer159 » Tue Aug 06, 2013 8:58 am

Wooooow, it looks great! Keep works on that!
Wiktor
Arminair VA
http://arminair.tk
ARA02xx

------------------
"There is no sport equal to that which aviators enjoy while being carried through the air on great white wings". - Wilbur Wright
User avatar
Flyer159
 
Posts: 42
Joined: Mon Jan 21, 2013 12:06 am
Location: Lodz, Poland (EPLL)
Callsign: SP-VIC or VIC1590
Version: 2.8.0.5
OS: Windows 7/8

Re: Nasal based Independant Ramp Marshall

Postby omega95 » Tue Aug 06, 2013 11:24 am

Alright, so I finshed a basic working version. (Need to test with a few more - only testing with 1 instance so far) It gets the data from an xml (if it exists) and creates xmls for the animations (most of the animations are in a single file though - the files created at runtime only have property alias params) and loads them accordingly.

Here's the nasal script.

I was hoping someone *cough* Hooray *cough* could clean it up for me and teach me something new today. :mrgreen:

Code: Select all
var closestAirport = func() {
   return getprop("/sim/airport/closest-airport-id");
};

var ramp_pos = geo.Coord.new();

var M2NM = 0.0005399568;
var NM2M = 1852;

var ramp_dist = getprop("/sim/model/ramp/x-m");
var ramp_class = getprop("/sim/model/ramp/class");
if (ramp_dist == nil) {
ramp_dist = -14;
}
if (ramp_class == nil) {
ramp_class = 3;
}

# RAMP CLASS CODES
## 0 - 747, 777-300, 787-9
## 1 - A330-300, 777-200
## 2 - A330-200, 787-8
## 3 - A320, 737, General

ramp_classes = [0,0.5,0.85,1.72];

ramp_dist = -(ramp_dist - ramp_classes[ramp_class]);

# Mathematical Heading Operations
var addHdg = func(hdg, add) {
   var result = hdg + add;
   if(result>360) {
      result = result - 360;
   }
   return result;
}

var subHdg = func(hdg, diff) {
   var result = hdg - diff;
   if(result<0) {
      result = 360 - result;
   }
   return result;
}

var getDeviation = func(hdg, target) {
   var deviation = target - hdg;
   if(deviation < -180) {
      deviation = 360 - deviation;
   } elsif(deviation > 180) {
      deviation = deviation - 360;
   }
   return deviation;
}

# Smooth Property Animation
var animate = func(prop, target, rate) { # Rate is in deg/sec
   
   var delta_sec = getprop("/sim/time/delta-sec");
   if(rate == nil) {
      rate = 50;
   }
   if(delta_sec == nil) {
      delta_sec = 0.1;
   }
   
   var value = getprop(prop);
   if(math.abs(value-target) > rate*delta_sec) {
      if(value < target) {
         setprop(prop, value + rate*delta_sec);
      } else {
         setprop(prop, value - rate*delta_sec);
      }
   } else {
      if(value != target) {
         setprop(prop, target);
      }
   }
   
}

# Positions
## Template => pos_name : {lA_x:, lA_z:, lAO_x:, rA_x:, rA_z:, rAO_x:}

var pos = {
   rest: {lA_x:80, lA_z:0, lAO_x:0, rA_x:-80, rA_z:0, rAO_x:0},
   stop: {lA_x:-55, lA_z:0, lAO_x:-70, rA_x:55, rA_z:0, rAO_x:70},
   fwd_out: {lA_x:0, lA_z:-90, lAO_x:-30, rA_x:0, rA_z:90, rAO_x:30},
   fwd_in: {lA_x:0, lA_z:-90, lAO_x:-120, rA_x:0, rA_z:90, rAO_x:120},
   left_in: {lA_x:0, lA_z:0, lAO_x:-120, rA_x:0, rA_z:0, rAO_x:0},
   left_out: {lA_x:0, lA_z:0, lAO_x:-30, rA_x:0, rA_z:0, rAO_x:0},
   right_in: {lA_x:0, lA_z:0, lAO_x:0, rA_x:0, rA_z:0, rAO_x:120},
   right_out: {lA_x:0, lA_z:0, lAO_x:0, rA_x:0, rA_z:0, rAO_x:30}
   
};

# Return current position values
var get_pos_values = func(ramp_tree) {
   
   var m = {
   
      lA_x: getprop(ramp_tree~"left-arm-x"),
      lA_z:  getprop(ramp_tree~"left-arm-z"),
      lAO_x: getprop(ramp_tree~"left-arm-outer-x"),
      rA_x: getprop(ramp_tree~"right-arm-x"),
      rA_z: getprop(ramp_tree~"right-arm-z"),
      rAO_x: getprop(ramp_tree~"right-arm-outer-x")
   };
   
   return m;

};

var check_pos = func(ramp_tree, target) {

   var position = get_pos_values(ramp_tree);
   
   if((position.lA_x == target.lA_x) and (position.lA_z == target.lA_z) and (position.lAO_x == target.lAO_x) and (position.rA_x == target.rA_x) and (position.rA_z == target.rA_z) and (position.rAO_x == target.rAO_x)) {
      return 1;
   } else {
      return 0;
   }

};

var full_animate = func(ramp_tree, pos_hash, rate) {
   animate(ramp_tree~"left-arm-x",pos_hash.lA_x , rate);
   animate(ramp_tree~"left-arm-z",pos_hash.lA_z , rate);
   animate(ramp_tree~"left-arm-outer-x",pos_hash.lAO_x , rate);
   animate(ramp_tree~"right-arm-x",pos_hash.rA_x , rate);
   animate(ramp_tree~"right-arm-z",pos_hash.rA_z , rate);
   animate(ramp_tree~"right-arm-outer-x",pos_hash.rAO_x , rate);
};

var addModel = func(path, lat, lon, alt, hdg) {

   # Derived from jetways.nas

   var models = props.globals.getNode("/models");
   var model = nil;
   for(var i=0; 1; i+=1) {
      if(models.getChild("model", i, 0) == nil) {
         model = models.getChild("model", i, 1);
         break;
      }
   }
   
   var model_path = model.getPath();
   model.getNode("path", 1).setValue(path);
   model.getNode("latitude-deg", 1).setDoubleValue(lat);
   model.getNode("latitude-deg-prop", 1).setValue(model_path ~ "/latitude-deg");
   model.getNode("longitude-deg", 1).setDoubleValue(lon);
   model.getNode("longitude-deg-prop", 1).setValue(model_path ~ "/longitude-deg");
   model.getNode("elevation-ft", 1).setDoubleValue(alt * M2FT);
   model.getNode("elevation-ft-prop", 1).setValue(model_path ~ "/elevation-ft");
   model.getNode("heading-deg", 1).setDoubleValue(hdg);
   model.getNode("heading-deg-prop", 1).setValue(model_path ~ "/heading-deg");
   model.getNode("pitch-deg", 1).setDoubleValue(0);
   model.getNode("pitch-deg-prop", 1).setValue(model_path ~ "/pitch-deg");
   model.getNode("roll-deg", 1).setDoubleValue(0);
   model.getNode("roll-deg-prop", 1).setValue(model_path ~ "/roll-deg");
   model.getNode("load", 1).remove();
   return model;

};

var load_ramps = func(icao) {

   var xml_file = getprop("/sim/fg-root") ~ "/AI/Airports/" ~ icao ~ "/ramps.xml";
   
   var rampsTree = "/airports/"~icao~"/ramps";
   
   setprop(rampsTree~"/loaded", 1); # Set Loaded flag so flightgear doesn't load again
   
   io.read_properties(xml_file, rampsTree);
   if(rampsTree == nil) {return;}
   
   var ramps = props.globals.getNode(rampsTree).getChildren();
   
   foreach(ramp; ramps) {
      # General Runtime XML
      var index = ramp.getIndex();
      var base_model = getprop("/sim/fg-root") ~ "/Models/Airport/Ramp/ramp.xml";
      
      var tmps = props.globals.getNode(rampsTree ~ "/models", 1);
      var tmp = tmps.getChild("model", 0, 1);
      tmp.getNode("path", 1).setValue(base_model);
      
      var tree = rampsTree ~ "/ramp[" ~ index ~ "]/";
      
      setprop(tree~"left-arm-x", pos.rest.lA_x);
      setprop(tree~"left-arm-z", pos.rest.lA_z);
      setprop(tree~"left-arm-outer-x", pos.rest.lAO_x);
      setprop(tree~"right-arm-x", pos.rest.rA_x);
      setprop(tree~"right-arm-z", pos.rest.rA_z);
      setprop(tree~"right-arm-outer-x", pos.rest.rAO_x);
      setprop(tree~"function", "rest");
      
      var params = tmp.getNode("overlay", 1).getNode("params", 1);
      params.getNode("left-arm-x", 1).setValue(tree~"left-arm-x");
      params.getNode("left-arm-outer-x", 1).setValue(tree~"left-arm-outer-x");
      params.getNode("left-arm-z", 1).setValue(tree~"left-arm-z");
      params.getNode("right-arm-x", 1).setValue(tree~"right-arm-x");
      params.getNode("right-arm-outer-x", 1).setValue(tree~"right-arm-outer-x");
      params.getNode("right-arm-z", 1).setValue(tree~"right-arm-z");
      params.getNode("toggle-ramp-marshall-script", 1).setValue("ramp_marshall.toggle_marshall(" ~ index ~ ");");
      
      var model_path = getprop("/sim/fg-home") ~ "/state/ramp-" ~ index ~ ".xml";
      
      io.write_properties(model_path, tmps.getPath());
      
      var ramp_path = rampsTree ~ "/ramp[" ~ index ~ "]/";
      
      # Add model to FlightGear
      addModel(model_path, getprop(ramp_path~"latitude-deg"), getprop(ramp_path~"longitude-deg"), getprop(ramp_path~"altitude-m"), getprop(ramp_path~"heading-deg"));
   }

};

var toggle_marshall = func(id) {

   var activeRamp = getprop("/airports/active-ramp");
   var rampEnable = getprop("/airports/enable-ramp");
   
   if(rampEnable == 0) {
      var ramp_dat = "/airports/"~closestAirport()~"/ramps/ramp["~id~"]/";
      ramp_pos.set_latlon(getprop(ramp_dat~"latitude-deg"), getprop(ramp_dat~"longitude-deg"));
      setprop("/airports/active-ramp", id);
      setprop("/airports/enable-ramp", 1);
   } else {
      if(activeRamp == id) {
      setprop("/airports/enable-ramp", 0); # Disable Ramp
      } else {
         var ramp_dat = "/airports/"~closestAirport()~"/ramps/ramp["~id~"]/";
         ramp_pos.set_latlon(getprop(ramp_dat~"latitude-deg"), getprop(ramp_dat~"longitude-deg"));
         setprop("/airports/active-ramp", id);
      }
   }

};

# Main Loop
var main_loop = {
   init : func {
      me.UPDATE_INTERVAL = 0.01;
      print("Initialized Ramp Marshall Script");
      me.function = getprop("rest");
      setprop("/airports/active-arpt", closestAirport());
      setprop("/airports/active-ramp", 0);
      setprop("/airports/enable-ramp", 0);
      me.phase = 0;
      me.loopid = 0;
      me.reset();
},
   update : func {
   
   # Check if ramps are loaded at the nearest airport
   
   if(getprop( "/airports/"~closestAirport()~"/ramps/loaded") == nil) {
      load_ramps(closestAirport());
      setprop("/airports/active-arpt", closestAirport());
   }
   
   var activeRamp = getprop("/airports/active-ramp");
   
   var ramp_tree = "/airports/"~closestAirport()~"/ramps/ramp["~activeRamp~"]/";
   
   # If a ramp is enabled, run the function to guide the pilot
   
   if(getprop("/airports/enable-ramp") == 1) {
   
      if(me.function != getprop(ramp_tree~"function")) {
         me.function = getprop(ramp_tree~"function");
         me.phase = 0;
      }
      
      var ac_pos = geo.aircraft_position();
      var heading = getprop("/orientation/heading-deg");
   
      var ngear = ac_pos;   
      ngear.apply_course_distance(heading, ramp_dist*M2NM);
   
      var dist_to_ramp = ngear.distance_to(ramp_pos);
   
      setprop(ramp_tree~"dist-ramp", dist_to_ramp);
   
      var taxi_course = ngear.course_to(ramp_pos);
   
      var deviation = getDeviation(heading, taxi_course);
   
      setprop(ramp_tree~"deviation", deviation);
   
      if(math.abs(deviation) > 150) {
         setprop(ramp_tree~"function", "imm_stop");
      } elsif(deviation > 1) {
         setprop(ramp_tree~"function", "turn_right");
      } elsif(deviation < -1) {
         setprop(ramp_tree~"function", "turn_left");
      } else {
         if(dist_to_ramp > ramp_dist + 2) {
            setprop(ramp_tree~"function", "move_fwd");
         } elsif(dist_to_ramp > ramp_dist + 0.3) {
            setprop(ramp_tree~"function", "slow_stop");
         } else {
            setprop(ramp_tree~"function", "imm_stop");
         }
      
      }
   
   
      # Ramp Marshall Signals   
   
      if(me.function == "slow_stop") {
         if(me.phase == 0) {
            if(!check_pos(ramp_tree, pos.rest)) {
               full_animate(ramp_tree, pos.rest, 140);
            }
            if(check_pos(ramp_tree, pos.rest)) {
               me.phase = 1;
            }
         } elsif(!check_pos(ramp_tree, pos.stop) and me.phase == 1) {
            full_animate(ramp_tree, pos.stop, 60);
         }
      }
   
      if(me.function == "rest") {
         if(!check_pos(ramp_tree, pos.rest)) {
            full_animate(ramp_tree, pos.rest, 80);
         }
      }
   
      if(me.function == "imm_stop") {
         if(!check_pos(ramp_tree, pos.stop)) {
            full_animate(ramp_tree, pos.stop, 240);
         }
      }
   
      if(me.function == "move_fwd") {
         if(me.phase == 0) {
            if(!check_pos(ramp_tree, pos.fwd_in)) {
               full_animate(ramp_tree, pos.fwd_in, 100);
            }
            if(check_pos(ramp_tree, pos.fwd_in)) {
               me.phase = 1;
            }
         } elsif(!check_pos(ramp_tree, pos.fwd_out) and me.phase == 1) {
            full_animate(ramp_tree, pos.fwd_out, 80);
            if(check_pos(ramp_tree, pos.fwd_out)) {
               me.phase = 2;
            }
         } elsif(!check_pos(ramp_tree, pos.fwd_in) and me.phase == 2) {
            full_animate(ramp_tree, pos.fwd_in, 80);
            if(check_pos(ramp_tree, pos.fwd_in)) {
               me.phase = 1;
            }
         }
      }
   
      if(me.function == "turn_left") {
         if(me.phase == 0) {
            if(!check_pos(ramp_tree, pos.left_in)) {
               full_animate(ramp_tree, pos.left_in, 100);
            }
            if(check_pos(ramp_tree, pos.left_in)) {
               me.phase = 1;
            }
         } elsif(!check_pos(ramp_tree, pos.left_out) and me.phase == 1) {
            full_animate(ramp_tree, pos.left_out, 80);
            if(check_pos(ramp_tree, pos.left_out)) {
               me.phase = 2;
            }
         } elsif(!check_pos(ramp_tree, pos.left_in) and me.phase == 2) {
            full_animate(ramp_tree, pos.left_in, 80);
            if(check_pos(ramp_tree, pos.left_in)) {
               me.phase = 1;
            }
         }
      }
   
      if(me.function == "turn_right") {
         if(me.phase == 0) {
            if(!check_pos(ramp_tree, pos.right_in)) {
               full_animate(ramp_tree, pos.right_in, 100);
            }
            if(check_pos(ramp_tree, pos.right_in)) {
               me.phase = 1;
            }
         } elsif(!check_pos(ramp_tree, pos.right_out) and me.phase == 1) {
            full_animate(ramp_tree, pos.right_out, 80);
            if(check_pos(ramp_tree, pos.right_out)) {
               me.phase = 2;
            }
         } elsif(!check_pos(ramp_tree, pos.right_in) and me.phase == 2) {
            full_animate(ramp_tree, pos.right_in, 80);
            if(check_pos(ramp_tree, pos.right_in)) {
               me.phase = 1;
            }
         }
      }
      
   } else { # Return to rest position
   
      full_animate(ramp_tree, pos.rest, 80);
   
   }
   
},

   reset : func {
      me.loopid += 1;
      me._loop_(me.loopid);
},
   _loop_ : func(id) {
      id == me.loopid or return;
      me.update();
      settimer(func { me._loop_(id); }, me.UPDATE_INTERVAL);
}

};

setlistener("sim/signals/fdm-initialized", func() {
main_loop.init();
});


EDIT - I'm still a little confused with the props class so I just replaced the ones that give errors with simple getprops ad setprops for now. :) I'll try to get to work on the ramp placement tool tonight. Cheers!
Merlion Virtual Airlines - the experience of a flight time...
Get high quality aircraft, airports, video tutorials or development tools from my hangar.
omega95
 
Posts: 1222
Joined: Sat Jul 30, 2011 1:59 am
Location: -unknown-
Callsign: MIA0001, OM-EGA
IRC name: omega95
Version: 2.12 git
OS: Ubuntu 13.04

Re: Nasal based Independant Ramp Marshall

Postby omega95 » Tue Aug 06, 2013 12:04 pm

Some progress on the markings - a little more realistic now. :)

Image

Image

Image
Merlion Virtual Airlines - the experience of a flight time...
Get high quality aircraft, airports, video tutorials or development tools from my hangar.
omega95
 
Posts: 1222
Joined: Sat Jul 30, 2011 1:59 am
Location: -unknown-
Callsign: MIA0001, OM-EGA
IRC name: omega95
Version: 2.12 git
OS: Ubuntu 13.04

Re: Nasal based Independant Ramp Marshall

Postby Johan G » Tue Aug 06, 2013 12:29 pm

Great work!

I got curious and looked into this, and (quite as usual) I went off on a tangent. I'm not sure this will be of any help, but I post it here just in case. :wink:

Google searching into it, I see that there have been a mess of different hands signals (and sometimes not identical wand signals): ICAO, IATA and NATO that all have changed over time, various variants and the mess that is when different systems are used at different airports and even different airlines. On top of that very few resources like posters and instructional videos seems to tell what system and version they are using. :evil:

The IATA and ICAO and NATO standards seems to be rather harmonised these days though. :) See edit below though. :(

Getting as close to the source as possible the marshalling signals are currently defined in:
  • ICAO Annex 2, Appendix 1, section 5 page APP 1-5. (10th edition, July 2005) - Can be accessed here
  • IATA Ground Operations Manual (IGOM) (2nd Edition)
  • NATO STANAG 3117 - Aircraft Marshalling Signals (8th edition, 27 Mars 2007) - Available directly from NATO(!)
I wonder what system(s) that have been used and are used used in Eastern Europe air forces though.


EDIT: Darn. Comparing the standards myself I find that most of the time the NATO standard does not follow the ICAO one where stated, even though the ICAO standard is older (even considering amendments related to marshalling under normal operations; some signals related to communication with firefighting personnel was added in 2009).
Last edited by Johan G on Wed Aug 07, 2013 8:21 pm, edited 1 time in total.
Low-level flying — It's all fun and games till someone looses an engine. (Paraphrased from a YouTube video)
Improving the Dassault Mirage F1 (Wiki, Forum, GitLab. Work in slow progress)
Some YouTube videos
Johan G
Moderator
 
Posts: 6629
Joined: Fri Aug 06, 2010 6:33 pm
Location: Sweden
Callsign: SE-JG
IRC name: Johan_G
Version: 2020.3.4
OS: Windows 10, 64 bit

Re: Nasal based Independant Ramp Marshall

Postby Hooray » Tue Aug 06, 2013 1:33 pm

looks great, we should add a paragraph or two about your project to the August newsletter.
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: Nasal based Independant Ramp Marshall

Postby Philosopher » Tue Aug 06, 2013 1:53 pm

Cool!

Hooray, you missed his problem ;)
omega95 wrote in Tue Aug 06, 2013 6:41 am:I get the error: non-objects have no members at this line - var tmp = ramps.getNode("models",1).getNode("model", 1);

You're using the plural here, ramps, which is a vector - ramp is what you want (since it's a props.Node). You can also combine the two getNode paths: «var tmp = ramps.getNode("models/model", 1)»

Also, make sure to use var in your foreach declarations !: «foreach (var ramp; ramps)»

Oh! If you only want to get children with a certain name, add that name as an argument to getChildren: var ramps = whatever.getChildren("models") for example. Right now you iterate through any child of the props.Node.
Philosopher
 
Posts: 1593
Joined: Sun Aug 12, 2012 7:29 pm

Re: Nasal based Independant Ramp Marshall

Postby omega95 » Tue Aug 06, 2013 1:56 pm

@Johan, thanks a lot for the sources! Apparently, the video I watched seems to have mixed them up! I guess I'll stick to the ICAO signals because 4 of the 5 signals are correct according to your first source. (ICAO Annex 2)

I'll be changing the signal to move forward and adding the signal to slow down for now. :)

@Philosopher, thanks a lot! I forgot about that, not sure why it still worked though without the var though. :D
Merlion Virtual Airlines - the experience of a flight time...
Get high quality aircraft, airports, video tutorials or development tools from my hangar.
omega95
 
Posts: 1222
Joined: Sat Jul 30, 2011 1:59 am
Location: -unknown-
Callsign: MIA0001, OM-EGA
IRC name: omega95
Version: 2.12 git
OS: Ubuntu 13.04

Re: Nasal based Independant Ramp Marshall

Postby omega95 » Tue Aug 06, 2013 4:30 pm

Hmm, need some help again.

I'm working on a function that converts stg files created using the ufo into airport ramp xml files.

This is where I'm having trouble - I'm trying to open the file-select dialog.
Code: Select all
fgcommand("dialog-show", props.Node.new({ "dialog-name": "file-select" }));
   setprop("/sim/gui/dialogs/file-select/path", ""));


But I get this error.
Code: Select all
Nasal runtime error: props.setValue() with non-number
  at /home/narendran/fgdata-git/Nasal/props.nas, line 29
  called from: __dlg:file-select, line 22


It points to this line in the file-select.xml dialog file.
Code: Select all
self.getNode("group[1]/input/visible/equals/value").setValue(self.show_files);
Merlion Virtual Airlines - the experience of a flight time...
Get high quality aircraft, airports, video tutorials or development tools from my hangar.
omega95
 
Posts: 1222
Joined: Sat Jul 30, 2011 1:59 am
Location: -unknown-
Callsign: MIA0001, OM-EGA
IRC name: omega95
Version: 2.12 git
OS: Ubuntu 13.04

Re: Nasal based Independant Ramp Marshall

Postby Philosopher » Tue Aug 06, 2013 4:50 pm

Try calling this before that (just a guess):
Code: Select all
setprop("/sim/gui/dialogs/file-select/show-files", 0);
Philosopher
 
Posts: 1593
Joined: Sun Aug 12, 2012 7:29 pm

Re: Nasal based Independant Ramp Marshall

Postby omega95 » Tue Aug 06, 2013 6:08 pm

Actually, this worked - I need it to show files to be able to select a file! Well, thanks for pointing me to the issue though! :D

Code: Select all
setprop("/sim/gui/dialogs/file-select/show-files", 1);


And now, you can create multiple instances with the ufo and they all work! :D
Merlion Virtual Airlines - the experience of a flight time...
Get high quality aircraft, airports, video tutorials or development tools from my hangar.
omega95
 
Posts: 1222
Joined: Sat Jul 30, 2011 1:59 am
Location: -unknown-
Callsign: MIA0001, OM-EGA
IRC name: omega95
Version: 2.12 git
OS: Ubuntu 13.04

Re: Nasal based Independant Ramp Marshall

Postby omega95 » Wed Aug 07, 2013 9:40 am

Just made some aircraft (most from my hangar and a couple others from fgdata) compatible with the ramps! I'll create a merge request for the updated -set.xml files soon, along with the ramps and a gui style. :mrgreen:

Image

EDIT - Merge request created for Ramp Marshall script v1.0 > https://gitorious.org/fg/fgdata/merge_requests/220#84e7651c815ce7a72440e26deacdf9d60dc007fd-84e7651c815ce7a72440e26deacdf9d60dc007fd@1
Merlion Virtual Airlines - the experience of a flight time...
Get high quality aircraft, airports, video tutorials or development tools from my hangar.
omega95
 
Posts: 1222
Joined: Sat Jul 30, 2011 1:59 am
Location: -unknown-
Callsign: MIA0001, OM-EGA
IRC name: omega95
Version: 2.12 git
OS: Ubuntu 13.04

Re: Nasal based Independant Ramp Marshall

Postby Philosopher » Wed Aug 07, 2013 1:46 pm

I'll definitely check this out today - but I'm a little concerned that I might run over the little guy :(. However, I have proportional brakes so it shouldn't be a problem ;).

Do we still need the WSSS scenery or can we select our own airport using the file selector and automatically get support?
Philosopher
 
Posts: 1593
Joined: Sun Aug 12, 2012 7:29 pm

Re: Nasal based Independant Ramp Marshall

Postby omega95 » Wed Aug 07, 2013 2:00 pm

Do we still need the WSSS scenery or can we select our own airport using the file selector and automatically get support?


Well, WSSS is the only airport with ramp marshalls for now but to put it somewhere else, follow these steps -

1. Use the ufo to place the $FGDATA/Models/Airport/Ramp/ramp.xml where you want and export it to stg.
2. Save the file with all the ramps you want somewhere and then start FG up again (ufo works).
3. Run this function in the Nasal Console and select the stg file with the ramps.
Code: Select all
ramp_marshall.convert_stg();

4. Copy the ramps-export.xml file from $FGHOME/Export into $FGDATA/AI/Airports/<icao>/ramps.xml (you have to rename it)

And you should be good to go! Start up and click on a ramp marshall to toggle him. :D

Oh and don't worry about running him over, he's about 20 m from where the nose gear should stop and he'll signal a cross (the slow down and stop signal) when you get close. If you're too close, he'll make the cross abruptly to signal and immediate stop. :)

And after you've come to a stop, click on him again to deactivate him. Else, he'll keep his hands up and get tired, lol. :D
Merlion Virtual Airlines - the experience of a flight time...
Get high quality aircraft, airports, video tutorials or development tools from my hangar.
omega95
 
Posts: 1222
Joined: Sat Jul 30, 2011 1:59 am
Location: -unknown-
Callsign: MIA0001, OM-EGA
IRC name: omega95
Version: 2.12 git
OS: Ubuntu 13.04

Re: Nasal based Independant Ramp Marshall

Postby Philosopher » Wed Aug 07, 2013 2:05 pm

Thanks!
Philosopher
 
Posts: 1593
Joined: Sun Aug 12, 2012 7:29 pm

Next

Return to Nasal

Who is online

Users browsing this forum: No registered users and 6 guests