Board index FlightGear Development Canvas

ATR72 FMC Development using Canvas

Canvas is FlightGear's new fully scriptable 2D drawing system that will allow you to easily create new instruments, HUDs and even GUI dialogs and custom GUI widgets, without having to write C++ code and without having to rebuild FlightGear.

Re: ATR72 FMC Development using Canvas

Postby omega95 » Mon Jul 30, 2012 8:08 pm

So, here's what I'm using for a page...

Code: Select all
fmcPages["ident"] = {

   initDisplay: func() {
   
      title.setText("IDENT").setColor(blue);
      
      labels[0].setText("MODEL").setColor(blue);
      labels[1].setText("CO-DATA").setColor(blue);
      labels[2].setText("NAVDATA").setColor(blue);
      labels[3].setText("CALLSIGN").setColor(blue);
      labels[5].setText("--------------------").setColor(blue);
      labels[12].setText("ENGINES").setColor(blue);
      labels[13].setText("CO-DATA").setColor(blue);
      labels[14].setText("NAVDATA").setColor(blue);
      
      values[0].setText(getprop("/sim/aero")).setColor(white);
      values[1].setText(getprop("/aircraft/fmc/company/db-id")).setColor(white);
      values[2].setText(getprop("/aircraft/fmc/navdata/db-id")).setColor(white);
      values[3].setText(getprop("/sim/multiplay/callsign")).setColor(white);
      values[12].setText("PW127F").setColor(white);
      values[13].setText(getprop("/aircraft/fmc/company/db-date")).setColor(white);
      values[14].setText(getprop("/aircraft/fmc/navdata/db-date")).setColor(white);
      values[12].setText("POS REF>").setColor(white);
   
   },
   
   r6: func() {
   
      GoToPage("posref");
   
   }

};


And the GoToPage is a very simple function...

Code: Select all
var GoToPage = func(page) {

   setprop(fmc~ "page", page);
   clearScreen();
   fmcPages[page].initDisplay();
        ActivePage = fmcPages[page];

};


And it works so far! :D It'll obviously get more complicated when it comes to flightplan/RTE/DEP/ARR pages...

Image

As much as the canvas system goes, I'm very happy with it at the moment. :mrgreen:

Now, here's a small thing I've been looking for in the past.. For the Jabiru J170's PFD. Synthetic terrain. Tom, do you have any idea how to view synthetic terrain using the canvas system? And what about a camera view? I did some research on that but didn't really get anywhere useful.

Synthetic terrain: http://flightgear.org/forums/viewtopic.php?f=4&t=15722&start=45#p153941
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: ATR72 FMC Development using Canvas

Postby Hooray » Mon Jul 30, 2012 8:13 pm

Now, here's a small thing I've been looking for in the past.. For the Jabiru J170's PFD. Synthetic terrain. Tom, do you have any idea how to view synthetic terrain using the canvas system? And what about a camera view? I did some research on that but didn't really get anywhere useful.


We also talked about that, but it's not really the main focus of the canvas system currently, which really is about 2D drawing. Synthetic terrain views, and complex moving map displays or 3D views are conceptually something different and would be better addressed separately.

However, this COULD be implemented as a custom canvas "layer" at some point: http://wiki.flightgear.org/Canvas_Maps#Moving_Maps

Obviously, despite the canvas not being primarily focused on this, it is definitely the easiest option to implement 3D views and moving maps in scripting space currently, definitely much simpler to use than fancy XML animations ;-)
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: ATR72 FMC Development using Canvas

Postby omega95 » Tue Jul 31, 2012 11:04 am

Alright, I hope this isn't too much to ask but will it be possible of you (Hooray) to check this code and add info to wiki on how you can optimize it? :mrgreen:

Image

Code: Select all
fmcPages["perfinit"] = {

   initDisplay: func() {

      title.setText("PERF INIT").setColor(blue);
      pageNo.setText("1/2").setColor(blue);
      
      labels[0].setText("GR WT").setColor(blue);
      labels[1].setText("FUEL").setColor(blue);
      labels[2].setText("ZFW").setColor(blue);
      labels[3].setText("RESERVES").setColor(blue);
      labels[4].setText("TRANS ALT").setColor(blue);
      labels[5].setText("------------------------------").setColor(blue);
      
      labels[12].setText("CRZ ALT").setColor(blue);
      labels[13].setText("CLIMB").setColor(blue);
      labels[14].setText("CRUISE").setColor(blue);
      labels[15].setText("DESCENT").setColor(blue);
      labels[16].setText("SPD TRANS").setColor(blue);
      
      if (getprop("/aircraft/fmc/perf/grwt") != nil)
         values[0].setText(getprop("/aircraft/fmc/perf/grwt")).setColor(white);
      else
         values[0].setText("--.-").setColor(white);
         
      if (getprop("/aircraft/fmc/perf/fuel") != nil)
         values[1].setText(getprop("/aircraft/fmc/perf/fuel")).setColor(white);
      else
         values[1].setText("--.- CALC").setColor(white);
         
      values[2].setText("28.5").setColor(white);
      
      if (getprop("/aircraft/fmc/perf/rsv") != nil)
         values[3].setText(getprop("/aircraft/fmc/perf/rsv")).setColor(white);
      else
         values[3].setText("--.-").setColor(white);
         
      values[4].setText(getprop("/aircraft/fmc/perf/trans-alt")).setColor(white);
      
      values[12].setText(getprop("/aircraft/fmc/perf/crz-alt")).setColor(white);
      values[13].setText(getprop("/aircraft/fmc/perf/climb")).setColor(white).setFontSize(40, 1.2);
      values[14].setText(getprop("/aircraft/fmc/perf/cruise")).setColor(white).setFontSize(40, 1.2);
      values[15].setText(getprop("/aircraft/fmc/perf/descent")).setColor(white).setFontSize(40, 1.2);
      values[16].setText(getprop("/aircraft/fmc/perf/spd-trans")).setColor(white).setFontSize(40, 1.2);
      
   },
   
   l1: func() {
   
      setprop("/aircraft/fmc/perf/grwt", (int(getprop("/fdm/jsbsim/inertia/weight-lbs")/10)/100));
      values[0].setText(getprop("/aircraft/fmc/perf/grwt")).setColor(white);
   
   },
   
   l2: func() {
   
      setprop("/aircraft/fmc/perf/fuel", (int(getprop("/consumables/fuel/total-fuel-lbs")/10)/100));
      values[1].setText(getprop("/aircraft/fmc/perf/fuel")).setColor(white);
   
   },
   
   l4: func() {
   
      var input = getprop(fmc~ "input");
   
      if (input != nil) {
         setprop("/aircraft/fmc/perf/rsv", input);
         values[3].setText(input).setColor(white);
         clearInput();
      } else
         setprop(fmc~ "input", "ERROR: WRONG FORMAT");
   
   },
   
   l5: func() {
   
      var input = getprop(fmc~ "input");
      
      setprop("/aircraft/fmc/perf/trans-alt", input);
      
      values[4].setText(input).setColor(white);
      
      clearInput();
   
   },
   
   r1: func() {
   
      var input = getprop(fmc~ "input");
      
      setprop("/aircraft/fmc/perf/crz-alt", input);
      
      values[12].setText(input).setColor(white);
      
      values[5].setText("< ERASE").setColor(green);
      
      setprop(fmc~ "exec-lt", 1);
      
      clearInput();
   
   },
   
   r2: func() {
   
      var input = getprop(fmc~ "input");
      
      setprop("/aircraft/fmc/perf/climb", input);
      
      values[13].setText(input).setColor(white);
      
      clearInput();
   
   },
   
   r3: func() {
   
      var input = getprop(fmc~ "input");
      
      setprop("/aircraft/fmc/perf/cruise", input);
      
      values[14].setText(input).setColor(white);
      
      clearInput();
   
   },
   
   r4: func() {
   
      var input = getprop(fmc~ "input");
      
      setprop("/aircraft/fmc/perf/descent", input);
      
      values[15].setText(input).setColor(white);
      
      clearInput();
   
   },
   
   r5: func() {
   
      var input = getprop(fmc~ "input");
      
      setprop("/aircraft/fmc/perf/spd-trans", input);
      
      values[16].setText(input).setColor(white);
      
      clearInput();
   
   },
   
   l6: func() {
   
      setprop("/aircraft/fmc/perf/crz-alt", "FL160");
      
      values[5].setText("").setColor(white);
      
      values[12].setText("FL160").setColor(white);
      
      setprop(fmc~ "exec-lt", 0);
   
   },
   
   exec: func() {
   
      setprop("/aicraft/afcs/crz-alt", getprop("/aircraft/fmc/perf/crz-alt"));
   
      values[5].setText("").setColor(white);
      
      setprop(fmc~ "exec-lt", 0);
   
   },

   next: func() {
   
      GoToPage("descent");
   
   }

};


Image

