]> git.mxchange.org Git - flightgear.git/blobdiff - src/Airports/dynamics.cxx
Conditional compilation of ATCDCL module. Use --disable-atcdcl to try building flight...
[flightgear.git] / src / Airports / dynamics.cxx
index 868c45cea171ed7e596bdc622f5f5def44dd7fbe..3e658a1473aa5effe73f158c7fe181d1e2c797b0 100644 (file)
@@ -26,7 +26,6 @@
 
 #include <simgear/compiler.h>
 
-#include <plib/sg.h>
 #include <plib/ul.h>
 
 #include <Environment/environment_mgr.hxx>
 #include <string>
 #include <vector>
 
-SG_USING_STD(string);
-SG_USING_STD(vector);
-SG_USING_STD(sort);
-SG_USING_STD(random_shuffle);
+using std::string;
+using std::vector;
+using std::sort;
+using std::random_shuffle;
 
 #include "simple.hxx"
 #include "dynamics.hxx"
 
 FGAirportDynamics::FGAirportDynamics(FGAirport* ap) :
-  _ap(ap), rwyPrefs(ap) {
+  _ap(ap), rwyPrefs(ap), SIDs(ap) {
   lastUpdate = 0;
-  for (int i = 0; i < 10; i++)
-     {
-       //avWindHeading [i] = 0;
-       //avWindSpeed   [i] = 0;
-     }
+
+  // For testing only. This needs to be refined when we move ATIS functionality over.
+  atisInformation = "Sierra";
 }
 
 // Note that the ground network should also be copied
 FGAirportDynamics::FGAirportDynamics(const FGAirportDynamics& other) :
-  rwyPrefs(other.rwyPrefs)
+  rwyPrefs(other.rwyPrefs),
+  SIDs(other.SIDs)
 {
   for (FGParkingVecConstIterator ip= other.parkings.begin(); ip != other.parkings.end(); ip++)
     parkings.push_back(*(ip));
@@ -76,11 +74,7 @@ FGAirportDynamics::FGAirportDynamics(const FGAirportDynamics& other) :
   for (il = other.takeoff.begin(); il != other.takeoff.end(); il++)
     takeoff.push_back(*il);
   lastUpdate = other.lastUpdate;
-  for (int i = 0; i < 10; i++)
-    {
-      //avWindHeading [i] = other.avWindHeading[i];
-      //avWindSpeed   [i] = other.avWindSpeed  [i];
-    }
+  atisInformation = other.atisInformation; 
 }
 
 // Destructor
@@ -348,26 +342,24 @@ void FGAirportDynamics::setRwyUse(const FGRunwayPreference& ref)
   //cerr << "Exiting due to not implemented yet" << endl;
   //exit(1);
 }
