time_t start_time;
int leg;
int gateId;
+ string activeRunway;
void createPushBack(bool, FGAirport*, double, double, double, string, string, string);
- void createTaxi(bool, int, FGAirport *, double, string, string, string);
+ void createTaxi(bool, int, FGAirport *, double, double, double, string, string, string);
void createTakeOff(bool, FGAirport *, double);
void createClimb(bool, FGAirport *, double, double);
void createCruise(bool, FGAirport*, FGAirport*, double, double, double, double);
break;
case 2:
//cerr << "Creating Taxi" << endl;
- createTaxi(firstFlight, 1, dep, radius, fltType, aircraftType, airline);
+ createTaxi(firstFlight, 1, dep, latitude, longitude, radius, fltType, aircraftType, airline);
break;
case 3:
//cerr << "Creating TAkeoff" << endl;
break;
case 8:
//cerr << "Creating Taxi 2" << endl;
- createTaxi(false, 2, arr, radius, fltType, aircraftType, airline);
+ createTaxi(false, 2, arr, latitude, longitude, radius, fltType, aircraftType, airline);
break;
case 9:
//cerr << "Creating Parking" << endl;
wpt->on_ground = true;
waypoints.push_back(wpt);
geo_direct_wgs_84 ( 0, lat, lon, heading,
- 100,
+ radius, // push back one entire aircraft radius
&lat2, &lon2, &az2 );
wpt = new waypoint;
wpt->name = "taxiStart";
wpt->on_ground = true;
waypoints.push_back(wpt);
- //wpt = new waypoint;
- //wpt->name = "END";
- //wpt->finished = false;
- //waypoints.push_back(wpt); // add one more to prevent a segfault.
- //waypoints.push_back(wpt); // add one more to prevent a segfault.
- //wpt_iterator = waypoints.begin();
- //if (!firstFlight)
- // wpt_iterator++;
- //wpt_iterator = waypoints.begin()+currWpt;
+
}
/*******************************************************************
* createCreate Taxi.
* initialize the Aircraft at the parking location
******************************************************************/
-void FGAIFlightPlan::createTaxi(bool firstFlight, int direction, FGAirport *apt, double radius, string fltType, string acType, string airline)
+void FGAIFlightPlan::createTaxi(bool firstFlight, int direction, FGAirport *apt, double latitude, double longitude, double radius, string fltType, string acType, string airline)
{
double wind_speed;
double wind_heading;
//int currWpt = wpt_iterator - waypoints.begin();
if (direction == 1)
{
-
-
-
-
- // Get the current active runway, based on code from David Luff
- // This should actually be unified and extended to include
- // Preferential runway use schema's
- //FGEnvironment
- //stationweather = ((FGEnvironmentMgr *) globals->get_subsystem("environment"))
- //->getEnvironment(apt->getLatitude(), apt->getLongitude(), apt->getElevation());
-
- //wind_speed = stationweather.get_wind_speed_kt();
- //wind_heading = stationweather.get_wind_from_heading_deg();
- //if (wind_speed == 0) {
- //wind_heading = 270; // This forces West-facing rwys to be used in no-wind situations
- // which is consistent with Flightgear's initial setup.
- //}
-
- //string rwy_no = globals->get_runways()->search(apt->getId(), int(wind_heading));
- string name;
- apt->getActiveRunway("com", 1, &name);
+ //string name;
+ // "NOTE: this is currently fixed to "com" for commercial traffic
+ // Should be changed to be used dynamically to allow "gen" and "mil"
+ // as well
+ apt->getActiveRunway("com", 1, &activeRunway);
if (!(globals->get_runways()->search(apt->getId(),
- name,
+ activeRunway,
&rwy)))
{
cout << "Failed to find runway for " << apt->getId() << endl;
geo_direct_wgs_84 ( 0, rwy._lat, rwy._lon, azimuth,
rwy._length * SG_FEET_TO_METER * 0.5 - 5.0,
&lat2, &lon2, &az2 );
-
- //Add the runway startpoint;
- wpt = new waypoint;
- wpt->name = "Airport Center";
- wpt->latitude = apt->getLatitude();
- wpt->longitude = apt->getLongitude();
- wpt->altitude = apt->getElevation();
- wpt->speed = 15;
- wpt->crossat = -10000;
- wpt->gear_down = true;
- wpt->flaps_down= true;
- wpt->finished = false;
- wpt->on_ground = true;
- waypoints.push_back(wpt);
-
- //Add the runway startpoint;
- wpt = new waypoint;
- wpt->name = "Runway Takeoff";
- wpt->latitude = lat2;
- wpt->longitude = lon2;
- wpt->altitude = apt->getElevation();
- wpt->speed = 15;
- wpt->crossat = -10000;
- wpt->gear_down = true;
- wpt->flaps_down= true;
- wpt->finished = false;
- wpt->on_ground = true;
- waypoints.push_back(wpt);
- //wpt = new waypoint;
- //wpt->finished = false;
- //waypoints.push_back(wpt); // add one more to prevent a segfault.
+ if (apt->getGroundNetwork()->exists())
+ {
+ intVec ids;
+ int runwayId = apt->getGroundNetwork()->findNearestNode(lat2, lon2);
+ //int currId = apt->getGroundNetwork()->findNearestNode(latitude,longitude);
+ //exit(1);
+
+ // 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;
+ if (gateId >= 0)
+ route = apt->getGroundNetwork()->findShortestRoute(gateId, runwayId);
+ else
+ route = apt->getGroundNetwork()->findShortestRoute(0, runwayId);
+ intVecIterator i;
+ //cerr << "creating route : ";
+ // No route found: go from gate directly to runway
+ if (route.empty()) {
+ //Add the runway startpoint;
+ wpt = new waypoint;
+ wpt->name = "Airport Center";
+ wpt->latitude = latitude;
+ wpt->longitude = longitude;
+ wpt->altitude = apt->getElevation();
+ wpt->speed = 15;
+ wpt->crossat = -10000;
+ wpt->gear_down = true;
+ wpt->flaps_down= true;
+ wpt->finished = false;
+ wpt->on_ground = true;
+ waypoints.push_back(wpt);
+
+ //Add the runway startpoint;
+ wpt = new waypoint;
+ wpt->name = "Runway Takeoff";
+ wpt->latitude = lat2;
+ wpt->longitude = lon2;
+ wpt->altitude = apt->getElevation();
+ wpt->speed = 15;
+ wpt->crossat = -10000;
+ wpt->gear_down = true;
+ wpt->flaps_down= true;
+ wpt->finished = false;
+ wpt->on_ground = true;
+ waypoints.push_back(wpt);
+ } else {
+ int node;
+ route.first();
+ while(route.next(&node))
+ {
+ //i = ids.end()-1;
+ //cerr << "Creating Node: " << node << endl;
+ FGTaxiNode *tn = apt->getGroundNetwork()->findNode(node);
+ //ids.pop_back();
+ wpt = new waypoint;
+ wpt->name = "taxiway"; // fixme: should be the name of the taxiway
+ wpt->latitude = tn->getLatitude();
+ wpt->longitude = tn->getLongitude();
+ wpt->altitude = apt->getElevation(); // should maybe be tn->elev too
+ wpt->speed = 15;
+ wpt->crossat = -10000;
+ wpt->gear_down = true;
+ wpt->flaps_down= true;
+ wpt->finished = false;
+ wpt->on_ground = true;
+ waypoints.push_back(wpt);
+ }
+ cerr << endl;
+ }
+ //exit(1);
+ }
+ else
+ {
+ //Add the runway startpoint;
+ wpt = new waypoint;
+ wpt->name = "Airport Center";
+ wpt->latitude = apt->getLatitude();
+ wpt->longitude = apt->getLongitude();
+ wpt->altitude = apt->getElevation();
+ wpt->speed = 15;
+ wpt->crossat = -10000;
+ wpt->gear_down = true;
+ wpt->flaps_down= true;
+ wpt->finished = false;
+ wpt->on_ground = true;
+ waypoints.push_back(wpt);
+
+ //Add the runway startpoint;
+ wpt = new waypoint;
+ wpt->name = "Runway Takeoff";
+ wpt->latitude = lat2;
+ wpt->longitude = lon2;
+ wpt->altitude = apt->getElevation();
+ wpt->speed = 15;
+ wpt->crossat = -10000;
+ wpt->gear_down = true;
+ wpt->flaps_down= true;
+ wpt->finished = false;
+ wpt->on_ground = true;
+ waypoints.push_back(wpt);
+ //wpt = new waypoint;
+ //wpt->finished = false;
+ //waypoints.push_back(wpt); // add one more to prevent a segfault.
+ }
}
- else
+ else // Landing taxi
{
- //direction = (rand() % 360);
- //geo_direct_wgs_84 ( 0, arr->getLatitude(), arr->getLongitude(), direction,
- //100,
- //&lat2, &lon2, &az2 );
+ //string name;
+ // "NOTE: this is currently fixed to "com" for commercial traffic
+ // Should be changed to be used dynamically to allow "gen" and "mil"
+ // as well
+ //apt->getActiveRunway("com", 1, &name);
+ //if (!(globals->get_runways()->search(apt->getId(),
+ // name,
+ // &rwy)))
+ //{//
+ //cout << "Failed to find runway for " << apt->getId() << endl;
+ // Hmm, how do we handle a potential error like this?
+ // exit(1);
+ // }
+ //string test;
+ //apt->getActiveRunway(string("com"), 1, &test);
+ //exit(1);
- // This next statement really requires the flight plan to be
- // split up into smaller sections, because
- // gate assignments will typically not be known until minutes before
- // landing, and certainly not at the start of a 10 hour flight.
+ //heading = rwy._heading;
+ //double azimuth = heading + 180.0;
+ //while ( azimuth >= 360.0 ) { azimuth -= 360.0; }
+ //geo_direct_wgs_84 ( 0, rwy._lat, rwy._lon, azimuth,
+ // rwy._length * SG_FEET_TO_METER * 0.5 - 5.0,
+ // &lat2, &lon2, &az2 );
apt->getAvailableParking(&lat, &lon, &heading, &gateId, radius, fltType, acType, airline);
heading += 180.0;
if (heading > 360)
geo_direct_wgs_84 ( 0, lat, lon, heading,
100,
&lat2, &lon2, &az2 );
- //Add the runway center
- wpt = new waypoint;
- wpt->name = "Airport Center";
- wpt->latitude = apt->getLatitude();
- wpt->longitude = apt->getLongitude();
- wpt->altitude = apt->getElevation();
- wpt->speed = 15;
- wpt->crossat = -10000;
- wpt->gear_down = true;
- wpt->flaps_down= true;
- wpt->finished = false;
- wpt->on_ground = true;
- waypoints.push_back(wpt);
+ double lat3 = (*(waypoints.end()-1))->latitude;
+ double lon3 = (*(waypoints.end()-1))->longitude;
+ cerr << (*(waypoints.end()-1))->name << endl;
+ if (apt->getGroundNetwork()->exists())
+ {
+ intVec ids;
+ int runwayId = apt->getGroundNetwork()->findNearestNode(lat3, lon3);
+ //int currId = apt->getGroundNetwork()->findNearestNode(latitude,longitude);
+ //exit(1);
+
+ // 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;
+ if (gateId >= 0)
+ route = apt->getGroundNetwork()->findShortestRoute(runwayId, gateId);
+ else
+ route = apt->getGroundNetwork()->findShortestRoute(runwayId, 0);
+ intVecIterator i;
+ //cerr << "creating route : ";
+ // No route found: go from gate directly to runway
+ if (route.empty()) {
+ //Add the runway startpoint;
+ wpt = new waypoint;
+ wpt->name = "Airport Center";
+ wpt->latitude = latitude;
+ wpt->longitude = longitude;
+ wpt->altitude = apt->getElevation();
+ wpt->speed = 15;
+ wpt->crossat = -10000;
+ wpt->gear_down = true;
+ wpt->flaps_down= true;
+ wpt->finished = false;
+ wpt->on_ground = true;
+ waypoints.push_back(wpt);
+
+ //Add the runway startpoint;
+ wpt = new waypoint;
+ wpt->name = "Runway Takeoff";
+ wpt->latitude = lat2;
+ wpt->longitude = lon2;
+ wpt->altitude = apt->getElevation();
+ wpt->speed = 15;
+ wpt->crossat = -10000;
+ wpt->gear_down = true;
+ wpt->flaps_down= true;
+ wpt->finished = false;
+ wpt->on_ground = true;
+ waypoints.push_back(wpt);
+ } else {
+ int node;
+ route.first();
+ while(route.next(&node))
+ {
+ //i = ids.end()-1;
+ //cerr << "Creating Node: " << node << endl;
+ FGTaxiNode *tn = apt->getGroundNetwork()->findNode(node);
+ //ids.pop_back();
+ wpt = new waypoint;
+ wpt->name = "taxiway"; // fixme: should be the name of the taxiway
+ wpt->latitude = tn->getLatitude();
+ wpt->longitude = tn->getLongitude();
+ wpt->altitude = apt->getElevation(); // should maybe be tn->elev too
+ wpt->speed = 15;
+ wpt->crossat = -10000;
+ wpt->gear_down = true;
+ wpt->flaps_down= true;
+ wpt->finished = false;
+ wpt->on_ground = true;
+ waypoints.push_back(wpt);
+ }
+ cerr << endl;
+ }
+ //exit(1);
+ }
+ else
+ {
+ //Add the runway startpoint;
+ wpt = new waypoint;
+ wpt->name = "Airport Center";
+ wpt->latitude = apt->getLatitude();
+ wpt->longitude = apt->getLongitude();
+ wpt->altitude = apt->getElevation();
+ wpt->speed = 15;
+ wpt->crossat = -10000;
+ wpt->gear_down = true;
+ wpt->flaps_down= true;
+ wpt->finished = false;
+ wpt->on_ground = true;
+ waypoints.push_back(wpt);
+
+ }
+
+
+
// Add the final destination waypoint
wpt = new waypoint;
- wpt->name = "Begin Parkingg"; //apt->getId(); //wpt_node->getStringValue("name", "END");
+ wpt->name = "Begin Parking"; //apt->getId(); //wpt_node->getStringValue("name", "END");
wpt->latitude = lat2;
wpt->longitude = lon2;
wpt->altitude = apt->getElevation();
// Preferential runway use schema's
if (firstFlight)
{
- string name;
- apt->getActiveRunway("com", 1, &name);
+ //string name;
+ // "NOTE: this is currently fixed to "com" for commercial traffic
+ // Should be changed to be used dynamically to allow "gen" and "mil"
+ // as well
+ apt->getActiveRunway("com", 1, &activeRunway);
if (!(globals->get_runways()->search(apt->getId(),
- name,
+ activeRunway,
&rwy)))
{
cout << "Failed to find runway for " << apt->getId() << endl;
// Preferential runway use schema's
if (firstFlight)
{
- string name;
- apt->getActiveRunway("com", 1, &name);
+ //string name;
+ // "NOTE: this is currently fixed to "com" for commercial traffic
+ // Should be changed to be used dynamically to allow "gen" and "mil"
+ // as well
+ apt->getActiveRunway("com", 1, &activeRunway);
if (!(globals->get_runways()->search(apt->getId(),
- name,
+ activeRunway,
&rwy)))
{
cout << "Failed to find runway for " << apt->getId() << endl;
waypoints.push_back(wpt);
//Beginning of Decent
- string name;
- arr->getActiveRunway("com", 2, &name);
+ //string name;
+ // should be changed dynamically to allow "gen" and "mil"
+ arr->getActiveRunway("com", 2, &activeRunway);
if (!(globals->get_runways()->search(arr->getId(),
- name,
+ activeRunway,
&rwy)))
{
cout << "Failed to find runway for " << arr->getId() << endl;
//resetWaypoints();
//Beginning of Decent
- string name;
- apt->getActiveRunway("com", 2, &name);
+ //string name;
+ // allow "mil" and "gen" as well
+ apt->getActiveRunway("com", 2, &activeRunway);
if (!(globals->get_runways()->search(apt->getId(),
- name,
+ activeRunway,
&rwy)))
{
cout << "Failed to find runway for " << apt->getId() << endl;
#include <simgear/compiler.h>
#include <plib/sg.h>
+#include <plib/ul.h>
#include <Environment/environment_mgr.hxx>
#include <Environment/environment.hxx>
#include "simple.hxx"
SG_USING_STD(sort);
+SG_USING_STD(random_shuffle);
/******************************************************************************
* ScheduleTime
<< endl;
}
-/*********************************************************************************
- * FGParking
- ********************************************************************************/
-FGParking::FGParking(double lat,
- double lon,
- double hdg,
- double rad,
- int idx,
- string name,
- string tpe,
- string codes)
-{
- latitude = lat;
- longitude = lon;
- heading = hdg;
- parkingName = name;
- index = idx;
- type = tpe;
- airlineCodes = codes;
-}
-
-double FGParking::processPosition(string pos)
+/*****************************************************************************
+ * Helper function for parsing position string
+ ****************************************************************************/
+double processPosition(string pos)
{
string prefix;
string subs;
return value;
}
+
+/*********************************************************************************
+ * FGParking
+ ********************************************************************************/
+FGParking::FGParking(double lat,
+ double lon,
+ double hdg,
+ double rad,
+ int idx,
+ string name,
+ string tpe,
+ string codes)
+{
+ latitude = lat;
+ longitude = lon;
+ heading = hdg;
+ parkingName = name;
+ index = idx;
+ type = tpe;
+ airlineCodes = codes;
+}
+
+
/***************************************************************************
* FGAirport
***************************************************************************/
}
+// Initialization required after XMLRead
+void FGAirport::init()
+{
+ // This may seem a bit weird to first randomly shuffle the parkings
+ // and then sort them again. However, parkings are sorted here by ascending
+ // radius. Since many parkings have similar radii, with each radius class they will
+ // still be allocated relatively systematically. Randomizing prior to sorting will
+ // prevent any initial orderings to be destroyed, leading (hopefully) to a more
+ // naturalistic gate assignment.
+ random_shuffle(parkings.begin(), parkings.end());
+ sort(parkings.begin(), parkings.end());
+ // add the gate positions to the ground network.
+ groundNetwork.addNodes(&parkings);
+ groundNetwork.init();
+}
+
bool FGAirport::getAvailableParking(double *lat, double *lon, double *heading, int *gateId, double rad, string flType, string acType, string airline)
{
bool found = false;
void FGAirport::startElement (const char * name, const XMLAttributes &atts) {
// const char *attval;
FGParking park;
+ FGTaxiNode taxiNode;
+ FGTaxiSegment taxiSegment;
+ int index = 0;
+ taxiSegment.setIndex(index);
//cout << "Start element " << name << endl;
string attname;
string value;
}
park.setName((gateName+gateNumber));
parkings.push_back(park);
- }
+ }
+ if (name == string("node"))
+ {
+ for (int i = 0; i < atts.size() ; i++)
+ {
+ attname = atts.getName(i);
+ if (attname == string("index"))
+ taxiNode.setIndex(atoi(atts.getValue(i)));
+ if (attname == string("lat"))
+ taxiNode.setLatitude(atts.getValue(i));
+ if (attname == string("lon"))
+ taxiNode.setLongitude(atts.getValue(i));
+ }
+ groundNetwork.addNode(taxiNode);
+ }
+ if (name == string("arc"))
+ {
+ taxiSegment.setIndex(++index);
+ for (int i = 0; i < atts.size() ; i++)
+ {
+ attname = atts.getName(i);
+ if (attname == string("begin"))
+ taxiSegment.setStartNodeRef(atoi(atts.getValue(i)));
+ if (attname == string("end"))
+ taxiSegment.setEndNodeRef(atoi(atts.getValue(i)));
+ }
+ groundNetwork.addSegment(taxiSegment);
+ }
// sort by radius, in asending order, so that smaller gates are first in the list
- sort(parkings.begin(), parkings.end());
}
void FGAirport::endElement (const char * name) {
return; // generic fall back goes here
}
+
+
+/**************************************************************************
+ * FGTaxiNode
+ *************************************************************************/
+FGTaxiNode::FGTaxiNode()
+{
+}
+
+/***************************************************************************
+ * FGTaxiSegment
+ **************************************************************************/
+FGTaxiSegment::FGTaxiSegment()
+{
+}
+
+void FGTaxiSegment::setStart(FGTaxiNodeVector *nodes)
+{
+ FGTaxiNodeVectorIterator i = nodes->begin();
+ while (i != nodes->end())
+ {
+ if (i->getIndex() == startNode)
+ {
+ start = i->getAddress();
+ i->addSegment(this);
+ return;
+ }
+ i++;
+ }
+}
+
+void FGTaxiSegment::setEnd(FGTaxiNodeVector *nodes)
+{
+ FGTaxiNodeVectorIterator i = nodes->begin();
+ while (i != nodes->end())
+ {
+ if (i->getIndex() == endNode)
+ {
+ end = i->getAddress();
+ return;
+ }
+ i++;
+ }
+}
+
+// There is probably a computationally cheaper way of
+// doing this.
+void FGTaxiSegment::setTrackDistance()
+{
+ double course;
+ SGWayPoint first (start->getLongitude(),
+ start->getLatitude(),
+ 0);
+ SGWayPoint second (end->getLongitude(),
+ end->getLatitude(),
+ 0);
+ first.CourseAndDistance(second, &course, &length);
+
+}
+
+bool FGTaxiRoute::next(int *val)
+{
+ //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 (currNode == nodes.end())
+ return false;
+ *val = *(currNode);
+ currNode++;
+ return true;
+};
+/***************************************************************************
+ * FGGroundNetwork()
+ **************************************************************************/
+
+FGGroundNetwork::FGGroundNetwork()
+{
+ hasNetwork = false;
+}
+
+void FGGroundNetwork::addSegment(FGTaxiSegment seg)
+{
+ segments.push_back(seg);
+}
+
+void FGGroundNetwork::addNode(FGTaxiNode node)
+{
+ nodes.push_back(node);
+}
+
+void FGGroundNetwork::addNodes(FGParkingVec *parkings)
+{
+ FGTaxiNode n;
+ FGParkingVecIterator i = parkings->begin();
+ while (i != parkings->end())
+ {
+ n.setIndex(i->getIndex());
+ n.setLatitude(i->getLatitude());
+ n.setLongitude(i->getLongitude());
+ nodes.push_back(n);
+
+ i++;
+ }
+}
+
+
+
+void FGGroundNetwork::init()
+{
+ hasNetwork = true;
+ FGTaxiSegmentVectorIterator i = segments.begin();
+ while(i != segments.end()) {
+ //cerr << "initializing node " << i->getIndex() << endl;
+ i->setStart(&nodes);
+ i->setEnd (&nodes);
+ i->setTrackDistance();
+ //cerr << "Track distance = " << i->getLength() << endl;
+ //cerr << "Track ends at" << i->getEnd()->getIndex() << endl;
+ i++;
+ }
+ //exit(1);
+}
+
+int FGGroundNetwork::findNearestNode(double lat, double lon)
+{
+ double minDist = HUGE;
+ double course, dist;
+ int index;
+ SGWayPoint first (lon,
+ lat,
+ 0);
+
+ for (FGTaxiNodeVectorIterator
+ itr = nodes.begin();
+ itr != nodes.end(); itr++)
+ {
+ double course;
+ SGWayPoint second (itr->getLongitude(),
+ itr->getLatitude(),
+ 0);
+ first.CourseAndDistance(second, &course, &dist);
+ if (dist < minDist)
+ {
+ minDist = dist;
+ index = itr->getIndex();
+ //cerr << "Minimum distance of " << minDist << " for index " << index << endl;
+ }
+ }
+ return index;
+}
+
+FGTaxiNode *FGGroundNetwork::findNode(int idx)
+{
+ for (FGTaxiNodeVectorIterator
+ itr = nodes.begin();
+ itr != nodes.end(); itr++)
+ {
+ if (itr->getIndex() == idx)
+ return itr->getAddress();
+ }
+ return 0;
+}
+
+FGTaxiRoute FGGroundNetwork::findShortestRoute(int start, int end)
+{
+ foundRoute = false;
+ totalDistance = 0;
+ FGTaxiNode *firstNode = findNode(start);
+ FGTaxiNode *lastNode = findNode(end);
+ //prevNode = prevPrevNode = -1;
+ //prevNode = start;
+ routes.clear();
+ traceStack.clear();
+ trace(firstNode, end, 0, 0);
+ FGTaxiRoute empty;
+
+ if (!foundRoute)
+ {
+ cerr << "Failed to find route from waypoint " << start << " to " << end << endl;
+ exit(1);
+ }
+ sort(routes.begin(), routes.end());
+ //for (intVecIterator i = route.begin(); i != route.end(); i++)
+ // {
+ // rte->push_back(*i);
+ // }
+
+ if (routes.begin() != routes.end())
+ return *(routes.begin());
+ else
+ return empty;
+}
+
+
+void FGGroundNetwork::trace(FGTaxiNode *currNode, int end, int depth, double distance)
+{
+ traceStack.push_back(currNode->getIndex());
+ totalDistance += distance;
+ //cerr << "Starting trace " << depth << " total distance: " << totalDistance<< endl;
+ //<< currNode->getIndex() << endl;
+
+ // If the current route matches the required end point we found a valid route
+ // 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();
+ if (!(foundRoute))
+ maxDistance = totalDistance;
+ else
+ if (totalDistance < maxDistance)
+ maxDistance = totalDistance;
+ foundRoute = true;
+ totalDistance -= distance;
+ return;
+ }
+
+
+ // search if the currentNode has been encountered before
+ // 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,
+ // and we should return.
+ // This only works at trace levels of 1 or higher though
+ if (depth > 0) {
+ intVecIterator i = traceStack.begin();
+ while ((*i) != currNode->getIndex()) {
+ //cerr << "Route so far : " << (*i) << endl;
+ i++;
+ }
+ if (i != traceStack.end()-1) {
+ traceStack.pop_back();
+ totalDistance -= distance;
+ return;
+ }
+ // If the total distance from start to the current waypoint
+ // is longer than that of a route we can also stop this trace
+ // and go back one level.
+ if ((totalDistance > maxDistance) && foundRoute)
+ {
+ //cerr << "Stopping rediculously long trace: " << totalDistance << endl;
+ traceStack.pop_back();
+ totalDistance -= distance;
+ return;
+ }
+ }
+
+ //cerr << "2" << endl;
+ if (currNode->getBeginRoute() != currNode->getEndRoute())
+ {
+ //cerr << "3" << endl;
+ for (FGTaxiSegmentPointerVectorIterator
+ i = currNode->getBeginRoute();
+ i != currNode->getEndRoute();
+ i++)
+ {
+ //cerr << (*i)->getLenght() << endl;
+ trace((*i)->getEnd(), end, depth+1, (*i)->getLength());
+ // {
+ // // cerr << currNode -> getIndex() << " ";
+ // route.push_back(currNode->getIndex());
+ // return true;
+ // }
+ }
+ }
+ else
+ {
+ cerr << "4" << endl;
+ }
+ traceStack.pop_back();
+ totalDistance -= distance;
+ return;
+}
+
+
+
/******************************************************************************
* FGAirportList
*****************************************************************************/
{
try {
readXML(parkpath.str(),*a);
+ a->init();
}
catch (const sg_exception &e) {
//cerr << "unable to read " << parkpath.str() << endl;
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
-
+#include <simgear/math/point3d.hxx>
+#include <simgear/route/waypoint.hxx>
#include <simgear/compiler.h>
#include <simgear/xml/easyxml.hxx>
typedef vector<time_t> timeVec;
typedef vector<time_t>::const_iterator timeVecConstIterator;
+
+
/***************************************************************************/
class ScheduleTime {
private:
virtual void error (const char * message, int line, int column);
};
+double processPosition(string pos);
+
class FGParking {
private:
double latitude;
string type;
string airlineCodes;
-
bool available;
- double processPosition(string pos);
+
public:
FGParking() { available = true;};
typedef vector<FGParking>::iterator FGParkingVecIterator;
typedef vector<FGParking>::const_iterator FGParkingVecConstIterator;
+class FGTaxiSegment; // forward reference
+
+typedef vector<FGTaxiSegment> FGTaxiSegmentVector;
+typedef vector<FGTaxiSegment*> FGTaxiSegmentPointerVector;
+typedef vector<FGTaxiSegment>::iterator FGTaxiSegmentVectorIterator;
+typedef vector<FGTaxiSegment*>::iterator FGTaxiSegmentPointerVectorIterator;
+
+/**************************************************************************************
+ * class FGTaxiNode
+ *************************************************************************************/
+class FGTaxiNode
+{
+private:
+ double lat;
+ double lon;
+ int index;
+ FGTaxiSegmentPointerVector next; // a vector to all the segments leaving from this node
+
+public:
+ FGTaxiNode();
+ FGTaxiNode(double, double, int);
+
+ void setIndex(int idx) { index = idx;};
+ void setLatitude (double val) { lat = val;};
+ void setLongitude(double val) { lon = val;};
+ void setLatitude (string val) { lat = processPosition(val); };
+ void setLongitude(string val) { lon = processPosition(val); };
+ void addSegment(FGTaxiSegment *segment) { next.push_back(segment); };
+
+ double getLatitude() { return lat;};
+ double getLongitude(){ return lon;};
+
+ int getIndex() { return index; };
+ FGTaxiNode *getAddress() { return this;};
+ FGTaxiSegmentPointerVectorIterator getBeginRoute() { return next.begin(); };
+ FGTaxiSegmentPointerVectorIterator getEndRoute() { return next.end(); };
+};
+
+typedef vector<FGTaxiNode> FGTaxiNodeVector;
+typedef vector<FGTaxiNode>::iterator FGTaxiNodeVectorIterator;
+
+/***************************************************************************************
+ * class FGTaxiSegment
+ **************************************************************************************/
+class FGTaxiSegment
+{
+private:
+ int startNode;
+ int endNode;
+ double length;
+ FGTaxiNode *start;
+ FGTaxiNode *end;
+ int index;
+
+public:
+ FGTaxiSegment();
+ FGTaxiSegment(FGTaxiNode *, FGTaxiNode *, int);
+
+ void setIndex (int val) { index = val; };
+ void setStartNodeRef (int val) { startNode = val; };
+ void setEndNodeRef (int val) { endNode = val; };
+ void setStart(FGTaxiNodeVector *nodes);
+ void setEnd (FGTaxiNodeVector *nodes);
+ void setTrackDistance();
+
+ FGTaxiNode * getEnd() { return end;};
+ double getLength() { return length; };
+ int getIndex() { return index; };
+
+
+};
+
+
+typedef vector<int> intVec;
+typedef vector<int>::iterator intVecIterator;
+
+class FGTaxiRoute
+{
+private:
+ intVec nodes;
+ double distance;
+ intVecIterator currNode;
+
+public:
+ FGTaxiRoute() { distance = 0; currNode = nodes.begin(); };
+ FGTaxiRoute(intVec nds, double dist) { nodes = nds; 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);
+
+ void first() { currNode = nodes.begin(); };
+};
+
+typedef vector<FGTaxiRoute> TaxiRouteVector;
+typedef vector<FGTaxiRoute>::iterator TaxiRouteVectorIterator;
+
+/**************************************************************************************
+ * class FGGroundNetWork
+ *************************************************************************************/
+class FGGroundNetwork
+{
+private:
+ bool hasNetwork;
+ FGTaxiNodeVector nodes;
+ FGTaxiSegmentVector segments;
+ //intVec route;
+ intVec traceStack;
+ TaxiRouteVector routes;
+
+ bool foundRoute;
+ double totalDistance, maxDistance;
+
+public:
+ FGGroundNetwork();
+
+ void addNode (FGTaxiNode node);
+ void addNodes (FGParkingVec *parkings);
+ void addSegment(FGTaxiSegment seg);
+
+ void init();
+ bool exists() { return hasNetwork; };
+ int findNearestNode(double lat, double lon);
+ FGTaxiNode *findNode(int idx);
+ FGTaxiRoute findShortestRoute(int start, int end);
+ void trace(FGTaxiNode *, int, int, double dist);
+
+};
+
+/***************************************************************************************
+ *
+ **************************************************************************************/
class FGAirport : public XMLVisitor{
private:
string _id;
bool _has_metar;
FGParkingVec parkings;
FGRunwayPreference rwyPrefs;
+ FGGroundNetwork groundNetwork;
time_t lastUpdate;
string prevTrafficType;
FGAirport(const FGAirport &other);
//operator= (FGAirport &other);
FGAirport(string id, double lon, double lat, double elev, string name, bool has_metar);
+
+ void init();
void getActiveRunway(string trafficType, int action, string *runway);
void chooseRunwayFallback(string *runway);
bool getAvailableParking(double *lat, double *lon, double *heading, int *gate, double rad, string fltype,
string getParkingName(int i);
string getId() const { return _id;};
const string &getName() const { return _name;};
+ //FGAirport *getAddress() { return this; };
+ //const string &getName() const { return _name;};
// Returns degrees
double getLongitude() const { return _longitude;};
// Returns degrees
// Returns ft
double getElevation() const { return _elevation;};
bool getMetar() const { return _has_metar;};
+ FGGroundNetwork* getGroundNetwork() { return &groundNetwork; };
void setId(string id) { _id = id;};
const double elevation, const string name, const bool has_metar );
// search for the specified id.
- // Returns NULL if unsucessfull.
+ // Returns NULL if unsucessfull.
FGAirport* search( const string& id );
// Search for the next airport in ASCII sequence to the supplied id.
return true;
}
}
-
+ //cerr << "Traffic schedule got to beyond last clause" << endl;
// EMH: prevent a warning, should this be 'true' instead?
- return false;
+ // DT: YES. Originally, this code couldn't be reached, but
+ // when the "if(!(AIManagerManager))" clause is false we
+ // fall through right to the end. This is a valid flow.
+ // the actual value is pretty innocent, only it triggers
+ // warning in TrafficManager::update().
+ // (which was added as a sanity check for myself in the first place. :-)
+ return true;
}