1
0
Fork 0

Merge branch 'next' of D:\Git_New\flightgear into next

This commit is contained in:
Vivian Meazza 2010-08-30 09:49:42 +01:00
commit 8ca420ec53
17 changed files with 2404 additions and 1490 deletions

View file

@ -83,12 +83,17 @@ Typical setup should decompose into the following steps :
10. Open file D:\FGFSDevel\SimGear\simgear\version.h.in and change @VERSION@ into "2.0.0" or any current version 10. Open file D:\FGFSDevel\SimGear\simgear\version.h.in and change @VERSION@ into "2.0.0" or any current version
11. Save file as version.h in the same directory 11. Save file as version.h in the same directory
12. Start build (usually F7) 12. Start build (usually F7)
13. Wait... 13. Get the data from Gitorious too : git clone git://gitorious.org/fg/fgdata.git fgdata
14. Enjoy - programs are in D:\FGFSDevel\FlightGear\projects\VC90\Win32\Release 14. Wait...
15. Add <any_directory_on_any_drive>/install/msvc90/OpenSceneGraph/bin and <any_directory_on_any_drive>/3rdParty/bin to your PATH environment variable
16. Enjoy - programs are in D:\FGFSDevel\FlightGear\projects\VC90\Win32\Release
It is also possible to compile a Debug version. This is only useful when hacking the code because It is also possible to compile a Debug version. This is only useful when hacking the code because
a Debug version is way slower than the Release one. a Debug version is way slower than the Release one.
The 64bit build is only available to people having the Professional edition of Visual Studio 2008. In that case, 14. above should be :
14. Add <any_directory_on_any_drive>/install/msvc90-64/OpenSceneGraph/bin and <any_directory_on_any_drive>/3rdParty.x64/bin to your PATH environment variable
When the manual build works, it is possible to start it from the command line. This is useful When the manual build works, it is possible to start it from the command line. This is useful
when setting up a build server or automating the process of retrieving the code and building when setting up a build server or automating the process of retrieving the code and building
it in a scheduled task. To do that : it in a scheduled task. To do that :

View file

