diff --git a/src/AIModel/AIAircraft.cxx b/src/AIModel/AIAircraft.cxx index eb8469fde..2bf71b3b1 100644 --- a/src/AIModel/AIAircraft.cxx +++ b/src/AIModel/AIAircraft.cxx @@ -51,9 +51,6 @@ using std::string; static string tempReg; -class AI_OutOfSight{}; -class FP_Inactive{}; - FGAIAircraft::FGAIAircraft(FGAISchedule *ref) : FGAIBase(otAircraft) { trafficRef = ref; if (trafficRef) { @@ -148,16 +145,16 @@ void FGAIAircraft::setPerformance(const std::string& acclass) { void FGAIAircraft::Run(double dt) { FGAIAircraft::dt = dt; + + bool outOfSight = false, + flightplanActive = true; + updatePrimaryTargetValues(flightplanActive, outOfSight); // target hdg, alt, speed + if (outOfSight) { + return; + } - try { - updatePrimaryTargetValues(); // target hdg, alt, speed - } - catch (AI_OutOfSight) { - return; - } - catch (FP_Inactive) { - //return; - groundTargetSpeed = 0; + if (!flightplanActive) { + groundTargetSpeed = 0; } handleATCRequests(); // ATC also has a word to say @@ -739,7 +736,7 @@ void FGAIAircraft::controlSpeed(FGAIFlightPlan::waypoint* curr, FGAIFlightPlan:: /** * Update target values (heading, alt, speed) depending on flight plan or control properties */ -void FGAIAircraft::updatePrimaryTargetValues() { +void FGAIAircraft::updatePrimaryTargetValues(bool& flightplanActive, bool& aiOutOfSight) { if (fp) // AI object has a flightplan { //TODO make this a function of AIBase @@ -760,16 +757,16 @@ void FGAIAircraft::updatePrimaryTargetValues() { } if (trafficRef) { //cerr << trafficRef->getRegistration() << " Setting altitude to " << altitude_ft; - if (! aiTrafficVisible()) { + aiOutOfSight = !aiTrafficVisible(); + if (aiOutOfSight) { setDie(true); //cerr << trafficRef->getRegistration() << " is set to die " << endl; - throw AI_OutOfSight(); + aiOutOfSight = true; + return; } } timeElapsed = now - fp->getStartTime(); - if (! fp->isActive(now)) { - throw FP_Inactive(); - } + flightplanActive = fp->isActive(now); } else { // no flight plan, update target heading, speed, and altitude // from control properties. These default to the initial diff --git a/src/AIModel/AIAircraft.hxx b/src/AIModel/AIAircraft.hxx index 49639799a..6a53e5a2b 100644 --- a/src/AIModel/AIAircraft.hxx +++ b/src/AIModel/AIAircraft.hxx @@ -29,7 +29,6 @@ #include #include -using std::string; class PerformanceData; @@ -66,8 +65,8 @@ public: void doGroundAltitude(); bool loadNextLeg (); - void setAcType(const string& ac) { acType = ac; }; - void setCompany(const string& comp) { company = comp;}; + void setAcType(const std::string& ac) { acType = ac; }; + void setCompany(const std::string& comp) { company = comp;}; void announcePositionToController(); //TODO have to be public? void processATC(FGATCInstruction instruction); @@ -75,8 +74,8 @@ public: virtual const char* getTypeString(void) const { return "aircraft"; } - string GetTransponderCode() { return transponderCode; }; - void SetTransponderCode(string tc) { transponderCode = tc;}; + std::string GetTransponderCode() { return transponderCode; }; + void SetTransponderCode(const std::string& tc) { transponderCode = tc;}; // included as performance data needs them, who else? inline PerformanceData* getPerformance() { return _performance; }; @@ -88,7 +87,7 @@ public: inline double getVerticalSpeed() const { return vs; }; inline double altitudeAGL() const { return props->getFloatValue("position/altitude-agl-ft");}; inline double airspeed() const { return props->getFloatValue("velocities/airspeed-kt");}; - string atGate(); + std::string atGate(); protected: void Run(double dt); @@ -121,7 +120,9 @@ private: void controlHeading(FGAIFlightPlan::waypoint* curr); void controlSpeed(FGAIFlightPlan::waypoint* curr, FGAIFlightPlan::waypoint* next); - void updatePrimaryTargetValues(); + + void updatePrimaryTargetValues(bool& flightplanActive, bool& aiOutOfSight); + void updateSecondaryTargetValues(); void updatePosition(); void updateHeading(); @@ -134,9 +135,9 @@ private: double sign(double x); - string acType; - string company; - string transponderCode; + std::string acType; + std::string company; + std::string transponderCode; int spinCounter; double prevSpeed; diff --git a/src/Traffic/Schedule.cxx b/src/Traffic/Schedule.cxx index 309d9340b..517bb3c21 100644 --- a/src/Traffic/Schedule.cxx +++ b/src/Traffic/Schedule.cxx @@ -55,8 +55,6 @@ #include "SchedFlight.hxx" #include "TrafficMgr.hxx" -using std::sort; - /****************************************************************************** * the FGAISchedule class contains data members and code to maintain a * schedule of Flights for an articically controlled aircraft. @@ -67,8 +65,6 @@ FGAISchedule::FGAISchedule() AIManagerRef = 0; heavy = false; - lat = 0; - lon = 0; radius = 0; groundOffset = 0; distanceToUser = 0; @@ -110,8 +106,6 @@ FGAISchedule::FGAISchedule(string model, airline = arln; m_class = mclass; flightType = fltpe; - lat = 0; - lon = 0; radius = rad; groundOffset = grnd; distanceToUser = 0; @@ -134,8 +128,6 @@ FGAISchedule::FGAISchedule(const FGAISchedule &other) heavy = other.heavy; flightIdentifier = other.flightIdentifier; flights = other.flights; - lat = other.lat; - lon = other.lon; AIManagerRef = other.AIManagerRef; acType = other.acType; airline = other.airline; @@ -186,308 +178,232 @@ bool FGAISchedule::init() return true; } -bool FGAISchedule::update(time_t now) +bool FGAISchedule::update(time_t now, const SGVec3d& userCart) { - FGAirport *dep; - FGAirport *arr; - double angle; - - FGAIManager *aimgr; - string airport; - - double speed; - + if (!fgGetBool("/sim/traffic-manager/enabled")) + return true; + time_t totalTimeEnroute, elapsedTimeEnroute, - remainingTimeEnroute, deptime = 0; - double - userLatitude, - userLongitude; - - SGVec3d newPos(0, 0, 0); - - - if (fgGetBool("/sim/traffic-manager/enabled") == false) - return true; + remainingTimeEnroute, + deptime = 0; - aimgr = (FGAIManager *) globals-> get_subsystem("ai_model"); - // Out-of-work aircraft seeks employment. Willing to work irregular hours ... - //cerr << "About to find a flight " << endl; - if (flights.empty()) { - //execute this loop at least once. - SG_LOG(SG_GENERAL, SG_BULK, "Scheduling for : " << modelPath << " " << registration << " " << homePort); - FGScheduledFlight *flight = 0; - do { - flight = findAvailableFlight(currentDestination, flightIdentifier); - if (flight) { - currentDestination = flight->getArrivalAirport()->getId(); - 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->getCallSign() << ":" - << " " << flight->getDepartureAirport()->getId() << ":" - << " " << depT << ":" - << " \"" << flight->getArrivalAirport()->getId() << "\"" << ":" - << " " << arrT << ":"); - flights.push_back(flight); - } - } while ((currentDestination != homePort) && (flight != 0)); - SG_LOG(SG_GENERAL, SG_BULK, cerr << " Done " << endl); - } - //cerr << " Done " << endl; - // No flights available for this aircraft - if (flights.size() == 0) { + scheduleFlights(); + if (flights.empty()) { // No flights available for this aircraft return false; } + // 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. //sort(flights.begin(), flights.end(), compareScheduledFlights); - if (firstRun) { + + if (firstRun) { if (fgGetBool("/sim/traffic-manager/instantaneous-action") == true) { deptime = now + rand() % 300; // Wait up to 5 minutes until traffic starts moving to prevent too many aircraft // from cluttering the gate areas. - cerr << "Scheduling " << registration << " for instantaneous action flight " << endl; } firstRun = false; } + + FGScheduledFlight* flight = flights.front(); if (!deptime) - deptime = (*flights.begin())->getDepartureTime(); - FGScheduledFlightVecIterator i = flights.begin(); - SG_LOG (SG_GENERAL, SG_DEBUG,"Traffic Manager: Processing registration " << registration << " with callsign " << (*i)->getCallSign()); - if (AIManagerRef) - { - // Check if this aircraft has been released. - FGTrafficManager *tmgr = (FGTrafficManager *) globals->get_subsystem("Traffic Manager"); - if (tmgr->isReleased(AIManagerRef)) - AIManagerRef = 0; + deptime = flight->getDepartureTime(); + + if (AIManagerRef) { + // Check if this aircraft has been released. + FGTrafficManager *tmgr = (FGTrafficManager *) globals->get_subsystem("Traffic Manager"); + if (tmgr->isReleased(AIManagerRef)) { + AIManagerRef = NULL; + } else { + return true; // in visual range, let the AIManager handle it } - - if (!AIManagerRef) - { - userLatitude = fgGetDouble("/position/latitude-deg"); - userLongitude = fgGetDouble("/position/longitude-deg"); - - //cerr << "Estimated minimum distance to user: " << distanceToUser << endl; - // This flight entry is entirely in the past, do we need to - // push it forward in time to the next scheduled departure. - if (((*i)->getDepartureTime() < now) && ((*i)->getArrivalTime() < now)) - { - SG_LOG (SG_GENERAL, SG_DEBUG, "Traffic Manager: Flight is in the Past"); - //cerr << modelPath << " " << registration << ": Flights from the past belong to the past :-)" << endl; - //exit(1); - // 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. - (*i)->update(); - i = flights.erase(i); + } + + // 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"); + // 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; } - - // Departure time in the past and arrival time in the future. - // This flight is in progress, so we need to calculate it's - // approximate position and -if in range- create an AIAircraft - // object for it. - //if ((i->getDepartureTime() < now) && (i->getArrivalTime() > now)) + + FGAirport* dep = flight->getDepartureAirport(); + FGAirport* arr = flight->getArrivalAirport(); + if (!dep || !arr) { + return false; + } + + double speed = 450.0; + if (dep != arr) { + totalTimeEnroute = flight->getArrivalTime() - flight->getDepartureTime(); + if (flight->getDepartureTime() < now) { + elapsedTimeEnroute = now - flight->getDepartureTime(); + remainingTimeEnroute = totalTimeEnroute - elapsedTimeEnroute; + double x = elapsedTimeEnroute / (double) totalTimeEnroute; - // Part of this flight is in the future. - if ((*i)->getArrivalTime() > now) - { - - dep = (*i)->getDepartureAirport(); - arr = (*i)->getArrivalAirport (); - if (!(dep && arr)) - return false; - - if (dep != arr) { - SGVec3d a = SGVec3d::fromGeoc(SGGeoc::fromDegM(dep->getLongitude(), - dep->getLatitude(), 1)); - SGVec3d b = SGVec3d::fromGeoc(SGGeoc::fromDegM(arr->getLongitude(), - arr->getLatitude(), 1)); - SGVec3d _cross = cross(b, a); - - angle = sgACos(dot(a, b)); - - // Okay, at this point we have the angle between departure and - // arrival airport, in degrees. From here we can interpolate the - // position of the aircraft by calculating the ratio between - // total time enroute and elapsed time enroute. - - totalTimeEnroute = (*i)->getArrivalTime() - (*i)->getDepartureTime(); - if (now > (*i)->getDepartureTime()) - { - //err << "Lat = " << lat << ", lon = " << lon << endl; - //cerr << "Time diff: " << now-i->getDepartureTime() << endl; - elapsedTimeEnroute = now - (*i)->getDepartureTime(); - remainingTimeEnroute = (*i)->getArrivalTime() - now; - SG_LOG (SG_GENERAL, SG_DEBUG, "Traffic Manager: Flight is in progress."); - } - else - { - lat = dep->getLatitude(); - lon = dep->getLongitude(); - elapsedTimeEnroute = 0; - remainingTimeEnroute = totalTimeEnroute; - SG_LOG (SG_GENERAL, SG_DEBUG, "Traffic Manager: Flight is pending."); - } - angle *= ( (double) elapsedTimeEnroute/ (double) totalTimeEnroute); - //cout << "a = " << a[0] << " " << a[1] << " " << a[2] - // << "b = " << b[0] << " " << b[1] << " " << b[2] << endl; - sgdMat4 matrix; - sgdMakeRotMat4(matrix, angle, _cross.data()); - for(int j = 0; j < 3; j++) { - for (int k = 0; k<3; k++) { - newPos[j] += matrix[j][k]*a[k]; - } - } - } - SGGeod current; - if ((now > (*i)->getDepartureTime() && (dep != arr))) { - current = SGGeod::fromCart(newPos); - speed = SGGeodesy::distanceNm(current, arr->geod()) / - ((double) remainingTimeEnroute/3600.0); - } else { - current = dep->geod(); - speed = 450; - } - SGGeod user = SGGeod::fromDegM(userLongitude, userLatitude, (*i)->getCruiseAlt()); - - distanceToUser = SGGeodesy::distanceNm(current, user); + // current pos is based on great-circle course between departure/arrival, + // with percentage of distance travelled, based upon percentage of time + // enroute elapsed. + double course, az2, distanceM; + SGGeodesy::inverse(dep->geod(), arr->geod(), course, az2, distanceM); + double coveredDistance = distanceM * x; + + SGGeodesy::direct(dep->geod(), course, coveredDistance, position, az2); + + SG_LOG (SG_GENERAL, 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 " + << flight->getDepartureTime() - now << " seconds "); + } + } else { + // departure / arrival coincident + remainingTimeEnroute = totalTimeEnroute = 0.0; + elapsedTimeEnroute = 0; + position = dep->geod(); + } + + // cartesian calculations are more numerically stable over the (potentially) + // 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 - // 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_DEBUG, "Traffic manager: " << registration << " is scheduled for a flight from " + // If distance between user and simulated aircaft 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 " << dep->getId() << " to " << arr->getId() << ". Current distance to user: " << distanceToUser); - if (distanceToUser < TRAFFICTOAIDISTTOSTART) - { - string flightPlanName = dep->getId() + string("-") + arr->getId() + - string(".xml"); - SG_LOG (SG_GENERAL, SG_DEBUG, "Traffic manager: Creating AIModel"); - //int alt; - //if ((i->getDepartureTime() < now)) - //{ - // alt = i->getCruiseAlt() *100; - // } - //else - //{ - // alt = dep->_elevation+19; - // } - - // 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()) - { - FGAIAircraft *aircraft = new FGAIAircraft(this); - aircraft->setPerformance(m_class); //"jet_transport"; - aircraft->setCompany(airline); //i->getAirline(); - aircraft->setAcType(acType); //i->getAcType(); - aircraft->setPath(modelPath.c_str()); - //aircraft->setFlightPlan(flightPlanName); - aircraft->setLatitude(lat); - aircraft->setLongitude(lon); - aircraft->setAltitude((*i)->getCruiseAlt()*100); // convert from FL to feet - aircraft->setSpeed(speed); - aircraft->setBank(0); - - courseToDest = SGGeodesy::courseDeg(current, arr->geod()); - aircraft->SetFlightPlan(new FGAIFlightPlan(aircraft, flightPlanName, courseToDest, deptime, - dep, arr,true, radius, - (*i)->getCruiseAlt()*100, - lat, lon, speed, flightType, acType, - airline)); - aimgr->attach(aircraft); - - - AIManagerRef = aircraft->getID(); - //cerr << "Class: " << m_class << ". acType: " << acType << ". Airline: " << airline << ". Speed = " << speed << ". From " << dep->getId() << " to " << arr->getId() << ". Time Fraction = " << (remainingTimeEnroute/(double) totalTimeEnroute) << endl; - //cerr << "Latitude : " << lat << ". Longitude : " << lon << endl; - //cerr << "Dep : " << dep->getLatitude()<< ", "<< dep->getLongitude() << endl; - //cerr << "Arr : " << arr->getLatitude()<< ", "<< arr->getLongitude() << endl; - //cerr << "Time remaining = " << (remainingTimeEnroute/3600.0) << endl; - //cerr << "Total time = " << (totalTimeEnroute/3600.0) << endl; - //cerr << "Distance remaining = " << distanceToDest*SG_METER_TO_NM << endl; - } - else - { - SG_LOG(SG_INPUT, SG_WARN, "TrafficManager: Could not load model " << mp.str()); - } - } - return true; - } - - // Both departure and arrival time are in the future, so this - // the aircraft is parked at the departure airport. - // Currently this status is mostly ignored, but in future - // versions, code should go here that -if within user range- - // positions these aircraft at parking locations at the airport. - if (((*i)->getDepartureTime() > now) && ((*i)->getArrivalTime() > now)) - { - dep = (*i)->getDepartureAirport(); - return true; - } - } - //cerr << "Traffic schedule got to beyond last clause" << endl; - // EMH: prevent a warning, should this be 'true' instead? - // DT: YES. Originally, this code couldn't be reached, but - // when the "if(!(AIManagerManager))" clause is false we - // fall through right to the end. This is a valid flow. - // the actual value is pretty innocent, only it triggers - // warning in TrafficManager::update(). - // (which was added as a sanity check for myself in the first place. :-) - return true; + if (distanceToUser >= TRAFFICTOAIDISTTOSTART) { + return true; // out of visual range, for the moment. + } + + return createAIAircraft(flight, speed, deptime); } +bool FGAISchedule::createAIAircraft(FGScheduledFlight* flight, double speedKnots, time_t deptime) +{ + 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); + + // 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_INPUT, SG_WARN, "TrafficManager: Could not load model " << mp.str()); + return true; + } + + FGAIAircraft *aircraft = new FGAIAircraft(this); + aircraft->setPerformance(m_class); //"jet_transport"; + aircraft->setCompany(airline); //i->getAirline(); + aircraft->setAcType(acType); //i->getAcType(); + aircraft->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(speedKnots); + aircraft->setBank(0); + + courseToDest = SGGeodesy::courseDeg(position, arr->geod()); + aircraft->SetFlightPlan(new FGAIFlightPlan(aircraft, flightPlanName, courseToDest, deptime, + dep, arr, true, radius, + flight->getCruiseAlt()*100, + position.getLatitudeDeg(), + position.getLongitudeDeg(), + speedKnots, flightType, acType, + airline)); + + + FGAIManager* aimgr = (FGAIManager *) globals-> get_subsystem("ai_model"); + aimgr->attach(aircraft); + AIManagerRef = aircraft->getID(); + return true; +} + +void FGAISchedule::scheduleFlights() +{ + if (!flights.empty()) { + return; + } + + SG_LOG(SG_GENERAL, SG_BULK, "Scheduling for : " << modelPath << " " << registration << " " << homePort); + FGScheduledFlight *flight = NULL; + do { + flight = findAvailableFlight(currentDestination, flightIdentifier); + if (!flight) { + break; + } + + currentDestination = flight->getArrivalAirport()->getId(); + + 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->getCallSign() << ":" + << " " << flight->getDepartureAirport()->getId() << ":" + << " " << depT << ":" + << " \"" << flight->getArrivalAirport()->getId() << "\"" << ":" + << " " << arrT << ":"); + + flights.push_back(flight); + } while (currentDestination != homePort); + SG_LOG(SG_GENERAL, SG_BULK, " Done "); +} bool FGAISchedule::next() { - FGScheduledFlightVecIterator i = flights.begin(); - (*i)->release(); - //FIXME: remove first entry, - // load new flights until back at home airport - // Lock loaded flights - //sort(flights.begin(), flights.end(), compareScheduledFlights); - // until that time - i = flights.erase(i); - //cerr << "Next: scheduling for : " << modelPath << " " << registration << endl; - FGScheduledFlight *flight = findAvailableFlight(currentDestination, flightIdentifier); - if (flight) { - currentDestination = flight->getArrivalAirport()->getId(); - 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); - //cerr << " " << flight->getCallSign() << ":" - // << " " << flight->getDepartureAirport()->getId() << ":" - // << " " << depT << ":" - // << " \"" << flight->getArrivalAirport()->getId() << "\"" << ":" - // << " " << arrT << ":" << endl; - - flights.push_back(flight); - return true; - } else { - return false; + if (!flights.empty()) { + flights.front()->release(); + flights.erase(flights.begin()); } - //cerr << "FGAISchedule :: next needs updating" << endl; - //exit(1); + + FGScheduledFlight *flight = findAvailableFlight(currentDestination, flightIdentifier); + if (!flight) { + return false; + } + + currentDestination = flight->getArrivalAirport()->getId(); +/* + 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); + //cerr << " " << flight->getCallSign() << ":" + // << " " << flight->getDepartureAirport()->getId() << ":" + // << " " << depT << ":" + // << " \"" << flight->getArrivalAirport()->getId() << "\"" << ":" + // << " " << arrT << ":" << endl; +*/ + flights.push_back(flight); + return true; } FGScheduledFlight* FGAISchedule::findAvailableFlight (const string ¤tDestination, @@ -513,7 +429,7 @@ FGScheduledFlight* FGAISchedule::findAvailableFlight (const string ¤tDesti //sort(fltBegin, fltEnd, compareScheduledFlights); //cerr << counter++ << endl; } - sort(fltBegin, fltEnd, compareScheduledFlights); + std::sort(fltBegin, fltEnd, compareScheduledFlights); for (FGScheduledFlightVecIterator i = fltBegin; i != fltEnd; i++) { //bool valid = true; counter++; @@ -548,7 +464,7 @@ FGScheduledFlight* FGAISchedule::findAvailableFlight (const string ¤tDesti // is departure port valid? // is arrival port valid? //cerr << "Ack no flight found: " << endl; - return 0; + return NULL; } double FGAISchedule::getSpeed() diff --git a/src/Traffic/Schedule.hxx b/src/Traffic/Schedule.hxx index 4dd8d5f00..75661bceb 100644 --- a/src/Traffic/Schedule.hxx +++ b/src/Traffic/Schedule.hxx @@ -48,8 +48,7 @@ class FGAISchedule string currentDestination; bool heavy; FGScheduledFlightVec flights; - float lat; - float lon; + SGGeod position; double radius; double groundOffset; double distanceToUser; @@ -58,7 +57,14 @@ class FGAISchedule bool firstRun; double courseToDest; - + void scheduleFlights(); + + /** + * Transition this schedule from distant mode to AI mode; + * create the AIAircraft (and flight plan) and register with the AIManager + */ + bool createAIAircraft(FGScheduledFlight* flight, double speedKnots, time_t deptime); + public: FGAISchedule(); // constructor FGAISchedule(string model, @@ -79,7 +85,7 @@ class FGAISchedule ~FGAISchedule(); //destructor - bool update(time_t now); + bool update(time_t now, const SGVec3d& userCart); bool init(); double getSpeed (); diff --git a/src/Traffic/TrafficMgr.cxx b/src/Traffic/TrafficMgr.cxx index 899685e93..dc2444fba 100644 --- a/src/Traffic/TrafficMgr.cxx +++ b/src/Traffic/TrafficMgr.cxx @@ -142,11 +142,16 @@ void FGTrafficManager::update(double /*dt*/) if (scheduledAircraft.size() == 0) { return; } + + SGVec3d userCart = SGVec3d::fromGeod(SGGeod::fromDeg( + fgGetDouble("/position/longitude-deg"), + fgGetDouble("/position/latitude-deg"))); + if(currAircraft == scheduledAircraft.end()) { currAircraft = scheduledAircraft.begin(); } - if (!((*currAircraft)->update(now))) + if (!((*currAircraft)->update(now, userCart))) { // NOTE: With traffic manager II, this statement below is no longer true // after proper initialization, we shouldnt get here.