work for ground based distance separation of AIAircraft.
Traffic manager initialization related changes:
- Schedules initialize "on the fly", instead of during initialization
- Invalid routes are no longer deleted, but marked as BOGUS and ignored
- Changed loading order from a distance based prioritization to a point-
score based prioritization, resulting in a much faster establisment of
AIAircraft near the user's plane.
Preparatory work for ground-based separation of Aircraft.
- The groundnetwork findShrortestRoute function not only returns a list
of waypoints, but also a list of taxi "segments" (a.k.a. taxiways).
- The taxiway list is stored in the Flightplan, and updated everytime
a new taxi leg is created.
start_time = 0;
leg = 10;
gateId = 0;
+ taxiRoute = 0;
SGPath path( globals->get_fg_root() );
path.append( ("/AI/FlightPlans/" + filename).c_str() );
SGPropertyNode root;
repeat = false;
leg = 10;
gateId=0;
+ taxiRoute = 0;
start_time = start;
bool useInitialWayPoint = true;
bool useCurrentWayPoint = false;
// delete *(waypoints.begin());
// waypoints.erase (waypoints.begin());
// }
+ if (taxiRoute)
+ delete taxiRoute;
}
int leg;
int gateId;
string activeRunway;
- FGAirRoute route;
+ FGAirRoute airRoute;
+ FGTaxiRoute *taxiRoute;
Point3D temp;
double lat2, lon2, az2;
waypoint *wpt;
+ int nrWaypointsToSkip;
+
if (direction == 1)
{
// If this function is called during initialization,
// fallback mechanism for this.
// Starting from gate 0 in this case is a bit of a hack
// which requires a more proper solution later on.
- FGTaxiRoute route;
+ //FGTaxiRoute route;
+ if (taxiRoute)
+ delete taxiRoute;
+ taxiRoute = new FGTaxiRoute;
if (gateId >= 0)
- route = apt->getDynamics()->getGroundNetwork()->findShortestRoute(gateId,
+ *taxiRoute = apt->getDynamics()->getGroundNetwork()->findShortestRoute(gateId,
runwayId);
else
- route = apt->getDynamics()->getGroundNetwork()->findShortestRoute(0, runwayId);
+ *taxiRoute = apt->getDynamics()->getGroundNetwork()->findShortestRoute(0, runwayId);
intVecIterator i;
- if (route.empty()) {
+ if (taxiRoute->empty()) {
//Add the runway startpoint;
wpt = new waypoint;
wpt->name = "Airport Center";
waypoints.push_back(wpt);
} else {
int node;
- route.first();
+ taxiRoute->first();
bool isPushBackPoint = false;
if (firstFlight) {
// If this is called during initialization, randomly
// skip a number of waypoints to get a more realistic
// taxi situation.
isPushBackPoint = true;
- int nrWaypoints = route.size();
- int nrWaypointsToSkip = rand() % nrWaypoints;
+ int nrWaypoints = taxiRoute->size();
+ nrWaypointsToSkip = rand() % nrWaypoints;
// but make sure we always keep two active waypoints
// to prevent a segmentation fault
for (int i = 0; i < nrWaypointsToSkip-2; i++) {
isPushBackPoint = false;
- route.next(&node);
+ taxiRoute->next(&node);
}
}
else {
//chop off the first two waypoints, because
// those have already been created
// by create pushback
- int size = route.size();
+ int size = taxiRoute->size();
if (size > 2) {
- route.next(&node);
- route.next(&node);
+ taxiRoute->next(&node);
+ taxiRoute->next(&node);
}
}
- while(route.next(&node))
+ while(taxiRoute->next(&node))
{
+ //FGTaxiNode *tn = apt->getDynamics()->getGroundNetwork()->findSegment(node)->getEnd();
FGTaxiNode *tn = apt->getDynamics()->getGroundNetwork()->findNode(node);
//ids.pop_back();
wpt = new waypoint;
wpt->on_ground = true;
waypoints.push_back(wpt);
}
- cerr << endl;
+ //cerr << endl;
+ // finally, rewind the taxiRoute object to the point where we started
+ taxiRoute->first();
+ if (firstFlight) {
+ for (int i = 0; i < nrWaypointsToSkip-2; i++) {
+ taxiRoute->next(&node);
+ }
+ } else {
+ int size = taxiRoute->size();
+ if (size > 2) {
+ taxiRoute->next(&node);
+ taxiRoute->next(&node);
+ }
+ }
}
}
else
// A negative gateId indicates an overflow parking, use a
// fallback mechanism for this.
// Starting from gate 0 is a bit of a hack...
- FGTaxiRoute route;
+ //FGTaxiRoute route;
+ if (taxiRoute)
+ delete taxiRoute;
+ taxiRoute = new FGTaxiRoute;
if (gateId >= 0)
- route = apt->getDynamics()->getGroundNetwork()->findShortestRoute(runwayId,
+ *taxiRoute = apt->getDynamics()->getGroundNetwork()->findShortestRoute(runwayId,
gateId);
else
- route = apt->getDynamics()->getGroundNetwork()->findShortestRoute(runwayId, 0);
+ *taxiRoute = apt->getDynamics()->getGroundNetwork()->findShortestRoute(runwayId, 0);
intVecIterator i;
// No route found: go from gate directly to runway
- if (route.empty()) {
+ if (taxiRoute->empty()) {
//Add the runway startpoint;
wpt = new waypoint;
wpt->name = "Airport Center";
waypoints.push_back(wpt);
} else {
int node;
- route.first();
- int size = route.size();
+ taxiRoute->first();
+ int size = taxiRoute->size();
// Omit the last two waypoints, as
// those are created by createParking()
for (int i = 0; i < size-2; i++)
{
- route.next(&node);
+ taxiRoute->next(&node);
+ //FGTaxiNode *tn = apt->getDynamics()->getGroundNetwork()->findNode(node);
FGTaxiNode *tn = apt->getDynamics()->getGroundNetwork()->findNode(node);
wpt = new waypoint;
wpt->name = "taxiway"; // fixme: should be the name of the taxiway
heading = rwy._heading;
double azimuth = heading + 180.0;
while ( azimuth >= 360.0 ) { azimuth -= 360.0; }
- cerr << "Creating climb at : " << rwy._id << " " << rwy._rwy_no << endl;
+ //cerr << "Creating climb at : " << rwy._id << " " << rwy._rwy_no << endl;
geo_direct_wgs_84 ( 0, rwy._lat, rwy._lon, heading,
10*SG_NM_TO_METER,
&lat2, &lon2, &az2 );
FGAirRoute routePart = globals->get_airwaynet()->findShortestRoute(*i, *j);
if (!(routePart.empty()))
{
- route.add(routePart);
+ airRoute.add(routePart);
i = j;
break;
}
end->getLatitude(),
0);
first.CourseAndDistance(second, &course, &length);
-
}
-bool FGTaxiRoute::next(int *val)
+bool FGTaxiRoute::next(int *nde)
{
//for (intVecIterator i = nodes.begin(); i != nodes.end(); i++)
// cerr << "FGTaxiRoute contains : " << *(i) << endl;
// cerr << "true" << endl;
//else
// cerr << "false" << endl;
+ //if (nodes.size() != (routes.size()) +1)
+ // cerr << "ALERT: Misconfigured TaxiRoute : " << nodes.size() << " " << routes.size() << endl;
if (currNode == nodes.end())
return false;
- *val = *(currNode);
+ *nde = *(currNode);
currNode++;
+ currRoute++;
+ return true;
+};
+
+bool FGTaxiRoute::next(int *nde, int *rte)
+{
+ //for (intVecIterator i = nodes.begin(); i != nodes.end(); i++)
+ // cerr << "FGTaxiRoute contains : " << *(i) << endl;
+ //cerr << "Offset from end: " << nodes.end() - currNode << endl;
+ //if (currNode != nodes.end())
+ // cerr << "true" << endl;
+ //else
+ // cerr << "false" << endl;
+ //if (nodes.size() != (routes.size()) +1)
+ // cerr << "ALERT: Misconfigured TaxiRoute : " << nodes.size() << " " << routes.size() << endl;
+
+ if (currNode == nodes.end())
+ return false;
+ *nde = *(currNode);
+ *rte = *(currRoute);
+ currNode++;
+ currRoute++;
return true;
};
/***************************************************************************
void FGGroundNetwork::init()
{
hasNetwork = true;
+ int index = 0;
FGTaxiSegmentVectorIterator i = segments.begin();
while(i != segments.end()) {
//cerr << "initializing node " << i->getIndex() << endl;
i->setStart(&nodes);
i->setEnd (&nodes);
i->setTrackDistance();
+ i->setIndex(index++);
//cerr << "Track distance = " << i->getLength() << endl;
//cerr << "Track ends at" << i->getEnd()->getIndex() << endl;
i++;
return 0;
}
+FGTaxiSegment *FGGroundNetwork::findSegment(int idx)
+{
+ for (FGTaxiSegmentVectorIterator
+ itr = segments.begin();
+ itr != segments.end(); itr++)
+ {
+ if (itr->getIndex() == idx)
+ return itr->getAddress();
+ }
+ return 0;
+}
+
FGTaxiRoute FGGroundNetwork::findShortestRoute(int start, int end)
{
foundRoute = false;
//prevNode = prevPrevNode = -1;
//prevNode = start;
routes.clear();
- traceStack.clear();
+ nodesStack.clear();
+ routesStack.clear();
+
trace(firstNode, end, 0, 0);
FGTaxiRoute empty;
void FGGroundNetwork::trace(FGTaxiNode *currNode, int end, int depth, double distance)
{
- traceStack.push_back(currNode->getIndex());
+ nodesStack.push_back(currNode->getIndex());
totalDistance += distance;
//cerr << "Starting trace " << depth << " total distance: " << totalDistance<< endl;
//<< currNode->getIndex() << endl;
// So we can add this to the routing table
if (currNode->getIndex() == end)
{
- //cerr << "Found route : " << totalDistance << "" << " " << *(traceStack.end()-1) << endl;
- routes.push_back(FGTaxiRoute(traceStack,totalDistance));
- traceStack.pop_back();
+ //cerr << "Found route : " << totalDistance << "" << " " << *(nodesStack.end()-1) << endl;
+ routes.push_back(FGTaxiRoute(nodesStack,routesStack,totalDistance));
+ nodesStack.pop_back();
+ routesStack.pop_back();
if (!(foundRoute))
maxDistance = totalDistance;
else
// if so, we should step back one level, because it is
// rather rediculous to proceed further from here.
// if the current node has not been encountered before,
- // i should point to traceStack.end()-1; and we can continue
- // if i is not traceStack.end, the previous node was found,
+ // i should point to nodesStack.end()-1; and we can continue
+ // if i is not nodesStack.end, the previous node was found,
// and we should return.
// This only works at trace levels of 1 or higher though
if (depth > 0) {
- intVecIterator i = traceStack.begin();
+ intVecIterator i = nodesStack.begin();
while ((*i) != currNode->getIndex()) {
//cerr << "Route so far : " << (*i) << endl;
i++;
}
- if (i != traceStack.end()-1) {
- traceStack.pop_back();
+ if (i != nodesStack.end()-1) {
+ nodesStack.pop_back();
+ routesStack.pop_back();
totalDistance -= distance;
return;
}
if ((totalDistance > maxDistance) && foundRoute)
{
//cerr << "Stopping rediculously long trace: " << totalDistance << endl;
- traceStack.pop_back();
+ nodesStack.pop_back();
+ routesStack.pop_back();
totalDistance -= distance;
return;
}
i != currNode->getEndRoute();
i++)
{
- //cerr << (*i)->getLenght() << endl;
+ //cerr << (*i)->getLength() << endl;
+ //cerr << (*i)->getIndex() << endl;
+ int idx = (*i)->getIndex();
+ routesStack.push_back((*i)->getIndex());
trace((*i)->getEnd(), end, depth+1, (*i)->getLength());
// {
// // cerr << currNode -> getIndex() << " ";
{
SG_LOG( SG_GENERAL, SG_DEBUG, "4" );
}
- traceStack.pop_back();
+ nodesStack.pop_back();
+ routesStack.pop_back();
totalDistance -= distance;
return;
}
double getLength() { return length; };
int getIndex() { return index; };
+ FGTaxiSegment *getAddress() { return this;};
+
};
typedef vector<int> intVec;
typedef vector<int>::iterator intVecIterator;
+/***************************************************************************************
+ * class FGTaxiRoute
+ **************************************************************************************/
class FGTaxiRoute
{
private:
intVec nodes;
+ intVec routes;
double distance;
intVecIterator currNode;
+ intVecIterator currRoute;
public:
- FGTaxiRoute() { distance = 0; currNode = nodes.begin(); };
- FGTaxiRoute(intVec nds, double dist) { nodes = nds; distance = dist; currNode = nodes.begin();};
+ FGTaxiRoute() { distance = 0; currNode = nodes.begin(); currRoute = routes.begin();};
+ FGTaxiRoute(intVec nds, intVec rts, double dist) {
+ nodes = nds;
+ routes = rts;
+ distance = dist;
+ currNode = nodes.begin();
+ };
bool operator< (const FGTaxiRoute &other) const {return distance < other.distance; };
bool empty () { return nodes.begin() == nodes.end(); };
- bool next(int *val);
+ bool next(int *nde);
+ bool next(int *nde, int *rte);
- void first() { currNode = nodes.begin(); };
+ void first() { currNode = nodes.begin(); currRoute = routes.begin(); };
int size() { return nodes.size(); };
};
FGTaxiNodeVector nodes;
FGTaxiSegmentVector segments;
//intVec route;
- intVec traceStack;
+ intVec nodesStack;
+ intVec routesStack;
TaxiRouteVector routes;
bool foundRoute;
bool exists() { return hasNetwork; };
int findNearestNode(double lat, double lon);
FGTaxiNode *findNode(int idx);
+ FGTaxiSegment *findSegment(int idx);
FGTaxiRoute findShortestRoute(int start, int end);
void trace(FGTaxiNode *, int, int, double dist);
departurePort = globals->get_airports()->search(depId);
if(departurePort == NULL)
{
- cerr << "Could not find " << depId << endl;
+ SG_LOG( SG_GENERAL, SG_WARN, "Traffic manager could not find departure airport : " << depId);
return false;
}
arrivalPort = globals->get_airports()->search(arrId);
if(arrivalPort == NULL)
{
- cerr << "Could not find " << arrId << endl;
+ SG_LOG( SG_GENERAL, SG_WARN, "Traffic manager could not find arrival airort : " << arrId);
return false;
}
# include "config.h"
#endif
+#define BOGUS 0xFFFF
+
#include <stdlib.h>
#include <time.h>
#include <iostream>
radius = 0;
groundOffset = 0;
distanceToUser = 0;
+ score = 0;
}
FGAISchedule::FGAISchedule(string mdl,
string fltpe,
double rad,
double grnd,
+ int scre,
FGScheduledFlightVec flt)
{
modelPath = mdl;
i++)
flights.push_back(FGScheduledFlight((*i)));
AIManagerRef = 0;
+ score = scre;
firstRun = true;
}
radius = other.radius;
groundOffset = other.groundOffset;
flightType = other.flightType;
+ score = other.score;
distanceToUser = other.distanceToUser;
}
// Since time isn't initialized yet when this function is called,
// Find the closest possible airport.
// This should give a reasonable initialization order.
- setClosestDistanceToUser();
+ //setClosestDistanceToUser();
return true;
}
// finally kicks in.
if (firstRun)
{
+ if (init() == false)
+ AIManagerRef = BOGUS;
+
for (FGScheduledFlightVecIterator i = flights.begin();
i != flights.end();
i++)
}
-void FGAISchedule::setClosestDistanceToUser()
-{
+// void FGAISchedule::setClosestDistanceToUser()
+// {
- double course;
- double dist;
+// double course;
+// double dist;
- Point3D temp;
- time_t
- totalTimeEnroute,
- elapsedTimeEnroute;
+// Point3D temp;
+// time_t
+// totalTimeEnroute,
+// elapsedTimeEnroute;
- double userLatitude = fgGetDouble("/position/latitude-deg");
- double userLongitude = fgGetDouble("/position/longitude-deg");
+// double userLatitude = fgGetDouble("/position/latitude-deg");
+// double userLongitude = fgGetDouble("/position/longitude-deg");
- FGAirport *dep;
+// 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;
+// #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;
-}
+// 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;
+// }
double groundOffset;
double distanceToUser;
int AIManagerRef;
+ int score;
bool firstRun;
public:
FGAISchedule(); // constructor
- FGAISchedule(string, string, string, bool, string, string, string, string, double, double, FGScheduledFlightVec); // construct & init
- FGAISchedule(const FGAISchedule &other); // copy constructor
+ FGAISchedule(string, string, string, bool, string, string, string, string, double, double,
+ int, FGScheduledFlightVec); // construct & init
+ FGAISchedule(const FGAISchedule &other); // copy constructor
~FGAISchedule(); //destructor
bool init();
double getSpeed ();
- void setClosestDistanceToUser();
+ //void setClosestDistanceToUser();
void next(); // forces the schedule to move on to the next flight.
time_t getDepartureTime () { return flights.begin()->getDepartureTime (); };
const string& getCallSign () { return flights.begin()->getCallSign (); };
const string& getRegistration () { return registration;};
bool getHeavy () { return heavy; };
- bool operator< (const FGAISchedule &other) const { return (distanceToUser < other.distanceToUser); };
+ // 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); };
//void * getAiRef () { return AIManagerRef; };
//FGAISchedule* getAddress () { return this;};
// More member functions follow later
#include <AIModel/AIFlightPlan.hxx>
#include <AIModel/AIBase.hxx>
#include <Airports/simple.hxx>
-#include <Main/fg_init.hxx> // That's pretty ugly, but I need fgFindAirportID
+#include <Main/fg_init.hxx>
*****************************************************************************/
FGTrafficManager::FGTrafficManager()
{
+ score = 0;
}
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++;
- }
- }
+ //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++;
+ // }
+ // }
//cerr << "Sorting by distance " << endl;
sort(scheduledAircraft.begin(), scheduledAircraft.end());
currAircraft = scheduledAircraft.begin();
{
time_t now = time(NULL) + fgGetLong("/sim/time/warp");
if (scheduledAircraft.size() == 0)
- return;
+ return;
if(currAircraft == scheduledAircraft.end())
{
//cerr << "resetting schedule " << endl;
//cerr << "Pusing back flight " << callsign << endl;
//cerr << callsign << " " << fltrules << " "<< departurePort << " " << arrivalPort << " "
// << cruiseAlt << " " << departureTime<< " "<< arrivalTime << " " << repeat << endl;
+
+ //Prioritize aircraft
+ string apt = fgGetString("/sim/presets/airport-id");
+ //cerr << "Airport information: " << apt << " " << departurePort << " " << arrivalPort << endl;
+ if (departurePort == apt) score++;
flights.push_back(FGScheduledFlight(callsign,
fltrules,
departurePort,
flighttype,
radius,
offset,
+ score,
flights));
while(flights.begin() != flights.end())
flights.pop_back();
+ SG_LOG( SG_GENERAL, SG_BULK, "Reading aircraft : "
+ << registration
+ << " with prioritization score "
+ << score);
+ score = 0;
}
}
port, timeString, departurePort, departureTime, arrivalPort, arrivalTime,
repeat, acType, airline, m_class, flighttype;
int cruiseAlt;
+ int score;
double radius, offset;
bool heavy;