/****************************************************************************** * AIFlightPlanCreateCruise.cxx * Written by Durk Talsma, started February, 2006. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * 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. * * **************************************************************************/ #ifdef HAVE_CONFIG_H # include #endif #include #include #include #include #include #include #include #include #include "AIFlightPlan.hxx" #include "AIAircraft.hxx" #include "performancedata.hxx" using std::iostream; /* void FGAIFlightPlan::evaluateRoutePart(double deplat, double deplon, double arrlat, double arrlon) { // First do a prescan of all the waypoints that are within a reasonable distance of the // ideal route. intVec nodes; int tmpNode, prevNode; SGGeoc dep(SGGeoc::fromDegM(deplon, deplat, 100.0)); SGGeoc arr(SGGeoc::fromDegM(arrlon, arrlat, 100.0)); SGVec3d a = SGVec3d::fromGeoc(dep); SGVec3d nb = normalize(SGVec3d::fromGeoc(arr)); SGVec3d na = normalize(a); SGVec3d _cross = cross(nb, na); double angle = acos(dot(na, nb)); const double angleStep = 0.05 * SG_DEGREES_TO_RADIANS; tmpNode = 0; for (double ang = 0.0; ang < angle; ang += angleStep) { SGQuatd q = SGQuatd::fromAngleAxis(ang, _cross); SGGeod geod = SGGeod::fromCart(q.transform(a)); prevNode = tmpNode; tmpNode = globals->get_airwaynet()->findNearestNode(geod); FGNode* node = globals->get_airwaynet()->findNode(tmpNode); if ((tmpNode != prevNode) && (SGGeodesy::distanceM(geod, node->getPosition()) < 25000)) { nodes.push_back(tmpNode); } } intVecIterator i = nodes.begin(); intVecIterator j = nodes.end(); while (i != nodes.end()) { j = nodes.end(); while (j != i) { j--; FGAirRoute routePart = globals->get_airwaynet()->findShortestRoute(*i, *j); if (!(routePart.empty())) { airRoute.add(routePart); i = j; break; } } i++; } } */ /* void FGAIFlightPlan::createCruise(bool firstFlight, FGAirport *dep, FGAirport *arr, double latitude, double longitude, double speed, double alt) { bool useInitialWayPoint = true; bool useCurrentWayPoint = false; double heading; double lat, lon, az; double lat2, lon2, az2; double azimuth; waypoint *wpt; waypoint *init_waypoint; intVec ids; char buffer[32]; SGPath routefile = globals->get_fg_root(); init_waypoint = new waypoint; init_waypoint->name = "Initial waypoint"; init_waypoint->latitude = latitude; init_waypoint->longitude = longitude;; //wpt->altitude = apt->getElevation(); // should maybe be tn->elev too init_waypoint->altitude = alt; init_waypoint->speed = 450; //speed; init_waypoint->crossat = -10000; init_waypoint->gear_down = false; init_waypoint->flaps_down= false; init_waypoint->finished = false; init_waypoint->on_ground = false; waypoints.push_back(init_waypoint); routefile.append("Data/AI/FlightPlans"); snprintf(buffer, 32, "%s-%s.txt", dep->getId().c_str(), arr->getId().c_str()); routefile.append(buffer); cerr << "trying to read " << routefile.c_str()<< endl; //exit(1); if (routefile.exists()) { sg_gzifstream in( routefile.str() ); do { in >> route; } while (!(in.eof())); } else { //int runwayId = apt->getDynamics()->getGroundNetwork()->findNearestNode(lat2, lon2); //int startId = globals->get_airwaynet()->findNearestNode(dep->getLatitude(), dep->getLongitude()); //int endId = globals->get_airwaynet()->findNearestNode(arr->getLatitude(), arr->getLongitude()); //FGAirRoute route; evaluateRoutePart(dep->getLatitude(), dep->getLongitude(), arr->getLatitude(), arr->getLongitude()); //exit(1); } route.first(); int node; if (route.empty()) { // if no route could be found, create a direct gps route... cerr << "still no route found from " << dep->getName() << " to << " << arr->getName() <get_airwaynet()->findNode(node); //cerr << "Checking status of each waypoint: " << fn->getIdent(); SGWayPoint first(init_waypoint->longitude, init_waypoint->latitude, alt); SGWayPoint curr (fn->getLongitude(), fn->getLatitude(), alt); SGWayPoint arr (arr->getLongitude(), arr->getLatitude(), alt); double crse, crsDiff; double dist; first.CourseAndDistance(arr, &course, &distance); first.CourseAndDistance(curr, &crse, &dist); dist *= SG_METER_TO_NM; // We're only interested in the absolute value of crsDiff // wich should fall in the 0-180 deg range. crsDiff = fabs(crse-course); if (crsDiff > 180) crsDiff = 360-crsDiff; // These are the three conditions that we consider including // in our flight plan: // 1) current waypoint is less then 100 miles away OR // 2) curren waypoint is ahead of us, at any distance //cerr << " Distance : " << dist << " : Course diff " << crsDiff // << " crs to dest : " << course // << " crs to wpt : " << crse; if ((dist > 20.0) && (crsDiff > 90.0)) { //useWpt = false; // Once we start including waypoints, we have to continue, even though // one of the following way point would suffice. // so once is the useWpt flag is set to true, we cannot reset it to false. //cerr << " discarding " << endl; // << ": Course difference = " << crsDiff // << "Course = " << course // << "crse = " << crse << endl; } else { //i = ids.end()-1; //cerr << " accepting " << endl; //ids.pop_back(); wpt = new waypoint; wpt->name = "Airway"; // fixme: should be the name of the waypoint wpt->latitude = fn->getLatitude(); wpt->longitude = fn->getLongitude(); //wpt->altitude = apt->getElevation(); // should maybe be tn->elev too wpt->altitude = alt; wpt->speed = 450; //speed; wpt->crossat = -10000; wpt->gear_down = false; wpt->flaps_down= false; wpt->finished = false; wpt->on_ground = false; waypoints.push_back(wpt); } if (!(routefile.exists())) { route.first(); fstream outf( routefile.c_str(), fstream::out ); while (route.next(&node)) outf << node << endl; } } } arr->getDynamics()->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); } //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); } */ /******************************************************************* * CreateCruise * initialize the Aircraft at the parking location * * Note that this is the original version that does not * do any dynamic route computation. ******************************************************************/ void FGAIFlightPlan::createCruise(FGAIAircraft *ac, bool firstFlight, FGAirport *dep, FGAirport *arr, double latitude, double longitude, double speed, double alt, const string& fltType) { double vCruise = ac->getPerformance()->vCruise(); waypoint *wpt; wpt = createInAir(ac, "Cruise", SGGeod::fromDeg(longitude, latitude), alt, vCruise); waypoints.push_back(wpt); string rwyClass = getRunwayClassFromTrafficType(fltType); double heading = ac->getTrafficRef()->getCourse(); arr->getDynamics()->getActiveRunway(rwyClass, 2, activeRunway, heading); rwy = arr->getRunwayByIdent(activeRunway); // begin descent 110km out SGGeod beginDescentPoint = rwy->pointOnCenterline(0); SGGeod secondaryDescentPoint = rwy->pointOnCenterline(-10000); wpt = createInAir(ac, "BOD", beginDescentPoint, alt, vCruise); waypoints.push_back(wpt); wpt = createInAir(ac, "BOD2", secondaryDescentPoint, alt, vCruise); waypoints.push_back(wpt); }