]> git.mxchange.org Git - flightgear.git/blobdiff - src/Traffic/Schedule.cxx
NavDisplay: fix update lag when switching range or centre.
[flightgear.git] / src / Traffic / Schedule.cxx
index 3b990e377d3364213c27d6269af5ee5e3a2f28a9..789631bd5cf68a73a7e891e844588ca8ebb2740b 100644 (file)
@@ -68,6 +68,8 @@ FGAISchedule::FGAISchedule()
   radius = 0;
   groundOffset = 0;
   distanceToUser = 0;
+  valid = true;
+  lastRun = 0;
   //score = 0;
 }
 
@@ -115,8 +117,13 @@ FGAISchedule::FGAISchedule(string model,
        i++)
     flights.push_back(new FGScheduledFlight((*(*i))));*/
   AIManagerRef     = 0;
-  //score    = scre;
+  score    =         0;
   firstRun         = true;
+  runCount         = 0;
+  hits             = 0;
+  lastRun          = 0;
+  initialized      = false;
+  valid            = true;
 }
 
 FGAISchedule::FGAISchedule(const FGAISchedule &other)
@@ -136,13 +143,19 @@ 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;
+  lastRun            = other.lastRun;
+  initialized        = other.initialized;
+  valid              = other.valid;
 }
 
 