Code: Select all
fmcPages["descent"] = {

   initDisplay: func() {

      title.setText("DESCENT").setColor(blue);
      pageNo.setText("2/2").setColor(blue);
      
      labels[1].setText("AT TOD").setColor(magenta);
      labels[3].setText("E/" ~ getprop("/autopilot/route-manager/destination/airport")).setColor(white);
      labels[4].setText("FIX/ALT").setColor(blue);
      labels[5].setText("------------------------------").setColor(blue);
      
      labels[6].setText("VTK ERR").setColor(blue);
      
      labels[12].setText("VS").setColor(blue);
      labels[13].setText("DTG   VS REQ").setColor(blue);
      labels[14].setText("").setColor(blue);
      labels[15].setText("FPA   VB").setColor(blue);
      
      values[1].setText(getprop("/aicraft/afcs/crz-alt")).setColor(magenta);
      values[2].setText(getprop("/aicraft/afcs/crz-alt")).setColor(white);
      values[3].setText("---- FT").setColor(white);
      
      var fl = substr(getprop("/aicraft/afcs/crz-alt"), 2, 3);
      
      var descent = split("/", getprop("/aircraft/fmc/perf/descent"));
      
      var desc_ias = descent[0];
      
      var desc_tas = desc_ias + (fl/4); # (Actual formula: TAS = IAS + FL/2, but we want to assume half the FL as average)
      
      var desc_time_hr = (fl * 100) / 72000;
      
      var tod = int(desc_time_hr * desc_tas);
      
      values[12].setText("00").setColor(white);
      values[13].setText(tod ~ " NM  -1200").setColor(magenta);
      
      var rte_num = getprop("/autopilot/route-manager/route/num");
      
      if (rte_num > 2) {
      
         var last_wp = rte_num - 2;
         
         var dist = 0;
         
         var last_wp_id = "-----";
         var req_vs = "+0000";
         
         var exit = 0;
         
         for(var n=last_wp; exit != 1; n-=1) {
         
            if (n == 1) {
            
               exit = 1;
            
            }
         
            dist += getprop("/autopilot/route-manager/route/wp[" ~ n ~ "]/leg-distance-nm");
            
            if (dist > tod) {
            
               last_wp_id = getprop("/autopilot/route-manager/route/wp[" ~ n ~ "]/id");
               
               var desc_time_hr = dist / desc_tas;
               
               var vs = (fl * 100) / (desc_time_hr * 60); # 60 is the hr -> min conv factor and 100 is the fl to alt conv factor
               
               req_vs = int(vs / 100) ~ "00";
               
               exit = 1;
            
            }
         
         }
         
         labels[2].setText("AT " ~ last_wp_id).setColor(white);
         values[14].setText(int(dist) ~ " NM  -" ~ req_vs).setColor(white);
      
      } else {
      
         labels[2].setText("AT -----").setColor(white);
         values[14].setText("--- NM  +0000").setColor(white);
      
      }
      
   },
   
   prev: func() {
   
      GoToPage("perfinit");
   
   }

};
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: ATR72 FMC Development using Canvas

Postby Hooray » Tue Jul 31, 2012 10:11 pm

you code looks fine to me, there's little left to be optimized from a sytax point of view.
So, I wouldn't worry about it too much. Like I said, if you really wan to optimize this more, then it's not so much about just "coding" but about "design", i.e. by using coding patterns and standard techniques like state machines or MVC separation.

While that would be worthwhile to look into, it would definitely be much more work, and it would be more about coming up with a generic design and a reusable architecture. So these are concerns relevant for the main canvas Nasal modules.

If you don't want to read up on state machines or MVC, I would just leave it like that for now.
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: ATR72 FMC Development using Canvas

Postby omega95 » Wed Aug 01, 2012 8:21 am

So, I've been thinking of Hooray's recommendation to use a basic framework (I didn't exactly understand but I assumed that's like a class in java or c++) so I'm trying to use that for the route management system. The ATR72's FMC should be able to manage 2 routes, RTE 1 and RTE 2, I used to think it had an Alternate Route too (like the Airbus aircraft) but didn't find any reference to it yet, so what I did was instead of creating separate classes for them, I made 1 nasal hash with all the functions that should be in a route and used the {parents:[rte]} function to create 2 routes out of this one class.

Btw, I've also noticed that the mCDU framework using canvas wiki just has the example, not really an explanation to create your own, so I was thinking I'll make a wiki for that, using the common methods used by Tom and myself. :)

Anyway, here's a basic idea of my Airway based Route Management System (still being worked on). Btw, the Route Legs systems is actually separate. Atleast in the ATR72, you have to set up a route using this first and then it'll automatically get all the waypoints in airways and create a proper route (compatible with the RM)... aka. Route Legs.

Code: Select all
# Route Management System Class

