From d24fe199143c3cd0adecd74f02430125e2bad45e Mon Sep 17 00:00:00 2001 From: durk Date: Sun, 15 Feb 2009 15:29:56 +0000 Subject: [PATCH] One step further toward better integration of AI and ATC systems. * 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 | 3 +- src/AIModel/AIFlightPlan.hxx | 33 ++++--- src/AIModel/AIFlightPlanCreate.cxx | 105 +++++++++++---------- src/AIModel/AIFlightPlanCreateCruise.cxx | 10 +- src/AIModel/AIFlightPlanCreatePushBack.cxx | 13 ++- src/ATC/trafficcontrol.cxx | 22 ++++- src/Airports/dynamics.cxx | 29 +++++- src/Airports/dynamics.hxx | 5 +- src/Traffic/Schedule.cxx | 2 +- src/Traffic/Schedule.hxx | 3 +- 10 files changed, 142 insertions(+), 83 deletions(-) diff --git a/src/AIModel/AIFlightPlan.cxx b/src/AIModel/AIFlightPlan.cxx index 4d130991f..c901cbf53 100644 --- a/src/AIModel/AIFlightPlan.cxx +++ b/src/AIModel/AIFlightPlan.cxx @@ -42,6 +42,7 @@ #include #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); diff --git a/src/AIModel/AIFlightPlan.hxx b/src/AIModel/AIFlightPlan.hxx index 2e24af376..50ba8d6f1 100644 --- a/src/AIModel/AIFlightPlan.hxx +++ b/src/AIModel/AIFlightPlan.hxx @@ -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 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 diff --git a/src/AIModel/AIFlightPlanCreate.cxx b/src/AIModel/AIFlightPlanCreate.cxx index d86b71440..87c253148 100644 --- a/src/AIModel/AIFlightPlanCreate.cxx +++ b/src/AIModel/AIFlightPlanCreate.cxx @@ -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); } diff --git a/src/AIModel/AIFlightPlanCreateCruise.cxx b/src/AIModel/AIFlightPlanCreateCruise.cxx index d2fc62473..f1d50fdba 100755 --- a/src/AIModel/AIFlightPlanCreateCruise.cxx +++ b/src/AIModel/AIFlightPlanCreateCruise.cxx @@ -26,6 +26,7 @@ #include #include #include "AIFlightPlan.hxx" +#include "AIAircraft.hxx" #include #include #include @@ -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); } diff --git a/src/AIModel/AIFlightPlanCreatePushBack.cxx b/src/AIModel/AIFlightPlanCreatePushBack.cxx index 3b9ade374..5dc017328 100644 --- a/src/AIModel/AIFlightPlanCreatePushBack.cxx +++ b/src/AIModel/AIFlightPlanCreatePushBack.cxx @@ -31,7 +31,8 @@ #include -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, diff --git a/src/ATC/trafficcontrol.cxx b/src/ATC/trafficcontrol.cxx index 594f4b68b..3d3d8a3e0 100644 --- a/src/ATC/trafficcontrol.cxx +++ b/src/ATC/trafficcontrol.cxx @@ -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: diff --git a/src/Airports/dynamics.cxx b/src/Airports/dynamics.cxx index bef81ebe6..34a6dce8a 100644 --- a/src/Airports/dynamics.cxx +++ b/src/Airports/dynamics.cxx @@ -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(); } diff --git a/src/Airports/dynamics.hxx b/src/Airports/dynamics.hxx index 9712c5b80..b2f1ba001 100644 --- a/src/Airports/dynamics.hxx +++ b/src/Airports/dynamics.hxx @@ -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, diff --git a/src/Traffic/Schedule.cxx b/src/Traffic/Schedule.cxx index 4da197644..675b48ac5 100644 --- a/src/Traffic/Schedule.cxx +++ b/src/Traffic/Schedule.cxx @@ -195,7 +195,7 @@ bool FGAISchedule::update(time_t now) FGAIManager *aimgr; string airport; - double courseToUser, courseToDest; + double courseToUser; double distanceToDest; double speed; diff --git a/src/Traffic/Schedule.hxx b/src/Traffic/Schedule.hxx index 5511a7d1a..4dd8d5f00 100644 --- a/src/Traffic/Schedule.hxx +++ b/src/Traffic/Schedule.hxx @@ -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 ¤tDestination, 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. -- 2.39.5