Durk Talsma, Olaf Flebbe & Mathias Frhlich:
Split up simple.cxx
This commit is contained in:
parent
c3f1331e52
commit
4be621fbe9
26 changed files with 2386 additions and 2002 deletions
|
@ -664,8 +664,10 @@ void FGAIAircraft::ProcessFlightPlan( double dt, time_t now )
|
|||
// << arr->getId() <<endl;
|
||||
// }
|
||||
if (prev->name == "park2")
|
||||
dep->releaseParking(fp->getGate());
|
||||
|
||||
{
|
||||
dep->getDynamics()->releaseParking(fp->getGate());
|
||||
}
|
||||
// Some debug messages, specific to TESTING THE Logical networks.
|
||||
//if ((arr->getId() == string("EHAM")) && (prev->name == "Center"))
|
||||
// {
|
||||
//
|
||||
|
|
|
@ -115,14 +115,17 @@ void FGAIFlightPlan::createPushBack(bool firstFlight, FGAirport *dep,
|
|||
// Otherwise use the current aircraft position.
|
||||
if (firstFlight)
|
||||
{
|
||||
if (!(dep->getAvailableParking(&lat, &lon, &heading, &gateId, radius, fltType, aircraftType, airline)))
|
||||
if (!(dep->getDynamics()->getAvailableParking(&lat, &lon,
|
||||
&heading, &gateId,
|
||||
radius, fltType,
|
||||
aircraftType, airline)))
|
||||
{
|
||||
cerr << "Could not find parking " << endl;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
dep->getParking(gateId, &lat, &lon, &heading);
|
||||
dep->getDynamics()->getParking(gateId, &lat, &lon, &heading);
|
||||
//lat = latitude;
|
||||
//lon = longitude;
|
||||
//heading = getHeading();
|
||||
|
@ -204,7 +207,7 @@ void FGAIFlightPlan::createTaxi(bool firstFlight, int direction, FGAirport *apt,
|
|||
// "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);
|
||||
apt->getDynamics()->getActiveRunway("com", 1, activeRunway);
|
||||
if (!(globals->get_runways()->search(apt->getId(),
|
||||
activeRunway,
|
||||
&rwy)))
|
||||
|
@ -223,10 +226,10 @@ 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())
|
||||
if (apt->getDynamics()->getGroundNetwork()->exists())
|
||||
{
|
||||
intVec ids;
|
||||
int runwayId = apt->getGroundNetwork()->findNearestNode(lat2, lon2);
|
||||
int runwayId = apt->getDynamics()->getGroundNetwork()->findNearestNode(lat2, lon2);
|
||||
//int currId = apt->getGroundNetwork()->findNearestNode(latitude,longitude);
|
||||
//exit(1);
|
||||
|
||||
|
@ -235,9 +238,9 @@ void FGAIFlightPlan::createTaxi(bool firstFlight, int direction, FGAirport *apt,
|
|||
// Starting from gate 0 is a bit of a hack...
|
||||
FGTaxiRoute route;
|
||||
if (gateId >= 0)
|
||||
route = apt->getGroundNetwork()->findShortestRoute(gateId, runwayId);
|
||||
route = apt->getDynamics()->getGroundNetwork()->findShortestRoute(gateId, runwayId);
|
||||
else
|
||||
route = apt->getGroundNetwork()->findShortestRoute(0, runwayId);
|
||||
route = apt->getDynamics()->getGroundNetwork()->findShortestRoute(0, runwayId);
|
||||
intVecIterator i;
|
||||
//cerr << "creating route : ";
|
||||
// No route found: go from gate directly to runway
|
||||
|
@ -276,7 +279,7 @@ void FGAIFlightPlan::createTaxi(bool firstFlight, int direction, FGAirport *apt,
|
|||
{
|
||||
//i = ids.end()-1;
|
||||
//cerr << "Creating Node: " << node << endl;
|
||||
FGTaxiNode *tn = apt->getGroundNetwork()->findNode(node);
|
||||
FGTaxiNode *tn = apt->getDynamics()->getGroundNetwork()->findNode(node);
|
||||
//ids.pop_back();
|
||||
wpt = new waypoint;
|
||||
wpt->name = "taxiway"; // fixme: should be the name of the taxiway
|
||||
|
@ -354,7 +357,7 @@ 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 );
|
||||
apt->getAvailableParking(&lat, &lon, &heading, &gateId, radius, fltType, acType, airline);
|
||||
apt->getDynamics()->getAvailableParking(&lat, &lon, &heading, &gateId, radius, fltType, acType, airline);
|
||||
heading += 180.0;
|
||||
if (heading > 360)
|
||||
heading -= 360;
|
||||
|
@ -364,10 +367,10 @@ void FGAIFlightPlan::createTaxi(bool firstFlight, int direction, FGAirport *apt,
|
|||
double lat3 = (*(waypoints.end()-1))->latitude;
|
||||
double lon3 = (*(waypoints.end()-1))->longitude;
|
||||
cerr << (*(waypoints.end()-1))->name << endl;
|
||||
if (apt->getGroundNetwork()->exists())
|
||||
if (apt->getDynamics()->getGroundNetwork()->exists())
|
||||
{
|
||||
intVec ids;
|
||||
int runwayId = apt->getGroundNetwork()->findNearestNode(lat3, lon3);
|
||||
int runwayId = apt->getDynamics()->getGroundNetwork()->findNearestNode(lat3, lon3);
|
||||
//int currId = apt->getGroundNetwork()->findNearestNode(latitude,longitude);
|
||||
//exit(1);
|
||||
|
||||
|
@ -376,9 +379,9 @@ void FGAIFlightPlan::createTaxi(bool firstFlight, int direction, FGAirport *apt,
|
|||
// Starting from gate 0 is a bit of a hack...
|
||||
FGTaxiRoute route;
|
||||
if (gateId >= 0)
|
||||
route = apt->getGroundNetwork()->findShortestRoute(runwayId, gateId);
|
||||
route = apt->getDynamics()->getGroundNetwork()->findShortestRoute(runwayId, gateId);
|
||||
else
|
||||
route = apt->getGroundNetwork()->findShortestRoute(runwayId, 0);
|
||||
route = apt->getDynamics()->getGroundNetwork()->findShortestRoute(runwayId, 0);
|
||||
intVecIterator i;
|
||||
//cerr << "creating route : ";
|
||||
// No route found: go from gate directly to runway
|
||||
|
@ -417,7 +420,7 @@ void FGAIFlightPlan::createTaxi(bool firstFlight, int direction, FGAirport *apt,
|
|||
{
|
||||
//i = ids.end()-1;
|
||||
//cerr << "Creating Node: " << node << endl;
|
||||
FGTaxiNode *tn = apt->getGroundNetwork()->findNode(node);
|
||||
FGTaxiNode *tn = apt->getDynamics()->getGroundNetwork()->findNode(node);
|
||||
//ids.pop_back();
|
||||
wpt = new waypoint;
|
||||
wpt->name = "taxiway"; // fixme: should be the name of the taxiway
|
||||
|
@ -514,7 +517,7 @@ void FGAIFlightPlan::createTakeOff(bool firstFlight, FGAirport *apt, double spee
|
|||
// "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);
|
||||
apt->getDynamics()->getActiveRunway("com", 1, activeRunway);
|
||||
if (!(globals->get_runways()->search(apt->getId(),
|
||||
activeRunway,
|
||||
&rwy)))
|
||||
|
@ -609,7 +612,7 @@ void FGAIFlightPlan::createClimb(bool firstFlight, FGAirport *apt, double speed,
|
|||
// "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);
|
||||
apt->getDynamics()->getActiveRunway("com", 1, activeRunway);
|
||||
if (!(globals->get_runways()->search(apt->getId(),
|
||||
activeRunway,
|
||||
&rwy)))
|
||||
|
@ -708,7 +711,7 @@ void FGAIFlightPlan::createCruise(bool firstFlight, FGAirport *dep, FGAirport *a
|
|||
|
||||
//string name;
|
||||
// should be changed dynamically to allow "gen" and "mil"
|
||||
arr->getActiveRunway("com", 2, activeRunway);
|
||||
arr->getDynamics()->getActiveRunway("com", 2, activeRunway);
|
||||
if (!(globals->get_runways()->search(arr->getId(),
|
||||
activeRunway,
|
||||
&rwy)))
|
||||
|
@ -787,7 +790,7 @@ void FGAIFlightPlan::createDecent(FGAirport *apt)
|
|||
//Beginning of Decent
|
||||
//string name;
|
||||
// allow "mil" and "gen" as well
|
||||
apt->getActiveRunway("com", 2, activeRunway);
|
||||
apt->getDynamics()->getActiveRunway("com", 2, activeRunway);
|
||||
if (!(globals->get_runways()->search(apt->getId(),
|
||||
activeRunway,
|
||||
&rwy)))
|
||||
|
@ -943,7 +946,7 @@ void FGAIFlightPlan::createParking(FGAirport *apt)
|
|||
double lat;
|
||||
double lon;
|
||||
double heading;
|
||||
apt->getParking(gateId, &lat, &lon, &heading);
|
||||
apt->getDynamics()->getParking(gateId, &lat, &lon, &heading);
|
||||
heading += 180.0;
|
||||
if (heading > 360)
|
||||
heading -= 360;
|
||||
|
|
|
@ -79,7 +79,7 @@ bool FGAIGAVFRTraffic::Init(const Point3D& pt, const string& destID, const strin
|
|||
_enroute = true;
|
||||
_destID = destID;
|
||||
_pos = pt;
|
||||
_destPos = dclGetAirportPos(destID); // TODO - check if we are within the tower catchment area already.
|
||||
_destPos = fgGetAirportPos(destID); // TODO - check if we are within the tower catchment area already.
|
||||
_cruise_alt = (_destPos.elev() + 2500.0) * SG_FEET_TO_METER; // TODO look at terrain elevation as well
|
||||
_pos.setelev(_cruise_alt);
|
||||
// initially set waypoint as airport location
|
||||
|
@ -218,7 +218,7 @@ void FGAIGAVFRTraffic::FlyPlane(double dt) {
|
|||
slope = atan((_wp.elev() - _pos.elev()) / dclGetHorizontalSeparation(_wp, _pos)) * DCL_RADIANS_TO_DEGREES;
|
||||
double thesh_offset = 0.0;
|
||||
Point3D opos = ortho.ConvertToLocal(_pos);
|
||||
double angToApt = atan((_pos.elev() - dclGetAirportElev(airportID)) / (opos.y() - thesh_offset)) * DCL_RADIANS_TO_DEGREES;
|
||||
double angToApt = atan((_pos.elev() - fgGetAirportElev(airportID)) / (opos.y() - thesh_offset)) * DCL_RADIANS_TO_DEGREES;
|
||||
//cout << "angToApt = " << angToApt << ' ';
|
||||
slope = (angToApt > -5.0 ? 0.0 : angToApt);
|
||||
//cout << "slope = " << slope << '\n';
|
||||
|
@ -246,7 +246,7 @@ void FGAIGAVFRTraffic::FlyPlane(double dt) {
|
|||
ConditionalTransmit(4);
|
||||
}
|
||||
}
|
||||
if(_pos.elev() < (dclGetAirportElev(airportID) + (1000.0 * SG_FEET_TO_METER))) slope = 0.0;
|
||||
if(_pos.elev() < (fgGetAirportElev(airportID) + (1000.0 * SG_FEET_TO_METER))) slope = 0.0;
|
||||
}
|
||||
}
|
||||
if(_incoming) {
|
||||
|
@ -254,7 +254,7 @@ void FGAIGAVFRTraffic::FlyPlane(double dt) {
|
|||
Point3D orthopos = ortho.ConvertToLocal(_pos);
|
||||
// TODO - Check whether to start descent
|
||||
// become _local after the 3 mile report.
|
||||
if(_pos.elev() < (dclGetAirportElev(airportID) + (1000.0 * SG_FEET_TO_METER))) slope = 0.0;
|
||||
if(_pos.elev() < (fgGetAirportElev(airportID) + (1000.0 * SG_FEET_TO_METER))) slope = 0.0;
|
||||
// TODO - work out why I needed to add the above line to stop the plane going underground!!!
|
||||
// (Although it's worth leaving it in as a robustness check anyway).
|
||||
if(_straightIn) {
|
||||
|
@ -265,9 +265,9 @@ void FGAIGAVFRTraffic::FlyPlane(double dt) {
|
|||
//cout << "Established at " << orthopos << '\n';
|
||||
}
|
||||
double thesh_offset = 30.0;
|
||||
//cout << "orthopos.y = " << orthopos.y() << " alt = " << _pos.elev() - dclGetAirportElev(airportID) << '\n';
|
||||
//cout << "orthopos.y = " << orthopos.y() << " alt = " << _pos.elev() - fgGetAirportElev(airportID) << '\n';
|
||||
if(_established && (orthopos.y() > -5400.0)) {
|
||||
slope = atan((_pos.elev() - dclGetAirportElev(airportID)) / (orthopos.y() - thesh_offset)) * DCL_RADIANS_TO_DEGREES;
|
||||
slope = atan((_pos.elev() - fgGetAirportElev(airportID)) / (orthopos.y() - thesh_offset)) * DCL_RADIANS_TO_DEGREES;
|
||||
//cout << "slope0 = " << slope << '\n';
|
||||
}
|
||||
//cout << "slope1 = " << slope << '\n';
|
||||
|
@ -437,20 +437,20 @@ Point3D FGAIGAVFRTraffic::GetPatternApproachPos() {
|
|||
if((orthopos.x() * patternDirection) > 0.0) { // 45 deg entry
|
||||
tmp.setx(2000 * patternDirection);
|
||||
tmp.sety((rwy.end2ortho.y() / 2.0) + 2000);
|
||||
tmp.setelev(dclGetAirportElev(airportID) + (1000 * SG_FEET_TO_METER));
|
||||
tmp.setelev(fgGetAirportElev(airportID) + (1000 * SG_FEET_TO_METER));
|
||||
_e45 = true;
|
||||
//cout << "45 deg entry... ";
|
||||
} else {
|
||||
tmp.setx(1000 * patternDirection * -1);
|
||||
tmp.sety(rwy.end2ortho.y());
|
||||
tmp.setelev(dclGetAirportElev(airportID) + (1000 * SG_FEET_TO_METER));
|
||||
tmp.setelev(fgGetAirportElev(airportID) + (1000 * SG_FEET_TO_METER));
|
||||
_e45 = false;
|
||||
//cout << "90 deg entry... ";
|
||||
}
|
||||
} else {
|
||||
tmp.setx(0);
|
||||
tmp.sety(-5400);
|
||||
tmp.setelev((5400.0 / 6.0) + dclGetAirportElev(airportID) + 10.0);
|
||||
tmp.setelev((5400.0 / 6.0) + fgGetAirportElev(airportID) + 10.0);
|
||||
//cout << "Straight in... ";
|
||||
}
|
||||
//cout << "Waypoint is " << tmp << '\n';
|
||||
|
|
|
@ -156,7 +156,7 @@ void FGAILocalTraffic::GetAirportDetails(const string& id) {
|
|||
_controlled = false;
|
||||
}
|
||||
// Get the airport elevation
|
||||
aptElev = dclGetAirportElev(airportID.c_str());
|
||||
aptElev = fgGetAirportElev(airportID.c_str());
|
||||
//cout << "Airport elev in AILocalTraffic = " << aptElev << '\n';
|
||||
// WARNING - we use this elev for the whole airport - some assumptions in the code
|
||||
// might fall down with very slopey airports.
|
||||
|
@ -1069,8 +1069,8 @@ void FGAILocalTraffic::FlyTrafficPattern(double dt) {
|
|||
if(descending) {
|
||||
if(orthopos.y() < -50.0) {
|
||||
double thesh_offset = 30.0;
|
||||
slope = atan((_pos.elev() - dclGetAirportElev(airportID)) / (orthopos.y() - thesh_offset)) * DCL_RADIANS_TO_DEGREES;
|
||||
//cout << "slope = " << slope << ", elev = " << _pos.elev() << ", apt_elev = " << dclGetAirportElev(airportID) << ", op.y = " << orthopos.y() << '\n';
|
||||
slope = atan((_pos.elev() - fgGetAirportElev(airportID)) / (orthopos.y() - thesh_offset)) * DCL_RADIANS_TO_DEGREES;
|
||||
//cout << "slope = " << slope << ", elev = " << _pos.elev() << ", apt_elev = " << fgGetAirportElev(airportID) << ", op.y = " << orthopos.y() << '\n';
|
||||
if(slope < -10.0) slope = -10.0;
|
||||
_savedSlope = slope;
|
||||
_pitch = -4.0;
|
||||
|
|
|
@ -24,7 +24,6 @@
|
|||
#include <Main/fg_props.hxx>
|
||||
#include <Main/globals.hxx>
|
||||
#include <simgear/math/sg_random.h>
|
||||
|
||||
#include <list>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
|
@ -131,9 +130,9 @@ void FGAIMgr::init() {
|
|||
ext = file.substr(pos + 1);
|
||||
if(ext == "taxi") {
|
||||
f_ident = file.substr(0, pos);
|
||||
FGAirport a;
|
||||
if(dclFindAirportID(f_ident, &a)) {
|
||||
SGBucket sgb(a.getLongitude(), a.getLatitude());
|
||||
const FGAirport *a = fgFindAirportID( f_ident);
|
||||
if(a){
|
||||
SGBucket sgb(a->getLongitude(), a->getLatitude());
|
||||
int idx = sgb.gen_index();
|
||||
if(facilities.find(idx) != facilities.end()) {
|
||||
facilities[idx]->push_back(f_ident);
|
||||
|
@ -159,7 +158,7 @@ void FGAIMgr::init() {
|
|||
/*
|
||||
// TESTING
|
||||
FGATCAlignedProjection ortho;
|
||||
ortho.Init(dclGetAirportPos("KEMT"), 205.0); // Guess of rwy19 heading
|
||||
ortho.Init(fgGetAirportPos("KEMT"), 205.0); // Guess of rwy19 heading
|
||||
//Point3D ip = ortho.ConvertFromLocal(Point3D(6000, 1000, 1000)); // 90 deg entry
|
||||
//Point3D ip = ortho.ConvertFromLocal(Point3D(-7000, 3000, 1000)); // 45 deg entry
|
||||
Point3D ip = ortho.ConvertFromLocal(Point3D(1000, -7000, 1000)); // straight-in
|
||||
|
@ -209,7 +208,7 @@ void FGAIMgr::update(double dt) {
|
|||
ai_activated_map_iterator apt_itr = activated.begin();
|
||||
while(apt_itr != activated.end()) {
|
||||
//cout << "FIRST IS " << (*apt_itr).first << '\n';
|
||||
if(dclGetHorizontalSeparation(userPos, dclGetAirportPos((*apt_itr).first)) > (35.0 * 1600.0)) {
|
||||
if(dclGetHorizontalSeparation(userPos, fgGetAirportPos((*apt_itr).first)) > (35.0 * 1600.0)) {
|
||||
// Then get rid of it and make sure the iterator is left pointing to the next one!
|
||||
string s = (*apt_itr).first;
|
||||
if(traffic.find(s) != traffic.end()) {
|
||||
|
@ -237,14 +236,14 @@ void FGAIMgr::update(double dt) {
|
|||
//cout << "s = " << s << " size = " << (*it).second.size() << '\n';
|
||||
// Only generate extra traffic if within a certain distance of the user,
|
||||
// TODO - maybe take users's tuned freq into account as well.
|
||||
double d = dclGetHorizontalSeparation(userPos, dclGetAirportPos(s));
|
||||
double d = dclGetHorizontalSeparation(userPos, fgGetAirportPos(s));
|
||||
if(d < (15.0 * 1600.0)) {
|
||||
double cd = 0.0;
|
||||
bool gen = false;
|
||||
//cout << "Size of list is " << (*it).second.size() << " at " << s << '\n';
|
||||
if((*it).second.size()) {
|
||||
FGAIEntity* e = *((*it).second.rbegin()); // Get the last airplane currently scheduled to arrive at this airport.
|
||||
cd = dclGetHorizontalSeparation(e->GetPos(), dclGetAirportPos(s));
|
||||
cd = dclGetHorizontalSeparation(e->GetPos(), fgGetAirportPos(s));
|
||||
if(cd < (d < 5000 ? 10000 : d + 5000)) {
|
||||
gen = true;
|
||||
}
|
||||
|
@ -331,8 +330,8 @@ void FGAIMgr::GenerateSimpleAirportTraffic(const string& ident, double min_dist)
|
|||
/*
|
||||
// TODO - check for military airports - this should be in the current data.
|
||||
// UGGH - there's no point at the moment - everything is labelled civil in basic.dat!
|
||||
FGAirport a;
|
||||
if(dclFindAirportID(ident, &a)) {
|
||||
FGAirport a = fgFindAirportID(ident, &a);
|
||||
if(a) {
|
||||
cout << "CODE IS " << a.code << '\n';
|
||||
} else {
|
||||
// UG - can't find the airport!
|
||||
|
@ -340,7 +339,7 @@ void FGAIMgr::GenerateSimpleAirportTraffic(const string& ident, double min_dist)
|
|||
}
|
||||
*/
|
||||
|
||||
Point3D aptpos = dclGetAirportPos(ident); // TODO - check for elev of -9999
|
||||
Point3D aptpos = fgGetAirportPos(ident); // TODO - check for elev of -9999
|
||||
//cout << "ident = " << ident << ", elev = " << aptpos.elev() << '\n';
|
||||
|
||||
// Operate from airports at 3000ft and below only to avoid the default cloud layers and since we don't degrade AI performance with altitude.
|
||||
|
@ -554,7 +553,7 @@ void FGAIMgr::SearchByPos(double range) {
|
|||
for(twd_itr = towered.begin(); twd_itr != towered.end(); twd_itr++) {
|
||||
// Only activate the closest airport not already activated each time.
|
||||
if(activated.find(twd_itr->ident) == activated.end()) {
|
||||
double sep = dclGetHorizontalSeparation(Point3D(lon, lat, elev), dclGetAirportPos(twd_itr->ident));
|
||||
double sep = dclGetHorizontalSeparation(Point3D(lon, lat, elev), fgGetAirportPos(twd_itr->ident));
|
||||
if(sep < closest) {
|
||||
closest = sep;
|
||||
s = twd_itr->ident;
|
||||
|
|
|
@ -365,8 +365,8 @@ void FGATCDialog::FreqDisplay(string& ident) {
|
|||
atcUppercase(ident);
|
||||
string label;
|
||||
|
||||
FGAirport a;
|
||||
if (!dclFindAirportID(ident, &a)) {
|
||||
const FGAirport *a = fgFindAirportID(ident);
|
||||
if (!a) {
|
||||
label = "Airport " + ident + " not found in database.";
|
||||
mkDialog(label.c_str());
|
||||
return;
|
||||
|
@ -379,7 +379,7 @@ void FGATCDialog::FreqDisplay(string& ident) {
|
|||
int n = 0; // Number of ATC frequencies at this airport
|
||||
|
||||
comm_list_type stations;
|
||||
int found = current_commlist->FindByPos(a.getLongitude(), a.getLatitude(), a.getElevation(), 20.0, &stations);
|
||||
int found = current_commlist->FindByPos(a->getLongitude(), a->getLatitude(), a->getElevation(), 20.0, &stations);
|
||||
if(found) {
|
||||
ostringstream ostr;
|
||||
comm_list_iterator itr = stations.begin();
|
||||
|
|
|
@ -21,7 +21,6 @@
|
|||
#include <simgear/misc/sg_path.hxx>
|
||||
#include <simgear/debug/logstream.hxx>
|
||||
#include <Airports/simple.hxx>
|
||||
|
||||
#include "ATCmgr.hxx"
|
||||
#include "commlist.hxx"
|
||||
#include "ATCdisplay.hxx"
|
||||
|
@ -216,14 +215,14 @@ bool FGATCMgr::AIRegisterAirport(const string& ident) {
|
|||
airport_atc_map[ident]->numAI++;
|
||||
return(true);
|
||||
} else {
|
||||
FGAirport ap;
|
||||
if(dclFindAirportID(ident, &ap)) {
|
||||
const FGAirport *ap = fgFindAirportID(ident);
|
||||
if (ap) {
|
||||
//cout << "ident = " << ident << '\n';
|
||||
AirportATC *a = new AirportATC;
|
||||
// I'm not entirely sure that this AirportATC structure business is actually needed - it just duplicates what we can find out anyway!
|
||||
a->lon = ap.getLongitude();
|
||||
a->lat = ap.getLatitude();
|
||||
a->elev = ap.getElevation();
|
||||
a->lon = ap->getLongitude();
|
||||
a->lat = ap->getLatitude();
|
||||
a->elev = ap->getElevation();
|
||||
a->atis_freq = GetFrequency(ident, ATIS);
|
||||
//cout << "ATIS freq = " << a->atis_freq << '\n';
|
||||
a->atis_active = false;
|
||||
|
@ -266,13 +265,13 @@ bool FGATCMgr::CommRegisterAirport(const string& ident, int chan, const atc_type
|
|||
return(true);
|
||||
} else {
|
||||
//cout << "NOT IN MAP - creating new..." << endl;
|
||||
FGAirport ap;
|
||||
if(dclFindAirportID(ident, &ap)) {
|
||||
const FGAirport *ap = fgFindAirportID(ident);
|
||||
if (ap) {
|
||||
AirportATC *a = new AirportATC;
|
||||
// I'm not entirely sure that this AirportATC structure business is actually needed - it just duplicates what we can find out anyway!
|
||||
a->lon = ap.getLongitude();
|
||||
a->lat = ap.getLatitude();
|
||||
a->elev = ap.getElevation();
|
||||
a->lon = ap->getLongitude();
|
||||
a->lat = ap->getLatitude();
|
||||
a->elev = ap->getElevation();
|
||||
a->atis_freq = GetFrequency(ident, ATIS);
|
||||
a->atis_active = false;
|
||||
a->tower_freq = GetFrequency(ident, TOWER);
|
||||
|
|
|
@ -291,67 +291,6 @@ double GetAngleDiff_deg( const double &a1, const double &a2) {
|
|||
return a3;
|
||||
}
|
||||
|
||||
//================================================================================================================
|
||||
|
||||
// Airport stuff. The next two functions are straight copies of their fg.... equivalents
|
||||
// in fg_init.cxx, and are just here temporarily until some rationalisation occurs.
|
||||
// find basic airport location info from airport database
|
||||
bool dclFindAirportID( const string& id, FGAirport *a ) {
|
||||
const FGAirport* result;
|
||||
|
||||
if ( id.length() ) {
|
||||
SG_LOG( SG_GENERAL, SG_INFO, "Searching for airport code = " << id );
|
||||
|
||||
result = globals->get_airports()->search(id);
|
||||
if ( result == NULL ) {
|
||||
SG_LOG( SG_GENERAL, SG_WARN,
|
||||
"Failed to find " << id << " in apt.dat.gz" );
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
*a = *result;
|
||||
|
||||
SG_LOG( SG_GENERAL, SG_INFO,
|
||||
"Position for " << id << " is ("
|
||||
<< a->getLongitude() << ", "
|
||||
<< a->getLatitude() << ")" );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// get airport elevation
|
||||
double dclGetAirportElev( const string& id ) {
|
||||
FGAirport a;
|
||||
// double lon, lat;
|
||||
|
||||
SG_LOG( SG_ATC, SG_INFO,
|
||||
"Finding elevation for airport: " << id );
|
||||
|
||||
if ( dclFindAirportID( id, &a ) ) {
|
||||
return a.getElevation() * SG_FEET_TO_METER;
|
||||
} else {
|
||||
return -9999.0;
|
||||
}
|
||||
}
|
||||
|
||||
// get airport position
|
||||
Point3D dclGetAirportPos( const string& id ) {
|
||||
FGAirport a;
|
||||
// double lon, lat;
|
||||
|
||||
SG_LOG( SG_ATC, SG_INFO,
|
||||
"Finding position for airport: " << id );
|
||||
|
||||
if ( dclFindAirportID( id, &a ) ) {
|
||||
return Point3D(a.getLongitude(), a.getLatitude(), a.getElevation());
|
||||
} else {
|
||||
return Point3D(0.0, 0.0, -9999.0);
|
||||
}
|
||||
}
|
||||
|
||||
// Runway stuff
|
||||
// Given a Point3D (lon/lat/elev) and an FGRunway struct, determine if the point lies on the runway
|
||||
bool OnRunway(const Point3D& pt, const FGRunway& rwy) {
|
||||
|
|
|
@ -92,25 +92,6 @@ void dclBoundHeading(double &hdg);
|
|||
// difference is negative if a1 > a2 and positive if a2 > a1
|
||||
double GetAngleDiff_deg( const double &a1, const double &a2);
|
||||
|
||||
|
||||
/*******************************
|
||||
*
|
||||
* Airport-related functions
|
||||
*
|
||||
********************************/
|
||||
|
||||
// The next two functions are straight copies of their fg.... equivalents
|
||||
// in fg_init.cxx, and are just here temporarily until some rationalisation occurs.
|
||||
|
||||
// find basic airport location info from airport database
|
||||
bool dclFindAirportID( const string& id, FGAirport *a );
|
||||
|
||||
// get airport elevation IN METERS
|
||||
double dclGetAirportElev( const string& id );
|
||||
|
||||
// get airport position (elev portion in FEET)
|
||||
Point3D dclGetAirportPos( const string& id );
|
||||
|
||||
/****************
|
||||
*
|
||||
* Runways
|
||||
|
|
|
@ -246,8 +246,8 @@ double FGCommList::FindClosest( double lon, double lat, double elev, ATCData& ad
|
|||
ATCData ad2 = *itr;
|
||||
//Point3D p1(*itr.lon, *itr.lat, *itr.elev);
|
||||
Point3D p1(ad2.lon, ad2.lat, ad2.elev);
|
||||
FGAirport a;
|
||||
if(dclFindAirportID(ad2.ident, &a)) {
|
||||
const FGAirport *a = fgFindAirportID(ad2.ident);
|
||||
if (a) {
|
||||
Point3D p2(lon, lat, elev);
|
||||
tmp = dclGetHorizontalSeparation(p1, p2);
|
||||
if(tmp <= closest) {
|
||||
|
@ -273,10 +273,10 @@ double FGCommList::FindClosest( double lon, double lat, double elev, ATCData& ad
|
|||
// This is basically a wrapper for a call to the airport database to get the airport
|
||||
// position followed by a call to FindByPos(...)
|
||||
bool FGCommList::FindByCode( const string& ICAO, ATCData& ad, atc_type tp ) {
|
||||
FGAirport a;
|
||||
if ( dclFindAirportID( ICAO, &a ) ) {
|
||||
const FGAirport *a = fgFindAirportID( ICAO);
|
||||
if ( a) {
|
||||
comm_list_type stations;
|
||||
int found = FindByPos(a.getLongitude(), a.getLatitude(), a.getElevation(), 10.0, &stations, tp);
|
||||
int found = FindByPos(a->getLongitude(), a->getLatitude(), a->getElevation(), 10.0, &stations, tp);
|
||||
if(found) {
|
||||
comm_list_iterator itr = stations.begin();
|
||||
while(itr != stations.end()) {
|
||||
|
|
|
@ -291,7 +291,7 @@ void FGTower::Init() {
|
|||
// TODO - attempt to get a departure control pointer to see if we need to hand off departing traffic to departure.
|
||||
|
||||
// Get the airport elevation
|
||||
aptElev = dclGetAirportElev(ident.c_str());
|
||||
aptElev = fgGetAirportElev(ident.c_str());
|
||||
|
||||
// TODO - this function only assumes one active rwy.
|
||||
DoRwyDetails();
|
||||
|
|
|
@ -5,7 +5,11 @@ noinst_PROGRAMS = calc_loc
|
|||
libAirports_a_SOURCES = \
|
||||
apt_loader.cxx apt_loader.hxx \
|
||||
runways.cxx runways.hxx \
|
||||
simple.cxx simple.hxx
|
||||
simple.cxx simple.hxx \
|
||||
runwayprefs.cxx runwayprefs.hxx \
|
||||
parking.cxx parking.hxx \
|
||||
groundnetwork.cxx groundnetwork.hxx \
|
||||
dynamics.cxx dynamics.hxx
|
||||
|
||||
calc_loc_SOURCES = calc_loc.cxx
|
||||
calc_loc_LDADD = -lsgmath -lsgdebug -lsgmisc -lz $(base_LIBS)
|
||||
|
|
630
src/Airports/dynamics.cxx
Normal file
630
src/Airports/dynamics.cxx
Normal file
|
@ -0,0 +1,630 @@
|
|||
// dynamics.cxx - Code to manage the higher order airport ground activities
|
||||
// Written by Durk Talsma, started December 2004.
|
||||
//
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
// published by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful, but
|
||||
// WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
//
|
||||
// $Id$
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
# define _USE_MATH_DEFINES
|
||||
#endif
|
||||
//#include <math.h>
|
||||
#include <algorithm>
|
||||
|
||||
#include <simgear/compiler.h>
|
||||
|
||||
#include <plib/sg.h>
|
||||
#include <plib/ul.h>
|
||||
|
||||
#include <Environment/environment_mgr.hxx>
|
||||
#include <Environment/environment.hxx>
|
||||
#include <simgear/misc/sg_path.hxx>
|
||||
#include <simgear/props/props.hxx>
|
||||
#include <simgear/structure/subsystem_mgr.hxx>
|
||||
#include <simgear/debug/logstream.hxx>
|
||||
#include <simgear/route/waypoint.hxx>
|
||||
#include <Main/globals.hxx>
|
||||
#include <Main/fg_props.hxx>
|
||||
#include <Airports/runways.hxx>
|
||||
#include <simgear/xml/easyxml.hxx>
|
||||
|
||||
#include STL_STRING
|
||||
#include <vector>
|
||||
|
||||
SG_USING_STD(string);
|
||||
SG_USING_STD(vector);
|
||||
SG_USING_STD(sort);
|
||||
SG_USING_STD(random_shuffle);
|
||||
|
||||
#include "parking.hxx"
|
||||
#include "groundnetwork.hxx"
|
||||
#include "runwayprefs.hxx"
|
||||
#include "dynamics.hxx"
|
||||
|
||||
/********** FGAirport Dynamics *********************************************/
|
||||
|
||||
FGAirportDynamics::FGAirportDynamics(double lat, double lon, double elev, string id) :
|
||||
_latitude(lat),
|
||||
_longitude(lon),
|
||||
_elevation(elev),
|
||||
_id(id)
|
||||
{
|
||||
lastUpdate = 0;
|
||||
for (int i = 0; i < 10; i++)
|
||||
{
|
||||
avWindHeading [i] = 0;
|
||||
avWindSpeed [i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Note that the ground network should also be copied
|
||||
FGAirportDynamics::FGAirportDynamics(const FGAirportDynamics& other)
|
||||
{
|
||||
for (FGParkingVecConstIterator ip= other.parkings.begin(); ip != other.parkings.end(); ip++)
|
||||
parkings.push_back(*(ip));
|
||||
rwyPrefs = other.rwyPrefs;
|
||||
lastUpdate = other.lastUpdate;
|
||||
|
||||
stringVecConstIterator il;
|
||||
for (il = other.landing.begin(); il != other.landing.end(); il++)
|
||||
landing.push_back(*il);
|
||||
for (il = other.takeoff.begin(); il != other.takeoff.end(); il++)
|
||||
takeoff.push_back(*il);
|
||||
lastUpdate = other.lastUpdate;
|
||||
for (int i = 0; i < 10; i++)
|
||||
{
|
||||
avWindHeading [i] = other.avWindHeading[i];
|
||||
avWindSpeed [i] = other.avWindSpeed [i];
|
||||
}
|
||||
}
|
||||
|
||||
// Destructor
|
||||
FGAirportDynamics::~FGAirportDynamics()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
// Initialization required after XMLRead
|
||||
void FGAirportDynamics::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 FGAirportDynamics::getAvailableParking(double *lat, double *lon, double *heading, int *gateId, double rad, const string &flType, const string &acType, const string &airline)
|
||||
{
|
||||
bool found = false;
|
||||
bool available = false;
|
||||
//string gateType;
|
||||
|
||||
FGParkingVecIterator i;
|
||||
// if (flType == "cargo")
|
||||
// {
|
||||
// gateType = "RAMP_CARGO";
|
||||
// }
|
||||
// else if (flType == "ga")
|
||||
// {
|
||||
// gateType = "RAMP_GA";
|
||||
// }
|
||||
// else gateType = "GATE";
|
||||
|
||||
if (parkings.begin() == parkings.end())
|
||||
{
|
||||
//cerr << "Could not find parking spot at " << _id << endl;
|
||||
*lat = _latitude;
|
||||
*lon = _longitude;
|
||||
*heading = 0;
|
||||
found = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// First try finding a parking with a designated airline code
|
||||
for (i = parkings.begin(); !(i == parkings.end() || found); i++)
|
||||
{
|
||||
//cerr << "Gate Id: " << i->getIndex()
|
||||
// << " Type : " << i->getType()
|
||||
// << " Codes : " << i->getCodes()
|
||||
// << " Radius: " << i->getRadius()
|
||||
// << " Name : " << i->getName()
|
||||
// << " Available: " << i->isAvailable() << endl;
|
||||
available = true;
|
||||
// Taken by another aircraft
|
||||
if (!(i->isAvailable()))
|
||||
{
|
||||
available = false;
|
||||
continue;
|
||||
}
|
||||
// No airline codes, so skip
|
||||
if (i->getCodes().empty())
|
||||
{
|
||||
available = false;
|
||||
continue;
|
||||
}
|
||||
else // Airline code doesn't match
|
||||
if (i->getCodes().find(airline, 0) == string::npos)
|
||||
{
|
||||
available = false;
|
||||
continue;
|
||||
}
|
||||
// Type doesn't match
|
||||
if (i->getType() != flType)
|
||||
{
|
||||
available = false;
|
||||
continue;
|
||||
}
|
||||
// too small
|
||||
if (i->getRadius() < rad)
|
||||
{
|
||||
available = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (available)
|
||||
{
|
||||
*lat = i->getLatitude ();
|
||||
*lon = i->getLongitude();
|
||||
*heading = i->getHeading ();
|
||||
*gateId = i->getIndex ();
|
||||
i->setAvailable(false);
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
// then try again for those without codes.
|
||||
for (i = parkings.begin(); !(i == parkings.end() || found); i++)
|
||||
{
|
||||
available = true;
|
||||
if (!(i->isAvailable()))
|
||||
{
|
||||
available = false;
|
||||
continue;
|
||||
}
|
||||
if (!(i->getCodes().empty()))
|
||||
{
|
||||
if ((i->getCodes().find(airline,0) == string::npos))
|
||||
{
|
||||
available = false;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (i->getType() != flType)
|
||||
{
|
||||
available = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (i->getRadius() < rad)
|
||||
{
|
||||
available = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (available)
|
||||
{
|
||||
*lat = i->getLatitude ();
|
||||
*lon = i->getLongitude();
|
||||
*heading = i->getHeading ();
|
||||
*gateId = i->getIndex ();
|
||||
i->setAvailable(false);
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
// And finally once more if that didn't work. Now ignore the airline codes, as a last resort
|
||||
for (i = parkings.begin(); !(i == parkings.end() || found); i++)
|
||||
{
|
||||
available = true;
|
||||
if (!(i->isAvailable()))
|
||||
{
|
||||
available = false;
|
||||
continue;
|
||||
}
|
||||
if (i->getType() != flType)
|
||||
{
|
||||
available = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (i->getRadius() < rad)
|
||||
{
|
||||
available = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (available)
|
||||
{
|
||||
*lat = i->getLatitude ();
|
||||
*lon = i->getLongitude();
|
||||
*heading = i->getHeading ();
|
||||
*gateId = i->getIndex ();
|
||||
i->setAvailable(false);
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!found)
|
||||
{
|
||||
//cerr << "Traffic overflow at" << _id
|
||||
// << ". flType = " << flType
|
||||
// << ". airline = " << airline
|
||||
// << " Radius = " <<rad
|
||||
// << endl;
|
||||
*lat = _latitude;
|
||||
*lon = _longitude;
|
||||
*heading = 0;
|
||||
*gateId = -1;
|
||||
//exit(1);
|
||||
}
|
||||
return found;
|
||||
}
|
||||
|
||||
void FGAirportDynamics::getParking (int id, double *lat, double* lon, double *heading)
|
||||
{
|
||||
if (id < 0)
|
||||
{
|
||||
*lat = _latitude;
|
||||
*lon = _longitude;
|
||||
*heading = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
FGParkingVecIterator i = parkings.begin();
|
||||
for (i = parkings.begin(); i != parkings.end(); i++)
|
||||
{
|
||||
if (id == i->getIndex())
|
||||
{
|
||||
*lat = i->getLatitude();
|
||||
*lon = i->getLongitude();
|
||||
*heading = i->getLongitude();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FGParking *FGAirportDynamics::getParking(int i)
|
||||
{
|
||||
if (i < (int)parkings.size())
|
||||
return &(parkings[i]);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
string FGAirportDynamics::getParkingName(int i)
|
||||
{
|
||||
if (i < (int)parkings.size() && i >= 0)
|
||||
return (parkings[i].getName());
|
||||
else
|
||||
return string("overflow");
|
||||
}
|
||||
void FGAirportDynamics::releaseParking(int id)
|
||||
{
|
||||
if (id >= 0)
|
||||
{
|
||||
|
||||
FGParkingVecIterator i = parkings.begin();
|
||||
for (i = parkings.begin(); i != parkings.end(); i++)
|
||||
{
|
||||
if (id == i->getIndex())
|
||||
{
|
||||
i -> setAvailable(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FGAirportDynamics::startXML () {
|
||||
//cout << "Start XML" << endl;
|
||||
}
|
||||
|
||||
void FGAirportDynamics::endXML () {
|
||||
//cout << "End XML" << endl;
|
||||
}
|
||||
|
||||
void FGAirportDynamics::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;
|
||||
string gateName;
|
||||
string gateNumber;
|
||||
string lat;
|
||||
string lon;
|
||||
if (name == string("Parking"))
|
||||
{
|
||||
for (int i = 0; i < atts.size(); i++)
|
||||
{
|
||||
//cout << " " << atts.getName(i) << '=' << atts.getValue(i) << endl;
|
||||
attname = atts.getName(i);
|
||||
if (attname == string("index"))
|
||||
park.setIndex(atoi(atts.getValue(i)));
|
||||
else if (attname == string("type"))
|
||||
park.setType(atts.getValue(i));
|
||||
else if (attname == string("name"))
|
||||
gateName = atts.getValue(i);
|
||||
else if (attname == string("number"))
|
||||
gateNumber = atts.getValue(i);
|
||||
else if (attname == string("lat"))
|
||||
park.setLatitude(atts.getValue(i));
|
||||
else if (attname == string("lon"))
|
||||
park.setLongitude(atts.getValue(i));
|
||||
else if (attname == string("heading"))
|
||||
park.setHeading(atof(atts.getValue(i)));
|
||||
else if (attname == string("radius")) {
|
||||
string radius = atts.getValue(i);
|
||||
if (radius.find("M") != string::npos)
|
||||
radius = radius.substr(0, radius.find("M",0));
|
||||
//cerr << "Radius " << radius <<endl;
|
||||
park.setRadius(atof(radius.c_str()));
|
||||
}
|
||||
else if (attname == string("airlineCodes"))
|
||||
park.setCodes(atts.getValue(i));
|
||||
}
|
||||
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
|
||||
}
|
||||
|
||||
void FGAirportDynamics::endElement (const char * name) {
|
||||
//cout << "End element " << name << endl;
|
||||
|
||||
}
|
||||
|
||||
void FGAirportDynamics::data (const char * s, int len) {
|
||||
string token = string(s,len);
|
||||
//cout << "Character data " << string(s,len) << endl;
|
||||
//if ((token.find(" ") == string::npos && (token.find('\n')) == string::npos))
|
||||
//value += token;
|
||||
//else
|
||||
//value = string("");
|
||||
}
|
||||
|
||||
void FGAirportDynamics::pi (const char * target, const char * data) {
|
||||
//cout << "Processing instruction " << target << ' ' << data << endl;
|
||||
}
|
||||
|
||||
void FGAirportDynamics::warning (const char * message, int line, int column) {
|
||||
cout << "Warning: " << message << " (" << line << ',' << column << ')'
|
||||
<< endl;
|
||||
}
|
||||
|
||||
void FGAirportDynamics::error (const char * message, int line, int column) {
|
||||
cout << "Error: " << message << " (" << line << ',' << column << ')'
|
||||
<< endl;
|
||||
}
|
||||
|
||||
void FGAirportDynamics::setRwyUse(const FGRunwayPreference& ref)
|
||||
{
|
||||
rwyPrefs = ref;
|
||||
//cerr << "Exiting due to not implemented yet" << endl;
|
||||
//exit(1);
|
||||
}
|
||||
void FGAirportDynamics::getActiveRunway(const string &trafficType, int action, string &runway)
|
||||
{
|
||||
double windSpeed;
|
||||
double windHeading;
|
||||
double maxTail;
|
||||
double maxCross;
|
||||
string name;
|
||||
string type;
|
||||
|
||||
if (!(rwyPrefs.available()))
|
||||
{
|
||||
runway = chooseRunwayFallback();
|
||||
return; // generic fall back goes here
|
||||
}
|
||||
else
|
||||
{
|
||||
RunwayGroup *currRunwayGroup = 0;
|
||||
int nrActiveRunways = 0;
|
||||
time_t dayStart = fgGetLong("/sim/time/utc/day-seconds");
|
||||
if (((dayStart - lastUpdate) > 600) || trafficType != prevTrafficType)
|
||||
{
|
||||
landing.clear();
|
||||
takeoff.clear();
|
||||
//lastUpdate = dayStart;
|
||||
prevTrafficType = trafficType;
|
||||
|
||||
FGEnvironment
|
||||
stationweather = ((FGEnvironmentMgr *) globals->get_subsystem("environment"))
|
||||
->getEnvironment(getLatitude(),
|
||||
getLongitude(),
|
||||
getElevation());
|
||||
|
||||
windSpeed = stationweather.get_wind_speed_kt();
|
||||
windHeading = stationweather.get_wind_from_heading_deg();
|
||||
double averageWindSpeed = 0;
|
||||
double averageWindHeading = 0;
|
||||
double cosHeading = 0;
|
||||
double sinHeading = 0;
|
||||
// Initialize at the beginning of the next day or startup
|
||||
if ((lastUpdate == 0) || (dayStart < lastUpdate))
|
||||
{
|
||||
for (int i = 0; i < 10; i++)
|
||||
{
|
||||
avWindHeading [i] = windHeading;
|
||||
avWindSpeed [i] = windSpeed;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (windSpeed != avWindSpeed[9]) // update if new metar data
|
||||
{
|
||||
// shift the running average
|
||||
for (int i = 0; i < 9 ; i++)
|
||||
{
|
||||
avWindHeading[i] = avWindHeading[i+1];
|
||||
avWindSpeed [i] = avWindSpeed [i+1];
|
||||
}
|
||||
}
|
||||
avWindHeading[9] = windHeading;
|
||||
avWindSpeed [9] = windSpeed;
|
||||
}
|
||||
|
||||
for (int i = 0; i < 10; i++)
|
||||
{
|
||||
averageWindSpeed += avWindSpeed [i];
|
||||
//averageWindHeading += avWindHeading [i];
|
||||
cosHeading += cos(avWindHeading[i] * SG_DEGREES_TO_RADIANS);
|
||||
sinHeading += sin(avWindHeading[i] * SG_DEGREES_TO_RADIANS);
|
||||
}
|
||||
averageWindSpeed /= 10;
|
||||
//averageWindHeading /= 10;
|
||||
cosHeading /= 10;
|
||||
sinHeading /= 10;
|
||||
averageWindHeading = atan2(sinHeading, cosHeading) *SG_RADIANS_TO_DEGREES;
|
||||
if (averageWindHeading < 0)
|
||||
averageWindHeading += 360.0;
|
||||
//cerr << "Wind Heading " << windHeading << " average " << averageWindHeading << endl;
|
||||
//cerr << "Wind Speed " << windSpeed << " average " << averageWindSpeed << endl;
|
||||
lastUpdate = dayStart;
|
||||
//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 scheduleName;
|
||||
//cerr << "finding active Runway for" << _id << endl;
|
||||
//cerr << "Nr of seconds since day start << " << dayStart << endl;
|
||||
ScheduleTime *currSched;
|
||||
//cerr << "A"<< endl;
|
||||
currSched = rwyPrefs.getSchedule(trafficType.c_str());
|
||||
if (!(currSched))
|
||||
return;
|
||||
//cerr << "B"<< endl;
|
||||
scheduleName = currSched->getName(dayStart);
|
||||
maxTail = currSched->getTailWind ();
|
||||
maxCross = currSched->getCrossWind ();
|
||||
//cerr << "SChedule anme = " << scheduleName << endl;
|
||||
if (scheduleName.empty())
|
||||
return;
|
||||
//cerr << "C"<< endl;
|
||||
currRunwayGroup = rwyPrefs.getGroup(scheduleName);
|
||||
//cerr << "D"<< endl;
|
||||
if (!(currRunwayGroup))
|
||||
return;
|
||||
nrActiveRunways = currRunwayGroup->getNrActiveRunways();
|
||||
//cerr << "Nr of Active Runways = " << nrActiveRunways << endl;
|
||||
currRunwayGroup->setActive(_id, averageWindSpeed, averageWindHeading, maxTail, maxCross);
|
||||
nrActiveRunways = currRunwayGroup->getNrActiveRunways();
|
||||
for (int i = 0; i < nrActiveRunways; i++)
|
||||
{
|
||||
type = "unknown"; // initialize to something other than landing or takeoff
|
||||
currRunwayGroup->getActive(i, name, type);
|
||||
if (type == "landing")
|
||||
{
|
||||
landing.push_back(name);
|
||||
//cerr << "Landing " << name << endl;
|
||||
}
|
||||
if (type == "takeoff")
|
||||
{
|
||||
takeoff.push_back(name);
|
||||
//cerr << "takeoff " << name << endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (action == 1) // takeoff
|
||||
{
|
||||
int nr = takeoff.size();
|
||||
if (nr)
|
||||
{
|
||||
runway = takeoff[(rand() % nr)];
|
||||
}
|
||||
else
|
||||
{ // Fallback
|
||||
runway = chooseRunwayFallback();
|
||||
}
|
||||
}
|
||||
if (action == 2) // landing
|
||||
{
|
||||
int nr = landing.size();
|
||||
if (nr)
|
||||
{
|
||||
runway = landing[(rand() % nr)];
|
||||
}
|
||||
else
|
||||
{ //fallback
|
||||
runway = chooseRunwayFallback();
|
||||
}
|
||||
}
|
||||
|
||||
//runway = globals->get_runways()->search(_id, int(windHeading));
|
||||
//cerr << "Seleceted runway: " << runway << endl;
|
||||
}
|
||||
}
|
||||
|
||||
string FGAirportDynamics::chooseRunwayFallback()
|
||||
{
|
||||
FGEnvironment
|
||||
stationweather = ((FGEnvironmentMgr *) globals->get_subsystem("environment"))
|
||||
->getEnvironment(getLatitude(),
|
||||
getLongitude(),
|
||||
getElevation());
|
||||
|
||||
double windSpeed = stationweather.get_wind_speed_kt();
|
||||
double windHeading = stationweather.get_wind_from_heading_deg();
|
||||
if (windSpeed == 0) {
|
||||
windHeading = 270; // This forces West-facing rwys to be used in no-wind situations
|
||||
//which is consistent with Flightgear's initial setup.
|
||||
}
|
||||
|
||||
return globals->get_runways()->search(_id, int(windHeading));
|
||||
}
|
101
src/Airports/dynamics.hxx
Normal file
101
src/Airports/dynamics.hxx
Normal file
|
@ -0,0 +1,101 @@
|
|||
// dynamics.hxx - a class to manage the higher order airport ground activities
|
||||
// Written by Durk Talsma, started December 2004.
|
||||
//
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
// published by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful, but
|
||||
// WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
//
|
||||
// $Id$
|
||||
|
||||
|
||||
#ifndef _AIRPORT_DYNAMICS_HXX_
|
||||
#define _AIRPORT_DYNAMICS_HXX_
|
||||
|
||||
|
||||
#ifndef __cplusplus
|
||||
# error This library requires C++
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
class FGAirportDynamics : public XMLVisitor {
|
||||
|
||||
private:
|
||||
double _longitude; // degrees
|
||||
double _latitude; // degrees
|
||||
double _elevation; // ft
|
||||
string _id;
|
||||
|
||||
FGParkingVec parkings;
|
||||
FGRunwayPreference rwyPrefs;
|
||||
FGGroundNetwork groundNetwork;
|
||||
|
||||
time_t lastUpdate;
|
||||
string prevTrafficType;
|
||||
stringVec landing;
|
||||
stringVec takeoff;
|
||||
|
||||
// Experimental keep a running average of wind dir and speed to prevent
|
||||
// Erratic runway changes.
|
||||
// Note: I should add these to the copy constructor and assigment operator to be
|
||||
// constistent
|
||||
double avWindHeading [10];
|
||||
double avWindSpeed [10];
|
||||
|
||||
string chooseRunwayFallback();
|
||||
|
||||
public:
|
||||
FGAirportDynamics(double, double, double, string);
|
||||
FGAirportDynamics(const FGAirportDynamics &other);
|
||||
~FGAirportDynamics();
|
||||
|
||||
|
||||
void init();
|
||||
double getLongitude() const { return _longitude;};
|
||||
// Returns degrees
|
||||
double getLatitude() const { return _latitude; };
|
||||
// Returns ft
|
||||
double getElevation() const { return _elevation;};
|
||||
|
||||
void getActiveRunway(const string& trafficType, int action, string& runway);
|
||||
bool getAvailableParking(double *lat, double *lon,
|
||||
double *heading, int *gate, double rad, const string& fltype,
|
||||
const string& acType, const string& airline);
|
||||
void getParking (int id, double *lat, double* lon, double *heading);
|
||||
FGParking *getParking(int i);
|
||||
void releaseParking(int id);
|
||||
string getParkingName(int i);
|
||||
//FGAirport *getAddress() { return this; };
|
||||
//const string &getName() const { return _name;};
|
||||
// Returns degrees
|
||||
|
||||
FGGroundNetwork* getGroundNetwork() { return &groundNetwork; };
|
||||
|
||||
|
||||
void setRwyUse(const FGRunwayPreference& ref);
|
||||
|
||||
// Some overloaded virtual XMLVisitor members
|
||||
virtual void startXML ();
|
||||
virtual void endXML ();
|
||||
virtual void startElement (const char * name, const XMLAttributes &atts);
|
||||
virtual void endElement (const char * name);
|
||||
virtual void data (const char * s, int len);
|
||||
virtual void pi (const char * target, const char * data);
|
||||
virtual void warning (const char * message, int line, int column);
|
||||
virtual void error (const char * message, int line, int column);
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif
|
337
src/Airports/groundnetwork.cxx
Normal file
337
src/Airports/groundnetwork.cxx
Normal file
|
@ -0,0 +1,337 @@
|
|||
// groundnet.cxx - Implimentation of the FlightGear airport ground handling code
|
||||
//
|
||||
// Written by Durk Talsma, started June 2005.
|
||||
//
|
||||
// Copyright (C) 2004 Durk Talsma.
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
// published by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful, but
|
||||
// WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
//
|
||||
// $Id$
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
# define _USE_MATH_DEFINES
|
||||
#endif
|
||||
#include <math.h>
|
||||
#include <algorithm>
|
||||
|
||||
#include <simgear/compiler.h>
|
||||
|
||||
//#include <plib/sg.h>
|
||||
//#include <plib/ul.h>
|
||||
|
||||
//#include <Environment/environment_mgr.hxx>
|
||||
//#include <Environment/environment.hxx>
|
||||
//#include <simgear/misc/sg_path.hxx>
|
||||
//#include <simgear/props/props.hxx>
|
||||
//#include <simgear/structure/subsystem_mgr.hxx>
|
||||
#include <simgear/debug/logstream.hxx>
|
||||
#include <simgear/route/waypoint.hxx>
|
||||
//#include <Main/globals.hxx>
|
||||
//#include <Main/fg_props.hxx>
|
||||
//#include <Airports/runways.hxx>
|
||||
|
||||
//#include STL_STRING
|
||||
|
||||
#include "groundnetwork.hxx"
|
||||
|
||||
SG_USING_STD(sort);
|
||||
|
||||
/**************************************************************************
|
||||
* 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;
|
||||
foundRoute = false;
|
||||
totalDistance = 0;
|
||||
maxDistance = 0;
|
||||
}
|
||||
|
||||
void FGGroundNetwork::addSegment(const FGTaxiSegment &seg)
|
||||
{
|
||||
segments.push_back(seg);
|
||||
}
|
||||
|
||||
void FGGroundNetwork::addNode(const 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_VAL;
|
||||
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)
|
||||
{
|
||||
SG_LOG( SG_GENERAL, SG_INFO, "Failed to find route from waypoint " << start << " to " << end );
|
||||
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
|
||||
{
|
||||
SG_LOG( SG_GENERAL, SG_DEBUG, "4" );
|
||||
}
|
||||
traceStack.pop_back();
|
||||
totalDistance -= distance;
|
||||
return;
|
||||
}
|
||||
|
164
src/Airports/groundnetwork.hxx
Normal file
164
src/Airports/groundnetwork.hxx
Normal file
|
@ -0,0 +1,164 @@
|
|||
// groundnet.hxx - A number of classes to handle taxiway
|
||||
// assignments by the AI code
|
||||
//
|
||||
// Written by Durk Talsma, started June 2005.
|
||||
//
|
||||
// Copyright (C) 2004 Durk Talsma.
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
// published by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful, but
|
||||
// WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
//
|
||||
// $Id$
|
||||
|
||||
#ifndef _GROUNDNETWORK_HXX_
|
||||
#define _GROUNDNETWORK_HXX_
|
||||
|
||||
#include STL_STRING
|
||||
#include <vector>
|
||||
|
||||
SG_USING_STD(string);
|
||||
SG_USING_STD(vector);
|
||||
|
||||
#include "parking.hxx"
|
||||
|
||||
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 (const string& val) { lat = processPosition(val); };
|
||||
void setLongitude(const 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 (const FGTaxiNode& node);
|
||||
void addNodes (FGParkingVec *parkings);
|
||||
void addSegment(const 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);
|
||||
|
||||
};
|
||||
|
||||
#endif
|
102
src/Airports/parking.cxx
Normal file
102
src/Airports/parking.cxx
Normal file
|
@ -0,0 +1,102 @@
|
|||
// parking.cxx - Implementation of a class to manage aircraft parking in
|
||||
// FlightGear. This code is intended to be used by AI code and
|
||||
// initial user-startup location selection.
|
||||
//
|
||||
// Written by Durk Talsma, started December 2004.
|
||||
//
|
||||
// Copyright (C) 2004 Durk Talsma.
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
// published by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful, but
|
||||
// WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
//
|
||||
// $Id$
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
# define _USE_MATH_DEFINES
|
||||
#endif
|
||||
//#include <math.h>
|
||||
//#include <algorithm>
|
||||
|
||||
#include <simgear/compiler.h>
|
||||
|
||||
//#include <plib/sg.h>
|
||||
//#include <plib/ul.h>
|
||||
|
||||
//#include <Environment/environment_mgr.hxx>
|
||||
//#include <Environment/environment.hxx>
|
||||
//#include <simgear/misc/sg_path.hxx>
|
||||
//#include <simgear/props/props.hxx>
|
||||
//#include <simgear/structure/subsystem_mgr.hxx>
|
||||
//#include <simgear/debug/logstream.hxx>
|
||||
//#include <Main/globals.hxx>
|
||||
//#include <Main/fg_props.hxx>
|
||||
//#include <Airports/runways.hxx>
|
||||
|
||||
#include STL_STRING
|
||||
|
||||
#include "parking.hxx"
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
* Helper function for parsing position string
|
||||
****************************************************************************/
|
||||
double processPosition(const string &pos)
|
||||
{
|
||||
string prefix;
|
||||
string subs;
|
||||
string degree;
|
||||
string decimal;
|
||||
int sign = 1;
|
||||
double value;
|
||||
subs = pos;
|
||||
prefix= subs.substr(0,1);
|
||||
if (prefix == string("S") || (prefix == string("W")))
|
||||
sign = -1;
|
||||
subs = subs.substr(1, subs.length());
|
||||
degree = subs.substr(0, subs.find(" ",0));
|
||||
decimal = subs.substr(subs.find(" ",0), subs.length());
|
||||
|
||||
|
||||
//cerr << sign << " "<< degree << " " << decimal << endl;
|
||||
value = sign * (atof(degree.c_str()) + atof(decimal.c_str())/60.0);
|
||||
//cerr << value <<endl;
|
||||
//exit(1);
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
/*********************************************************************************
|
||||
* FGParking
|
||||
********************************************************************************/
|
||||
FGParking::FGParking(double lat,
|
||||
double lon,
|
||||
double hdg,
|
||||
double rad,
|
||||
int idx,
|
||||
const string &name,
|
||||
const string &tpe,
|
||||
const string &codes)
|
||||
{
|
||||
latitude = lat;
|
||||
longitude = lon;
|
||||
heading = hdg;
|
||||
parkingName = name;
|
||||
index = idx;
|
||||
type = tpe;
|
||||
airlineCodes = codes;
|
||||
}
|
97
src/Airports/parking.hxx
Normal file
97
src/Airports/parking.hxx
Normal file
|
@ -0,0 +1,97 @@
|
|||
// parking.hxx - A class to handle airport startup locations in
|
||||
// FlightGear. This code is intended to be used by AI code and
|
||||
// initial user-startup location selection.
|
||||
//
|
||||
// Written by Durk Talsma, started December 2004.
|
||||
//
|
||||
// Copyright (C) 2004 Durk Talsma.
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
// published by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful, but
|
||||
// WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
//
|
||||
// $Id$
|
||||
|
||||
#ifndef _PARKING_HXX_
|
||||
#define _PARKING_HXX_
|
||||
|
||||
#ifndef __cplusplus
|
||||
# error This library requires C++
|
||||
#endif
|
||||
|
||||
#include STL_STRING
|
||||
#include <vector>
|
||||
|
||||
|
||||
|
||||
|
||||
SG_USING_STD(string);
|
||||
SG_USING_STD(vector);
|
||||
|
||||
double processPosition(const string& pos);
|
||||
|
||||
class FGParking {
|
||||
private:
|
||||
double latitude;
|
||||
double longitude;
|
||||
double heading;
|
||||
double radius;
|
||||
int index;
|
||||
string parkingName;
|
||||
string type;
|
||||
string airlineCodes;
|
||||
|
||||
bool available;
|
||||
|
||||
|
||||
|
||||
public:
|
||||
FGParking() { available = true;};
|
||||
//FGParking(FGParking &other);
|
||||
FGParking(double lat,
|
||||
double lon,
|
||||
double hdg,
|
||||
double rad,
|
||||
int idx,
|
||||
const string& name,
|
||||
const string& tpe,
|
||||
const string& codes);
|
||||
void setLatitude (const string& lat) { latitude = processPosition(lat); };
|
||||
void setLongitude(const string& lon) { longitude = processPosition(lon); };
|
||||
void setHeading (double hdg) { heading = hdg; };
|
||||
void setRadius (double rad) { radius = rad; };
|
||||
void setIndex (int idx) { index = idx; };
|
||||
void setName (const string& name) { parkingName = name; };
|
||||
void setType (const string& tpe) { type = tpe; };
|
||||
void setCodes (const string& codes){ airlineCodes= codes;};
|
||||
|
||||
bool isAvailable () { return available;};
|
||||
void setAvailable(bool val) { available = val; };
|
||||
|
||||
double getLatitude () { return latitude; };
|
||||
double getLongitude() { return longitude; };
|
||||
double getHeading () { return heading; };
|
||||
double getRadius () { return radius; };
|
||||
int getIndex () { return index; };
|
||||
string getType () { return type; };
|
||||
string getCodes () { return airlineCodes;};
|
||||
string getName () { return parkingName; };
|
||||
|
||||
bool operator< (const FGParking &other) const {return radius < other.radius; };
|
||||
};
|
||||
|
||||
typedef vector<FGParking> FGParkingVec;
|
||||
typedef vector<FGParking>::iterator FGParkingVecIterator;
|
||||
typedef vector<FGParking>::const_iterator FGParkingVecConstIterator;
|
||||
|
||||
#endif
|
558
src/Airports/runwayprefs.cxx
Normal file
558
src/Airports/runwayprefs.cxx
Normal file
|
@ -0,0 +1,558 @@
|
|||
// runwayprefs.cxx - class implementations corresponding to runwayprefs.hxx
|
||||
// assignments by the AI code
|
||||
//
|
||||
// Written by Durk Talsma, started January 2005.
|
||||
//
|
||||
// Copyright (C) 2004 Durk Talsma.
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
// published by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful, but
|
||||
// WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
//
|
||||
// $Id$
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
# define _USE_MATH_DEFINES
|
||||
#endif
|
||||
#include <math.h>
|
||||
//#include <algorithm>
|
||||
|
||||
#include <simgear/compiler.h>
|
||||
|
||||
//#include <plib/sg.h>
|
||||
//#include <plib/ul.h>
|
||||
|
||||
//#include <Environment/environment_mgr.hxx>
|
||||
//#include <Environment/environment.hxx>
|
||||
//#include <simgear/misc/sg_path.hxx>
|
||||
//#include <simgear/props/props.hxx>
|
||||
//#include <simgear/structure/subsystem_mgr.hxx>
|
||||
#include <simgear/debug/logstream.hxx>
|
||||
#include <Main/globals.hxx>
|
||||
//#include <Main/fg_props.hxx>
|
||||
#include <Airports/runways.hxx>
|
||||
|
||||
#include "runwayprefs.hxx"
|
||||
|
||||
/******************************************************************************
|
||||
* ScheduleTime
|
||||
***************e*************************************************************/
|
||||
void ScheduleTime::clear()
|
||||
{
|
||||
start.clear();
|
||||
end.clear();
|
||||
scheduleNames.clear();
|
||||
}
|
||||
|
||||
|
||||
ScheduleTime::ScheduleTime(const ScheduleTime &other)
|
||||
{
|
||||
//timeVec start;
|
||||
timeVecConstIterator i;
|
||||
for (i = other.start.begin(); i != other.start.end(); i++)
|
||||
start.push_back(*i);
|
||||
for (i = other.end.begin(); i != other.end.end(); i++)
|
||||
end.push_back(*i);
|
||||
stringVecConstIterator k;
|
||||
for (k = other.scheduleNames.begin(); k != other.scheduleNames.end(); k++)
|
||||
scheduleNames.push_back(*k);
|
||||
|
||||
//timeVec end;
|
||||
//stringVec scheduleNames;
|
||||
tailWind = other.tailWind;
|
||||
crssWind = other.tailWind;
|
||||
}
|
||||
|
||||
|
||||
ScheduleTime & ScheduleTime::operator= (const ScheduleTime &other)
|
||||
{
|
||||
//timeVec start;
|
||||
clear();
|
||||
timeVecConstIterator i;
|
||||
for (i = other.start.begin(); i != other.start.end(); i++)
|
||||
start.push_back(*i);
|
||||
for (i = other.end.begin(); i != other.end.end(); i++)
|
||||
end.push_back(*i);
|
||||
stringVecConstIterator k;
|
||||
for (k = other.scheduleNames.begin(); k != other.scheduleNames.end(); k++)
|
||||
scheduleNames.push_back(*k);
|
||||
|
||||
//timeVec end;
|
||||
//stringVec scheduleNames;
|
||||
tailWind = other.tailWind;
|
||||
crssWind = other.tailWind;
|
||||
return *this;
|
||||
}
|
||||
string ScheduleTime::getName(time_t dayStart)
|
||||
{
|
||||
if ((start.size() != end.size()) || (start.size() != scheduleNames.size()))
|
||||
{
|
||||
SG_LOG( SG_GENERAL, SG_INFO, "Unable to parse schedule times" );
|
||||
exit(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
int nrItems = start.size();
|
||||
//cerr << "Nr of items to process: " << nrItems << endl;
|
||||
if (nrItems > 0)
|
||||
{
|
||||
for (unsigned int i = 0; i < start.size(); i++)
|
||||
{
|
||||
//cerr << i << endl;
|
||||
if ((dayStart >= start[i]) && (dayStart <= end[i]))
|
||||
return scheduleNames[i];
|
||||
}
|
||||
}
|
||||
//couldn't find one so return 0;
|
||||
//cerr << "Returning 0 " << endl;
|
||||
}
|
||||
return string(0);
|
||||
}
|
||||
/******************************************************************************
|
||||
* RunwayList
|
||||
*****************************************************************************/
|
||||
|
||||
RunwayList::RunwayList(const RunwayList &other)
|
||||
{
|
||||
type = other.type;
|
||||
stringVecConstIterator i;
|
||||
for (i = other.preferredRunways.begin(); i != other.preferredRunways.end(); i++)
|
||||
preferredRunways.push_back(*i);
|
||||
}
|
||||
RunwayList& RunwayList::operator= (const RunwayList &other)
|
||||
{
|
||||
type = other.type;
|
||||
preferredRunways.clear();
|
||||
stringVecConstIterator i;
|
||||
for (i = other.preferredRunways.begin(); i != other.preferredRunways.end(); i++)
|
||||
preferredRunways.push_back(*i);
|
||||
return *this;
|
||||
}
|
||||
void RunwayList::set(const string &tp, const string &lst)
|
||||
{
|
||||
//weekday = atoi(timeCopy.substr(0,1).c_str());
|
||||
// timeOffsetInDays = weekday - currTimeDate->getGmt()->tm_wday;
|
||||
// timeCopy = timeCopy.substr(2,timeCopy.length());
|
||||
type = tp;
|
||||
string rwys = lst;
|
||||
string rwy;
|
||||
while (rwys.find(",") != string::npos)
|
||||
{
|
||||
rwy = rwys.substr(0, rwys.find(",",0));
|
||||
//cerr << "adding runway [" << rwy << "] to the list " << endl;
|
||||
preferredRunways.push_back(rwy);
|
||||
rwys.erase(0, rwys.find(",",0)+1); // erase until after the first whitspace
|
||||
while (rwys[0] == ' ')
|
||||
rwys.erase(0, 1); // Erase any leading whitespaces.
|
||||
//cerr << "Remaining runway list " << rwys;
|
||||
}
|
||||
preferredRunways.push_back(rwys);
|
||||
//exit(1);
|
||||
}
|
||||
|
||||
void RunwayList::clear()
|
||||
{
|
||||
type = "";
|
||||
preferredRunways.clear();
|
||||
}
|
||||
/****************************************************************************
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
RunwayGroup::RunwayGroup(const RunwayGroup &other)
|
||||
{
|
||||
name = other.name;
|
||||
RunwayListVecConstIterator i;
|
||||
for (i = other.rwyList.begin(); i != other.rwyList.end(); i++)
|
||||
rwyList.push_back(*i);
|
||||
choice[0] = other.choice[0];
|
||||
choice[1] = other.choice[1];
|
||||
nrActive = other.nrActive;
|
||||
}
|
||||
RunwayGroup& RunwayGroup:: operator= (const RunwayGroup &other)
|
||||
{
|
||||
rwyList.clear();
|
||||
name = other.name;
|
||||
RunwayListVecConstIterator i;
|
||||
for (i = other.rwyList.begin(); i != other.rwyList.end(); i++)
|
||||
rwyList.push_back(*i);
|
||||
choice[0] = other.choice[0];
|
||||
choice[1] = other.choice[1];
|
||||
nrActive = other.nrActive;
|
||||
return *this;
|
||||
}
|
||||
|
||||
void RunwayGroup::setActive(const string &aptId,
|
||||
double windSpeed,
|
||||
double windHeading,
|
||||
double maxTail,
|
||||
double maxCross)
|
||||
{
|
||||
|
||||
FGRunway rwy;
|
||||
int activeRwys = rwyList.size(); // get the number of runways active
|
||||
int nrOfPreferences;
|
||||
// bool found = true;
|
||||
// double heading;
|
||||
double hdgDiff;
|
||||
double crossWind;
|
||||
double tailWind;
|
||||
string name;
|
||||
|
||||
if (activeRwys > 0)
|
||||
{
|
||||
nrOfPreferences = rwyList[0].getRwyList()->size();
|
||||
for (int i = 0; i < nrOfPreferences; i++)
|
||||
{
|
||||
bool validSelection = true;
|
||||
for (int j = 0; j < activeRwys; j++)
|
||||
{
|
||||
//cerr << "I J " << i << " " << j << endl;
|
||||
name = rwyList[j].getRwyList(i);
|
||||
//cerr << "Name of Runway: " << name << endl;
|
||||
if (globals->get_runways()->search( aptId,
|
||||
name,
|
||||
&rwy))
|
||||
{
|
||||
//cerr << "Succes" << endl;
|
||||
hdgDiff = fabs(windHeading - rwy._heading);
|
||||
//cerr << "Wind Heading: " << windHeading << "Runway Heading: " <<rwy._heading << endl;
|
||||
//cerr << "Wind Speed : " << windSpeed << endl;
|
||||
if (hdgDiff > 180)
|
||||
hdgDiff = 360 - hdgDiff;
|
||||
//cerr << "Heading diff: " << hdgDiff << endl;
|
||||
hdgDiff *= ((2*M_PI)/360.0); // convert to radians
|
||||
crossWind = windSpeed * sin(hdgDiff);
|
||||
tailWind = -windSpeed * cos(hdgDiff);
|
||||
//cerr << "Tailwind : " << tailWind << endl;
|
||||
//cerr << "Crosswnd : " << crossWind << endl;
|
||||
if ((tailWind > maxTail) || (crossWind > maxCross))
|
||||
validSelection = false;
|
||||
}else {
|
||||
SG_LOG( SG_GENERAL, SG_INFO, "Failed to find runway " << name << " at " << aptId );
|
||||
exit(1);
|
||||
}
|
||||
|
||||
}
|
||||
if (validSelection)
|
||||
{
|
||||
//cerr << "Valid runay selection : " << i << endl;
|
||||
nrActive = activeRwys;
|
||||
active = i;
|
||||
return;
|
||||
}
|
||||
}
|
||||
// If this didn't work, due to heavy winds, try again
|
||||
// but select only one landing and one takeoff runway.
|
||||
choice[0] = 0;
|
||||
choice[1] = 0;
|
||||
for (int i = activeRwys-1; i; i--)
|
||||
{
|
||||
if (rwyList[i].getType() == string("landing"))
|
||||
choice[0] = i;
|
||||
if (rwyList[i].getType() == string("takeoff"))
|
||||
choice[1] = i;
|
||||
}
|
||||
//cerr << "Choosing " << choice[0] << " for landing and " << choice[1] << "for takeoff" << endl;
|
||||
nrOfPreferences = rwyList[0].getRwyList()->size();
|
||||
for (int i = 0; i < nrOfPreferences; i++)
|
||||
{
|
||||
bool validSelection = true;
|
||||
for (int j = 0; j < 2; j++)
|
||||
{
|
||||
//cerr << "I J " << i << " " << j << endl;
|
||||
name = rwyList[choice[j]].getRwyList(i);
|
||||
//cerr << "Name of Runway: " << name << endl;
|
||||
if (globals->get_runways()->search( aptId,
|
||||
name,
|
||||
&rwy))
|
||||
{
|
||||
//cerr << "Succes" << endl;
|
||||
hdgDiff = fabs(windHeading - rwy._heading);
|
||||
//cerr << "Wind Heading: " << windHeading << "Runway Heading: " <<rwy._heading << endl;
|
||||
//cerr << "Wind Speed : " << windSpeed << endl;
|
||||
if (hdgDiff > 180)
|
||||
hdgDiff = 360 - hdgDiff;
|
||||
//cerr << "Heading diff: " << hdgDiff << endl;
|
||||
hdgDiff *= ((2*M_PI)/360.0); // convert to radians
|
||||
crossWind = windSpeed * sin(hdgDiff);
|
||||
tailWind = -windSpeed * cos(hdgDiff);
|
||||
//cerr << "Tailwind : " << tailWind << endl;
|
||||
//cerr << "Crosswnd : " << crossWind << endl;
|
||||
if ((tailWind > maxTail) || (crossWind > maxCross))
|
||||
validSelection = false;
|
||||
}else {
|
||||
SG_LOG( SG_GENERAL, SG_INFO, "Failed to find runway " << name << " at " << aptId );
|
||||
exit(1);
|
||||
}
|
||||
|
||||
}
|
||||
if (validSelection)
|
||||
{
|
||||
//cerr << "Valid runay selection : " << i << endl;
|
||||
active = i;
|
||||
nrActive = 2;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
active = -1;
|
||||
//RunwayListVectorIterator i; // = rwlist.begin();
|
||||
//stringVecIterator j;
|
||||
//for (i = rwyList.begin(); i != rwyList.end(); i++)
|
||||
// {
|
||||
// cerr << i->getType();
|
||||
// for (j = i->getRwyList()->begin(); j != i->getRwyList()->end(); j++)
|
||||
// {
|
||||
// cerr << (*j);
|
||||
// }
|
||||
// cerr << endl;
|
||||
// }
|
||||
//for (int
|
||||
|
||||
}
|
||||
|
||||
void RunwayGroup::getActive(int i, string &name, string &type)
|
||||
{
|
||||
if (i == -1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (nrActive == (int)rwyList.size())
|
||||
{
|
||||
name = rwyList[i].getRwyList(active);
|
||||
type = rwyList[i].getType();
|
||||
}
|
||||
else
|
||||
{
|
||||
name = rwyList[choice[i]].getRwyList(active);
|
||||
type = rwyList[choice[i]].getType();
|
||||
}
|
||||
}
|
||||
/*****************************************************************************
|
||||
* FGRunway preference
|
||||
****************************************************************************/
|
||||
FGRunwayPreference::FGRunwayPreference()
|
||||
{
|
||||
//cerr << "Running default Constructor" << endl;
|
||||
initialized = false;
|
||||
}
|
||||
|
||||
FGRunwayPreference::FGRunwayPreference(const FGRunwayPreference &other)
|
||||
{
|
||||
initialized = other.initialized;
|
||||
value = other.value;
|
||||
scheduleName = other.scheduleName;
|
||||
|
||||
comTimes = other.comTimes; // Commercial Traffic;
|
||||
genTimes = other.genTimes; // General Aviation;
|
||||
milTimes = other.milTimes; // Military Traffic;
|
||||
currTimes= other.currTimes; // Needed for parsing;
|
||||
|
||||
rwyList = other.rwyList;
|
||||
rwyGroup = other.rwyGroup;
|
||||
PreferenceListConstIterator i;
|
||||
for (i = other.preferences.begin(); i != other.preferences.end(); i++)
|
||||
preferences.push_back(*i);
|
||||
}
|
||||
|
||||
FGRunwayPreference & FGRunwayPreference::operator= (const FGRunwayPreference &other)
|
||||
{
|
||||
initialized = other.initialized;
|
||||
value = other.value;
|
||||
scheduleName = other.scheduleName;
|
||||
|
||||
comTimes = other.comTimes; // Commercial Traffic;
|
||||
genTimes = other.genTimes; // General Aviation;
|
||||
milTimes = other.milTimes; // Military Traffic;
|
||||
currTimes= other.currTimes; // Needed for parsing;
|
||||
|
||||
rwyList = other.rwyList;
|
||||
rwyGroup = other.rwyGroup;
|
||||
PreferenceListConstIterator i;
|
||||
preferences.clear();
|
||||
for (i = other.preferences.begin(); i != other.preferences.end(); i++)
|
||||
preferences.push_back(*i);
|
||||
return *this;
|
||||
}
|
||||
|
||||
ScheduleTime *FGRunwayPreference::getSchedule(const char *trafficType)
|
||||
{
|
||||
if (!(strcmp(trafficType, "com"))) {
|
||||
return &comTimes;
|
||||
}
|
||||
if (!(strcmp(trafficType, "gen"))) {
|
||||
return &genTimes;
|
||||
}
|
||||
if (!(strcmp(trafficType, "mil"))) {
|
||||
return &milTimes;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
RunwayGroup *FGRunwayPreference::getGroup(const string &groupName)
|
||||
{
|
||||
PreferenceListIterator i = preferences.begin();
|
||||
if (preferences.begin() == preferences.end())
|
||||
return 0;
|
||||
while (!(i == preferences.end() || i->getName() == groupName))
|
||||
i++;
|
||||
if (i != preferences.end())
|
||||
return &(*i);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
void FGRunwayPreference::startXML () {
|
||||
// cout << "Start XML" << endl;
|
||||
}
|
||||
|
||||
void FGRunwayPreference::endXML () {
|
||||
cout << "End XML" << endl;
|
||||
}
|
||||
|
||||
void FGRunwayPreference::startElement (const char * name, const XMLAttributes &atts) {
|
||||
//cout << "StartElement " << name << endl;
|
||||
value = string("");
|
||||
if (!(strcmp(name, "wind"))) {
|
||||
//cerr << "Will be processing Wind" << endl;
|
||||
for (int i = 0; i < atts.size(); i++)
|
||||
{
|
||||
//cout << " " << atts.getName(i) << '=' << atts.getValue(i) << endl;
|
||||
//attname = atts.getName(i);
|
||||
if (atts.getName(i) == string("tail")) {
|
||||
//cerr << "Tail Wind = " << atts.getValue(i) << endl;
|
||||
currTimes.setTailWind(atof(atts.getValue(i)));
|
||||
}
|
||||
if (atts.getName(i) == string("cross")) {
|
||||
//cerr << "Cross Wind = " << atts.getValue(i) << endl;
|
||||
currTimes.setCrossWind(atof(atts.getValue(i)));
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!(strcmp(name, "time"))) {
|
||||
//cerr << "Will be processing time" << endl;
|
||||
for (int i = 0; i < atts.size(); i++)
|
||||
{
|
||||
if (atts.getName(i) == string("start")) {
|
||||
//cerr << "Start Time = " << atts.getValue(i) << endl;
|
||||
currTimes.addStartTime(processTime(atts.getValue(i)));
|
||||
}
|
||||
if (atts.getName(i) == string("end")) {
|
||||
//cerr << "End time = " << atts.getValue(i) << endl;
|
||||
currTimes.addEndTime(processTime(atts.getValue(i)));
|
||||
}
|
||||
if (atts.getName(i) == string("schedule")) {
|
||||
//cerr << "Schedule Name = " << atts.getValue(i) << endl;
|
||||
currTimes.addScheduleName(atts.getValue(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!(strcmp(name, "takeoff"))) {
|
||||
rwyList.clear();
|
||||
}
|
||||
if (!(strcmp(name, "landing")))
|
||||
{
|
||||
rwyList.clear();
|
||||
}
|
||||
if (!(strcmp(name, "schedule"))) {
|
||||
for (int i = 0; i < atts.size(); i++)
|
||||
{
|
||||
//cout << " " << atts.getName(i) << '=' << atts.getValue(i) << endl;
|
||||
//attname = atts.getName(i);
|
||||
if (atts.getName(i) == string("name")) {
|
||||
//cerr << "Schedule name = " << atts.getValue(i) << endl;
|
||||
scheduleName = atts.getValue(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//based on a string containing hour and minute, return nr seconds since day start.
|
||||
time_t FGRunwayPreference::processTime(const string &tme)
|
||||
{
|
||||
string hour = tme.substr(0, tme.find(":",0));
|
||||
string minute = tme.substr(tme.find(":",0)+1, tme.length());
|
||||
|
||||
//cerr << "hour = " << hour << " Minute = " << minute << endl;
|
||||
return (atoi(hour.c_str()) * 3600 + atoi(minute.c_str()) * 60);
|
||||
}
|
||||
|
||||
void FGRunwayPreference::endElement (const char * name) {
|
||||
//cout << "End element " << name << endl;
|
||||
if (!(strcmp(name, "rwyuse"))) {
|
||||
initialized = true;
|
||||
}
|
||||
if (!(strcmp(name, "com"))) { // Commercial Traffic
|
||||
//cerr << "Setting time table for commerical traffic" << endl;
|
||||
comTimes = currTimes;
|
||||
currTimes.clear();
|
||||
}
|
||||
if (!(strcmp(name, "gen"))) { // General Aviation
|
||||
//cerr << "Setting time table for general aviation" << endl;
|
||||
genTimes = currTimes;
|
||||
currTimes.clear();
|
||||
}
|
||||
if (!(strcmp(name, "mil"))) { // Military Traffic
|
||||
//cerr << "Setting time table for military traffic" << endl;
|
||||
genTimes = currTimes;
|
||||
currTimes.clear();
|
||||
}
|
||||
|
||||
if (!(strcmp(name, "takeoff"))) {
|
||||
//cerr << "Adding takeoff: " << value << endl;
|
||||
rwyList.set(name, value);
|
||||
rwyGroup.add(rwyList);
|
||||
}
|
||||
if (!(strcmp(name, "landing"))) {
|
||||
//cerr << "Adding landing: " << value << endl;
|
||||
rwyList.set(name, value);
|
||||
rwyGroup.add(rwyList);
|
||||
}
|
||||
if (!(strcmp(name, "schedule"))) {
|
||||
//cerr << "Adding schedule" << scheduleName << endl;
|
||||
rwyGroup.setName(scheduleName);
|
||||
//rwyGroup.addRunways(rwyList);
|
||||
preferences.push_back(rwyGroup);
|
||||
rwyGroup.clear();
|
||||
//exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
void FGRunwayPreference::data (const char * s, int len) {
|
||||
string token = string(s,len);
|
||||
//cout << "Character data " << string(s,len) << endl;
|
||||
//if ((token.find(" ") == string::npos && (token.find('\n')) == string::npos))
|
||||
// value += token;
|
||||
//else
|
||||
// value = string("");
|
||||
value += token;
|
||||
}
|
||||
|
||||
void FGRunwayPreference::pi (const char * target, const char * data) {
|
||||
//cout << "Processing instruction " << target << ' ' << data << endl;
|
||||
}
|
||||
|
||||
void FGRunwayPreference::warning (const char * message, int line, int column) {
|
||||
cout << "Warning: " << message << " (" << line << ',' << column << ')'
|
||||
<< endl;
|
||||
}
|
||||
|
||||
void FGRunwayPreference::error (const char * message, int line, int column) {
|
||||
cout << "Error: " << message << " (" << line << ',' << column << ')'
|
||||
<< endl;
|
||||
}
|
159
src/Airports/runwayprefs.hxx
Normal file
159
src/Airports/runwayprefs.hxx
Normal file
|
@ -0,0 +1,159 @@
|
|||
// runwayprefs.hxx - A number of classes to configure runway
|
||||
// assignments by the AI code
|
||||
//
|
||||
// Written by Durk Talsma, started January 2005.
|
||||
//
|
||||
// Copyright (C) 2004 Durk Talsma.
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
// published by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful, but
|
||||
// WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
//
|
||||
// $Id$
|
||||
|
||||
#ifndef _RUNWAYPREFS_HXX_
|
||||
#define _RUNWAYPREFS_HXX_
|
||||
|
||||
#include <simgear/xml/easyxml.hxx>
|
||||
|
||||
typedef vector<time_t> timeVec;
|
||||
typedef vector<time_t>::const_iterator timeVecConstIterator;
|
||||
|
||||
typedef vector<string> stringVec;
|
||||
typedef vector<string>::iterator stringVecIterator;
|
||||
typedef vector<string>::const_iterator stringVecConstIterator;
|
||||
|
||||
|
||||
/***************************************************************************/
|
||||
class ScheduleTime {
|
||||
private:
|
||||
timeVec start;
|
||||
timeVec end;
|
||||
stringVec scheduleNames;
|
||||
double tailWind;
|
||||
double crssWind;
|
||||
public:
|
||||
ScheduleTime() : tailWind(0), crssWind(0) {};
|
||||
ScheduleTime(const ScheduleTime &other);
|
||||
ScheduleTime &operator= (const ScheduleTime &other);
|
||||
string getName(time_t dayStart);
|
||||
|
||||
void clear();
|
||||
void addStartTime(time_t time) { start.push_back(time); };
|
||||
void addEndTime (time_t time) { end. push_back(time); };
|
||||
void addScheduleName(const string& sched) { scheduleNames.push_back(sched); };
|
||||
void setTailWind(double wnd) { tailWind = wnd; };
|
||||
void setCrossWind(double wnd) { tailWind = wnd; };
|
||||
|
||||
double getTailWind() { return tailWind; };
|
||||
double getCrossWind() { return crssWind; };
|
||||
};
|
||||
|
||||
//typedef vector<ScheduleTime> ScheduleTimes;
|
||||
/*****************************************************************************/
|
||||
|
||||
class RunwayList
|
||||
{
|
||||
private:
|
||||
string type;
|
||||
stringVec preferredRunways;
|
||||
public:
|
||||
RunwayList() {};
|
||||
RunwayList(const RunwayList &other);
|
||||
RunwayList& operator= (const RunwayList &other);
|
||||
|
||||
void set(const string&, const string&);
|
||||
void clear();
|
||||
|
||||
string getType() { return type; };
|
||||
stringVec *getRwyList() { return &preferredRunways; };
|
||||
string getRwyList(int j) { return preferredRunways[j]; };
|
||||
};
|
||||
|
||||
typedef vector<RunwayList> RunwayListVec;
|
||||
typedef vector<RunwayList>::iterator RunwayListVectorIterator;
|
||||
typedef vector<RunwayList>::const_iterator RunwayListVecConstIterator;
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
class RunwayGroup
|
||||
{
|
||||
private:
|
||||
string name;
|
||||
RunwayListVec rwyList;
|
||||
int active;
|
||||
//stringVec runwayNames;
|
||||
int choice[2];
|
||||
int nrActive;
|
||||
public:
|
||||
RunwayGroup() {};
|
||||
RunwayGroup(const RunwayGroup &other);
|
||||
RunwayGroup &operator= (const RunwayGroup &other);
|
||||
|
||||
void setName(const string& nm) { name = nm; };
|
||||
void add(const RunwayList& list) { rwyList.push_back(list);};
|
||||
void setActive(const string& aptId, double windSpeed, double windHeading, double maxTail, double maxCross);
|
||||
|
||||
int getNrActiveRunways() { return nrActive;};
|
||||
void getActive(int i, string& name, string& type);
|
||||
|
||||
string getName() { return name; };
|
||||
void clear() { rwyList.clear(); };
|
||||
//void add(string, string);
|
||||
};
|
||||
|
||||
typedef vector<RunwayGroup> PreferenceList;
|
||||
typedef vector<RunwayGroup>::iterator PreferenceListIterator;
|
||||
typedef vector<RunwayGroup>::const_iterator PreferenceListConstIterator;
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
class FGRunwayPreference : public XMLVisitor {
|
||||
private:
|
||||
string value;
|
||||
string scheduleName;
|
||||
|
||||
ScheduleTime comTimes; // Commercial Traffic;
|
||||
ScheduleTime genTimes; // General Aviation;
|
||||
ScheduleTime milTimes; // Military Traffic;
|
||||
ScheduleTime currTimes; // Needed for parsing;
|
||||
|
||||
RunwayList rwyList;
|
||||
RunwayGroup rwyGroup;
|
||||
PreferenceList preferences;
|
||||
|
||||
time_t processTime(const string&);
|
||||
bool initialized;
|
||||
|
||||
public:
|
||||
FGRunwayPreference();
|
||||
FGRunwayPreference(const FGRunwayPreference &other);
|
||||
|
||||
FGRunwayPreference & operator= (const FGRunwayPreference &other);
|
||||
ScheduleTime *getSchedule(const char *trafficType);
|
||||
RunwayGroup *getGroup(const string& groupName);
|
||||
bool available() { return initialized; };
|
||||
|
||||
// Some overloaded virtual XMLVisitor members
|
||||
virtual void startXML ();
|
||||
virtual void endXML ();
|
||||
virtual void startElement (const char * name, const XMLAttributes &atts);
|
||||
virtual void endElement (const char * name);
|
||||
virtual void data (const char * s, int len);
|
||||
virtual void pi (const char * target, const char * data);
|
||||
virtual void warning (const char * message, int line, int column);
|
||||
virtual void error (const char * message, int line, int column);
|
||||
};
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load diff
|
@ -37,406 +37,63 @@
|
|||
# include <config.h>
|
||||
#endif
|
||||
#include <simgear/math/point3d.hxx>
|
||||
#include <simgear/route/waypoint.hxx>
|
||||
|
||||
#include <simgear/compiler.h>
|
||||
#include <simgear/xml/easyxml.hxx>
|
||||
//#include <simgear/xml/easyxml.hxx>
|
||||
|
||||
#include STL_STRING
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <vector>
|
||||
|
||||
#include "runwayprefs.hxx"
|
||||
#include "parking.hxx"
|
||||
#include "groundnetwork.hxx"
|
||||
#include "dynamics.hxx"
|
||||
|
||||
SG_USING_STD(string);
|
||||
SG_USING_STD(map);
|
||||
SG_USING_STD(set);
|
||||
SG_USING_STD(vector);
|
||||
|
||||
typedef vector<string> stringVec;
|
||||
typedef vector<string>::iterator stringVecIterator;
|
||||
typedef vector<string>::const_iterator stringVecConstIterator;
|
||||
|
||||
typedef vector<time_t> timeVec;
|
||||
typedef vector<time_t>::const_iterator timeVecConstIterator;
|
||||
|
||||
|
||||
/***************************************************************************/
|
||||
class ScheduleTime {
|
||||
private:
|
||||
timeVec start;
|
||||
timeVec end;
|
||||
stringVec scheduleNames;
|
||||
double tailWind;
|
||||
double crssWind;
|
||||
public:
|
||||
ScheduleTime() : tailWind(0), crssWind(0) {};
|
||||
ScheduleTime(const ScheduleTime &other);
|
||||
ScheduleTime &operator= (const ScheduleTime &other);
|
||||
string getName(time_t dayStart);
|
||||
|
||||
void clear();
|
||||
void addStartTime(time_t time) { start.push_back(time); };
|
||||
void addEndTime (time_t time) { end. push_back(time); };
|
||||
void addScheduleName(const string& sched) { scheduleNames.push_back(sched); };
|
||||
void setTailWind(double wnd) { tailWind = wnd; };
|
||||
void setCrossWind(double wnd) { tailWind = wnd; };
|
||||
|
||||
double getTailWind() { return tailWind; };
|
||||
double getCrossWind() { return crssWind; };
|
||||
};
|
||||
|
||||
//typedef vector<ScheduleTime> ScheduleTimes;
|
||||
/*****************************************************************************/
|
||||
|
||||
class RunwayList
|
||||
{
|
||||
private:
|
||||
string type;
|
||||
stringVec preferredRunways;
|
||||
public:
|
||||
RunwayList() {};
|
||||
RunwayList(const RunwayList &other);
|
||||
RunwayList& operator= (const RunwayList &other);
|
||||
|
||||
void set(const string&, const string&);
|
||||
void clear();
|
||||
|
||||
string getType() { return type; };
|
||||
stringVec *getRwyList() { return &preferredRunways; };
|
||||
string getRwyList(int j) { return preferredRunways[j]; };
|
||||
};
|
||||
|
||||
typedef vector<RunwayList> RunwayListVec;
|
||||
typedef vector<RunwayList>::iterator RunwayListVectorIterator;
|
||||
typedef vector<RunwayList>::const_iterator RunwayListVecConstIterator;
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
class RunwayGroup
|
||||
{
|
||||
private:
|
||||
string name;
|
||||
RunwayListVec rwyList;
|
||||
int active;
|
||||
//stringVec runwayNames;
|
||||
int choice[2];
|
||||
int nrActive;
|
||||
public:
|
||||
RunwayGroup() {};
|
||||
RunwayGroup(const RunwayGroup &other);
|
||||
RunwayGroup &operator= (const RunwayGroup &other);
|
||||
|
||||
void setName(string nm) { name = nm; };
|
||||
void add(RunwayList list) { rwyList.push_back(list);};
|
||||
void setActive(const string& aptId, double windSpeed, double windHeading, double maxTail, double maxCross);
|
||||
|
||||
int getNrActiveRunways() { return nrActive;};
|
||||
void getActive(int i, string& name, string& type);
|
||||
|
||||
string getName() { return name; };
|
||||
void clear() { rwyList.clear(); };
|
||||
//void add(string, string);
|
||||
};
|
||||
|
||||
typedef vector<RunwayGroup> PreferenceList;
|
||||
typedef vector<RunwayGroup>::iterator PreferenceListIterator;
|
||||
typedef vector<RunwayGroup>::const_iterator PreferenceListConstIterator;
|
||||
/******************************************************************************/
|
||||
|
||||
class FGRunwayPreference : public XMLVisitor {
|
||||
private:
|
||||
string value;
|
||||
string scheduleName;
|
||||
|
||||
ScheduleTime comTimes; // Commercial Traffic;
|
||||
ScheduleTime genTimes; // General Aviation;
|
||||
ScheduleTime milTimes; // Military Traffic;
|
||||
ScheduleTime currTimes; // Needed for parsing;
|
||||
|
||||
RunwayList rwyList;
|
||||
RunwayGroup rwyGroup;
|
||||
PreferenceList preferences;
|
||||
|
||||
time_t processTime(const string&);
|
||||
bool initialized;
|
||||
|
||||
public:
|
||||
FGRunwayPreference();
|
||||
FGRunwayPreference(const FGRunwayPreference &other);
|
||||
|
||||
FGRunwayPreference & operator= (const FGRunwayPreference &other);
|
||||
ScheduleTime *getSchedule(const char *trafficType);
|
||||
RunwayGroup *getGroup(const string& groupName);
|
||||
bool available() { return initialized; };
|
||||
|
||||
// Some overloaded virtual XMLVisitor members
|
||||
virtual void startXML ();
|
||||
virtual void endXML ();
|
||||
virtual void startElement (const char * name, const XMLAttributes &atts);
|
||||
virtual void endElement (const char * name);
|
||||
virtual void data (const char * s, int len);
|
||||
virtual void pi (const char * target, const char * data);
|
||||
virtual void warning (const char * message, int line, int column);
|
||||
virtual void error (const char * message, int line, int column);
|
||||
};
|
||||
|
||||
double processPosition(const string& pos);
|
||||
|
||||
class FGParking {
|
||||
private:
|
||||
double latitude;
|
||||
double longitude;
|
||||
double heading;
|
||||
double radius;
|
||||
int index;
|
||||
string parkingName;
|
||||
string type;
|
||||
string airlineCodes;
|
||||
|
||||
bool available;
|
||||
|
||||
|
||||
|
||||
public:
|
||||
FGParking() { available = true;};
|
||||
//FGParking(FGParking &other);
|
||||
FGParking(double lat,
|
||||
double lon,
|
||||
double hdg,
|
||||
double rad,
|
||||
int idx,
|
||||
const string& name,
|
||||
const string& tpe,
|
||||
const string& codes);
|
||||
void setLatitude (const string& lat) { latitude = processPosition(lat); };
|
||||
void setLongitude(const string& lon) { longitude = processPosition(lon); };
|
||||
void setHeading (double hdg) { heading = hdg; };
|
||||
void setRadius (double rad) { radius = rad; };
|
||||
void setIndex (int idx) { index = idx; };
|
||||
void setName (const string& name) { parkingName = name; };
|
||||
void setType (const string& tpe) { type = tpe; };
|
||||
void setCodes (const string& codes){ airlineCodes= codes;};
|
||||
|
||||
bool isAvailable () { return available;};
|
||||
void setAvailable(bool val) { available = val; };
|
||||
|
||||
double getLatitude () { return latitude; };
|
||||
double getLongitude() { return longitude; };
|
||||
double getHeading () { return heading; };
|
||||
double getRadius () { return radius; };
|
||||
int getIndex () { return index; };
|
||||
string getType () { return type; };
|
||||
string getCodes () { return airlineCodes;};
|
||||
string getName () { return parkingName; };
|
||||
|
||||
bool operator< (const FGParking &other) const {return radius < other.radius; };
|
||||
};
|
||||
|
||||
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 (const string& val) { lat = processPosition(val); };
|
||||
void setLongitude(const 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 (const FGTaxiNode& node);
|
||||
void addNodes (FGParkingVec *parkings);
|
||||
void addSegment(const 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{
|
||||
class FGAirport {
|
||||
private:
|
||||
string _id;
|
||||
double _longitude; // degrees
|
||||
double _latitude; // degrees
|
||||
double _elevation; // ft
|
||||
string _code; // depricated and can be removed
|
||||
string _name;
|
||||
bool _has_metar;
|
||||
FGParkingVec parkings;
|
||||
FGRunwayPreference rwyPrefs;
|
||||
FGGroundNetwork groundNetwork;
|
||||
|
||||
time_t lastUpdate;
|
||||
string prevTrafficType;
|
||||
stringVec landing;
|
||||
stringVec takeoff;
|
||||
|
||||
// Experimental keep a running average of wind dir and speed to prevent
|
||||
// Erratic runway changes.
|
||||
// Note: I should add these to the copy constructor and assigment operator to be
|
||||
// constistent
|
||||
double avWindHeading [10];
|
||||
double avWindSpeed [10];
|
||||
|
||||
string chooseRunwayFallback();
|
||||
FGAirportDynamics *dynamics;
|
||||
|
||||
public:
|
||||
FGAirport();
|
||||
FGAirport(const FGAirport &other);
|
||||
//operator= (FGAirport &other);
|
||||
// FGAirport(const FGAirport &other);
|
||||
FGAirport(const string& id, double lon, double lat, double elev, const string& name, bool has_metar);
|
||||
~FGAirport();
|
||||
|
||||
void init();
|
||||
void getActiveRunway(const string& trafficType, int action, string& runway);
|
||||
bool getAvailableParking(double *lat, double *lon, double *heading, int *gate, double rad, const string& fltype,
|
||||
const string& acType, const string& airline);
|
||||
void getParking (int id, double *lat, double* lon, double *heading);
|
||||
FGParking *getParking(int i); // { if (i < parkings.size()) return parkings[i]; else return 0;};
|
||||
void releaseParking(int id);
|
||||
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
|
||||
double getLatitude() const { return _latitude; };
|
||||
// Returns ft
|
||||
double getElevation() const { return _elevation;};
|
||||
bool getMetar() const { return _has_metar;};
|
||||
FGGroundNetwork* getGroundNetwork() { return &groundNetwork; };
|
||||
|
||||
|
||||
void setId(const string& id) { _id = id;};
|
||||
void setMetar(bool value) { _has_metar = value; };
|
||||
|
||||
void setRwyUse(const FGRunwayPreference& ref);
|
||||
|
||||
// Some overloaded virtual XMLVisitor members
|
||||
virtual void startXML ();
|
||||
virtual void endXML ();
|
||||
virtual void startElement (const char * name, const XMLAttributes &atts);
|
||||
virtual void endElement (const char * name);
|
||||
virtual void data (const char * s, int len);
|
||||
virtual void pi (const char * target, const char * data);
|
||||
virtual void warning (const char * message, int line, int column);
|
||||
virtual void error (const char * message, int line, int column);
|
||||
FGAirportDynamics *getDynamics();
|
||||
private:
|
||||
FGAirport operator=(FGAirport &other);
|
||||
FGAirport(const FGAirport&);
|
||||
};
|
||||
|
||||
typedef map < string, FGAirport* > airport_map;
|
||||
|
@ -454,7 +111,7 @@ private:
|
|||
|
||||
airport_map airports_by_id;
|
||||
airport_list airports_array;
|
||||
set < string > ai_dirs;
|
||||
//set < string > ai_dirs;
|
||||
|
||||
public:
|
||||
|
||||
|
@ -514,6 +171,14 @@ public:
|
|||
|
||||
};
|
||||
|
||||
// find basic airport location info from airport database
|
||||
const FGAirport *fgFindAirportID( const string& id);
|
||||
|
||||
// get airport elevation
|
||||
double fgGetAirportElev( const string& id );
|
||||
|
||||
// get airport position
|
||||
Point3D fgGetAirportPos( const string& id );
|
||||
|
||||
#endif // _FG_SIMPLE_HXX
|
||||
|
||||
|
|
|
@ -644,7 +644,6 @@ void TgtAptDialog_OK (puObject *)
|
|||
int NewWaypoint( const string& Tgt_Alt )
|
||||
{
|
||||
string TgtAptId;
|
||||
FGAirport a;
|
||||
FGFix f;
|
||||
|
||||
double alt = 0.0;
|
||||
|
@ -661,15 +660,15 @@ int NewWaypoint( const string& Tgt_Alt )
|
|||
}
|
||||
|
||||
FGRouteMgr *rm = (FGRouteMgr *)globals->get_subsystem("route-manager");
|
||||
|
||||
if ( fgFindAirportID( TgtAptId, &a ) ) {
|
||||
const FGAirport *a = fgFindAirportID( TgtAptId);
|
||||
if (a) {
|
||||
|
||||
SG_LOG( SG_GENERAL, SG_INFO,
|
||||
"Adding waypoint (airport) = " << TgtAptId );
|
||||
|
||||
sprintf( NewTgtAirportId, "%s", TgtAptId.c_str() );
|
||||
|
||||
SGWayPoint wp( a.getLongitude(), a.getLatitude(), alt,
|
||||
SGWayPoint wp( a->getLongitude(), a->getLatitude(), alt,
|
||||
SGWayPoint::WGS84, TgtAptId );
|
||||
rm->add_waypoint( wp );
|
||||
|
||||
|
|
|
@ -328,7 +328,8 @@ FGMetarEnvironmentCtrl::FGMetarEnvironmentCtrl ()
|
|||
_error_count( 0 ),
|
||||
_stale_count( 0 ),
|
||||
_dt( 0.0 ),
|
||||
_error_dt( 0.0 )
|
||||
_error_dt( 0.0 ),
|
||||
last_apt(0)
|
||||
{
|
||||
#if defined(ENABLE_THREADS)
|
||||
thread = new MetarThread(this);
|
||||
|
@ -412,7 +413,7 @@ FGMetarEnvironmentCtrl::init ()
|
|||
if ( result.m != NULL ) {
|
||||
SG_LOG( SG_GENERAL, SG_INFO, "closest station w/ metar = "
|
||||
<< a->getId());
|
||||
last_apt = *a;
|
||||
last_apt = a;
|
||||
_icao = a->getId();
|
||||
search_elapsed = 0.0;
|
||||
fetch_elapsed = 0.0;
|
||||
|
@ -470,13 +471,13 @@ FGMetarEnvironmentCtrl::update(double delta_time_sec)
|
|||
latitude->getDoubleValue(),
|
||||
true );
|
||||
if ( a ) {
|
||||
if ( last_apt.getId() != a->getId()
|
||||
if ( !last_apt || last_apt->getId() != a->getId()
|
||||
|| fetch_elapsed > same_station_interval_sec )
|
||||
{
|
||||
SG_LOG( SG_GENERAL, SG_INFO, "closest station w/ metar = "
|
||||
<< a->getId());
|
||||
request_queue.push( a->getId() );
|
||||
last_apt = *a;
|
||||
last_apt = a;
|
||||
_icao = a->getId();
|
||||
search_elapsed = 0.0;
|
||||
fetch_elapsed = 0.0;
|
||||
|
|
|
@ -173,7 +173,7 @@ private:
|
|||
float same_station_interval_sec;
|
||||
float search_elapsed;
|
||||
float fetch_elapsed;
|
||||
FGAirport last_apt;
|
||||
const FGAirport *last_apt;
|
||||
SGPropertyNode *proxy_host;
|
||||
SGPropertyNode *proxy_port;
|
||||
SGPropertyNode *proxy_auth;
|
||||
|
|
|
@ -35,7 +35,6 @@
|
|||
#include <stdlib.h>
|
||||
#include <string.h> // strcmp()
|
||||
|
||||
|
||||
#if defined( unix ) || defined( __CYGWIN__ )
|
||||
# include <unistd.h> // for gethostname()
|
||||
#endif
|
||||
|
@ -625,48 +624,7 @@ bool fgInitConfig ( int argc, char **argv ) {
|
|||
}
|
||||
|
||||
|
||||
// find basic airport location info from airport database
|
||||
bool fgFindAirportID( const string& id, FGAirport *a ) {
|
||||
const FGAirport* result;
|
||||
if ( id.length() ) {
|
||||
SG_LOG( SG_GENERAL, SG_INFO, "Searching for airport code = " << id );
|
||||
|
||||
result = globals->get_airports()->search( id );
|
||||
|
||||
if ( result == NULL ) {
|
||||
SG_LOG( SG_GENERAL, SG_ALERT,
|
||||
"Failed to find " << id << " in apt.dat.gz" );
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
*a = *result;
|
||||
|
||||
SG_LOG( SG_GENERAL, SG_INFO,
|
||||
"Position for " << id << " is ("
|
||||
<< a->getLongitude() << ", "
|
||||
<< a->getLatitude() << ")" );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// get airport elevation
|
||||
static double fgGetAirportElev( const string& id ) {
|
||||
FGAirport a;
|
||||
// double lon, lat;
|
||||
|
||||
SG_LOG( SG_GENERAL, SG_INFO,
|
||||
"Finding elevation for airport: " << id );
|
||||
|
||||
if ( fgFindAirportID( id, &a ) ) {
|
||||
return a.getElevation();
|
||||
} else {
|
||||
return -9999.0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
|
@ -676,7 +634,7 @@ static double fgGetAirportElev( const string& id ) {
|
|||
|
||||
// Preset lon/lat given an airport id
|
||||
static bool fgSetPosFromAirportID( const string& id ) {
|
||||
FGAirport a;
|
||||
FGAirport *a;
|
||||
// double lon, lat;
|
||||
|
||||
SG_LOG( SG_GENERAL, SG_INFO,
|
||||
|
@ -684,17 +642,17 @@ static bool fgSetPosFromAirportID( const string& id ) {
|
|||
|
||||
if ( fgFindAirportID( id, &a ) ) {
|
||||
// presets
|
||||
fgSetDouble("/sim/presets/longitude-deg", a.longitude );
|
||||
fgSetDouble("/sim/presets/latitude-deg", a.latitude );
|
||||
fgSetDouble("/sim/presets/longitude-deg", a->longitude );
|
||||
fgSetDouble("/sim/presets/latitude-deg", a->latitude );
|
||||
|
||||
// other code depends on the actual postition being set so set
|
||||
// that as well
|
||||
fgSetDouble("/position/longitude-deg", a.longitude );
|
||||
fgSetDouble("/position/latitude-deg", a.latitude );
|
||||
fgSetDouble("/position/longitude-deg", a->longitude );
|
||||
fgSetDouble("/position/latitude-deg", a->latitude );
|
||||
|
||||
SG_LOG( SG_GENERAL, SG_INFO,
|
||||
"Position for " << id << " is (" << a.longitude
|
||||
<< ", " << a.latitude << ")" );
|
||||
"Position for " << id << " is (" << a->longitude
|
||||
<< ", " << a->latitude << ")" );
|
||||
|
||||
return true;
|
||||
} else {
|
||||
|
@ -706,7 +664,7 @@ static bool fgSetPosFromAirportID( const string& id ) {
|
|||
|
||||
// Set current tower position lon/lat given an airport id
|
||||
static bool fgSetTowerPosFromAirportID( const string& id, double hdg ) {
|
||||
FGAirport a;
|
||||
|
||||
// tower height hard coded for now...
|
||||
float towerheight=50.0f;
|
||||
|
||||
|
@ -714,10 +672,11 @@ static bool fgSetTowerPosFromAirportID( const string& id, double hdg ) {
|
|||
float fudge_lon = fabs(sin(hdg)) * .003f;
|
||||
float fudge_lat = .003f - fudge_lon;
|
||||
|
||||
if ( fgFindAirportID( id, &a ) ) {
|
||||
fgSetDouble("/sim/tower/longitude-deg", a.getLongitude() + fudge_lon);
|
||||
fgSetDouble("/sim/tower/latitude-deg", a.getLatitude() + fudge_lat);
|
||||
fgSetDouble("/sim/tower/altitude-ft", a.getElevation() + towerheight);
|
||||
const FGAirport *a = fgFindAirportID( id);
|
||||
if ( a) {
|
||||
fgSetDouble("/sim/tower/longitude-deg", a->getLongitude() + fudge_lon);
|
||||
fgSetDouble("/sim/tower/latitude-deg", a->getLatitude() + fudge_lat);
|
||||
fgSetDouble("/sim/tower/altitude-ft", a->getElevation() + towerheight);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
|
@ -1578,7 +1537,6 @@ bool fgInitSubsystems() {
|
|||
// = fgGetNode("/sim/presets/latitude-deg");
|
||||
// static const SGPropertyNode *altitude
|
||||
// = fgGetNode("/sim/presets/altitude-ft");
|
||||
|
||||
SG_LOG( SG_GENERAL, SG_INFO, "Initialize Subsystems");
|
||||
SG_LOG( SG_GENERAL, SG_INFO, "========== ==========");
|
||||
|
||||
|
@ -1879,7 +1837,7 @@ bool fgInitSubsystems() {
|
|||
// Save the initial state for future
|
||||
// reference.
|
||||
globals->saveInitialState();
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue