X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=src%2FTraffic%2FSchedule.cxx;h=a47dfd2ca3493c2485be2d0b1181736b07747e0d;hb=070dba29f9390806457206c2660f2daebd3d847c;hp=3d4db5cb7683517f85e257e5f7599b5148730e2a;hpb=7d547d128702a643c40b54809e2b4e1a38c4a16d;p=flightgear.git diff --git a/src/Traffic/Schedule.cxx b/src/Traffic/Schedule.cxx index 3d4db5cb7..a47dfd2ca 100644 --- a/src/Traffic/Schedule.cxx +++ b/src/Traffic/Schedule.cxx @@ -36,6 +36,7 @@ #include #include #include +#include #include #include @@ -47,56 +48,62 @@ #include #include #include -#include +#include #include
// That's pretty ugly, but I need fgFindAirportID #include "SchedFlight.hxx" #include "TrafficMgr.hxx" +using std::string; + /****************************************************************************** * the FGAISchedule class contains data members and code to maintain a * schedule of Flights for an artificially controlled aircraft. *****************************************************************************/ FGAISchedule::FGAISchedule() + : heavy(false), + radius(0), + groundOffset(0), + distanceToUser(0), + score(0), + runCount(0), + hits(0), + lastRun(0), + firstRun(false), + courseToDest(0), + initialized(false), + valid(false), + scheduleComplete(false) { - firstRun = true; - AIManagerRef = 0; - - heavy = false; - radius = 0; - groundOffset = 0; - distanceToUser = 0; - valid = true; - lastRun = 0; - //score = 0; } -/* -FGAISchedule::FGAISchedule(string mdl, - string liv, - string reg, - bool hvy, - string act, - string arln, - string mclass, - string fltpe, - double rad, - double grnd, - int scre, - FGScheduledFlightVec flt)*/ -FGAISchedule::FGAISchedule(string model, - string lvry, - string port, - string reg, - string flightId, + +FGAISchedule::FGAISchedule(const string& model, + const string& lvry, + const string& port, + const string& reg, + const string& flightId, bool hvy, - string act, - string arln, - string mclass, - string fltpe, + const string& act, + const string& arln, + const string& mclass, + const string& fltpe, double rad, double grnd) + : heavy(hvy), + radius(rad), + groundOffset(grnd), + distanceToUser(0), + score(0), + runCount(0), + hits(0), + lastRun(0), + firstRun(true), + courseToDest(0), + initialized(false), + valid(true), + scheduleComplete(false) { modelPath = model; livery = lvry; @@ -107,22 +114,10 @@ FGAISchedule::FGAISchedule(string model, airline = arln; m_class = mclass; flightType = fltpe; - radius = rad; - groundOffset = grnd; - distanceToUser = 0; - heavy = hvy; /*for (FGScheduledFlightVecIterator i = flt.begin(); i != flt.end(); i++) flights.push_back(new FGScheduledFlight((*(*i))));*/ - AIManagerRef = 0; - score = 0; - firstRun = true; - runCount = 0; - hits = 0; - lastRun = 0; - initialized = false; - valid = true; } FGAISchedule::FGAISchedule(const FGAISchedule &other) @@ -134,7 +129,7 @@ FGAISchedule::FGAISchedule(const FGAISchedule &other) heavy = other.heavy; flightIdentifier = other.flightIdentifier; flights = other.flights; - AIManagerRef = other.AIManagerRef; + aiAircraft = other.aiAircraft; acType = other.acType; airline = other.airline; m_class = other.m_class; @@ -149,8 +144,10 @@ FGAISchedule::FGAISchedule(const FGAISchedule &other) runCount = other.runCount; hits = other.hits; lastRun = other.lastRun; + courseToDest = other.courseToDest; initialized = other.initialized; valid = other.valid; + scheduleComplete = other.scheduleComplete; } @@ -158,12 +155,9 @@ FGAISchedule::FGAISchedule(const FGAISchedule &other) FGAISchedule::~FGAISchedule() { // remove related object from AI manager - if (AIManagerRef) + if (aiAircraft) { - FGAIManager* aimgr = (FGAIManager *) globals-> get_subsystem("ai-model"); - if (aimgr) - aimgr->destroyObject(AIManagerRef); - AIManagerRef = 0; + aiAircraft->setDie(true); } /* for (FGScheduledFlightVecIterator flt = flights.begin(); flt != flights.end(); flt++) @@ -199,22 +193,37 @@ bool FGAISchedule::init() return true; } +/** + * Returns true when processing is complete. + * Returns false when processing was aborted due to timeout, so + * more time required - and another call is requested (next sim iteration). + */ bool FGAISchedule::update(time_t now, const SGVec3d& userCart) -{ - time_t - totalTimeEnroute, - elapsedTimeEnroute, - //remainingTimeEnroute, - deptime = 0; +{ + + time_t totalTimeEnroute, + elapsedTimeEnroute, + //remainingTimeEnroute, + deptime = 0; + if (!valid) { - return false; + return true; // processing complete + } + + if (!scheduleComplete) { + scheduleComplete = scheduleFlights(now); + } + + if (!scheduleComplete) { + return false; // not ready yet, continue processing in next iteration } - scheduleFlights(now); + if (flights.empty()) { // No flights available for this aircraft valid = false; - return false; + return true; // processing complete } - + + // Sort all the scheduled flights according to scheduled departure time. // Because this is done at every update, we only need to check the status // of the first listed flight. @@ -231,14 +240,12 @@ bool FGAISchedule::update(time_t now, const SGVec3d& userCart) FGScheduledFlight* flight = flights.front(); if (!deptime) { deptime = flight->getDepartureTime(); - //cerr << "Settiing departure time " << deptime << endl; + //cerr << "Setting departure time " << deptime << endl; } - if (AIManagerRef) { - // Check if this aircraft has been released. - FGTrafficManager *tmgr = (FGTrafficManager *) globals->get_subsystem("traffic-manager"); - if (tmgr->isReleased(AIManagerRef)) { - AIManagerRef = 0; + if (aiAircraft) { + if (aiAircraft->getDie()) { + aiAircraft = NULL; } else { return true; // in visual range, let the AIManager handle it } @@ -247,19 +254,19 @@ bool FGAISchedule::update(time_t now, const SGVec3d& userCart) // This flight entry is entirely in the past, do we need to // push it forward in time to the next scheduled departure. if (flight->getArrivalTime() < now) { - SG_LOG (SG_GENERAL, SG_BULK, "Traffic Manager: Flight is in the Past"); + SG_LOG (SG_AI, SG_BULK, "Traffic Manager: Flight is in the Past"); // Don't just update: check whether we need to load a new leg. etc. // This update occurs for distant aircraft, so we can update the current leg // and detach it from the current list of aircraft. flight->update(); flights.erase(flights.begin()); // pop_front(), effectively - return true; + return true; // processing complete } FGAirport* dep = flight->getDepartureAirport(); FGAirport* arr = flight->getArrivalAirport(); if (!dep || !arr) { - return false; + return true; // processing complete } double speed = 450.0; @@ -279,14 +286,14 @@ bool FGAISchedule::update(time_t now, const SGVec3d& userCart) SGGeodesy::direct(dep->geod(), course, coveredDistance, position, az2); - SG_LOG (SG_GENERAL, SG_BULK, "Traffic Manager: Flight is in progress, %=" << x); + SG_LOG (SG_AI, SG_BULK, "Traffic Manager: Flight is in progress, %=" << x); speed = ((distanceM - coveredDistance) * SG_METER_TO_NM) / 3600.0; } else { // not departed yet //remainingTimeEnroute = totalTimeEnroute; elapsedTimeEnroute = 0; position = dep->geod(); - SG_LOG (SG_GENERAL, SG_BULK, "Traffic Manager: Flight is pending, departure in " + SG_LOG (SG_AI, SG_BULK, "Traffic Manager: Flight is pending, departure in " << flight->getDepartureTime() - now << " seconds "); } } else { @@ -300,29 +307,50 @@ bool FGAISchedule::update(time_t now, const SGVec3d& userCart) // large distances involved here: see bug #80 distanceToUser = dist(userCart, SGVec3d::fromGeod(position)) * SG_METER_TO_NM; - // If distance between user and simulated aircaft is less + + // If distance between user and simulated aircraft is less // then 500nm, create this flight. At jet speeds 500 nm is roughly // one hour flight time, so that would be a good approximate point // to start a more detailed simulation of this aircraft. - SG_LOG (SG_GENERAL, SG_BULK, "Traffic manager: " << registration << " is scheduled for a flight from " + SG_LOG (SG_AI, SG_BULK, "Traffic manager: " << registration << " is scheduled for a flight from " << dep->getId() << " to " << arr->getId() << ". Current distance to user: " << distanceToUser); if (distanceToUser >= TRAFFICTOAIDISTTOSTART) { return true; // out of visual range, for the moment. } - return createAIAircraft(flight, speed, deptime); + + if (!createAIAircraft(flight, speed, deptime)) { + valid = false; + } + + + return true; // processing complete } bool FGAISchedule::validModelPath(const std::string& modelPath) { - SGPath mp(globals->get_fg_root()); - SGPath mp_ai = mp; + return (resolveModelPath(modelPath) != SGPath()); +} - mp.append(modelPath); - mp_ai.append("AI"); - mp_ai.append(modelPath); +SGPath FGAISchedule::resolveModelPath(const std::string& modelPath) +{ + BOOST_FOREACH(SGPath aiPath, globals->get_data_paths("AI")) { + aiPath.append(modelPath); + if (aiPath.exists()) { + return aiPath; + } + } + + // check aircraft dirs + BOOST_FOREACH(std::string aircraftPath, globals->get_aircraft_paths()) { + SGPath mp(aircraftPath); + mp.append(modelPath); + if (mp.exists()) { + return mp; + } + } - return mp.exists() || mp_ai.exists(); + return SGPath(); } bool FGAISchedule::createAIAircraft(FGScheduledFlight* flight, double speedKnots, time_t deptime) @@ -330,35 +358,22 @@ bool FGAISchedule::createAIAircraft(FGScheduledFlight* flight, double speedKnots FGAirport* dep = flight->getDepartureAirport(); FGAirport* arr = flight->getArrivalAirport(); string flightPlanName = dep->getId() + "-" + arr->getId() + ".xml"; - SG_LOG(SG_GENERAL, SG_INFO, "Traffic manager: Creating AIModel from:" << flightPlanName); + SG_LOG(SG_AI, SG_DEBUG, "Traffic manager: Creating AIModel from:" << flightPlanName); - // Only allow traffic to be created when the model path (or the AI version of mp) exists - SGPath mp(globals->get_fg_root()); - SGPath mp_ai = mp; - - mp.append(modelPath); - mp_ai.append("AI"); - mp_ai.append(modelPath); - - if (!mp.exists() && !mp_ai.exists()) { - SG_LOG(SG_GENERAL, SG_WARN, "TrafficManager: Could not load model " << mp_ai.str()); - return true; - } - - FGAIAircraft *aircraft = new FGAIAircraft(this); - aircraft->setPerformance(acType, m_class); //"jet_transport"; - aircraft->setCompany(airline); //i->getAirline(); - aircraft->setAcType(acType); //i->getAcType(); - aircraft->setPath(modelPath.c_str()); + aiAircraft = new FGAIAircraft(this); + aiAircraft->setPerformance(acType, m_class); //"jet_transport"; + aiAircraft->setCompany(airline); //i->getAirline(); + aiAircraft->setAcType(acType); //i->getAcType(); + aiAircraft->setPath(modelPath.c_str()); //aircraft->setFlightPlan(flightPlanName); - aircraft->setLatitude(position.getLatitudeDeg()); - aircraft->setLongitude(position.getLongitudeDeg()); - aircraft->setAltitude(flight->getCruiseAlt()*100); // convert from FL to feet - aircraft->setSpeed(0); - aircraft->setBank(0); + aiAircraft->setLatitude(position.getLatitudeDeg()); + aiAircraft->setLongitude(position.getLongitudeDeg()); + aiAircraft->setAltitude(flight->getCruiseAlt()*100); // convert from FL to feet + aiAircraft->setSpeed(0); + aiAircraft->setBank(0); courseToDest = SGGeodesy::courseDeg(position, arr->geod()); - FGAIFlightPlan *fp = new FGAIFlightPlan(aircraft, flightPlanName, courseToDest, deptime, + FGAIFlightPlan *fp = new FGAIFlightPlan(aiAircraft, flightPlanName, courseToDest, deptime, dep, arr, true, radius, flight->getCruiseAlt()*100, position.getLatitudeDeg(), @@ -366,13 +381,12 @@ bool FGAISchedule::createAIAircraft(FGScheduledFlight* flight, double speedKnots speedKnots, flightType, acType, airline); if (fp->isValidPlan()) { - aircraft->SetFlightPlan(fp); + aiAircraft->SetFlightPlan(fp); FGAIManager* aimgr = (FGAIManager *) globals-> get_subsystem("ai-model"); - aimgr->attach(aircraft); - AIManagerRef = aircraft->getID(); + aimgr->attach(aiAircraft); return true; } else { - delete aircraft; + aiAircraft = NULL; delete fp; //hand back the flights that had already been scheduled while (!flights.empty()) { @@ -389,30 +403,32 @@ void FGAISchedule::setHeading() courseToDest = SGGeodesy::courseDeg((*flights.begin())->getDepartureAirport()->geod(), (*flights.begin())->getArrivalAirport()->geod()); } -void FGAISchedule::scheduleFlights(time_t now) +bool FGAISchedule::scheduleFlights(time_t now) { - if (!flights.empty()) { - return; - } //string startingPort; - string userPort = fgGetString("/sim/presets/airport-id"); - SG_LOG(SG_GENERAL, SG_BULK, "Scheduling Flights for : " << modelPath << " " << registration << " " << homePort); + const string& userPort = fgGetString("/sim/presets/airport-id"); + SG_LOG(SG_AI, SG_BULK, "Scheduling Flights for : " << modelPath << " " << registration << " " << homePort); FGScheduledFlight *flight = NULL; + SGTimeStamp start; + start.stamp(); + + bool first = true; + if (currentDestination.empty()) + flight = findAvailableFlight(userPort, flightIdentifier, now, (now+6400)); + do { - if (currentDestination.empty()) { - flight = findAvailableFlight(userPort, flightIdentifier, now, (now+6400)); - if (!flight) - flight = findAvailableFlight(currentDestination, flightIdentifier); - } else { + if ((!flight)||(!first)) { flight = findAvailableFlight(currentDestination, flightIdentifier); } if (!flight) { break; } + + first = false; currentDestination = flight->getArrivalAirport()->getId(); //cerr << "Current destination " << currentDestination << endl; if (!initialized) { - string departurePort = flight->getDepartureAirport()->getId(); + const string& departurePort = flight->getDepartureAirport()->getId(); if (userPort == departurePort) { lastRun = 1; hits++; @@ -423,23 +439,36 @@ void FGAISchedule::scheduleFlights(time_t now) initialized = true; } - time_t arr, dep; - dep = flight->getDepartureTime(); - arr = flight->getArrivalTime(); - string depT = asctime(gmtime(&dep)); - string arrT = asctime(gmtime(&arr)); - - depT = depT.substr(0,24); - arrT = arrT.substr(0,24); - SG_LOG(SG_GENERAL, SG_BULK, " Flight " << flight->getCallSign() << ":" - << " " << flight->getDepartureAirport()->getId() << ":" - << " " << depT << ":" - << " \"" << flight->getArrivalAirport()->getId() << "\"" << ":" - << " " << arrT << ":"); + if (sglog().would_log(SG_AI, SG_BULK)) + { + time_t arr, dep; + dep = flight->getDepartureTime(); + arr = flight->getArrivalTime(); + string depT = asctime(gmtime(&dep)); + string arrT = asctime(gmtime(&arr)); + depT = depT.substr(0,24); + arrT = arrT.substr(0,24); + SG_LOG(SG_AI, SG_BULK, " Flight " << flight->getCallSign() << ":" + << " " << flight->getDepartureAirport()->getId() << ":" + << " " << depT << ":" + << " \"" << flight->getArrivalAirport()->getId() << "\"" << ":" + << " " << arrT << ":"); + } flights.push_back(flight); - } while (currentDestination != homePort); - SG_LOG(SG_GENERAL, SG_BULK, " Done "); + + // continue processing until complete, or preempt after timeout + } while ((currentDestination != homePort)&& + (start.elapsedMSec()<3.0)); + + if (flight && (currentDestination != homePort)) + { + // processing preempted, need to continue in next iteration + return false; + } + + SG_LOG(SG_AI, SG_BULK, " Done "); + return true; } bool FGAISchedule::next() @@ -520,7 +549,7 @@ FGScheduledFlight* FGAISchedule::findAvailableFlight (const string ¤tDesti continue; } } - if (flights.size()) { + if (! flights.empty()) { time_t arrival = flights.back()->getArrivalTime(); int groundTime = groundTimeFromRadius(); if ((*i)->getDepartureTime() < (arrival+(groundTime)))