var rte = {

   n: 0,
   loadAwys: func(index) {
   
      var location = "/database/navdata/awys/_" ~ index ~ "/";
      var filename = getprop("/sim/aircraft-dir") ~ "/Database/NavData/Airways/" ~ index ~ ".xml";

      io.read_properties(filename, location);
   
   },
   addAwy: func(name) {
   
      # First check if the airway exists
      
      var index = substr(name, 0, 2);
      
      me.loadAwys(index);
      
      var found = 0;
      var start = 0;
      
      var rte_num = getprop("/aircraft/fmc/rte"~me.n~"/rte/num");
      
      var prev_wp = getprop("/aircraft/fmc/rte"~me.n~"/rte/entry[" ~ (rte_num - 1) ~ "]/wp");
      
      for (var n=0; getprop("/database/navdata/awys/~" ~ index ~ "awy[" ~ n ~ "]/id") != nil; n+=1) {
      
         if (getprop("/database/navdata/awys/~" ~ index ~ "awy[" ~ n ~ "]/id") == name) {
         
            found = 1;
            
            if ((getprop("/database/navdata/awys/~" ~ index ~ "awy[" ~ n ~ "]/wp1") == prev_wp) or (getprop("/database/navdata/awys/~" ~ index ~ "awy[" ~ n ~ "]/wp2") == prev_wp)) {
            
               start = 1;
            
            }
         
         }
      
      }
      
      if ((found == 1) and (start == 1)) {
      
         # Accept Airway Entry and add it if Found
         var rte_num = getprop("/aircraft/fmc/rte"~me.n~"/rte/num");
         setprop("/aircraft/fmc/rte"~me.n~"/rte/entry["~rte_num~"]/awy", name);
         setprop("/aircraft/fmc/rte"~me.n~"/rte/entry["~rte_num~"]/wp", "---");
         
      
      } elsif (found == 1) {
      
         setInput("ERROR: WRONG INIT WAYPOINT");
      
      } else {
      
         # This means the airway doesn't exist in the database
         
         setInput("ERROR: NOT IN DATABASE");
      
      }      
   
   },
   updateAwy: func(n, name) {
   
      
   
   },
   addWP: func(name) {
   
      
   
   },
   updateWP: func(name) {
   
      
   
   },
   eraseRte: func() {
   
   
   
   },
   new: func(index) {
   
      var m = {parents:[rte]};
      
      m.n = index;
      
      return m;
   
   }

};

var rte1 = rte.new(1);
var rte2 = rte.new(2);


Note that I still haven't finished most of the functions, this is just a basic idea. Oh and if you're wondering about the airways, I used this nasal script to convert the awy.dat file (currently unused by any C++ code) into easily usable xml files for the route management system.

Code: Select all
var awy_hash = {};
var awy_vect = [];

var parse_awys = func() {

   var root = getprop("/sim/aircraft-dir");

   var awy_dat = io.open(root~ "/Devel/awy.dat", mode="r");
   
   var n = 0;
   
   while(var line = io.readln(awy_dat)) {
   
      var data = split(" ", line);
      
      var wp1 = data[0];
      var wp2 = data[3];
      var awy0 = split("-", data[9]);
      var awy = awy0[0];
      
      var index = substr(awy, 0, 2);
      
      if (awy_hash[index] == nil) {
      
         awy_hash[index] = 0;
         append(awy_vect, index);
         n+=1;
      
      } else {
      
         awy_hash[index] += 1;
      
      }
      
      var tree = "/database/navdata/awys/_" ~ index ~ "/awy[" ~ awy_hash[index] ~ "]/";
      
      setprop(tree~ "id", awy);
      setprop(tree~ "wp1", wp1);
      setprop(tree~ "wp2", wp2);
      
   }

}

var write_dat = func(index) {

   var location = "/database/navdata/awys/_" ~ index ~ "/";
   var filename = getprop("/sim/aircraft-dir") ~ "/Database/NavData/Airways/" ~ index ~ ".xml";

   io.write_properties(filename, location);

}

var awys2xml = func() {

   foreach(var index; awy_vect) {
   
      write_dat(index);
   
   }

}


Btw, the Airway data parser worked great... and I have xml files well sorted for the route management system to get airways from. :mrgreen:
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: ATR72 FMC Development using Canvas

Postby Hooray » Wed Aug 01, 2012 2:42 pm

obviously, coming up with a generic framework and a reusable design, would allow you to more easily reuse your work in other aircraft that you are working on, just by customizing and parametrizing some of your modules. Given the amount of aircraft that you tend to work on, that may still be beneficial
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: ATR72 FMC Development using Canvas

Postby omega95 » Thu Aug 02, 2012 4:28 pm

Hey, I've written a function to get airways from the xml airway db I created earlier out of airways from awy.dat (note that the airways are already read into the property tree when being entered in the rte) and get the list of waypoints and put them onto the route legs.

This is the second time I've written it-the first was really messy and I didn't comment anything so it was really difficult for me to manage, but the thing was it SORTA worked, just didn't do exactly what I wanted it to. And then again, I created a new one with proper comments and made it easy to read, but the problem IS that it seems to get stuck in an infinite loop. :shock:

Can someone help me out here?

