]> git.mxchange.org Git - flightgear.git/commitdiff
One step further toward better integration of AI and ATC systems.
authordurk <durk>
Sun, 15 Feb 2009 15:29:56 +0000 (15:29 +0000)
committerTim Moore <timoore@redhat.com>
Sun, 15 Feb 2009 23:56:44 +0000 (00:56 +0100)
 * Changed the runway XX. ATC message to actually report the real
   designated departure runway
 * In case of multiple active runways, select the one with a heading that is
   closest to the direction of the ultimate departure destination / lines up
   with the arrival path.

src/AIModel/AIFlightPlan.cxx
src/AIModel/AIFlightPlan.hxx
src/AIModel/AIFlightPlanCreate.cxx
src/AIModel/AIFlightPlanCreateCruise.cxx
src/AIModel/AIFlightPlanCreatePushBack.cxx
src/ATC/trafficcontrol.cxx
src/Airports/dynamics.cxx
src/Airports/dynamics.hxx
src/Traffic/Schedule.cxx
src/Traffic/Schedule.hxx

index 4d130991fe0a782e4fdbb1a75de93fc6e67bb179..c901cbf5348f976648b663cd05fdca5c2227e84d 100644 (file)
@@ -42,6 +42,7 @@
 #include <Environment/environment.hxx>
 
 #include "AIFlightPlan.hxx"
+#include "AIAircraft.hxx"
 
 using std::cerr;
 
@@ -201,7 +202,7 @@ FGAIFlightPlan::FGAIFlightPlan(FGAIAircraft *ac,
       if (timeDiff >= 2000)
           leg = 5;
 
-      SG_LOG(SG_GENERAL, SG_INFO, "Route from " << dep->getId() << " to " << arr->getId() << ". Set leg to : " << leg);
+      SG_LOG(SG_GENERAL, SG_INFO, "Route from " << dep->getId() << " to " << arr->getId() << ". Set leg to : " << leg << " " << ac->getTrafficRef()->getCallSign());
       wpt_iterator = waypoints.begin();
       create(ac, dep,arr, leg, alt, speed, lat, lon,
             firstLeg, radius, fltType, acType, airline);
index 2e24af376894867dd327fd3a0c537f6eeaab8f5b..50ba8d6f110218c5e66147e0883c7e6950edc78f 100644 (file)
@@ -110,6 +110,9 @@ public:
   string getRunway() { return activeRunway; }
   bool isActive(time_t time) {return time >= this->getStartTime();}
 
+  void setRunway(string rwy) { activeRunway = rwy; };
+  string getRunwayClassFromTrafficType(string fltType);
+
 private:
   FGRunway* rwy;
   typedef vector <waypoint*> wpt_vector_type;
@@ -129,30 +132,30 @@ private:
   FGAirRoute airRoute;
   FGTaxiRoute *taxiRoute;
 
-  void createPushBack(bool, FGAirport*, double, double, double, const string&, const string&, const string&);
-  void createPushBackFallBack(bool, FGAirport*, double, double, double, const string&, const string&, const string&);
+  void createPushBack(FGAIAircraft *, bool, FGAirport*, double, double, double, const string&, const string&, const string&);
+  void createPushBackFallBack(FGAIAircraft *, bool, FGAirport*, double, double, double, const string&, const string&, const string&);
   void createTakeOff(FGAIAircraft *, bool, FGAirport *, double, const string&);
-  void createClimb(bool, FGAirport *, double, double, const string&);
-  void createCruise(bool, FGAirport*, FGAirport*, double, double, double, double, const string&);
-  void createDecent(FGAirport *, const string&);
-  void createLanding(FGAirport *);
-  void createParking(FGAirport *, double radius);
+  void createClimb(FGAIAircraft *, bool, FGAirport *, double, double, const string&);
+  void createCruise(FGAIAircraft *, bool, FGAirport*, FGAirport*, double, double, double, double, const string&);
+  void createDecent(FGAIAircraft *, FGAirport *, const string&);
+  void createLanding(FGAIAircraft *, FGAirport *);
+  void createParking(FGAIAircraft *, FGAirport *, double radius);
   void deleteWaypoints(); 
   void resetWaypoints();
 
-  void createLandingTaxi(FGAirport *apt, double radius, const string& fltType, const string& acType, const string& airline);
-  void createDefaultLandingTaxi(FGAirport* aAirport);
-  void createDefaultTakeoffTaxi(FGAirport* aAirport, FGRunway* aRunway);
-  void createTakeoffTaxi(bool firstFlight, FGAirport *apt, double radius, const string& fltType, const string& acType, const string& airline);
+  void createLandingTaxi(FGAIAircraft *, FGAirport *apt, double radius, const string& fltType, const string& acType, const string& airline);
+  void createDefaultLandingTaxi(FGAIAircraft *, FGAirport* aAirport);
+  void createDefaultTakeoffTaxi(FGAIAircraft *, FGAirport* aAirport, FGRunway* aRunway);
+  void createTakeoffTaxi(FGAIAircraft *, bool firstFlight, FGAirport *apt, double radius, const string& fltType, const string& acType, const string& airline);
         
-  waypoint* createOnGround(const std::string& aName, const SGGeod& aPos, double aElev, double aSpeed);
-  waypoint* createInAir(const std::string& aName, const SGGeod& aPos, double aElev, double aSpeed);
-  waypoint* cloneWithPos(waypoint* aWpt, const std::string& aName, const SGGeod& aPos);
+  waypoint* createOnGround(FGAIAircraft *, const std::string& aName, const SGGeod& aPos, double aElev, double aSpeed);
+  waypoint* createInAir(FGAIAircraft *, const std::string& aName, const SGGeod& aPos, double aElev, double aSpeed);
+  waypoint* cloneWithPos(FGAIAircraft *, waypoint* aWpt, const std::string& aName, const SGGeod& aPos);
     
-  string getRunwayClassFromTrafficType(string fltType);
 
   //void createCruiseFallback(bool, FGAirport*, FGAirport*, double, double, double, double);
  void evaluateRoutePart(double deplat, double deplon, double arrlat, double arrlon);
 };    
 
 #endif  // _FG_AIFLIGHTPLAN_HXX
