X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;ds=sidebyside;f=src%2FAIModel%2FAIFlightPlanCreate.cxx;h=c49b4abe8a6c7504e764ec779c22d4c63c5beb7b;hb=b1ff365a8f0bf2f25f030ef2058c42f3052e0d8b;hp=ef12ac4890733067583948e731c694daafa9c73a;hpb=dbceffeae81fe2e25e6578465969d726ee28ce1c;p=flightgear.git diff --git a/src/AIModel/AIFlightPlanCreate.cxx b/src/AIModel/AIFlightPlanCreate.cxx index ef12ac489..c49b4abe8 100644 --- a/src/AIModel/AIFlightPlanCreate.cxx +++ b/src/AIModel/AIFlightPlanCreate.cxx @@ -22,6 +22,8 @@ # include #endif +#include + #include "AIFlightPlan.hxx" #include #include @@ -35,6 +37,7 @@ #include #include +#include /* FGAIFlightPlan::create() @@ -59,8 +62,13 @@ 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) { + // waypoints.back()->setName( waypoints.back()->getName() + string("legend")); + // retVal = createTakeoffTaxi(ac, false, dep, radius, fltType, aircraftType, airline); + //} break; case 2: retVal = createTakeoffTaxi(ac, firstFlight, dep, radius, fltType, @@ -91,99 +99,88 @@ bool FGAIFlightPlan::create(FGAIAircraft * ac, FGAirport * dep, break; default: //exit(1); - SG_LOG(SG_INPUT, SG_ALERT, + SG_LOG(SG_AI, SG_ALERT, "AIFlightPlan::create() attempting to create unknown leg" " this is probably an internal program error"); } wpt_iterator = waypoints.begin() + currWpt; - leg++; + //don't increment leg right away, but only once we pass the actual last waypoint that was created. + // to do so, mark the last waypoint with a special status flag + if (retVal) { + waypoints.back()->setName( waypoints.back()->getName() + string("legend")); + // "It's pronounced Leg-end" (Roger Glover (Deep Purple): come Hell or High Water DvD, 1993) + } + + + //leg++; return retVal; } -FGAIFlightPlan::waypoint * - FGAIFlightPlan::createOnGround(FGAIAircraft * ac, +FGAIWaypoint * FGAIFlightPlan::createOnGround(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.1; - wpt->gear_down = true; - wpt->flaps_down = true; - wpt->finished = false; - wpt->on_ground = true; - wpt->routeIndex = 0; + FGAIWaypoint *wpt = new FGAIWaypoint; + wpt->setName (aName ); + wpt->setLongitude (aPos.getLongitudeDeg() ); + wpt->setLatitude (aPos.getLatitudeDeg() ); + wpt->setAltitude (aElev ); + wpt->setSpeed (aSpeed ); + wpt->setCrossat (-10000.1 ); + wpt->setGear_down (true ); + wpt->setFlaps_down (true ); + wpt->setFinished (false ); + wpt->setOn_ground (true ); + wpt->setRouteIndex (0 ); return wpt; } -FGAIFlightPlan::waypoint * - FGAIFlightPlan::createInAir(FGAIAircraft * ac, +FGAIWaypoint * 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.1; - wpt->gear_down = false; - wpt->flaps_down = false; - wpt->finished = false; - wpt->on_ground = false; - wpt->routeIndex = 0; + FGAIWaypoint * wpt = createOnGround(ac, aName, aPos, aElev, aSpeed); + wpt->setGear_down (false ); + wpt->setFlaps_down (false ); + wpt->setOn_ground (false ); return wpt; } -FGAIFlightPlan::waypoint * - FGAIFlightPlan::cloneWithPos(FGAIAircraft * ac, waypoint * aWpt, - const std::string & aName, - const SGGeod & aPos) +FGAIWaypoint * FGAIFlightPlan::clone(FGAIWaypoint * aWpt) { - 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; + FGAIWaypoint *wpt = new FGAIWaypoint; + wpt->setName ( aWpt->getName () ); + wpt->setLongitude ( aWpt->getLongitude() ); + wpt->setLatitude ( aWpt->getLatitude() ); + wpt->setAltitude ( aWpt->getAltitude() ); + wpt->setSpeed ( aWpt->getSpeed() ); + wpt->setCrossat ( aWpt->getCrossat() ); + wpt->setGear_down ( aWpt->getGear_down() ); + wpt->setFlaps_down ( aWpt->getFlaps_down() ); + wpt->setFinished ( aWpt->isFinished() ); + wpt->setOn_ground ( aWpt->getOn_ground() ); + wpt->setRouteIndex ( 0 ); return wpt; } -FGAIFlightPlan::waypoint * FGAIFlightPlan::clone(waypoint * aWpt) + +FGAIWaypoint * FGAIFlightPlan::cloneWithPos(FGAIAircraft * ac, FGAIWaypoint * aWpt, + const std::string & aName, + const SGGeod & aPos) { - 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; + FGAIWaypoint *wpt = clone(aWpt); + wpt->setName ( aName ); + wpt->setLongitude ( aPos.getLongitudeDeg () ); + wpt->setLatitude ( aPos.getLatitudeDeg () ); return wpt; } + void FGAIFlightPlan::createDefaultTakeoffTaxi(FGAIAircraft * ac, FGAirport * aAirport, FGRunway * aRunway) @@ -191,15 +188,15 @@ void FGAIFlightPlan::createDefaultTakeoffTaxi(FGAIAircraft * ac, SGGeod runwayTakeoff = aRunway->pointOnCenterline(5.0); double airportElev = aAirport->getElevation(); - waypoint *wpt; + FGAIWaypoint *wpt; wpt = createOnGround(ac, "Airport Center", aAirport->geod(), airportElev, ac->getPerformance()->vTaxi()); - waypoints.push_back(wpt); + pushBackWaypoint(wpt); wpt = createOnGround(ac, "Runway Takeoff", runwayTakeoff, airportElev, ac->getPerformance()->vTaxi()); - waypoints.push_back(wpt); + pushBackWaypoint(wpt); } bool FGAIFlightPlan::createTakeoffTaxi(FGAIAircraft * ac, bool firstFlight, @@ -209,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_INPUT, 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); @@ -236,7 +232,8 @@ bool FGAIFlightPlan::createTakeoffTaxi(FGAIAircraft * ac, bool firstFlight, apt->getDynamics()->getActiveRunway(rwyClass, 1, activeRunway, depHeading); } - rwy = apt->getRunwayByIdent(activeRunway); + FGRunway * rwy = apt->getRunwayByIdent(activeRunway); + assert( rwy != NULL ); SGGeod runwayTakeoff = rwy->pointOnCenterline(5.0); FGGroundNetwork *gn = apt->getDynamics()->getGroundNetwork(); @@ -246,7 +243,12 @@ bool FGAIFlightPlan::createTakeoffTaxi(FGAIAircraft * ac, bool firstFlight, } intVec ids; - int runwayId = gn->findNearestNode(runwayTakeoff); + int runwayId = 0; + if (gn->getVersion() > 0) { + runwayId = gn->findNearestNodeOnRunway(runwayTakeoff); + } else { + runwayId = gn->findNearestNode(runwayTakeoff); + } // A negative gateId indicates an overflow parking, use a // fallback mechanism for this. @@ -304,17 +306,33 @@ bool FGAIFlightPlan::createTakeoffTaxi(FGAIAircraft * ac, bool firstFlight, // push each node on the taxi route as a waypoint int route; + //cerr << "Building taxi route" << endl; 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(), + FGAIWaypoint *wpt = + createOnGround(ac, buffer, tn->geod(), apt->getElevation(), ac->getPerformance()->vTaxi()); - wpt->routeIndex = route; - waypoints.push_back(wpt); + wpt->setRouteIndex(route); + //cerr << "Nodes left " << taxiRoute->nodesLeft() << " "; + if (taxiRoute->nodesLeft() == 1) { + // Note that we actually have hold points in the ground network, but this is just an initial test. + //cerr << "Setting departurehold point: " << endl; + wpt->setName( wpt->getName() + string("DepartureHold")); + } + if (taxiRoute->nodesLeft() == 0) { + wpt->setName(wpt->getName() + string("Accel")); + } + pushBackWaypoint(wpt); } + // Acceleration point, 105 meters into the runway, + SGGeod accelPoint = rwy->pointOnCenterline(105.0); + FGAIWaypoint *wpt = createOnGround(ac, "accel", accelPoint, apt->getElevation(), ac->getPerformance()->vRotate()); + pushBackWaypoint(wpt); + + //cerr << "[done]" << endl; return true; } @@ -322,26 +340,26 @@ void FGAIFlightPlan::createDefaultLandingTaxi(FGAIAircraft * ac, FGAirport * aAirport) { SGGeod lastWptPos = - SGGeod::fromDeg(waypoints.back()->longitude, - waypoints.back()->latitude); + SGGeod::fromDeg(waypoints.back()->getLongitude(), + waypoints.back()->getLatitude()); double airportElev = aAirport->getElevation(); - waypoint *wpt; + FGAIWaypoint *wpt; wpt = createOnGround(ac, "Runway Exit", lastWptPos, airportElev, ac->getPerformance()->vTaxi()); - waypoints.push_back(wpt); + pushBackWaypoint(wpt); wpt = createOnGround(ac, "Airport Center", aAirport->geod(), airportElev, ac->getPerformance()->vTaxi()); - waypoints.push_back(wpt); + pushBackWaypoint(wpt); - 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); + FGParking* parkPos = aAirport->getDynamics()->getParking(gateId); + if (parkPos) { + wpt = createOnGround(ac, "ENDtaxi", parkPos->geod(), airportElev, + ac->getPerformance()->vTaxi()); + pushBackWaypoint(wpt); + } } bool FGAIFlightPlan::createLandingTaxi(FGAIAircraft * ac, FGAirport * apt, @@ -350,14 +368,12 @@ 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 = - SGGeod::fromDeg(waypoints.back()->longitude, - waypoints.back()->latitude); + SGGeod::fromDeg(waypoints.back()->getLongitude(), + waypoints.back()->getLatitude()); FGGroundNetwork *gn = apt->getDynamics()->getGroundNetwork(); // Find a route from runway end to parking/gate. @@ -367,7 +383,13 @@ bool FGAIFlightPlan::createLandingTaxi(FGAIAircraft * ac, FGAirport * apt, } intVec ids; - int runwayId = gn->findNearestNode(lastWptPos); + int runwayId = 0; + if (gn->getVersion() == 1) { + runwayId = gn->findNearestNodeOnRunway(lastWptPos); + } else { + runwayId = gn->findNearestNode(lastWptPos); + } + //cerr << "Using network node " << runwayId << endl; // A negative gateId indicates an overflow parking, use a // fallback mechanism for this. // Starting from gate 0 is a bit of a hack... @@ -396,11 +418,11 @@ bool FGAIFlightPlan::createLandingTaxi(FGAIAircraft * ac, FGAirport * apt, char buffer[10]; snprintf(buffer, 10, "%d", node); FGTaxiNode *tn = gn->findNode(node); - waypoint *wpt = - createOnGround(ac, buffer, tn->getGeod(), apt->getElevation(), + FGAIWaypoint *wpt = + createOnGround(ac, buffer, tn->geod(), apt->getElevation(), ac->getPerformance()->vTaxi()); - wpt->routeIndex = route; - waypoints.push_back(wpt); + wpt->setRouteIndex(route); + pushBackWaypoint(wpt); } return true; } @@ -441,7 +463,7 @@ bool FGAIFlightPlan::createTakeOff(FGAIAircraft * ac, bool firstFlight, (vRotateMetric * vRotateMetric - vTaxiMetric * vTaxiMetric) / (2 * accelMetric); //cerr << "Using " << accelDistance << " " << accelMetric << " " << vRotateMetric << endl; - waypoint *wpt; + FGAIWaypoint *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 @@ -453,24 +475,19 @@ bool FGAIFlightPlan::createTakeOff(FGAIAircraft * ac, bool firstFlight, apt->getDynamics()->getActiveRunway(rwyClass, 1, activeRunway, heading); } - rwy = apt->getRunwayByIdent(activeRunway); - - + FGRunway * rwy = apt->getRunwayByIdent(activeRunway); + assert( rwy != NULL ); 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); + SGGeod accelPoint = rwy->pointOnCenterline(105.0 + accelDistance); wpt = createOnGround(ac, "rotate", accelPoint, airportElev, vTakeoff); - waypoints.push_back(wpt); + pushBackWaypoint(wpt); accelDistance = ((vTakeoffMetric * 1.1) * (vTakeoffMetric * 1.1) - @@ -480,19 +497,19 @@ bool FGAIFlightPlan::createTakeOff(FGAIAircraft * ac, bool firstFlight, wpt = createOnGround(ac, "rotate", accelPoint, airportElev + 1000, vTakeoff * 1.1); - wpt->on_ground = false; - waypoints.push_back(wpt); + wpt->setOn_ground(false); + pushBackWaypoint(wpt); wpt = cloneWithPos(ac, wpt, "3000 ft", rwy->end()); - wpt->altitude = airportElev + 3000; - waypoints.push_back(wpt); + wpt->setAltitude(airportElev + 3000); + pushBackWaypoint(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); + wpt->setAltitude(airportElev + 5000); + pushBackWaypoint(wpt); return true; } @@ -504,7 +521,7 @@ bool FGAIFlightPlan::createClimb(FGAIAircraft * ac, bool firstFlight, FGAirport * apt, double speed, double alt, const string & fltType) { - waypoint *wpt; + FGAIWaypoint *wpt; // bool planLoaded = false; string fPLName; double vClimb = ac->getPerformance()->vClimb(); @@ -514,25 +531,27 @@ bool FGAIFlightPlan::createClimb(FGAIAircraft * ac, bool firstFlight, 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))); + pushBackWaypoint(clone(*(i))); //cerr << " Cloning waypoint " << endl; } } else { + FGRunway * rwy = apt->getRunwayByIdent(activeRunway); + assert( rwy != NULL ); + 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); + wpt = createInAir(ac, "10000ft climb", climb1, 10000, vClimb); + wpt->setGear_down(true); + wpt->setFlaps_down(true); + pushBackWaypoint(wpt); SGGeod climb2 = rwy->pointOnCenterline(20 * SG_NM_TO_METER); wpt = cloneWithPos(ac, wpt, "18000ft climb", climb2); - wpt->altitude = 18000; - waypoints.push_back(wpt); + wpt->setAltitude(18000); + pushBackWaypoint(wpt); } return true; } @@ -551,9 +570,10 @@ bool FGAIFlightPlan::createDescent(FGAIAircraft * ac, FGAirport * apt, double requiredDistance) { bool reposition = false; - waypoint *wpt; + FGAIWaypoint *wpt; double vDescent = ac->getPerformance()->vDescent(); double vApproach = ac->getPerformance()->vApproach(); + double vTouchdown = ac->getPerformance()->vTouchdown(); //Beginning of Descent @@ -561,9 +581,8 @@ bool FGAIFlightPlan::createDescent(FGAIAircraft * ac, FGAirport * apt, double heading = ac->getTrafficRef()->getCourse(); apt->getDynamics()->getActiveRunway(rwyClass, 2, activeRunway, heading); - rwy = apt->getRunwayByIdent(activeRunway); - - + FGRunway * rwy = apt->getRunwayByIdent(activeRunway); + assert( rwy != NULL ); // Create a slow descent path that ends 250 lateral to the runway. double initialTurnRadius = getTurnRadius(vDescent, true); @@ -602,7 +621,17 @@ bool FGAIFlightPlan::createDescent(FGAIAircraft * ac, FGAirport * apt, } - double dAlt = alt - (apt->getElevation() + 2000); + double dAlt = 0; // = alt - (apt->getElevation() + 2000); + FGTaxiNode * tn = 0; + if (apt->getDynamics()->getGroundNetwork()) { + int node = apt->getDynamics()->getGroundNetwork()->findNearestNode(refPoint); + tn = apt->getDynamics()->getGroundNetwork()->findNode(node); + } + if (tn) { + dAlt = alt - ((tn->getElevationFt(apt->getElevation())) + 2000); + } else { + dAlt = alt - (apt->getElevation() + 2000); + } double nPoints = 100; @@ -619,11 +648,11 @@ bool FGAIFlightPlan::createDescent(FGAIAircraft * ac, FGAirport * apt, //cerr << "Distance : " << distance << endl; //cerr << "Azimuth : " << azimuth << endl; //cerr << "Initial Lateral point: " << lateralOffset << endl; - double lat = refPoint.getLatitudeDeg(); - double lon = refPoint.getLongitudeDeg(); +// double lat = refPoint.getLatitudeDeg(); +// double lon = refPoint.getLongitudeDeg(); //cerr << "Reference point (" << lat << ", " << lon << ")." << endl; - lat = initialTarget.getLatitudeDeg(); - lon = initialTarget.getLongitudeDeg(); +// lat = initialTarget.getLatitudeDeg(); +// lon = initialTarget.getLongitudeDeg(); //cerr << "Initial Target point (" << lat << ", " << lon << ")." << endl; double ratio = initialTurnRadius / distance; @@ -692,8 +721,8 @@ bool FGAIFlightPlan::createDescent(FGAIAircraft * ac, FGAirport * apt, azimuth = SGGeodesy::courseDeg(origin, secondaryTarget); - lat = secondaryTarget.getLatitudeDeg(); - lon = secondaryTarget.getLongitudeDeg(); +// lat = secondaryTarget.getLatitudeDeg(); +// lon = secondaryTarget.getLongitudeDeg(); //cerr << "Secondary Target point (" << lat << ", " << lon << ")." << endl; //cerr << "Distance : " << distance << endl; //cerr << "Azimuth : " << azimuth << endl; @@ -717,8 +746,8 @@ bool FGAIFlightPlan::createDescent(FGAIAircraft * ac, FGAirport * apt, SGGeodesy::direct(origin, azimuth, newDistance, tertiaryTarget, dummyAz2); - lat = tertiaryTarget.getLatitudeDeg(); - lon = tertiaryTarget.getLongitudeDeg(); +// lat = tertiaryTarget.getLatitudeDeg(); +// lon = tertiaryTarget.getLongitudeDeg(); //cerr << "tertiary Target point (" << lat << ", " << lon << ")." << endl; @@ -729,9 +758,9 @@ bool FGAIFlightPlan::createDescent(FGAIAircraft * ac, FGAirport * apt, SGGeodesy::direct(origin, azimuth, currentDist, result, dummyAz2); snprintf(buffer, 16, "descent%03d", i); wpt = createInAir(ac, buffer, result, currentAltitude, vDescent); - wpt->crossat = currentAltitude; - wpt->trackLength = (newDistance / nPoints); - waypoints.push_back(wpt); + wpt->setCrossat(currentAltitude); + wpt->setTrackLength((newDistance / nPoints)); + pushBackWaypoint(wpt); //cerr << "Track Length : " << wpt->trackLength; //cerr << " Position : " << result.getLatitudeDeg() << " " << result.getLongitudeDeg() << " " << currentAltitude << endl; } @@ -764,42 +793,59 @@ bool FGAIFlightPlan::createDescent(FGAIAircraft * ac, FGAirport * apt, } //cerr << "creating circle between " << startval << " and " << endval << " using " << increment << endl; + //FGTaxiNode * tn = apt->getDynamics()->getGroundNetwork()->findNearestNode(initialTarget); + double currentAltitude = 0; + if (tn) { + currentAltitude = (tn->getElevationFt(apt->getElevation())) + 2000; + } else { + currentAltitude = apt->getElevation() + 2000; + } + double trackLength = (2 * M_PI * initialTurnRadius) / 360.0; for (int i = startval; i != endval; i += increment) { SGGeod result; - double currentAltitude = apt->getElevation() + 2000; + //double currentAltitude = apt->getElevation() + 2000; + SGGeodesy::direct(secondaryTarget, i, initialTurnRadius, result, dummyAz2); snprintf(buffer, 16, "turn%03d", i); wpt = createInAir(ac, buffer, result, currentAltitude, vDescent); - wpt->crossat = currentAltitude; - wpt->trackLength = trackLength; + wpt->setCrossat(currentAltitude); + wpt->setTrackLength(trackLength); //cerr << "Track Length : " << wpt->trackLength; - waypoints.push_back(wpt); + pushBackWaypoint(wpt); //cerr << " Position : " << result.getLatitudeDeg() << " " << result.getLongitudeDeg() << " " << currentAltitude << endl; } - // The approach leg should bring the aircraft to approximately 4-6 out, after which the landing phase should take over. + // The approach leg should bring the aircraft to approximately 4-6 nm out, after which the landing phase should take over. //cerr << "Phase 3: Approach" << endl; + double tgt_speed = vApproach; distanceOut -= distanceCovered; + double touchDownPoint = 0; //(rwy->lengthM() * 0.1); for (int i = 1; i < nPoints; i++) { SGGeod result; double currentDist = i * (distanceOut / nPoints); - double currentAltitude = - apt->getElevation() + 2000 - (i * 2000 / nPoints); + //double currentAltitude = + // apt->getElevation() + 2000 - (i * 2000 / (nPoints-1)); + double alt = currentAltitude - (i * 2000 / (nPoints - 1)); snprintf(buffer, 16, "final%03d", i); - result = rwy->pointOnCenterline((-distanceOut) + currentDist); - wpt = createInAir(ac, buffer, result, currentAltitude, vApproach); - wpt->crossat = currentAltitude; - wpt->trackLength = (distanceOut / nPoints); + result = rwy->pointOnCenterline((-distanceOut) + currentDist + touchDownPoint); + if (i == nPoints - 30) { + tgt_speed = vTouchdown; + } + wpt = createInAir(ac, buffer, result, alt, tgt_speed); + wpt->setCrossat(alt); + wpt->setTrackLength((distanceOut / nPoints)); // account for the extra distance due to an extended downwind leg if (i == 1) { - wpt->trackLength += distanceCovered; + wpt->setTrackLength(wpt->getTrackLength() + distanceCovered); } //cerr << "Track Length : " << wpt->trackLength; - waypoints.push_back(wpt); - //cerr << " Position : " << result.getLatitudeDeg() << " " << result.getLongitudeDeg() << " " << currentAltitude << endl; + pushBackWaypoint(wpt); + //if (apt->ident() == fgGetString("/sim/presets/airport-id")) { + // cerr << " Position : " << result.getLatitudeDeg() << " " << result.getLongitudeDeg() << " " << currentAltitude << " " << apt->getElevation() << " " << distanceOut << endl; + //} } //cerr << "Done" << endl; @@ -831,6 +877,8 @@ bool FGAIFlightPlan::createDescent(FGAIAircraft * ac, FGAirport * apt, //cerr << "Repositioning to waypoint " << (*waypoints.begin())->name << endl; ac->resetPositionFromFlightPlan(); } + waypoints[1]->setName( (waypoints[1]->getName() + string("legend"))); + waypoints.back()->setName(waypoints.back()->getName() + "LandingThreshold"); return true; } @@ -839,12 +887,18 @@ bool FGAIFlightPlan::createDescent(FGAIAircraft * ac, FGAirport * apt, * Create a flight path from the "permision to land" point (currently hardcoded at 5000 meters from the threshold) to the threshold, at a standard glide slope angle of 3 degrees. + Position : 50.0354 8.52592 384 364 11112 ******************************************************************/ bool FGAIFlightPlan::createLanding(FGAIAircraft * ac, FGAirport * apt, const string & fltType) { double vTouchdown = ac->getPerformance()->vTouchdown(); - //double vTaxi = ac->getPerformance()->vTaxi(); + double vTaxi = ac->getPerformance()->vTaxi(); + double decel = ac->getPerformance()->deceleration() * 1.4; + + double vTouchdownMetric = (vTouchdown * SG_NM_TO_METER) / 3600; + double vTaxiMetric = (vTaxi * SG_NM_TO_METER) / 3600; + double decelMetric = (decel * SG_NM_TO_METER) / 3600; //string rwyClass = getRunwayClassFromTrafficType(fltType); //double heading = ac->getTrafficRef()->getCourse(); @@ -852,33 +906,96 @@ bool FGAIFlightPlan::createLanding(FGAIAircraft * ac, FGAirport * apt, //rwy = apt->getRunwayByIdent(activeRunway); - waypoint *wpt; - double aptElev = apt->getElevation(); + FGAIWaypoint *wpt; + //double aptElev = apt->getElevation(); + double currElev = 0; + char buffer[12]; + FGRunway * rwy = apt->getRunwayByIdent(activeRunway); + assert( rwy != NULL ); + SGGeod refPoint = rwy->pointOnCenterline(0); + FGTaxiNode *tn = 0; + if (apt->getDynamics()->getGroundNetwork()) { + int node = apt->getDynamics()->getGroundNetwork()->findNearestNode(refPoint); + tn = apt->getDynamics()->getGroundNetwork()->findNode(node); + } + if (tn) { + currElev = tn->getElevationFt(apt->getElevation()); + } else { + currElev = 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); + + + /*double distanceOut = rwy->lengthM() * .1; + double nPoints = 20; + for (int i = 1; i < nPoints; i++) { + snprintf(buffer, 12, "flare%d", i); + double currentDist = i * (distanceOut / nPoints); + double currentAltitude = apt->getElevation() + 20 - (i * 20 / nPoints); + coord = rwy->pointOnCenterline((currentDist * (i / nPoints))); + wpt = createInAir(ac, buffer, coord, currentAltitude, (vTouchdown)); + }*/ + double rolloutDistance = + (vTouchdownMetric * vTouchdownMetric - vTaxiMetric * vTaxiMetric) / (2 * decelMetric); + //cerr << " touchdown speed = " << vTouchdown << ". Rollout distance " << rolloutDistance << endl; + int nPoints = 50; + for (int i = 1; i < nPoints; i++) { + snprintf(buffer, 12, "landing03%d", i); + + coord = rwy->pointOnCenterline((rolloutDistance * ((double) i / (double) nPoints))); + wpt = createOnGround(ac, buffer, coord, currElev, 2*vTaxi); + wpt->setCrossat(currElev); + pushBackWaypoint(wpt); + } + wpt->setSpeed(vTaxi); + double mindist = 1.1 * rolloutDistance; + double maxdist = rwy->lengthM(); + //cerr << "Finding nearest exit" << endl; + FGGroundNetwork *gn = apt->getDynamics()->getGroundNetwork(); + if (gn) { + double min = 0; + for (int i = ceil(mindist); i < floor(maxdist); i++) { + coord = rwy->pointOnCenterline(mindist); + int nodeId = 0; + if (gn->getVersion() > 0) { + nodeId = gn->findNearestNodeOnRunway(coord); + } else { + nodeId = gn->findNearestNode(coord); + } + if (tn) + tn = gn->findNode(nodeId); + if (!tn) + break; + + double dist = SGGeodesy::distanceM(coord, tn->geod()); + if (dist < (min + 0.75)) { + break; + } + min = dist; + } + if (tn) { + wpt = createOnGround(ac, buffer, tn->geod(), currElev, vTaxi); + pushBackWaypoint(wpt); + } } + //cerr << "Done. " << endl; /* //Runway Threshold wpt = createOnGround(ac, "Threshold", rwy->threshold(), aptElev, vTouchdown); wpt->crossat = apt->getElevation(); - waypoints.push_back(wpt); + pushBackWaypoint(wpt); // Roll-out wpt = createOnGround(ac, "Center", rwy->geod(), aptElev, vTaxi*2); - waypoints.push_back(wpt); + pushBackWaypoint(wpt); SGGeod rollOut = rwy->pointOnCenterline(rwy->lengthM() * 0.9); wpt = createOnGround(ac, "Roll Out", rollOut, aptElev, vTaxi); wpt->crossat = apt->getElevation(); - waypoints.push_back(wpt); + pushBackWaypoint(wpt); */ return true; } @@ -890,38 +1007,37 @@ bool FGAIFlightPlan::createLanding(FGAIAircraft * ac, FGAirport * apt, bool FGAIFlightPlan::createParking(FGAIAircraft * ac, FGAirport * apt, double radius) { - waypoint *wpt; + 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); - waypoints.push_back(wpt); + FGParking* parking = apt->getDynamics()->getParking(gateId); + if (!parking) { + wpt = createOnGround(ac, "END-Parking", apt->geod(), 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); - waypoints.push_back(wpt); - - wpt = - createOnGround(ac, "END", SGGeod::fromDeg(lon, lat), aptElev, + return true; + } + + double heading = SGMiscd::normalizePeriodic(0, 360, parking->getHeading() + 180.0); + double az; // unused + SGGeod pos; + + SGGeodesy::direct(parking->geod(), heading, 2.2 * parking->getRadius(), + pos, az); + + wpt = createOnGround(ac, "taxiStart", pos, aptElev, vTaxiReduced); + pushBackWaypoint(wpt); + + SGGeodesy::direct(parking->geod(), heading, 0.1 * parking->getRadius(), + pos, az); + wpt = createOnGround(ac, "taxiStart2", pos, aptElev, vTaxiReduced); + pushBackWaypoint(wpt); + + wpt = createOnGround(ac, "END-Parking", parking->geod(), aptElev, vTaxiReduced); - waypoints.push_back(wpt); + pushBackWaypoint(wpt); return true; }