1
0
Fork 0

Durk Talsma, Olaf Flebbe & Mathias Frhlich:

Split up simple.cxx
This commit is contained in:
ehofman 2005-12-29 13:58:21 +00:00
parent c3f1331e52
commit 4be621fbe9
26 changed files with 2386 additions and 2002 deletions

View file

@ -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"))
// {
//

View file

@ -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;

View file

@ -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';

View file

@ -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;

View file

@ -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;

View file

@ -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();

View file

@ -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);

View file

@ -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) {

View file

@ -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

View file

@ -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()) {

View file

@ -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();

View file

@ -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
View 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
View 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

View 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;
}

View 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
View 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
View 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

View 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;
}

View 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

View file

@ -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

View file

@ -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 );

View file

@ -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;

View file

@ -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;

View file

@ -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;
}