]> git.mxchange.org Git - flightgear.git/commitdiff
Durk Talsma:
authorehofman <ehofman>
Tue, 18 Oct 2005 18:44:37 +0000 (18:44 +0000)
committerehofman <ehofman>
Tue, 18 Oct 2005 18:44:37 +0000 (18:44 +0000)
Auf Niederlandisch:
Bij deze de patch voor de taxiway code. Deze code is nog gebaseerd
op de bestaaande architectuur, gebaseerd op de FGAirport class in simple.[ch]xx
Ik heb me voornamelijk gericht op nieuwe functionaliteit; de volgende
submissie zal waarschijnlijk bestaan uit opschoning, opsplitsing en een
implementatie van de nieuwe airport architectuur, zoals voorgesteld door
David Luff.

En Anglais:
Here is the patch for the taxiway code. This code is still based on the
exsisting architecture, which is based on the FGAirport class in simple.[ch]xx
I've aimed mostly at new functionality; The next batch will probably contain
code cleanups, splitups and the implementation fo the new airport architecture,
as proposed by David Luff.

src/AIModel/AIFlightPlan.hxx
src/AIModel/AIFlightPlanCreate.cxx
src/Airports/simple.cxx
src/Airports/simple.hxx
src/Traffic/Schedule.cxx

index a6ae1182e2f137e1f85654d8ff0451d4c7a6f978..15c479672078b184f0862c97a862dec4904dbdef 100644 (file)
@@ -104,9 +104,10 @@ private:
    time_t start_time;
   int leg;
   int gateId;
+  string activeRunway;
 
   void createPushBack(bool, FGAirport*, double, double, double, string, string, string);
-  void createTaxi(bool, int, FGAirport *, double, string, string, string);
+  void createTaxi(bool, int, FGAirport *, double, double, double, string, string, string);
   void createTakeOff(bool, FGAirport *, double);
   void createClimb(bool, FGAirport *, double, double);
   void createCruise(bool, FGAirport*, FGAirport*, double, double, double, double);
