radius = 0;
groundOffset = 0;
distanceToUser = 0;
+ valid = true;
+ lastRun = 0;
//score = 0;
}
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)
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++)
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;
}
firstRun = false;
}
- FGScheduledFlight* flight = flights.front();
+ FGScheduledFlight* flight = flights.front();
if (!deptime) {
deptime = flight->getDepartureTime();
//cerr << "Settiing departure time " << deptime << endl;
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
}
if (distanceToUser >= TRAFFICTOAIDISTTOSTART) {
return true; // out of visual range, for the moment.
}
-
return createAIAircraft(flight, speed, deptime);
}
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;
}
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();
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);
}
FGScheduledFlight* FGAISchedule::findAvailableFlight (const string ¤tDestination,
- 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);
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;
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();
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;
+}