Code: Select all
var awy2legs = func(id) {

   var tree = "/aircraft/fmc/rte"~id~"/";

   var legs = [];

   var num = getprop(tree~"rte/num");

   # Go through every single entry in the route

   for(var n=0; n<(num-1); n+=1) {

      var wp = getprop(tree~"rte/entry["~n~"]/wp"); # Current WP

      var awy = getprop(tree~"rte/entry["~(n+1)~"]/awy"); # Airway from the current WP to the next

      var next_wp = getprop(tree~"rte/entry["~(n+1)~"]/wp"); # Next WP

      # This section has proper airways and the waypoints must be taken out of the airway and appended to the legs

      if ((awy != nil) and (awy != "") and (awy != "----") and (awy != "DIRECT")) {

         # Here's the really tricky and annoying part- (took me hours to figure it out) we have to start at the wp and look for airway entries from the database that go both ways. Then, we go along both loops separately till 1 of them reaches the next_wp. If none of them reaches the next waypoint, we will ignore the airway altogether and simply use go directly to the next waypoint.

         var awyup = [wp]; # Vector of airways going up from the starting waypoint
         var awydn = [wp]; # Vector of airways going down from the starting waypoint

         var found = 0; # Whether next waypoint is found in either vectors

         var awyup_end = 0; # Whether the line of waypoints up the airway has ended

         var awydn_end = 1; # Whether the line of waypoints down the airway has ended, it can also be used to check if a line of waypoints down the airway exists

         for(var k=0; getprop("/database/navdata/awys/awy["~k~"]/id") != nil; k+=1) { # Find the waypoint up the airway line

            var db_awy = getprop("/database/navdata/awys/awy["~k~"]/id"); # Airway ID
            var db_wp1 = getprop("/database/navdata/awys/awy["~k~"]/wp1"); # Init Waypoint
            var db_wp2 = getprop("/database/navdata/awys/awy["~k~"]/wp2"); # Final Waypoint

            if (db_awy == awy) {

               if (db_wp1 == wp) { # Check if the waypoint has a match

                  append(awyup, db_wp2); # Append the OTHER waypoint to the airway line

               }

               if (db_wp2 == wp) { # Check if the other waypoint has a match

                  append(awyup, db_wp1); # Append the initial one to the airway line

               }

            }

         } # End of Waypoints for loop

         for(var k=0; getprop("/database/navdata/awys/awy["~k~"]/id") != nil; k+=1) { # Find the waypoint down the airway line

            var db_awy = getprop("/database/navdata/awys/awy["~k~"]/id"); # Airway ID
            var db_wp1 = getprop("/database/navdata/awys/awy["~k~"]/wp1"); # Init Waypoint
            var db_wp2 = getprop("/database/navdata/awys/awy["~k~"]/wp2"); # Final Waypoint

            if (db_awy == awy) {

               if ((db_wp1 == wp) and (db_wp2 != awyup[1])) { # Check if the waypoint has a match

                  append(awydn, db_wp2); # Append the OTHER waypoint to the airway line

                  awydn_end = 0; # Means that there is a line of waypoints down the airway

               }

               if ((db_wp2 == wp) and (db_wp1 != awydn[1])) { # Check if the other waypoint has a match

                  append(awydn, db_wp1); # Append the initial one to the airway line

                  awydn_end = 0; # Means that there is a line of waypoints down the airway

               }

            }

         } # End of waypoints for loop

         # Airway Up Vector

         while((found == 0) and (awyup_end == 0)) { # Keep Checking until either the line ends or the waypoint is found

            for(var k=0; getprop("/database/navdata/awys/awy["~k~"]/id") != nil; k+=1) {

               var db_awy = getprop("/database/navdata/awys/awy["~k~"]/id"); # Airway ID
               var db_wp1 = getprop("/database/navdata/awys/awy["~k~"]/wp1"); # Init Waypoint
               var db_wp2 = getprop("/database/navdata/awys/awy["~k~"]/wp2"); # Final Waypoint

               if (db_awy == awy) { # Look into the airway we've got from the route

                  var active = size(awyup) - 1;

                  # If Waypoint 1 is the previous waypoint in the awyup line

                  if ((db_wp1 == awyup[active-1]) and (db_wp2 != awyup[active-2])) { # This forces the loop to check in a straight line and not go back

                     # Now check whether we've reached the last waypoint or not

                     if (db_wp2 == next_wp) { # This means we've reached the last waypoint

                        found = 1; # Set the waypoint found flag

                        append(legs, awyup);

                     } else {

                        append(awyup, db_wp2);

                     }

                  }

                  # If Waypoint 2 is the previous waypoint in the awyup line

                  if ((db_wp2 == awyup[active-1]) and (db_wp1 != awyup[active-2])) { # This forces the loop to check in a straight line and not go back

                     # Now check whether we've reached the last waypoint or not

                     if (db_wp1 == next_wp) { # This means we've reached the last waypoint

                        found = 1; # Set the waypoint found flag

                        append(legs, awyup);

                     } else {

                        append(awyup, db_wp1);

                     }

                  }

               } # End of airway check

            } # End of DB Airways check for loop
            
         } # End of Airway Up Check While Loop

         # Airway Down Vector

         while((found == 0) and (awydn_end == 0)) { # Keep Checking until either the line ends or the waypoint is found

            for(var k=0; getprop("/database/navdata/awys/awy["~k~"]/id") != nil; k+=1) {

               var db_awy = getprop("/database/navdata/awys/awy["~k~"]/id"); # Airway ID
               var db_wp1 = getprop("/database/navdata/awys/awy["~k~"]/wp1"); # Init Waypoint
               var db_wp2 = getprop("/database/navdata/awys/awy["~k~"]/wp2"); # Final Waypoint

               if (db_awy == awy) { # Look into the airway we've got from the route

                  var active = size(awydn) - 1;

                  # If Waypoint 1 is the previous waypoint in the awydn line

                  if ((db_wp1 == awydn[active-1]) and (db_wp2 != awydn[active-2])) { # This forces the loop to check in a straight line and not go back

                     # Now check whether we've reached the last waypoint or not

                     if (db_wp2 == next_wp) { # This means we've reached the last waypoint

                        found = 1; # Set the waypoint found flag

                        append(legs, awydn);

                     } else {

                        append(awydn, db_wp2);

                     }

                  }

                  # If Waypoint 2 is the previous waypoint in the awydn line

                  if ((db_wp2 == awydn[active-1]) and (db_wp1 != awydn[active-2])) { # This forces the loop to check in a straight line and not go back

                     # Now check whether we've reached the last waypoint or not

                     if (db_wp1 == next_wp) { # This means we've reached the last waypoint

                        found = 1; # Set the waypoint found flag

                        append(legs, awydn);

                     } else {

                        append(awydn, db_wp1);

                     }

                  }

               } # End of airway check

            } # End of DB Airways check for loop
            
         } # End of Airway Down Check While Loop

         # Check if the airway is found, if it ISN'T found, then assume direct transition

         if (found == 0) {

            append(legs, wp);

         }

      } # End of NOT-DIRECT if clause

      # This section means that the transition to next waypoint is DIRECT

      else {

         append(legs, wp);

      } # End of NOT-DIRECT else clause
      
   } # End of rte entries for loop

   append(legs, getprop(tree~"rte/entry["~(num-1)~"]/wp")); # Append Last waypoint to legs

   # Once all the waypoints are appended to the vector, copy them to property

   for(var m=0; m<size(legs); m+=1) {

      setprop(tree~"legs/wp["~m~"]/wp", legs[m]);
      setprop(tree~"legs/wp["~m~"]/alt", "-----");

   }

   setprop(tree~"legs/num", size(legs));

};
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: ATR72 FMC Development using Canvas

