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:
parent
13945c6cd4
commit
54594e5219
5 changed files with 772 additions and 132 deletions
|
@ -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);
|
||||
|
|
|
@ -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,7 +223,80 @@ 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);
|
||||
|
||||
// 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";
|
||||
|
@ -279,17 +328,32 @@ void FGAIFlightPlan::createTaxi(bool firstFlight, int direction, FGAirport *apt,
|
|||
//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,7 +361,84 @@ 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
|
||||
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();
|
||||
|
@ -311,9 +452,14 @@ void FGAIFlightPlan::createTaxi(bool firstFlight, int direction, FGAirport *apt,
|
|||
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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;};
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue