1
0
Fork 0

Durk Talsma:

Auf Niederlandisch:
Bij deze de patch voor de taxiway code. Deze code is nog gebaseerd
op de bestaaande architectuur, gebaseerd op de FGAirport class in simple.[ch]xx
Ik heb me voornamelijk gericht op nieuwe functionaliteit; de volgende
submissie zal waarschijnlijk bestaan uit opschoning, opsplitsing en een
implementatie van de nieuwe airport architectuur, zoals voorgesteld door
David Luff.

En Anglais:
Here is the patch for the taxiway code. This code is still based on the
exsisting architecture, which is based on the FGAirport class in simple.[ch]xx
I've aimed mostly at new functionality; The next batch will probably contain
code cleanups, splitups and the implementation fo the new airport architecture,
as proposed by David Luff.
This commit is contained in:
ehofman 2005-10-18 18:44:37 +00:00
parent 13945c6cd4
commit 54594e5219
5 changed files with 772 additions and 132 deletions

View file

@ -104,9 +104,10 @@ private:
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);

View file

@ -50,7 +50,7 @@ void FGAIFlightPlan::create(FGAirport *dep, FGAirport *arr, int legNr, double al
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;
@ -74,7 +74,7 @@ void FGAIFlightPlan::create(FGAirport *dep, FGAirport *arr, int legNr, double al
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;
@ -161,7 +161,7 @@ void FGAIFlightPlan::createPushBack(bool firstFlight, FGAirport *dep,
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";
@ -176,22 +176,14 @@ void FGAIFlightPlan::createPushBack(bool firstFlight, FGAirport *dep,
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;
@ -208,29 +200,13 @@ void FGAIFlightPlan::createTaxi(bool firstFlight, int direction, FGAirport *apt,
//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;
@ -247,49 +223,137 @@ void FGAIFlightPlan::createTaxi(bool firstFlight, int direction, FGAirport *apt,
geo_direct_wgs_84 ( 0, rwy._lat, rwy._lon, azimuth,
rwy._length * SG_FEET_TO_METER * 0.5 - 5.0,
&lat2, &lon2, &az2 );
if (apt->getGroundNetwork()->exists())
{
intVec ids;
int runwayId = apt->getGroundNetwork()->findNearestNode(lat2, lon2);
//int currId = apt->getGroundNetwork()->findNearestNode(latitude,longitude);
//exit(1);
//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);
// 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);
//wpt = new waypoint;
//wpt->finished = false;
//waypoints.push_back(wpt); // add one more to prevent a segfault.
//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)
@ -297,23 +361,105 @@ void FGAIFlightPlan::createTaxi(bool firstFlight, int direction, FGAirport *apt,
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();
@ -364,10 +510,13 @@ void FGAIFlightPlan::createTakeOff(bool firstFlight, FGAirport *apt, double spee
// 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;
@ -456,10 +605,13 @@ void FGAIFlightPlan::createClimb(bool firstFlight, FGAirport *apt, double speed,
// 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;
@ -554,10 +706,11 @@ void FGAIFlightPlan::createCruise(bool firstFlight, FGAirport *dep, FGAirport *a
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;
@ -632,10 +785,11 @@ void FGAIFlightPlan::createDecent(FGAirport *apt)
//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;

View file

@ -37,6 +37,7 @@
#include <simgear/compiler.h>
#include <plib/sg.h>
#include <plib/ul.h>
#include <Environment/environment_mgr.hxx>
#include <Environment/environment.hxx>
@ -53,6 +54,7 @@
#include "simple.hxx"
SG_USING_STD(sort);
SG_USING_STD(random_shuffle);
/******************************************************************************
* ScheduleTime
@ -563,28 +565,10 @@ void FGRunwayPreference::error (const char * message, int line, int column) {
<< 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;
@ -608,6 +592,29 @@ double FGParking::processPosition(string pos)
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
***************************************************************************/
@ -664,6 +671,22 @@ FGAirport::FGAirport(string id, double lon, double lat, double elev, string name
}
// 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;
@ -893,6 +916,10 @@ void FGAirport::endXML () {
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;
@ -933,8 +960,34 @@ void FGAirport::startElement (const char * name, const XMLAttributes &atts) {
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) {
@ -1145,6 +1198,290 @@ void FGAirport::chooseRunwayFallback(string *runway)
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
*****************************************************************************/
@ -1199,6 +1536,7 @@ void FGAirportList::add( const string id, const double longitude,
{
try {
readXML(parkpath.str(),*a);
a->init();
}
catch (const sg_exception &e) {
//cerr << "unable to read " << parkpath.str() << endl;

View file

@ -36,7 +36,8 @@
#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>
@ -56,6 +57,8 @@ typedef vector<string>::const_iterator stringVecConstIterator;
typedef vector<time_t> timeVec;
typedef vector<time_t>::const_iterator timeVecConstIterator;
/***************************************************************************/
class ScheduleTime {
private:
@ -177,6 +180,8 @@ public:
virtual void error (const char * message, int line, int column);
};
double processPosition(string pos);
class FGParking {
private:
double latitude;
@ -188,10 +193,9 @@ private:
string type;
string airlineCodes;
bool available;
double processPosition(string pos);
public:
FGParking() { available = true;};
@ -232,7 +236,138 @@ typedef vector<FGParking> FGParkingVec;
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;
@ -244,6 +379,7 @@ private:
bool _has_metar;
FGParkingVec parkings;
FGRunwayPreference rwyPrefs;
FGGroundNetwork groundNetwork;
time_t lastUpdate;
string prevTrafficType;
@ -262,6 +398,8 @@ public:
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,
@ -272,6 +410,8 @@ public:
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
@ -279,6 +419,7 @@ public:
// Returns ft
double getElevation() const { return _elevation;};
bool getMetar() const { return _has_metar;};
FGGroundNetwork* getGroundNetwork() { return &groundNetwork; };
void setId(string id) { _id = id;};
@ -325,7 +466,7 @@ public:
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.

View file

@ -392,9 +392,15 @@ bool FGAISchedule::update(time_t now)
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;
}