index d86b71440545e414e7ea0b71fc38efe3f1bbfa54..87c2531482a2e2c69bd08b0bc837605d342945cf 100644 (file)
@@ -53,32 +53,32 @@ void FGAIFlightPlan::create(FGAIAircraft *ac, FGAirport *dep, FGAirport *arr, in
   switch(legNr)
     {
       case 1:
-      createPushBack(firstFlight,dep, latitude, longitude, 
+      createPushBack(ac, firstFlight,dep, latitude, longitude, 
                     radius, fltType, aircraftType, airline);
       break;
     case 2: 
-      createTakeoffTaxi(firstFlight, dep, radius, fltType, aircraftType, airline);
+      createTakeoffTaxi(ac, firstFlight, dep, radius, fltType, aircraftType, airline);
       break;
     case 3: 
       createTakeOff(ac, firstFlight, dep, speed, fltType);
       break;
     case 4: 
-      createClimb(firstFlight, dep, speed, alt, fltType);
+      createClimb(ac, firstFlight, dep, speed, alt, fltType);
       break;
     case 5: 
-      createCruise(firstFlight, dep,arr, latitude, longitude, speed, alt, fltType);
+      createCruise(ac, firstFlight, dep,arr, latitude, longitude, speed, alt, fltType);
       break;
     case 6: 
-      createDecent(arr, fltType);
+      createDecent(ac, arr, fltType);
       break;
     case 7: 
-      createLanding(arr);
+      createLanding(ac, arr);
       break;
     case 8: 
-      createLandingTaxi(arr, radius, fltType, aircraftType, airline);
+      createLandingTaxi(ac, arr, radius, fltType, aircraftType, airline);
       break;
       case 9: 
-       createParking(arr, radius);
+       createParking(ac, arr, radius);
       break;
     default:
       //exit(1);
@@ -90,7 +90,7 @@ void FGAIFlightPlan::create(FGAIAircraft *ac, FGAirport *dep, FGAirport *arr, in
 }
 
 FGAIFlightPlan::waypoint*
-FGAIFlightPlan::createOnGround(const std::string& aName, const SGGeod& aPos, double aElev, double aSpeed)
+FGAIFlightPlan::createOnGround(FGAIAircraft *ac, const std::string& aName, const SGGeod& aPos, double aElev, double aSpeed)
 {
   waypoint* wpt = new waypoint;
   wpt->name = aName;
@@ -108,7 +108,7 @@ FGAIFlightPlan::createOnGround(const std::string& aName, const SGGeod& aPos, dou
 }
 
 FGAIFlightPlan::waypoint*
-FGAIFlightPlan::createInAir(const std::string& aName, const SGGeod& aPos, double aElev, double aSpeed)
+FGAIFlightPlan::createInAir(FGAIAircraft *ac, const std::string& aName, const SGGeod& aPos, double aElev, double aSpeed)
 {
   waypoint* wpt = new waypoint;
   wpt->name = aName;
@@ -126,7 +126,7 @@ FGAIFlightPlan::createInAir(const std::string& aName, const SGGeod& aPos, double
 }
 
 FGAIFlightPlan::waypoint*
-FGAIFlightPlan::cloneWithPos(waypoint* aWpt, const std::string& aName, const SGGeod& aPos)
+FGAIFlightPlan::cloneWithPos(FGAIAircraft *ac, waypoint* aWpt, const std::string& aName, const SGGeod& aPos)
 {
   waypoint* wpt = new waypoint;
   wpt->name = aName;
@@ -145,19 +145,19 @@ FGAIFlightPlan::cloneWithPos(waypoint* aWpt, const std::string& aName, const SGG
   return wpt;
 }
 
-void FGAIFlightPlan::createDefaultTakeoffTaxi(FGAirport* aAirport, FGRunway* aRunway)
+void FGAIFlightPlan::createDefaultTakeoffTaxi(FGAIAircraft *ac, FGAirport* aAirport, FGRunway* aRunway)
 {
   SGGeod runwayTakeoff = aRunway->pointOnCenterline(5.0);
   double airportElev = aAirport->getElevation();
   
   waypoint* wpt;
-  wpt = createOnGround("Airport Center", aAirport->geod(), airportElev, 15);
+  wpt = createOnGround(ac, "Airport Center", aAirport->geod(), airportElev, 15);
   waypoints.push_back(wpt);
-  wpt = createOnGround("Runway Takeoff", runwayTakeoff, airportElev, 15);
+  wpt = createOnGround(ac, "Runway Takeoff", runwayTakeoff, airportElev, 15);
   waypoints.push_back(wpt);    
 }
 
-void FGAIFlightPlan::createTakeoffTaxi(bool firstFlight, 
+void FGAIFlightPlan::createTakeoffTaxi(FGAIAircraft *ac, bool firstFlight, 
                                FGAirport *apt,
                                double radius, const string& fltType, 
                                const string& acType, const string& airline)
@@ -182,13 +182,19 @@ void FGAIFlightPlan::createTakeoffTaxi(bool firstFlight,
   }
   
   string rwyClass = getRunwayClassFromTrafficType(fltType);
-  apt->getDynamics()->getActiveRunway(rwyClass, 1, activeRunway);
+
+  // Only set this if it hasn't been set by ATC already.
+  if (activeRunway.empty()) {
+      //cerr << "Getting runway for " << ac->getTrafficRef()->getCallSign() << " at " << apt->getId() << endl;
+      double depHeading = ac->getTrafficRef()->getCourse();
+      apt->getDynamics()->getActiveRunway(rwyClass, 1, activeRunway, depHeading);
+  }
   rwy = apt->getRunwayByIdent(activeRunway);
   SGGeod runwayTakeoff = rwy->pointOnCenterline(5.0);
 
   FGGroundNetwork* gn = apt->getDynamics()->getGroundNetwork();
   if (!gn->exists()) {
-    createDefaultTakeoffTaxi(apt, rwy);
+    createDefaultTakeoffTaxi(ac, apt, rwy);
     return;
   }
   
@@ -227,7 +233,7 @@ void FGAIFlightPlan::createTakeoffTaxi(bool firstFlight,
   intVecIterator i;
         
   if (taxiRoute->empty()) {
-    createDefaultTakeoffTaxi(apt, rwy);
+    createDefaultTakeoffTaxi(ac, apt, rwy);
     return;
   }
   
@@ -256,31 +262,31 @@ void FGAIFlightPlan::createTakeoffTaxi(bool firstFlight,
                char buffer[10];
                snprintf (buffer, 10, "%d", node);
                FGTaxiNode *tn = apt->getDynamics()->getGroundNetwork()->findNode(node);
-    waypoint* wpt = createOnGround(buffer, tn->geod(), apt->getElevation(), 15);
+    waypoint* wpt = createOnGround(ac, buffer, tn->geod(), apt->getElevation(), 15);
     wpt->routeIndex = route;
                waypoints.push_back(wpt);
   }
 }
 
-void FGAIFlightPlan::createDefaultLandingTaxi(FGAirport* aAirport)
+void FGAIFlightPlan::createDefaultLandingTaxi(FGAIAircraft *ac, FGAirport* aAirport)
 {
   SGGeod lastWptPos = 
     SGGeod::fromDeg(waypoints.back()->longitude, waypoints.back()->latitude);
   double airportElev = aAirport->getElevation();
   
   waypoint* wpt;
-  wpt = createOnGround("Runway Exit", lastWptPos, airportElev, 15);
+  wpt = createOnGround(ac, "Runway Exit", lastWptPos, airportElev, 15);
   waypoints.push_back(wpt);    
-  wpt = createOnGround("Airport Center", aAirport->geod(), airportElev, 15);
+  wpt = createOnGround(ac, "Airport Center", aAirport->geod(), airportElev, 15);
   waypoints.push_back(wpt);
   
   double heading, lat, lon;
   aAirport->getDynamics()->getParking(gateId, &lat, &lon, &heading);
-  wpt = createOnGround("END", SGGeod::fromDeg(lon, lat), airportElev, 15);
+  wpt = createOnGround(ac, "END", SGGeod::fromDeg(lon, lat), airportElev, 15);
   waypoints.push_back(wpt);
 }
 
-void FGAIFlightPlan::createLandingTaxi(FGAirport *apt,
+void FGAIFlightPlan::createLandingTaxi(FGAIAircraft *ac, FGAirport *apt,
                                double radius, const string& fltType, 
                                const string& acType, const string& airline)
 {
@@ -294,7 +300,7 @@ void FGAIFlightPlan::createLandingTaxi(FGAirport *apt,
   
    // Find a route from runway end to parking/gate.
   if (!gn->exists()) {
-    createDefaultLandingTaxi(apt);
+    createDefaultLandingTaxi(ac, apt);
     return;
   }
   
@@ -313,7 +319,7 @@ void FGAIFlightPlan::createLandingTaxi(FGAirport *apt,
   intVecIterator i;
   
   if (taxiRoute->empty()) {
-    createDefaultLandingTaxi(apt);
+    createDefaultLandingTaxi(ac, apt);
     return;
   }
   
@@ -328,7 +334,7 @@ void FGAIFlightPlan::createLandingTaxi(FGAirport *apt,
     char buffer[10];
     snprintf (buffer, 10, "%d", node);
     FGTaxiNode *tn = gn->findNode(node);
-    waypoint* wpt = createOnGround(buffer, tn->geod(), apt->getElevation(), 15);
+    waypoint* wpt = createOnGround(ac, buffer, tn->geod(), apt->getElevation(), 15);
     wpt->routeIndex = route;
     waypoints.push_back(wpt);
   }
@@ -359,32 +365,33 @@ void FGAIFlightPlan::createTakeOff(FGAIAircraft *ac, bool firstFlight, FGAirport
     if (firstFlight)
     {
         string rwyClass = getRunwayClassFromTrafficType(fltType);
-        apt->getDynamics()->getActiveRunway(rwyClass, 1, activeRunway);
+        double heading = ac->getTrafficRef()->getCourse();
+        apt->getDynamics()->getActiveRunway(rwyClass, 1, activeRunway, heading);
         rwy = apt->getRunwayByIdent(activeRunway);
     }
 
     double airportElev = apt->getElevation();
     // Acceleration point, 105 meters into the runway,
     SGGeod accelPoint = rwy->pointOnCenterline(105.0);
-    wpt = createOnGround("accel", accelPoint, airportElev, speed);
+    wpt = createOnGround(ac, "accel", accelPoint, airportElev, speed);
     waypoints.push_back(wpt); 
  
     //Start Climbing to 3000 ft. Let's do this 
     // at the center of the runway for now:
     SGGeod rotate = rwy->pointOnCenterline(105.0+accelDistance);
-    wpt = cloneWithPos(wpt, "SOC", rotate);
+    wpt = cloneWithPos(ac, wpt, "SOC", rotate);
     wpt->altitude  = airportElev+1000;
     wpt->on_ground = false;
     waypoints.push_back(wpt);
 
-    wpt = cloneWithPos(wpt, "3000 ft", rwy->end());
+    wpt = cloneWithPos(ac, wpt, "3000 ft", rwy->end());
     wpt->altitude  = airportElev+3000;
     waypoints.push_back(wpt);
 
     // Finally, add two more waypoints, so that aircraft will remain under
     // Tower control until they have reached the 3000 ft climb point
     SGGeod pt = rwy->pointOnCenterline(5000 + rwy->lengthM() * 0.5);
-    wpt = cloneWithPos(wpt, "5000 ft", pt);
+    wpt = cloneWithPos(ac, wpt, "5000 ft", pt);
     wpt->altitude  = airportElev+5000;
     waypoints.push_back(wpt);
 }
@@ -393,24 +400,25 @@ void FGAIFlightPlan::createTakeOff(FGAIAircraft *ac, bool firstFlight, FGAirport
  * CreateClimb
  * initialize the Aircraft at the parking location
  ******************************************************************/
-void FGAIFlightPlan::createClimb(bool firstFlight, FGAirport *apt, double speed, double alt, const string &fltType)
+void FGAIFlightPlan::createClimb(FGAIAircraft *ac, bool firstFlight, FGAirport *apt, double speed, double alt, const string &fltType)
 {
   waypoint *wpt;
 
   if (firstFlight) {
     string rwyClass = getRunwayClassFromTrafficType(fltType);
-    apt->getDynamics()->getActiveRunway(rwyClass, 1, activeRunway);
+    double heading = ac->getTrafficRef()->getCourse();
+    apt->getDynamics()->getActiveRunway(rwyClass, 1, activeRunway, heading);
     rwy = apt->getRunwayByIdent(activeRunway);
   }
   
   SGGeod climb1 = rwy->pointOnCenterline(10*SG_NM_TO_METER);
-  wpt = createInAir("10000ft climb", climb1, speed, 10000);
+  wpt = createInAir(ac, "10000ft climb", climb1, speed, 10000);
   wpt->gear_down = true;
   wpt->flaps_down= true;
   waypoints.push_back(wpt); 
 
   SGGeod climb2 = rwy->pointOnCenterline(20*SG_NM_TO_METER);
-  wpt = cloneWithPos(wpt, "18000ft climb", climb2);
+  wpt = cloneWithPos(ac, wpt, "18000ft climb", climb2);
   wpt->altitude  = 18000;
   waypoints.push_back(wpt); 
 }
@@ -420,7 +428,7 @@ void FGAIFlightPlan::createClimb(bool firstFlight, FGAirport *apt, double speed,
  * CreateDecent
  * initialize the Aircraft at the parking location
  ******************************************************************/
-void FGAIFlightPlan::createDecent(FGAirport *apt, const string &fltType)
+void FGAIFlightPlan::createDecent(FGAIAircraft *ac, FGAirport *apt, const string &fltType)
 {
   // Ten thousand ft. Slowing down to 240 kts
   waypoint *wpt;
@@ -429,17 +437,18 @@ void FGAIFlightPlan::createDecent(FGAirport *apt, const string &fltType)
   //string name;
   // allow "mil" and "gen" as well
   string rwyClass = getRunwayClassFromTrafficType(fltType);
-  apt->getDynamics()->getActiveRunway(rwyClass, 2, activeRunway);
+  double heading = ac->getTrafficRef()->getCourse();
+  apt->getDynamics()->getActiveRunway(rwyClass, 2, activeRunway, heading);
   rwy = apt->getRunwayByIdent(activeRunway);
      
   SGGeod descent1 = rwy->pointOnCenterline(-100000); // 100km out
-  wpt = createInAir("Dec 10000ft", descent1, apt->getElevation(), 240);
+  wpt = createInAir(ac, "Dec 10000ft", descent1, apt->getElevation(), 240);
   wpt->crossat   = 10000;
   waypoints.push_back(wpt);  
   
   // Three thousand ft. Slowing down to 160 kts
   SGGeod descent2 = rwy->pointOnCenterline(-8*SG_NM_TO_METER); // 8nm out
-  wpt = createInAir("DEC 3000ft", descent2, apt->getElevation(), 160);
+  wpt = createInAir(ac, "DEC 3000ft", descent2, apt->getElevation(), 160);
   wpt->crossat   = 3000;
   wpt->gear_down = true;
   wpt->flaps_down= true;
@@ -449,22 +458,22 @@ void FGAIFlightPlan::createDecent(FGAirport *apt, const string &fltType)
  * CreateLanding
  * initialize the Aircraft at the parking location
  ******************************************************************/
-void FGAIFlightPlan::createLanding(FGAirport *apt)
+void FGAIFlightPlan::createLanding(FGAIAircraft *ac, FGAirport *apt)
 {
   // Ten thousand ft. Slowing down to 150 kts
   waypoint *wpt;
   double aptElev = apt->getElevation();
   //Runway Threshold
-  wpt = createOnGround("Threshold", rwy->threshold(), aptElev, 150);
+  wpt = createOnGround(ac, "Threshold", rwy->threshold(), aptElev, 150);
   wpt->crossat = apt->getElevation();
   waypoints.push_back(wpt); 
 
  // Roll-out
-  wpt = createOnGround("Center", rwy->geod(), aptElev, 30);
+  wpt = createOnGround(ac, "Center", rwy->geod(), aptElev, 30);
   waypoints.push_back(wpt);
 
   SGGeod rollOut = rwy->pointOnCenterline(rwy->lengthM() * 0.9);
-  wpt = createOnGround("Roll Out", rollOut, aptElev, 15);
+  wpt = createOnGround(ac, "Roll Out", rollOut, aptElev, 15);
   wpt->crossat   = apt->getElevation();
   waypoints.push_back(wpt); 
 }
@@ -473,7 +482,7 @@ void FGAIFlightPlan::createLanding(FGAirport *apt)
  * CreateParking
  * initialize the Aircraft at the parking location
  ******************************************************************/
-void FGAIFlightPlan::createParking(FGAirport *apt, double radius)
+void FGAIFlightPlan::createParking(FGAIAircraft *ac, FGAirport *apt, double radius)
 {
   waypoint* wpt;
   double aptElev = apt->getElevation();
@@ -488,17 +497,17 @@ void FGAIFlightPlan::createParking(FGAirport *apt, double radius)
   geo_direct_wgs_84 ( 0, lat, lon, heading, 
                      2.2*radius,           
                      &lat2, &lon2, &az2 );
-  wpt = createOnGround("taxiStart", SGGeod::fromDeg(lon2, lat2), aptElev, 10);
+  wpt = createOnGround(ac, "taxiStart", SGGeod::fromDeg(lon2, lat2), aptElev, 10);
   waypoints.push_back(wpt);
   
   geo_direct_wgs_84 ( 0, lat, lon, heading, 
                      0.1 *radius,           
                      &lat2, &lon2, &az2 );
           
-  wpt = createOnGround("taxiStart2", SGGeod::fromDeg(lon2, lat2), aptElev, 10);
+  wpt = createOnGround(ac, "taxiStart2", SGGeod::fromDeg(lon2, lat2), aptElev, 10);
   waypoints.push_back(wpt);   
 
-  wpt = createOnGround("END", SGGeod::fromDeg(lon, lat), aptElev, 10);
+  wpt = createOnGround(ac, "END", SGGeod::fromDeg(lon, lat), aptElev, 10);
   waypoints.push_back(wpt);
 }
 
index d2fc62473be08e4e2b5caf54b63f29cc018a007d..f1d50fdbad9757ab6bf2d3a07f79b5c4eaf06bcb 100755 (executable)
@@ -26,6 +26,7 @@
 #include <fstream>
 #include <iostream>
 #include "AIFlightPlan.hxx"
+#include "AIAircraft.hxx"
 #include <simgear/math/polar3d.hxx>
 #include <simgear/math/sg_geodesy.hxx>
 #include <simgear/route/waypoint.hxx>
@@ -310,21 +311,22 @@ void FGAIFlightPlan::createCruise(bool firstFlight, FGAirport *dep,
  * Note that this is the original version that does not 
  * do any dynamic route computation.
  ******************************************************************/
-void FGAIFlightPlan::createCruise(bool firstFlight, FGAirport *dep, 
+void FGAIFlightPlan::createCruise(FGAIAircraft *ac, bool firstFlight, FGAirport *dep, 
                                  FGAirport *arr, double latitude, 
                                  double longitude, double speed, 
                                  double alt, const string& fltType)
 {
   waypoint *wpt;
-  wpt = createInAir("Cruise", SGGeod::fromDeg(longitude, latitude), alt, speed);
+  wpt = createInAir(ac, "Cruise", SGGeod::fromDeg(longitude, latitude), alt, speed);
   waypoints.push_back(wpt); 
   
   string rwyClass = getRunwayClassFromTrafficType(fltType);
-  arr->getDynamics()->getActiveRunway(rwyClass, 2, activeRunway);
+  double heading = ac->getTrafficRef()->getCourse();
+  arr->getDynamics()->getActiveRunway(rwyClass, 2, activeRunway, heading);
   rwy = arr->getRunwayByIdent(activeRunway);
   // begin descent 110km out
   SGGeod beginDescentPoint = rwy->pointOnCenterline(-110000);
   
-  wpt = createInAir("BOD", beginDescentPoint, alt, speed);
+  wpt = createInAir(ac, "BOD", beginDescentPoint, alt, speed);
   waypoints.push_back(wpt); 
 }
index 3b9ade3747ffcbac4f2e06e9598909f86a3bfe51..5dc01732874013e880a413e0f8f333d5724834fe 100644 (file)
@@ -31,7 +31,8 @@
 #include <Environment/environment.hxx>
 
 
-void FGAIFlightPlan::createPushBack(bool firstFlight, FGAirport *dep, 
+void FGAIFlightPlan::createPushBack(FGAIAircraft *ac,
+                                    bool firstFlight, FGAirport *dep, 
                                    double latitude,
                                    double longitude,
                                    double radius,
@@ -41,9 +42,13 @@ void FGAIFlightPlan::createPushBack(bool firstFlight, FGAirport *dep,
 {
     double lat, lon, heading;
     FGTaxiRoute *pushBackRoute;
+    // Active runway can be conditionally set by ATC, so at the start of a new flight, this
+    // must be reset.
+    activeRunway.clear();
+
     if (!(dep->getDynamics()->getGroundNetwork()->exists())) {
        //cerr << "Push Back fallback" << endl;
-        createPushBackFallBack(firstFlight, dep, latitude, longitude,
+        createPushBackFallBack(ac, firstFlight, dep, latitude, longitude,
                                radius, fltType, aircraftType, airline);
     } else {
         if (firstFlight) {
@@ -88,7 +93,7 @@ void FGAIFlightPlan::createPushBack(bool firstFlight, FGAirport *dep,
             dep->getDynamics()->getParking(gateId, &lat, &lon, &heading);
         }
         if (gateId < 0) {
-             createPushBackFallBack(firstFlight, dep, latitude, longitude,
+             createPushBackFallBack(ac, firstFlight, dep, latitude, longitude,
                                     radius, fltType, aircraftType, airline);
              return;
 
@@ -223,7 +228,7 @@ void FGAIFlightPlan::createPushBack(bool firstFlight, FGAirport *dep,
  * This is the backup function for airports that don't have a 
  * network yet. 
  ******************************************************************/
-void FGAIFlightPlan::createPushBackFallBack(bool firstFlight, FGAirport *dep, 
+void FGAIFlightPlan::createPushBackFallBack(FGAIAircraft *ac, bool firstFlight, FGAirport *dep, 
                                    double latitude,
                                    double longitude,
                                    double radius,
index 594f4b68b183f6b6cfa01d6a429397f83a1a3547..3d3d8a3e05ff4462ba8d001eb4edac6e6f0a27ab 100644 (file)
@@ -380,6 +380,10 @@ void FGATCController::transmit(FGTrafficRecord *rec, AtcMsgId msgId, AtcMsgDir m
     string text;
     string taxiFreqStr;
     char buffer[7];
+    double heading = 0;
+    string activeRunway;
+    string fltType;
+    string rwyClass;
     switch (msgId) {
           case MSG_ANNOUNCE_ENGINE_START:
                text = sender + ". Ready to Start up";
@@ -390,9 +394,21 @@ void FGATCController::transmit(FGTrafficRecord *rec, AtcMsgId msgId, AtcMsgDir m
                        rec->getAircraft()->getTrafficRef()->getFlightRules() + " to " + 
                        rec->getAircraft()->getTrafficRef()->getArrivalAirport()->getName() + ". Request start-up";
                break;
+          // Acknowledge engine startup permission
+          // Assign departure runway
+          // Assign SID, if necessery (TODO)
           case MSG_PERMIT_ENGINE_START:
                taxiFreqStr = formatATCFrequency3_2(taxiFreq);
-               text = receiver + ". Start-up approved. " + atisInformation + " correct, runway ZZ, AAA departure, squawk BBBB. " +
+               
+               heading = rec->getAircraft()->getTrafficRef()->getCourse();
+               fltType = rec->getAircraft()->getTrafficRef()->getFlightType();
+               rwyClass= rec->getAircraft()->GetFlightPlan()->getRunwayClassFromTrafficType(fltType);
+
+               rec->getAircraft()->getTrafficRef()->getDepartureAirport()->getDynamics()->getActiveRunway(rwyClass, 1, activeRunway, heading);
+               rec->getAircraft()->GetFlightPlan()->setRunway(activeRunway);
+               //snprintf(buffer, 7, "%3.2f", heading);
+               text = receiver + ". Start-up approved. " + atisInformation + " correct, runway " + activeRunway
+                       + ", AAA departure, squawk BBBB. " +
                       "For push-back and taxi clearance call " + taxiFreqStr + ". " + sender + " control.";
                break;
           case MSG_DENY_ENGINE_START:
@@ -400,7 +416,9 @@ void FGATCController::transmit(FGTrafficRecord *rec, AtcMsgId msgId, AtcMsgDir m
                break;
          case MSG_ACKNOWLEDGE_ENGINE_START:
                taxiFreqStr = formatATCFrequency3_2(taxiFreq);
-               text = receiver + ". Start-up approved. " + atisInformation + " correct, runway ZZ, AAA departure, squawk BBBB. " +
+               activeRunway = rec->getAircraft()->GetFlightPlan()->getRunway();
+               text = receiver + ". Start-up approved. " + atisInformation + " correct, runway " +
+                      activeRunway + ", AAA departure, squawk BBBB. " +
                       "For push-back and taxi clearance call " + taxiFreqStr + ". " + sender;
                break;
            default:
index bef81ebe60bf228e5862ae039913a07e9be8f781..34a6dce8ad71d9ca8693ec477f22071168624ed6 100644 (file)
@@ -343,7 +343,7 @@ void FGAirportDynamics::setRwyUse(const FGRunwayPreference& ref)
   //exit(1);
 }
 
-bool FGAirportDynamics::innerGetActiveRunway(const string &trafficType, int action, string &runway)
+bool FGAirportDynamics::innerGetActiveRunway(const string &trafficType, int action, string &runway, double heading)
 {
 double windSpeed;
   double windHeading;
@@ -452,7 +452,7 @@ double windSpeed;
              // 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
@@ -465,7 +465,7 @@ double windSpeed;
          int nr = landing.size();
          if (nr)
            {
-             runway = landing[(rand() % nr)];
+             runway = chooseRwyByHeading (landing, heading);
            }
          else
            {  //fallback
@@ -476,9 +476,28 @@ double windSpeed;
   return true;
 }
 
-void FGAirportDynamics::getActiveRunway(const string &trafficType, int action, string &runway)
+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);
+  bool ok = innerGetActiveRunway(trafficType, action, runway, heading);
   if (!ok) {
     runway = chooseRunwayFallback();
   }
index 9712c5b8059c8be5262f317d3df1e63e5bb919e4..b2f1ba00168dd0b838a79b5ecc59354b7eba1026 100644 (file)
@@ -67,7 +67,8 @@ private:
   string atisInformation;
 
   string chooseRunwayFallback();
-  bool innerGetActiveRunway(const string &trafficType, int action, string &runway);
+  bool innerGetActiveRunway(const string &trafficType, int action, string &runway, double heading);
+  string chooseRwyByHeading(stringVec rwys, double heading);
 public:
   FGAirportDynamics(FGAirport* ap);
   FGAirportDynamics(const FGAirportDynamics &other);
@@ -88,7 +89,7 @@ public:
   double getElevation() const; 
   const string& getId() const; 
   
-  void getActiveRunway(const string& trafficType, int action, string& runway);
+  void getActiveRunway(const string& trafficType, int action, string& runway, double heading);
 
   void addParking(FGParking& park);
   bool getAvailableParking(double *lat, double *lon, 
index 4da19764428f54e0c9b09eff7ff19405018b97cd..675b48ac5b1493f710bbea1f253a6573520ea4b1 100644 (file)
@@ -195,7 +195,7 @@ bool FGAISchedule::update(time_t now)
   FGAIManager *aimgr;
   string airport;
   
-  double courseToUser,   courseToDest;
+  double courseToUser;
   double distanceToDest;
   double speed;
 
index 5511a7d1a258e01534376b99b7efbda037c47255..4dd8d5f001a16eec3f145313ff27c106bc91cbd1 100644 (file)
@@ -56,7 +56,7 @@ class FGAISchedule
   int AIManagerRef;
   //int score;
   bool firstRun;
-  
+  double courseToDest;
 
 
  public:
@@ -100,6 +100,7 @@ class FGAISchedule
   const string& getRegistration   () { return registration;};
   const string& getFlightRules    () { return (*flights.begin())->getFlightRules (); };
   bool getHeavy                   () { return heavy; };
+  double getCourse                () { return courseToDest; };
   FGScheduledFlight*findAvailableFlight (const string &currentDestination, const string &req);
   // used to sort in decending order of score: I've probably found a better way to
   // decending order sorting, but still need to test that.