Traffic Manager II source code changes
- Decouple aircraft entities from Flights - Dynamic runtime flight assignment for each aircraft
This commit is contained in:
parent
66b5a7c53b
commit
d8a2726894
6 changed files with 569 additions and 173 deletions
|
@ -79,21 +79,25 @@
|
||||||
|
|
||||||
FGScheduledFlight::FGScheduledFlight()
|
FGScheduledFlight::FGScheduledFlight()
|
||||||
{
|
{
|
||||||
|
initialized = false;
|
||||||
|
available = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
FGScheduledFlight::FGScheduledFlight(const FGScheduledFlight &other)
|
FGScheduledFlight::FGScheduledFlight(const FGScheduledFlight &other)
|
||||||
{
|
{
|
||||||
callsign = other.callsign;
|
callsign = other.callsign;
|
||||||
fltRules = other.fltRules;
|
fltRules = other.fltRules;
|
||||||
departurePort = other.departurePort;
|
departurePort = other.departurePort;
|
||||||
depId = other.depId;
|
depId = other.depId;
|
||||||
arrId = other.arrId;
|
arrId = other.arrId;
|
||||||
departureTime = other.departureTime;
|
departureTime = other.departureTime;
|
||||||
cruiseAltitude = other.cruiseAltitude;
|
cruiseAltitude = other.cruiseAltitude;
|
||||||
arrivalPort = other.arrivalPort;
|
arrivalPort = other.arrivalPort;
|
||||||
arrivalTime = other.arrivalTime;
|
arrivalTime = other.arrivalTime;
|
||||||
repeatPeriod = other.repeatPeriod;
|
repeatPeriod = other.repeatPeriod;
|
||||||
initialized = other.initialized;
|
initialized = other.initialized;
|
||||||
|
requiredAircraft = other.requiredAircraft;
|
||||||
|
available = other.available;
|
||||||
}
|
}
|
||||||
|
|
||||||
FGScheduledFlight::FGScheduledFlight(const string& cs,
|
FGScheduledFlight::FGScheduledFlight(const string& cs,
|
||||||
|
@ -103,7 +107,8 @@ FGScheduledFlight::FGScheduledFlight(const string& cs,
|
||||||
int cruiseAlt,
|
int cruiseAlt,
|
||||||
const string& deptime,
|
const string& deptime,
|
||||||
const string& arrtime,
|
const string& arrtime,
|
||||||
const string& rep)
|
const string& rep,
|
||||||
|
const string& reqAC)
|
||||||
{
|
{
|
||||||
callsign = cs;
|
callsign = cs;
|
||||||
fltRules = fr;
|
fltRules = fr;
|
||||||
|
@ -115,6 +120,7 @@ FGScheduledFlight::FGScheduledFlight(const string& cs,
|
||||||
//departureTime = processTimeString(deptime);
|
//departureTime = processTimeString(deptime);
|
||||||
//arrivalTime = processTimeString(arrtime);
|
//arrivalTime = processTimeString(arrtime);
|
||||||
cruiseAltitude = cruiseAlt;
|
cruiseAltitude = cruiseAlt;
|
||||||
|
requiredAircraft = reqAC;
|
||||||
|
|
||||||
// Process the repeat period string
|
// Process the repeat period string
|
||||||
if (rep.find("WEEK",0) != string::npos)
|
if (rep.find("WEEK",0) != string::npos)
|
||||||
|
@ -136,11 +142,13 @@ FGScheduledFlight::FGScheduledFlight(const string& cs,
|
||||||
// arrival times.
|
// arrival times.
|
||||||
departureTime = processTimeString(deptime);
|
departureTime = processTimeString(deptime);
|
||||||
arrivalTime = processTimeString(arrtime);
|
arrivalTime = processTimeString(arrtime);
|
||||||
|
//departureTime += rand() % 300; // Make sure departure times are not limited to 5 minute increments.
|
||||||
if (departureTime > arrivalTime)
|
if (departureTime > arrivalTime)
|
||||||
{
|
{
|
||||||
departureTime -= repeatPeriod;
|
departureTime -= repeatPeriod;
|
||||||
}
|
}
|
||||||
initialized = false;
|
initialized = false;
|
||||||
|
available = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -55,11 +55,14 @@ private:
|
||||||
FGAirport *arrivalPort;
|
FGAirport *arrivalPort;
|
||||||
string depId;
|
string depId;
|
||||||
string arrId;
|
string arrId;
|
||||||
|
string requiredAircraft;
|
||||||
time_t departureTime;
|
time_t departureTime;
|
||||||
time_t arrivalTime;
|
time_t arrivalTime;
|
||||||
time_t repeatPeriod;
|
time_t repeatPeriod;
|
||||||
int cruiseAltitude;
|
int cruiseAltitude;
|
||||||
|
|
||||||
bool initialized;
|
bool initialized;
|
||||||
|
bool available;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -74,7 +77,8 @@ public:
|
||||||
int cruiseAlt,
|
int cruiseAlt,
|
||||||
const string& deptime,
|
const string& deptime,
|
||||||
const string& arrtime,
|
const string& arrtime,
|
||||||
const string& rep
|
const string& rep,
|
||||||
|
const string& reqAC
|
||||||
);
|
);
|
||||||
~FGScheduledFlight();
|
~FGScheduledFlight();
|
||||||
|
|
||||||
|
@ -99,11 +103,19 @@ public:
|
||||||
|
|
||||||
time_t processTimeString(const string& time);
|
time_t processTimeString(const string& time);
|
||||||
const string& getCallSign() {return callsign; };
|
const string& getCallSign() {return callsign; };
|
||||||
|
const string& getRequirement() { return requiredAircraft; }
|
||||||
|
|
||||||
|
void lock() { available = false; };
|
||||||
|
void release() { available = true; };
|
||||||
|
|
||||||
|
bool isAvailable() { return available; };
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef vector<FGScheduledFlight*> FGScheduledFlightVec;
|
typedef vector<FGScheduledFlight*> FGScheduledFlightVec;
|
||||||
typedef vector<FGScheduledFlight*>::iterator FGScheduledFlightVecIterator;
|
typedef vector<FGScheduledFlight*>::iterator FGScheduledFlightVecIterator;
|
||||||
|
|
||||||
|
typedef std::map < std::string, FGScheduledFlightVec > FGScheduledFlightMap;
|
||||||
|
|
||||||
bool compareScheduledFlights(FGScheduledFlight *a, FGScheduledFlight *b);
|
bool compareScheduledFlights(FGScheduledFlight *a, FGScheduledFlight *b);
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -74,9 +74,10 @@ FGAISchedule::FGAISchedule()
|
||||||
radius = 0;
|
radius = 0;
|
||||||
groundOffset = 0;
|
groundOffset = 0;
|
||||||
distanceToUser = 0;
|
distanceToUser = 0;
|
||||||
score = 0;
|
//score = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
FGAISchedule::FGAISchedule(string mdl,
|
FGAISchedule::FGAISchedule(string mdl,
|
||||||
string liv,
|
string liv,
|
||||||
string reg,
|
string reg,
|
||||||
|
@ -88,59 +89,77 @@ FGAISchedule::FGAISchedule(string mdl,
|
||||||
double rad,
|
double rad,
|
||||||
double grnd,
|
double grnd,
|
||||||
int scre,
|
int scre,
|
||||||
FGScheduledFlightVec flt)
|
FGScheduledFlightVec flt)*/
|
||||||
|
FGAISchedule::FGAISchedule(string model,
|
||||||
|
string lvry,
|
||||||
|
string port,
|
||||||
|
string reg,
|
||||||
|
string flightId,
|
||||||
|
bool hvy,
|
||||||
|
string act,
|
||||||
|
string arln,
|
||||||
|
string mclass,
|
||||||
|
string fltpe,
|
||||||
|
double rad,
|
||||||
|
double grnd)
|
||||||
{
|
{
|
||||||
modelPath = mdl;
|
modelPath = model;
|
||||||
livery = liv;
|
livery = lvry;
|
||||||
registration = reg;
|
homePort = port;
|
||||||
acType = act;
|
registration = reg;
|
||||||
airline = arln;
|
flightIdentifier = flightId;
|
||||||
m_class = mclass;
|
acType = act;
|
||||||
flightType = fltpe;
|
airline = arln;
|
||||||
lat = 0;
|
m_class = mclass;
|
||||||
lon = 0;
|
flightType = fltpe;
|
||||||
radius = rad;
|
lat = 0;
|
||||||
groundOffset = grnd;
|
lon = 0;
|
||||||
distanceToUser = 0;
|
radius = rad;
|
||||||
heavy = hvy;
|
groundOffset = grnd;
|
||||||
for (FGScheduledFlightVecIterator i = flt.begin();
|
distanceToUser = 0;
|
||||||
|
heavy = hvy;
|
||||||
|
/*for (FGScheduledFlightVecIterator i = flt.begin();
|
||||||
i != flt.end();
|
i != flt.end();
|
||||||
i++)
|
i++)
|
||||||
flights.push_back(new FGScheduledFlight((*(*i))));
|
flights.push_back(new FGScheduledFlight((*(*i))));*/
|
||||||
AIManagerRef = 0;
|
AIManagerRef = 0;
|
||||||
score = scre;
|
//score = scre;
|
||||||
firstRun = true;
|
firstRun = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
FGAISchedule::FGAISchedule(const FGAISchedule &other)
|
FGAISchedule::FGAISchedule(const FGAISchedule &other)
|
||||||
{
|
{
|
||||||
modelPath = other.modelPath;
|
modelPath = other.modelPath;
|
||||||
livery = other.livery;
|
homePort = other.homePort;
|
||||||
registration = other.registration;
|
livery = other.livery;
|
||||||
heavy = other.heavy;
|
registration = other.registration;
|
||||||
flights = other.flights;
|
heavy = other.heavy;
|
||||||
lat = other.lat;
|
flightIdentifier = other.flightIdentifier;
|
||||||
lon = other.lon;
|
flights = other.flights;
|
||||||
AIManagerRef = other.AIManagerRef;
|
lat = other.lat;
|
||||||
acType = other.acType;
|
lon = other.lon;
|
||||||
airline = other.airline;
|
AIManagerRef = other.AIManagerRef;
|
||||||
m_class = other.m_class;
|
acType = other.acType;
|
||||||
firstRun = other.firstRun;
|
airline = other.airline;
|
||||||
radius = other.radius;
|
m_class = other.m_class;
|
||||||
groundOffset = other.groundOffset;
|
firstRun = other.firstRun;
|
||||||
flightType = other.flightType;
|
radius = other.radius;
|
||||||
score = other.score;
|
groundOffset = other.groundOffset;
|
||||||
distanceToUser = other.distanceToUser;
|
flightType = other.flightType;
|
||||||
|
//score = other.score;
|
||||||
|
distanceToUser = other.distanceToUser;
|
||||||
|
currentDestination = other.currentDestination;
|
||||||
|
firstRun = other.firstRun;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
FGAISchedule::~FGAISchedule()
|
FGAISchedule::~FGAISchedule()
|
||||||
{
|
{
|
||||||
for (FGScheduledFlightVecIterator flt = flights.begin(); flt != flights.end(); flt++)
|
/* for (FGScheduledFlightVecIterator flt = flights.begin(); flt != flights.end(); flt++)
|
||||||
{
|
{
|
||||||
delete (*flt);
|
delete (*flt);
|
||||||
}
|
}
|
||||||
flights.clear();
|
flights.clear();*/
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FGAISchedule::init()
|
bool FGAISchedule::init()
|
||||||
|
@ -153,14 +172,14 @@ bool FGAISchedule::init()
|
||||||
//sgTimeFormatTime(&targetTimeDate, buffer);
|
//sgTimeFormatTime(&targetTimeDate, buffer);
|
||||||
//cout << "Scheduled Time " << buffer << endl;
|
//cout << "Scheduled Time " << buffer << endl;
|
||||||
//cout << "Time :" << time(NULL) << " SGTime : " << sgTimeGetGMT(temp) << endl;
|
//cout << "Time :" << time(NULL) << " SGTime : " << sgTimeGetGMT(temp) << endl;
|
||||||
for (FGScheduledFlightVecIterator i = flights.begin();
|
/*for (FGScheduledFlightVecIterator i = flights.begin();
|
||||||
i != flights.end();
|
i != flights.end();
|
||||||
i++)
|
i++)
|
||||||
{
|
{
|
||||||
//i->adjustTime(now);
|
//i->adjustTime(now);
|
||||||
if (!((*i)->initializeAirports()))
|
if (!((*i)->initializeAirports()))
|
||||||
return false;
|
return false;
|
||||||
}
|
} */
|
||||||
//sort(flights.begin(), flights.end());
|
//sort(flights.begin(), flights.end());
|
||||||
// Since time isn't initialized yet when this function is called,
|
// Since time isn't initialized yet when this function is called,
|
||||||
// Find the closest possible airport.
|
// Find the closest possible airport.
|
||||||
|
@ -170,7 +189,7 @@ bool FGAISchedule::init()
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FGAISchedule::update(time_t now)
|
bool FGAISchedule::update(time_t now)
|
||||||
{
|
{
|
||||||
FGAirport *dep;
|
FGAirport *dep;
|
||||||
FGAirport *arr;
|
FGAirport *arr;
|
||||||
double angle;
|
double angle;
|
||||||
|
@ -194,40 +213,51 @@ bool FGAISchedule::update(time_t now)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
aimgr = (FGAIManager *) globals-> get_subsystem("ai_model");
|
aimgr = (FGAIManager *) globals-> get_subsystem("ai_model");
|
||||||
// Before the flight status of this traffic entity is updated
|
// Out-of-work aircraft seeks employment. Willing to work irregular hours ...
|
||||||
// for the first time, we need to roll back it's flight schedule so
|
//cerr << "About to find a flight " << endl;
|
||||||
// so that all the flights are centered around this simulated week's time
|
if (flights.empty()) {
|
||||||
// table. This is to avoid the situation where the first scheduled flight is
|
//execute this loop at least once.
|
||||||
// in the future, causing the traffic manager to not generate traffic until
|
SG_LOG(SG_GENERAL, SG_INFO, "Scheduling for : " << modelPath << " " << registration << " " << homePort);
|
||||||
// simulated time has caught up with the real world time at initialization.
|
FGScheduledFlight *flight = 0;
|
||||||
// This is to counter a more general initialization bug, caused by the fact
|
do {
|
||||||
// that warp is not yet set when the schedule is initialized. This is
|
flight = findAvailableFlight(currentDestination, flightIdentifier);
|
||||||
// especially a problem when using a negative time offset.
|
if (flight) {
|
||||||
// i.e let's say we specify FlightGear to run with --time-offset=-24:00:00.
|
currentDestination = flight->getArrivalAirport()->getId();
|
||||||
// Then the schedule will initialize using today, but we will fly yesterday.
|
time_t arr, dep;
|
||||||
// Thus, it would take a whole day of simulation before the traffic manager
|
dep = flight->getDepartureTime();
|
||||||
// finally kicks in.
|
arr = flight->getArrivalTime();
|
||||||
if (firstRun)
|
string depT = asctime(gmtime(&dep));
|
||||||
{
|
string arrT = asctime(gmtime(&arr));
|
||||||
if (init() == false)
|
|
||||||
AIManagerRef = BOGUS;
|
depT = depT.substr(0,24);
|
||||||
|
arrT = arrT.substr(0,24);
|
||||||
for (FGScheduledFlightVecIterator i = flights.begin();
|
SG_LOG(SG_GENERAL, SG_INFO, " " << flight->getCallSign() << ":"
|
||||||
i != flights.end();
|
<< " " << flight->getDepartureAirport()->getId() << ":"
|
||||||
i++)
|
<< " " << depT << ":"
|
||||||
{
|
<< " \"" << flight->getArrivalAirport()->getId() << "\"" << ":"
|
||||||
(*i)->adjustTime(now);
|
<< " " << arrT << ":");
|
||||||
}
|
flights.push_back(flight);
|
||||||
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
|
} while ((currentDestination != homePort) && (flight != 0));
|
||||||
// from cluttering the gate areas.
|
SG_LOG(SG_GENERAL, SG_INFO, cerr << " Done " << endl);
|
||||||
firstRun = false;
|
|
||||||
}
|
}
|
||||||
|
//cerr << " Done " << endl;
|
||||||
|
// No flights available for this aircraft
|
||||||
|
if (flights.size() == 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
// Sort all the scheduled flights according to scheduled departure time.
|
// Sort all the scheduled flights according to scheduled departure time.
|
||||||
// Because this is done at every update, we only need to check the status
|
// Because this is done at every update, we only need to check the status
|
||||||
// of the first listed flight.
|
// of the first listed flight.
|
||||||
sort(flights.begin(), flights.end(), compareScheduledFlights);
|
//sort(flights.begin(), flights.end(), compareScheduledFlights);
|
||||||
|
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;
|
||||||
|
}
|
||||||
if (!deptime)
|
if (!deptime)
|
||||||
deptime = (*flights.begin())->getDepartureTime();
|
deptime = (*flights.begin())->getDepartureTime();
|
||||||
FGScheduledFlightVecIterator i = flights.begin();
|
FGScheduledFlightVecIterator i = flights.begin();
|
||||||
|
@ -251,7 +281,13 @@ bool FGAISchedule::update(time_t now)
|
||||||
if (((*i)->getDepartureTime() < now) && ((*i)->getArrivalTime() < now))
|
if (((*i)->getDepartureTime() < now) && ((*i)->getArrivalTime() < now))
|
||||||
{
|
{
|
||||||
SG_LOG (SG_GENERAL, SG_DEBUG, "Traffic Manager: Flight is in the Past");
|
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)->update();
|
||||||
|
i = flights.erase(i);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -357,7 +393,7 @@ bool FGAISchedule::update(time_t now)
|
||||||
SG_LOG (SG_GENERAL, SG_DEBUG, "Traffic manager: " << registration << " is scheduled for a flight from "
|
SG_LOG (SG_GENERAL, SG_DEBUG, "Traffic manager: " << registration << " is scheduled for a flight from "
|
||||||
<< dep->getId() << " to " << arr->getId() << ". Current distance to user: "
|
<< dep->getId() << " to " << arr->getId() << ". Current distance to user: "
|
||||||
<< distanceToUser*SG_METER_TO_NM);
|
<< distanceToUser*SG_METER_TO_NM);
|
||||||
if ((distanceToUser*SG_METER_TO_NM) < TRAFFICTOAIDIST)
|
if ((distanceToUser*SG_METER_TO_NM) < TRAFFICTOAIDISTTOSTART)
|
||||||
{
|
{
|
||||||
string flightPlanName = dep->getId() + string("-") + arr->getId() +
|
string flightPlanName = dep->getId() + string("-") + arr->getId() +
|
||||||
string(".xml");
|
string(".xml");
|
||||||
|
@ -441,10 +477,102 @@ bool FGAISchedule::update(time_t now)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FGAISchedule::next()
|
bool FGAISchedule::next()
|
||||||
{
|
{
|
||||||
(*flights.begin())->update();
|
FGScheduledFlightVecIterator i = flights.begin();
|
||||||
sort(flights.begin(), flights.end(), compareScheduledFlights);
|
(*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;
|
||||||
|
}
|
||||||
|
//cerr << "FGAISchedule :: next needs updating" << endl;
|
||||||
|
//exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
FGScheduledFlight* FGAISchedule::findAvailableFlight (const string ¤tDestination,
|
||||||
|
const string &req)
|
||||||
|
{
|
||||||
|
time_t now = time(NULL) + fgGetLong("/sim/time/warp");
|
||||||
|
|
||||||
|
FGTrafficManager *tmgr = (FGTrafficManager *) globals->get_subsystem("Traffic Manager");
|
||||||
|
FGScheduledFlightVecIterator fltBegin, fltEnd;
|
||||||
|
fltBegin = tmgr->getFirstFlight(req);
|
||||||
|
fltEnd = tmgr->getLastFlight(req);
|
||||||
|
|
||||||
|
|
||||||
|
//cerr << "Finding available flight " << endl;
|
||||||
|
// For Now:
|
||||||
|
// Traverse every registered flight
|
||||||
|
if (fltBegin == fltEnd) {
|
||||||
|
//cerr << "No Flights Scheduled for " << req << endl;
|
||||||
|
}
|
||||||
|
int counter = 0;
|
||||||
|
for (FGScheduledFlightVecIterator i = fltBegin; i != fltEnd; i++) {
|
||||||
|
(*i)->adjustTime(now);
|
||||||
|
//sort(fltBegin, fltEnd, compareScheduledFlights);
|
||||||
|
//cerr << counter++ << endl;
|
||||||
|
}
|
||||||
|
sort(fltBegin, fltEnd, compareScheduledFlights);
|
||||||
|
for (FGScheduledFlightVecIterator i = fltBegin; i != fltEnd; i++) {
|
||||||
|
//bool valid = true;
|
||||||
|
counter++;
|
||||||
|
if (!(*i)->isAvailable()) {
|
||||||
|
//cerr << (*i)->getCallSign() << "is no longer available" << endl;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!((*i)->getRequirement() == req)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!(((*i)->getArrivalAirport()) && ((*i)->getDepartureAirport()))) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!(currentDestination.empty())) {
|
||||||
|
if (currentDestination != (*i)->getDepartureAirport()->getId()) {
|
||||||
|
//cerr << (*i)->getCallSign() << "Doesn't match destination" << endl;
|
||||||
|
//cerr << "Current Destination " << currentDestination << "Doesnt match flight's " <<
|
||||||
|
// (*i)->getArrivalAirport()->getId() << endl;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//TODO: check time
|
||||||
|
// So, if we actually get here, we have a winner
|
||||||
|
//cerr << "found flight: " << req << " : " << currentDestination << " : " <<
|
||||||
|
// (*i)->getArrivalAirport()->getId() << endl;
|
||||||
|
(*i)->lock();
|
||||||
|
return (*i);
|
||||||
|
}
|
||||||
|
// matches req?
|
||||||
|
// if currentDestination has a value, does it match departure of next flight?
|
||||||
|
// is departure time later than planned arrival?
|
||||||
|
// is departure port valid?
|
||||||
|
// is arrival port valid?
|
||||||
|
//cerr << "Ack no flight found: " << endl;
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
double FGAISchedule::getSpeed()
|
double FGAISchedule::getSpeed()
|
||||||
|
@ -472,12 +600,20 @@ double FGAISchedule::getSpeed()
|
||||||
dest.CourseAndDistance(curr, &courseToDest, &distanceToDest);
|
dest.CourseAndDistance(curr, &courseToDest, &distanceToDest);
|
||||||
speed = (distanceToDest*SG_METER_TO_NM) /
|
speed = (distanceToDest*SG_METER_TO_NM) /
|
||||||
((double) remainingTimeEnroute/3600.0);
|
((double) remainingTimeEnroute/3600.0);
|
||||||
|
if (speed < 300) {
|
||||||
|
//cerr << "Warning : calculated speed for " << (*i)->getCallSign() << " is low : " << speed << " clamping to 300" << endl;
|
||||||
|
speed = 300.0;
|
||||||
|
}
|
||||||
|
if (speed > 500) {
|
||||||
|
//cerr << "Warning : calculated speed for " << (*i)->getCallSign() << " is high : " << speed << " clamping to 300" << endl;
|
||||||
|
speed = 500.0;
|
||||||
|
}
|
||||||
return speed;
|
return speed;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool compareSchedules(FGAISchedule*a, FGAISchedule*b)
|
bool compareSchedules(FGAISchedule*a, FGAISchedule*b)
|
||||||
{
|
{
|
||||||
return (*a) < (*b);
|
//return (*a) < (*b);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -29,19 +29,23 @@
|
||||||
#ifndef _FGSCHEDULE_HXX_
|
#ifndef _FGSCHEDULE_HXX_
|
||||||
#define _FGSCHEDULE_HXX_
|
#define _FGSCHEDULE_HXX_
|
||||||
|
|
||||||
#define TRAFFICTOAIDIST 150.0
|
#define TRAFFICTOAIDISTTOSTART 150.0
|
||||||
|
#define TRAFFICTOAIDISTTODIE 200.0
|
||||||
|
|
||||||
|
|
||||||
class FGAISchedule
|
class FGAISchedule
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
string modelPath;
|
string modelPath;
|
||||||
|
string homePort;
|
||||||
string livery;
|
string livery;
|
||||||
string registration;
|
string registration;
|
||||||
string airline;
|
string airline;
|
||||||
string acType;
|
string acType;
|
||||||
string m_class;
|
string m_class;
|
||||||
string flightType;
|
string flightType;
|
||||||
|
string flightIdentifier;
|
||||||
|
string currentDestination;
|
||||||
bool heavy;
|
bool heavy;
|
||||||
FGScheduledFlightVec flights;
|
FGScheduledFlightVec flights;
|
||||||
float lat;
|
float lat;
|
||||||
|
@ -50,14 +54,25 @@ class FGAISchedule
|
||||||
double groundOffset;
|
double groundOffset;
|
||||||
double distanceToUser;
|
double distanceToUser;
|
||||||
int AIManagerRef;
|
int AIManagerRef;
|
||||||
int score;
|
//int score;
|
||||||
bool firstRun;
|
bool firstRun;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
FGAISchedule(); // constructor
|
FGAISchedule(); // constructor
|
||||||
FGAISchedule(string, string, string, bool, string, string, string, string, double, double,
|
FGAISchedule(string model,
|
||||||
int, FGScheduledFlightVec); // construct & init
|
string livery,
|
||||||
|
string homePort,
|
||||||
|
string registration,
|
||||||
|
string flightId,
|
||||||
|
bool heavy,
|
||||||
|
string acType,
|
||||||
|
string airline,
|
||||||
|
string m_class,
|
||||||
|
string flight_type,
|
||||||
|
double radius,
|
||||||
|
double offset); // construct & init
|
||||||
FGAISchedule(const FGAISchedule &other); // copy constructor
|
FGAISchedule(const FGAISchedule &other); // copy constructor
|
||||||
|
|
||||||
|
|
||||||
|
@ -69,9 +84,10 @@ class FGAISchedule
|
||||||
|
|
||||||
double getSpeed ();
|
double getSpeed ();
|
||||||
//void setClosestDistanceToUser();
|
//void setClosestDistanceToUser();
|
||||||
void next(); // forces the schedule to move on to the next flight.
|
bool next(); // forces the schedule to move on to the next flight.
|
||||||
|
|
||||||
time_t getDepartureTime () { return (*flights.begin())->getDepartureTime (); };
|
// TODO: rework these four functions
|
||||||
|
time_t getDepartureTime () { return (*flights.begin())->getDepartureTime (); };
|
||||||
FGAirport * getDepartureAirport () { return (*flights.begin())->getDepartureAirport(); };
|
FGAirport * getDepartureAirport () { return (*flights.begin())->getDepartureAirport(); };
|
||||||
FGAirport * getArrivalAirport () { return (*flights.begin())->getArrivalAirport (); };
|
FGAirport * getArrivalAirport () { return (*flights.begin())->getArrivalAirport (); };
|
||||||
int getCruiseAlt () { return (*flights.begin())->getCruiseAlt (); };
|
int getCruiseAlt () { return (*flights.begin())->getCruiseAlt (); };
|
||||||
|
@ -84,9 +100,10 @@ class FGAISchedule
|
||||||
const string& getRegistration () { return registration;};
|
const string& getRegistration () { return registration;};
|
||||||
const string& getFlightRules () { return (*flights.begin())->getFlightRules (); };
|
const string& getFlightRules () { return (*flights.begin())->getFlightRules (); };
|
||||||
bool getHeavy () { return heavy; };
|
bool getHeavy () { return heavy; };
|
||||||
|
FGScheduledFlight*findAvailableFlight (const string ¤tDestination, const string &req);
|
||||||
// used to sort in decending order of score: I've probably found a better way to
|
// 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.
|
// 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; };
|
//void * getAiRef () { return AIManagerRef; };
|
||||||
//FGAISchedule* getAddress () { return this;};
|
//FGAISchedule* getAddress () { return this;};
|
||||||
|
|
||||||
|
|
|
@ -19,9 +19,11 @@
|
||||||
*
|
*
|
||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
|
|
||||||
/* This a prototype version of a top-level flight plan manager for Flightgear.
|
/*
|
||||||
* It parses the fgtraffic.txt file and determine for a specific time/date,
|
* Traffic manager parses airlines timetable-like data and uses this to
|
||||||
* where each aircraft listed in this file is at the current time.
|
* determine the approximate position of each AI aircraft in its database.
|
||||||
|
* When an AI aircraft is close to the user's position, a more detailed
|
||||||
|
* AIModels based simulation is set up.
|
||||||
*
|
*
|
||||||
* I'm currently assuming the following simplifications:
|
* I'm currently assuming the following simplifications:
|
||||||
* 1) The earth is a perfect sphere
|
* 1) The earth is a perfect sphere
|
||||||
|
@ -77,8 +79,9 @@ using std::sort;
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
FGTrafficManager::FGTrafficManager()
|
FGTrafficManager::FGTrafficManager()
|
||||||
{
|
{
|
||||||
score = 0;
|
//score = 0;
|
||||||
runCount = 0;
|
//runCount = 0;
|
||||||
|
acCounter = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
FGTrafficManager:: ~FGTrafficManager()
|
FGTrafficManager:: ~FGTrafficManager()
|
||||||
|
@ -88,50 +91,22 @@ FGTrafficManager:: ~FGTrafficManager()
|
||||||
delete (*sched);
|
delete (*sched);
|
||||||
}
|
}
|
||||||
scheduledAircraft.clear();
|
scheduledAircraft.clear();
|
||||||
// for (FGScheduledFlightVecIterator flt = flights.begin(); flt != flights.end(); flt++)
|
flights.clear();
|
||||||
// {
|
|
||||||
// delete (*flt);
|
|
||||||
// }
|
|
||||||
// flights.clear();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FGTrafficManager::init()
|
void FGTrafficManager::init()
|
||||||
{
|
{
|
||||||
//cerr << "Initializing Schedules" << endl;
|
|
||||||
//time_t now = time(NULL) + fgGetLong("/sim/time/warp");
|
|
||||||
//currAircraft = scheduledAircraft.begin();
|
|
||||||
//while (currAircraft != scheduledAircraft.end())
|
|
||||||
// {
|
|
||||||
// if (!(currAircraft->init()))
|
|
||||||
// {
|
|
||||||
// currAircraft=scheduledAircraft.erase(currAircraft);
|
|
||||||
// //cerr << "Erasing " << currAircraft->getRegistration() << endl;
|
|
||||||
// }
|
|
||||||
// else
|
|
||||||
// {
|
|
||||||
// currAircraft++;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// Sort by points: Aircraft with frequent visits to the
|
|
||||||
// startup airport will be processed first
|
|
||||||
ulDir* d, *d2;
|
ulDir* d, *d2;
|
||||||
ulDirEnt* dent, *dent2;
|
ulDirEnt* dent, *dent2;
|
||||||
SGPath aircraftDir = globals->get_fg_root();
|
SGPath aircraftDir = globals->get_fg_root();
|
||||||
|
|
||||||
/* keep the following three lines (which mimicks the old "fixed path" behavior)
|
|
||||||
* until we have some AI models with traffic in the base package
|
|
||||||
*/
|
|
||||||
SGPath path = aircraftDir;
|
SGPath path = aircraftDir;
|
||||||
path.append("Traffic/fgtraffic.xml");
|
|
||||||
if (path.exists())
|
aircraftDir.append("AI/Traffic");
|
||||||
readXML(path.str(),*this);
|
|
||||||
|
|
||||||
aircraftDir.append("AI/Aircraft");
|
|
||||||
if ((d = ulOpenDir(aircraftDir.c_str())) != NULL)
|
if ((d = ulOpenDir(aircraftDir.c_str())) != NULL)
|
||||||
{
|
{
|
||||||
while((dent = ulReadDir(d)) != NULL) {
|
while((dent = ulReadDir(d)) != NULL) {
|
||||||
//cerr << "Scanning : " << dent->d_name << endl;
|
|
||||||
if (string(dent->d_name) != string(".") &&
|
if (string(dent->d_name) != string(".") &&
|
||||||
string(dent->d_name) != string("..") &&
|
string(dent->d_name) != string("..") &&
|
||||||
dent->d_isdir)
|
dent->d_isdir)
|
||||||
|
@ -145,7 +120,6 @@ void FGTrafficManager::init()
|
||||||
currFile.append(dent2->d_name);
|
currFile.append(dent2->d_name);
|
||||||
if (currFile.extension() == string("xml"))
|
if (currFile.extension() == string("xml"))
|
||||||
{
|
{
|
||||||
//cerr << "found " << dent2->d_name << " for parsing" << endl;
|
|
||||||
SGPath currFile = currACDir;
|
SGPath currFile = currACDir;
|
||||||
currFile.append(dent2->d_name);
|
currFile.append(dent2->d_name);
|
||||||
SG_LOG(SG_GENERAL, SG_INFO, "Scanning " << currFile.str() << " for traffic");
|
SG_LOG(SG_GENERAL, SG_INFO, "Scanning " << currFile.str() << " for traffic");
|
||||||
|
@ -157,12 +131,10 @@ void FGTrafficManager::init()
|
||||||
}
|
}
|
||||||
ulCloseDir(d);
|
ulCloseDir(d);
|
||||||
}
|
}
|
||||||
// Sort by points: Aircraft with frequent visits to the
|
time_t now = time(NULL) + fgGetLong("/sim/time/warp");
|
||||||
// startup airport will be processed first
|
|
||||||
sort(scheduledAircraft.begin(), scheduledAircraft.end(), compareSchedules);
|
currAircraft = scheduledAircraft.begin();
|
||||||
currAircraft = scheduledAircraft.begin();
|
currAircraftClosest = scheduledAircraft.begin();
|
||||||
currAircraftClosest = scheduledAircraft.begin();
|
|
||||||
//cerr << "Done initializing schedules" << endl;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void FGTrafficManager::update(double /*dt*/)
|
void FGTrafficManager::update(double /*dt*/)
|
||||||
|
@ -170,7 +142,6 @@ void FGTrafficManager::update(double /*dt*/)
|
||||||
|
|
||||||
time_t now = time(NULL) + fgGetLong("/sim/time/warp");
|
time_t now = time(NULL) + fgGetLong("/sim/time/warp");
|
||||||
if (scheduledAircraft.size() == 0) {
|
if (scheduledAircraft.size() == 0) {
|
||||||
//SG_LOG( SG_GENERAL, SG_INFO, "Returned Running TrafficManager::Update() ");
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(currAircraft == scheduledAircraft.end())
|
if(currAircraft == scheduledAircraft.end())
|
||||||
|
@ -179,12 +150,12 @@ void FGTrafficManager::update(double /*dt*/)
|
||||||
}
|
}
|
||||||
if (!((*currAircraft)->update(now)))
|
if (!((*currAircraft)->update(now)))
|
||||||
{
|
{
|
||||||
|
// NOTE: With traffic manager II, this statement below is no longer true
|
||||||
// after proper initialization, we shouldnt get here.
|
// after proper initialization, we shouldnt get here.
|
||||||
// But let's make sure
|
// But let's make sure
|
||||||
SG_LOG( SG_GENERAL, SG_ALERT, "Failed to update aircraft schedule in traffic manager");
|
//SG_LOG( SG_GENERAL, SG_ALERT, "Failed to update aircraft schedule in traffic manager");
|
||||||
}
|
}
|
||||||
currAircraft++;
|
currAircraft++;
|
||||||
//SG_LOG( SG_GENERAL, SG_INFO, "Done Running TrafficManager::Update() ");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void FGTrafficManager::release(int id)
|
void FGTrafficManager::release(int id)
|
||||||
|
@ -206,9 +177,181 @@ bool FGTrafficManager::isReleased(int id)
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
|
void FGTrafficManager::readTimeTableFromFile(SGPath infileName)
|
||||||
|
{
|
||||||
|
string model;
|
||||||
|
string livery;
|
||||||
|
string homePort;
|
||||||
|
string registration;
|
||||||
|
string flightReq;
|
||||||
|
bool isHeavy;
|
||||||
|
string acType;
|
||||||
|
string airline;
|
||||||
|
string m_class;
|
||||||
|
string FlightType;
|
||||||
|
double radius;
|
||||||
|
double offset;
|
||||||
|
|
||||||
|
char buffer[256];
|
||||||
|
string buffString;
|
||||||
|
vector <string> tokens, depTime,arrTime;
|
||||||
|
vector <string>::iterator it;
|
||||||
|
ifstream infile(infileName.str().c_str());
|
||||||
|
while (1) {
|
||||||
|
infile.getline(buffer, 256);
|
||||||
|
if (infile.eof()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
//cerr << "Read line : " << buffer << endl;
|
||||||
|
buffString = string(buffer);
|
||||||
|
tokens.clear();
|
||||||
|
Tokenize(buffString, tokens, " \t");
|
||||||
|
//for (it = tokens.begin(); it != tokens.end(); it++) {
|
||||||
|
// cerr << "Tokens: " << *(it) << endl;
|
||||||
|
//}
|
||||||
|
//cerr << endl;
|
||||||
|
if (!tokens.empty()) {
|
||||||
|
if (tokens[0] == string("AC")) {
|
||||||
|
if (tokens.size() != 13) {
|
||||||
|
SG_LOG(SG_GENERAL, SG_ALERT, "Error parsing traffic file " << infileName.str() << " at " << buffString);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
model = tokens[12];
|
||||||
|
livery = tokens[6];
|
||||||
|
homePort = tokens[1];
|
||||||
|
registration = tokens[2];
|
||||||
|
if (tokens[11] == string("false")) {
|
||||||
|
isHeavy = false;
|
||||||
|
} else {
|
||||||
|
isHeavy = true;
|
||||||
|
}
|
||||||
|
acType = tokens[4];
|
||||||
|
airline = tokens[5];
|
||||||
|
flightReq = tokens[3] + tokens[5];
|
||||||
|
m_class = tokens[10];
|
||||||
|
FlightType = tokens[9];
|
||||||
|
radius = atof(tokens[8].c_str());
|
||||||
|
offset = atof(tokens[7].c_str());;
|
||||||
|
//cerr << "Found AC string " << model << " " << livery << " " << homePort << " "
|
||||||
|
// << registration << " " << flightReq << " " << isHeavy << " " << acType << " " << airline << " " << m_class
|
||||||
|
// << " " << FlightType << " " << radius << " " << offset << endl;
|
||||||
|
scheduledAircraft.push_back(new FGAISchedule(model,
|
||||||
|
livery,
|
||||||
|
homePort,
|
||||||
|
registration,
|
||||||
|
flightReq,
|
||||||
|
isHeavy,
|
||||||
|
acType,
|
||||||
|
airline,
|
||||||
|
m_class,
|
||||||
|
FlightType,
|
||||||
|
radius,
|
||||||
|
offset));
|
||||||
|
}
|
||||||
|
if (tokens[0] == string("FLIGHT")) {
|
||||||
|
//cerr << "Found flight " << buffString << " size is : " << tokens.size() << endl;
|
||||||
|
if (tokens.size() != 10) {
|
||||||
|
SG_LOG(SG_GENERAL, SG_ALERT, "Error parsing traffic file " << infileName.str() << " at " << buffString);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
string callsign = tokens[1];
|
||||||
|
string fltrules = tokens[2];
|
||||||
|
string weekdays = tokens[3];
|
||||||
|
string departurePort = tokens[5];
|
||||||
|
string arrivalPort = tokens[7];
|
||||||
|
int cruiseAlt = atoi(tokens[8].c_str());
|
||||||
|
string depTimeGen = tokens[4];
|
||||||
|
string arrTimeGen = tokens[6];
|
||||||
|
string repeat = "WEEK";
|
||||||
|
string requiredAircraft = tokens[9];
|
||||||
|
|
||||||
|
if (weekdays.size() != 7) {
|
||||||
|
cerr << "Found misconfigured weekdays string" << weekdays << endl;
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
depTime.clear();
|
||||||
|
arrTime.clear();
|
||||||
|
Tokenize(depTimeGen, depTime, ":");
|
||||||
|
Tokenize(arrTimeGen, arrTime, ":");
|
||||||
|
double dep = atof(depTime[0].c_str()) + (atof(depTime[1].c_str()) / 60.0);
|
||||||
|
double arr = atof(arrTime[0].c_str()) + (atof(arrTime[1].c_str()) / 60.0);
|
||||||
|
//cerr << "Using " << dep << " " << arr << endl;
|
||||||
|
bool arrivalWeekdayNeedsIncrement = false;
|
||||||
|
if (arr < dep) {
|
||||||
|
arrivalWeekdayNeedsIncrement = true;
|
||||||
|
}
|
||||||
|
for (int i = 0; i < 7; i++) {
|
||||||
|
if (weekdays[i] != '.') {
|
||||||
|
char buffer[4];
|
||||||
|
snprintf(buffer, 4, "%d/", i);
|
||||||
|
string departureTime = string(buffer) + depTimeGen + string(":00");
|
||||||
|
string arrivalTime;
|
||||||
|
if (!arrivalWeekdayNeedsIncrement) {
|
||||||
|
arrivalTime = string(buffer) + arrTimeGen + string(":00");
|
||||||
|
}
|
||||||
|
if (arrivalWeekdayNeedsIncrement && i != 6 ) {
|
||||||
|
snprintf(buffer, 4, "%d/", i+1);
|
||||||
|
arrivalTime = string(buffer) + arrTimeGen + string(":00");
|
||||||
|
}
|
||||||
|
if (arrivalWeekdayNeedsIncrement && i == 6 ) {
|
||||||
|
snprintf(buffer, 4, "%d/", 0);
|
||||||
|
arrivalTime = string(buffer) + arrTimeGen + string(":00");
|
||||||
|
}
|
||||||
|
cerr << "Adding flight: " << callsign << " "
|
||||||
|
<< fltrules << " "
|
||||||
|
<< departurePort << " "
|
||||||
|
<< arrivalPort << " "
|
||||||
|
<< cruiseAlt << " "
|
||||||
|
<< departureTime << " "
|
||||||
|
<< arrivalTime << " "
|
||||||
|
<< repeat << " "
|
||||||
|
<< requiredAircraft << endl;
|
||||||
|
|
||||||
|
flights[requiredAircraft].push_back(new FGScheduledFlight(callsign,
|
||||||
|
fltrules,
|
||||||
|
departurePort,
|
||||||
|
arrivalPort,
|
||||||
|
cruiseAlt,
|
||||||
|
departureTime,
|
||||||
|
arrivalTime,
|
||||||
|
repeat,
|
||||||
|
requiredAircraft));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
//exit(1);
|
||||||
|
}*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
void FGTrafficManager::Tokenize(const string& str,
|
||||||
|
vector<string>& tokens,
|
||||||
|
const string& delimiters)
|
||||||
|
{
|
||||||
|
// Skip delimiters at beginning.
|
||||||
|
string::size_type lastPos = str.find_first_not_of(delimiters, 0);
|
||||||
|
// Find first "non-delimiter".
|
||||||
|
string::size_type pos = str.find_first_of(delimiters, lastPos);
|
||||||
|
|
||||||
|
while (string::npos != pos || string::npos != lastPos)
|
||||||
|
{
|
||||||
|
// Found a token, add it to the vector.
|
||||||
|
tokens.push_back(str.substr(lastPos, pos - lastPos));
|
||||||
|
// Skip delimiters. Note the "not_of"
|
||||||
|
lastPos = str.find_first_not_of(delimiters, pos);
|
||||||
|
// Find next "non-delimiter"
|
||||||
|
pos = str.find_first_of(delimiters, lastPos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
void FGTrafficManager::startXML () {
|
void FGTrafficManager::startXML () {
|
||||||
//cout << "Start XML" << endl;
|
//cout << "Start XML" << endl;
|
||||||
|
requiredAircraft = "";
|
||||||
|
homePort = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
void FGTrafficManager::endXML () {
|
void FGTrafficManager::endXML () {
|
||||||
|
@ -245,12 +388,16 @@ void FGTrafficManager::endElement (const char * name) {
|
||||||
mdl = value;
|
mdl = value;
|
||||||
else if (element == string("livery"))
|
else if (element == string("livery"))
|
||||||
livery = value;
|
livery = value;
|
||||||
|
else if (element == string("home-port"))
|
||||||
|
homePort = value;
|
||||||
else if (element == string("registration"))
|
else if (element == string("registration"))
|
||||||
registration = value;
|
registration = value;
|
||||||
else if (element == string("airline"))
|
else if (element == string("airline"))
|
||||||
airline = value;
|
airline = value;
|
||||||
else if (element == string("actype"))
|
else if (element == string("actype"))
|
||||||
acType = value;
|
acType = value;
|
||||||
|
else if (element == string("required-aircraft"))
|
||||||
|
requiredAircraft = value;
|
||||||
else if (element == string("flighttype"))
|
else if (element == string("flighttype"))
|
||||||
flighttype = value;
|
flighttype = value;
|
||||||
else if (element == string("radius"))
|
else if (element == string("radius"))
|
||||||
|
@ -299,42 +446,91 @@ void FGTrafficManager::endElement (const char * name) {
|
||||||
//Prioritize aircraft
|
//Prioritize aircraft
|
||||||
string apt = fgGetString("/sim/presets/airport-id");
|
string apt = fgGetString("/sim/presets/airport-id");
|
||||||
//cerr << "Airport information: " << apt << " " << departurePort << " " << arrivalPort << endl;
|
//cerr << "Airport information: " << apt << " " << departurePort << " " << arrivalPort << endl;
|
||||||
if (departurePort == apt) score++;
|
//if (departurePort == apt) score++;
|
||||||
flights.push_back(new FGScheduledFlight(callsign,
|
//flights.push_back(new FGScheduledFlight(callsign,
|
||||||
fltrules,
|
// fltrules,
|
||||||
departurePort,
|
// departurePort,
|
||||||
arrivalPort,
|
// arrivalPort,
|
||||||
cruiseAlt,
|
// cruiseAlt,
|
||||||
departureTime,
|
// departureTime,
|
||||||
arrivalTime,
|
// arrivalTime,
|
||||||
repeat));
|
// repeat));
|
||||||
|
if (requiredAircraft == "") {
|
||||||
|
char buffer[16];
|
||||||
|
snprintf(buffer, 16, "%d", acCounter);
|
||||||
|
requiredAircraft = buffer;
|
||||||
}
|
}
|
||||||
|
SG_LOG(SG_GENERAL, SG_DEBUG, "Adding flight: " << callsign << " "
|
||||||
|
<< fltrules << " "
|
||||||
|
<< departurePort << " "
|
||||||
|
<< arrivalPort << " "
|
||||||
|
<< cruiseAlt << " "
|
||||||
|
<< departureTime << " "
|
||||||
|
<< arrivalTime << " "
|
||||||
|
<< repeat << " "
|
||||||
|
<< requiredAircraft);
|
||||||
|
|
||||||
|
flights[requiredAircraft].push_back(new FGScheduledFlight(callsign,
|
||||||
|
fltrules,
|
||||||
|
departurePort,
|
||||||
|
arrivalPort,
|
||||||
|
cruiseAlt,
|
||||||
|
departureTime,
|
||||||
|
arrivalTime,
|
||||||
|
repeat,
|
||||||
|
requiredAircraft));
|
||||||
|
requiredAircraft = "";
|
||||||
|
}
|
||||||
else if (element == string("aircraft"))
|
else if (element == string("aircraft"))
|
||||||
{
|
{
|
||||||
int proportion = (int) (fgGetDouble("/sim/traffic-manager/proportion") * 100);
|
int proportion = (int) (fgGetDouble("/sim/traffic-manager/proportion") * 100);
|
||||||
int randval = rand() & 100;
|
int randval = rand() & 100;
|
||||||
if (randval < proportion) {
|
if (randval < proportion) {
|
||||||
scheduledAircraft.push_back(new FGAISchedule(mdl,
|
//scheduledAircraft.push_back(new FGAISchedule(mdl,
|
||||||
livery,
|
// livery,
|
||||||
registration,
|
// registration,
|
||||||
heavy,
|
// heavy,
|
||||||
acType,
|
// acType,
|
||||||
airline,
|
// airline,
|
||||||
m_class,
|
// m_class,
|
||||||
flighttype,
|
// flighttype,
|
||||||
radius,
|
// radius,
|
||||||
offset,
|
// offset,
|
||||||
score,
|
// score,
|
||||||
flights));
|
// flights));
|
||||||
|
if (requiredAircraft == "") {
|
||||||
|
char buffer[16];
|
||||||
|
snprintf(buffer, 16, "%d", acCounter);
|
||||||
|
requiredAircraft = buffer;
|
||||||
|
}
|
||||||
|
if (homePort == "") {
|
||||||
|
homePort = departurePort;
|
||||||
|
}
|
||||||
|
scheduledAircraft.push_back(new FGAISchedule(mdl,
|
||||||
|
livery,
|
||||||
|
homePort,
|
||||||
|
registration,
|
||||||
|
requiredAircraft,
|
||||||
|
heavy,
|
||||||
|
acType,
|
||||||
|
airline,
|
||||||
|
m_class,
|
||||||
|
flighttype,
|
||||||
|
radius,
|
||||||
|
offset));
|
||||||
|
|
||||||
// while(flights.begin() != flights.end()) {
|
// while(flights.begin() != flights.end()) {
|
||||||
// flights.pop_back();
|
// flights.pop_back();
|
||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
for (FGScheduledFlightVecIterator flt = flights.begin(); flt != flights.end(); flt++)
|
acCounter++;
|
||||||
{
|
requiredAircraft = "";
|
||||||
delete (*flt);
|
homePort = "";
|
||||||
}
|
//for (FGScheduledFlightVecIterator flt = flights.begin(); flt != flights.end(); flt++)
|
||||||
flights.clear();
|
// {
|
||||||
|
// delete (*flt);
|
||||||
|
// }
|
||||||
|
//flights.clear();
|
||||||
SG_LOG( SG_GENERAL, SG_BULK, "Reading aircraft : "
|
SG_LOG( SG_GENERAL, SG_BULK, "Reading aircraft : "
|
||||||
<< registration
|
<< registration
|
||||||
<< " with prioritization score "
|
<< " with prioritization score "
|
||||||
|
@ -360,3 +556,4 @@ void FGTrafficManager::warning (const char * message, int line, int column) {
|
||||||
void FGTrafficManager::error (const char * message, int line, int column) {
|
void FGTrafficManager::error (const char * message, int line, int column) {
|
||||||
SG_LOG(SG_IO, SG_ALERT, "Error: " << message << " (" << line << ',' << column << ')');
|
SG_LOG(SG_IO, SG_ALERT, "Error: " << message << " (" << line << ',' << column << ')');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,6 +22,25 @@
|
||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
* This file contains the class definitions for a (Top Level) traffic
|
* This file contains the class definitions for a (Top Level) traffic
|
||||||
* manager for FlightGear.
|
* manager for FlightGear.
|
||||||
|
*
|
||||||
|
* This is traffic manager version II. The major difference from version
|
||||||
|
* I is that the Flight Schedules are decoupled from the AIAircraft
|
||||||
|
* entities. This allows for a much greater flexibility in setting up
|
||||||
|
* Irregular schedules. Traffic Manager II also makes no longer use of .xml
|
||||||
|
* based configuration files.
|
||||||
|
*
|
||||||
|
* Here is a step plan to achieve the goal of creating Traffic Manager II
|
||||||
|
*
|
||||||
|
* 1) Read aircraft data from a simple text file, like the one provided by
|
||||||
|
* Gabor Toth
|
||||||
|
* 2) Create a new database structure of SchedFlights. This new database
|
||||||
|
* should not be part of the Schedule class, but of TrafficManager itself
|
||||||
|
* 3) Each aircraft should have a list of possible Flights it can operate
|
||||||
|
* (i.e. airline and AC type match).
|
||||||
|
* 4) Aircraft processing proceeds as current. During initialization, we seek
|
||||||
|
* the most urgent flight that needs to be operated
|
||||||
|
* 5) Modify the getNextLeg function so that the next flight is loaded smoothly.
|
||||||
|
|
||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
|
|
||||||
#ifndef _TRAFFICMGR_HXX_
|
#ifndef _TRAFFICMGR_HXX_
|
||||||
|
@ -29,6 +48,7 @@
|
||||||
|
|
||||||
#include <simgear/structure/subsystem_mgr.hxx>
|
#include <simgear/structure/subsystem_mgr.hxx>
|
||||||
#include <simgear/xml/easyxml.hxx>
|
#include <simgear/xml/easyxml.hxx>
|
||||||
|
#include <simgear/misc/sg_path.hxx>
|
||||||
|
|
||||||
#include "SchedFlight.hxx"
|
#include "SchedFlight.hxx"
|
||||||
#include "Schedule.hxx"
|
#include "Schedule.hxx"
|
||||||
|
@ -47,15 +67,18 @@ private:
|
||||||
|
|
||||||
string mdl, livery, registration, callsign, fltrules,
|
string mdl, livery, registration, callsign, fltrules,
|
||||||
port, timeString, departurePort, departureTime, arrivalPort, arrivalTime,
|
port, timeString, departurePort, departureTime, arrivalPort, arrivalTime,
|
||||||
repeat, acType, airline, m_class, flighttype;
|
repeat, acType, airline, m_class, flighttype, requiredAircraft, homePort;
|
||||||
int cruiseAlt;
|
int cruiseAlt;
|
||||||
int score, runCount;
|
int score, runCount, acCounter;
|
||||||
double radius, offset;
|
double radius, offset;
|
||||||
bool heavy;
|
bool heavy;
|
||||||
|
|
||||||
IdList releaseList;
|
IdList releaseList;
|
||||||
|
|
||||||
FGScheduledFlightVec flights;
|
FGScheduledFlightMap flights;
|
||||||
|
|
||||||
|
//void readTimeTableFromFile(SGPath infilename);
|
||||||
|
//void Tokenize(const string& str, vector<string>& tokens, const string& delimiters = " ");
|
||||||
|
|
||||||
public:
|
public:
|
||||||
FGTrafficManager();
|
FGTrafficManager();
|
||||||
|
@ -65,6 +88,9 @@ public:
|
||||||
void release(int ref);
|
void release(int ref);
|
||||||
bool isReleased(int id);
|
bool isReleased(int id);
|
||||||
|
|
||||||
|
FGScheduledFlightVecIterator getFirstFlight(const string &ref) { return flights[ref].begin(); }
|
||||||
|
FGScheduledFlightVecIterator getLastFlight(const string &ref) { return flights[ref].end(); }
|
||||||
|
|
||||||
// Some overloaded virtual XMLVisitor members
|
// Some overloaded virtual XMLVisitor members
|
||||||
virtual void startXML ();
|
virtual void startXML ();
|
||||||
virtual void endXML ();
|
virtual void endXML ();
|
||||||
|
|
Loading…
Reference in a new issue