index f5455effe64f5c84aa6b0efcbdfbff69e4b9ce7f..c851a6e71fc170048e7e179ace7139d05bebdd42 100644 (file)
@@ -50,7 +50,7 @@ void FGAIFlightPlan::create(FGAirport *dep, FGAirport *arr, int legNr, double al
       break;
     case 2: 
       //cerr << "Creating Taxi" << endl;
-      createTaxi(firstFlight, 1, dep, radius, fltType, aircraftType, airline);
+      createTaxi(firstFlight, 1, dep, latitude, longitude, radius, fltType, aircraftType, airline);
       break;
     case 3: 
       //cerr << "Creating TAkeoff" << endl;
@@ -74,7 +74,7 @@ void FGAIFlightPlan::create(FGAirport *dep, FGAirport *arr, int legNr, double al
       break;
     case 8: 
       //cerr << "Creating Taxi 2" << endl;
-      createTaxi(false, 2, arr, radius, fltType, aircraftType, airline);
+      createTaxi(false, 2, arr, latitude, longitude, radius, fltType, aircraftType, airline);
       break;
     case 9: 
       //cerr << "Creating Parking" << endl;
@@ -161,7 +161,7 @@ void FGAIFlightPlan::createPushBack(bool firstFlight, FGAirport *dep,
   wpt->on_ground = true;
   waypoints.push_back(wpt); 
   geo_direct_wgs_84 ( 0, lat, lon, heading, 
-                     100, 
+                     radius,                 // push back one entire aircraft radius
                      &lat2, &lon2, &az2 );
   wpt = new waypoint;
   wpt->name      = "taxiStart";
@@ -176,22 +176,14 @@ void FGAIFlightPlan::createPushBack(bool firstFlight, FGAirport *dep,
   wpt->on_ground = true;
   waypoints.push_back(wpt); 
 
-  //wpt = new waypoint;
-  //wpt->name = "END";
-  //wpt->finished = false;
-  //waypoints.push_back(wpt);  // add one more to prevent a segfault.  
-  //waypoints.push_back(wpt);  // add one more to prevent a segfault. 
-  //wpt_iterator = waypoints.begin();
-  //if (!firstFlight)
-  //  wpt_iterator++;
-  //wpt_iterator = waypoints.begin()+currWpt;
+  
 }
 
 /*******************************************************************
  * createCreate Taxi. 
  * initialize the Aircraft at the parking location
  ******************************************************************/
-void FGAIFlightPlan::createTaxi(bool firstFlight, int direction, FGAirport *apt, double radius, string fltType, string acType, string airline)
+void FGAIFlightPlan::createTaxi(bool firstFlight, int direction, FGAirport *apt, double latitude, double longitude, double radius, string fltType, string acType, string airline)
 {
   double wind_speed;
   double wind_heading;
@@ -208,29 +200,13 @@ void FGAIFlightPlan::createTaxi(bool firstFlight, int direction, FGAirport *apt,
   //int currWpt = wpt_iterator - waypoints.begin();
   if (direction == 1)
     {
-      
-      
-
-     
-      // Get the current active runway, based on code from David Luff
-      // This should actually be unified and extended to include 
-      // Preferential runway use schema's 
-      //FGEnvironment 
-      //stationweather = ((FGEnvironmentMgr *) globals->get_subsystem("environment"))
-      //->getEnvironment(apt->getLatitude(), apt->getLongitude(), apt->getElevation());
-      
-      //wind_speed = stationweather.get_wind_speed_kt();
-      //wind_heading = stationweather.get_wind_from_heading_deg();
-      //if (wind_speed == 0) {
-      //wind_heading = 270;    // This forces West-facing rwys to be used in no-wind situations
-       // which is consistent with Flightgear's initial setup.
-      //}
-      
-      //string rwy_no = globals->get_runways()->search(apt->getId(), int(wind_heading));
-      string name;
-      apt->getActiveRunway("com", 1, &name);
+      //string name;
+      // "NOTE: this is currently fixed to "com" for commercial traffic
+      // Should be changed to be used dynamically to allow "gen" and "mil"
+      // as well
+      apt->getActiveRunway("com", 1, &activeRunway);
       if (!(globals->get_runways()->search(apt->getId(), 
-                                           name
+                                           activeRunway
                                            &rwy)))
        {
          cout << "Failed to find runway for " << apt->getId() << endl;
@@ -247,49 +223,137 @@ void FGAIFlightPlan::createTaxi(bool firstFlight, int direction, FGAirport *apt,
       geo_direct_wgs_84 ( 0, rwy._lat, rwy._lon, azimuth, 
                          rwy._length * SG_FEET_TO_METER * 0.5 - 5.0,
                          &lat2, &lon2, &az2 );
-      
-      //Add the runway startpoint;
-      wpt = new waypoint;
-      wpt->name      = "Airport Center";
-      wpt->latitude  = apt->getLatitude();
-      wpt->longitude = apt->getLongitude();
-      wpt->altitude  = apt->getElevation();
-      wpt->speed     = 15; 
-      wpt->crossat   = -10000;
-      wpt->gear_down = true;
-      wpt->flaps_down= true;
-      wpt->finished  = false;
-      wpt->on_ground = true;
-      waypoints.push_back(wpt);
-       
-      //Add the runway startpoint;
-      wpt = new waypoint;
-      wpt->name      = "Runway Takeoff";
-      wpt->latitude  = lat2;
-      wpt->longitude = lon2;
-      wpt->altitude  = apt->getElevation();
-      wpt->speed     = 15; 
-      wpt->crossat   = -10000;
-      wpt->gear_down = true;
-      wpt->flaps_down= true;
-      wpt->finished  = false;
-      wpt->on_ground = true;
-      waypoints.push_back(wpt);
-      //wpt = new waypoint;
-      //wpt->finished = false;
-      //waypoints.push_back(wpt);  // add one more to prevent a segfault. 
+      if (apt->getGroundNetwork()->exists())
+       {
+         intVec ids;
+         int runwayId = apt->getGroundNetwork()->findNearestNode(lat2, lon2);
+         //int currId   = apt->getGroundNetwork()->findNearestNode(latitude,longitude);
+         //exit(1);
+         
+         // A negative gateId indicates an overflow parking, use a
+         // fallback mechanism for this. 
+         // Starting from gate 0 is a bit of a hack...
+         FGTaxiRoute route;
+         if (gateId >= 0)
+           route = apt->getGroundNetwork()->findShortestRoute(gateId, runwayId);
+         else
+           route = apt->getGroundNetwork()->findShortestRoute(0, runwayId);
+         intVecIterator i;
+         //cerr << "creating route : ";
+         // No route found: go from gate directly to runway
+         if (route.empty()) {
+           //Add the runway startpoint;
+           wpt = new waypoint;
+           wpt->name      = "Airport Center";
+           wpt->latitude  = latitude;
+           wpt->longitude = longitude;
+           wpt->altitude  = apt->getElevation();
+           wpt->speed     = 15; 
+           wpt->crossat   = -10000;
+           wpt->gear_down = true;
+           wpt->flaps_down= true;
+           wpt->finished  = false;
+           wpt->on_ground = true;
+           waypoints.push_back(wpt);
+           
+           //Add the runway startpoint;
+           wpt = new waypoint;
+           wpt->name      = "Runway Takeoff";
+           wpt->latitude  = lat2;
+           wpt->longitude = lon2;
+           wpt->altitude  = apt->getElevation();
+           wpt->speed     = 15; 
+           wpt->crossat   = -10000;
+           wpt->gear_down = true;
+           wpt->flaps_down= true;
+           wpt->finished  = false;
+           wpt->on_ground = true;
+           waypoints.push_back(wpt);   
+         } else {
+           int node;
+           route.first();
+           while(route.next(&node))
+             {
+               //i = ids.end()-1;
+               //cerr << "Creating Node: " << node << endl;
+               FGTaxiNode *tn = apt->getGroundNetwork()->findNode(node);
+               //ids.pop_back();  
+               wpt = new waypoint;
+               wpt->name      = "taxiway"; // fixme: should be the name of the taxiway
+               wpt->latitude  = tn->getLatitude();
+               wpt->longitude = tn->getLongitude();
+               wpt->altitude  = apt->getElevation(); // should maybe be tn->elev too
+               wpt->speed     = 15; 
+               wpt->crossat   = -10000;
+               wpt->gear_down = true;
+               wpt->flaps_down= true;
+               wpt->finished  = false;
+               wpt->on_ground = true;
+               waypoints.push_back(wpt);
+             }
+           cerr << endl;
+         }
+         //exit(1);
+       }
+      else 
+       {
+         //Add the runway startpoint;
+         wpt = new waypoint;
+         wpt->name      = "Airport Center";
+         wpt->latitude  = apt->getLatitude();
+         wpt->longitude = apt->getLongitude();
+         wpt->altitude  = apt->getElevation();
+         wpt->speed     = 15; 
+         wpt->crossat   = -10000;
+         wpt->gear_down = true;
+         wpt->flaps_down= true;
+         wpt->finished  = false;
+         wpt->on_ground = true;
+         waypoints.push_back(wpt);
+         
+         //Add the runway startpoint;
+         wpt = new waypoint;
+         wpt->name      = "Runway Takeoff";
+         wpt->latitude  = lat2;
+         wpt->longitude = lon2;
+         wpt->altitude  = apt->getElevation();
+         wpt->speed     = 15; 
+         wpt->crossat   = -10000;
+         wpt->gear_down = true;
+         wpt->flaps_down= true;
+         wpt->finished  = false;
+         wpt->on_ground = true;
+         waypoints.push_back(wpt);
+         //wpt = new waypoint;
+         //wpt->finished = false;
+         //waypoints.push_back(wpt);  // add one more to prevent a segfault. 
+       }
     }
-  else
+  else  // Landing taxi
     {
-      //direction = (rand() % 360);
-      //geo_direct_wgs_84 ( 0, arr->getLatitude(), arr->getLongitude(), direction, 
-      //100,
-      //&lat2, &lon2, &az2 );
+      //string name;
+      // "NOTE: this is currently fixed to "com" for commercial traffic
+      // Should be changed to be used dynamically to allow "gen" and "mil"
+      // as well
+      //apt->getActiveRunway("com", 1, &name);
+      //if (!(globals->get_runways()->search(apt->getId(), 
+      //                                   name, 
+      //                           &rwy)))
+      //{//
+      //cout << "Failed to find runway for " << apt->getId() << endl;
+      // Hmm, how do we handle a potential error like this?
+      // exit(1);
+      //       }
+      //string test;
+      //apt->getActiveRunway(string("com"), 1, &test);
+      //exit(1);
       
-      // This next statement really requires the flight plan to be
-      // split up into smaller sections, because 
-      // gate assignments will typically not be known until minutes before 
-      // landing, and certainly not at the start of a 10 hour flight.
+      //heading = rwy._heading;
+      //double azimuth = heading + 180.0;
+      //while ( azimuth >= 360.0 ) { azimuth -= 360.0; }
+      //geo_direct_wgs_84 ( 0, rwy._lat, rwy._lon, azimuth, 
+      //                 rwy._length * SG_FEET_TO_METER * 0.5 - 5.0,
+      //                 &lat2, &lon2, &az2 );
       apt->getAvailableParking(&lat, &lon, &heading, &gateId, radius, fltType, acType, airline);
       heading += 180.0;
       if (heading > 360)
@@ -297,23 +361,105 @@ void FGAIFlightPlan::createTaxi(bool firstFlight, int direction, FGAirport *apt,
       geo_direct_wgs_84 ( 0, lat, lon, heading, 
                          100,
                          &lat2, &lon2, &az2 );
-      //Add the runway center
-      wpt = new waypoint;
-      wpt->name      = "Airport Center";
-      wpt->latitude  = apt->getLatitude();
-      wpt->longitude = apt->getLongitude();
-      wpt->altitude  = apt->getElevation();
-      wpt->speed     = 15; 
-      wpt->crossat   = -10000;
-      wpt->gear_down = true;
-      wpt->flaps_down= true;
-      wpt->finished  = false;
-      wpt->on_ground = true;
-      waypoints.push_back(wpt);
+      double lat3 = (*(waypoints.end()-1))->latitude;
+      double lon3 = (*(waypoints.end()-1))->longitude;
+      cerr << (*(waypoints.end()-1))->name << endl;
+      if (apt->getGroundNetwork()->exists())
+       {
+         intVec ids;
+         int runwayId = apt->getGroundNetwork()->findNearestNode(lat3, lon3);
+         //int currId   = apt->getGroundNetwork()->findNearestNode(latitude,longitude);
+         //exit(1);
+         
+         // A negative gateId indicates an overflow parking, use a
+         // fallback mechanism for this. 
+         // Starting from gate 0 is a bit of a hack...
+         FGTaxiRoute route;
+         if (gateId >= 0)
+           route = apt->getGroundNetwork()->findShortestRoute(runwayId, gateId);
+         else
+           route = apt->getGroundNetwork()->findShortestRoute(runwayId, 0);
+         intVecIterator i;
+         //cerr << "creating route : ";
+         // No route found: go from gate directly to runway
+         if (route.empty()) {
+           //Add the runway startpoint;
+           wpt = new waypoint;
+           wpt->name      = "Airport Center";
+           wpt->latitude  = latitude;
+           wpt->longitude = longitude;
+           wpt->altitude  = apt->getElevation();
+           wpt->speed     = 15; 
+           wpt->crossat   = -10000;
+           wpt->gear_down = true;
+           wpt->flaps_down= true;
+           wpt->finished  = false;
+           wpt->on_ground = true;
+           waypoints.push_back(wpt);
+           
+           //Add the runway startpoint;
+           wpt = new waypoint;
+           wpt->name      = "Runway Takeoff";
+           wpt->latitude  = lat2;
+           wpt->longitude = lon2;
+           wpt->altitude  = apt->getElevation();
+           wpt->speed     = 15; 
+           wpt->crossat   = -10000;
+           wpt->gear_down = true;
+           wpt->flaps_down= true;
+           wpt->finished  = false;
+           wpt->on_ground = true;
+           waypoints.push_back(wpt);   
+         } else {
+           int node;
+           route.first();
+           while(route.next(&node))
+             {
+               //i = ids.end()-1;
+               //cerr << "Creating Node: " << node << endl;
+               FGTaxiNode *tn = apt->getGroundNetwork()->findNode(node);
+               //ids.pop_back();  
+               wpt = new waypoint;
+               wpt->name      = "taxiway"; // fixme: should be the name of the taxiway
+               wpt->latitude  = tn->getLatitude();
+               wpt->longitude = tn->getLongitude();
+               wpt->altitude  = apt->getElevation(); // should maybe be tn->elev too
+               wpt->speed     = 15; 
+               wpt->crossat   = -10000;
+               wpt->gear_down = true;
+               wpt->flaps_down= true;
+               wpt->finished  = false;
+               wpt->on_ground = true;
+               waypoints.push_back(wpt);
+             }
+           cerr << endl;
+         }
+         //exit(1);
+       }
+      else
+       {
+         //Add the runway startpoint;
+         wpt = new waypoint;
+         wpt->name      = "Airport Center";
+         wpt->latitude  = apt->getLatitude();
+         wpt->longitude = apt->getLongitude();
+         wpt->altitude  = apt->getElevation();
+         wpt->speed     = 15; 
+         wpt->crossat   = -10000;
+         wpt->gear_down = true;
+         wpt->flaps_down= true;
+         wpt->finished  = false;
+         wpt->on_ground = true;
+         waypoints.push_back(wpt);
+         
+       }
+
+
+
 
       // Add the final destination waypoint
       wpt = new waypoint;
-      wpt->name      = "Begin Parkingg"; //apt->getId(); //wpt_node->getStringValue("name", "END");
+      wpt->name      = "Begin Parking"; //apt->getId(); //wpt_node->getStringValue("name", "END");
       wpt->latitude  = lat2;
       wpt->longitude = lon2;
       wpt->altitude  = apt->getElevation();
@@ -364,10 +510,13 @@ void FGAIFlightPlan::createTakeOff(bool firstFlight, FGAirport *apt, double spee
   // Preferential runway use schema's 
   if (firstFlight)
     {
-      string name;
-      apt->getActiveRunway("com", 1, &name);
+      //string name;
+       // "NOTE: this is currently fixed to "com" for commercial traffic
+      // Should be changed to be used dynamically to allow "gen" and "mil"
+      // as well
+      apt->getActiveRunway("com", 1, &activeRunway);
        if (!(globals->get_runways()->search(apt->getId(), 
-                                             name
+                                             activeRunway
                                              &rwy)))
          {
            cout << "Failed to find runway for " << apt->getId() << endl;
@@ -456,10 +605,13 @@ void FGAIFlightPlan::createClimb(bool firstFlight, FGAirport *apt, double speed,
   // Preferential runway use schema's 
   if (firstFlight)
     {
-      string name;
-      apt->getActiveRunway("com", 1, &name);
+      //string name;
+      // "NOTE: this is currently fixed to "com" for commercial traffic
+      // Should be changed to be used dynamically to allow "gen" and "mil"
+      // as well
+      apt->getActiveRunway("com", 1, &activeRunway);
        if (!(globals->get_runways()->search(apt->getId(), 
-                                             name
+                                             activeRunway
                                              &rwy)))
          {
            cout << "Failed to find runway for " << apt->getId() << endl;
@@ -554,10 +706,11 @@ void FGAIFlightPlan::createCruise(bool firstFlight, FGAirport *dep, FGAirport *a
   waypoints.push_back(wpt); 
   //Beginning of Decent
  
-  string name;
-  arr->getActiveRunway("com", 2, &name);
+  //string name;
+  // should be changed dynamically to allow "gen" and "mil"
+  arr->getActiveRunway("com", 2, &activeRunway);
   if (!(globals->get_runways()->search(arr->getId(), 
-                                      name
+                                      activeRunway
                                       &rwy)))
     {
       cout << "Failed to find runway for " << arr->getId() << endl;
@@ -632,10 +785,11 @@ void FGAIFlightPlan::createDecent(FGAirport *apt)
   //resetWaypoints();
 
   //Beginning of Decent
-  string name;
-  apt->getActiveRunway("com", 2, &name);
+  //string name;
+  // allow "mil" and "gen" as well
+  apt->getActiveRunway("com", 2, &activeRunway);
     if (!(globals->get_runways()->search(apt->getId(), 
-                                         name
+                                         activeRunway
                                          &rwy)))
       {
        cout << "Failed to find runway for " << apt->getId() << endl;
index 4a9a8837c6809641628f388e7bbbac7d0d987866..e862af61ea17ae7b1ed32abcb5d6baad0e4ee030 100644 (file)
@@ -37,6 +37,7 @@
 #include <simgear/compiler.h>
 
 #include <plib/sg.h>
+#include <plib/ul.h>
 
 #include <Environment/environment_mgr.hxx>
 #include <Environment/environment.hxx>
@@ -53,6 +54,7 @@
 #include "simple.hxx"
 
 SG_USING_STD(sort);
+SG_USING_STD(random_shuffle);
 
 /******************************************************************************
  * ScheduleTime
@@ -563,28 +565,10 @@ void  FGRunwayPreference::error (const char * message, int line, int column) {
        << endl;
 }
 
-/*********************************************************************************
- * FGParking
- ********************************************************************************/
-FGParking::FGParking(double lat,
-                    double lon,
-                    double hdg,
-                    double rad,
-                    int idx,
-                    string name,
-                    string tpe,
-                    string codes)
-{
-  latitude     = lat;
-  longitude    = lon;
-  heading      = hdg;
-  parkingName  = name;
-  index        = idx;
-  type         = tpe;
-  airlineCodes = codes;
-}
-
-double FGParking::processPosition(string pos)
+/*****************************************************************************
+ * Helper function for parsing position string
+ ****************************************************************************/
+double processPosition(string pos)
 {
   string prefix;
   string subs;
@@ -608,6 +592,29 @@ double FGParking::processPosition(string pos)
   return value;
 }
 
+
+/*********************************************************************************
+ * FGParking
+ ********************************************************************************/
+FGParking::FGParking(double lat,
+                    double lon,
+                    double hdg,
+                    double rad,
+                    int idx,
+                    string name,
+                    string tpe,
+                    string codes)
+{
+  latitude     = lat;
+  longitude    = lon;
+  heading      = hdg;
+  parkingName  = name;
+  index        = idx;
+  type         = tpe;
+  airlineCodes = codes;
+}
+
+
 /***************************************************************************
  * FGAirport
  ***************************************************************************/
@@ -664,6 +671,22 @@ FGAirport::FGAirport(string id, double lon, double lat, double elev, string name
  
 }
 
+// Initialization required after XMLRead
+void FGAirport::init() 
+{
+  // This may seem a bit weird to first randomly shuffle the parkings
+  // and then sort them again. However, parkings are sorted here by ascending 
+  // radius. Since many parkings have similar radii, with each radius class they will
+  // still be allocated relatively systematically. Randomizing prior to sorting will
+  // prevent any initial orderings to be destroyed, leading (hopefully) to a more 
+  // naturalistic gate assignment. 
+  random_shuffle(parkings.begin(), parkings.end());
+  sort(parkings.begin(), parkings.end());
+  // add the gate positions to the ground network. 
+  groundNetwork.addNodes(&parkings);
+  groundNetwork.init();
+}
+
 bool FGAirport::getAvailableParking(double *lat, double *lon, double *heading, int *gateId, double rad, string flType, string acType, string airline)
 {
   bool found = false;
@@ -893,6 +916,10 @@ void  FGAirport::endXML () {
 void  FGAirport::startElement (const char * name, const XMLAttributes &atts) {
   // const char *attval;
   FGParking park;
+  FGTaxiNode taxiNode;
+  FGTaxiSegment taxiSegment;
+  int index = 0;
+  taxiSegment.setIndex(index);
   //cout << "Start element " << name << endl;
   string attname;
   string value;
@@ -932,9 +959,35 @@ void  FGAirport::startElement (const char * name, const XMLAttributes &atts) {
        }
       park.setName((gateName+gateNumber));
       parkings.push_back(park);
-    }  
+    }
+  if (name == string("node")) 
+    {
+      for (int i = 0; i < atts.size() ; i++)
+       {
+         attname = atts.getName(i);
+         if (attname == string("index"))
+           taxiNode.setIndex(atoi(atts.getValue(i)));
+         if (attname == string("lat"))
+           taxiNode.setLatitude(atts.getValue(i));
+         if (attname == string("lon"))
+           taxiNode.setLongitude(atts.getValue(i));
+       }
+      groundNetwork.addNode(taxiNode);
+    }
+  if (name == string("arc")) 
+    {
+      taxiSegment.setIndex(++index);
+      for (int i = 0; i < atts.size() ; i++)
+       {
+         attname = atts.getName(i);
+         if (attname == string("begin"))
+           taxiSegment.setStartNodeRef(atoi(atts.getValue(i)));
+         if (attname == string("end"))
+           taxiSegment.setEndNodeRef(atoi(atts.getValue(i)));
+       }
+      groundNetwork.addSegment(taxiSegment);
+    }
   // sort by radius, in asending order, so that smaller gates are first in the list
-  sort(parkings.begin(), parkings.end());
 }
 
 void  FGAirport::endElement (const char * name) {
@@ -1145,6 +1198,290 @@ void FGAirport::chooseRunwayFallback(string *runway)
   return; // generic fall back goes here
 }
 
+
+
+/**************************************************************************
+ * FGTaxiNode
+ *************************************************************************/
+FGTaxiNode::FGTaxiNode()
+{
+}
+
+/***************************************************************************
+ * FGTaxiSegment
+ **************************************************************************/
+FGTaxiSegment::FGTaxiSegment()
+{
+}
+
+void FGTaxiSegment::setStart(FGTaxiNodeVector *nodes)
+{
+  FGTaxiNodeVectorIterator i = nodes->begin();
+  while (i != nodes->end())
+    {
+      if (i->getIndex() == startNode)
+       {
+         start = i->getAddress();
+         i->addSegment(this);
+         return;
+       }
+      i++;
+    }
+}
+
+void FGTaxiSegment::setEnd(FGTaxiNodeVector *nodes)
+{
+  FGTaxiNodeVectorIterator i = nodes->begin();
+  while (i != nodes->end())
+    {
+      if (i->getIndex() == endNode)
+       {
+         end = i->getAddress();
+         return;
+       }
+      i++;
+    }
+}
+
+// There is probably a computationally cheaper way of 
+// doing this.
+void FGTaxiSegment::setTrackDistance()
+{
+  double course;
+  SGWayPoint first  (start->getLongitude(),
+                    start->getLatitude(),
+                    0);
+  SGWayPoint second (end->getLongitude(),
+                    end->getLatitude(),
+                    0);
+  first.CourseAndDistance(second, &course, &length);
+  
+}
+
+bool FGTaxiRoute::next(int *val) 
+{ 
+  //for (intVecIterator i = nodes.begin(); i != nodes.end(); i++)
+  //  cerr << "FGTaxiRoute contains : " << *(i) << endl;
+  //cerr << "Offset from end: " << nodes.end() - currNode << endl;
+  //if (currNode != nodes.end())
+  //  cerr << "true" << endl;
+  //else
+  //  cerr << "false" << endl;
+      
+  if (currNode == nodes.end())
+    return false;
+  *val = *(currNode); 
+  currNode++;
+  return true;
+};
+/***************************************************************************
+ * FGGroundNetwork()
+ **************************************************************************/
+
+FGGroundNetwork::FGGroundNetwork()
+{
+  hasNetwork = false;
+}
+
+void FGGroundNetwork::addSegment(FGTaxiSegment seg)
+{
+  segments.push_back(seg);
+}
+
+void FGGroundNetwork::addNode(FGTaxiNode node)
+{
+  nodes.push_back(node);
+}
+
+void FGGroundNetwork::addNodes(FGParkingVec *parkings)
+{
+  FGTaxiNode n;
+  FGParkingVecIterator i = parkings->begin();
+  while (i != parkings->end())
+    {
+      n.setIndex(i->getIndex());
+      n.setLatitude(i->getLatitude());
+      n.setLongitude(i->getLongitude());
+      nodes.push_back(n);
+
+      i++;
+    }
+}
+
+
+
+void FGGroundNetwork::init()
+{
+  hasNetwork = true;
+  FGTaxiSegmentVectorIterator i = segments.begin();
+  while(i != segments.end()) {
+    //cerr << "initializing node " << i->getIndex() << endl;
+    i->setStart(&nodes);
+    i->setEnd  (&nodes);
+    i->setTrackDistance();
+    //cerr << "Track distance = " << i->getLength() << endl;
+    //cerr << "Track ends at"      << i->getEnd()->getIndex() << endl;
+    i++;
+  }
+  //exit(1);
+}
+
+int FGGroundNetwork::findNearestNode(double lat, double lon)
+{
+  double minDist = HUGE;
+  double course, dist;
+  int index;
+  SGWayPoint first  (lon,
+                    lat,
+                    0);
+  
+  for (FGTaxiNodeVectorIterator 
+        itr = nodes.begin();
+       itr != nodes.end(); itr++)
+    {
+      double course;
+      SGWayPoint second (itr->getLongitude(),
+                        itr->getLatitude(),
+                        0);
+      first.CourseAndDistance(second, &course, &dist);
+      if (dist < minDist)
+       {
+         minDist = dist;
+         index = itr->getIndex();
+         //cerr << "Minimum distance of " << minDist << " for index " << index << endl;
+       }
+    }
+  return index;
+}
+
+FGTaxiNode *FGGroundNetwork::findNode(int idx)
+{
+  for (FGTaxiNodeVectorIterator 
+        itr = nodes.begin();
+       itr != nodes.end(); itr++)
+    {
+      if (itr->getIndex() == idx)
+       return itr->getAddress();
+    }
+  return 0;
+}
+
+FGTaxiRoute FGGroundNetwork::findShortestRoute(int start, int end) 
+{
+  foundRoute = false;
+  totalDistance = 0;
+  FGTaxiNode *firstNode = findNode(start);
+  FGTaxiNode *lastNode  = findNode(end);
+  //prevNode = prevPrevNode = -1;
+  //prevNode = start;
+  routes.clear();
+  traceStack.clear();
+  trace(firstNode, end, 0, 0);
+  FGTaxiRoute empty;
+  
+  if (!foundRoute)
+    {
+      cerr << "Failed to find route from waypoint " << start << " to " << end << endl;
+      exit(1);
+    }
+  sort(routes.begin(), routes.end());
+  //for (intVecIterator i = route.begin(); i != route.end(); i++)
+  //  {
+  //    rte->push_back(*i);
+  //  }
+  
+  if (routes.begin() != routes.end())
+    return *(routes.begin());
+  else
+    return empty;
+}
+
+
+void FGGroundNetwork::trace(FGTaxiNode *currNode, int end, int depth, double distance)
+{
+  traceStack.push_back(currNode->getIndex());
+  totalDistance += distance;
+  //cerr << "Starting trace " << depth << " total distance: " << totalDistance<< endl;
+  //<< currNode->getIndex() << endl;
+
+  // If the current route matches the required end point we found a valid route
+  // So we can add this to the routing table
+  if (currNode->getIndex() == end)
+    {
+      //cerr << "Found route : " <<  totalDistance << "" << " " << *(traceStack.end()-1) << endl;
+      routes.push_back(FGTaxiRoute(traceStack,totalDistance));
+      traceStack.pop_back();
+      if (!(foundRoute))
+       maxDistance = totalDistance;
+      else
+       if (totalDistance < maxDistance)
+         maxDistance = totalDistance;
+      foundRoute = true;
+      totalDistance -= distance;
+      return;
+    }
+
+  // search if the currentNode has been encountered before
+  // if so, we should step back one level, because it is
+  // rather rediculous to proceed further from here. 
+  // if the current node has not been encountered before,
+  // i should point to traceStack.end()-1; and we can continue
+  // if i is not traceStack.end, the previous node was found, 
+  // and we should return. 
+  // This only works at trace levels of 1 or higher though
+  if (depth > 0) {
+    intVecIterator i = traceStack.begin();
+    while ((*i) != currNode->getIndex()) {
+      //cerr << "Route so far : " << (*i) << endl;
+      i++;
+    }
+    if (i != traceStack.end()-1) {
+      traceStack.pop_back();
+      totalDistance -= distance;
+      return;
+    }
+    // If the total distance from start to the current waypoint
+    // is longer than that of a route we can also stop this trace 
+    // and go back one level. 
+    if ((totalDistance > maxDistance) && foundRoute)
+      {
+       //cerr << "Stopping rediculously long trace: " << totalDistance << endl;
+       traceStack.pop_back();
+       totalDistance -= distance;
+       return;
+      }
+  }
+  
+  //cerr << "2" << endl;
+  if (currNode->getBeginRoute() != currNode->getEndRoute())
+    {
+      //cerr << "3" << endl;
+      for (FGTaxiSegmentPointerVectorIterator 
+            i = currNode->getBeginRoute();
+          i != currNode->getEndRoute();
+          i++)
+       {
+         //cerr << (*i)->getLenght() << endl;
+         trace((*i)->getEnd(), end, depth+1, (*i)->getLength());
+       //  {
+       //      // cerr << currNode -> getIndex() << " ";
+       //      route.push_back(currNode->getIndex());
+       //      return true;
+       //    }
+       }
+    }
+  else
+    {
+      cerr << "4" << endl;
+    }
+  traceStack.pop_back();
+  totalDistance -= distance;
+  return;
+}
+
+
+
 /******************************************************************************
  * FGAirportList
  *****************************************************************************/
@@ -1199,6 +1536,7 @@ void FGAirportList::add( const string id, const double longitude,
     {
         try {
             readXML(parkpath.str(),*a);
+           a->init();
         } 
         catch  (const sg_exception &e) {
             //cerr << "unable to read " << parkpath.str() << endl;
index 901cb06d1d7b8c26f459e14946d7be1b57532ed0..eea3c0edecf702b7cf46aac894ae03b3f0cb1712 100644 (file)
@@ -36,7 +36,8 @@
 #ifdef HAVE_CONFIG_H
 #  include <config.h>
 #endif
-
+#include <simgear/math/point3d.hxx>
+#include <simgear/route/waypoint.hxx>
 #include <simgear/compiler.h>
 #include <simgear/xml/easyxml.hxx>
 
@@ -56,6 +57,8 @@ typedef vector<string>::const_iterator stringVecConstIterator;
 
 typedef vector<time_t> timeVec;
 typedef vector<time_t>::const_iterator timeVecConstIterator;
+
+
 /***************************************************************************/
 class ScheduleTime {
 private:
@@ -177,6 +180,8 @@ public:
   virtual void error (const char * message, int line, int column);
 };
 
+double processPosition(string pos);
+
 class FGParking {
 private:
   double latitude;
@@ -188,10 +193,9 @@ private:
   string type;
   string airlineCodes;
  
-
   bool available;
 
-  double processPosition(string pos);
+  
 
 public:
   FGParking() { available = true;};
@@ -232,7 +236,138 @@ typedef vector<FGParking> FGParkingVec;
 typedef vector<FGParking>::iterator FGParkingVecIterator;
 typedef vector<FGParking>::const_iterator FGParkingVecConstIterator;
 
+class FGTaxiSegment; // forward reference
+
+typedef vector<FGTaxiSegment>  FGTaxiSegmentVector;
+typedef vector<FGTaxiSegment*> FGTaxiSegmentPointerVector;
+typedef vector<FGTaxiSegment>::iterator FGTaxiSegmentVectorIterator;
+typedef vector<FGTaxiSegment*>::iterator FGTaxiSegmentPointerVectorIterator;
+
+/**************************************************************************************
+ * class FGTaxiNode
+ *************************************************************************************/
+class FGTaxiNode 
+{
+private:
+  double lat;
+  double lon;
+  int index;
+  FGTaxiSegmentPointerVector next; // a vector to all the segments leaving from this node
+  
+public:
+  FGTaxiNode();
+  FGTaxiNode(double, double, int);
+
+  void setIndex(int idx)                  { index = idx;};
+  void setLatitude (double val)           { lat = val;};
+  void setLongitude(double val)           { lon = val;};
+  void setLatitude (string val)           { lat = processPosition(val);  };
+  void setLongitude(string val)           { lon = processPosition(val);  };
+  void addSegment(FGTaxiSegment *segment) { next.push_back(segment); };
+  
+  double getLatitude() { return lat;};
+  double getLongitude(){ return lon;};
+
+  int getIndex() { return index; };
+  FGTaxiNode *getAddress() { return this;};
+  FGTaxiSegmentPointerVectorIterator getBeginRoute() { return next.begin(); };
+  FGTaxiSegmentPointerVectorIterator getEndRoute()   { return next.end();   }; 
+};
+
+typedef vector<FGTaxiNode> FGTaxiNodeVector;
+typedef vector<FGTaxiNode>::iterator FGTaxiNodeVectorIterator;
+
+/***************************************************************************************
+ * class FGTaxiSegment
+ **************************************************************************************/
+class FGTaxiSegment
+{
+private:
+  int startNode;
+  int endNode;
+  double length;
+  FGTaxiNode *start;
+  FGTaxiNode *end;
+  int index;
+
+public:
+  FGTaxiSegment();
+  FGTaxiSegment(FGTaxiNode *, FGTaxiNode *, int);
+
+  void setIndex        (int val) { index     = val; };
+  void setStartNodeRef (int val) { startNode = val; };
+  void setEndNodeRef   (int val) { endNode   = val; };
 
+  void setStart(FGTaxiNodeVector *nodes);
+  void setEnd  (FGTaxiNodeVector *nodes);
+  void setTrackDistance();
+
+  FGTaxiNode * getEnd() { return end;};
+  double getLength() { return length; };
+  int getIndex() { return index; };
+
+  
+};
+
+
+typedef vector<int> intVec;
+typedef vector<int>::iterator intVecIterator;
+
+class FGTaxiRoute
+{
+private:
+  intVec nodes;
+  double distance;
+  intVecIterator currNode;
+
+public:
+  FGTaxiRoute() { distance = 0; currNode = nodes.begin(); };
+  FGTaxiRoute(intVec nds, double dist) { nodes = nds; distance = dist; currNode = nodes.begin();};
+  bool operator< (const FGTaxiRoute &other) const {return distance < other.distance; };
+  bool empty () { return nodes.begin() == nodes.end(); };
+  bool next(int *val); 
+  
+  void first() { currNode = nodes.begin(); };
+};
+
+typedef vector<FGTaxiRoute> TaxiRouteVector;
+typedef vector<FGTaxiRoute>::iterator TaxiRouteVectorIterator;
+
+/**************************************************************************************
+ * class FGGroundNetWork
+ *************************************************************************************/
+class FGGroundNetwork
+{
+private:
+  bool hasNetwork;
+  FGTaxiNodeVector    nodes;
+  FGTaxiSegmentVector segments;
+  //intVec route;
+  intVec traceStack;
+  TaxiRouteVector routes;
+  
+  bool foundRoute;
+  double totalDistance, maxDistance;
+  
+public:
+  FGGroundNetwork();
+
+  void addNode   (FGTaxiNode node);
+  void addNodes  (FGParkingVec *parkings);
+  void addSegment(FGTaxiSegment seg); 
+
+  void init();
+  bool exists() { return hasNetwork; };
+  int findNearestNode(double lat, double lon);
+  FGTaxiNode *findNode(int idx);
+  FGTaxiRoute findShortestRoute(int start, int end);
+  void trace(FGTaxiNode *, int, int, double dist);
+};
+
+/***************************************************************************************
+ *
+ **************************************************************************************/
 class FGAirport : public XMLVisitor{
 private:
   string _id;
@@ -244,6 +379,7 @@ private:
   bool _has_metar;
   FGParkingVec parkings;
   FGRunwayPreference rwyPrefs;
+  FGGroundNetwork groundNetwork;
 
   time_t lastUpdate;
   string prevTrafficType;
@@ -262,6 +398,8 @@ public:
   FGAirport(const FGAirport &other);
   //operator= (FGAirport &other);
   FGAirport(string id, double lon, double lat, double elev, string name, bool has_metar);
+
+  void init();
   void getActiveRunway(string trafficType, int action, string *runway);
   void chooseRunwayFallback(string *runway);
   bool getAvailableParking(double *lat, double *lon, double *heading, int *gate, double rad, string fltype, 
@@ -272,6 +410,8 @@ public:
   string getParkingName(int i); 
   string getId() const { return _id;};
   const string &getName() const { return _name;};
+  //FGAirport *getAddress() { return this; };
+  //const string &getName() const { return _name;};
   // Returns degrees
   double getLongitude() const { return _longitude;};
   // Returns degrees
@@ -279,6 +419,7 @@ public:
   // Returns ft
   double getElevation() const { return _elevation;};
   bool   getMetar()     const { return _has_metar;};
+ FGGroundNetwork* getGroundNetwork() { return &groundNetwork; };
   
 
   void setId(string id) { _id = id;};
@@ -325,7 +466,7 @@ public:
               const double elevation, const string name, const bool has_metar );
 
     // search for the specified id.
-    // Returns NULL if unsucessfull.
+      // Returns NULL if unsucessfull.
     FGAirport* search( const string& id );
        
        // Search for the next airport in ASCII sequence to the supplied id.
index 6af4287f1029f1b530ed15c1d94f4254dc8c86be..6dfe218da9e1fa47ad50dab8f214365e65b3fbeb 100644 (file)
@@ -392,9 +392,15 @@ bool FGAISchedule::update(time_t now)
          return true;
        } 
     }
-
+  //cerr << "Traffic schedule got to beyond last clause" << endl;
     // EMH: prevent a warning, should this be 'true' instead?
-    return false;
+    // DT: YES. Originally, this code couldn't be reached, but
+    // when the "if(!(AIManagerManager))" clause is false we
+    // fall through right to the end. This is a valid flow.
+    // the actual value is pretty innocent, only it triggers
+    // warning in TrafficManager::update().
+    // (which was added as a sanity check for myself in the first place. :-)
+    return true;
 }