]> git.mxchange.org Git - flightgear.git/commitdiff
Improved selection of active runway (currently AI traffic only).
authordurk <durk>
Sat, 4 Mar 2006 08:49:36 +0000 (08:49 +0000)
committerdurk <durk>
Sat, 4 Mar 2006 08:49:36 +0000 (08:49 +0000)
The original code selected the most preferable runway combination,
regardless of which combination was currently active. This patch
builds in some additional resistance against change, by keeping
track of which runways are already in use, and forces a change
in active runways only when new (wheather/time of day) conditions
force it to do so, resulting in much more consistent runway assignment.
behavior.

src/Airports/dynamics.cxx
src/Airports/dynamics.hxx
src/Airports/runwayprefs.cxx
src/Airports/runwayprefs.hxx

index 517e25bea3f3cda7458f9bcb9c914b351514bb29..4e3384e64e7c666c232249cf6b178d230f44d5da 100644 (file)
@@ -486,60 +486,61 @@ void FGAirportDynamics::getActiveRunway(const string &trafficType, int action, s
          
          windSpeed = stationweather.get_wind_speed_kt();
          windHeading = stationweather.get_wind_from_heading_deg();
-         double averageWindSpeed   = 0;
-         double averageWindHeading = 0;
-         double cosHeading         = 0;
-         double sinHeading         = 0;
-         // Initialize at the beginning of the next day or startup
-         if ((lastUpdate == 0) || (dayStart < lastUpdate))
-           {
-             for (int i = 0; i < 10; i++)
-               {
-                 avWindHeading [i] = windHeading;
-                 avWindSpeed   [i] = windSpeed;
-               }
-           }
-         else
-           {
-             if (windSpeed != avWindSpeed[9]) // update if new metar data 
-               {
-                 // shift the running average
-                 for (int i = 0; i < 9 ; i++)
-                   {
-                     avWindHeading[i] = avWindHeading[i+1];
-                     avWindSpeed  [i] = avWindSpeed  [i+1];
-                   }
-               } 
-             avWindHeading[9] = windHeading;
-             avWindSpeed  [9] = windSpeed;
-           }
+        //  double averageWindSpeed   = 0;
+//       double averageWindHeading = 0;
+//       double cosHeading         = 0;
+//       double sinHeading         = 0;
+//       // Initialize at the beginning of the next day or startup
+//       if ((lastUpdate == 0) || (dayStart < lastUpdate))
+//         {
+//           for (int i = 0; i < 10; i++)
+//             {
+//               avWindHeading [i] = windHeading;
+//               avWindSpeed   [i] = windSpeed;
+//             }
+//         }
+//       else
+//         {
+//           if (windSpeed != avWindSpeed[9]) // update if new metar data 
+//             {
+//               // shift the running average
+//               for (int i = 0; i < 9 ; i++)
+//                 {
+//                   avWindHeading[i] = avWindHeading[i+1];
+//                   avWindSpeed  [i] = avWindSpeed  [i+1];
+//                 }
+//             } 
+//           avWindHeading[9] = windHeading;
+//           avWindSpeed  [9] = windSpeed;
+//         }
          
-         for (int i = 0; i < 10; i++)
-           {
-             averageWindSpeed   += avWindSpeed   [i];
-             //averageWindHeading += avWindHeading [i];
-             cosHeading += cos(avWindHeading[i] * SG_DEGREES_TO_RADIANS);
-             sinHeading += sin(avWindHeading[i] * SG_DEGREES_TO_RADIANS);
-           }
-         averageWindSpeed   /= 10;
-         //averageWindHeading /= 10;
-         cosHeading /= 10;
-         sinHeading /= 10;
-         averageWindHeading = atan2(sinHeading, cosHeading) *SG_RADIANS_TO_DEGREES;
-         if (averageWindHeading < 0)
-           averageWindHeading += 360.0;
-         //cerr << "Wind Heading " << windHeading << " average " << averageWindHeading << endl;
-         //cerr << "Wind Speed   " << windSpeed   << " average " << averageWindSpeed   << endl;
-         lastUpdate = dayStart;
-             //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.
-         //}
+//       for (int i = 0; i < 10; i++)
+//         {
+//           averageWindSpeed   += avWindSpeed   [i];
+//           //averageWindHeading += avWindHeading [i];
+//           cosHeading += cos(avWindHeading[i] * SG_DEGREES_TO_RADIANS);
+//           sinHeading += sin(avWindHeading[i] * SG_DEGREES_TO_RADIANS);
+//         }
+//       averageWindSpeed   /= 10;
+//       //averageWindHeading /= 10;
+//       cosHeading /= 10;
+//       sinHeading /= 10;
+//       averageWindHeading = atan2(sinHeading, cosHeading) *SG_RADIANS_TO_DEGREES;
+//       if (averageWindHeading < 0)
+//         averageWindHeading += 360.0;
+//       //cerr << "Wind Heading " << windHeading << " average " << averageWindHeading << endl;
+//       //cerr << "Wind Speed   " << windSpeed   << " average " << averageWindSpeed   << endl;
+//       lastUpdate = dayStart;
+//           //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 scheduleName;
          //cerr << "finding active Runway for" << _id << endl;
          //cerr << "Nr of seconds since day start << " << dayStart << endl;
+
          ScheduleTime *currSched;
          //cerr << "A"<< endl;
          currSched = rwyPrefs.getSchedule(trafficType.c_str());
@@ -559,7 +560,19 @@ void FGAirportDynamics::getActiveRunway(const string &trafficType, int action, s
            return;
          nrActiveRunways = currRunwayGroup->getNrActiveRunways();
          //cerr << "Nr of Active Runways = " << nrActiveRunways << endl; 
-         currRunwayGroup->setActive(_id, averageWindSpeed, averageWindHeading, maxTail, maxCross); 
+
+         // 
+         currRunwayGroup->setActive(_id, 
+                                    windSpeed, 
+                                    windHeading, 
+                                    maxTail, 
+                                    maxCross, 
+                                    &currentlyActive); 
+
+         // Note that I SHOULD keep three lists in memory, one for 
+         // general aviation, one for commercial and one for military
+         // traffic.
+         currentlyActive.clear();
          nrActiveRunways = currRunwayGroup->getNrActiveRunways();
          for (int i = 0; i < nrActiveRunways; i++)
            {
@@ -568,11 +581,13 @@ void FGAirportDynamics::getActiveRunway(const string &trafficType, int action, s
              if (type == "landing")
                {
                  landing.push_back(name);
+                 currentlyActive.push_back(name);
                  //cerr << "Landing " << name << endl; 
                }
              if (type == "takeoff")
                {
                  takeoff.push_back(name);
+                 currentlyActive.push_back(name);
                  //cerr << "takeoff " << name << endl;
                }
            }
@@ -582,6 +597,9 @@ void FGAirportDynamics::getActiveRunway(const string &trafficType, int action, s
          int nr = takeoff.size();
          if (nr)
            {
+             // Note that the randomization below, is just a placeholder to choose between
+             // multiple active runways for this action. This should be
+             // under ATC control.
              runway = takeoff[(rand() %  nr)];
            }
          else
index 30b4bf7f9d991eeaddd8bdbffd32e50f1ce15294..4eb8b4bc179c99bbb03227717ed07266cd5b5bc7 100644 (file)
@@ -45,6 +45,7 @@ private:
   string prevTrafficType;
   stringVec landing;
   stringVec takeoff;
+  stringVec currentlyActive;
 
   // Experimental keep a running average of wind dir and speed to prevent
   // Erratic runway changes. 
index d549cac5a3a46ad1f1cc990322276e8a6d4a88f3..e829c8dd057dea344a22f21f721b108a989f9c8e 100644 (file)
@@ -197,7 +197,8 @@ void RunwayGroup::setActive(const string &aptId,
                            double windSpeed, 
                            double windHeading, 
                            double maxTail, 
-                           double maxCross)
+                           double maxCross,
+                           stringVec *currentlyActive)
 {
 
   FGRunway rwy;
@@ -209,16 +210,31 @@ void RunwayGroup::setActive(const string &aptId,
   double crossWind;
   double tailWind;
   string name;
+  //stringVec names;
+  int bestMatch = 0, bestChoice = 0;
 
   if (activeRwys > 0)
-    {
+    {  
+      // Now downward iterate across all the possible preferences
+      // starting by the least preferred choice working toward the most preferred choice
+
       nrOfPreferences = rwyList[0].getRwyList()->size();
-      for (int i = 0; i < nrOfPreferences; i++)
+      bool validSelection = true;
+      bool foundValidSelection = false;
+      for (int i = nrOfPreferences-1; i >= 0; i--)
        {
-         bool validSelection = true;
+         int match = 0;
+         
+
+         // Test each runway listed in the preference to see if it's possible to use
+         // If one runway of the selection isn't allowed, we need to exclude this
+         // preference, however, we don't want to stop right there, because we also
+         // don't want to randomly swap runway preferences, unless there is a need to. 
+         //
+
          for (int j = 0; j < activeRwys; j++)
            {
-             //cerr << "I J " << i << " " << j << endl;
+             validSelection = true;
              name = rwyList[j].getRwyList(i);
              //cerr << "Name of Runway: " << name << endl;
              if (globals->get_runways()->search( aptId, 
@@ -238,20 +254,42 @@ void RunwayGroup::setActive(const string &aptId,
                  //cerr << "Tailwind : " << tailWind << endl;
                  //cerr << "Crosswnd : " << crossWind << endl;
                  if ((tailWind > maxTail) || (crossWind > maxCross))
-                   validSelection = false;
+                   {
+                     //cerr << "Invalid : ";
+                     validSelection = false;
+                  }
+                 else 
+                   {
+                     //cerr << "Valid   : ";
+                 }
                }else {
-                 SG_LOG( SG_GENERAL, SG_INFO, "Failed to find runway " << name << " at " << aptId );
-                 exit(1);
-               }
-
+               SG_LOG( SG_GENERAL, SG_INFO, "Failed to find runway " << name << " at " << aptId );
+               exit(1);
+             }
            }
-         if (validSelection)
+         if (validSelection) 
            {
-             //cerr << "Valid runay selection : " << i << endl;
-             nrActive = activeRwys;
-             active = i;
-             return;
-           }
+             //cerr << "Valid   : ";
+             foundValidSelection = true;
+             for (stringVecIterator it = currentlyActive->begin(); 
+                  it != currentlyActive->end(); it++)
+               {
+                 if ((*it) == name)
+                   match++;
+                 if (match >= bestMatch) {
+                   bestMatch = match;
+                   bestChoice = i;
+                 }
+               }
+           } 
+         //cerr << "Preference " << i << " bestMatch " << bestMatch << " choice " << bestChoice << endl;
+       }
+      if (foundValidSelection)
+       {
+         //cerr << "Valid runay selection : " << bestChoice << endl;
+         nrActive = activeRwys;
+         active = bestChoice;
+         return;
        }
       // If this didn't work, due to heavy winds, try again
       // but select only one landing and one takeoff runway. 
@@ -280,16 +318,11 @@ void RunwayGroup::setActive(const string &aptId,
                {
                  //cerr << "Succes" << endl;
                  hdgDiff = fabs(windHeading - rwy._heading);
-                 //cerr << "Wind Heading: " << windHeading << "Runway Heading: " <<rwy._heading << endl;
-                 //cerr << "Wind Speed  : " << windSpeed << endl;
                  if (hdgDiff > 180)
                    hdgDiff = 360 - hdgDiff;
-                 //cerr << "Heading diff: " << hdgDiff << endl;
                  hdgDiff *= ((2*M_PI)/360.0); // convert to radians
                  crossWind = windSpeed * sin(hdgDiff);
                  tailWind  = -windSpeed * cos(hdgDiff);
-                 //cerr << "Tailwind : " << tailWind << endl;
-                 //cerr << "Crosswnd : " << crossWind << endl;
                  if ((tailWind > maxTail) || (crossWind > maxCross))
                    validSelection = false;
                }else {
@@ -308,19 +341,7 @@ void RunwayGroup::setActive(const string &aptId,
        }
     }
   active = -1;
-  //RunwayListVectorIterator i; // = rwlist.begin();
-  //stringVecIterator j;
-  //for (i = rwyList.begin(); i != rwyList.end(); i++)
-  //  {
-  //    cerr << i->getType();
-  //    for (j = i->getRwyList()->begin(); j != i->getRwyList()->end(); j++)
-  //   {                                 
-  //     cerr << (*j);
-  //   }
-  //    cerr << endl;
-  //  }
-  //for (int
-
+  nrActive = 0;
 }
 
 void RunwayGroup::getActive(int i, string &name, string &type)
index e45a057ea1db88fd8d14d2939a816e87406a933e..c52312c895882a7d25c1c50a4a6c5b4b1ea2d520 100644 (file)
@@ -96,6 +96,7 @@ private:
   //stringVec runwayNames;
   int choice[2];
   int nrActive;
+
 public:
   RunwayGroup() {};
   RunwayGroup(const RunwayGroup &other);
@@ -103,7 +104,7 @@ public:
 
   void setName(const string& nm) { name = nm;                };
   void add(const RunwayList& list) { rwyList.push_back(list);};
-  void setActive(const string& aptId, double windSpeed, double windHeading, double maxTail, double maxCross);
+  void setActive(const string& aptId, double windSpeed, double windHeading, double maxTail, double maxCross, stringVec *curr);
 
   int getNrActiveRunways() { return nrActive;};
   void getActive(int i, string& name, string& type);
@@ -132,6 +133,7 @@ private:
   RunwayList  rwyList;
   RunwayGroup rwyGroup;
   PreferenceList preferences;
+  
 
   time_t processTime(const string&);
   bool initialized;