-void FGAirportDynamics::getActiveRunway(const string &trafficType, int action, string &runway)
+
+bool FGAirportDynamics::innerGetActiveRunway(const string &trafficType, int action, string &runway, double heading)
 {
-  double windSpeed;
+double windSpeed;
   double windHeading;
   double maxTail;
   double maxCross;
   string name;
   string type;
 
-  if (!(rwyPrefs.available()))
-    {
-      runway = chooseRunwayFallback();
-      return; // generic fall back goes here
-    }
-  else
-    {
-      RunwayGroup *currRunwayGroup = 0;
-      int nrActiveRunways = 0;
-      time_t dayStart = fgGetLong("/sim/time/utc/day-seconds");
-      if ((abs((long)(dayStart - lastUpdate)) > 600) || trafficType != prevTrafficType)
+  if (!rwyPrefs.available()) {
+    return false;
+  }
+  
+  RunwayGroup *currRunwayGroup = 0;
+  int nrActiveRunways = 0;
+  time_t dayStart = fgGetLong("/sim/time/utc/day-seconds");
+  if ((abs((long)(dayStart - lastUpdate)) > 600) || trafficType != prevTrafficType)
        {
          landing.clear();
          takeoff.clear();
@@ -390,19 +382,19 @@ void FGAirportDynamics::getActiveRunway(const string &trafficType, int action, s
          //cerr << "A"<< endl;
          currSched = rwyPrefs.getSchedule(trafficType.c_str());
          if (!(currSched))
-           return;
+           return false;
          //cerr << "B"<< endl;
          scheduleName = currSched->getName(dayStart);
          maxTail  = currSched->getTailWind  ();
          maxCross = currSched->getCrossWind ();
          //cerr << "SChedule anme = " << scheduleName << endl;
          if (scheduleName.empty())
-           return;
+           return false;
          //cerr << "C"<< endl;
          currRunwayGroup = rwyPrefs.getGroup(scheduleName); 
          //cerr << "D"<< endl;
          if (!(currRunwayGroup))
-           return;
+           return false;
          nrActiveRunways = currRunwayGroup->getNrActiveRunways();
 
         // Keep a history of the currently active runways, to ensure
@@ -419,7 +411,7 @@ void FGAirportDynamics::getActiveRunway(const string &trafficType, int action, s
           currentlyActive = &ulActive;
         }
          // 
-         currRunwayGroup->setActive(_ap->getId()
+         currRunwayGroup->setActive(_ap, 
                                     windSpeed, 
                                     windHeading, 
                                     maxTail, 
@@ -451,7 +443,8 @@ void FGAirportDynamics::getActiveRunway(const string &trafficType, int action, s
            }
           //cerr << endl;
        }
-      if (action == 1) // takeoff 
+  
+  if (action == 1) // takeoff 
        {
          int nr = takeoff.size();
          if (nr)
@@ -459,46 +452,61 @@ void FGAirportDynamics::getActiveRunway(const string &trafficType, int action, s
              // 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)];
+             runway = chooseRwyByHeading (takeoff, heading);
            }
          else
            { // Fallback
              runway = chooseRunwayFallback();
            }
        } 
-      if (action == 2) // landing
+  
+  if (action == 2) // landing
        {
          int nr = landing.size();
          if (nr)
            {
-             runway = landing[(rand() % nr)];
+             runway = chooseRwyByHeading (landing, heading);
            }
          else
            {  //fallback
               runway = chooseRunwayFallback();
            }
        } 
-      //runway = globals->get_runways()->search(_ap->getId(), int(windHeading));
-      //cerr << "Seleceted runway: " << runway << endl;
-    }
+
+  return true;
+}
+
+string FGAirportDynamics::chooseRwyByHeading(stringVec rwys, double heading) {
+   double bestError = 360.0;
+   double rwyHeading, headingError;
+   string runway;
+   for (stringVecIterator i = rwys.begin(); i != rwys.end(); i++) {
+       FGRunway *rwy = _ap->getRunwayByIdent((*i));
+       rwyHeading = rwy->headingDeg();
+       headingError = fabs(heading - rwyHeading);
+        if (headingError > 180)
+            headingError = fabs(headingError - 360);
+        if (headingError < bestError) {
+            runway = (*i);
+            bestError = headingError;
+        }
+   }
+   //cerr << "Using active runway " << runway << " for heading " << heading << endl;
+   return runway;
+}
+
+void FGAirportDynamics::getActiveRunway(const string &trafficType, int action, string &runway, double heading)
+{
+  bool ok = innerGetActiveRunway(trafficType, action, runway, heading);
+  if (!ok) {
+    runway = chooseRunwayFallback();
+  }
 }
 
 string FGAirportDynamics::chooseRunwayFallback()
 {   
-  FGEnvironment 
-    stationweather = ((FGEnvironmentMgr *) globals->get_subsystem("environment"))
-    ->getEnvironment(getLatitude(), 
-                    getLongitude(),
-                    getElevation());
-  
-  double windSpeed = stationweather.get_wind_speed_kt();
-  double windHeading = stationweather.get_wind_from_heading_deg();
-  if (windSpeed == 0) {
-    windHeading = 270; // This forces West-facing rwys to be used in no-wind situations
-    //which is consistent with Flightgear's initial setup.
-  }
-  
-   return globals->get_runways()->search(_ap->getId(), int(windHeading));
+  FGRunway* rwy = _ap->getActiveRunwayForUsage();
+  return rwy->ident();
 }
 
 void FGAirportDynamics::addParking(FGParking& park) {
@@ -520,3 +528,36 @@ double FGAirportDynamics::getElevation() const {
 const string& FGAirportDynamics::getId() const {
   return _ap->getId();
 }
+
+// Experimental: Return a different ground frequency depending on the leg of the
+// Flight. Leg should always have a minimum value of two when this function is called. 
+// Note that in this scheme, the assignment of various frequencies to various ground 
+// operations is completely arbitrary. As such, is a short cut I need to take now,
+// so that at least I can start working on assigning different frequencies to different
+// operations.
+
+int FGAirportDynamics::getGroundFrequency(unsigned leg) { 
+     //return freqGround.size() ? freqGround[0] : 0; };
+     int groundFreq = 0;
+     if (leg < 2) {
+         SG_LOG(SG_ATC, SG_ALERT, "Leg value is smaller than two at " << SG_ORIGIN);
+     }
+     if (freqGround.size() == 0) {
+         return 0;
+     }
+     if ((freqGround.size() > leg-1) && (leg > 1)) {
+          groundFreq =  freqGround[leg-1];
+     }
+     if ((freqGround.size() < leg-1) && (leg > 1)) {
+          groundFreq = (freqGround.size() < (leg-1)) ? freqGround[freqGround.size()-1] : freqGround[leg-2];
+     }
+     if ((freqGround.size() >= leg-1) && (leg > 1)) {
+          groundFreq = freqGround[leg-2];
+     }
+    return groundFreq;
+}
+
+FGAIFlightPlan *FGAirportDynamics::getSID(string activeRunway, double heading)
+{
+   return SIDs.getBest(activeRunway, heading);
+}