From b1854459b3100e4c51e3a5704caa4e2c3869228c Mon Sep 17 00:00:00 2001 From: James Turner Date: Sun, 23 Sep 2012 21:42:40 +0100 Subject: [PATCH] Clean up dynamics/parking handing code. Refactor some parking / airport-dynamics APIs, in preparation for caching the ground cache data in the nav-cache. --- src/AIModel/AIFlightPlan.hxx | 4 +- src/AIModel/AIFlightPlanCreate.cxx | 72 +++--- src/AIModel/AIFlightPlanCreatePushBack.cxx | 248 +++++++++----------- src/ATC/atc_mgr.cxx | 2 - src/ATC/trafficcontrol.cxx | 10 +- src/Airports/dynamics.cxx | 252 +++++++-------------- src/Airports/dynamics.hxx | 47 ++-- src/Airports/gnnode.hxx | 8 +- src/Airports/parking.hxx | 41 ++-- src/Airports/simple.cxx | 2 +- src/Airports/xmlloader.cxx | 13 +- src/Main/positioninit.cxx | 29 ++- 12 files changed, 273 insertions(+), 455 deletions(-) diff --git a/src/AIModel/AIFlightPlan.hxx b/src/AIModel/AIFlightPlan.hxx index 40ba4efdc..e5e4bb10d 100644 --- a/src/AIModel/AIFlightPlan.hxx +++ b/src/AIModel/AIFlightPlan.hxx @@ -129,7 +129,7 @@ public: bool create(FGAIAircraft *, FGAirport *dep, FGAirport *arr, int leg, double alt, double speed, double lat, double lon, bool firstLeg, double radius, const std::string& fltType, const std::string& aircraftType, const std::string& airline, double distance); - bool createPushBack(FGAIAircraft *, bool, FGAirport*, double, double, double, const std::string&, const std::string&, const std::string&); + bool createPushBack(FGAIAircraft *, bool, FGAirport*, double radius, const std::string&, const std::string&, const std::string&); bool createTakeOff(FGAIAircraft *, bool, FGAirport *, double, const std::string&); void setLeg(int val) { leg = val;} @@ -189,7 +189,7 @@ private: std::string name; bool isValid; - void createPushBackFallBack(FGAIAircraft *, bool, FGAirport*, double, double, double, const std::string&, const std::string&, const std::string&); + void createPushBackFallBack(FGAIAircraft *, bool, FGAirport*, double radius, const std::string&, const std::string&, const std::string&); bool createClimb(FGAIAircraft *, bool, FGAirport *, double, double, const std::string&); bool createCruise(FGAIAircraft *, bool, FGAirport*, FGAirport*, double, double, double, double, const std::string&); bool createDescent(FGAIAircraft *, FGAirport *, double latitude, double longitude, double speed, double alt,const std::string&, double distance); diff --git a/src/AIModel/AIFlightPlanCreate.cxx b/src/AIModel/AIFlightPlanCreate.cxx index fdb5c5001..a9dfb15fe 100644 --- a/src/AIModel/AIFlightPlanCreate.cxx +++ b/src/AIModel/AIFlightPlanCreate.cxx @@ -62,7 +62,7 @@ bool FGAIFlightPlan::create(FGAIAircraft * ac, FGAirport * dep, int currWpt = wpt_iterator - waypoints.begin(); switch (legNr) { case 1: - retVal = createPushBack(ac, firstFlight, dep, latitude, longitude, + retVal = createPushBack(ac, firstFlight, dep, radius, fltType, aircraftType, airline); // Pregenerate the taxi leg. //if (retVal) { @@ -206,22 +206,21 @@ bool FGAIFlightPlan::createTakeoffTaxi(FGAIAircraft * ac, bool firstFlight, const string & acType, const string & airline) { - double heading, lat, lon; // If this function is called during initialization, // make sure we obtain a valid gate ID first // and place the model at the location of the gate. - if (firstFlight) { - if (!(apt->getDynamics()->getAvailableParking(&lat, &lon, - &heading, &gateId, - radius, fltType, - acType, airline))) { - SG_LOG(SG_AI, SG_WARN, "Could not find parking for a " << - acType << - " of flight type " << fltType << - " of airline " << airline << - " at airport " << apt->getId()); - } + if (firstFlight) + { + gateId = apt->getDynamics()->getAvailableParking(radius, fltType, + acType, airline); + if (gateId < 0) { + SG_LOG(SG_AI, SG_WARN, "Could not find parking for a " << + acType << + " of flight type " << fltType << + " of airline " << airline << + " at airport " << apt->getId()); + } } string rwyClass = getRunwayClassFromTrafficType(fltType); @@ -355,11 +354,9 @@ void FGAIFlightPlan::createDefaultLandingTaxi(FGAIAircraft * ac, ac->getPerformance()->vTaxi()); pushBackWaypoint(wpt); - double heading, lat, lon; - aAirport->getDynamics()->getParking(gateId, &lat, &lon, &heading); - wpt = - createOnGround(ac, "ENDtaxi", SGGeod::fromDeg(lon, lat), airportElev, - ac->getPerformance()->vTaxi()); + FGParking* parkPos = aAirport->getDynamics()->getParking(gateId); + wpt = createOnGround(ac, "ENDtaxi", parkPos->getGeod(), airportElev, + ac->getPerformance()->vTaxi()); pushBackWaypoint(wpt); } @@ -369,9 +366,7 @@ bool FGAIFlightPlan::createLandingTaxi(FGAIAircraft * ac, FGAirport * apt, const string & acType, const string & airline) { - double heading, lat, lon; - apt->getDynamics()->getAvailableParking(&lat, &lon, &heading, - &gateId, radius, fltType, + gateId = apt->getDynamics()->getAvailableParking(radius, fltType, acType, airline); SGGeod lastWptPos = @@ -1012,34 +1007,25 @@ bool FGAIFlightPlan::createParking(FGAIAircraft * ac, FGAirport * apt, { FGAIWaypoint *wpt; double aptElev = apt->getElevation(); - double lat = 0.0, lat2 = 0.0; - double lon = 0.0, lon2 = 0.0; - double az2 = 0.0; - double heading = 0.0; - double vTaxi = ac->getPerformance()->vTaxi(); double vTaxiReduced = vTaxi * (2.0 / 3.0); - apt->getDynamics()->getParking(gateId, &lat, &lon, &heading); - heading += 180.0; - if (heading > 360) - heading -= 360; - geo_direct_wgs_84(0, lat, lon, heading, - 2.2 * radius, &lat2, &lon2, &az2); - wpt = - createOnGround(ac, "taxiStart", SGGeod::fromDeg(lon2, lat2), - aptElev, vTaxiReduced); + FGParking* parking = apt->getDynamics()->getParking(gateId); + double heading = SGMiscd::normalizePeriodic(0, 360, parking->getHeading() + 180.0); + double az; // unused + SGGeod pos; + + SGGeodesy::direct(parking->getGeod(), heading, 2.2 * parking->getRadius(), + pos, az); + + wpt = createOnGround(ac, "taxiStart", pos, aptElev, vTaxiReduced); pushBackWaypoint(wpt); - geo_direct_wgs_84(0, lat, lon, heading, - 0.1 * radius, &lat2, &lon2, &az2); - - wpt = - createOnGround(ac, "taxiStart2", SGGeod::fromDeg(lon2, lat2), - aptElev, vTaxiReduced); + SGGeodesy::direct(parking->getGeod(), heading, 0.1 * parking->getRadius(), + pos, az); + wpt = createOnGround(ac, "taxiStart2", pos, aptElev, vTaxiReduced); pushBackWaypoint(wpt); - wpt = - createOnGround(ac, "END-Parking", SGGeod::fromDeg(lon, lat), aptElev, + wpt = createOnGround(ac, "END-Parking", parking->getGeod(), aptElev, vTaxiReduced); pushBackWaypoint(wpt); return true; diff --git a/src/AIModel/AIFlightPlanCreatePushBack.cxx b/src/AIModel/AIFlightPlanCreatePushBack.cxx index bf256bac9..07d7eeca1 100644 --- a/src/AIModel/AIFlightPlanCreatePushBack.cxx +++ b/src/AIModel/AIFlightPlanCreatePushBack.cxx @@ -41,14 +41,11 @@ // TODO: Use James Turner's createOnGround functions. bool FGAIFlightPlan::createPushBack(FGAIAircraft *ac, bool firstFlight, FGAirport *dep, - double latitude, - double longitude, double radius, const string& fltType, const string& aircraftType, const string& airline) { - double lat, lon, heading; double vTaxi = ac->getPerformance()->vTaxi(); double vTaxiBackward = vTaxi * (-2.0/3.0); double vTaxiReduced = vTaxi * (2.0/3.0); @@ -59,132 +56,111 @@ bool FGAIFlightPlan::createPushBack(FGAIAircraft *ac, if (!(dep->getDynamics()->getGroundNetwork()->exists())) { //cerr << "Push Back fallback" << endl; - createPushBackFallBack(ac, firstFlight, dep, latitude, longitude, + createPushBackFallBack(ac, firstFlight, dep, radius, fltType, aircraftType, airline); + return true; + } + + // establish the parking position / gate if required + if (firstFlight) { + gateId = dep->getDynamics()->getAvailableParking(radius, fltType, + aircraftType, airline); + if (gateId < 0) { + SG_LOG(SG_AI, SG_WARN, "Warning: Could not find parking for a " << + aircraftType << + " of flight type " << fltType << + " of airline " << airline << + " at airport " << dep->getId()); + return false; + } } else { - if (firstFlight) { + dep->getDynamics()->getParking(gateId); + } + + if (gateId < 0) { + createPushBackFallBack(ac, firstFlight, dep, + radius, fltType, aircraftType, airline); + return true; - if (!(dep->getDynamics()->getAvailableParking(&lat, &lon, - &heading, &gateId, - radius, fltType, - aircraftType, airline))) { - SG_LOG(SG_AI, SG_WARN, "Warning: Could not find parking for a " << - aircraftType << - " of flight type " << fltType << - " of airline " << airline << - " at airport " << dep->getId()); - return false; - char buffer[10]; - snprintf (buffer, 10, "%d", gateId); - SGGeod coord = coord.fromDeg(lon, lat); - //FGTaxiNode *tn = dep->getDynamics()->getGroundNetwork()->findNode(node); - FGAIWaypoint *wpt = createOnGround(ac, string(buffer), coord, dep->getElevation(), vTaxiBackward); - wpt->setRouteIndex(-1); - pushBackWaypoint(wpt); - } - //cerr << "Success : GateId = " << gateId << endl; - SG_LOG(SG_AI, SG_WARN, "Warning: Successfully found a parking for a " << - aircraftType << - " of flight type " << fltType << - " of airline " << airline << - " at airport " << dep->getId()); - } else { - //cerr << "Push Back follow-up Flight" << endl; - dep->getDynamics()->getParking(gateId, &lat, &lon, &heading); - } - if (gateId < 0) { - createPushBackFallBack(ac, firstFlight, dep, latitude, longitude, - radius, fltType, aircraftType, airline); - return true; + } - } - //cerr << "getting parking " << gateId; - //cerr << " for a " << - // aircraftType << - // " of flight type " << fltType << - // " of airline " << airline << - // " at airport " << dep->getId() << endl; - FGParking *parking = dep->getDynamics()->getParking(gateId); - int pushBackNode = parking->getPushBackPoint(); + FGParking *parking = dep->getDynamics()->getParking(gateId); + int pushBackNode = parking->getPushBackPoint(); + + pushBackRoute = parking->getPushBackRoute(); + if ((pushBackNode > 0) && (pushBackRoute == 0)) { // Load the already established route for this gate + int node, rte; + FGTaxiRoute route; + //cerr << "Creating push-back for " << gateId << " (" << parking->getName() << ") using push-back point " << pushBackNode << endl; + route = dep->getDynamics()->getGroundNetwork()->findShortestRoute(gateId, pushBackNode, false); + parking->setPushBackRoute(new FGTaxiRoute(route)); pushBackRoute = parking->getPushBackRoute(); - if ((pushBackNode > 0) && (pushBackRoute == 0)) { // Load the already established route for this gate - int node, rte; - FGTaxiRoute route; - //cerr << "Creating push-back for " << gateId << " (" << parking->getName() << ") using push-back point " << pushBackNode << endl; - route = dep->getDynamics()->getGroundNetwork()->findShortestRoute(gateId, pushBackNode, false); - parking->setPushBackRoute(new FGTaxiRoute(route)); - - - pushBackRoute = parking->getPushBackRoute(); - int size = pushBackRoute->size(); - if (size < 2) { - SG_LOG(SG_AI, SG_ALERT, "Push back route from gate " << gateId << " has only " << size << " nodes."); - SG_LOG(SG_AI, SG_ALERT, "Using " << pushBackNode); - } - pushBackRoute->first(); - while (pushBackRoute->next(&node, &rte)) - { - //FGTaxiNode *tn = apt->getDynamics()->getGroundNetwork()->findSegment(node)->getEnd(); - char buffer[10]; - snprintf (buffer, 10, "%d", node); - FGTaxiNode *tn = dep->getDynamics()->getGroundNetwork()->findNode(node); - //ids.pop_back(); - //wpt = new waypoint; - SGGeod coord = coord.fromDeg(tn->getLongitude(), tn->getLatitude()); - FGAIWaypoint *wpt = createOnGround(ac, string(buffer), coord, dep->getElevation(), vTaxiBackward); - - wpt->setRouteIndex(rte); - pushBackWaypoint(wpt); - } - // some special considerations for the last point: - waypoints.back()->setName(string("PushBackPoint")); - waypoints.back()->setSpeed(vTaxi); - ac->setTaxiClearanceRequest(true); - } else { // In case of a push forward departure... - ac->setTaxiClearanceRequest(false); - double lat2 = 0.0, lon2 = 0.0, az2 = 0.0; - - //cerr << "Creating final push forward point for gate " << gateId << endl; - FGTaxiNode *tn = dep->getDynamics()->getGroundNetwork()->findNode(gateId); - FGTaxiSegmentVectorIterator ts = tn->getBeginRoute(); - FGTaxiSegmentVectorIterator te = tn->getEndRoute(); - // if the starting node equals the ending node, then there aren't any routes for this parking. - // in cases like these we should flag the gate as being inoperative and return false - if (ts == te) { - SG_LOG(SG_AI, SG_ALERT, "Gate " << gateId << "doesn't seem to have routes associated with it."); - parking->setAvailable(false); - return false; - } - tn = (*ts)->getEnd(); - lastNodeVisited = tn->getIndex(); - if (tn == NULL) { - SG_LOG(SG_AI, SG_ALERT, "No valid taxinode found"); - exit(1); - } - double distance = (*ts)->getLength(); - //cerr << "Length of push forward route = " << distance << " and heading is " << heading << endl; - lat2 = tn->getLatitude(); - lon2 = tn->getLongitude(); - - for (int i = 1; i < 10; i++) { - geo_direct_wgs_84 ( 0, lat, lon, heading, - ((i / 10.0) * distance), &lat2, &lon2, &az2 ); - char buffer[16]; - snprintf(buffer, 16, "pushback-%02d", i); - SGGeod coord = coord.fromDeg(lon2, lat2); - //cerr << i << endl; - FGAIWaypoint *wpt = createOnGround(ac, string(buffer), coord, dep->getElevation(), vTaxiReduced); - - wpt->setRouteIndex((*ts)->getIndex()); - pushBackWaypoint(wpt); - } - // cerr << "Done " << endl; - waypoints.back()->setName(string("PushBackPoint")); - // cerr << "Done assinging new name" << endl; + int size = pushBackRoute->size(); + if (size < 2) { + SG_LOG(SG_AI, SG_ALERT, "Push back route from gate " << gateId << " has only " << size << " nodes."); + SG_LOG(SG_AI, SG_ALERT, "Using " << pushBackNode); } + pushBackRoute->first(); + while (pushBackRoute->next(&node, &rte)) + { + //FGTaxiNode *tn = apt->getDynamics()->getGroundNetwork()->findSegment(node)->getEnd(); + char buffer[10]; + snprintf (buffer, 10, "%d", node); + FGTaxiNode *tn = dep->getDynamics()->getGroundNetwork()->findNode(node); + //ids.pop_back(); + //wpt = new waypoint; + FGAIWaypoint *wpt = createOnGround(ac, string(buffer), tn->getGeod(), dep->getElevation(), vTaxiBackward); + + wpt->setRouteIndex(rte); + pushBackWaypoint(wpt); + } + // some special considerations for the last point: + waypoints.back()->setName(string("PushBackPoint")); + waypoints.back()->setSpeed(vTaxi); + ac->setTaxiClearanceRequest(true); + } else { // In case of a push forward departure... + ac->setTaxiClearanceRequest(false); + double az2 = 0.0; + + //cerr << "Creating final push forward point for gate " << gateId << endl; + FGTaxiNode *tn = dep->getDynamics()->getGroundNetwork()->findNode(gateId); + FGTaxiSegmentVectorIterator ts = tn->getBeginRoute(); + FGTaxiSegmentVectorIterator te = tn->getEndRoute(); + // if the starting node equals the ending node, then there aren't any routes for this parking. + // in cases like these we should flag the gate as being inoperative and return false + if (ts == te) { + SG_LOG(SG_AI, SG_ALERT, "Gate " << gateId << "doesn't seem to have routes associated with it."); + parking->setAvailable(false); + return false; + } + tn = (*ts)->getEnd(); + lastNodeVisited = tn->getIndex(); + if (tn == NULL) { + SG_LOG(SG_AI, SG_ALERT, "No valid taxinode found"); + exit(1); + } + double distance = (*ts)->getLength(); + + double parkingHeading = parking->getHeading(); + + for (int i = 1; i < 10; i++) { + SGGeod pushForwardPt; + SGGeodesy::direct(parking->getGeod(), parkingHeading, + ((i / 10.0) * distance), pushForwardPt, az2); + char buffer[16]; + snprintf(buffer, 16, "pushback-%02d", i); + FGAIWaypoint *wpt = createOnGround(ac, string(buffer), pushForwardPt, dep->getElevation(), vTaxiReduced); + + wpt->setRouteIndex((*ts)->getIndex()); + pushBackWaypoint(wpt); + } + // cerr << "Done " << endl; + waypoints.back()->setName(string("PushBackPoint")); + // cerr << "Done assinging new name" << endl; } + return true; } /******************************************************************* @@ -193,49 +169,29 @@ bool FGAIFlightPlan::createPushBack(FGAIAircraft *ac, * network yet. ******************************************************************/ void FGAIFlightPlan::createPushBackFallBack(FGAIAircraft *ac, bool firstFlight, FGAirport *dep, - double latitude, - double longitude, double radius, const string& fltType, const string& aircraftType, const string& airline) { - double heading; - double lat; - double lon; - double lat2 = 0.0; - double lon2 = 0.0; double az2 = 0.0; double vTaxi = ac->getPerformance()->vTaxi(); double vTaxiBackward = vTaxi * (-2.0/3.0); double vTaxiReduced = vTaxi * (2.0/3.0); - - - dep->getDynamics()->getParking(-1, &lat, &lon, &heading); - - heading += 180.0; - if (heading > 360) - heading -= 360; - - SGGeod coord = coord.fromDeg(lon, lat); - FGAIWaypoint *wpt = createOnGround(ac, string("park"), coord, dep->getElevation(), vTaxiBackward); + double heading = 180.0; // this is a completely arbitrary heading! + FGAIWaypoint *wpt = createOnGround(ac, string("park"), dep->geod(), dep->getElevation(), vTaxiBackward); pushBackWaypoint(wpt); - geo_direct_wgs_84 ( 0, lat, lon, heading, - 10, - &lat2, &lon2, &az2 ); - coord = coord.fromDeg(lon2, lat2); + SGGeod coord; + SGGeodesy::direct(dep->geod(), heading, 10, coord, az2); wpt = createOnGround(ac, string("park2"), coord, dep->getElevation(), vTaxiBackward); pushBackWaypoint(wpt); - - geo_direct_wgs_84 ( 0, lat, lon, heading, - 2.2*radius, - &lat2, &lon2, &az2 ); - coord = coord.fromDeg(lon2, lat2); + + SGGeodesy::direct(dep->geod(), heading, 2.2 * radius, coord, az2); wpt = createOnGround(ac, string("taxiStart"), coord, dep->getElevation(), vTaxiReduced); pushBackWaypoint(wpt); diff --git a/src/ATC/atc_mgr.cxx b/src/ATC/atc_mgr.cxx index 3b727c903..c43721739 100644 --- a/src/ATC/atc_mgr.cxx +++ b/src/ATC/atc_mgr.cxx @@ -143,8 +143,6 @@ void FGATCManager::init() { if (!(fp->createPushBack(&ai_ac, false, apt, - latitude, - longitude, aircraftRadius, fltType, aircraftType, diff --git a/src/ATC/trafficcontrol.cxx b/src/ATC/trafficcontrol.cxx index 621687687..93878e4ea 100644 --- a/src/ATC/trafficcontrol.cxx +++ b/src/ATC/trafficcontrol.cxx @@ -589,8 +589,7 @@ void FGATCController::transmit(FGTrafficRecord * rec, FGAirportDynamics *parent, getDynamics()->getActiveRunway(rwyClass, 1, activeRunway, heading); rec->getAircraft()->GetFlightPlan()->setRunway(activeRunway); - fp = rec->getAircraft()->getTrafficRef()->getDepartureAirport()-> - getDynamics()->getSID(activeRunway, heading); + fp = NULL; rec->getAircraft()->GetFlightPlan()->setSID(fp); if (fp) { SID = fp->getName() + " departure"; @@ -737,11 +736,8 @@ void FGATCController::transmit(FGTrafficRecord * rec, FGAirportDynamics *parent, SGGeod sender_pos; double sender_alt_ft, sender_alt; if(ground_to_air) { - sender_alt_ft = parent->getElevation(); - sender_alt = sender_alt_ft * SG_FEET_TO_METER; - sender_pos= SGGeod::fromDegM( parent->getLongitude(), - parent->getLatitude(), sender_alt ); - } + sender_pos = parent->parent()->geod(); + } else { sender_alt_ft = rec->getAltitude(); sender_alt = sender_alt_ft * SG_FEET_TO_METER; diff --git a/src/Airports/dynamics.cxx b/src/Airports/dynamics.cxx index b4e91554e..21d45d08b 100644 --- a/src/Airports/dynamics.cxx +++ b/src/Airports/dynamics.cxx @@ -23,6 +23,10 @@ #endif #include +#include +#include + +#include #include @@ -37,20 +41,17 @@ #include #include -#include -#include +#include "simple.hxx" +#include "dynamics.hxx" 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), SIDs(ap), - startupController (this), + _ap(ap), rwyPrefs(ap), + startupController (this), towerController (this), approachController (this), atisSequenceIndex(-1), @@ -85,159 +86,67 @@ void FGAirportDynamics::init() } -bool FGAirportDynamics::getAvailableParking(double *lat, double *lon, - double *heading, int *gateId, - double rad, - const string & flType, +int FGAirportDynamics::innerGetAvailableParking(double radius, const string & flType, + const string & acType, + const string & airline, + bool skipEmptyAirlineCode) +{ + FGParkingVecIterator i; + for (i = parkings.begin(); i != parkings.end(); i++) { + // Taken by another aircraft, or no airline codes + if (!i->isAvailable()) { + continue; + } + + if (skipEmptyAirlineCode && i->getCodes().empty()) { + continue; + } + + // check airline codes match + if (!airline.empty() && !i->getCodes().empty()) { + if (i->getCodes().find(airline, 0) == string::npos) { + continue; + } + } + + // Type doesn't match + if (i->getType() != flType) { + continue; + } + // too small + if (i->getRadius() < radius) { + continue; + } + + i->setAvailable(false); + return i->getIndex(); + } + + return -1; +} + +int FGAirportDynamics::getAvailableParking(double radius, const string & flType, const string & acType, const string & airline) { - bool found = false; - bool available = false; - - - FGParkingVecIterator i; - if (parkings.begin() == parkings.end()) { - //cerr << "Could not find parking spot at " << _ap->getId() << endl; - *lat = _ap->getLatitude(); - *lon = _ap->getLongitude(); - * gateId = -1; - *heading = 0; - found = true; - } else { - // First try finding a parking with a designated airline code - for (i = parkings.begin(); !(i == parkings.end() || found); i++) { - available = true; - // Taken by another aircraft - if (!(i->isAvailable())) { - available = false; - continue; - } - // No airline codes, so skip - if (i->getCodes().empty()) { - available = false; - continue; - } else { // Airline code doesn't match - //cerr << "Code = " << airline << ": Codes " << i->getCodes(); - if (i->getCodes().find(airline, 0) == string::npos) { - available = false; - //cerr << "Unavailable" << endl; - continue; - } else { - //cerr << "Available" << endl; - } - } - // Type doesn't match - if (i->getType() != flType) { - available = false; - continue; - } - // too small - if (i->getRadius() < rad) { - available = false; - continue; - } - - if (available) { - *lat = i->getLatitude(); - *lon = i->getLongitude(); - *heading = i->getHeading(); - *gateId = i->getIndex(); - i->setAvailable(false); - found = true; - } - } - // then try again for those without codes. - for (i = parkings.begin(); !(i == parkings.end() || found); i++) { - available = true; - if (!(i->isAvailable())) { - available = false; - continue; - } - if (!(i->getCodes().empty())) { - if ((i->getCodes().find(airline, 0) == string::npos)) { - available = false; - continue; - } - } - if (i->getType() != flType) { - available = false; - continue; - } - - if (i->getRadius() < rad) { - available = false; - continue; - } - - if (available) { - *lat = i->getLatitude(); - *lon = i->getLongitude(); - *heading = i->getHeading(); - *gateId = i->getIndex(); - i->setAvailable(false); - found = true; - } - } - // And finally once more if that didn't work. Now ignore the airline codes, as a last resort - for (i = parkings.begin(); !(i == parkings.end() || found); i++) { - available = true; - if (!(i->isAvailable())) { - available = false; - continue; - } - if (i->getType() != flType) { - available = false; - continue; - } - - if (i->getRadius() < rad) { - available = false; - continue; - } - - if (available) { - *lat = i->getLatitude(); - *lon = i->getLongitude(); - *heading = i->getHeading(); - *gateId = i->getIndex(); - i->setAvailable(false); - found = true; - } - } + if (parkings.empty()) { + return -1; } - if (!found) { - //cerr << "Traffic overflow at" << _ap->getId() - // << ". flType = " << flType - // << ". airline = " << airline - // << " Radius = " <getLatitude(); - *lon = _ap->getLongitude(); - *heading = 0; - *gateId = -1; - //exit(1); - } - return found; -} + + // most exact seach - airline codes must be present and match + int result = innerGetAvailableParking(radius, flType, acType, airline, true); + if (result >= 0) { + return result; + } + + // more tolerant - gates with empty airline codes are permitted + result = innerGetAvailableParking(radius, flType, acType, airline, false); + if (result >= 0) { + return result; + } -void FGAirportDynamics::getParking(int id, double *lat, double *lon, - double *heading) -{ - if (id < 0) { - *lat = _ap->getLatitude(); - *lon = _ap->getLongitude(); - *heading = 0; - } else { - FGParkingVecIterator i = parkings.begin(); - for (i = parkings.begin(); i != parkings.end(); i++) { - if (id == i->getIndex()) { - *lat = i->getLatitude(); - *lon = i->getLongitude(); - *heading = i->getHeading(); - } - } - } + // fallback - ignore the airline code entirely + return innerGetAvailableParking(radius, flType, acType, string(), false); } FGParking *FGAirportDynamics::getParking(int id) @@ -263,6 +172,18 @@ string FGAirportDynamics::getParkingName(int id) return string("overflow"); } +int FGAirportDynamics::findParkingByName(const std::string& name) const +{ + FGParkingVec::const_iterator i = parkings.begin(); + for (i = parkings.begin(); i != parkings.end(); i++) { + if (i->getName() == name) { + return i->getIndex(); + } + } + + return -1; +} + void FGAirportDynamics::releaseParking(int id) { if (id >= 0) { @@ -279,8 +200,6 @@ void FGAirportDynamics::releaseParking(int id) void FGAirportDynamics::setRwyUse(const FGRunwayPreference & ref) { rwyPrefs = ref; - //cerr << "Exiting due to not implemented yet" << endl; - //exit(1); } bool FGAirportDynamics::innerGetActiveRunway(const string & trafficType, @@ -466,22 +385,12 @@ void FGAirportDynamics::addParking(FGParking & park) parkings.push_back(park); } -double FGAirportDynamics::getLatitude() const -{ - return _ap->getLatitude(); -} - -double FGAirportDynamics::getLongitude() const -{ - return _ap->getLongitude(); -} - double FGAirportDynamics::getElevation() const { return _ap->getElevation(); } -const string & FGAirportDynamics::getId() const +const string FGAirportDynamics::getId() const { return _ap->getId(); } @@ -543,13 +452,6 @@ int FGAirportDynamics::getTowerFrequency(unsigned nr) return towerFreq; } - -FGAIFlightPlan *FGAirportDynamics::getSID(string activeRunway, - double heading) -{ - return SIDs.getBest(activeRunway, heading); -} - const std::string FGAirportDynamics::getAtisSequence() { if (atisSequenceIndex == -1) { diff --git a/src/Airports/dynamics.hxx b/src/Airports/dynamics.hxx index 7e828e4f9..cb489bfa3 100644 --- a/src/Airports/dynamics.hxx +++ b/src/Airports/dynamics.hxx @@ -26,7 +26,6 @@ #include "parking.hxx" #include "groundnetwork.hxx" #include "runwayprefs.hxx" -#include "sidstar.hxx" // forward decls class FGAirport; @@ -39,7 +38,6 @@ private: FGParkingVec parkings; FGRunwayPreference rwyPrefs; - FGSidStar SIDs; FGStartupController startupController; FGGroundNetwork groundNetwork; FGTowerController towerController; @@ -65,8 +63,9 @@ private: bool innerGetActiveRunway(const std::string &trafficType, int action, std::string &runway, double heading); std::string chooseRwyByHeading(stringVec rwys, double heading); - double elevation; - + int innerGetAvailableParking(double radius, const std::string & flType, + const std::string & acType, const std::string & airline, + bool skipEmptyAirlineCode); public: FGAirportDynamics(FGAirport* ap); ~FGAirportDynamics(); @@ -91,36 +90,36 @@ public: }; void init(); - double getLongitude() const; - // Returns degrees - double getLatitude() const; - // Returns ft + double getElevation() const; - const string& getId() const; - + const std::string getId() const; + + FGAirport* parent() const + { return _ap; } + void getActiveRunway(const string& trafficType, int action, string& runway, double heading); void addParking(FGParking& park); - bool getAvailableParking(double *lat, double *lon, - double *heading, int *gate, double rad, const string& fltype, - const string& acType, const string& airline); - void getParking (int id, double *lat, double* lon, double *heading); + + /** + * retrieve an available parking by GateID, or -1 if no suitable + * parking location could be found. + */ + int getAvailableParking(double radius, const std::string& fltype, + const std::string& acType, const std::string& airline); + FGParking *getParking(int i); void releaseParking(int id); - string getParkingName(int i); + std::string getParkingName(int i); int getNrOfParkings() { return parkings.size(); }; - //FGAirport *getAddress() { return this; }; - //const string &getName() const { return _name;}; - // Returns degrees - - // Departure / Arrival procedures - FGSidStar * getSIDs() { - return &SIDs; - }; - FGAIFlightPlan * getSID(string activeRunway, double heading); + /** + * Find a parking gate index by name. Note names are often not unique + * in our data, so will return the first match. + */ + int findParkingByName(const std::string& name) const; // ATC related functions. FGStartupController *getStartupController() { diff --git a/src/Airports/gnnode.hxx b/src/Airports/gnnode.hxx index aa4e7ed26..c64b51fd0 100644 --- a/src/Airports/gnnode.hxx +++ b/src/Airports/gnnode.hxx @@ -31,7 +31,7 @@ bool sortByLength (FGTaxiSegment *a, FGTaxiSegment *b); class FGTaxiNode { -private: +protected: SGGeod geod; int index; @@ -106,9 +106,9 @@ FGTaxiNode &operator =(const FGTaxiNode &other) const SGGeod& getGeod() const { return geod; } - int getIndex() { return index; }; - int getHoldPointType() { return holdType; }; - bool getIsOnRunway() { return isOnRunway; }; + int getIndex() const { return index; }; + int getHoldPointType() const { return holdType; }; + bool getIsOnRunway() const { return isOnRunway; }; FGTaxiNode *getAddress() { return this;}; FGTaxiSegmentVectorIterator getBeginRoute() { return next.begin(); }; diff --git a/src/Airports/parking.hxx b/src/Airports/parking.hxx index 0cac08bbc..1d009c03c 100644 --- a/src/Airports/parking.hxx +++ b/src/Airports/parking.hxx @@ -36,9 +36,6 @@ #include "gnnode.hxx" -using std::string; -using std::vector; - class FGTaxiRoute; @@ -46,9 +43,9 @@ class FGParking : public FGTaxiNode { private: double heading; double radius; - string parkingName; - string type; - string airlineCodes; + std::string parkingName; + std::string type; + std::string airlineCodes; bool available; int pushBackPoint; @@ -92,34 +89,26 @@ public: return *this; }; ~FGParking(); -// FGParking(double lat, -// double lon, -// double hdg, -// double rad, -// int idx, -// const string& name, -// const string& tpe, -// const string& codes); void setHeading (double hdg) { heading = hdg; }; void setRadius (double rad) { radius = rad; }; - void setName (const string& name) { parkingName = name; }; - void setType (const string& tpe) { type = tpe; }; - void setCodes (const string& codes){ airlineCodes= codes;}; + void setName (const std::string& name) { parkingName = name; }; + void setType (const std::string& tpe) { type = tpe; }; + void setCodes (const std::string& codes){ airlineCodes= codes;}; void setPushBackRoute(FGTaxiRoute *val) { pushBackRoute = val; }; void setPushBackPoint(int val) { pushBackPoint = val; }; - bool isAvailable () { return available;}; + bool isAvailable () const { return available;}; void setAvailable(bool val) { available = val; }; - double getHeading () { return heading; }; - double getRadius () { return radius; }; + double getHeading () const { return heading; }; + double getRadius () const { return radius; }; - string getType () { return type; }; - string getCodes () { return airlineCodes;}; - string getName () { return parkingName; }; + std::string getType () const { return type; }; + std::string getCodes () const { return airlineCodes;}; + std::string getName () const { return parkingName; }; FGTaxiRoute * getPushBackRoute () { return pushBackRoute; }; @@ -129,8 +118,8 @@ public: return radius < other.radius; }; }; -typedef vector FGParkingVec; -typedef vector::iterator FGParkingVecIterator; -typedef vector::const_iterator FGParkingVecConstIterator; +typedef std::vector FGParkingVec; +typedef std::vector::iterator FGParkingVecIterator; +typedef std::vector::const_iterator FGParkingVecConstIterator; #endif diff --git a/src/Airports/simple.cxx b/src/Airports/simple.cxx index 63e28c9e6..aac730e50 100644 --- a/src/Airports/simple.cxx +++ b/src/Airports/simple.cxx @@ -38,6 +38,7 @@ #include #include #include +#include #include #include @@ -115,7 +116,6 @@ FGAirportDynamics * FGAirport::getDynamics() FGRunwayPreference rwyPrefs(this); XMLLoader::load(&rwyPrefs); _dynamics->setRwyUse(rwyPrefs); - XMLLoader::load(_dynamics->getSIDs()); return _dynamics; } diff --git a/src/Airports/xmlloader.cxx b/src/Airports/xmlloader.cxx index 71082a331..8b35cabd5 100644 --- a/src/Airports/xmlloader.cxx +++ b/src/Airports/xmlloader.cxx @@ -29,6 +29,7 @@ #include "runwayprefloader.hxx" #include "dynamics.hxx" +#include "simple.hxx" #include "runwayprefs.hxx" using std::string; @@ -36,9 +37,10 @@ using std::string; XMLLoader::XMLLoader() {} XMLLoader::~XMLLoader() {} -void XMLLoader::load(FGAirportDynamics* d) { +void XMLLoader::load(FGAirportDynamics* d) +{ FGAirportDynamicsXMLLoader visitor(d); - if(loadAirportXMLDataIntoVisitor(d->getId(), "groundnet", visitor)) { + if(loadAirportXMLDataIntoVisitor(d->parent()->ident(), "groundnet", visitor)) { d->init(); } } @@ -48,13 +50,6 @@ void XMLLoader::load(FGRunwayPreference* p) { loadAirportXMLDataIntoVisitor(p->getId(), "rwyuse", visitor); } -void XMLLoader::load(FGSidStar* p) { - SGPath path; - if (findAirportData(p->getId(), "SID", path)) { - p->load(path); - } -} - bool XMLLoader::findAirportData(const std::string& aICAO, const std::string& aFileName, SGPath& aPath) { diff --git a/src/Main/positioninit.cxx b/src/Main/positioninit.cxx index 884c82181..fd5db70b1 100644 --- a/src/Main/positioninit.cxx +++ b/src/Main/positioninit.cxx @@ -24,6 +24,7 @@ // simgear #include +#include #include "globals.hxx" #include "fg_props.hxx" @@ -150,7 +151,8 @@ bool setPosFromAirportIDandHdg( const string& id, double tgt_hdg ) { } // Set current_options lon/lat given an airport id and parkig position name -static bool fgSetPosFromAirportIDandParkpos( const string& id, const string& parkpos ) { +static bool fgSetPosFromAirportIDandParkpos( const string& id, const string& parkpos ) +{ if ( id.empty() ) return false; @@ -167,11 +169,9 @@ static bool fgSetPosFromAirportIDandParkpos( const string& id, const string& par return false; } - int park_index = dcs->getNrOfParkings() - 1; - bool succes; + int gateID; double radius = fgGetDouble("/sim/dimensions/radius-m"); if ((parkpos == string("AVAILABLE")) && (radius > 0)) { - double lat, lon, heading; string fltType; string acOperator; SGPath acData; @@ -203,30 +203,27 @@ static bool fgSetPosFromAirportIDandParkpos( const string& id, const string& par } string acType; // Currently not used by findAvailable parking, so safe to leave empty. - succes = dcs->getAvailableParking(&lat, &lon, &heading, &park_index, radius, fltType, acType, acOperator); - if (succes) { + gateID = dcs->getAvailableParking(radius, fltType, acType, acOperator); + if (gateID >=0 ) { fgGetString("/sim/presets/parkpos"); - fgSetString("/sim/presets/parkpos", dcs->getParking(park_index)->getName()); + fgSetString("/sim/presets/parkpos", dcs->getParking(gateID)->getName()); } else { SG_LOG( SG_GENERAL, SG_ALERT, "Failed to find a suitable parking at airport " << id ); return false; } } else { - //cerr << "We shouldn't get here when AVAILABLE" << endl; - while (park_index >= 0 && dcs->getParkingName(park_index) != parkpos) park_index--; - if (park_index < 0) { + gateID = dcs->findParkingByName(parkpos); + if (gateID < 0) { SG_LOG( SG_GENERAL, SG_ALERT, - "Failed to find parking position " << parkpos << - " at airport " << id ); + "Failed to find a parking at airport " << id << ":" << parkpos); return false; } } - FGParking* parking = dcs->getParking(park_index); + + FGParking* parking = dcs->getParking(gateID); parking->setAvailable(false); - fgApplyStartOffset( - SGGeod::fromDeg(parking->getLongitude(), parking->getLatitude()), - parking->getHeading()); + fgApplyStartOffset(parking->getGeod(), parking->getHeading()); return true; }