X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=src%2FAIModel%2FAIFlightPlanCreate.cxx;h=d2cd7a81e386148014fd0b68c56f1fe36f1292be;hb=b78bf2e9e66f9e404f76d416db11315302da0f40;hp=5c0aa56e3697310aed517fb9662f8e9a55a673b1;hpb=62a359cc4a338b2f8b720edf8183ab5b69710b14;p=flightgear.git diff --git a/src/AIModel/AIFlightPlanCreate.cxx b/src/AIModel/AIFlightPlanCreate.cxx index 5c0aa56e3..d2cd7a81e 100644 --- a/src/AIModel/AIFlightPlanCreate.cxx +++ b/src/AIModel/AIFlightPlanCreate.cxx @@ -14,13 +14,23 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * **************************************************************************/ + +#ifdef HAVE_CONFIG_H +# include +#endif + #include "AIFlightPlan.hxx" #include +#include +#include + #include +#include +#include "AIAircraft.hxx" +#include "performancedata.hxx" #include #include @@ -30,947 +40,597 @@ * dynamically create a flight plan for AI traffic, based on data provided by the * Traffic Manager, when reading a filed flightplan failes. (DT, 2004/07/10) * - * This is the top-level function, and the only one that publicly available. + * This is the top-level function, and the only one that is publicly available. * */ // Check lat/lon values during initialization; -void FGAIFlightPlan::create(FGAirport *dep, FGAirport *arr, int legNr, double alt, double speed, - double latitude, double longitude, bool firstFlight, - double radius, const string& fltType, const string& aircraftType, const string& airline) +void FGAIFlightPlan::create(FGAIAircraft *ac, FGAirport *dep, FGAirport *arr, int legNr, + double alt, double speed, double latitude, + double longitude, bool firstFlight,double radius, + const string& fltType, const string& aircraftType, + const string& airline) { int currWpt = wpt_iterator - waypoints.begin(); switch(legNr) { - case 1: - //cerr << "Creating Push_Back" << endl; - createPushBack(firstFlight,dep, latitude, longitude, radius, fltType, aircraftType, airline); - //cerr << "Done" << endl; + case 1: + createPushBack(ac, firstFlight,dep, latitude, longitude, + radius, fltType, aircraftType, airline); break; case 2: - //cerr << "Creating Taxi" << endl; - createTaxi(firstFlight, 1, dep, latitude, longitude, radius, fltType, aircraftType, airline); + createTakeoffTaxi(ac, firstFlight, dep, radius, fltType, aircraftType, airline); break; case 3: - //cerr << "Creating TAkeoff" << endl; - createTakeOff(firstFlight, dep, speed); + createTakeOff(ac, firstFlight, dep, speed, fltType); break; case 4: - //cerr << "Creating Climb" << endl; - createClimb(firstFlight, dep, speed, alt); + createClimb(ac, firstFlight, dep, speed, alt, fltType); break; case 5: - //cerr << "Creating Cruise" << endl; - createCruise(firstFlight, dep,arr, latitude, longitude, speed, alt); + createCruise(ac, firstFlight, dep,arr, latitude, longitude, speed, alt, fltType); break; case 6: - //cerr << "Creating Decent" << endl; - createDecent(arr); + createDecent(ac, arr, fltType); break; case 7: - //cerr << "Creating Landing" << endl; - createLanding(arr); + createLanding(ac, arr, fltType); break; case 8: - //cerr << "Creating Taxi 2" << endl; - createTaxi(false, 2, arr, latitude, longitude, radius, fltType, aircraftType, airline); + createLandingTaxi(ac, arr, radius, fltType, aircraftType, airline); break; - case 9: - //cerr << "Creating Parking" << endl; - createParking(arr); + case 9: + createParking(ac, arr, radius); break; default: //exit(1); - cerr << "Unknown case: " << legNr << endl; + SG_LOG(SG_INPUT, SG_ALERT, "AIFlightPlan::create() attempting to create unknown leg" + " this is probably an internal program error"); } wpt_iterator = waypoints.begin()+currWpt; leg++; } -/******************************************************************* - * createPushBack - * initialize the Aircraft at the parking location - ******************************************************************/ -void FGAIFlightPlan::createPushBack(bool firstFlight, FGAirport *dep, - double latitude, - double longitude, - double radius, - const string& fltType, - const string& aircraftType, - const string& airline) +FGAIFlightPlan::waypoint* +FGAIFlightPlan::createOnGround(FGAIAircraft *ac, const std::string& aName, const SGGeod& aPos, double aElev, double aSpeed) { - double heading; - double lat; - double lon; - double lat2; - double lon2; - double az2; - - //int currWpt = wpt_iterator - waypoints.begin(); - // Erase all existing waypoints. - //resetWaypoints(); - - // We only need to get a valid parking if this is the first leg. - // Otherwise use the current aircraft position. - if (firstFlight) - { - if (!(dep->getAvailableParking(&lat, &lon, &heading, &gateId, radius, fltType, aircraftType, airline))) - { - cerr << "Could not find parking " << endl; - } - } - else - { - dep->getParking(gateId, &lat, &lon, &heading); - //lat = latitude; - //lon = longitude; - //heading = getHeading(); - } - heading += 180.0; - if (heading > 360) - heading -= 360; - waypoint *wpt = new waypoint; - wpt->name = "park"; - wpt->latitude = lat; - wpt->longitude = lon; - wpt->altitude = dep->getElevation(); - wpt->speed = -10; + waypoint* wpt = new waypoint; + wpt->name = aName; + wpt->longitude = aPos.getLongitudeDeg(); + wpt->latitude = aPos.getLatitudeDeg(); + wpt->altitude = aElev; + wpt->speed = aSpeed; wpt->crossat = -10000; wpt->gear_down = true; wpt->flaps_down= true; wpt->finished = false; wpt->on_ground = true; - waypoints.push_back(wpt); - - // Add park twice, because it uses park once for initialization and once - // to trigger the departure ATC message - geo_direct_wgs_84 ( 0, lat, lon, heading, - 10, - &lat2, &lon2, &az2 ); - wpt = new waypoint; - wpt->name = "park2"; - wpt->latitude = lat2; - wpt->longitude = lon2; - wpt->altitude = dep->getElevation(); - wpt->speed = -10; - wpt->crossat = -10000; - wpt->gear_down = true; - wpt->flaps_down= true; - wpt->finished = false; - wpt->on_ground = true; - waypoints.push_back(wpt); - geo_direct_wgs_84 ( 0, lat, lon, heading, - radius, // push back one entire aircraft radius - &lat2, &lon2, &az2 ); - wpt = new waypoint; - wpt->name = "taxiStart"; - wpt->latitude = lat2; - wpt->longitude = lon2; - wpt->altitude = dep->getElevation(); - wpt->speed = 10; + wpt->routeIndex= 0; + return wpt; +} + +FGAIFlightPlan::waypoint* +FGAIFlightPlan::createInAir(FGAIAircraft *ac, const std::string& aName, const SGGeod& aPos, double aElev, double aSpeed) +{ + waypoint* wpt = new waypoint; + wpt->name = aName; + wpt->longitude = aPos.getLongitudeDeg(); + wpt->latitude = aPos.getLatitudeDeg(); + wpt->altitude = aElev; + wpt->speed = aSpeed; wpt->crossat = -10000; - wpt->gear_down = true; - wpt->flaps_down= true; + wpt->gear_down = false; + wpt->flaps_down= false; wpt->finished = false; - wpt->on_ground = true; - waypoints.push_back(wpt); + wpt->on_ground = false; + wpt->routeIndex= 0; + return wpt; +} +FGAIFlightPlan::waypoint* +FGAIFlightPlan::cloneWithPos(FGAIAircraft *ac, waypoint* aWpt, const std::string& aName, const SGGeod& aPos) +{ + waypoint* wpt = new waypoint; + wpt->name = aName; + wpt->longitude = aPos.getLongitudeDeg(); + wpt->latitude = aPos.getLatitudeDeg(); + + wpt->altitude = aWpt->altitude; + wpt->speed = aWpt->speed; + wpt->crossat = aWpt->crossat; + wpt->gear_down = aWpt->gear_down; + wpt->flaps_down= aWpt->flaps_down; + wpt->finished = aWpt->finished; + wpt->on_ground = aWpt->on_ground; + wpt->routeIndex = 0; + return wpt; } -/******************************************************************* - * createCreate Taxi. - * initialize the Aircraft at the parking location - ******************************************************************/ -void FGAIFlightPlan::createTaxi(bool firstFlight, int direction, FGAirport *apt, double latitude, double longitude, double radius, const string& fltType, const string& acType, const string& airline) +FGAIFlightPlan::waypoint* +FGAIFlightPlan::clone(waypoint* aWpt) { - double wind_speed; - double wind_heading; - double heading; - //FGRunway rwy; - double lat, lon, az; - double lat2, lon2, az2; - //int direction; - waypoint *wpt; + waypoint* wpt = new waypoint; + wpt->name = aWpt->name; + wpt->longitude = aWpt->longitude; + wpt->latitude = aWpt->latitude; + + wpt->altitude = aWpt->altitude; + wpt->speed = aWpt->speed; + wpt->crossat = aWpt->crossat; + wpt->gear_down = aWpt->gear_down; + wpt->flaps_down= aWpt->flaps_down; + wpt->finished = aWpt->finished; + wpt->on_ground = aWpt->on_ground; + wpt->routeIndex = 0; + + return wpt; +} - // Erase all existing waypoints. - // wpt_vector_iterator i= waypoints.begin(); - //resetWaypoints(); - //int currWpt = wpt_iterator - waypoints.begin(); - if (direction == 1) - { - //string name; - // "NOTE: this is currently fixed to "com" for commercial traffic - // Should be changed to be used dynamically to allow "gen" and "mil" - // as well - apt->getActiveRunway("com", 1, activeRunway); - if (!(globals->get_runways()->search(apt->getId(), - activeRunway, - &rwy))) - { - cout << "Failed to find runway for " << apt->getId() << endl; - // Hmm, how do we handle a potential error like this? - exit(1); - } - //string test; - //apt->getActiveRunway(string("com"), 1, test); - //exit(1); - - heading = rwy._heading; - double azimuth = heading + 180.0; - while ( azimuth >= 360.0 ) { azimuth -= 360.0; } - geo_direct_wgs_84 ( 0, rwy._lat, rwy._lon, azimuth, - rwy._length * SG_FEET_TO_METER * 0.5 - 5.0, - &lat2, &lon2, &az2 ); - if (apt->getGroundNetwork()->exists()) - { - intVec ids; - int runwayId = apt->getGroundNetwork()->findNearestNode(lat2, lon2); - //int currId = apt->getGroundNetwork()->findNearestNode(latitude,longitude); - //exit(1); - - // A negative gateId indicates an overflow parking, use a - // fallback mechanism for this. - // Starting from gate 0 is a bit of a hack... - FGTaxiRoute route; - if (gateId >= 0) - route = apt->getGroundNetwork()->findShortestRoute(gateId, runwayId); - else - route = apt->getGroundNetwork()->findShortestRoute(0, runwayId); - intVecIterator i; - //cerr << "creating route : "; - // No route found: go from gate directly to runway - if (route.empty()) { - //Add the runway startpoint; - wpt = new waypoint; - wpt->name = "Airport Center"; - wpt->latitude = latitude; - wpt->longitude = longitude; - wpt->altitude = apt->getElevation(); - wpt->speed = 15; - wpt->crossat = -10000; - wpt->gear_down = true; - wpt->flaps_down= true; - wpt->finished = false; - wpt->on_ground = true; - waypoints.push_back(wpt); - - //Add the runway startpoint; - wpt = new waypoint; - wpt->name = "Runway Takeoff"; - wpt->latitude = lat2; - wpt->longitude = lon2; - wpt->altitude = apt->getElevation(); - wpt->speed = 15; - wpt->crossat = -10000; - wpt->gear_down = true; - wpt->flaps_down= true; - wpt->finished = false; - wpt->on_ground = true; - waypoints.push_back(wpt); - } else { - int node; - route.first(); - while(route.next(&node)) - { - //i = ids.end()-1; - //cerr << "Creating Node: " << node << endl; - FGTaxiNode *tn = apt->getGroundNetwork()->findNode(node); - //ids.pop_back(); - wpt = new waypoint; - wpt->name = "taxiway"; // fixme: should be the name of the taxiway - wpt->latitude = tn->getLatitude(); - wpt->longitude = tn->getLongitude(); - wpt->altitude = apt->getElevation(); // should maybe be tn->elev too - wpt->speed = 15; - wpt->crossat = -10000; - wpt->gear_down = true; - wpt->flaps_down= true; - wpt->finished = false; - wpt->on_ground = true; - waypoints.push_back(wpt); - } - cerr << endl; - } - //exit(1); - } - else - { - //Add the runway startpoint; - wpt = new waypoint; - wpt->name = "Airport Center"; - wpt->latitude = apt->getLatitude(); - wpt->longitude = apt->getLongitude(); - wpt->altitude = apt->getElevation(); - wpt->speed = 15; - wpt->crossat = -10000; - wpt->gear_down = true; - wpt->flaps_down= true; - wpt->finished = false; - wpt->on_ground = true; - waypoints.push_back(wpt); - - //Add the runway startpoint; - wpt = new waypoint; - wpt->name = "Runway Takeoff"; - wpt->latitude = lat2; - wpt->longitude = lon2; - wpt->altitude = apt->getElevation(); - wpt->speed = 15; - wpt->crossat = -10000; - wpt->gear_down = true; - wpt->flaps_down= true; - wpt->finished = false; - wpt->on_ground = true; - waypoints.push_back(wpt); - //wpt = new waypoint; - //wpt->finished = false; - //waypoints.push_back(wpt); // add one more to prevent a segfault. - } - } - else // Landing taxi - { - //string name; - // "NOTE: this is currently fixed to "com" for commercial traffic - // Should be changed to be used dynamically to allow "gen" and "mil" - // as well - //apt->getActiveRunway("com", 1, name); - //if (!(globals->get_runways()->search(apt->getId(), - // name, - // &rwy))) - //{// - //cout << "Failed to find runway for " << apt->getId() << endl; - // Hmm, how do we handle a potential error like this? - // exit(1); - // } - //string test; - //apt->getActiveRunway(string("com"), 1, test); - //exit(1); - - //heading = rwy._heading; - //double azimuth = heading + 180.0; - //while ( azimuth >= 360.0 ) { azimuth -= 360.0; } - //geo_direct_wgs_84 ( 0, rwy._lat, rwy._lon, azimuth, - // rwy._length * SG_FEET_TO_METER * 0.5 - 5.0, - // &lat2, &lon2, &az2 ); - apt->getAvailableParking(&lat, &lon, &heading, &gateId, radius, fltType, acType, airline); - heading += 180.0; - if (heading > 360) - heading -= 360; - geo_direct_wgs_84 ( 0, lat, lon, heading, - 100, - &lat2, &lon2, &az2 ); - double lat3 = (*(waypoints.end()-1))->latitude; - double lon3 = (*(waypoints.end()-1))->longitude; - cerr << (*(waypoints.end()-1))->name << endl; - if (apt->getGroundNetwork()->exists()) - { - intVec ids; - int runwayId = apt->getGroundNetwork()->findNearestNode(lat3, lon3); - //int currId = apt->getGroundNetwork()->findNearestNode(latitude,longitude); - //exit(1); - - // A negative gateId indicates an overflow parking, use a - // fallback mechanism for this. - // Starting from gate 0 is a bit of a hack... - FGTaxiRoute route; - if (gateId >= 0) - route = apt->getGroundNetwork()->findShortestRoute(runwayId, gateId); - else - route = apt->getGroundNetwork()->findShortestRoute(runwayId, 0); - intVecIterator i; - //cerr << "creating route : "; - // No route found: go from gate directly to runway - if (route.empty()) { - //Add the runway startpoint; - wpt = new waypoint; - wpt->name = "Airport Center"; - wpt->latitude = latitude; - wpt->longitude = longitude; - wpt->altitude = apt->getElevation(); - wpt->speed = 15; - wpt->crossat = -10000; - wpt->gear_down = true; - wpt->flaps_down= true; - wpt->finished = false; - wpt->on_ground = true; - waypoints.push_back(wpt); - - //Add the runway startpoint; - wpt = new waypoint; - wpt->name = "Runway Takeoff"; - wpt->latitude = lat2; - wpt->longitude = lon2; - wpt->altitude = apt->getElevation(); - wpt->speed = 15; - wpt->crossat = -10000; - wpt->gear_down = true; - wpt->flaps_down= true; - wpt->finished = false; - wpt->on_ground = true; - waypoints.push_back(wpt); - } else { - int node; - route.first(); - while(route.next(&node)) - { - //i = ids.end()-1; - //cerr << "Creating Node: " << node << endl; - FGTaxiNode *tn = apt->getGroundNetwork()->findNode(node); - //ids.pop_back(); - wpt = new waypoint; - wpt->name = "taxiway"; // fixme: should be the name of the taxiway - wpt->latitude = tn->getLatitude(); - wpt->longitude = tn->getLongitude(); - wpt->altitude = apt->getElevation(); // should maybe be tn->elev too - wpt->speed = 15; - wpt->crossat = -10000; - wpt->gear_down = true; - wpt->flaps_down= true; - wpt->finished = false; - wpt->on_ground = true; - waypoints.push_back(wpt); - } - cerr << endl; - } - //exit(1); - } - else - { - //Add the runway startpoint; - wpt = new waypoint; - wpt->name = "Airport Center"; - wpt->latitude = apt->getLatitude(); - wpt->longitude = apt->getLongitude(); - wpt->altitude = apt->getElevation(); - wpt->speed = 15; - wpt->crossat = -10000; - wpt->gear_down = true; - wpt->flaps_down= true; - wpt->finished = false; - wpt->on_ground = true; - waypoints.push_back(wpt); - - } - - - - - // Add the final destination waypoint - wpt = new waypoint; - wpt->name = "Begin Parking"; //apt->getId(); //wpt_node->getStringValue("name", "END"); - wpt->latitude = lat2; - wpt->longitude = lon2; - wpt->altitude = apt->getElevation(); - wpt->speed = 15; - wpt->crossat = -10000; - wpt->gear_down = true; - wpt->flaps_down= true; - wpt->finished = false; - wpt->on_ground = true; - waypoints.push_back(wpt); - - } - // wpt_iterator = waypoints.begin(); - //if (!firstFlight) - // wpt_iterator++; - //wpt_iterator = waypoints.begin()+currWpt; +void FGAIFlightPlan::createDefaultTakeoffTaxi(FGAIAircraft *ac, FGAirport* aAirport, FGRunway* aRunway) +{ + SGGeod runwayTakeoff = aRunway->pointOnCenterline(5.0); + double airportElev = aAirport->getElevation(); + + waypoint* wpt; + wpt = createOnGround(ac, "Airport Center", aAirport->geod(), airportElev, ac->getPerformance()->vTaxi()); + waypoints.push_back(wpt); + wpt = createOnGround(ac, "Runway Takeoff", runwayTakeoff, airportElev, ac->getPerformance()->vTaxi()); + waypoints.push_back(wpt); } -/******************************************************************* - * CreateTakeOff - * initialize the Aircraft at the parking location - ******************************************************************/ -void FGAIFlightPlan::createTakeOff(bool firstFlight, FGAirport *apt, double speed) +void FGAIFlightPlan::createTakeoffTaxi(FGAIAircraft *ac, bool firstFlight, + FGAirport *apt, + double radius, const string& fltType, + const string& acType, const string& airline) { - double wind_speed; - double wind_heading; - double heading; - //FGRunway rwy; - double lat, lon, az; - double lat2, lon2, az2; - //int direction; - waypoint *wpt; + 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_INPUT, SG_WARN, "Could not find parking for a " << + acType << + " of flight type " << fltType << + " of airline " << airline << + " at airport " << apt->getId()); + } + } - // Erase all existing waypoints. - // wpt_vector_iterator i= waypoints.begin(); - //while(waypoints.begin() != waypoints.end()) - // { - // delete *(i); - // waypoints.erase(i); - // } - //resetWaypoints(); + string rwyClass = getRunwayClassFromTrafficType(fltType); + + // 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(ac, apt, rwy); + return; + } + intVec ids; + int runwayId = gn->findNearestNode(runwayTakeoff); + + // A negative gateId indicates an overflow parking, use a + // fallback mechanism for this. + // Starting from gate 0 in this case is a bit of a hack + // which requires a more proper solution later on. + delete taxiRoute; + taxiRoute = new FGTaxiRoute; + + // Determine which node to start from. + int node = 0; + // Find out which node to start from + FGParking *park = apt->getDynamics()->getParking(gateId); + if (park) { + node = park->getPushBackPoint(); + } - // Get the current active runway, based on code from David Luff - // This should actually be unified and extended to include - // Preferential runway use schema's - if (firstFlight) - { - //string name; - // "NOTE: this is currently fixed to "com" for commercial traffic - // Should be changed to be used dynamically to allow "gen" and "mil" - // as well - apt->getActiveRunway("com", 1, activeRunway); - if (!(globals->get_runways()->search(apt->getId(), - activeRunway, - &rwy))) - { - cout << "Failed to find runway for " << apt->getId() << endl; - // Hmm, how do we handle a potential error like this? - exit(1); - } - //string test; - //apt->getActiveRunway(string("com"), 1, test); - //exit(1); + if (node == -1) { + node = gateId; + } + + // HAndle case where parking doens't have a node + if ((node == 0) && park) { + if (firstFlight) { + node = gateId; + } else { + node = lastNodeVisited; } + } + + *taxiRoute = gn->findShortestRoute(node, runwayId); + intVecIterator i; + + if (taxiRoute->empty()) { + createDefaultTakeoffTaxi(ac, apt, rwy); + return; + } - heading = rwy._heading; - double azimuth = heading + 180.0; - while ( azimuth >= 360.0 ) { azimuth -= 360.0; } - geo_direct_wgs_84 ( 0, rwy._lat, rwy._lon, azimuth, - rwy._length * SG_FEET_TO_METER * 0.5 - 105.0, - &lat2, &lon2, &az2 ); - wpt = new waypoint; - wpt->name = "accel"; - wpt->latitude = lat2; - wpt->longitude = lon2; - wpt->altitude = apt->getElevation(); - wpt->speed = speed; - wpt->crossat = -10000; - wpt->gear_down = true; - wpt->flaps_down= true; - wpt->finished = false; - wpt->on_ground = true; - waypoints.push_back(wpt); + taxiRoute->first(); + //bool isPushBackPoint = false; + if (firstFlight) { + // If this is called during initialization, randomly + // skip a number of waypoints to get a more realistic + // taxi situation. + int nrWaypointsToSkip = rand() % taxiRoute->size(); + // but make sure we always keep two active waypoints + // to prevent a segmentation fault + for (int i = 0; i < nrWaypointsToSkip-2; i++) { + taxiRoute->next(&node); + } + apt->getDynamics()->releaseParking(gateId); + } else { + if (taxiRoute->size() > 1) { + taxiRoute->next(&node); // chop off the first waypoint, because that is already the last of the pushback route + } + } - lat = lat2; - lon = lon2; - az = az2; + // push each node on the taxi route as a waypoint + int route; + while(taxiRoute->next(&node, &route)) { + char buffer[10]; + snprintf (buffer, 10, "%d", node); + FGTaxiNode *tn = apt->getDynamics()->getGroundNetwork()->findNode(node); + waypoint* wpt = createOnGround(ac, buffer, tn->getGeod(), apt->getElevation(), ac->getPerformance()->vTaxi()); + wpt->routeIndex = route; + waypoints.push_back(wpt); + } +} + +void FGAIFlightPlan::createDefaultLandingTaxi(FGAIAircraft *ac, FGAirport* aAirport) +{ + SGGeod lastWptPos = + SGGeod::fromDeg(waypoints.back()->longitude, waypoints.back()->latitude); + double airportElev = aAirport->getElevation(); - //Next: the Start of Climb - geo_direct_wgs_84 ( 0, lat, lon, heading, - 2560 * SG_FEET_TO_METER, - &lat2, &lon2, &az2 ); + waypoint* wpt; + wpt = createOnGround(ac, "Runway Exit", lastWptPos, airportElev, ac->getPerformance()->vTaxi()); + waypoints.push_back(wpt); + wpt = createOnGround(ac, "Airport Center", aAirport->geod(), airportElev, ac->getPerformance()->vTaxi()); + waypoints.push_back(wpt); - wpt = new waypoint; - wpt->name = "SOC"; - wpt->latitude = lat2; - wpt->longitude = lon2; - wpt->altitude = apt->getElevation()+3000; - wpt->speed = speed; - wpt->crossat = -10000; - wpt->gear_down = true; - wpt->flaps_down= true; - wpt->finished = false; - wpt->on_ground = false; + double heading, lat, lon; + aAirport->getDynamics()->getParking(gateId, &lat, &lon, &heading); + wpt = createOnGround(ac, "END", SGGeod::fromDeg(lon, lat), airportElev, ac->getPerformance()->vTaxi()); waypoints.push_back(wpt); - // waypoints.push_back(wpt); - //waypoints.push_back(wpt); // add one more to prevent a segfault. - // wpt_iterator = waypoints.begin(); - //if (!firstFlight) - // wpt_iterator++; } - -/******************************************************************* - * CreateClimb - * initialize the Aircraft at the parking location - ******************************************************************/ -void FGAIFlightPlan::createClimb(bool firstFlight, FGAirport *apt, double speed, double alt) -{ - double wind_speed; - double wind_heading; - double heading; - //FGRunway rwy; - double lat, lon, az; - double lat2, lon2, az2; - //int direction; - waypoint *wpt; - // Erase all existing waypoints. - // wpt_vector_iterator i= waypoints.begin(); - //while(waypoints.begin() != waypoints.end()) - // { - // delete *(i); - // waypoints.erase(i); - // } - //resetWaypoints(); +void FGAIFlightPlan::createLandingTaxi(FGAIAircraft *ac, FGAirport *apt, + double radius, const string& fltType, + const string& acType, const string& airline) +{ + double heading, lat, lon; + apt->getDynamics()->getAvailableParking(&lat, &lon, &heading, + &gateId, radius, fltType, acType, airline); + SGGeod lastWptPos = + SGGeod::fromDeg(waypoints.back()->longitude, waypoints.back()->latitude); + FGGroundNetwork* gn = apt->getDynamics()->getGroundNetwork(); - // Get the current active runway, based on code from David Luff - // This should actually be unified and extended to include - // Preferential runway use schema's - if (firstFlight) - { - //string name; - // "NOTE: this is currently fixed to "com" for commercial traffic - // Should be changed to be used dynamically to allow "gen" and "mil" - // as well - apt->getActiveRunway("com", 1, activeRunway); - if (!(globals->get_runways()->search(apt->getId(), - activeRunway, - &rwy))) - { - cout << "Failed to find runway for " << apt->getId() << endl; - // Hmm, how do we handle a potential error like this? - exit(1); - } - //string test; - //apt->getActiveRunway(string("com"), 1, test); - //exit(1); - } + // Find a route from runway end to parking/gate. + if (!gn->exists()) { + createDefaultLandingTaxi(ac, apt); + return; + } + intVec ids; + int runwayId = gn->findNearestNode(lastWptPos); + // A negative gateId indicates an overflow parking, use a + // fallback mechanism for this. + // Starting from gate 0 is a bit of a hack... + //FGTaxiRoute route; + delete taxiRoute; + taxiRoute = new FGTaxiRoute; + if (gateId >= 0) + *taxiRoute = gn->findShortestRoute(runwayId, gateId); + else + *taxiRoute = gn->findShortestRoute(runwayId, 0); + intVecIterator i; - heading = rwy._heading; - double azimuth = heading + 180.0; - while ( azimuth >= 360.0 ) { azimuth -= 360.0; } - geo_direct_wgs_84 ( 0, rwy._lat, rwy._lon, heading, - 10*SG_NM_TO_METER, - &lat2, &lon2, &az2 ); - wpt = new waypoint; - wpt->name = "10000ft climb"; - wpt->latitude = lat2; - wpt->longitude = lon2; - wpt->altitude = 10000; - wpt->speed = speed; - wpt->crossat = -10000; - wpt->gear_down = true; - wpt->flaps_down= true; - wpt->finished = false; - wpt->on_ground = false; - waypoints.push_back(wpt); + if (taxiRoute->empty()) { + createDefaultLandingTaxi(ac, apt); + return; + } - - geo_direct_wgs_84 ( 0, rwy._lat, rwy._lon, heading, - 20*SG_NM_TO_METER, - &lat2, &lon2, &az2 ); - wpt = new waypoint; - wpt->name = "18000ft climb"; - wpt->latitude = lat2; - wpt->longitude = lon2; - wpt->altitude = 18000; - wpt->speed = speed; - wpt->crossat = -10000; - wpt->gear_down = true; - wpt->flaps_down= true; - wpt->finished = false; - wpt->on_ground = false; - waypoints.push_back(wpt); - //waypoints.push_back(wpt); - //waypoints.push_back(wpt); // add one more to prevent a segfault. - // wpt_iterator = waypoints.begin(); - //if (!firstFlight) - // wpt_iterator++; + int node; + taxiRoute->first(); + int size = taxiRoute->size(); + // Omit the last two waypoints, as + // those are created by createParking() + int route; + for (int i = 0; i < size-2; i++) { + taxiRoute->next(&node, &route); + char buffer[10]; + snprintf (buffer, 10, "%d", node); + FGTaxiNode *tn = gn->findNode(node); + waypoint* wpt = createOnGround(ac, buffer, tn->getGeod(), apt->getElevation(), ac->getPerformance()->vTaxi()); + wpt->routeIndex = route; + waypoints.push_back(wpt); + } } +/******************************************************************* + * CreateTakeOff + * A note on units: + * - Speed -> knots -> nm/hour + * - distance along runway =-> meters + * - accel / decel -> is given as knots/hour, but this is highly questionable: + * for a jet_transport performance class, a accel / decel rate of 5 / 2 is + * given respectively. According to performance data.cxx, a value of kts / second seems + * more likely however. + * + ******************************************************************/ +void FGAIFlightPlan::createTakeOff(FGAIAircraft *ac, bool firstFlight, FGAirport *apt, double speed, const string &fltType) +{ + double accel = ac->getPerformance()->acceleration(); + double vTaxi = ac->getPerformance()->vTaxi(); + double vRotate = ac->getPerformance()->vRotate(); + double vTakeoff = ac->getPerformance()->vTakeoff(); + double vClimb = ac->getPerformance()->vClimb(); + + double accelMetric = (accel * SG_NM_TO_METER) / 3600; + double vTaxiMetric = (vTaxi * SG_NM_TO_METER) / 3600; + double vRotateMetric = (vRotate * SG_NM_TO_METER) / 3600; + double vTakeoffMetric = (vTakeoff * SG_NM_TO_METER) / 3600; + double vClimbMetric = (vClimb * SG_NM_TO_METER) / 3600; + // Acceleration = dV / dT + // Acceleration X dT = dV + // dT = dT / Acceleration + //d = (Vf^2 - Vo^2) / (2*a) + //double accelTime = (vRotate - vTaxi) / accel; + //cerr << "Using " << accelTime << " as total acceleration time" << endl; + double accelDistance = (vRotateMetric*vRotateMetric - vTaxiMetric*vTaxiMetric) / (2*accelMetric); + cerr << "Using " << accelDistance << " " << accelMetric << " " << vRotateMetric << endl; + waypoint *wpt; + // Get the current active runway, based on code from David Luff + // This should actually be unified and extended to include + // Preferential runway use schema's + // NOTE: DT (2009-01-18: IIRC, this is currently already the case, + // because the getActive runway function takes care of that. + if (firstFlight) + { + string rwyClass = getRunwayClassFromTrafficType(fltType); + 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(ac, "accel", accelPoint, airportElev, vRotate); + waypoints.push_back(wpt); + + + accelDistance = (vTakeoffMetric*vTakeoffMetric - vTaxiMetric*vTaxiMetric) / (2*accelMetric); + cerr << "Using " << accelDistance << " " << accelMetric << " " << vTakeoffMetric << endl; + accelPoint = rwy->pointOnCenterline(105.0+accelDistance); + wpt = createOnGround(ac, "rotate", accelPoint, airportElev, vTakeoff); + waypoints.push_back(wpt); + + accelDistance = ((vTakeoffMetric*1.1)*(vTakeoffMetric*1.1) - vTaxiMetric*vTaxiMetric) / (2*accelMetric); + cerr << "Using " << accelDistance << " " << accelMetric << " " << vTakeoffMetric << endl; + accelPoint = rwy->pointOnCenterline(105.0+accelDistance); + wpt = createOnGround(ac, "rotate", accelPoint, airportElev+1000, vTakeoff*1.1); + wpt->on_ground = false; + waypoints.push_back(wpt); + + 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(ac, wpt, "5000 ft", pt); + wpt->altitude = airportElev+5000; + waypoints.push_back(wpt); +} + /******************************************************************* - * CreateCruise + * CreateClimb * initialize the Aircraft at the parking location ******************************************************************/ -void FGAIFlightPlan::createCruise(bool firstFlight, FGAirport *dep, FGAirport *arr, double latitude, double longitude, double speed, double alt) +void FGAIFlightPlan::createClimb(FGAIAircraft *ac, bool firstFlight, FGAirport *apt, double speed, double alt, const string &fltType) { - double wind_speed; - double wind_heading; - double heading; - //FGRunway rwy; - double lat, lon, az; - double lat2, lon2, az2; - double azimuth; - //int direction; waypoint *wpt; - - // Erase all existing waypoints. - // wpt_vector_iterator i= waypoints.begin(); - //while(waypoints.begin() != waypoints.end()) - // { - // delete *(i); - // waypoints.erase(i); - // } - //resetWaypoints(); - - wpt = new waypoint; - wpt->name = "Cruise"; //wpt_node->getStringValue("name", "END"); - wpt->latitude = latitude; - wpt->longitude = longitude; - wpt->altitude = alt; - wpt->speed = speed; - wpt->crossat = -10000; - wpt->gear_down = false; - wpt->flaps_down= false; - wpt->finished = false; - wpt->on_ground = false; - waypoints.push_back(wpt); - //Beginning of Decent - - //string name; - // should be changed dynamically to allow "gen" and "mil" - arr->getActiveRunway("com", 2, activeRunway); - if (!(globals->get_runways()->search(arr->getId(), - activeRunway, - &rwy))) - { - cout << "Failed to find runway for " << arr->getId() << endl; - // Hmm, how do we handle a potential error like this? - exit(1); +// bool planLoaded = false; + string fPLName; + double vClimb = ac->getPerformance()->vClimb(); + + if (firstFlight) { + string rwyClass = getRunwayClassFromTrafficType(fltType); + double heading = ac->getTrafficRef()->getCourse(); + apt->getDynamics()->getActiveRunway(rwyClass, 1, activeRunway, heading); + rwy = apt->getRunwayByIdent(activeRunway); + } + if (sid) { + for (wpt_vector_iterator i = sid->getFirstWayPoint(); + i != sid->getLastWayPoint(); + i++) { + waypoints.push_back(clone(*(i))); + //cerr << " Cloning waypoint " << endl; } - //string test; - //arr->getActiveRunway(string("com"), 1, test); - //exit(1); - - //cerr << "Altitude = " << alt << endl; - //cerr << "Done" << endl; - //if (arr->getId() == "EHAM") - // { - // cerr << "Creating cruise to EHAM " << latitude << " " << longitude << endl; - // } - heading = rwy._heading; - azimuth = heading + 180.0; - while ( azimuth >= 360.0 ) { azimuth -= 360.0; } - - - // Note: This places us at the location of the active - // runway during initial cruise. This needs to be - // fixed later. - geo_direct_wgs_84 ( 0, rwy._lat, rwy._lon, azimuth, - 110000, - &lat2, &lon2, &az2 ); - wpt = new waypoint; - wpt->name = "BOD"; //wpt_node->getStringValue("name", "END"); - wpt->latitude = lat2; - wpt->longitude = lon2; - wpt->altitude = alt; - wpt->speed = speed; - wpt->crossat = alt; - wpt->gear_down = false; - wpt->flaps_down= false; - wpt->finished = false; - wpt->on_ground = false; - waypoints.push_back(wpt); - //waypoints.push_back(wpt); - //waypoints.push_back(wpt); // add one more to prevent a segfault. - //wpt_iterator = waypoints.begin(); - //if (!firstFlight) - // wpt_iterator++; + } else { + SGGeod climb1 = rwy->pointOnCenterline(10*SG_NM_TO_METER); + wpt = createInAir(ac, "10000ft climb", climb1, vClimb, 10000); + wpt->gear_down = true; + wpt->flaps_down= true; + waypoints.push_back(wpt); + + SGGeod climb2 = rwy->pointOnCenterline(20*SG_NM_TO_METER); + wpt = cloneWithPos(ac, wpt, "18000ft climb", climb2); + wpt->altitude = 18000; + waypoints.push_back(wpt); + } } + + /******************************************************************* * CreateDecent * initialize the Aircraft at the parking location ******************************************************************/ -void FGAIFlightPlan::createDecent(FGAirport *apt) +void FGAIFlightPlan::createDecent(FGAIAircraft *ac, FGAirport *apt, const string &fltType) { - // Ten thousand ft. Slowing down to 240 kts - double wind_speed; - double wind_heading; - double heading; - //FGRunway rwy; - double lat, lon, az; - double lat2, lon2, az2; - double azimuth; - //int direction; waypoint *wpt; - - //// Erase all existing waypoints. - // wpt_vector_iterator i= waypoints.begin(); - //while(waypoints.begin() != waypoints.end()) - // { - // delete *(i); - // waypoints.erase(i); - // } - //resetWaypoints(); + double vDecent = ac->getPerformance()->vDescent(); + double vApproach = ac->getPerformance()->vApproach(); //Beginning of Decent //string name; // allow "mil" and "gen" as well - apt->getActiveRunway("com", 2, activeRunway); - if (!(globals->get_runways()->search(apt->getId(), - activeRunway, - &rwy))) - { - cout << "Failed to find runway for " << apt->getId() << endl; - // Hmm, how do we handle a potential error like this? - exit(1); - } - //string test; - //apt->getActiveRunway(string("com"), 1, test); - //exit(1); - - //cerr << "Done" << endl; - heading = rwy._heading; - azimuth = heading + 180.0; - while ( azimuth >= 360.0 ) { azimuth -= 360.0; } - - - - geo_direct_wgs_84 ( 0, rwy._lat, rwy._lon, azimuth, - 100000, - &lat2, &lon2, &az2 ); - - wpt = new waypoint; - wpt->name = "Dec 10000ft"; //wpt_node->getStringValue("name", "END"); - wpt->latitude = lat2; - wpt->longitude = lon2; - wpt->altitude = apt->getElevation(); - wpt->speed = 240; + string rwyClass = getRunwayClassFromTrafficType(fltType); + 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(ac, "Dec 10000ft", descent1, apt->getElevation(), vDecent); wpt->crossat = 10000; - wpt->gear_down = false; - wpt->flaps_down= false; - wpt->finished = false; - wpt->on_ground = false; waypoints.push_back(wpt); - + // Three thousand ft. Slowing down to 160 kts - geo_direct_wgs_84 ( 0, rwy._lat, rwy._lon, azimuth, - 8*SG_NM_TO_METER, - &lat2, &lon2, &az2 ); - wpt = new waypoint; - wpt->name = "DEC 3000ft"; //wpt_node->getStringValue("name", "END"); - wpt->latitude = lat2; - wpt->longitude = lon2; - wpt->altitude = apt->getElevation(); - wpt->speed = 160; + SGGeod descent2 = rwy->pointOnCenterline(-8*SG_NM_TO_METER); // 8nm out + wpt = createInAir(ac, "DEC 3000ft", descent2, apt->getElevation(), vApproach); wpt->crossat = 3000; wpt->gear_down = true; wpt->flaps_down= true; - wpt->finished = false; - wpt->on_ground = false; waypoints.push_back(wpt); - //waypoints.push_back(wpt); - //waypoints.push_back(wpt); // add one more to prevent a segfault. - //wpt_iterator = waypoints.begin(); - //wpt_iterator++; - //if (apt->getId() == "EHAM") - // { - // cerr << "Created Decend to EHAM " << lat2 << " " << lon2 << ": Runway = " << rwy._rwy_no - // << "heading " << heading << endl; - // } } /******************************************************************* * CreateLanding * initialize the Aircraft at the parking location ******************************************************************/ -void FGAIFlightPlan::createLanding(FGAirport *apt) +void FGAIFlightPlan::createLanding(FGAIAircraft *ac, FGAirport *apt, const string &fltType) { - // Ten thousand ft. Slowing down to 240 kts - double wind_speed; - double wind_heading; - double heading; - //FGRunway rwy; - double lat, lon, az; - double lat2, lon2, az2; - double azimuth; - //int direction; - waypoint *wpt; + double vTouchdown = ac->getPerformance()->vTouchdown(); + double vTaxi = ac->getPerformance()->vTaxi(); + string rwyClass = getRunwayClassFromTrafficType(fltType); + double heading = ac->getTrafficRef()->getCourse(); + apt->getDynamics()->getActiveRunway(rwyClass, 2, activeRunway, heading); + rwy = apt->getRunwayByIdent(activeRunway); - heading = rwy._heading; - azimuth = heading + 180.0; - while ( azimuth >= 360.0 ) { azimuth -= 360.0; } + waypoint *wpt; + double aptElev = apt->getElevation(); + + SGGeod coord; + char buffer[12]; + for (int i = 1; i < 10; i++) { + snprintf(buffer, 12, "wpt%d", i); + coord = rwy->pointOnCenterline(rwy->lengthM() * (i/10.0)); + wpt = createOnGround(ac, buffer, coord, aptElev, (vTouchdown/i)); + wpt->crossat = apt->getElevation(); + waypoints.push_back(wpt); + } + + /* //Runway Threshold - geo_direct_wgs_84 ( 0, rwy._lat, rwy._lon, azimuth, - rwy._length*0.45 * SG_FEET_TO_METER, - &lat2, &lon2, &az2 ); - wpt = new waypoint; - wpt->name = "Threshold"; //wpt_node->getStringValue("name", "END"); - wpt->latitude = lat2; - wpt->longitude = lon2; - wpt->altitude = apt->getElevation(); - wpt->speed = 150; - wpt->crossat = apt->getElevation(); - wpt->gear_down = true; - wpt->flaps_down= true; - wpt->finished = false; - wpt->on_ground = true; + wpt = createOnGround(ac, "Threshold", rwy->threshold(), aptElev, vTouchdown); + wpt->crossat = apt->getElevation(); waypoints.push_back(wpt); - //Full stop at the runway centerpoint - geo_direct_wgs_84 ( 0, rwy._lat, rwy._lon, azimuth, - rwy._length*0.45, - &lat2, &lon2, &az2 ); - wpt = new waypoint; - wpt->name = "Center"; //wpt_node->getStringValue("name", "END"); - wpt->latitude = rwy._lat; - wpt->longitude = rwy._lon; - wpt->altitude = apt->getElevation(); - wpt->speed = 30; - wpt->crossat = -10000; - wpt->gear_down = true; - wpt->flaps_down= true; - wpt->finished = false; - wpt->on_ground = true; + // Roll-out + wpt = createOnGround(ac, "Center", rwy->geod(), aptElev, vTaxi*2); waypoints.push_back(wpt); - geo_direct_wgs_84 ( 0, rwy._lat, rwy._lon, heading, - rwy._length*0.45 * SG_FEET_TO_METER, - &lat2, &lon2, &az2 ); - wpt = new waypoint; - wpt->name = "Threshold"; //wpt_node->getStringValue("name", "END"); - wpt->latitude = lat2; - wpt->longitude = lon2; - wpt->altitude = apt->getElevation(); - wpt->speed = 15; + SGGeod rollOut = rwy->pointOnCenterline(rwy->lengthM() * 0.9); + wpt = createOnGround(ac, "Roll Out", rollOut, aptElev, vTaxi); wpt->crossat = apt->getElevation(); - wpt->gear_down = true; - wpt->flaps_down= true; - wpt->finished = false; - wpt->on_ground = true; waypoints.push_back(wpt); - //waypoints.push_back(wpt); - //waypoints.push_back(wpt); // add one more to prevent a segfault. - //wpt_iterator = waypoints.begin(); - //wpt_iterator++; - - //if (apt->getId() == "EHAM") - //{ - // cerr << "Created Landing to EHAM " << lat2 << " " << lon2 << ": Runway = " << rwy._rwy_no - // << "heading " << heading << endl; - //} + */ } /******************************************************************* * CreateParking * initialize the Aircraft at the parking location ******************************************************************/ -void FGAIFlightPlan::createParking(FGAirport *apt) +void FGAIFlightPlan::createParking(FGAIAircraft *ac, FGAirport *apt, double radius) { waypoint* wpt; - double lat; - double lon; - double heading; - apt->getParking(gateId, &lat, &lon, &heading); + 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); + waypoints.push_back(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); + waypoints.push_back(wpt); - // Erase all existing waypoints. - // wpt_vector_iterator i= waypoints.begin(); - //while(waypoints.begin() != waypoints.end()) - // { - // delete *(i); - // waypoints.erase(i); - // } - //resetWaypoints(); - // And finally one more named "END" - wpt = new waypoint; - wpt->name = "END"; //wpt_node->getStringValue("name", "END"); - wpt->latitude = lat; - wpt->longitude = lon; - wpt->altitude = 19; - wpt->speed = 15; - wpt->crossat = -10000; - wpt->gear_down = true; - wpt->flaps_down= true; - wpt->finished = false; - wpt->on_ground = true; + wpt = createOnGround(ac, "END", SGGeod::fromDeg(lon, lat), aptElev, vTaxiReduced); waypoints.push_back(wpt); - //waypoints.push_back(wpt); - //waypoints.push_back(wpt); // add one more to prevent a segfault. - //wpt_iterator = waypoints.begin(); - //wpt_iterator++; +} + +/** + * + * @param fltType a string describing the type of + * traffic, normally used for gate assignments + * @return a converted string that gives the runway + * preference schedule to be used at aircraft having + * a preferential runway schedule implemented (i.e. + * having a rwyprefs.xml file + * + * Currently valid traffic types for gate assignment: + * - gate (commercial gate) + * - cargo (commercial gargo), + * - ga (general aviation) , + * - ul (ultralight), + * - mil-fighter (military - fighter), + * - mil-transport (military - transport) + * + * Valid runway classes: + * - com (commercial traffic: jetliners, passenger and cargo) + * - gen (general aviation) + * - ul (ultralight: I can imagine that these may share a runway with ga on some airports) + * - mil (all military traffic) + */ +string FGAIFlightPlan::getRunwayClassFromTrafficType(string fltType) +{ + if ((fltType == "gate") || (fltType == "cargo")) { + return string("com"); + } + if (fltType == "ga") { + return string ("gen"); + } + if (fltType == "ul") { + return string("ul"); + } + if ((fltType == "mil-fighter") || (fltType == "mil-transport")) { + return string("mil"); + } + return string("com"); }