From b090d3dabce3ad1261fb4b514cb71ed0c8a4d29b Mon Sep 17 00:00:00 2001 From: Durk Talsma Date: Mon, 30 Aug 2010 21:13:16 +0200 Subject: [PATCH] Enable the collection of AI aircraft position statistics. This will allow for a dramatic speedup of the establishment of AI traffic after program initialization. --- src/Traffic/Schedule.cxx | 25 ++++++++--- src/Traffic/Schedule.hxx | 14 ++++++- src/Traffic/TrafficMgr.cxx | 86 ++++++++++++++++++++++++++++++++++++-- src/Traffic/TrafficMgr.hxx | 16 +++++++ 4 files changed, 130 insertions(+), 11 deletions(-) diff --git a/src/Traffic/Schedule.cxx b/src/Traffic/Schedule.cxx index 65e8a2403..8b193550b 100644 --- a/src/Traffic/Schedule.cxx +++ b/src/Traffic/Schedule.cxx @@ -115,8 +115,11 @@ FGAISchedule::FGAISchedule(string model, i++) flights.push_back(new FGScheduledFlight((*(*i))));*/ AIManagerRef = 0; - //score = scre; + score = 0; firstRun = true; + runCount = 0; + hits = 0; + initialized = false; } FGAISchedule::FGAISchedule(const FGAISchedule &other) @@ -136,13 +139,17 @@ FGAISchedule::FGAISchedule(const FGAISchedule &other) radius = other.radius; groundOffset = other.groundOffset; flightType = other.flightType; - //score = other.score; + score = other.score; distanceToUser = other.distanceToUser; currentDestination = other.currentDestination; firstRun = other.firstRun; + runCount = other.runCount; + hits = other.hits; + initialized = other.initialized; } + FGAISchedule::~FGAISchedule() { /* for (FGScheduledFlightVecIterator flt = flights.begin(); flt != flights.end(); flt++) @@ -355,6 +362,14 @@ void FGAISchedule::scheduleFlights() } currentDestination = flight->getArrivalAirport()->getId(); + if (!initialized) { + string departurePort = flight->getDepartureAirport()->getId(); + if (fgGetString("/sim/presets/airport-id") == departurePort) { + hits++; + } + runCount++; + initialized = true; + } time_t arr, dep; dep = flight->getDepartureTime(); @@ -481,12 +496,12 @@ double FGAISchedule::getSpeed() SG_CLAMP_RANGE(speed, 300.0, 500.0); return speed; } -/* + bool compareSchedules(FGAISchedule*a, FGAISchedule*b) { - //return (*a) < (*b); + return (*a) < (*b); } -*/ + // void FGAISchedule::setClosestDistanceToUser() // { diff --git a/src/Traffic/Schedule.hxx b/src/Traffic/Schedule.hxx index 75661bceb..bfda8c0fe 100644 --- a/src/Traffic/Schedule.hxx +++ b/src/Traffic/Schedule.hxx @@ -53,9 +53,12 @@ class FGAISchedule double groundOffset; double distanceToUser; int AIManagerRef; - //int score; + double score; + unsigned int runCount; + unsigned int hits; bool firstRun; double courseToDest; + bool initialized; void scheduleFlights(); @@ -107,10 +110,17 @@ class FGAISchedule const string& getFlightRules () { return (*flights.begin())->getFlightRules (); }; bool getHeavy () { return heavy; }; double getCourse () { return courseToDest; }; + unsigned int getRunCount () { return runCount; }; + unsigned int getHits () { return hits; }; + + void setrunCount(unsigned int count) { runCount = count; }; + void setHits (unsigned int count) { hits = count; }; + void setScore () { score = runCount ? ((double) hits / (double) runCount) : 0; }; + double getScore () { return score; }; FGScheduledFlight*findAvailableFlight (const string ¤tDestination, const string &req); // used to sort in decending order of score: I've probably found a better way to // decending order sorting, but still need to test that. - //bool operator< (const FGAISchedule &other) const { return (score > other.score); }; + bool operator< (const FGAISchedule &other) const { return (score > other.score); }; //void * getAiRef () { return AIManagerRef; }; //FGAISchedule* getAddress () { return this;}; diff --git a/src/Traffic/TrafficMgr.cxx b/src/Traffic/TrafficMgr.cxx index 7c13f0db6..c570c9ebd 100644 --- a/src/Traffic/TrafficMgr.cxx +++ b/src/Traffic/TrafficMgr.cxx @@ -85,10 +85,39 @@ FGTrafficManager::FGTrafficManager() FGTrafficManager:: ~FGTrafficManager() { - for (ScheduleVectorIterator sched = scheduledAircraft.begin(); sched != scheduledAircraft.end(); sched++) - { + // Save the heuristics data + bool saveData = false; + ofstream cachefile; + if (fgGetBool("/sim/traffic-manager/heuristics")) { + SGPath cacheData(fgGetString("/sim/fg-home")); + cacheData.append("ai"); + string airport = fgGetString("/sim/presets/airport-id"); + + if ((airport) != "") { + char buffer[128]; + ::snprintf(buffer, 128, "%c/%c/%c/", + airport[0], airport[1], airport[2]); + cacheData.append(buffer); + if (!cacheData.exists()) { + cacheData.create_dir(0777); + } + cacheData.append(airport + "-cache.txt"); + //cerr << "Saving AI traffic heuristics" << endl; + saveData = true; + cachefile.open(cacheData.str().c_str()); + } + } + for (ScheduleVectorIterator sched = scheduledAircraft.begin(); sched != scheduledAircraft.end(); sched++) { + if (saveData) { + cachefile << (*sched)->getRegistration() << " " + << (*sched)-> getRunCount() << " " + << (*sched)->getHits() << endl; + } delete (*sched); } + if (saveData) { + cachefile.close(); + } scheduledAircraft.clear(); flights.clear(); } @@ -99,9 +128,11 @@ void FGTrafficManager::init() ulDir* d, *d2; ulDirEnt* dent, *dent2; SGPath aircraftDir = globals->get_fg_root(); - SGPath path = aircraftDir; + heuristicsVector heuristics; + HeuristicMap heurMap; + aircraftDir.append("AI/Traffic"); if ((d = ulOpenDir(aircraftDir.c_str())) != NULL) { @@ -130,7 +161,53 @@ void FGTrafficManager::init() } ulCloseDir(d); } - + if (fgGetBool("/sim/traffic-manager/heuristics")) { + //cerr << "Processing Heuristics" << endl; + // Load the heuristics data + SGPath cacheData(fgGetString("/sim/fg-home")); + cacheData.append("ai"); + string airport = fgGetString("/sim/presets/airport-id"); + if ((airport) != "") { + char buffer[128]; + ::snprintf(buffer, 128, "%c/%c/%c/", + airport[0], airport[1], airport[2]); + cacheData.append(buffer); + cacheData.append(airport + "-cache.txt"); + if (cacheData.exists()) { + ifstream data(cacheData.c_str()); + while (1) { + Heuristic *h = new Heuristic; + data >> h->registration >> h->runCount >> h->hits; + if (data.eof()) + break; + heurMap[h->registration] = h; + heuristics.push_back(h); + } + } + } + for (currAircraft = scheduledAircraft.begin(); + currAircraft != scheduledAircraft.end(); + currAircraft++) { + string registration = (*currAircraft)->getRegistration(); + HeuristicMapIterator itr = heurMap.find(registration); + //cerr << "Processing heuristics for" << (*currAircraft)->getRegistration() << endl; + if (itr == heurMap.end()) { + //cerr << "No heuristics found for " << registration << endl; + } else { + (*currAircraft)->setrunCount(itr->second->runCount); + (*currAircraft)->setHits (itr->second->hits); + (*currAircraft)->setScore(); + //cerr <<"Runcount " << itr->second->runCount << ".Hits " << itr->second->hits << endl; + } + } + //cerr << "Done" << endl; + for (heuristicsVectorIterator hvi = heuristics.begin(); + hvi != heuristics.end(); + hvi++) { + delete (*hvi); + } + sort (scheduledAircraft.begin(), scheduledAircraft.end(), compareSchedules); + } currAircraft = scheduledAircraft.begin(); currAircraftClosest = scheduledAircraft.begin(); } @@ -153,6 +230,7 @@ void FGTrafficManager::update(double /*dt*/) { currAircraft = scheduledAircraft.begin(); } + //cerr << "Processing << " << (*currAircraft)->getRegistration() << " with score " << (*currAircraft)->getScore() << endl; if (!((*currAircraft)->update(now, userCart))) { // NOTE: With traffic manager II, this statement below is no longer true diff --git a/src/Traffic/TrafficMgr.hxx b/src/Traffic/TrafficMgr.hxx index c1a4465a8..6c72ce95c 100644 --- a/src/Traffic/TrafficMgr.hxx +++ b/src/Traffic/TrafficMgr.hxx @@ -57,6 +57,22 @@ typedef vector IdList; typedef vector::iterator IdListIterator; +class Heuristic +{ +public: + string registration; + unsigned int runCount; + unsigned int hits; +}; + +typedef vector heuristicsVector; +typedef vector::iterator heuristicsVectorIterator; + +typedef std::map < std::string, Heuristic *> HeuristicMap; +typedef HeuristicMap::iterator HeuristicMapIterator; + + + class FGTrafficManager : public SGSubsystem, public XMLVisitor {