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
11. Save file as version.h in the same directory
12. Start build (usually F7)
13. Wait...
14. Enjoy - programs are in D:\FGFSDevel\FlightGear\projects\VC90\Win32\Release
13. Get the data from Gitorious too : git clone git://gitorious.org/fg/fgdata.git fgdata
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
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 setting up a build server or automating the process of retrieving the code and building
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.
//
@ -78,6 +78,8 @@ FGAIAircraft::FGAIAircraft(FGAISchedule *ref) : FGAIBase(otAircraft) {
roll = 0;
headingChangeRate = 0.0;
headingError = 0;
minBearing = 360;
speedFraction =1.0;
holdPos = false;
needsTaxiClearance = false;
@ -257,6 +259,16 @@ void FGAIAircraft::ProcessFlightPlan( double dt, time_t now ) {
return;
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)) {
controlHeading(curr);
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)
fp->IncrementWaypoint( trafficRef != 0 );
if (!(fp->getNextWaypoint()) && trafficRef != 0)
if ( ((!(fp->getNextWaypoint()))) && (trafficRef != 0) )
if (!loadNextLeg()) {
setDie(true);
return;
@ -342,7 +354,7 @@ const char * FGAIAircraft::_getTransponderCode() const {
}
bool FGAIAircraft::loadNextLeg() {
bool FGAIAircraft::loadNextLeg(double distance) {
int leg;
if ((leg = fp->getLeg()) == 10) {
@ -374,7 +386,8 @@ bool FGAIAircraft::loadNextLeg() {
trafficRef->getRadius(),
trafficRef->getFlightType(),
acType,
company);
company,
distance);
//cerr << "created leg " << leg << " for " << trafficRef->getCallSign() << endl;
}
return true;
@ -423,6 +436,7 @@ void FGAIAircraft::doGroundAltitude() {
altitude_ft = (tgt_altitude_ft + groundOffset);
else
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;
}
break;
case 7:
if (trafficRef->getDepartureAirport()->getDynamics()) {
controller = trafficRef->getArrivalAirport()->getDynamics()->getApproachController();
}
break;
case 9: // Taxiing for parking
if (trafficRef->getArrivalAirport()->getDynamics()->getGroundNetwork()->exists())
controller = trafficRef->getArrivalAirport()->getDynamics()->getGroundNetwork();
@ -629,13 +648,34 @@ bool FGAIAircraft::leadPointReached(FGAIFlightPlan::waypoint* curr) {
// << dist_to_go << ": Lead distance "
// << lead_dist << " " << curr->name
// << " Ground target speed " << groundTargetSpeed << endl;
// if (trafficRef) {
// if (trafficRef->getCallSign() == "Transavia7584") {
// cerr << trafficRef->getCallSign() << " " << tgt_altitude_ft << " " << _getSpeed() << " "
// << _getAltitude() << " "<< _getLatitude() << " " << _getLongitude() << " " << dist_to_go << " " << lead_dist << curr->name << endl;
// }
// }
return dist_to_go < lead_dist;
double bearing;
if (speed > 50) { // don't do bearing calculations for ground traffic
bearing = getBearing(fp->getBearing(pos.getLatitudeDeg(), pos.getLongitudeDeg(), curr));
if (bearing < minBearing) {
minBearing = bearing;
if (minBearing < 10) {
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())
speed = _performance->actualSpeed(this, groundTargetSpeed, dt);
else
speed = _performance->actualSpeed(this, tgt_speed, dt);
speed = _performance->actualSpeed(this, (tgt_speed *speedFraction), dt);
updateHeading();
roll = _performance->actualBankAngle(this, tgt_roll, dt);
@ -1045,3 +1085,89 @@ void FGAIAircraft::updateSecondaryTargetValues() {
//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();
FGAIFlightPlan* GetFlightPlan() const { return fp; };
void ProcessFlightPlan( double dt, time_t now );
time_t checkForArrivalTime(string wptName);
void AccelTo(double speed);
void PitchTo(double angle);
@ -63,7 +64,9 @@ public:
void getGroundElev(double dt); //TODO these 3 really need to be public?
void doGroundAltitude();
bool loadNextLeg ();
bool loadNextLeg (double dist=0);
void resetPositionFromFlightPlan();
double getBearing(double crse);
void setAcType(const std::string& ac) { acType = ac; };
void setCompany(const std::string& comp) { company = comp;};
@ -91,6 +94,7 @@ public:
inline double airspeed() const { return props->getFloatValue("velocities/airspeed-kt");};
std::string atGate();
protected:
void Run(double dt);
@ -104,6 +108,8 @@ private:
double dt_elev_count;
double headingChangeRate;
double headingError;
double minBearing;
double speedFraction;
double groundTargetSpeed;
double groundOffset;
double dt;
@ -118,6 +124,7 @@ private:
void handleFirstWaypoint(void);
bool leadPointReached(FGAIFlightPlan::waypoint* curr);
bool handleAirportEndPoints(FGAIFlightPlan::waypoint* prev, time_t now);
bool reachedEndOfCruise(double&);
bool aiTrafficVisible(void);
void controlHeading(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 timeDiff = now-start;
leg = 1;
/*
if ((timeDiff > 300) && (timeDiff < 1200))
if ((timeDiff > 60) && (timeDiff < 1200))
leg = 2;
else if ((timeDiff >= 1200) && (timeDiff < 1500))
leg = 3;
@ -196,14 +196,15 @@ FGAIFlightPlan::FGAIFlightPlan(FGAIAircraft *ac,
leg = 4;
else if (timeDiff >= 2000)
leg = 5;
*/
/*
if (timeDiff >= 2000)
leg = 5;
*/
SG_LOG(SG_GENERAL, SG_INFO, "Route from " << dep->getId() << " to " << arr->getId() << ". Set leg to : " << leg << " " << ac->getTrafficRef()->getCallSign());
wpt_iterator = waypoints.begin();
bool dist = 0;
create(ac, dep,arr, leg, alt, speed, lat, lon,
firstLeg, radius, fltType, acType, airline);
firstLeg, radius, fltType, acType, airline, dist);
wpt_iterator = waypoints.begin();
//cerr << "after create: " << (*wpt_iterator)->name << endl;
//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 * tan((leadInAngle * SG_DEGREES_TO_RADIANS)/2);
/*
if ((lead_distance > (3*turn_radius)) && (current->on_ground == false)) {
// cerr << "Warning: Lead-in distance is large. Inbound = " << inbound
// << ". 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)) {
lead_distance = turn_radius * tan((90 * SG_DEGREES_TO_RADIANS)/2);
return;
}
}*/
}
void FGAIFlightPlan::setLeadDistance(double distance_ft){
@ -493,3 +495,20 @@ int FGAIFlightPlan::getRouteIndex(int i) {
else
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;
int routeIndex; // For AI/ATC purposes;
double time_sec;
double trackLength; // distance from previous waypoint (for AI purposes);
string time;
} waypoint;
@ -90,10 +91,12 @@ public:
double getLeadDistance( void ) const {return lead_distance;}
double getBearing(waypoint* previous, 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 getArrivalTime() const { return arrivalTime; }
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 setTime(time_t st) { start_time = st; }
@ -128,6 +131,7 @@ private:
typedef vector <waypoint*> wpt_vector_type;
typedef wpt_vector_type::const_iterator wpt_vector_iterator;
wpt_vector_type waypoints;
wpt_vector_iterator wpt_iterator;
@ -136,6 +140,7 @@ private:
double lead_distance;
double leadInAngle;
time_t start_time;
time_t arrivalTime; // For AI/ATC purposes.
int leg;
int gateId, lastNodeVisited;
string activeRunway;
@ -148,7 +153,7 @@ private:
void createTakeOff(FGAIAircraft *, bool, FGAirport *, 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 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 createParking(FGAIAircraft *, FGAirport *, double radius);
void deleteWaypoints();
@ -159,6 +164,8 @@ private:
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);
double getTurnRadius(double, bool);
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* cloneWithPos(FGAIAircraft *, waypoint* aWpt, const std::string& aName, const SGGeod& aPos);

View file

@ -46,21 +46,23 @@
// Check lat/lon values during initialization;
void FGAIFlightPlan::create(FGAIAircraft *ac, FGAirport *dep, FGAirport *arr, int legNr,
double alt, double speed, double latitude,
double longitude, bool firstFlight,double radius,
const string& fltType, const string& aircraftType,
const string& airline)
void FGAIFlightPlan::create(FGAIAircraft * ac, FGAirport * dep,
FGAirport * arr, int legNr, double alt,
double speed, double latitude,
double longitude, bool firstFlight,
double radius, const string & fltType,
const string & aircraftType,
const string & airline, double distance)
{
int currWpt = wpt_iterator - waypoints.begin();
switch(legNr)
{
switch (legNr) {
case 1:
createPushBack(ac, firstFlight,dep, latitude, longitude,
createPushBack(ac, firstFlight, dep, latitude, longitude,
radius, fltType, aircraftType, airline);
break;
case 2:
createTakeoffTaxi(ac, firstFlight, dep, radius, fltType, aircraftType, airline);
createTakeoffTaxi(ac, firstFlight, dep, radius, fltType,
aircraftType, airline);
break;
case 3:
createTakeOff(ac, firstFlight, dep, speed, fltType);
@ -69,10 +71,12 @@ void FGAIFlightPlan::create(FGAIAircraft *ac, FGAirport *dep, FGAirport *arr, in
createClimb(ac, firstFlight, dep, speed, alt, fltType);
break;
case 5:
createCruise(ac, firstFlight, dep,arr, latitude, longitude, speed, alt, fltType);
createCruise(ac, firstFlight, dep, arr, latitude, longitude, speed,
alt, fltType);
break;
case 6:
createDecent(ac, arr, fltType);
createDescent(ac, arr, latitude, longitude, speed, alt, fltType,
distance);
break;
case 7:
createLanding(ac, arr, fltType);
@ -85,53 +89,62 @@ void FGAIFlightPlan::create(FGAIAircraft *ac, FGAirport *dep, FGAirport *arr, in
break;
default:
//exit(1);
SG_LOG(SG_INPUT, SG_ALERT, "AIFlightPlan::create() attempting to create unknown leg"
SG_LOG(SG_INPUT, SG_ALERT,
"AIFlightPlan::create() attempting to create unknown leg"
" this is probably an internal program error");
}
wpt_iterator = waypoints.begin()+currWpt;
wpt_iterator = waypoints.begin() + currWpt;
leg++;
}
FGAIFlightPlan::waypoint*
FGAIFlightPlan::createOnGround(FGAIAircraft *ac, const std::string& aName, const SGGeod& aPos, double aElev, double aSpeed)
FGAIFlightPlan::waypoint *
FGAIFlightPlan::createOnGround(FGAIAircraft * ac,
const std::string & aName,
const SGGeod & aPos, double aElev,
double aSpeed)
{
waypoint* wpt = new waypoint;
waypoint *wpt = new waypoint;
wpt->name = aName;
wpt->longitude = aPos.getLongitudeDeg();
wpt->latitude = aPos.getLatitudeDeg();
wpt->altitude = aElev;
wpt->speed = aSpeed;
wpt->crossat = -10000;
wpt->crossat = -10000.1;
wpt->gear_down = true;
wpt->flaps_down= true;
wpt->flaps_down = true;
wpt->finished = false;
wpt->on_ground = true;
wpt->routeIndex= 0;
wpt->routeIndex = 0;
return wpt;
}
FGAIFlightPlan::waypoint*
FGAIFlightPlan::createInAir(FGAIAircraft *ac, const std::string& aName, const SGGeod& aPos, double aElev, double aSpeed)
FGAIFlightPlan::waypoint *
FGAIFlightPlan::createInAir(FGAIAircraft * ac,
const std::string & aName,
const SGGeod & aPos, double aElev,
double aSpeed)
{
waypoint* wpt = new waypoint;
waypoint *wpt = new waypoint;
wpt->name = aName;
wpt->longitude = aPos.getLongitudeDeg();
wpt->latitude = aPos.getLatitudeDeg();
wpt->altitude = aElev;
wpt->speed = aSpeed;
wpt->crossat = -10000;
wpt->crossat = -10000.1;
wpt->gear_down = false;
wpt->flaps_down= false;
wpt->flaps_down = false;
wpt->finished = false;
wpt->on_ground = false;
wpt->routeIndex= 0;
wpt->routeIndex = 0;
return wpt;
}
FGAIFlightPlan::waypoint*
FGAIFlightPlan::cloneWithPos(FGAIAircraft *ac, waypoint* aWpt, const std::string& aName, const SGGeod& aPos)
FGAIFlightPlan::waypoint *
FGAIFlightPlan::cloneWithPos(FGAIAircraft * ac, waypoint * aWpt,
const std::string & aName,
const SGGeod & aPos)
{
waypoint* wpt = new waypoint;
waypoint *wpt = new waypoint;
wpt->name = aName;
wpt->longitude = aPos.getLongitudeDeg();
wpt->latitude = aPos.getLatitudeDeg();
@ -140,7 +153,7 @@ FGAIFlightPlan::cloneWithPos(FGAIAircraft *ac, waypoint* aWpt, const std::string
wpt->speed = aWpt->speed;
wpt->crossat = aWpt->crossat;
wpt->gear_down = aWpt->gear_down;
wpt->flaps_down= aWpt->flaps_down;
wpt->flaps_down = aWpt->flaps_down;
wpt->finished = aWpt->finished;
wpt->on_ground = aWpt->on_ground;
wpt->routeIndex = 0;
@ -148,10 +161,9 @@ FGAIFlightPlan::cloneWithPos(FGAIAircraft *ac, waypoint* aWpt, const std::string
return wpt;
}
FGAIFlightPlan::waypoint*
FGAIFlightPlan::clone(waypoint* aWpt)
FGAIFlightPlan::waypoint * FGAIFlightPlan::clone(waypoint * aWpt)
{
waypoint* wpt = new waypoint;
waypoint *wpt = new waypoint;
wpt->name = aWpt->name;
wpt->longitude = aWpt->longitude;
wpt->latitude = aWpt->latitude;
@ -160,7 +172,7 @@ FGAIFlightPlan::clone(waypoint* aWpt)
wpt->speed = aWpt->speed;
wpt->crossat = aWpt->crossat;
wpt->gear_down = aWpt->gear_down;
wpt->flaps_down= aWpt->flaps_down;
wpt->flaps_down = aWpt->flaps_down;
wpt->finished = aWpt->finished;
wpt->on_ground = aWpt->on_ground;
wpt->routeIndex = 0;
@ -169,22 +181,30 @@ FGAIFlightPlan::clone(waypoint* aWpt)
}
void FGAIFlightPlan::createDefaultTakeoffTaxi(FGAIAircraft *ac, FGAirport* aAirport, FGRunway* aRunway)
void FGAIFlightPlan::createDefaultTakeoffTaxi(FGAIAircraft * ac,
FGAirport * aAirport,
FGRunway * aRunway)
{
SGGeod runwayTakeoff = aRunway->pointOnCenterline(5.0);
double airportElev = aAirport->getElevation();
waypoint* wpt;
wpt = createOnGround(ac, "Airport Center", aAirport->geod(), airportElev, ac->getPerformance()->vTaxi());
waypoint *wpt;
wpt =
createOnGround(ac, "Airport Center", aAirport->geod(), airportElev,
ac->getPerformance()->vTaxi());
waypoints.push_back(wpt);
wpt = createOnGround(ac, "Runway Takeoff", runwayTakeoff, airportElev, ac->getPerformance()->vTaxi());
wpt =
createOnGround(ac, "Runway Takeoff", runwayTakeoff, airportElev,
ac->getPerformance()->vTaxi());
waypoints.push_back(wpt);
}
void FGAIFlightPlan::createTakeoffTaxi(FGAIAircraft *ac, bool firstFlight,
FGAirport *apt,
double radius, const string& fltType,
const string& acType, const string& airline)
void FGAIFlightPlan::createTakeoffTaxi(FGAIAircraft * ac, bool firstFlight,
FGAirport * apt,
double radius,
const string & fltType,
const string & acType,
const string & airline)
{
double heading, lat, lon;
@ -195,8 +215,7 @@ void FGAIFlightPlan::createTakeoffTaxi(FGAIAircraft *ac, bool firstFlight,
if (!(apt->getDynamics()->getAvailableParking(&lat, &lon,
&heading, &gateId,
radius, fltType,
acType, airline)))
{
acType, airline))) {
SG_LOG(SG_INPUT, SG_WARN, "Could not find parking for a " <<
acType <<
" of flight type " << fltType <<
@ -211,12 +230,13 @@ void FGAIFlightPlan::createTakeoffTaxi(FGAIAircraft *ac, bool firstFlight,
if (activeRunway.empty()) {
//cerr << "Getting runway for " << ac->getTrafficRef()->getCallSign() << " at " << apt->getId() << endl;
double depHeading = ac->getTrafficRef()->getCourse();
apt->getDynamics()->getActiveRunway(rwyClass, 1, activeRunway, depHeading);
apt->getDynamics()->getActiveRunway(rwyClass, 1, activeRunway,
depHeading);
}
rwy = apt->getRunwayByIdent(activeRunway);
SGGeod runwayTakeoff = rwy->pointOnCenterline(5.0);
FGGroundNetwork* gn = apt->getDynamics()->getGroundNetwork();
FGGroundNetwork *gn = apt->getDynamics()->getGroundNetwork();
if (!gn->exists()) {
createDefaultTakeoffTaxi(ac, apt, rwy);
return;
@ -243,7 +263,6 @@ void FGAIFlightPlan::createTakeoffTaxi(FGAIAircraft *ac, bool firstFlight,
if (node == -1) {
node = gateId;
}
// HAndle case where parking doens't have a node
if ((node == 0) && park) {
if (firstFlight) {
@ -270,7 +289,7 @@ void FGAIFlightPlan::createTakeoffTaxi(FGAIAircraft *ac, bool firstFlight,
int nrWaypointsToSkip = rand() % taxiRoute->size();
// but make sure we always keep two active waypoints
// to prevent a segmentation fault
for (int i = 0; i < nrWaypointsToSkip-2; i++) {
for (int i = 0; i < nrWaypointsToSkip - 3; i++) {
taxiRoute->next(&node);
}
apt->getDynamics()->releaseParking(gateId);
@ -282,45 +301,60 @@ void FGAIFlightPlan::createTakeoffTaxi(FGAIAircraft *ac, bool firstFlight,
// push each node on the taxi route as a waypoint
int route;
while(taxiRoute->next(&node, &route)) {
while (taxiRoute->next(&node, &route)) {
char buffer[10];
snprintf (buffer, 10, "%d", node);
FGTaxiNode *tn = apt->getDynamics()->getGroundNetwork()->findNode(node);
waypoint* wpt = createOnGround(ac, buffer, tn->getGeod(), apt->getElevation(), ac->getPerformance()->vTaxi());
snprintf(buffer, 10, "%d", node);
FGTaxiNode *tn =
apt->getDynamics()->getGroundNetwork()->findNode(node);
waypoint *wpt =
createOnGround(ac, buffer, tn->getGeod(), apt->getElevation(),
ac->getPerformance()->vTaxi());
wpt->routeIndex = route;
waypoints.push_back(wpt);
}
}
void FGAIFlightPlan::createDefaultLandingTaxi(FGAIAircraft *ac, FGAirport* aAirport)
void FGAIFlightPlan::createDefaultLandingTaxi(FGAIAircraft * ac,
FGAirport * aAirport)
{
SGGeod lastWptPos =
SGGeod::fromDeg(waypoints.back()->longitude, waypoints.back()->latitude);
SGGeod::fromDeg(waypoints.back()->longitude,
waypoints.back()->latitude);
double airportElev = aAirport->getElevation();
waypoint* wpt;
wpt = createOnGround(ac, "Runway Exit", lastWptPos, airportElev, ac->getPerformance()->vTaxi());
waypoint *wpt;
wpt =
createOnGround(ac, "Runway Exit", lastWptPos, airportElev,
ac->getPerformance()->vTaxi());
waypoints.push_back(wpt);
wpt = createOnGround(ac, "Airport Center", aAirport->geod(), airportElev, ac->getPerformance()->vTaxi());
wpt =
createOnGround(ac, "Airport Center", aAirport->geod(), airportElev,
ac->getPerformance()->vTaxi());
waypoints.push_back(wpt);
double heading, lat, lon;
aAirport->getDynamics()->getParking(gateId, &lat, &lon, &heading);
wpt = createOnGround(ac, "END", SGGeod::fromDeg(lon, lat), airportElev, ac->getPerformance()->vTaxi());
wpt =
createOnGround(ac, "END", SGGeod::fromDeg(lon, lat), airportElev,
ac->getPerformance()->vTaxi());
waypoints.push_back(wpt);
}
void FGAIFlightPlan::createLandingTaxi(FGAIAircraft *ac, FGAirport *apt,
double radius, const string& fltType,
const string& acType, const string& airline)
void FGAIFlightPlan::createLandingTaxi(FGAIAircraft * ac, FGAirport * apt,
double radius,
const string & fltType,
const string & acType,
const string & airline)
{
double heading, lat, lon;
apt->getDynamics()->getAvailableParking(&lat, &lon, &heading,
&gateId, radius, fltType, acType, airline);
&gateId, radius, fltType,
acType, airline);
SGGeod lastWptPos =
SGGeod::fromDeg(waypoints.back()->longitude, waypoints.back()->latitude);
FGGroundNetwork* gn = apt->getDynamics()->getGroundNetwork();
SGGeod::fromDeg(waypoints.back()->longitude,
waypoints.back()->latitude);
FGGroundNetwork *gn = apt->getDynamics()->getGroundNetwork();
// Find a route from runway end to parking/gate.
if (!gn->exists()) {
@ -353,12 +387,14 @@ void FGAIFlightPlan::createLandingTaxi(FGAIAircraft *ac, FGAirport *apt,
// Omit the last two waypoints, as
// those are created by createParking()
int route;
for (int i = 0; i < size-2; i++) {
for (int i = 0; i < size - 2; i++) {
taxiRoute->next(&node, &route);
char buffer[10];
snprintf (buffer, 10, "%d", node);
snprintf(buffer, 10, "%d", node);
FGTaxiNode *tn = gn->findNode(node);
waypoint* wpt = createOnGround(ac, buffer, tn->getGeod(), apt->getElevation(), ac->getPerformance()->vTaxi());
waypoint *wpt =
createOnGround(ac, buffer, tn->getGeod(), apt->getElevation(),
ac->getPerformance()->vTaxi());
wpt->routeIndex = route;
waypoints.push_back(wpt);
}
@ -375,7 +411,9 @@ void FGAIFlightPlan::createLandingTaxi(FGAIAircraft *ac, FGAirport *apt,
* more likely however.
*
******************************************************************/
void FGAIFlightPlan::createTakeOff(FGAIAircraft *ac, bool firstFlight, FGAirport *apt, double speed, const string &fltType)
void FGAIFlightPlan::createTakeOff(FGAIAircraft * ac, bool firstFlight,
FGAirport * apt, double speed,
const string & fltType)
{
double accel = ac->getPerformance()->acceleration();
double vTaxi = ac->getPerformance()->vTaxi();
@ -394,19 +432,21 @@ void FGAIFlightPlan::createTakeOff(FGAIAircraft *ac, bool firstFlight, FGAirport
//d = (Vf^2 - Vo^2) / (2*a)
//double accelTime = (vRotate - vTaxi) / accel;
//cerr << "Using " << accelTime << " as total acceleration time" << endl;
double accelDistance = (vRotateMetric*vRotateMetric - vTaxiMetric*vTaxiMetric) / (2*accelMetric);
cerr << "Using " << accelDistance << " " << accelMetric << " " << vRotateMetric << endl;
double accelDistance =
(vRotateMetric * vRotateMetric -
vTaxiMetric * vTaxiMetric) / (2 * accelMetric);
//cerr << "Using " << accelDistance << " " << accelMetric << " " << vRotateMetric << endl;
waypoint *wpt;
// Get the current active runway, based on code from David Luff
// This should actually be unified and extended to include
// Preferential runway use schema's
// NOTE: DT (2009-01-18: IIRC, this is currently already the case,
// because the getActive runway function takes care of that.
if (firstFlight)
{
if (firstFlight) {
string rwyClass = getRunwayClassFromTrafficType(fltType);
double heading = ac->getTrafficRef()->getCourse();
apt->getDynamics()->getActiveRunway(rwyClass, 1, activeRunway, heading);
apt->getDynamics()->getActiveRunway(rwyClass, 1, activeRunway,
heading);
rwy = apt->getRunwayByIdent(activeRunway);
}
@ -417,28 +457,34 @@ void FGAIFlightPlan::createTakeOff(FGAIAircraft *ac, bool firstFlight, FGAirport
waypoints.push_back(wpt);
accelDistance = (vTakeoffMetric*vTakeoffMetric - vTaxiMetric*vTaxiMetric) / (2*accelMetric);
cerr << "Using " << accelDistance << " " << accelMetric << " " << vTakeoffMetric << endl;
accelPoint = rwy->pointOnCenterline(105.0+accelDistance);
accelDistance =
(vTakeoffMetric * vTakeoffMetric -
vTaxiMetric * vTaxiMetric) / (2 * accelMetric);
//cerr << "Using " << accelDistance << " " << accelMetric << " " << vTakeoffMetric << endl;
accelPoint = rwy->pointOnCenterline(105.0 + accelDistance);
wpt = createOnGround(ac, "rotate", accelPoint, airportElev, vTakeoff);
waypoints.push_back(wpt);
accelDistance = ((vTakeoffMetric*1.1)*(vTakeoffMetric*1.1) - vTaxiMetric*vTaxiMetric) / (2*accelMetric);
cerr << "Using " << accelDistance << " " << accelMetric << " " << vTakeoffMetric << endl;
accelPoint = rwy->pointOnCenterline(105.0+accelDistance);
wpt = createOnGround(ac, "rotate", accelPoint, airportElev+1000, vTakeoff*1.1);
accelDistance =
((vTakeoffMetric * 1.1) * (vTakeoffMetric * 1.1) -
vTaxiMetric * vTaxiMetric) / (2 * accelMetric);
//cerr << "Using " << accelDistance << " " << accelMetric << " " << vTakeoffMetric << endl;
accelPoint = rwy->pointOnCenterline(105.0 + accelDistance);
wpt =
createOnGround(ac, "rotate", accelPoint, airportElev + 1000,
vTakeoff * 1.1);
wpt->on_ground = false;
waypoints.push_back(wpt);
wpt = cloneWithPos(ac, wpt, "3000 ft", rwy->end());
wpt->altitude = airportElev+3000;
wpt->altitude = airportElev + 3000;
waypoints.push_back(wpt);
// Finally, add two more waypoints, so that aircraft will remain under
// Tower control until they have reached the 3000 ft climb point
SGGeod pt = rwy->pointOnCenterline(5000 + rwy->lengthM() * 0.5);
wpt = cloneWithPos(ac, wpt, "5000 ft", pt);
wpt->altitude = airportElev+5000;
wpt->altitude = airportElev + 5000;
waypoints.push_back(wpt);
}
@ -446,7 +492,9 @@ void FGAIFlightPlan::createTakeOff(FGAIAircraft *ac, bool firstFlight, FGAirport
* CreateClimb
* initialize the Aircraft at the parking location
******************************************************************/
void FGAIFlightPlan::createClimb(FGAIAircraft *ac, bool firstFlight, FGAirport *apt, double speed, double alt, const string &fltType)
void FGAIFlightPlan::createClimb(FGAIAircraft * ac, bool firstFlight,
FGAirport * apt, double speed, double alt,
const string & fltType)
{
waypoint *wpt;
// bool planLoaded = false;
@ -456,24 +504,24 @@ void FGAIFlightPlan::createClimb(FGAIAircraft *ac, bool firstFlight, FGAirport *
if (firstFlight) {
string rwyClass = getRunwayClassFromTrafficType(fltType);
double heading = ac->getTrafficRef()->getCourse();
apt->getDynamics()->getActiveRunway(rwyClass, 1, activeRunway, heading);
apt->getDynamics()->getActiveRunway(rwyClass, 1, activeRunway,
heading);
rwy = apt->getRunwayByIdent(activeRunway);
}
if (sid) {
for (wpt_vector_iterator i = sid->getFirstWayPoint();
i != sid->getLastWayPoint();
i++) {
i != sid->getLastWayPoint(); i++) {
waypoints.push_back(clone(*(i)));
//cerr << " Cloning waypoint " << endl;
}
} else {
SGGeod climb1 = rwy->pointOnCenterline(10*SG_NM_TO_METER);
SGGeod climb1 = rwy->pointOnCenterline(10 * SG_NM_TO_METER);
wpt = createInAir(ac, "10000ft climb", climb1, vClimb, 10000);
wpt->gear_down = true;
wpt->flaps_down= true;
wpt->flaps_down = true;
waypoints.push_back(wpt);
SGGeod climb2 = rwy->pointOnCenterline(20*SG_NM_TO_METER);
SGGeod climb2 = rwy->pointOnCenterline(20 * SG_NM_TO_METER);
wpt = cloneWithPos(ac, wpt, "18000ft climb", climb2);
wpt->altitude = 18000;
waypoints.push_back(wpt);
@ -483,50 +531,317 @@ void FGAIFlightPlan::createClimb(FGAIAircraft *ac, bool firstFlight, FGAirport *
/*******************************************************************
* CreateDecent
* initialize the Aircraft at the parking location
* CreateDescent
* Generate a flight path from the last waypoint of the cruise to
* the permission to land point
******************************************************************/
void FGAIFlightPlan::createDecent(FGAIAircraft *ac, FGAirport *apt, const string &fltType)
void FGAIFlightPlan::createDescent(FGAIAircraft * ac, FGAirport * apt,
double latitude, double longitude,
double speed, double alt,
const string & fltType,
double requiredDistance)
{
// Ten thousand ft. Slowing down to 240 kts
bool reposition = false;
waypoint *wpt;
double vDecent = ac->getPerformance()->vDescent();
double vDescent = ac->getPerformance()->vDescent();
double vApproach = ac->getPerformance()->vApproach();
//Beginning of Decent
//string name;
// allow "mil" and "gen" as well
//Beginning of Descent
string rwyClass = getRunwayClassFromTrafficType(fltType);
double heading = ac->getTrafficRef()->getCourse();
apt->getDynamics()->getActiveRunway(rwyClass, 2, activeRunway, heading);
apt->getDynamics()->getActiveRunway(rwyClass, 2, activeRunway,
heading);
rwy = apt->getRunwayByIdent(activeRunway);
SGGeod descent1 = rwy->pointOnCenterline(-100000); // 100km out
wpt = createInAir(ac, "Dec 10000ft", descent1, apt->getElevation(), vDecent);
wpt->crossat = 10000;
waypoints.push_back(wpt);
// Three thousand ft. Slowing down to 160 kts
SGGeod descent2 = rwy->pointOnCenterline(-8*SG_NM_TO_METER); // 8nm out
wpt = createInAir(ac, "DEC 3000ft", descent2, apt->getElevation(), vApproach);
wpt->crossat = 3000;
wpt->gear_down = true;
wpt->flaps_down= true;
// Create a slow descent path that ends 250 lateral to the runway.
double initialTurnRadius = getTurnRadius(vDescent, true);
double finalTurnRadius = getTurnRadius(vApproach, true);
// get length of the downwind leg for the intended runway
double distanceOut = apt->getDynamics()->getApproachController()->getRunway(rwy->name())->getApproachDistance(); //12 * SG_NM_TO_METER;
//time_t previousArrivalTime= apt->getDynamics()->getApproachController()->getRunway(rwy->name())->getEstApproachTime();
SGGeod current = SGGeod::fromDegM(longitude, latitude, 0);
SGGeod initialTarget = rwy->pointOnCenterline(-distanceOut);
SGGeod refPoint = rwy->pointOnCenterline(0);
double distance = SGGeodesy::distanceM(current, initialTarget);
double azimuth = SGGeodesy::courseDeg(current, initialTarget);
double dummyAz2;
// To prevent absurdly steep approaches, compute the origin from where the approach should have started
SGGeod origin;
if (ac->getTrafficRef()->getCallSign() ==
fgGetString("/ai/track-callsign")) {
//cerr << "Reposition information: Actual distance " << distance << ". required distance " << requiredDistance << endl;
//exit(1);
}
if (distance < requiredDistance * 0.8) {
reposition = true;
SGGeodesy::direct(initialTarget, azimuth,
-requiredDistance, origin, dummyAz2);
distance = SGGeodesy::distanceM(current, initialTarget);
azimuth = SGGeodesy::courseDeg(current, initialTarget);
} else {
origin = current;
}
double dAlt = alt - (apt->getElevation() + 2000);
double nPoints = 100;
char buffer[16];
// The descent path contains the following phases:
// 1) a linear glide path from the initial position to
// 2) a semi circle turn to final
// 3) approach
//cerr << "Phase 1: Linear Descent path to runway" << rwy->name() << endl;
// Create an initial destination point on a semicircle
//cerr << "lateral offset : " << lateralOffset << endl;
//cerr << "Distance : " << distance << endl;
//cerr << "Azimuth : " << azimuth << endl;
//cerr << "Initial Lateral point: " << lateralOffset << endl;
double lat = refPoint.getLatitudeDeg();
double lon = refPoint.getLongitudeDeg();
//cerr << "Reference point (" << lat << ", " << lon << ")." << endl;
lat = initialTarget.getLatitudeDeg();
lon = initialTarget.getLongitudeDeg();
//cerr << "Initial Target point (" << lat << ", " << lon << ")." << endl;
double ratio = initialTurnRadius / distance;
if (ratio > 1.0)
ratio = 1.0;
if (ratio < -1.0)
ratio = -1.0;
double newHeading = asin(ratio) * SG_RADIANS_TO_DEGREES;
double newDistance =
cos(newHeading * SG_DEGREES_TO_RADIANS) * distance;
//cerr << "new distance " << newDistance << ". additional Heading " << newHeading << endl;
double side = azimuth - rwy->headingDeg();
double lateralOffset = initialTurnRadius;
if (side < 0)
side += 360;
if (side < 180) {
lateralOffset *= -1;
}
// Calculate the ETA at final, based on remaining distance, and approach speed.
// distance should really consist of flying time to terniary target, plus circle
// but the distance to secondary target should work as a reasonable approximation
// aditionally add the amount of distance covered by making a turn of "side"
double turnDistance = (2 * M_PI * initialTurnRadius) * (side / 360.0);
time_t remaining =
(turnDistance + distance) / ((vDescent * SG_NM_TO_METER) / 3600.0);
time_t now = time(NULL) + fgGetLong("/sim/time/warp");
//if (ac->getTrafficRef()->getCallSign() == fgGetString("/ai/track-callsign")) {
// cerr << " Arrival time estimation: turn angle " << side << ". Turn distance " << turnDistance << ". Linear distance " << distance << ". Time to go " << remaining << endl;
// //exit(1);
//}
time_t eta = now + remaining;
//choose a distance to the runway such that it will take at least 60 seconds more
// time to get there than the previous aircraft.
// Don't bother when aircraft need to be repositioned, because that marks the initialization phased...
time_t newEta;
if (reposition == false) {
newEta =
apt->getDynamics()->getApproachController()->getRunway(rwy->
name
())->
requestTimeSlot(eta);
} else {
newEta = eta;
}
//if ((eta < (previousArrivalTime+60)) && (reposition == false)) {
arrivalTime = newEta;
time_t additionalTimeNeeded = newEta - eta;
double distanceCovered =
((vApproach * SG_NM_TO_METER) / 3600.0) * additionalTimeNeeded;
distanceOut += distanceCovered;
//apt->getDynamics()->getApproachController()->getRunway(rwy->name())->setEstApproachTime(eta+additionalTimeNeeded);
//cerr << "Adding additional distance: " << distanceCovered << " to allow " << additionalTimeNeeded << " seconds of flying time" << endl << endl;
//} else {
//apt->getDynamics()->getApproachController()->getRunway(rwy->name())->setEstApproachTime(eta);
//}
//cerr << "Timing information : Previous eta: " << previousArrivalTime << ". Current ETA : " << eta << endl;
SGGeod secondaryTarget =
rwy->pointOffCenterline(-distanceOut, lateralOffset);
initialTarget = rwy->pointOnCenterline(-distanceOut);
distance = SGGeodesy::distanceM(origin, secondaryTarget);
azimuth = SGGeodesy::courseDeg(origin, secondaryTarget);
lat = secondaryTarget.getLatitudeDeg();
lon = secondaryTarget.getLongitudeDeg();
//cerr << "Secondary Target point (" << lat << ", " << lon << ")." << endl;
//cerr << "Distance : " << distance << endl;
//cerr << "Azimuth : " << azimuth << endl;
ratio = initialTurnRadius / distance;
if (ratio > 1.0)
ratio = 1.0;
if (ratio < -1.0)
ratio = -1.0;
newHeading = asin(ratio) * SG_RADIANS_TO_DEGREES;
newDistance = cos(newHeading * SG_DEGREES_TO_RADIANS) * distance;
//cerr << "new distance realative to secondary target: " << newDistance << ". additional Heading " << newHeading << endl;
if (side < 180) {
azimuth += newHeading;
} else {
azimuth -= newHeading;
}
SGGeod tertiaryTarget;
SGGeodesy::direct(origin, azimuth,
newDistance, tertiaryTarget, dummyAz2);
lat = tertiaryTarget.getLatitudeDeg();
lon = tertiaryTarget.getLongitudeDeg();
//cerr << "tertiary Target point (" << lat << ", " << lon << ")." << endl;
for (int i = 1; i < nPoints; i++) {
SGGeod result;
double currentDist = i * (newDistance / nPoints);
double currentAltitude = alt - (i * (dAlt / nPoints));
SGGeodesy::direct(origin, azimuth, currentDist, result, dummyAz2);
snprintf(buffer, 16, "descent%03d", i);
wpt = createInAir(ac, buffer, result, currentAltitude, vDescent);
wpt->crossat = currentAltitude;
wpt->trackLength = (newDistance / nPoints);
waypoints.push_back(wpt);
//cerr << "Track Length : " << wpt->trackLength;
//cerr << " Position : " << result.getLatitudeDeg() << " " << result.getLongitudeDeg() << " " << currentAltitude << endl;
}
//cerr << "Phase 2: Circle " << endl;
double initialAzimuth =
SGGeodesy::courseDeg(secondaryTarget, tertiaryTarget);
double finalAzimuth =
SGGeodesy::courseDeg(secondaryTarget, initialTarget);
//cerr << "Angles from secondary target: " << initialAzimuth << " " << finalAzimuth << endl;
int increment, startval, endval;
// circle right around secondary target if orig of position is to the right of the runway
// i.e. use negative angles; else circle leftward and use postivi
if (side < 180) {
increment = -1;
startval = floor(initialAzimuth);
endval = ceil(finalAzimuth);
if (endval > startval) {
endval -= 360;
}
} else {
increment = 1;
startval = ceil(initialAzimuth);
endval = floor(finalAzimuth);
if (endval < startval) {
endval += 360;
}
}
//cerr << "creating circle between " << startval << " and " << endval << " using " << increment << endl;
double trackLength = (2 * M_PI * initialTurnRadius) / 360.0;
for (int i = startval; i != endval; i += increment) {
SGGeod result;
double currentAltitude = apt->getElevation() + 2000;
SGGeodesy::direct(secondaryTarget, i,
initialTurnRadius, result, dummyAz2);
snprintf(buffer, 16, "turn%03d", i);
wpt = createInAir(ac, buffer, result, currentAltitude, vDescent);
wpt->crossat = currentAltitude;
wpt->trackLength = trackLength;
//cerr << "Track Length : " << wpt->trackLength;
waypoints.push_back(wpt);
//cerr << " Position : " << result.getLatitudeDeg() << " " << result.getLongitudeDeg() << " " << currentAltitude << endl;
}
// The approach leg should bring the aircraft to approximately 4-6 out, after which the landing phase should take over.
//cerr << "Phase 3: Approach" << endl;
distanceOut -= distanceCovered;
for (int i = 1; i < nPoints; i++) {
SGGeod result;
double currentDist = i * (distanceOut / nPoints);
double currentAltitude =
apt->getElevation() + 2000 - (i * 2000 / nPoints);
snprintf(buffer, 16, "final%03d", i);
result = rwy->pointOnCenterline((-distanceOut) + currentDist);
wpt = createInAir(ac, buffer, result, currentAltitude, vApproach);
wpt->crossat = currentAltitude;
wpt->trackLength = (distanceOut / nPoints);
// account for the extra distance due to an extended downwind leg
if (i == 1) {
wpt->trackLength += distanceCovered;
}
//cerr << "Track Length : " << wpt->trackLength;
waypoints.push_back(wpt);
//cerr << " Position : " << result.getLatitudeDeg() << " " << result.getLongitudeDeg() << " " << currentAltitude << endl;
}
//cerr << "Done" << endl;
// Erase the two bogus BOD points: Note check for conflicts with scripted AI flightPlans
IncrementWaypoint(true);
IncrementWaypoint(true);
if (reposition) {
double tempDistance;
double minDistance = HUGE_VAL;
string wptName;
tempDistance = SGGeodesy::distanceM(current, initialTarget);
time_t eta =
tempDistance / ((vDescent * SG_NM_TO_METER) / 3600.0) + now;
time_t newEta =
apt->getDynamics()->getApproachController()->getRunway(rwy->
name
())->
requestTimeSlot(eta);
arrivalTime = newEta;
double newDistance =
((vDescent * SG_NM_TO_METER) / 3600.0) * (newEta - now);
//cerr << "Repositioning information : eta" << eta << ". New ETA " << newEta << ". Diff = " << (newEta - eta) << ". Distance = " << tempDistance << ". New distance = " << newDistance << endl;
IncrementWaypoint(true); // remove waypoint BOD2
while (checkTrackLength("final001") > newDistance) {
IncrementWaypoint(true);
}
//cerr << "Repositioning to waypoint " << (*waypoints.begin())->name << endl;
ac->resetPositionFromFlightPlan();
}
}
/*******************************************************************
* CreateLanding
* initialize the Aircraft at the parking location
* Create a flight path from the "permision to land" point (currently
hardcoded at 5000 meters from the threshold) to the threshold, at
a standard glide slope angle of 3 degrees.
******************************************************************/
void FGAIFlightPlan::createLanding(FGAIAircraft *ac, FGAirport *apt, const string &fltType)
void FGAIFlightPlan::createLanding(FGAIAircraft * ac, FGAirport * apt,
const string & fltType)
{
double vTouchdown = ac->getPerformance()->vTouchdown();
double vTaxi = ac->getPerformance()->vTaxi();
string rwyClass = getRunwayClassFromTrafficType(fltType);
double heading = ac->getTrafficRef()->getCourse();
apt->getDynamics()->getActiveRunway(rwyClass, 2, activeRunway, heading);
rwy = apt->getRunwayByIdent(activeRunway);
//string rwyClass = getRunwayClassFromTrafficType(fltType);
//double heading = ac->getTrafficRef()->getCourse();
//apt->getDynamics()->getActiveRunway(rwyClass, 2, activeRunway, heading);
//rwy = apt->getRunwayByIdent(activeRunway);
waypoint *wpt;
@ -536,8 +851,8 @@ void FGAIFlightPlan::createLanding(FGAIAircraft *ac, FGAirport *apt, const strin
char buffer[12];
for (int i = 1; i < 10; i++) {
snprintf(buffer, 12, "wpt%d", i);
coord = rwy->pointOnCenterline(rwy->lengthM() * (i/10.0));
wpt = createOnGround(ac, buffer, coord, aptElev, (vTouchdown/i));
coord = rwy->pointOnCenterline(rwy->lengthM() * (i / 10.0));
wpt = createOnGround(ac, buffer, coord, aptElev, (vTouchdown / i));
wpt->crossat = apt->getElevation();
waypoints.push_back(wpt);
}
@ -563,9 +878,10 @@ void FGAIFlightPlan::createLanding(FGAIAircraft *ac, FGAirport *apt, const strin
* CreateParking
* initialize the Aircraft at the parking location
******************************************************************/
void FGAIFlightPlan::createParking(FGAIAircraft *ac, FGAirport *apt, double radius)
void FGAIFlightPlan::createParking(FGAIAircraft * ac, FGAirport * apt,
double radius)
{
waypoint* wpt;
waypoint *wpt;
double aptElev = apt->getElevation();
double lat = 0.0, lat2 = 0.0;
double lon = 0.0, lon2 = 0.0;
@ -573,25 +889,29 @@ void FGAIFlightPlan::createParking(FGAIAircraft *ac, FGAirport *apt, double radi
double heading = 0.0;
double vTaxi = ac->getPerformance()->vTaxi();
double vTaxiReduced = vTaxi * (2.0/3.0);
double vTaxiReduced = vTaxi * (2.0 / 3.0);
apt->getDynamics()->getParking(gateId, &lat, &lon, &heading);
heading += 180.0;
if (heading > 360)
heading -= 360;
geo_direct_wgs_84 ( 0, lat, lon, heading,
2.2*radius,
&lat2, &lon2, &az2 );
wpt = createOnGround(ac, "taxiStart", SGGeod::fromDeg(lon2, lat2), aptElev, vTaxiReduced);
geo_direct_wgs_84(0, lat, lon, heading,
2.2 * radius, &lat2, &lon2, &az2);
wpt =
createOnGround(ac, "taxiStart", SGGeod::fromDeg(lon2, lat2),
aptElev, vTaxiReduced);
waypoints.push_back(wpt);
geo_direct_wgs_84 ( 0, lat, lon, heading,
0.1 *radius,
&lat2, &lon2, &az2 );
geo_direct_wgs_84(0, lat, lon, heading,
0.1 * radius, &lat2, &lon2, &az2);
wpt = createOnGround(ac, "taxiStart2", SGGeod::fromDeg(lon2, lat2), aptElev, vTaxiReduced);
wpt =
createOnGround(ac, "taxiStart2", SGGeod::fromDeg(lon2, lat2),
aptElev, vTaxiReduced);
waypoints.push_back(wpt);
wpt = createOnGround(ac, "END", SGGeod::fromDeg(lon, lat), aptElev, vTaxiReduced);
wpt =
createOnGround(ac, "END", SGGeod::fromDeg(lon, lat), aptElev,
vTaxiReduced);
waypoints.push_back(wpt);
}
@ -624,7 +944,7 @@ string FGAIFlightPlan::getRunwayClassFromTrafficType(string fltType)
return string("com");
}
if (fltType == "ga") {
return string ("gen");
return string("gen");
}
if (fltType == "ul") {
return string("ul");
@ -634,3 +954,15 @@ string FGAIFlightPlan::getRunwayClassFromTrafficType(string fltType)
}
return string("com");
}
double FGAIFlightPlan::getTurnRadius(double speed, bool inAir)
{
double turn_radius;
if (inAir == false) {
turn_radius = ((360 / 30) * fabs(speed)) / (2 * M_PI);
} else {
turn_radius = 0.1911 * speed * speed; // an estimate for 25 degrees bank
}
return turn_radius;
}

View file

@ -300,8 +300,11 @@ void FGAIFlightPlan::createCruise(FGAIAircraft *ac, bool firstFlight, FGAirport
arr->getDynamics()->getActiveRunway(rwyClass, 2, activeRunway, heading);
rwy = arr->getRunwayByIdent(activeRunway);
// 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);
waypoints.push_back(wpt);
wpt = createInAir(ac, "BOD2", secondaryDescentPoint, alt, vCruise);
waypoints.push_back(wpt);
}

File diff suppressed because it is too large Load diff

View file

@ -28,6 +28,8 @@
#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>
@ -185,6 +187,9 @@ public:
typedef vector<FGTrafficRecord> TrafficVector;
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
@ -195,11 +200,18 @@ class ActiveRunway
private:
string rwy;
int currentlyCleared;
double distanceToFinal;
TimeVector estimatedArrivalTimes;
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; };
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;
@ -207,7 +219,7 @@ typedef vector<ActiveRunway>::iterator ActiveRunwayVecIterator;
/**
* 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
{
@ -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

View file

@ -325,17 +325,21 @@ bool FGAirportDynamics::innerGetActiveRunway(const string & trafficType,
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();
*/
windSpeed = fgGetInt("/environment/metar/base-wind-speed-kt"); //stationweather.get_wind_speed_kt();
windHeading = fgGetInt("/environment/metar/base-wind-dir-deg");
//stationweather.get_wind_from_heading_deg();
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;
ScheduleTime *currSched;
@ -347,7 +351,7 @@ bool FGAirportDynamics::innerGetActiveRunway(const string & trafficType,
scheduleName = currSched->getName(dayStart);
maxTail = currSched->getTailWind();
maxCross = currSched->getCrossWind();
//cerr << "SChedule anme = " << scheduleName << endl;
//cerr << "Current Schedule = : " << scheduleName << endl;
if (scheduleName.empty())
return false;
//cerr << "C"<< endl;
@ -371,6 +375,13 @@ bool FGAirportDynamics::innerGetActiveRunway(const string & trafficType,
currentlyActive = &ulActive;
}
//cerr << "Durrently active selection for " << trafficType << ": ";
for (stringVecIterator it = currentlyActive->begin();
it != currentlyActive->end(); it++) {
//cerr << (*it) << " ";
}
//cerr << endl;
currRunwayGroup->setActive(_ap,
windSpeed,
windHeading,

View file

@ -52,6 +52,7 @@ private:
FGStartupController startupController;
FGGroundNetwork groundNetwork;
FGTowerController towerController;
FGApproachController approachController;
time_t lastUpdate;
string prevTrafficType;
@ -115,6 +116,7 @@ public:
FGStartupController *getStartupController() { return &startupController; };
FGGroundNetwork *getGroundNetwork() { return &groundNetwork; };
FGTowerController *getTowerController() { return &towerController; };
FGApproachController *getApproachController() { return &approachController; };
const string& getAtisInformation() { return atisInformation; };
int getGroundFrequency(unsigned leg); //{ return freqGround.size() ? freqGround[0] : 0; };

View file

@ -553,19 +553,21 @@ void FGGroundNetwork::update(int id, double lat, double lon,
current->clearResolveCircularWait();
current->setWaitsForId(0);
checkSpeedAdjustment(id, lat, lon, heading, speed, alt);
bool needsTaxiClearance = current->getAircraft()->getTaxiClearanceRequest();
if (!needsTaxiClearance) {
checkHoldPosition(id, lat, lon, heading, speed, alt);
if (checkForCircularWaits(id)) {
i->setResolveCircularWait();
}
bool needsTaxiClearance = current->getAircraft()->getTaxiClearanceRequest();
} else {
current->setHoldPosition(true);
int state = current->getState();
time_t now = time(NULL) + fgGetLong("/sim/time/warp");
if ((now - lastTransmission) > 15) {
available = true;
}
if (needsTaxiClearance && available) {
if ((state < 3) && available) {
transmit(&(*current), MSG_REQUEST_TAXI_CLEARANCE, ATC_AIR_TO_GROUND);
current->getAircraft()->setTaxiClearanceRequest(false);
current->setState(3);
lastTransmission = now;
available = false;
@ -578,10 +580,19 @@ void FGGroundNetwork::update(int id, double lat, double lon,
}
if ((state == 4) && available) {
transmit(&(*current), MSG_ACKNOWLEDGE_TAXI_CLEARANCE, ATC_AIR_TO_GROUND);
current->setState(0);
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;
}
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
{
return ((_surface_code == 1) || (_surface_code == 2));

View file

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

View file

@ -48,7 +48,7 @@ void ScheduleTime::clear()
}
ScheduleTime::ScheduleTime(const ScheduleTime &other)
ScheduleTime::ScheduleTime(const ScheduleTime & other)
{
//timeVec start;
timeVecConstIterator i;
@ -57,7 +57,8 @@ ScheduleTime::ScheduleTime(const ScheduleTime &other)
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++)
for (k = other.scheduleNames.begin(); k != other.scheduleNames.end();
k++)
scheduleNames.push_back(*k);
//timeVec end;
@ -67,7 +68,7 @@ ScheduleTime::ScheduleTime(const ScheduleTime &other)
}
ScheduleTime & ScheduleTime::operator= (const ScheduleTime &other)
ScheduleTime & ScheduleTime::operator=(const ScheduleTime & other)
{
//timeVec start;
clear();
@ -77,7 +78,8 @@ ScheduleTime & ScheduleTime::operator= (const ScheduleTime &other)
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++)
for (k = other.scheduleNames.begin(); k != other.scheduleNames.end();
k++)
scheduleNames.push_back(*k);
//timeVec end;
@ -86,21 +88,18 @@ ScheduleTime & ScheduleTime::operator= (const ScheduleTime &other)
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" );
if ((start.size() != end.size())
|| (start.size() != scheduleNames.size())) {
SG_LOG(SG_GENERAL, SG_INFO, "Unable to parse schedule times");
exit(1);
}
else
{
} 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++)
{
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];
@ -111,27 +110,32 @@ string ScheduleTime::getName(time_t dayStart)
}
return string("");
}
/******************************************************************************
* RunwayList
*****************************************************************************/
RunwayList::RunwayList(const RunwayList &other)
RunwayList::RunwayList(const RunwayList & other)
{
type = other.type;
stringVecConstIterator i;
for (i = other.preferredRunways.begin(); i != other.preferredRunways.end(); i++)
for (i = other.preferredRunways.begin();
i != other.preferredRunways.end(); i++)
preferredRunways.push_back(*i);
}
RunwayList& RunwayList::operator= (const RunwayList &other)
RunwayList & RunwayList::operator=(const RunwayList & other)
{
type = other.type;
preferredRunways.clear();
stringVecConstIterator i;
for (i = other.preferredRunways.begin(); i != other.preferredRunways.end(); 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)
void RunwayList::set(const string & tp, const string & lst)
{
//weekday = atoi(timeCopy.substr(0,1).c_str());
// timeOffsetInDays = weekday - currTimeDate->getGmt()->tm_wday;
@ -139,12 +143,11 @@ void RunwayList::set(const string &tp, const string &lst)
type = tp;
string rwys = lst;
string rwy;
while (rwys.find(",") != string::npos)
{
rwy = rwys.substr(0, rwys.find(",",0));
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
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;
@ -158,11 +161,12 @@ void RunwayList::clear()
type = "";
preferredRunways.clear();
}
/****************************************************************************
*
***************************************************************************/
RunwayGroup::RunwayGroup(const RunwayGroup &other)
RunwayGroup::RunwayGroup(const RunwayGroup & other)
{
name = other.name;
RunwayListVecConstIterator i;
@ -172,7 +176,8 @@ RunwayGroup::RunwayGroup(const RunwayGroup &other)
choice[1] = other.choice[1];
nrActive = other.nrActive;
}
RunwayGroup& RunwayGroup:: operator= (const RunwayGroup &other)
RunwayGroup & RunwayGroup::operator=(const RunwayGroup & other)
{
rwyList.clear();
name = other.name;
@ -185,15 +190,14 @@ RunwayGroup& RunwayGroup:: operator= (const RunwayGroup &other)
return *this;
}
void RunwayGroup::setActive(const FGAirport* airport,
void RunwayGroup::setActive(const FGAirport * airport,
double windSpeed,
double windHeading,
double maxTail,
double maxCross,
stringVec *currentlyActive)
double maxCross, stringVec * currentlyActive)
{
FGRunway* rwy;
FGRunway *rwy;
int activeRwys = rwyList.size(); // get the number of runways active
int nrOfPreferences;
// bool found = true;
@ -205,16 +209,14 @@ void RunwayGroup::setActive(const FGAirport* airport,
//stringVec names;
int bestMatch = 0, bestChoice = 0;
if (activeRwys > 0)
{
if (activeRwys > 0) {
// Now downward iterate across all the possible preferences
// starting by the least preferred choice working toward the most preferred choice
nrOfPreferences = rwyList[0].getRwyList()->size();
bool validSelection = true;
bool foundValidSelection = false;
for (int i = nrOfPreferences-1; i >= 0; i--)
{
for (int i = nrOfPreferences - 1; i >= 0; i--) {
int match = 0;
@ -224,11 +226,13 @@ void RunwayGroup::setActive(const FGAirport* airport,
// don't want to randomly swap runway preferences, unless there is a need to.
//
validSelection = true;
for (int j = 0; j < activeRwys; j++)
{
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());
SG_LOG(SG_GENERAL, SG_WARN,
"no such runway:" << ident << " at " <<
airport->ident());
continue;
}
@ -236,47 +240,45 @@ void RunwayGroup::setActive(const FGAirport* airport,
//cerr << "Succes" << endl;
hdgDiff = fabs(windHeading - rwy->headingDeg());
//cerr << "Wind Heading: " << windHeading << "Runway Heading: " <<rwy._heading << endl;
//cerr << "Wind Speed : " << windSpeed << endl;
name = rwy->name();
if (hdgDiff > 180)
hdgDiff = 360 - hdgDiff;
//cerr << "Heading diff: " << hdgDiff << endl;
hdgDiff *= ((2*M_PI)/360.0); // convert to radians
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))
{
if ((tailWind > maxTail) || (crossWind > maxCross)) {
//cerr << ". [Invalid] " << endl;
validSelection = false;
}
else
{
} 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)
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 << " bestMatch " << bestMatch << " choice " << bestChoice << endl;
//cerr << "Preference " << i << "Match " << match << " bestMatch " << bestMatch << " choice " << bestChoice << " valid selection " << validSelection << endl;
}
if (foundValidSelection)
{
if (foundValidSelection) {
//cerr << "Valid runay selection : " << bestChoice << endl;
nrActive = activeRwys;
active = bestChoice;
@ -286,8 +288,7 @@ void RunwayGroup::setActive(const FGAirport* airport,
// but select only one landing and one takeoff runway.
choice[0] = 0;
choice[1] = 0;
for (int i = activeRwys-1; i; i--)
{
for (int i = activeRwys - 1; i; i--) {
if (rwyList[i].getType() == string("landing"))
choice[0] = i;
if (rwyList[i].getType() == string("takeoff"))
@ -295,11 +296,9 @@ void RunwayGroup::setActive(const FGAirport* airport,
}
//cerr << "Choosing " << choice[0] << " for landing and " << choice[1] << "for takeoff" << endl;
nrOfPreferences = rwyList[0].getRwyList()->size();
for (int i = 0; i < nrOfPreferences; i++)
{
for (int i = 0; i < nrOfPreferences; i++) {
bool validSelection = true;
for (int j = 0; j < 2; j++)
{
for (int j = 0; j < 2; j++) {
name = rwyList[choice[j]].getRwyList(i);
rwy = airport->getRunwayByIdent(name);
@ -307,7 +306,7 @@ void RunwayGroup::setActive(const FGAirport* airport,
hdgDiff = fabs(windHeading - rwy->headingDeg());
if (hdgDiff > 180)
hdgDiff = 360 - hdgDiff;
hdgDiff *= ((2*M_PI)/360.0); // convert to radians
hdgDiff *= ((2 * M_PI) / 360.0); // convert to radians
crossWind = windSpeed * sin(hdgDiff);
tailWind = -windSpeed * cos(hdgDiff);
if ((tailWind > maxTail) || (crossWind > maxCross))
@ -315,8 +314,7 @@ void RunwayGroup::setActive(const FGAirport* airport,
}
if (validSelection)
{
if (validSelection) {
//cerr << "Valid runay selection : " << i << endl;
active = i;
nrActive = 2;
@ -328,34 +326,31 @@ void RunwayGroup::setActive(const FGAirport* airport,
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;
}
if (nrActive == (int)rwyList.size())
{
if (nrActive == (int) rwyList.size()) {
name = rwyList[i].getRwyList(active);
type = rwyList[i].getType();
}
else
{
} else {
name = rwyList[choice[i]].getRwyList(active);
type = rwyList[choice[i]].getType();
}
}
/*****************************************************************************
* FGRunway preference
****************************************************************************/
FGRunwayPreference::FGRunwayPreference(FGAirport* ap) :
_ap(ap)
FGRunwayPreference::FGRunwayPreference(FGAirport * ap):
_ap(ap)
{
//cerr << "Running default Constructor" << endl;
initialized = false;
}
FGRunwayPreference::FGRunwayPreference(const FGRunwayPreference &other)
FGRunwayPreference::FGRunwayPreference(const FGRunwayPreference & other)
{
initialized = other.initialized;
@ -368,7 +363,8 @@ FGRunwayPreference::FGRunwayPreference(const FGRunwayPreference &other)
preferences.push_back(*i);
}
FGRunwayPreference & FGRunwayPreference::operator= (const FGRunwayPreference &other)
FGRunwayPreference & FGRunwayPreference::operator=(const FGRunwayPreference
& other)
{
initialized = other.initialized;
@ -397,7 +393,7 @@ ScheduleTime *FGRunwayPreference::getSchedule(const char *trafficType)
return 0;
}
RunwayGroup *FGRunwayPreference::getGroup(const string &groupName)
RunwayGroup *FGRunwayPreference::getGroup(const string & groupName)
{
PreferenceListIterator i = preferences.begin();
if (preferences.begin() == preferences.end())
@ -410,6 +406,7 @@ RunwayGroup *FGRunwayPreference::getGroup(const string &groupName)
return 0;
}
string FGRunwayPreference::getId() {
string FGRunwayPreference::getId()
{
return _ap->getId();
};
};

View file

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

View file

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