+
 FGAISchedule::~FGAISchedule()
 {
 /*  for (FGScheduledFlightVecIterator flt = flights.begin(); flt != flights.end(); flt++)
@@ -180,17 +193,17 @@ bool FGAISchedule::init()
 
 bool FGAISchedule::update(time_t now, const SGVec3d& userCart)
 { 
-  if (!fgGetBool("/sim/traffic-manager/enabled"))
-    return true;
-  
   time_t 
     totalTimeEnroute, 
     elapsedTimeEnroute,
     remainingTimeEnroute, 
     deptime = 0;
-  
-  scheduleFlights();
+  if (!valid) {
+    return false;
+  }
+  scheduleFlights(now);
   if (flights.empty()) { // No flights available for this aircraft
+      valid = false;
       return false;
   }
   
@@ -207,7 +220,7 @@ bool FGAISchedule::update(time_t now, const SGVec3d& userCart)
      firstRun = false;
   }
   
-  FGScheduledFlight* flight = flights.front();
+    FGScheduledFlight* flight = flights.front();
   if (!deptime) {
     deptime = flight->getDepartureTime();
     //cerr << "Settiing departure time " << deptime << endl;
@@ -215,9 +228,9 @@ bool FGAISchedule::update(time_t now, const SGVec3d& userCart)
     
   if (AIManagerRef) {
     // Check if this aircraft has been released. 
-    FGTrafficManager *tmgr = (FGTrafficManager *) globals->get_subsystem("Traffic Manager");
+    FGTrafficManager *tmgr = (FGTrafficManager *) globals->get_subsystem("traffic-manager");
     if (tmgr->isReleased(AIManagerRef)) {
-      AIManagerRef = NULL;
+      AIManagerRef = 0;
     } else {
       return true; // in visual range, let the AIManager handle it
     }
@@ -289,7 +302,6 @@ bool FGAISchedule::update(time_t now, const SGVec3d& userCart)
   if (distanceToUser >= TRAFFICTOAIDISTTOSTART) {
     return true; // out of visual range, for the moment.
   }
-  
   return createAIAircraft(flight, speed, deptime);
 }
 
@@ -309,7 +321,7 @@ bool FGAISchedule::createAIAircraft(FGScheduledFlight* flight, double speedKnots
   mp_ai.append(modelPath);
 
   if (!mp.exists() && !mp_ai.exists()) {
-    SG_LOG(SG_INPUT, SG_WARN, "TrafficManager: Could not load model " << mp.str());
+    SG_LOG(SG_GENERAL, SG_WARN, "TrafficManager: Could not load model " << mp.str());
     return true;
   }
 
@@ -322,40 +334,74 @@ bool FGAISchedule::createAIAircraft(FGScheduledFlight* flight, double speedKnots
   aircraft->setLatitude(position.getLatitudeDeg());
   aircraft->setLongitude(position.getLongitudeDeg());
   aircraft->setAltitude(flight->getCruiseAlt()*100); // convert from FL to feet
-  aircraft->setSpeed(speedKnots);
+  aircraft->setSpeed(0);
   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;
+    FGAIFlightPlan *fp = new FGAIFlightPlan(aircraft, flightPlanName, courseToDest, deptime, 
+                                            dep, arr, true, radius, 
+                                            flight->getCruiseAlt()*100, 
+                                            position.getLatitudeDeg(), 
+                                            position.getLongitudeDeg(), 
+                                            speedKnots, flightType, acType, 
+                                            airline);
+  if (fp->isValidPlan()) {
+        aircraft->SetFlightPlan(fp);
+        FGAIManager* aimgr = (FGAIManager *) globals-> get_subsystem("ai-model");
+        aimgr->attach(aircraft);
+        AIManagerRef = aircraft->getID();
+        return true;
+  } else {
+        delete aircraft;
+        delete fp;
+        //hand back the flights that had already been scheduled
+        while (!flights.empty()) {
+            flights.front()->release();
+            flights.erase(flights.begin());
+        }
+        return false;
+  }
 }
 
-void FGAISchedule::scheduleFlights()
+// Create an initial heading for user controlled aircraft.
+void FGAISchedule::setHeading()  
+{ 
+    courseToDest = SGGeodesy::courseDeg((*flights.begin())->getDepartureAirport()->geod(), (*flights.begin())->getArrivalAirport()->geod());
+}
+
+void FGAISchedule::scheduleFlights(time_t now)
 {
   if (!flights.empty()) {
     return;
   }
-  
-  SG_LOG(SG_GENERAL, SG_BULK, "Scheduling for : " << modelPath << " " <<  registration << " " << homePort);
+  //string startingPort;
+  string userPort = fgGetString("/sim/presets/airport-id");
+  SG_LOG(SG_GENERAL, SG_BULK, "Scheduling Flights for : " << modelPath << " " <<  registration << " " << homePort);
   FGScheduledFlight *flight = NULL;
   do {
-    flight = findAvailableFlight(currentDestination, flightIdentifier);
+    if (currentDestination.empty()) {
+        flight = findAvailableFlight(userPort, flightIdentifier, now, (now+6400));
+        if (!flight)
+            flight = findAvailableFlight(currentDestination, flightIdentifier);
+    } else {
+        flight = findAvailableFlight(currentDestination, flightIdentifier);
+    }
     if (!flight) {
       break;
     }
-    
     currentDestination = flight->getArrivalAirport()->getId();
+    //cerr << "Current destination " <<  currentDestination << endl;
+    if (!initialized) {
+        string departurePort = flight->getDepartureAirport()->getId();
+        if (userPort == departurePort) {
+            lastRun = 1;
+            hits++;
+        } else {
+            lastRun = 0;
+        }
+        //runCount++;
+        initialized = true;
+    }
   
     time_t arr, dep;
     dep = flight->getDepartureTime();
@@ -365,11 +411,11 @@ void FGAISchedule::scheduleFlights()
 
     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 << ":");
+    SG_LOG(SG_GENERAL, SG_BULK, "  Flight " << flight->getCallSign() << ":" 
+                             << "  "        << flight->getDepartureAirport()->getId() << ":"
+                             << "  "        << depT << ":"
+                             << " \""       << flight->getArrivalAirport()->getId() << "\"" << ":"
+                             << "  "        << arrT << ":");
   
     flights.push_back(flight);
   } while (currentDestination != homePort);
@@ -409,11 +455,12 @@ bool FGAISchedule::next()
 }
 
 FGScheduledFlight* FGAISchedule::findAvailableFlight (const string &currentDestination,
-                                                      const string &req)
+                                                      const string &req,
+                                                     time_t min, time_t max)
 {
     time_t now = time(NULL) + fgGetLong("/sim/time/warp");
 
-    FGTrafficManager *tmgr = (FGTrafficManager *) globals->get_subsystem("Traffic Manager");
+    FGTrafficManager *tmgr = (FGTrafficManager *) globals->get_subsystem("traffic-manager");
     FGScheduledFlightVecIterator fltBegin, fltEnd;
     fltBegin = tmgr->getFirstFlight(req);
     fltEnd   = tmgr->getLastFlight(req);
@@ -453,7 +500,18 @@ FGScheduledFlight* FGAISchedule::findAvailableFlight (const string &currentDesti
                    continue;
               }
           }
-          //TODO: check time
+          if (flights.size()) {
+            time_t arrival = flights.back()->getArrivalTime();
+            int groundTime = groundTimeFromRadius();
+            if ((*i)->getDepartureTime() < (arrival+(groundTime)))
+                continue;
+          }
+          if (min != 0) {
+              time_t dep = (*i)->getDepartureTime();
+              if ((dep < min) || (dep > max))
+                  continue;
+          }
+
           // So, if we actually get here, we have a winner
           //cerr << "found flight: " << req << " : " << currentDestination << " : " <<       
           //         (*i)->getArrivalAirport()->getId() << endl;
@@ -469,6 +527,23 @@ FGScheduledFlight* FGAISchedule::findAvailableFlight (const string &currentDesti
      return NULL;
 }
 
+int FGAISchedule::groundTimeFromRadius()
+{
+    if (radius < 10) 
+        return 15 * 60;
+    else if (radius < 15)
+        return 20 * 60;
+    else if (radius < 20)
+        return 30 * 60;
+    else if (radius < 25)
+        return 50 * 60;
+    else if (radius < 30)
+        return 90 * 60;
+    else 
+        return 120 * 60;
+}
+
+
 double FGAISchedule::getSpeed()
 {
   FGScheduledFlightVecIterator i = flights.begin();
@@ -482,55 +557,31 @@ double FGAISchedule::getSpeed()
   SG_CLAMP_RANGE(speed, 300.0, 500.0);
   return speed;
 }
-/*
+
+void FGAISchedule::setScore   () 
+{ 
+    if (runCount) {
+        score = ((double) hits / (double) runCount);
+    } else {
+        if (homePort == fgGetString("/sim/presets/airport-id")) {
+            score = 0.1;
+        } else {
+            score = 0.0;
+        }
+    }
+    runCount++;
+}
+
 bool compareSchedules(FGAISchedule*a, FGAISchedule*b)
 { 
-  //return (*a) < (*b); 
+  return (*a) < (*b); 
 } 
-*/
-
-// void FGAISchedule::setClosestDistanceToUser()
-// {
-  
-  
-//   double course;
-//   double dist;
-
-//   Point3D temp;
-//   time_t 
-//     totalTimeEnroute, 
-//     elapsedTimeEnroute;
-//   double userLatitude  = fgGetDouble("/position/latitude-deg");
-//   double userLongitude = fgGetDouble("/position/longitude-deg");
 
-//   FGAirport *dep;
-  
-// #if defined( __CYGWIN__) || defined( __MINGW32__)
-//   #define HUGE HUGE_VAL
-// #endif
-//   distanceToUser = HUGE;
-//   FGScheduledFlightVecIterator i = flights.begin();
-//   while (i != flights.end())
-//     {
-//       dep = i->getDepartureAirport();
-//       //if (!(dep))
-//       //return HUGE;
-      
-//       SGWayPoint user (   userLongitude,
-//                       userLatitude,
-//                       i->getCruiseAlt());
-//       SGWayPoint current (dep->getLongitude(),
-//                       dep->getLatitude(),
-//                       0);
-//       user.CourseAndDistance(current, &course, &dist);
-//       if (dist < distanceToUser)
-//     {
-//       distanceToUser = dist;
-//       //cerr << "Found closest distance to user for " << registration << " to be " << distanceToUser << " at airport " << dep->getId() << endl;
-//     }
-//       i++;
-//     }
-//   //return distToUser;
-// }
+bool FGAISchedule::operator< (const FGAISchedule &other) const
+{ 
+    //cerr << "Sorting " << registration << " and "  << other.registration << endl;
+    double currentScore = score       * (1.5 - lastRun);
+    double otherScore   = other.score * (1.5 - other.lastRun);
+    return currentScore > otherScore;
+}