Postby omega95 » Thu Aug 02, 2012 4:39 pm

Well, the problem is in the airway search loop, cuz using direct waypoints, the conversion works fine. :|

Image

Image

Note that the distances are messed up cuz I forgot to put the conversion factor for meters to nm :mrgreen:

EDIT: I can enter airways properly, (If the airway doesn't exist, it'll show ERROR: NOT IN DATABASE on the FMC and if the init waypoint and airway doesn't match, it'll show ERROR: WRONG INIT WAYPOINT on the FMC, so if you're able to enter an airway, that means it found it and you're on the right track cuz the airway connects the wp in the last entry. So, here's the RTE 1 page but then when I click on RTE 1 LEG, the airway conversion gets stuck. :evil:

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: ATR72 FMC Development using Canvas

Postby omega95 » Thu Aug 02, 2012 5:43 pm

Nevermind, I found hte solution.. I added print("<with status here>") commands in various places to see where it's going wrong and found the error. :mrgreen:

Works PERFECTLY NOW! :D :D :D :D

Code: Select all
var awy2legs = func(id) {

   var tree = "/aircraft/fmc/rte"~id~"/";

   var legs = [];

   var num = getprop(tree~"rte/num");

   # Go through every single entry in the route

   print("Started AWY conversion");

   for(var n=0; n<(num-1); n+=1) {

      var wp = getprop(tree~"rte/entry["~n~"]/wp"); # Current WP

      var awy = getprop(tree~"rte/entry["~(n+1)~"]/awy"); # Airway from the current WP to the next

      var next_wp = getprop(tree~"rte/entry["~(n+1)~"]/wp"); # Next WP

      print("Checking Waypoint-> "~wp~" with next Airway ("~awy~") pointing to "~next_wp);

      # This section has proper airways and the waypoints must be taken out of the airway and appended to the legs

      if ((awy != nil) and (awy != "") and (awy != "----") and (awy != "DIRECT")) {

         # Here's the really tricky and annoying part- (took me hours to figure it out) we have to start at the wp and look for airway entries from the database that go both ways. Then, we go along both loops separately till 1 of them reaches the next_wp. If none of them reaches the next waypoint, we will ignore the airway altogether and simply use go directly to the next waypoint.

         var awyup = [wp]; # Vector of airways going up from the starting waypoint
         var awydn = [wp]; # Vector of airways going down from the starting waypoint

         var found = 0; # Whether next waypoint is found in either vectors

         var awyup_end = 0; # Whether the line of waypoints up the airway has ended

         var awydn_end = 1; # Whether the line of waypoints down the airway has ended, it can also be used to check if a line of waypoints down the airway exists

         print("Looking for first waypoint up the airway");

         for(var k=0; getprop("/database/navdata/awys/_"~substr(awy,0,2)~"/awy["~k~"]/id") != nil; k+=1) { # Find the waypoint up the airway line

            var db_awy = getprop("/database/navdata/awys/_"~substr(awy,0,2)~"/awy["~k~"]/id"); # Airway ID
            var db_wp1 = getprop("/database/navdata/awys/_"~substr(awy,0,2)~"/awy["~k~"]/wp1"); # Init Waypoint
            var db_wp2 = getprop("/database/navdata/awys/_"~substr(awy,0,2)~"/awy["~k~"]/wp2"); # Final Waypoint

            if (db_awy == awy) {

               if (db_wp1 == wp) { # Check if the waypoint has a match

                  append(awyup, db_wp2); # Append the OTHER waypoint to the airway line

                  print("Found first waypoint up the airway ->"~db_wp2);

                  k = 10000; # To get out of the loop

               }

               if (db_wp2 == wp) { # Check if the other waypoint has a match

                  append(awyup, db_wp1); # Append the initial one to the airway line

                  print("Found first waypoint up the airway ->"~db_wp1);

                  k = 10000; # To get out of the loop

               }

            }

         } # End of Waypoints for loop

         print("Looking for first waypoint down the airway");

         for(var k=0; getprop("/database/navdata/awys/_"~substr(awy,0,2)~"/awy["~k~"]/id") != nil; k+=1) { # Find the waypoint down the airway line

            var db_awy = getprop("/database/navdata/awys/_"~substr(awy,0,2)~"/awy["~k~"]/id"); # Airway ID
            var db_wp1 = getprop("/database/navdata/awys/_"~substr(awy,0,2)~"/awy["~k~"]/wp1"); # Init Waypoint
            var db_wp2 = getprop("/database/navdata/awys/_"~substr(awy,0,2)~"/awy["~k~"]/wp2"); # Final Waypoint

            if (db_awy == awy) {

               if ((db_wp1 == wp) and (db_wp2 != awyup[1])) { # Check if the waypoint has a match

                  append(awydn, db_wp2); # Append the OTHER waypoint to the airway line

                  awydn_end = 0; # Means that there is a line of waypoints down the airway

                  print("Found first waypoint down the airway ->"~db_wp2);

                  k = 10000; # To get out of the loop

               }

               if ((db_wp2 == wp) and (db_wp1 != awyup[1])) { # Check if the other waypoint has a match

                  append(awydn, db_wp1); # Append the initial one to the airway line

                  awydn_end = 0; # Means that there is a line of waypoints down the airway

                  print("Found first waypoint down the airway ->"~db_wp1);

                  k = 10000; # To get out of the loop

               }

            }

         } # End of waypoints for loop

         print("Starting to look for a line of waypoints UP till the next WP");

         # Airway Up Vector

         var up=0;

         while((found == 0) and (awyup_end == 0)) { # Keep Checking until either the line ends or the waypoint is found

            for(var k=0; getprop("/database/navdata/awys/_"~substr(awy,0,2)~"/awy["~k~"]/id") != nil; k+=1) {

               var db_awy = getprop("/database/navdata/awys/_"~substr(awy,0,2)~"/awy["~k~"]/id"); # Airway ID
               var db_wp1 = getprop("/database/navdata/awys/_"~substr(awy,0,2)~"/awy["~k~"]/wp1"); # Init Waypoint
               var db_wp2 = getprop("/database/navdata/awys/_"~substr(awy,0,2)~"/awy["~k~"]/wp2"); # Final Waypoint

               if (db_awy == awy) { # Look into the airway we've got from the route

                  var active = size(awyup);

                  # If Waypoint 1 is the previous waypoint in the awyup line

                  if ((db_wp1 == awyup[active-1]) and (db_wp2 != awyup[active-2])) { # This forces the loop to check in a straight line and not go back

                     # Now check whether we've reached the last waypoint or not

                     if (db_wp2 == next_wp) { # This means we've reached the last waypoint

                        found = 1; # Set the waypoint found flag

                        foreach(var element; awyup) {

                           append(legs, element);

                        }

                        print("Found the next waypoint up the airway!");

                        k = 10000; # Escape the for loop

                     } else {

                        append(awyup, db_wp2);

                        print("Added "~db_wp2~" to the Airway List");

                     }

                  }

                  # If Waypoint 2 is the previous waypoint in the awyup line

                  if ((db_wp2 == awyup[active-1]) and (db_wp1 != awyup[active-2])) { # This forces the loop to check in a straight line and not go back

                     # Now check whether we've reached the last waypoint or not

                     if (db_wp1 == next_wp) { # This means we've reached the last waypoint

                        found = 1; # Set the waypoint found flag

                        foreach(var element; awyup) {

                           append(legs, element);

                        }

                        print("Found the next waypoint up the airway!");

                        k = 10000; # Escape the for loop

                     } else {

                        append(awyup, db_wp1);

                        print("Added "~db_wp1~" to the Airway List");

                     }

                  }

               } # End of airway check

            } # End of DB Airways check for loop

            up+=1;

            if (up>30)   awyup_end = 1; # LOOP COUNTER TO ESC
            
         } # End of Airway Up Check While Loop

         print("Starting to look for a line of waypoints DOWN till the next WP");

         # Airway Down Vector

         var down = 0;

         while((found == 0) and (awydn_end == 0)) { # Keep Checking until either the line ends or the waypoint is found

            for(var k=0; getprop("/database/navdata/awys/_"~substr(awy,0,2)~"/awy["~k~"]/id") != nil; k+=1) {

               var db_awy = getprop("/database/navdata/awys/_"~substr(awy,0,2)~"/awy["~k~"]/id"); # Airway ID
               var db_wp1 = getprop("/database/navdata/awys/_"~substr(awy,0,2)~"/awy["~k~"]/wp1"); # Init Waypoint
               var db_wp2 = getprop("/database/navdata/awys/_"~substr(awy,0,2)~"/awy["~k~"]/wp2"); # Final Waypoint

               if (db_awy == awy) { # Look into the airway we've got from the route

                  var active = size(awydn);

                  # If Waypoint 1 is the previous waypoint in the awydn line

                  if ((db_wp1 == awydn[active-1]) and (db_wp2 != awydn[active-2])) { # This forces the loop to check in a straight line and not go back

                     # Now check whether we've reached the last waypoint or not

                     if (db_wp2 == next_wp) { # This means we've reached the last waypoint

                        found = 1; # Set the waypoint found flag

                        foreach(var element; awydn) {

                           append(legs, element);

                        }

                        print("Found the next waypoint down the airway!");

                        k = 10000; # Escape the for loop

                     } else {

                        append(awydn, db_wp2);

                        print("Added "~db_wp1~" to the Airway List");

                     }

                  }

                  # If Waypoint 2 is the previous waypoint in the awydn line

                  if ((db_wp2 == awydn[active-1]) and (db_wp1 != awydn[active-2])) { # This forces the loop to check in a straight line and not go back

                     # Now check whether we've reached the last waypoint or not

                     if (db_wp1 == next_wp) { # This means we've reached the last waypoint

                        found = 1; # Set the waypoint found flag

                        foreach(var element; awydn) {

                           append(legs, element);

                        }

                        print("Found the next waypoint down the airway!");

                        k = 10000; # Escape the for loop

                     } else {

                        append(awydn, db_wp1);

                        print("Added "~db_wp2~" to the Airway List");

                     }

                  }

               } # End of airway check

            } # End of DB Airways check for loop

            down+=1;

            if(down>30) awydn_end = 1; # LOOP COUNTER TO ESC
            
         } # End of Airway Down Check While Loop

         # Check if the airway is found, if it ISN'T found, then assume direct transition

         if (found == 0) {

            append(legs, wp);

            print("Set Direct");

         }

      } # End of NOT-DIRECT if clause

      # This section means that the transition to next waypoint is DIRECT

      else {

         append(legs, wp);

         print("Set Direct");

      } # End of NOT-DIRECT else clause
      
   } # End of rte entries for loop

   append(legs, getprop(tree~"rte/entry["~(num-1)~"]/wp")); # Append Last waypoint to legs

   for(var m=0; m<size(legs); m+=1) {

      setprop(tree~"legs/wp["~m~"]/wp", legs[m]);
      setprop(tree~"legs/wp["~m~"]/alt", "-----");

   }

   print("Copied Legs to Property Tree");

   setprop(tree~"legs/num", size(legs));

};


Image

EDIT: An Airway Format Route I tried from CBE (VOCB) to BOM (VABB)

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

Previous

Return to Canvas

Who is online

Users browsing this forum: No registered users and 5 guests