X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=src%2FAIModel%2FAIFlightPlanCreate.cxx;h=d2cd7a81e386148014fd0b68c56f1fe36f1292be;hb=b78bf2e9e66f9e404f76d416db11315302da0f40;hp=f48110b72df63aab9c8f5fc70beef88f177962d9;hpb=89010e6b0ac344970dfe3e802e4e51703fedc8ff;p=flightgear.git diff --git a/src/AIModel/AIFlightPlanCreate.cxx b/src/AIModel/AIFlightPlanCreate.cxx index f48110b72..d2cd7a81e 100644 --- a/src/AIModel/AIFlightPlanCreate.cxx +++ b/src/AIModel/AIFlightPlanCreate.cxx @@ -24,8 +24,13 @@ #include "AIFlightPlan.hxx" #include +#include +#include + #include #include +#include "AIAircraft.hxx" +#include "performancedata.hxx" #include #include @@ -41,7 +46,7 @@ // Check lat/lon values during initialization; -void FGAIFlightPlan::create(FGAirport *dep, FGAirport *arr, int legNr, +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, @@ -51,32 +56,32 @@ void FGAIFlightPlan::create(FGAirport *dep, FGAirport *arr, int legNr, 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(firstFlight, dep, speed, fltType); + 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, fltType); 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); @@ -88,7 +93,7 @@ void FGAIFlightPlan::create(FGAirport *dep, FGAirport *arr, int legNr, } 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; @@ -106,7 +111,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; @@ -124,7 +129,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; @@ -143,19 +148,40 @@ FGAIFlightPlan::cloneWithPos(waypoint* aWpt, const std::string& aName, const SGG return wpt; } -void FGAIFlightPlan::createDefaultTakeoffTaxi(FGAirport* aAirport, FGRunway* aRunway) +FGAIFlightPlan::waypoint* +FGAIFlightPlan::clone(waypoint* aWpt) +{ + 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; +} + + +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, ac->getPerformance()->vTaxi()); waypoints.push_back(wpt); - wpt = createOnGround("Runway Takeoff", runwayTakeoff, airportElev, 15); + wpt = createOnGround(ac, "Runway Takeoff", runwayTakeoff, airportElev, ac->getPerformance()->vTaxi()); 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) @@ -180,13 +206,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; } @@ -225,7 +257,7 @@ void FGAIFlightPlan::createTakeoffTaxi(bool firstFlight, intVecIterator i; if (taxiRoute->empty()) { - createDefaultTakeoffTaxi(apt, rwy); + createDefaultTakeoffTaxi(ac, apt, rwy); return; } @@ -254,31 +286,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->getGeod(), apt->getElevation(), ac->getPerformance()->vTaxi()); 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, ac->getPerformance()->vTaxi()); waypoints.push_back(wpt); - wpt = createOnGround("Airport Center", aAirport->geod(), airportElev, 15); + wpt = createOnGround(ac, "Airport Center", aAirport->geod(), airportElev, ac->getPerformance()->vTaxi()); 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, ac->getPerformance()->vTaxi()); 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) { @@ -292,7 +324,7 @@ void FGAIFlightPlan::createLandingTaxi(FGAirport *apt, // Find a route from runway end to parking/gate. if (!gn->exists()) { - createDefaultLandingTaxi(apt); + createDefaultLandingTaxi(ac, apt); return; } @@ -311,7 +343,7 @@ void FGAIFlightPlan::createLandingTaxi(FGAirport *apt, intVecIterator i; if (taxiRoute->empty()) { - createDefaultLandingTaxi(apt); + createDefaultLandingTaxi(ac, apt); return; } @@ -326,7 +358,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->getGeod(), apt->getElevation(), ac->getPerformance()->vTaxi()); wpt->routeIndex = route; waypoints.push_back(wpt); } @@ -334,98 +366,149 @@ void FGAIFlightPlan::createLandingTaxi(FGAirport *apt, /******************************************************************* * CreateTakeOff - * initialize the Aircraft at the parking location + * 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(bool firstFlight, FGAirport *apt, double speed, const string &fltType) +void FGAIFlightPlan::createTakeOff(FGAIAircraft *ac, bool firstFlight, FGAirport *apt, double speed, const string &fltType) { - 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 - if (firstFlight) - { - string rwyClass = getRunwayClassFromTrafficType(fltType); - apt->getDynamics()->getActiveRunway(rwyClass, 1, activeRunway); - 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); - waypoints.push_back(wpt); - - //Start Climbing to 3000 ft. Let's do this - // at the center of the runway for now: - wpt = cloneWithPos(wpt, "SOC", rwy->geod()); - wpt->altitude = airportElev+1000; - wpt->on_ground = false; - waypoints.push_back(wpt); - - wpt = cloneWithPos(wpt, "3000 ft", rwy->reverseThreshold()); - 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->altitude = airportElev+5000; - waypoints.push_back(wpt); + 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); } /******************************************************************* * 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; +// bool planLoaded = false; + string fPLName; + double vClimb = ac->getPerformance()->vClimb(); 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->gear_down = true; - wpt->flaps_down= true; - waypoints.push_back(wpt); + if (sid) { + for (wpt_vector_iterator i = sid->getFirstWayPoint(); + i != sid->getLastWayPoint(); + i++) { + waypoints.push_back(clone(*(i))); + //cerr << " Cloning waypoint " << endl; + } + } 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(wpt, "18000ft climb", climb2); - wpt->altitude = 18000; - 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, const string &fltType) +void FGAIFlightPlan::createDecent(FGAIAircraft *ac, FGAirport *apt, const string &fltType) { // Ten thousand ft. Slowing down to 240 kts waypoint *wpt; + double vDecent = ac->getPerformance()->vDescent(); + double vApproach = ac->getPerformance()->vApproach(); //Beginning of Decent //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(), vDecent); 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(), vApproach); wpt->crossat = 3000; wpt->gear_down = true; wpt->flaps_down= true; @@ -435,38 +518,62 @@ 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, const string &fltType) { - // Ten thousand ft. Slowing down to 150 kts + 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); + + 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 - wpt = createOnGround("Threshold", rwy->displacedThreshold(), aptElev, 150); + wpt = createOnGround(ac, "Threshold", rwy->threshold(), aptElev, vTouchdown); wpt->crossat = apt->getElevation(); waypoints.push_back(wpt); // Roll-out - wpt = createOnGround("Center", rwy->geod(), aptElev, 30); + wpt = createOnGround(ac, "Center", rwy->geod(), aptElev, vTaxi*2); 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, vTaxi); wpt->crossat = apt->getElevation(); waypoints.push_back(wpt); + */ } /******************************************************************* * 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(); - double lat, lat2; - double lon, lon2; - double az2; - double heading; + 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) @@ -474,17 +581,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, vTaxiReduced); 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, vTaxiReduced); waypoints.push_back(wpt); - wpt = createOnGround("END", SGGeod::fromDeg(lon, lat), aptElev, 10); + wpt = createOnGround(ac, "END", SGGeod::fromDeg(lon, lat), aptElev, vTaxiReduced); waypoints.push_back(wpt); }