@ -1,4 +1,4 @@
// // // FGAIAircraft - FGAIBase-derived class creates an AI airplane // FGAIAircraft - FGAIBase-derived class creates an AI airplane
// //
// Written by David Culp, started October 2003. // Written by David Culp, started October 2003.
// //
@ -78,6 +78,8 @@ FGAIAircraft::FGAIAircraft(FGAISchedule *ref) : FGAIBase(otAircraft) {
roll = 0; roll = 0;
headingChangeRate = 0.0; headingChangeRate = 0.0;
headingError = 0; headingError = 0;
minBearing = 360;
speedFraction =1.0;
holdPos = false; holdPos = false;
needsTaxiClearance = false; needsTaxiClearance = false;
@ -257,6 +259,16 @@ void FGAIAircraft::ProcessFlightPlan( double dt, time_t now ) {
return; return;
dt_count = 0; dt_count = 0;
double distanceToDescent;
if(reachedEndOfCruise(distanceToDescent)) {
if (!loadNextLeg(distanceToDescent)) {
setDie(true);
return;
}
prev = fp->getPreviousWaypoint();
curr = fp->getCurrentWaypoint();
next = fp->getNextWaypoint();
}
if (! leadPointReached(curr)) { if (! leadPointReached(curr)) {
controlHeading(curr); controlHeading(curr);
controlSpeed(curr, next); controlSpeed(curr, next);
@ -278,7 +290,7 @@ void FGAIAircraft::ProcessFlightPlan( double dt, time_t now ) {
//TODO let the fp handle this (loading of next leg) //TODO let the fp handle this (loading of next leg)
fp->IncrementWaypoint( trafficRef != 0 ); fp->IncrementWaypoint( trafficRef != 0 );
if (!(fp->getNextWaypoint()) && trafficRef != 0) if ( ((!(fp->getNextWaypoint()))) && (trafficRef != 0) )
if (!loadNextLeg()) { if (!loadNextLeg()) {
setDie(true); setDie(true);
return; return;
@ -342,7 +354,7 @@ const char * FGAIAircraft::_getTransponderCode() const {
} }
bool FGAIAircraft::loadNextLeg() { bool FGAIAircraft::loadNextLeg(double distance) {
int leg; int leg;
if ((leg = fp->getLeg()) == 10) { if ((leg = fp->getLeg()) == 10) {
@ -374,7 +386,8 @@ bool FGAIAircraft::loadNextLeg() {
trafficRef->getRadius(), trafficRef->getRadius(),
trafficRef->getFlightType(), trafficRef->getFlightType(),
acType, acType,
company); company,
distance);
//cerr << "created leg " << leg << " for " << trafficRef->getCallSign() << endl; //cerr << "created leg " << leg << " for " << trafficRef->getCallSign() << endl;
} }
return true; return true;
@ -423,6 +436,7 @@ void FGAIAircraft::doGroundAltitude() {
altitude_ft = (tgt_altitude_ft + groundOffset); altitude_ft = (tgt_altitude_ft + groundOffset);
else else
altitude_ft += 0.1 * ((tgt_altitude_ft+groundOffset) - altitude_ft); altitude_ft += 0.1 * ((tgt_altitude_ft+groundOffset) - altitude_ft);
tgt_vs = 0;
} }
@ -449,6 +463,11 @@ void FGAIAircraft::announcePositionToController() {
cerr << "Error: Could not find Dynamics at airport : " << trafficRef->getDepartureAirport()->getId() << endl; cerr << "Error: Could not find Dynamics at airport : " << trafficRef->getDepartureAirport()->getId() << endl;
} }
break; break;
case 7:
if (trafficRef->getDepartureAirport()->getDynamics()) {
controller = trafficRef->getArrivalAirport()->getDynamics()->getApproachController();
}
break;
case 9: // Taxiing for parking case 9: // Taxiing for parking
if (trafficRef->getArrivalAirport()->getDynamics()->getGroundNetwork()->exists()) if (trafficRef->getArrivalAirport()->getDynamics()->getGroundNetwork()->exists())
controller = trafficRef->getArrivalAirport()->getDynamics()->getGroundNetwork(); controller = trafficRef->getArrivalAirport()->getDynamics()->getGroundNetwork();
@ -629,13 +648,34 @@ bool FGAIAircraft::leadPointReached(FGAIFlightPlan::waypoint* curr) {
// << dist_to_go << ": Lead distance " // << dist_to_go << ": Lead distance "
// << lead_dist << " " << curr->name // << lead_dist << " " << curr->name
// << " Ground target speed " << groundTargetSpeed << endl; // << " Ground target speed " << groundTargetSpeed << endl;
// if (trafficRef) { double bearing;
// if (trafficRef->getCallSign() == "Transavia7584") { if (speed > 50) { // don't do bearing calculations for ground traffic
// cerr << trafficRef->getCallSign() << " " << tgt_altitude_ft << " " << _getSpeed() << " " bearing = getBearing(fp->getBearing(pos.getLatitudeDeg(), pos.getLongitudeDeg(), curr));
// << _getAltitude() << " "<< _getLatitude() << " " << _getLongitude() << " " << dist_to_go << " " << lead_dist << curr->name << endl; if (bearing < minBearing) {
// } minBearing = bearing;
// } if (minBearing < 10) {
return dist_to_go < lead_dist; minBearing = 10;
}
if ((minBearing < 360.0) && (minBearing > 10.0)) {
speedFraction = cos(minBearing *SG_DEGREES_TO_RADIANS);
} else {
speedFraction = 1.0;
}
}
}
if (trafficRef) {
//cerr << "Tracking callsign : \"" << fgGetString("/ai/track-callsign") << "\"" << endl;
/* if (trafficRef->getCallSign() == fgGetString("/ai/track-callsign")) {
cerr << trafficRef->getCallSign() << " " << tgt_altitude_ft << " " << _getSpeed() << " "
<< _getAltitude() << " "<< _getLatitude() << " " << _getLongitude() << " " << dist_to_go << " " << lead_dist << " " << curr->name << " " << vs << " " << tgt_vs << " " << bearing << " " << minBearing << " " << speedFraction << endl;
}*/
}
if ((dist_to_go < lead_dist) || (bearing > (minBearing * 1.1))) {
minBearing = 360;
return true;
} else {
return false;
}
} }
@ -1024,7 +1064,7 @@ void FGAIAircraft::updateActualState() {
if (onGround()) if (onGround())
speed = _performance->actualSpeed(this, groundTargetSpeed, dt); speed = _performance->actualSpeed(this, groundTargetSpeed, dt);
else else
speed = _performance->actualSpeed(this, tgt_speed, dt); speed = _performance->actualSpeed(this, (tgt_speed *speedFraction), dt);
updateHeading(); updateHeading();
roll = _performance->actualBankAngle(this, tgt_roll, dt); roll = _performance->actualBankAngle(this, tgt_roll, dt);
@ -1045,3 +1085,89 @@ void FGAIAircraft::updateSecondaryTargetValues() {
//TODO calculate wind correction angle (tgt_yaw) //TODO calculate wind correction angle (tgt_yaw)
} }
bool FGAIAircraft::reachedEndOfCruise(double &distance) {
FGAIFlightPlan::waypoint* curr = fp->getCurrentWaypoint();
if (curr->name == "BOD") {
double dist = fp->getDistanceToGo(pos.getLatitudeDeg(), pos.getLongitudeDeg(), curr);
double descentSpeed = (getPerformance()->vDescent() * SG_NM_TO_METER) / 3600.0; // convert from kts to meter/s
double descentRate = (getPerformance()->descentRate() * SG_FEET_TO_METER) / 60.0; // convert from feet/min to meter/s
double verticalDistance = ((altitude_ft - 2000.0) - trafficRef->getArrivalAirport()->getElevation()) *SG_FEET_TO_METER;
double descentTimeNeeded = verticalDistance / descentRate;
double distanceCovered = descentSpeed * descentTimeNeeded;
//cerr << "Tracking : " << fgGetString("/ai/track-callsign");
if (trafficRef->getCallSign() == fgGetString("/ai/track-callsign")) {
cerr << "Checking for end of cruise stage for :" << trafficRef->getCallSign() << endl;
cerr << "Descent rate : " << descentRate << endl;
cerr << "Descent speed : " << descentSpeed << endl;
cerr << "VerticalDistance : " << verticalDistance << ". Altitude : " << altitude_ft << ". Elevation " << trafficRef->getArrivalAirport()->getElevation() << endl;
cerr << "DecentTimeNeeded : " << descentTimeNeeded << endl;
cerr << "DistanceCovered : " << distanceCovered << endl;
}
//cerr << "Distance = " << distance << endl;
distance = distanceCovered;
if (dist < distanceCovered) {
if (trafficRef->getCallSign() == fgGetString("/ai/track-callsign")) {
//exit(1);
}
return true;
} else {
return false;
}
} else {
return false;
}
}
void FGAIAircraft::resetPositionFromFlightPlan()
{
// the one behind you
FGAIFlightPlan::waypoint* prev = 0;
// the one ahead
FGAIFlightPlan::waypoint* curr = 0;
// the next plus 1
FGAIFlightPlan::waypoint* next = 0;
prev = fp->getPreviousWaypoint();
curr = fp->getCurrentWaypoint();
next = fp->getNextWaypoint();
setLatitude(prev->latitude);
setLongitude(prev->longitude);
double tgt_heading = fp->getBearing(curr, next);
setHeading(tgt_heading);
setAltitude(prev->altitude);
setSpeed(prev->speed);
}
double FGAIAircraft::getBearing(double crse)
{
double hdgDiff = fabs(hdg-crse);
if (hdgDiff > 180)
hdgDiff = fabs(hdgDiff - 360);
return hdgDiff;
}
time_t FGAIAircraft::checkForArrivalTime(string wptName) {
FGAIFlightPlan::waypoint* curr = 0;
curr = fp->getCurrentWaypoint();
double tracklength = fp->checkTrackLength(wptName);
if (tracklength > 0.1) {
tracklength += fp->getDistanceToGo(pos.getLatitudeDeg(), pos.getLongitudeDeg(), curr);
} else {
return 0;
}
time_t now = time(NULL) + fgGetLong("/sim/time/warp");
time_t arrivalTime = fp->getArrivalTime();
time_t ete = tracklength / ((speed * SG_NM_TO_METER) / 3600.0);
time_t secondsToGo = arrivalTime - now;
if (trafficRef->getCallSign() == fgGetString("/ai/track-callsign")) {
cerr << "Checking arrival time: ete " << ete << ". Time to go : " << secondsToGo << ". Track length = " << tracklength << endl;
}
return (ete - secondsToGo); // Positive when we're too slow...
}

View file

@ -53,6 +53,7 @@ public:
void initializeFlightPlan(); void initializeFlightPlan();
FGAIFlightPlan* GetFlightPlan() const { return fp; }; FGAIFlightPlan* GetFlightPlan() const { return fp; };
void ProcessFlightPlan( double dt, time_t now ); void ProcessFlightPlan( double dt, time_t now );
time_t checkForArrivalTime(string wptName);
void AccelTo(double speed); void AccelTo(double speed);
void PitchTo(double angle); void PitchTo(double angle);
@ -63,7 +64,9 @@ public:
void getGroundElev(double dt); //TODO these 3 really need to be public? void getGroundElev(double dt); //TODO these 3 really need to be public?
void doGroundAltitude(); void doGroundAltitude();
bool loadNextLeg (); bool loadNextLeg (double dist=0);
void resetPositionFromFlightPlan();
double getBearing(double crse);
void setAcType(const std::string& ac) { acType = ac; }; void setAcType(const std::string& ac) { acType = ac; };
void setCompany(const std::string& comp) { company = comp;}; void setCompany(const std::string& comp) { company = comp;};
@ -90,6 +93,7 @@ public:
inline double altitudeAGL() const { return props->getFloatValue("position/altitude-agl-ft");}; inline double altitudeAGL() const { return props->getFloatValue("position/altitude-agl-ft");};
inline double airspeed() const { return props->getFloatValue("velocities/airspeed-kt");}; inline double airspeed() const { return props->getFloatValue("velocities/airspeed-kt");};
std::string atGate(); std::string atGate();
protected: protected:
void Run(double dt); void Run(double dt);
@ -104,6 +108,8 @@ private:
double dt_elev_count; double dt_elev_count;
double headingChangeRate; double headingChangeRate;
double headingError; double headingError;
double minBearing;
double speedFraction;
double groundTargetSpeed; double groundTargetSpeed;
double groundOffset; double groundOffset;
double dt; double dt;
@ -118,6 +124,7 @@ private:
void handleFirstWaypoint(void); void handleFirstWaypoint(void);
bool leadPointReached(FGAIFlightPlan::waypoint* curr); bool leadPointReached(FGAIFlightPlan::waypoint* curr);
bool handleAirportEndPoints(FGAIFlightPlan::waypoint* prev, time_t now); bool handleAirportEndPoints(FGAIFlightPlan::waypoint* prev, time_t now);
bool reachedEndOfCruise(double&);
bool aiTrafficVisible(void); bool aiTrafficVisible(void);
void controlHeading(FGAIFlightPlan::waypoint* curr); void controlHeading(FGAIFlightPlan::waypoint* curr);
void controlSpeed(FGAIFlightPlan::waypoint* curr, void controlSpeed(FGAIFlightPlan::waypoint* curr,

View file

@ -187,8 +187,8 @@ FGAIFlightPlan::FGAIFlightPlan(FGAIAircraft *ac,
time_t now = time(NULL) + fgGetLong("/sim/time/warp"); time_t now = time(NULL) + fgGetLong("/sim/time/warp");
time_t timeDiff = now-start; time_t timeDiff = now-start;
leg = 1; leg = 1;
/*
if ((timeDiff > 300) && (timeDiff < 1200)) if ((timeDiff > 60) && (timeDiff < 1200))
leg = 2; leg = 2;
else if ((timeDiff >= 1200) && (timeDiff < 1500)) else if ((timeDiff >= 1200) && (timeDiff < 1500))
leg = 3; leg = 3;
@ -196,14 +196,15 @@ FGAIFlightPlan::FGAIFlightPlan(FGAIAircraft *ac,
leg = 4; leg = 4;
else if (timeDiff >= 2000) else if (timeDiff >= 2000)
leg = 5; leg = 5;
*/ /*
if (timeDiff >= 2000) if (timeDiff >= 2000)
leg = 5; leg = 5;
*/
SG_LOG(SG_GENERAL, SG_INFO, "Route from " << dep->getId() << " to " << arr->getId() << ". Set leg to : " << leg << " " << ac->getTrafficRef()->getCallSign()); SG_LOG(SG_GENERAL, SG_INFO, "Route from " << dep->getId() << " to " << arr->getId() << ". Set leg to : " << leg << " " << ac->getTrafficRef()->getCallSign());
wpt_iterator = waypoints.begin(); wpt_iterator = waypoints.begin();
bool dist = 0;
create(ac, dep,arr, leg, alt, speed, lat, lon, create(ac, dep,arr, leg, alt, speed, lat, lon,
firstLeg, radius, fltType, acType, airline); firstLeg, radius, fltType, acType, airline, dist);
wpt_iterator = waypoints.begin(); wpt_iterator = waypoints.begin();
//cerr << "after create: " << (*wpt_iterator)->name << endl; //cerr << "after create: " << (*wpt_iterator)->name << endl;
//leg++; //leg++;
@ -411,6 +412,7 @@ void FGAIFlightPlan::setLeadDistance(double speed, double bearing,
//lead_distance = turn_radius * sin(leadInAngle * SG_DEGREES_TO_RADIANS); //lead_distance = turn_radius * sin(leadInAngle * SG_DEGREES_TO_RADIANS);
lead_distance = turn_radius * tan((leadInAngle * SG_DEGREES_TO_RADIANS)/2); lead_distance = turn_radius * tan((leadInAngle * SG_DEGREES_TO_RADIANS)/2);
/*
if ((lead_distance > (3*turn_radius)) && (current->on_ground == false)) { if ((lead_distance > (3*turn_radius)) && (current->on_ground == false)) {
// cerr << "Warning: Lead-in distance is large. Inbound = " << inbound // cerr << "Warning: Lead-in distance is large. Inbound = " << inbound
// << ". Outbound = " << outbound << ". Lead in angle = " << leadInAngle << ". Turn radius = " << turn_radius << endl; // << ". Outbound = " << outbound << ". Lead in angle = " << leadInAngle << ". Turn radius = " << turn_radius << endl;
@ -420,7 +422,7 @@ void FGAIFlightPlan::setLeadDistance(double speed, double bearing,
if ((leadInAngle > 90) && (current->on_ground == true)) { if ((leadInAngle > 90) && (current->on_ground == true)) {
lead_distance = turn_radius * tan((90 * SG_DEGREES_TO_RADIANS)/2); lead_distance = turn_radius * tan((90 * SG_DEGREES_TO_RADIANS)/2);
return; return;
} }*/
} }
void FGAIFlightPlan::setLeadDistance(double distance_ft){ void FGAIFlightPlan::setLeadDistance(double distance_ft){
@ -493,3 +495,20 @@ int FGAIFlightPlan::getRouteIndex(int i) {
else else
return 0; return 0;
} }
double FGAIFlightPlan::checkTrackLength(string wptName) {
// skip the first two waypoints: first one is behind, second one is partially done;
double trackDistance = 0;
wpt_vector_iterator wptvec = waypoints.begin();
wptvec++;
wptvec++;
while ((wptvec != waypoints.end()) && ((*wptvec)->name != wptName)) {
trackDistance += (*wptvec)->trackLength;
wptvec++;
}
if (wptvec == waypoints.end()) {
trackDistance = 0; // name not found
}
return trackDistance;
}

View file

@ -55,6 +55,7 @@ public:
bool on_ground; bool on_ground;
int routeIndex; // For AI/ATC purposes; int routeIndex; // For AI/ATC purposes;
double time_sec; double time_sec;
double trackLength; // distance from previous waypoint (for AI purposes);
string time; string time;
} waypoint; } waypoint;
@ -90,10 +91,12 @@ public:
double getLeadDistance( void ) const {return lead_distance;} double getLeadDistance( void ) const {return lead_distance;}
double getBearing(waypoint* previous, waypoint* next) const; double getBearing(waypoint* previous, waypoint* next) const;
double getBearing(double lat, double lon, waypoint* next) const; double getBearing(double lat, double lon, waypoint* next) const;
double checkTrackLength(string wptName);
time_t getStartTime() const { return start_time; } time_t getStartTime() const { return start_time; }
time_t getArrivalTime() const { return arrivalTime; }
void create(FGAIAircraft *, FGAirport *dep, FGAirport *arr, int leg, double alt, double speed, double lat, double lon, void create(FGAIAircraft *, FGAirport *dep, FGAirport *arr, int leg, double alt, double speed, double lat, double lon,
bool firstLeg, double radius, const string& fltType, const string& aircraftType, const string& airline); bool firstLeg, double radius, const string& fltType, const string& aircraftType, const string& airline, double distance);
void setLeg(int val) { leg = val;} void setLeg(int val) { leg = val;}
void setTime(time_t st) { start_time = st; } void setTime(time_t st) { start_time = st; }
@ -128,6 +131,7 @@ private:
typedef vector <waypoint*> wpt_vector_type; typedef vector <waypoint*> wpt_vector_type;
typedef wpt_vector_type::const_iterator wpt_vector_iterator; typedef wpt_vector_type::const_iterator wpt_vector_iterator;
wpt_vector_type waypoints; wpt_vector_type waypoints;
wpt_vector_iterator wpt_iterator; wpt_vector_iterator wpt_iterator;
@ -136,6 +140,7 @@ private:
double lead_distance; double lead_distance;
double leadInAngle; double leadInAngle;
time_t start_time; time_t start_time;
time_t arrivalTime; // For AI/ATC purposes.
int leg; int leg;
int gateId, lastNodeVisited; int gateId, lastNodeVisited;
string activeRunway; string activeRunway;
@ -148,7 +153,7 @@ private:
void createTakeOff(FGAIAircraft *, bool, FGAirport *, double, const string&); void createTakeOff(FGAIAircraft *, bool, FGAirport *, double, const string&);
void createClimb(FGAIAircraft *, bool, FGAirport *, double, double, const string&); void createClimb(FGAIAircraft *, bool, FGAirport *, double, double, const string&);
void createCruise(FGAIAircraft *, bool, FGAirport*, FGAirport*, double, double, double, double, const string&); void createCruise(FGAIAircraft *, bool, FGAirport*, FGAirport*, double, double, double, double, const string&);
void createDecent(FGAIAircraft *, FGAirport *, const string&); void createDescent(FGAIAircraft *, FGAirport *, double latitude, double longitude, double speed, double alt,const string&, double distance);
void createLanding(FGAIAircraft *, FGAirport *, const string&); void createLanding(FGAIAircraft *, FGAirport *, const string&);
void createParking(FGAIAircraft *, FGAirport *, double radius); void createParking(FGAIAircraft *, FGAirport *, double radius);
void deleteWaypoints(); void deleteWaypoints();
@ -158,6 +163,8 @@ private:
void createDefaultLandingTaxi(FGAIAircraft *, FGAirport* aAirport); void createDefaultLandingTaxi(FGAIAircraft *, FGAirport* aAirport);
void createDefaultTakeoffTaxi(FGAIAircraft *, FGAirport* aAirport, FGRunway* aRunway); void createDefaultTakeoffTaxi(FGAIAircraft *, FGAirport* aAirport, FGRunway* aRunway);
void createTakeoffTaxi(FGAIAircraft *, bool firstFlight, FGAirport *apt, double radius, const string& fltType, const string& acType, const string& airline); void createTakeoffTaxi(FGAIAircraft *, bool firstFlight, FGAirport *apt, double radius, const string& fltType, const string& acType, const string& airline);
double getTurnRadius(double, bool);
waypoint* createOnGround(FGAIAircraft *, const std::string& aName, const SGGeod& aPos, double aElev, double aSpeed); waypoint* createOnGround(FGAIAircraft *, const std::string& aName, const SGGeod& aPos, double aElev, double aSpeed);
waypoint* createInAir(FGAIAircraft *, const std::string& aName, const SGGeod& aPos, double aElev, double aSpeed); waypoint* createInAir(FGAIAircraft *, const std::string& aName, const SGGeod& aPos, double aElev, double aSpeed);

File diff suppressed because it is too large Load diff

View file

@ -300,8 +300,11 @@ void FGAIFlightPlan::createCruise(FGAIAircraft *ac, bool firstFlight, FGAirport
arr->getDynamics()->getActiveRunway(rwyClass, 2, activeRunway, heading); arr->getDynamics()->getActiveRunway(rwyClass, 2, activeRunway, heading);
rwy = arr->getRunwayByIdent(activeRunway); rwy = arr->getRunwayByIdent(activeRunway);
// begin descent 110km out // begin descent 110km out
SGGeod beginDescentPoint = rwy->pointOnCenterline(-110000); SGGeod beginDescentPoint = rwy->pointOnCenterline(0);
SGGeod secondaryDescentPoint = rwy->pointOnCenterline(-10000);
wpt = createInAir(ac, "BOD", beginDescentPoint, alt, vCruise); wpt = createInAir(ac, "BOD", beginDescentPoint, alt, vCruise);
waypoints.push_back(wpt);
wpt = createInAir(ac, "BOD2", secondaryDescentPoint, alt, vCruise);
waypoints.push_back(wpt); waypoints.push_back(wpt);
} }

File diff suppressed because it is too large Load diff

View file

@ -28,6 +28,8 @@
#include <simgear/compiler.h> #include <simgear/compiler.h>
// There is probably a better include than sg_geodesy to get the SG_NM_TO_METER...
#include <simgear/math/sg_geodesy.hxx>
#include <simgear/debug/logstream.hxx> #include <simgear/debug/logstream.hxx>
@ -185,6 +187,9 @@ public:
typedef vector<FGTrafficRecord> TrafficVector; typedef vector<FGTrafficRecord> TrafficVector;
typedef vector<FGTrafficRecord>::iterator TrafficVectorIterator; typedef vector<FGTrafficRecord>::iterator TrafficVectorIterator;
typedef vector<time_t> TimeVector;
typedef vector<time_t>::iterator TimeVectorIterator;
/*********************************************************************** /***********************************************************************
* Active runway, a utility class to keep track of which aircraft has * Active runway, a utility class to keep track of which aircraft has
@ -195,11 +200,18 @@ class ActiveRunway
private: private:
string rwy; string rwy;
int currentlyCleared; int currentlyCleared;
double distanceToFinal;
TimeVector estimatedArrivalTimes;
public: public:
ActiveRunway(string r, int cc) { rwy = r; currentlyCleared = cc; }; ActiveRunway(string r, int cc) { rwy = r; currentlyCleared = cc; distanceToFinal = 6.0 * SG_NM_TO_METER; };
string getRunwayName() { return rwy; }; string getRunwayName() { return rwy; };
int getCleared () { return currentlyCleared; }; int getCleared () { return currentlyCleared; };
double getApproachDistance() { return distanceToFinal; };
//time_t getEstApproachTime() { return estimatedArrival; };
//void setEstApproachTime(time_t time) { estimatedArrival = time; };
time_t requestTimeSlot(time_t eta);
}; };
typedef vector<ActiveRunway> ActiveRunwayVec; typedef vector<ActiveRunway> ActiveRunwayVec;
@ -207,7 +219,7 @@ typedef vector<ActiveRunway>::iterator ActiveRunwayVecIterator;
/** /**
* class FGATCController * class FGATCController
* NOTE: this class serves as an abstraction layer for all sorts of ATC controller. * NOTE: this class serves as an abstraction layer for all sorts of ATC controllers.
*************************************************************************************/ *************************************************************************************/
class FGATCController class FGATCController
{ {
@ -317,4 +329,33 @@ public:
}; };
/******************************************************************************
* class FGTowerControl
*****************************************************************************/
class FGApproachController : public FGATCController
{
private:
TrafficVector activeTraffic;
ActiveRunwayVec activeRunways;
public:
FGApproachController();
virtual ~FGApproachController() {};
virtual void announcePosition(int id, FGAIFlightPlan *intendedRoute, int currentRoute,
double lat, double lon,
double hdg, double spd, double alt, double radius, int leg,
FGAIAircraft *aircraft);
virtual void signOff(int id);
virtual void update(int id, double lat, double lon,
double heading, double speed, double alt, double dt);
virtual bool hasInstruction(int id);
virtual FGATCInstruction getInstruction(int id);
ActiveRunway* getRunway(string name);
bool hasActiveTraffic() { return activeTraffic.size() != 0; };
TrafficVector &getActiveTraffic() { return activeTraffic; };
};
#endif // _TRAFFIC_CONTROL_HXX #endif // _TRAFFIC_CONTROL_HXX

View file

@ -325,17 +325,21 @@ bool FGAirportDynamics::innerGetActiveRunway(const string & trafficType,
takeoff.clear(); takeoff.clear();
lastUpdate = dayStart; lastUpdate = dayStart;
prevTrafficType = trafficType; prevTrafficType = trafficType;
/*
FGEnvironment FGEnvironment
stationweather = stationweather =
((FGEnvironmentMgr *) globals->get_subsystem("environment")) ((FGEnvironmentMgr *) globals->get_subsystem("environment"))
->getEnvironment(getLatitude(), getLongitude(), ->getEnvironment(getLatitude(), getLongitude(),
getElevation()); getElevation());
*/
windSpeed = stationweather.get_wind_speed_kt(); windSpeed = fgGetInt("/environment/metar/base-wind-speed-kt"); //stationweather.get_wind_speed_kt();
windHeading = stationweather.get_wind_from_heading_deg(); windHeading = fgGetInt("/environment/metar/base-wind-dir-deg");
//stationweather.get_wind_from_heading_deg();
string scheduleName; string scheduleName;
//cerr << "finding active Runway for" << _ap->getId() << endl; //cerr << "finding active Runway for : " << _ap->getId() << endl;
//cerr << "Wind Heading : " << windHeading << endl;
//cerr << "Wind Speed : " << windSpeed << endl;
//cerr << "Nr of seconds since day start << " << dayStart << endl; //cerr << "Nr of seconds since day start << " << dayStart << endl;
ScheduleTime *currSched; ScheduleTime *currSched;
@ -347,7 +351,7 @@ bool FGAirportDynamics::innerGetActiveRunway(const string & trafficType,
scheduleName = currSched->getName(dayStart); scheduleName = currSched->getName(dayStart);
maxTail = currSched->getTailWind(); maxTail = currSched->getTailWind();
maxCross = currSched->getCrossWind(); maxCross = currSched->getCrossWind();
//cerr << "SChedule anme = " << scheduleName << endl; //cerr << "Current Schedule = : " << scheduleName << endl;
if (scheduleName.empty()) if (scheduleName.empty())
return false; return false;
//cerr << "C"<< endl; //cerr << "C"<< endl;
@ -371,6 +375,13 @@ bool FGAirportDynamics::innerGetActiveRunway(const string & trafficType,
currentlyActive = &ulActive; currentlyActive = &ulActive;
} }
//cerr << "Durrently active selection for " << trafficType << ": ";
for (stringVecIterator it = currentlyActive->begin();
it != currentlyActive->end(); it++) {
//cerr << (*it) << " ";
}
//cerr << endl;
currRunwayGroup->setActive(_ap, currRunwayGroup->setActive(_ap,
windSpeed, windSpeed,
windHeading, windHeading,

View file

@ -46,12 +46,13 @@ class FGAirportDynamics {
private: private:
FGAirport* _ap; FGAirport* _ap;
FGParkingVec parkings; FGParkingVec parkings;
FGRunwayPreference rwyPrefs; FGRunwayPreference rwyPrefs;
FGSidStar SIDs; FGSidStar SIDs;
FGStartupController startupController; FGStartupController startupController;
FGGroundNetwork groundNetwork; FGGroundNetwork groundNetwork;
FGTowerController towerController; FGTowerController towerController;
FGApproachController approachController;
time_t lastUpdate; time_t lastUpdate;
string prevTrafficType; string prevTrafficType;
@ -112,9 +113,10 @@ public:
// ATC related functions. // ATC related functions.
FGStartupController *getStartupController() { return &startupController; }; FGStartupController *getStartupController() { return &startupController; };
FGGroundNetwork *getGroundNetwork() { return &groundNetwork; }; FGGroundNetwork *getGroundNetwork() { return &groundNetwork; };
FGTowerController *getTowerController() { return &towerController; }; FGTowerController *getTowerController() { return &towerController; };
FGApproachController *getApproachController() { return &approachController; };
const string& getAtisInformation() { return atisInformation; }; const string& getAtisInformation() { return atisInformation; };
int getGroundFrequency(unsigned leg); //{ return freqGround.size() ? freqGround[0] : 0; }; int getGroundFrequency(unsigned leg); //{ return freqGround.size() ? freqGround[0] : 0; };

View file

@ -553,35 +553,46 @@ void FGGroundNetwork::update(int id, double lat, double lon,
current->clearResolveCircularWait(); current->clearResolveCircularWait();
current->setWaitsForId(0); current->setWaitsForId(0);
checkSpeedAdjustment(id, lat, lon, heading, speed, alt); checkSpeedAdjustment(id, lat, lon, heading, speed, alt);
checkHoldPosition(id, lat, lon, heading, speed, alt);
if (checkForCircularWaits(id)) {
i->setResolveCircularWait();
}
bool needsTaxiClearance = current->getAircraft()->getTaxiClearanceRequest(); bool needsTaxiClearance = current->getAircraft()->getTaxiClearanceRequest();
int state = current->getState(); if (!needsTaxiClearance) {
time_t now = time(NULL) + fgGetLong("/sim/time/warp"); checkHoldPosition(id, lat, lon, heading, speed, alt);
if ((now - lastTransmission) > 15) { if (checkForCircularWaits(id)) {
available = true; i->setResolveCircularWait();
} }
if (needsTaxiClearance && available) { } else {
transmit(&(*current), MSG_REQUEST_TAXI_CLEARANCE, ATC_AIR_TO_GROUND); current->setHoldPosition(true);
current->getAircraft()->setTaxiClearanceRequest(false); int state = current->getState();
current->setState(3); time_t now = time(NULL) + fgGetLong("/sim/time/warp");
lastTransmission = now; if ((now - lastTransmission) > 15) {
available = false; available = true;
} }
if ((state == 3) && available) { if ((state < 3) && available) {
transmit(&(*current), MSG_ISSUE_TAXI_CLEARANCE, ATC_GROUND_TO_AIR); transmit(&(*current), MSG_REQUEST_TAXI_CLEARANCE, ATC_AIR_TO_GROUND);
current->setState(4); current->setState(3);
lastTransmission = now; lastTransmission = now;
available = false; available = false;
} }
if ((state == 4) && available) { if ((state == 3) && available) {
transmit(&(*current), MSG_ACKNOWLEDGE_TAXI_CLEARANCE, ATC_AIR_TO_GROUND); transmit(&(*current), MSG_ISSUE_TAXI_CLEARANCE, ATC_GROUND_TO_AIR);
current->setState(0); current->setState(4);
lastTransmission = now; lastTransmission = now;
available = false; available = false;
}
if ((state == 4) && available) {
transmit(&(*current), MSG_ACKNOWLEDGE_TAXI_CLEARANCE, ATC_AIR_TO_GROUND);
current->setState(5);
lastTransmission = now;
available = false;
}
if ((state == 5) && available) {
current->setState(0);
current->getAircraft()->setTaxiClearanceRequest(false);
current->setHoldPosition(true);
available = false;
}
} }
} }
/** /**

View file

@ -73,6 +73,27 @@ SGGeod FGRunwayBase::pointOnCenterline(double aOffset) const
return result; return result;
} }
SGGeod FGRunwayBase::pointOffCenterline(double aOffset, double lateralOffset) const
{
SGGeod result;
SGGeod temp;
double dummyAz2;
double halfLengthMetres = lengthM() * 0.5;
SGGeodesy::direct(mPosition, _heading,
aOffset - halfLengthMetres,
temp, dummyAz2);
SGGeodesy::direct(temp, (_heading+90.0),
lateralOffset,
result, dummyAz2);
return result;
}
bool FGRunwayBase::isHardSurface() const bool FGRunwayBase::isHardSurface() const
{ {
return ((_surface_code == 1) || (_surface_code == 2)); return ((_surface_code == 1) || (_surface_code == 2));

View file

@ -52,6 +52,7 @@ public:
* opposited direction. 0.0 corresponds to the (non-displaced) threshold * opposited direction. 0.0 corresponds to the (non-displaced) threshold
*/ */
SGGeod pointOnCenterline(double aOffset) const; SGGeod pointOnCenterline(double aOffset) const;
SGGeod pointOffCenterline(double aOffset, double lateralOffset) const;
double lengthFt() const double lengthFt() const
{ return _length; } { return _length; }

View file

@ -41,375 +41,372 @@
* ScheduleTime * ScheduleTime
***************e*************************************************************/ ***************e*************************************************************/
void ScheduleTime::clear() void ScheduleTime::clear()
{
start.clear();
end.clear();
scheduleNames.clear();
}
ScheduleTime::ScheduleTime(const ScheduleTime &other)
{ {
//timeVec start; start.clear();
timeVecConstIterator i; end.clear();
for (i = other.start.begin(); i != other.start.end(); i++) scheduleNames.clear();
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) ScheduleTime::ScheduleTime(const ScheduleTime & other)
{ {
//timeVec start; //timeVec start;
clear(); timeVecConstIterator i;
timeVecConstIterator i; for (i = other.start.begin(); i != other.start.end(); i++)
for (i = other.start.begin(); i != other.start.end(); i++) start.push_back(*i);
start.push_back(*i); for (i = other.end.begin(); i != other.end.end(); i++)
for (i = other.end.begin(); i != other.end.end(); i++) end.push_back(*i);
end.push_back(*i); stringVecConstIterator k;
stringVecConstIterator k; for (k = other.scheduleNames.begin(); k != other.scheduleNames.end();
for (k = other.scheduleNames.begin(); k != other.scheduleNames.end(); k++) k++)
scheduleNames.push_back(*k); scheduleNames.push_back(*k);
//timeVec end; //timeVec end;
//stringVec scheduleNames; //stringVec scheduleNames;
tailWind = other.tailWind; tailWind = other.tailWind;
crssWind = other.tailWind; crssWind = other.tailWind;
return *this;
} }
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) string ScheduleTime::getName(time_t dayStart)
{ {
if ((start.size() != end.size()) || (start.size() != scheduleNames.size())) if ((start.size() != end.size())
{ || (start.size() != scheduleNames.size())) {
SG_LOG( SG_GENERAL, SG_INFO, "Unable to parse schedule times" ); SG_LOG(SG_GENERAL, SG_INFO, "Unable to parse schedule times");
exit(1); exit(1);
} } else {
else int nrItems = start.size();
{ //cerr << "Nr of items to process: " << nrItems << endl;
int nrItems = start.size(); if (nrItems > 0) {
//cerr << "Nr of items to process: " << nrItems << endl; for (unsigned int i = 0; i < start.size(); i++) {
if (nrItems > 0) //cerr << i << endl;
{ if ((dayStart >= start[i]) && (dayStart <= end[i]))
for (unsigned int i = 0; i < start.size(); i++) return scheduleNames[i];
{ }
//cerr << i << endl; }
if ((dayStart >= start[i]) && (dayStart <= end[i])) //couldn't find one so return 0;
return scheduleNames[i]; //cerr << "Returning 0 " << endl;
}
}
//couldn't find one so return 0;
//cerr << "Returning 0 " << endl;
} }
return string(""); return string("");
} }
/****************************************************************************** /******************************************************************************
* RunwayList * RunwayList
*****************************************************************************/ *****************************************************************************/
RunwayList::RunwayList(const RunwayList &other) RunwayList::RunwayList(const RunwayList & other)
{ {
type = other.type; type = other.type;
stringVecConstIterator i; stringVecConstIterator i;
for (i = other.preferredRunways.begin(); i != other.preferredRunways.end(); i++) for (i = other.preferredRunways.begin();
preferredRunways.push_back(*i); 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() RunwayList & RunwayList::operator=(const RunwayList & other)
{ {
type = ""; type = other.type;
preferredRunways.clear(); 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) RunwayGroup::RunwayGroup(const RunwayGroup & other)
{ {
name = other.name; name = other.name;
RunwayListVecConstIterator i; RunwayListVecConstIterator i;
for (i = other.rwyList.begin(); i != other.rwyList.end(); i++) for (i = other.rwyList.begin(); i != other.rwyList.end(); i++)
rwyList.push_back(*i); rwyList.push_back(*i);
choice[0] = other.choice[0]; choice[0] = other.choice[0];
choice[1] = other.choice[1]; choice[1] = other.choice[1];
nrActive = other.nrActive; 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 FGAirport* airport, RunwayGroup & RunwayGroup::operator=(const RunwayGroup & other)
double windSpeed, {
double windHeading, rwyList.clear();
double maxTail, name = other.name;
double maxCross, RunwayListVecConstIterator i;
stringVec *currentlyActive) 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 FGAirport * airport,
double windSpeed,
double windHeading,
double maxTail,
double maxCross, stringVec * currentlyActive)
{ {
FGRunway* rwy; FGRunway *rwy;
int activeRwys = rwyList.size(); // get the number of runways active int activeRwys = rwyList.size(); // get the number of runways active
int nrOfPreferences; int nrOfPreferences;
// bool found = true; // bool found = true;
// double heading; // double heading;
double hdgDiff; double hdgDiff;
double crossWind; double crossWind;
double tailWind; double tailWind;
string name; string name;
//stringVec names; //stringVec names;
int bestMatch = 0, bestChoice = 0; int bestMatch = 0, bestChoice = 0;
if (activeRwys > 0) if (activeRwys > 0) {
{ // Now downward iterate across all the possible preferences
// Now downward iterate across all the possible preferences // starting by the least preferred choice working toward the most preferred choice
// starting by the least preferred choice working toward the most preferred choice
nrOfPreferences = rwyList[0].getRwyList()->size(); nrOfPreferences = rwyList[0].getRwyList()->size();
bool validSelection = true; bool validSelection = true;
bool foundValidSelection = false; bool foundValidSelection = false;
for (int i = nrOfPreferences-1; i >= 0; i--) for (int i = nrOfPreferences - 1; i >= 0; i--) {
{ int match = 0;
int match = 0;
// Test each runway listed in the preference to see if it's possible to use
// If one runway of the selection isn't allowed, we need to exclude this
// preference, however, we don't want to stop right there, because we also
// don't want to randomly swap runway preferences, unless there is a need to.
//
validSelection = true;
for (int j = 0; j < activeRwys; j++)
{
string ident(rwyList[j].getRwyList(i));
if (!airport->hasRunwayWithIdent(ident)) {
SG_LOG(SG_GENERAL, SG_WARN, "no such runway:" << ident << " at " << airport->ident());
continue;
}
rwy = airport->getRunwayByIdent(ident);
//cerr << "Succes" << endl;
hdgDiff = fabs(windHeading - rwy->headingDeg());
//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;
//cerr << ". Crosswnd : " << crossWind;
if ((tailWind > maxTail) || (crossWind > maxCross))
{
//cerr << ". [Invalid] " << endl;
validSelection = false;
}
else
{
//cerr << ". [Valid] ";
}
//cerr << endl;
} // of active runways iteration
if (validSelection)
{
//cerr << "Valid selection : " << i << endl;;
foundValidSelection = true;
for (stringVecIterator it = currentlyActive->begin();
it != currentlyActive->end(); it++)
{
if ((*it) == name)
match++;
}
if (match >= bestMatch) {
bestMatch = match;
bestChoice = i;
}
}
//cerr << "Preference " << i << " bestMatch " << bestMatch << " choice " << bestChoice << endl;
}
if (foundValidSelection)
{
//cerr << "Valid runay selection : " << bestChoice << endl;
nrActive = activeRwys;
active = bestChoice;
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++)
{
name = rwyList[choice[j]].getRwyList(i);
rwy = airport->getRunwayByIdent(name);
//cerr << "Succes" << endl;
hdgDiff = fabs(windHeading - rwy->headingDeg());
if (hdgDiff > 180)
hdgDiff = 360 - hdgDiff;
hdgDiff *= ((2*M_PI)/360.0); // convert to radians
crossWind = windSpeed * sin(hdgDiff);
tailWind = -windSpeed * cos(hdgDiff);
if ((tailWind > maxTail) || (crossWind > maxCross))
validSelection = false;
} // Test each runway listed in the preference to see if it's possible to use
if (validSelection) // If one runway of the selection isn't allowed, we need to exclude this
{ // preference, however, we don't want to stop right there, because we also
//cerr << "Valid runay selection : " << i << endl; // don't want to randomly swap runway preferences, unless there is a need to.
active = i; //
nrActive = 2; validSelection = true;
return;
} for (int j = 0; j < activeRwys; j++) {
} string ident(rwyList[j].getRwyList(i));
if (!airport->hasRunwayWithIdent(ident)) {
SG_LOG(SG_GENERAL, SG_WARN,
"no such runway:" << ident << " at " <<
airport->ident());
continue;
}
rwy = airport->getRunwayByIdent(ident);
//cerr << "Succes" << endl;
hdgDiff = fabs(windHeading - rwy->headingDeg());
name = rwy->name();
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 << "Runway : " << rwy->name() << ": " << rwy->headingDeg() << endl;
//cerr << ". Tailwind : " << tailWind;
//cerr << ". Crosswnd : " << crossWind;
if ((tailWind > maxTail) || (crossWind > maxCross)) {
//cerr << ". [Invalid] " << endl;
validSelection = false;
} else {
//cerr << ". [Valid] ";
}
//cerr << endl;
for (stringVecIterator it = currentlyActive->begin();
it != currentlyActive->end(); it++) {
//cerr << "Checking : \"" << (*it) << "\". vs \"" << name << "\"" << endl;
if ((*it) == name) {
match++;
}
}
} // of active runways iteration
if (validSelection) {
//cerr << "Valid selection : " << i << endl;;
foundValidSelection = true;
if (match >= bestMatch) {
bestMatch = match;
bestChoice = i;
}
}
//cerr << "Preference " << i << "Match " << match << " bestMatch " << bestMatch << " choice " << bestChoice << " valid selection " << validSelection << endl;
}
if (foundValidSelection) {
//cerr << "Valid runay selection : " << bestChoice << endl;
nrActive = activeRwys;
active = bestChoice;
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++) {
name = rwyList[choice[j]].getRwyList(i);
rwy = airport->getRunwayByIdent(name);
//cerr << "Succes" << endl;
hdgDiff = fabs(windHeading - rwy->headingDeg());
if (hdgDiff > 180)
hdgDiff = 360 - hdgDiff;
hdgDiff *= ((2 * M_PI) / 360.0); // convert to radians
crossWind = windSpeed * sin(hdgDiff);
tailWind = -windSpeed * cos(hdgDiff);
if ((tailWind > maxTail) || (crossWind > maxCross))
validSelection = false;
}
if (validSelection) {
//cerr << "Valid runay selection : " << i << endl;
active = i;
nrActive = 2;
return;
}
}
} }
active = -1; active = -1;
nrActive = 0; nrActive = 0;
} }
void RunwayGroup::getActive(int i, string &name, string &type) void RunwayGroup::getActive(int i, string & name, string & type)
{ {
if (i == -1) if (i == -1) {
{ return;
return;
} }
if (nrActive == (int)rwyList.size()) if (nrActive == (int) rwyList.size()) {
{ name = rwyList[i].getRwyList(active);
name = rwyList[i].getRwyList(active); type = rwyList[i].getType();
type = rwyList[i].getType(); } else {
} name = rwyList[choice[i]].getRwyList(active);
else type = rwyList[choice[i]].getType();
{
name = rwyList[choice[i]].getRwyList(active);
type = rwyList[choice[i]].getType();
} }
} }
/***************************************************************************** /*****************************************************************************
* FGRunway preference * FGRunway preference
****************************************************************************/ ****************************************************************************/
FGRunwayPreference::FGRunwayPreference(FGAirport* ap) : FGRunwayPreference::FGRunwayPreference(FGAirport * ap):
_ap(ap) _ap(ap)
{ {
//cerr << "Running default Constructor" << endl; //cerr << "Running default Constructor" << endl;
initialized = false; initialized = false;
} }
FGRunwayPreference::FGRunwayPreference(const FGRunwayPreference &other) FGRunwayPreference::FGRunwayPreference(const FGRunwayPreference & other)
{ {
initialized = other.initialized; initialized = other.initialized;
comTimes = other.comTimes; // Commercial Traffic; comTimes = other.comTimes; // Commercial Traffic;
genTimes = other.genTimes; // General Aviation; genTimes = other.genTimes; // General Aviation;
milTimes = other.milTimes; // Military Traffic; milTimes = other.milTimes; // Military Traffic;
PreferenceListConstIterator i; PreferenceListConstIterator i;
for (i = other.preferences.begin(); i != other.preferences.end(); i++) for (i = other.preferences.begin(); i != other.preferences.end(); i++)
preferences.push_back(*i); preferences.push_back(*i);
} }
FGRunwayPreference & FGRunwayPreference::operator= (const FGRunwayPreference &other) FGRunwayPreference & FGRunwayPreference::operator=(const FGRunwayPreference
& other)
{ {
initialized = other.initialized; initialized = other.initialized;
comTimes = other.comTimes; // Commercial Traffic; comTimes = other.comTimes; // Commercial Traffic;
genTimes = other.genTimes; // General Aviation; genTimes = other.genTimes; // General Aviation;
milTimes = other.milTimes; // Military Traffic; milTimes = other.milTimes; // Military Traffic;
PreferenceListConstIterator i; PreferenceListConstIterator i;
preferences.clear(); preferences.clear();
for (i = other.preferences.begin(); i != other.preferences.end(); i++) for (i = other.preferences.begin(); i != other.preferences.end(); i++)
preferences.push_back(*i); preferences.push_back(*i);
return *this; return *this;
} }
ScheduleTime *FGRunwayPreference::getSchedule(const char *trafficType) ScheduleTime *FGRunwayPreference::getSchedule(const char *trafficType)
{ {
if (!(strcmp(trafficType, "com"))) { if (!(strcmp(trafficType, "com"))) {
return &comTimes; return &comTimes;
} }
if (!(strcmp(trafficType, "gen"))) { if (!(strcmp(trafficType, "gen"))) {
return &genTimes; return &genTimes;
} }
if (!(strcmp(trafficType, "mil"))) { if (!(strcmp(trafficType, "mil"))) {
return &milTimes; return &milTimes;
} }
return 0; return 0;
} }
RunwayGroup *FGRunwayPreference::getGroup(const string &groupName) RunwayGroup *FGRunwayPreference::getGroup(const string & groupName)
{ {
PreferenceListIterator i = preferences.begin(); PreferenceListIterator i = preferences.begin();
if (preferences.begin() == preferences.end()) if (preferences.begin() == preferences.end())
return 0; return 0;
while (!(i == preferences.end() || i->getName() == groupName)) while (!(i == preferences.end() || i->getName() == groupName))
i++; i++;
if (i != preferences.end()) if (i != preferences.end())
return &(*i); return &(*i);
else else
return 0; return 0;
} }
string FGRunwayPreference::getId() { string FGRunwayPreference::getId()
return _ap->getId(); {
}; return _ap->getId();
};

View file

@ -289,7 +289,6 @@ bool FGAISchedule::update(time_t now, const SGVec3d& userCart)
if (distanceToUser >= TRAFFICTOAIDISTTOSTART) { if (distanceToUser >= TRAFFICTOAIDISTTOSTART) {
return true; // out of visual range, for the moment. return true; // out of visual range, for the moment.
} }
return createAIAircraft(flight, speed, deptime); return createAIAircraft(flight, speed, deptime);
} }

View file

@ -137,7 +137,9 @@ void FGTrafficManager::init()
void FGTrafficManager::update(double /*dt*/) void FGTrafficManager::update(double /*dt*/)
{ {
if (fgGetBool("/environment/metar/valid") == false) {
return;
}
time_t now = time(NULL) + fgGetLong("/sim/time/warp"); time_t now = time(NULL) + fgGetLong("/sim/time/warp");
if (scheduledAircraft.size() == 0) { if (scheduledAircraft.size() == 0) {
return; return;