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,
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,7 +89,8 @@ 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;
@ -93,7 +98,10 @@ void FGAIFlightPlan::create(FGAIAircraft *ac, FGAirport *dep, FGAirport *arr, in
}
FGAIFlightPlan::waypoint *
FGAIFlightPlan::createOnGround(FGAIAircraft *ac, const std::string& aName, const SGGeod& aPos, double aElev, double aSpeed)
FGAIFlightPlan::createOnGround(FGAIAircraft * ac,
const std::string & aName,
const SGGeod & aPos, double aElev,
double aSpeed)
{
waypoint *wpt = new waypoint;
wpt->name = aName;
@ -101,7 +109,7 @@ FGAIFlightPlan::createOnGround(FGAIAircraft *ac, const std::string& aName, const
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->finished = false;
@ -111,7 +119,10 @@ FGAIFlightPlan::createOnGround(FGAIAircraft *ac, const std::string& aName, const
}
FGAIFlightPlan::waypoint *
FGAIFlightPlan::createInAir(FGAIAircraft *ac, const std::string& aName, const SGGeod& aPos, double aElev, double aSpeed)
FGAIFlightPlan::createInAir(FGAIAircraft * ac,
const std::string & aName,
const SGGeod & aPos, double aElev,
double aSpeed)
{
waypoint *wpt = new waypoint;
wpt->name = aName;
@ -119,7 +130,7 @@ FGAIFlightPlan::createInAir(FGAIAircraft *ac, const std::string& aName, const SG
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->finished = false;
@ -129,7 +140,9 @@ FGAIFlightPlan::createInAir(FGAIAircraft *ac, const std::string& aName, const SG
}
FGAIFlightPlan::waypoint *
FGAIFlightPlan::cloneWithPos(FGAIAircraft *ac, waypoint* aWpt, const std::string& aName, const SGGeod& aPos)
FGAIFlightPlan::cloneWithPos(FGAIAircraft * ac, waypoint * aWpt,
const std::string & aName,
const SGGeod & aPos)
{
waypoint *wpt = new waypoint;
wpt->name = aName;
@ -148,8 +161,7 @@ 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;
wpt->name = aWpt->name;
@ -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());
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)
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,7 +230,8 @@ 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);
@ -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);
@ -285,41 +304,56 @@ void FGAIFlightPlan::createTakeoffTaxi(FGAIAircraft *ac, bool firstFlight,
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());
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());
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)
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);
SGGeod::fromDeg(waypoints.back()->longitude,
waypoints.back()->latitude);
FGGroundNetwork *gn = apt->getDynamics()->getGroundNetwork();
// Find a route from runway end to parking/gate.
@ -358,7 +392,9 @@ void FGAIFlightPlan::createLandingTaxi(FGAIAircraft *ac, FGAirport *apt,
char buffer[10];
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,16 +457,22 @@ 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;
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;
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 =
createOnGround(ac, "rotate", accelPoint, airportElev + 1000,
vTakeoff * 1.1);
wpt->on_ground = false;
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,13 +504,13 @@ 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;
}
@ -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;
waypoints.push_back(wpt);
// 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;
@ -563,7 +878,8 @@ 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;
double aptElev = apt->getElevation();
@ -579,19 +895,23 @@ void FGAIFlightPlan::createParking(FGAIAircraft *ac, FGAirport *apt, double radi
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);
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 );
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);
}
@ -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);
}

View file

@ -24,13 +24,110 @@
# include <config.h>
#endif
#include <algorithm>
#include "trafficcontrol.hxx"
#include <AIModel/AIAircraft.hxx>
#include <AIModel/AIFlightPlan.hxx>
#include <AIModel/performancedata.hxx>
#include <AIModel/performancedb.hxx>
#include <Traffic/TrafficMgr.hxx>
#include <Airports/groundnetwork.hxx>
#include <Airports/dynamics.hxx>
using std::sort;
/***************************************************************************
* ActiveRunway
**************************************************************************/
time_t ActiveRunway::requestTimeSlot(time_t eta)
{
time_t newEta;
time_t separation = 90;
bool found = false;
if (estimatedArrivalTimes.size() == 0) {
estimatedArrivalTimes.push_back(eta);
return eta;
} else {
TimeVectorIterator i = estimatedArrivalTimes.begin();
//cerr << "Checking eta slots " << eta << ": " << endl;
for (i = estimatedArrivalTimes.begin();
i != estimatedArrivalTimes.end(); i++) {
//cerr << "Stored time : " << (*i) << endl;
}
i = estimatedArrivalTimes.begin();
if ((eta + separation) < (*i)) {
newEta = eta;
found = true;
//cerr << "Storing at beginning" << endl;
}
while ((i != estimatedArrivalTimes.end()) && (!found)) {
TimeVectorIterator j = i + 1;
if (j == estimatedArrivalTimes.end()) {
if (((*i) + separation) < eta) {
//cerr << "Storing at end" << endl;
newEta = eta;
} else {
newEta = (*i) + separation;
//cerr << "Storing at end + separation" << endl;
}
} else {
if ((((*j) - (*i)) > (separation * 2))) { // found a potential slot
// now check whether this slow is usable:
// 1) eta should fall between the two points
// i.e. eta > i AND eta < j
//
//cerr << "Found potential slot after " << (*i) << endl;
if (eta > (*i) && (eta < (*j))) {
found = true;
if (eta < ((*i) + separation)) {
newEta = (*i) + separation;
//cerr << "Using original" << (*i) << " + separation " << endl;
} else {
newEta = eta;
//cerr << "Using original after " << (*i) << endl;
}
} else if (eta < (*i)) {
found = true;
newEta = (*i) + separation;
//cerr << "Using delayed slot after " << (*i) << endl;
}
/*
if (((*j) - separation) < eta) {
found = true;
if (((*i) + separation) < eta) {
newEta = eta;
cerr << "Using original after " << (*i) << endl;
} else {
newEta = (*i) + separation;
cerr << "Using " << (*i) << " + separation " << endl;
}
} */
}
}
i++;
}
}
//cerr << ". done. New ETA : " << newEta << endl;
estimatedArrivalTimes.push_back(newEta);
sort(estimatedArrivalTimes.begin(), estimatedArrivalTimes.end());
// do some housekeeping : remove any timestamps that are past
time_t now = time(NULL) + fgGetLong("/sim/time/warp");
TimeVectorIterator i = estimatedArrivalTimes.begin();
while (i != estimatedArrivalTimes.end()) {
if ((*i) < now) {
//cerr << "Deleting timestamp " << (*i) << " (now = " << now << "). " << endl;
estimatedArrivalTimes.erase(i);
i = estimatedArrivalTimes.begin();
} else {
i++;
}
}
return newEta;
}
/***************************************************************************
* FGTrafficRecord
**************************************************************************/
@ -41,25 +138,23 @@ FGTrafficRecord::FGTrafficRecord() :
frequencyId(0),
state(0),
allowTransmission(true),
latitude(0),
longitude(0),
heading(0),
speed(0),
altitude(0),
radius(0)
latitude(0), longitude(0), heading(0), speed(0), altitude(0), radius(0)
{
}
void FGTrafficRecord::setPositionAndIntentions(int pos, FGAIFlightPlan *route)
void FGTrafficRecord::setPositionAndIntentions(int pos,
FGAIFlightPlan * route)
{
currentPos = pos;
if (intentions.size()) {
intVecIterator i = intentions.begin();
if ((*i) != pos) {
SG_LOG(SG_GENERAL, SG_ALERT, "Error in FGTrafficRecord::setPositionAndIntentions");
SG_LOG(SG_GENERAL, SG_ALERT,
"Error in FGTrafficRecord::setPositionAndIntentions");
//cerr << "Pos : " << pos << " Curr " << *(intentions.begin()) << endl;
for (intVecIterator i = intentions.begin(); i != intentions.end() ; i++) {
for (intVecIterator i = intentions.begin();
i != intentions.end(); i++) {
//cerr << (*i) << " ";
}
//cerr << endl;
@ -73,8 +168,7 @@ void FGTrafficRecord::setPositionAndIntentions(int pos, FGAIFlightPlan *route)
for (int i = 0; i < size; i++) {
int val = route->getRouteIndex(i);
//cerr << val<< " ";
if ((val) && (val != pos))
{
if ((val) && (val != pos)) {
intentions.push_back(val);
//cerr << "[set] ";
}
@ -92,8 +186,7 @@ bool FGTrafficRecord::checkPositionAndIntentions(FGTrafficRecord &other)
{
bool result = false;
//cerr << "Start check 1" << endl;
if (currentPos == other.currentPos)
{
if (currentPos == other.currentPos) {
//cerr << callsign << ": Check Position and intentions: we are on the same taxiway" << other.callsign << "Index = " << currentPos << endl;
result = true;
}
@ -126,8 +219,9 @@ bool FGTrafficRecord::checkPositionAndIntentions(FGTrafficRecord &other)
return result;
}
void FGTrafficRecord::setPositionAndHeading(double lat, double lon, double hdg,
double spd, double alt)
void FGTrafficRecord::setPositionAndHeading(double lat, double lon,
double hdg, double spd,
double alt)
{
latitude = lat;
longitude = lon;
@ -136,9 +230,11 @@ void FGTrafficRecord::setPositionAndHeading(double lat, double lon, double hdg,
altitude = alt;
}
int FGTrafficRecord::crosses(FGGroundNetwork *net, FGTrafficRecord &other)
int FGTrafficRecord::crosses(FGGroundNetwork * net,
FGTrafficRecord & other)
{
if (checkPositionAndIntentions(other) || (other.checkPositionAndIntentions(*this)))
if (checkPositionAndIntentions(other)
|| (other.checkPositionAndIntentions(*this)))
return -1;
intVecIterator i, j;
int currentTargetNode = 0, otherTargetNode = 0;
@ -148,44 +244,40 @@ int FGTrafficRecord::crosses(FGGroundNetwork *net, FGTrafficRecord &other)
otherTargetNode = net->findSegment(other.currentPos)->getEnd()->getIndex(); // OKAY,...
if ((currentTargetNode == otherTargetNode) && currentTargetNode > 0)
return currentTargetNode;
if (intentions.size())
{
for (i = intentions.begin(); i != intentions.end(); i++)
{
if (intentions.size()) {
for (i = intentions.begin(); i != intentions.end(); i++) {
if ((*i) > 0) {
if ((currentTargetNode == net->findSegment(*i)->getEnd()->getIndex()))
{
if ((currentTargetNode ==
net->findSegment(*i)->getEnd()->getIndex())) {
//cerr << "Current crosses at " << currentTargetNode <<endl;
return currentTargetNode;
}
}
}
}
if (other.intentions.size())
{
for (i = other.intentions.begin(); i != other.intentions.end(); i++)
{
if (other.intentions.size()) {
for (i = other.intentions.begin(); i != other.intentions.end();
i++) {
if ((*i) > 0) {
if (otherTargetNode == net->findSegment(*i)->getEnd()->getIndex())
{
if (otherTargetNode ==
net->findSegment(*i)->getEnd()->getIndex()) {
//cerr << "Other crosses at " << currentTargetNode <<endl;
return otherTargetNode;
}
}
}
}
if (intentions.size() && other.intentions.size())
{
for (i = intentions.begin(); i != intentions.end(); i++)
{
for (j = other.intentions.begin(); j != other.intentions.end(); j++)
{
if (intentions.size() && other.intentions.size()) {
for (i = intentions.begin(); i != intentions.end(); i++) {
for (j = other.intentions.begin(); j != other.intentions.end();
j++) {
//cerr << "finding segment " << *i << " and " << *j << endl;
if (((*i) > 0) && ((*j) > 0)) {
currentTargetNode = net->findSegment(*i)->getEnd()->getIndex();
otherTargetNode = net->findSegment(*j)->getEnd()->getIndex();
if (currentTargetNode == otherTargetNode)
{
currentTargetNode =
net->findSegment(*i)->getEnd()->getIndex();
otherTargetNode =
net->findSegment(*j)->getEnd()->getIndex();
if (currentTargetNode == otherTargetNode) {
//cerr << "Routes will cross at " << currentTargetNode << endl;
return currentTargetNode;
}
@ -196,21 +288,21 @@ int FGTrafficRecord::crosses(FGGroundNetwork *net, FGTrafficRecord &other)
return -1;
}
bool FGTrafficRecord::onRoute(FGGroundNetwork *net, FGTrafficRecord &other)
bool FGTrafficRecord::onRoute(FGGroundNetwork * net,
FGTrafficRecord & other)
{
int node = -1, othernode = -1;
if (currentPos > 0)
node = net->findSegment(currentPos)->getEnd()->getIndex();
if (other.currentPos > 0)
othernode = net->findSegment(other.currentPos)->getEnd()->getIndex();
othernode =
net->findSegment(other.currentPos)->getEnd()->getIndex();
if ((node == othernode) && (node != -1))
return true;
if (other.intentions.size())
{
for (intVecIterator i = other.intentions.begin(); i != other.intentions.end(); i++)
{
if (*i > 0)
{
if (other.intentions.size()) {
for (intVecIterator i = other.intentions.begin();
i != other.intentions.end(); i++) {
if (*i > 0) {
othernode = net->findSegment(*i)->getEnd()->getIndex();
if ((node == othernode) && (node > -1))
return true;
@ -235,27 +327,27 @@ bool FGTrafficRecord::onRoute(FGGroundNetwork *net, FGTrafficRecord &other)
}
bool FGTrafficRecord::isOpposing (FGGroundNetwork *net, FGTrafficRecord &other, int node)
bool FGTrafficRecord::isOpposing(FGGroundNetwork * net,
FGTrafficRecord & other, int node)
{
// Check if current segment is the reverse segment for the other aircraft
FGTaxiSegment *opp;
//cerr << "Current segment " << currentPos << endl;
if ((currentPos > 0) && (other.currentPos > 0))
{
if ((currentPos > 0) && (other.currentPos > 0)) {
opp = net->findSegment(currentPos)->opposite();
if (opp) {
if (opp->getIndex() == other.currentPos)
return true;
}
for (intVecIterator i = intentions.begin(); i != intentions.end(); i++)
{
if ((opp = net->findSegment(other.currentPos)->opposite()))
{
for (intVecIterator i = intentions.begin(); i != intentions.end();
i++) {
if ((opp = net->findSegment(other.currentPos)->opposite())) {
if ((*i) > 0)
if (opp->getIndex() == net->findSegment(*i)->getIndex())
{
if (net->findSegment(*i)->getStart()->getIndex() == node) {
if (opp->getIndex() ==
net->findSegment(*i)->getIndex()) {
if (net->findSegment(*i)->getStart()->getIndex() ==
node) {
{
//cerr << "Found the node " << node << endl;
return true;
@ -263,21 +355,19 @@ bool FGTrafficRecord::isOpposing (FGGroundNetwork *net, FGTrafficRecord &other,
}
}
}
if (other.intentions.size())
{
for (intVecIterator j = other.intentions.begin(); j != other.intentions.end(); j++)
{
if (other.intentions.size()) {
for (intVecIterator j = other.intentions.begin();
j != other.intentions.end(); j++) {
// cerr << "Current segment 1 " << (*i) << endl;
if ((*i) > 0) {
if ((opp = net->findSegment(*i)->opposite()))
{
if ((opp = net->findSegment(*i)->opposite())) {
if (opp->getIndex() ==
net->findSegment(*j)->getIndex())
{
net->findSegment(*j)->getIndex()) {
//cerr << "Nodes " << net->findSegment(*i)->getIndex()
// << " and " << net->findSegment(*j)->getIndex()
// << " are opposites " << endl;
if (net->findSegment(*i)->getStart()->getIndex() == node) {
if (net->findSegment(*i)->getStart()->
getIndex() == node) {
{
//cerr << "Found the node " << node << endl;
return true;
@ -305,11 +395,11 @@ void FGTrafficRecord::setHeadingAdjustment(double heading)
instruction.setHeading(heading);
}
bool FGTrafficRecord::pushBackAllowed() {
bool FGTrafficRecord::pushBackAllowed()
{
double course, az2, dist;
SGGeod curr(SGGeod::fromDegM(getLongitude(),
getLatitude(),
getAltitude()));
getLatitude(), getAltitude()));
double userLatitude = fgGetDouble("/position/latitude-deg");
double userLongitude = fgGetDouble("/position/longitude-deg");
@ -343,7 +433,8 @@ FGATCInstruction::FGATCInstruction()
bool FGATCInstruction::hasInstruction()
{
return (holdPattern || holdPosition || changeSpeed || changeHeading || changeAltitude || resolveCircularWait);
return (holdPattern || holdPosition || changeSpeed || changeHeading
|| changeAltitude || resolveCircularWait);
}
/***************************************************************************
@ -366,7 +457,8 @@ string FGATCController::getGateName(FGAIAircraft *ref)
return ref->atGate();
}
void FGATCController::transmit(FGTrafficRecord *rec, AtcMsgId msgId, AtcMsgDir msgDir)
void FGATCController::transmit(FGTrafficRecord * rec, AtcMsgId msgId,
AtcMsgDir msgDir)
{
string sender, receiver;
int stationFreq = 0;
@ -392,14 +484,22 @@ void FGATCController::transmit(FGTrafficRecord *rec, AtcMsgId msgId, AtcMsgDir m
case 3:
freqId = rec->getNextFrequency();
stationFreq =
rec->getAircraft()->getTrafficRef()->getDepartureAirport()->getDynamics()->getGroundFrequency(rec->getLeg()+freqId);
rec->getAircraft()->getTrafficRef()->getDepartureAirport()->
getDynamics()->getGroundFrequency(rec->getLeg() + freqId);
taxiFreq =
rec->getAircraft()->getTrafficRef()->getDepartureAirport()->getDynamics()->getGroundFrequency(3);
receiver = rec->getAircraft()->getTrafficRef()->getDepartureAirport()->getName() + "-Ground";
atisInformation = rec->getAircraft()->getTrafficRef()->getDepartureAirport()->getDynamics()->getAtisInformation();
rec->getAircraft()->getTrafficRef()->getDepartureAirport()->
getDynamics()->getGroundFrequency(3);
receiver =
rec->getAircraft()->getTrafficRef()->getDepartureAirport()->
getName() + "-Ground";
atisInformation =
rec->getAircraft()->getTrafficRef()->getDepartureAirport()->
getDynamics()->getAtisInformation();
break;
case 4:
receiver = rec->getAircraft()->getTrafficRef()->getDepartureAirport()->getName() + "-Tower";
receiver =
rec->getAircraft()->getTrafficRef()->getDepartureAirport()->
getName() + "-Tower";
break;
}
// Swap sender and receiver value in case of a ground to air transmission
@ -413,10 +513,14 @@ void FGATCController::transmit(FGTrafficRecord *rec, AtcMsgId msgId, AtcMsgDir m
text = sender + ". Ready to Start up";
break;
case MSG_REQUEST_ENGINE_START:
text = receiver + ", This is " + sender + ". Position " +getGateName(rec->getAircraft()) +
". Information " + atisInformation + ". " +
rec->getAircraft()->getTrafficRef()->getFlightRules() + " to " +
rec->getAircraft()->getTrafficRef()->getArrivalAirport()->getName() + ". Request start-up";
text =
receiver + ", This is " + sender + ". Position " +
getGateName(rec->getAircraft()) + ". Information " +
atisInformation + ". " +
rec->getAircraft()->getTrafficRef()->getFlightRules() +
" to " +
rec->getAircraft()->getTrafficRef()->getArrivalAirport()->
getName() + ". Request start-up";
break;
// Acknowledge engine startup permission
// Assign departure runway
@ -426,11 +530,16 @@ void FGATCController::transmit(FGTrafficRecord *rec, AtcMsgId msgId, AtcMsgDir m
heading = rec->getAircraft()->getTrafficRef()->getCourse();
fltType = rec->getAircraft()->getTrafficRef()->getFlightType();
rwyClass= rec->getAircraft()->GetFlightPlan()->getRunwayClassFromTrafficType(fltType);
rwyClass =
rec->getAircraft()->GetFlightPlan()->
getRunwayClassFromTrafficType(fltType);
rec->getAircraft()->getTrafficRef()->getDepartureAirport()->getDynamics()->getActiveRunway(rwyClass, 1, activeRunway, heading);
rec->getAircraft()->getTrafficRef()->getDepartureAirport()->
getDynamics()->getActiveRunway(rwyClass, 1, activeRunway,
heading);
rec->getAircraft()->GetFlightPlan()->setRunway(activeRunway);
fp = rec->getAircraft()->getTrafficRef()->getDepartureAirport()->getDynamics()->getSID(activeRunway, heading);
fp = rec->getAircraft()->getTrafficRef()->getDepartureAirport()->
getDynamics()->getSID(activeRunway, heading);
rec->getAircraft()->GetFlightPlan()->setSID(fp);
if (fp) {
SID = fp->getName() + " departure";
@ -441,9 +550,12 @@ void FGATCController::transmit(FGTrafficRecord *rec, AtcMsgId msgId, AtcMsgDir m
fltRules = rec->getAircraft()->getTrafficRef()->getFlightRules();
transponderCode = genTransponderCode(fltRules);
rec->getAircraft()->SetTransponderCode(transponderCode);
text = receiver + ". Start-up approved. " + atisInformation + " correct, runway " + activeRunway
+ ", " + SID + ", squawk " + transponderCode + ". " +
"For push-back and taxi clearance call " + taxiFreqStr + ". " + sender + " control.";
text =
receiver + ". Start-up approved. " + atisInformation +
" correct, runway " + activeRunway + ", " + SID + ", squawk " +
transponderCode + ". " +
"For push-back and taxi clearance call " + taxiFreqStr + ". " +
sender + " control.";
break;
case MSG_DENY_ENGINE_START:
text = receiver + ". Standby";
@ -451,16 +563,21 @@ void FGATCController::transmit(FGTrafficRecord *rec, AtcMsgId msgId, AtcMsgDir m
case MSG_ACKNOWLEDGE_ENGINE_START:
fp = rec->getAircraft()->GetFlightPlan()->getSID();
if (fp) {
SID = rec->getAircraft()->GetFlightPlan()->getSID()->getName() + " departure";
SID =
rec->getAircraft()->GetFlightPlan()->getSID()->getName() +
" departure";
} else {
SID = "fly runway heading ";
}
taxiFreqStr = formatATCFrequency3_2(taxiFreq);
activeRunway = rec->getAircraft()->GetFlightPlan()->getRunway();
transponderCode = rec->getAircraft()->GetTransponderCode();
text = receiver + ". Start-up approved. " + atisInformation + " correct, runway " +
activeRunway + ", " + SID + ", squawk " + transponderCode + ". " +
"For push-back and taxi clearance call " + taxiFreqStr + ". " + sender;
text =
receiver + ". Start-up approved. " + atisInformation +
" correct, runway " + activeRunway + ", " + SID + ", squawk " +
transponderCode + ". " +
"For push-back and taxi clearance call " + taxiFreqStr + ". " +
sender;
break;
case MSG_ACKNOWLEDGE_SWITCH_GROUND_FREQUENCY:
taxiFreqStr = formatATCFrequency3_2(taxiFreq);
@ -506,8 +623,10 @@ void FGATCController::transmit(FGTrafficRecord *rec, AtcMsgId msgId, AtcMsgDir m
text = text + sender + ". Transmitting unknown Message";
break;
}
double onBoardRadioFreq0 = fgGetDouble("/instrumentation/comm[0]/frequencies/selected-mhz");
double onBoardRadioFreq1 = fgGetDouble("/instrumentation/comm[1]/frequencies/selected-mhz");
double onBoardRadioFreq0 =
fgGetDouble("/instrumentation/comm[0]/frequencies/selected-mhz");
double onBoardRadioFreq1 =
fgGetDouble("/instrumentation/comm[1]/frequencies/selected-mhz");
int onBoardRadioFreqI0 = (int) floor(onBoardRadioFreq0 * 100 + 0.5);
int onBoardRadioFreqI1 = (int) floor(onBoardRadioFreq1 * 100 + 0.5);
//cerr << "Using " << onBoardRadioFreq0 << ", " << onBoardRadioFreq1 << " and " << stationFreq << " for " << text << endl;
@ -515,14 +634,16 @@ void FGATCController::transmit(FGTrafficRecord *rec, AtcMsgId msgId, AtcMsgDir m
// Display ATC message only when one of the radios is tuned
// the relevant frequency.
// Note that distance attenuation is currently not yet implemented
if ((onBoardRadioFreqI0 == stationFreq) || (onBoardRadioFreqI1 == stationFreq)) {
if ((onBoardRadioFreqI0 == stationFreq)
|| (onBoardRadioFreqI1 == stationFreq)) {
if (rec->allowTransmissions()) {
fgSetString("/sim/messages/atc", text.c_str());
}
}
}
string FGATCController::formatATCFrequency3_2(int freq) {
string FGATCController::formatATCFrequency3_2(int freq)
{
char buffer[7];
snprintf(buffer, 7, "%3.2f", ((float) freq / 100.0));
return string(buffer);
@ -530,12 +651,14 @@ string FGATCController::formatATCFrequency3_2(int freq) {
// TODO: Set transponder codes according to real-world routes.
// The current version just returns a random string of four octal numbers.
string FGATCController::genTransponderCode(string fltRules) {
string FGATCController::genTransponderCode(string fltRules)
{
if (fltRules == "VFR") {
return string("1200");
} else {
char buffer[5];
snprintf(buffer, 5, "%d%d%d%d", rand() % 8, rand() % 8,rand() % 8, rand() % 8);
snprintf(buffer, 5, "%d%d%d%d", rand() % 8, rand() % 8, rand() % 8,
rand() % 8);
return string(buffer);
}
}
@ -550,9 +673,12 @@ FGTowerController::FGTowerController() :
}
//
void FGTowerController::announcePosition(int id, FGAIFlightPlan *intendedRoute, int currentPosition,
double lat, double lon, double heading,
double speed, double alt, double radius, int leg,
void FGTowerController::announcePosition(int id,
FGAIFlightPlan * intendedRoute,
int currentPosition, double lat,
double lon, double heading,
double speed, double alt,
double radius, int leg,
FGAIAircraft * ref)
{
TrafficVectorIterator i = activeTraffic.begin();
@ -567,7 +693,6 @@ void FGTowerController::announcePosition(int id, FGAIFlightPlan *intendedRoute,
i++;
}
}
// Add a new TrafficRecord if no one exsists for this aircraft.
if (i == activeTraffic.end() || (activeTraffic.size() == 0)) {
FGTrafficRecord rec;
@ -584,11 +709,12 @@ void FGTowerController::announcePosition(int id, FGAIFlightPlan *intendedRoute,
}
}
void FGTowerController::update(int id, double lat, double lon, double heading, double speed, double alt,
void FGTowerController::update(int id, double lat, double lon,
double heading, double speed, double alt,
double dt)
{
TrafficVectorIterator i = activeTraffic.begin();
// Search search if the current id has an entry
// Search whether the current id has an entry
// This might be faster using a map instead of a vector, but let's start by taking a safe route
TrafficVectorIterator current, closest;
if (activeTraffic.size()) {
@ -600,10 +726,10 @@ void FGTowerController::update(int id, double lat, double lon, double heading, d
i++;
}
}
// // update position of the current aircraft
if (i == activeTraffic.end() || (activeTraffic.size() == 0)) {
SG_LOG(SG_GENERAL, SG_ALERT, "AI error: updating aircraft without traffic record");
SG_LOG(SG_GENERAL, SG_ALERT,
"AI error: updating aircraft without traffic record");
} else {
i->setPositionAndHeading(lat, lon, heading, speed, alt);
current = i;
@ -626,8 +752,7 @@ void FGTowerController::update(int id, double lat, double lon, double heading, d
ActiveRunway aRwy(current->getRunway(), id);
activeRunways.push_back(aRwy); // Since there are no clearance records for this runway yet
current->setHoldPosition(false); // Clear the current aircraft to continue
}
else {
} else {
// Okay, we have a clearance record for this runway, so check
// whether the clearence ID matches that of the current aircraft
if (id == rwy->getCleared()) {
@ -666,11 +791,13 @@ void FGTowerController::signOff(int id)
if (rwy != activeRunways.end()) {
rwy = activeRunways.erase(rwy);
} else {
SG_LOG(SG_GENERAL, SG_ALERT, "AI error: Attempting to erase non-existing runway clearance record in FGTowerController::signoff");
SG_LOG(SG_GENERAL, SG_ALERT,
"AI error: Attempting to erase non-existing runway clearance record in FGTowerController::signoff");
}
}
if (i == activeTraffic.end() || (activeTraffic.size() == 0)) {
SG_LOG(SG_GENERAL, SG_ALERT, "AI error: Aircraft without traffic record is signing off from tower");
SG_LOG(SG_GENERAL, SG_ALERT,
"AI error: Aircraft without traffic record is signing off from tower");
} else {
i = activeTraffic.erase(i);
}
@ -687,8 +814,7 @@ bool FGTowerController::hasInstruction(int id)
TrafficVectorIterator i = activeTraffic.begin();
// Search search if the current id has an entry
// This might be faster using a map instead of a vector, but let's start by taking a safe route
if (activeTraffic.size())
{
if (activeTraffic.size()) {
//while ((i->getId() != id) && i != activeTraffic.end()) {
while (i != activeTraffic.end()) {
if (i->getId() == id) {
@ -698,7 +824,8 @@ bool FGTowerController::hasInstruction(int id)
}
}
if (i == activeTraffic.end() || (activeTraffic.size() == 0)) {
SG_LOG(SG_GENERAL, SG_ALERT, "AI error: checking ATC instruction for aircraft without traffic record");
SG_LOG(SG_GENERAL, SG_ALERT,
"AI error: checking ATC instruction for aircraft without traffic record");
} else {
return i->hasInstruction();
}
@ -721,7 +848,8 @@ FGATCInstruction FGTowerController::getInstruction(int id)
}
}
if (i == activeTraffic.end() || (activeTraffic.size() == 0)) {
SG_LOG(SG_GENERAL, SG_ALERT, "AI error: requesting ATC instruction for aircraft without traffic record");
SG_LOG(SG_GENERAL, SG_ALERT,
"AI error: requesting ATC instruction for aircraft without traffic record");
} else {
return i->getInstruction();
}
@ -737,9 +865,12 @@ FGStartupController::FGStartupController() :
{
}
void FGStartupController::announcePosition(int id, FGAIFlightPlan *intendedRoute, int currentPosition,
double lat, double lon, double heading,
double speed, double alt, double radius, int leg,
void FGStartupController::announcePosition(int id,
FGAIFlightPlan * intendedRoute,
int currentPosition, double lat,
double lon, double heading,
double speed, double alt,
double radius, int leg,
FGAIAircraft * ref)
{
TrafficVectorIterator i = activeTraffic.begin();
@ -754,7 +885,6 @@ void FGStartupController::announcePosition(int id, FGAIFlightPlan *intendedRoute
i++;
}
}
// Add a new TrafficRecord if no one exsists for this aircraft.
if (i == activeTraffic.end() || (activeTraffic.size() == 0)) {
FGTrafficRecord rec;
@ -784,8 +914,7 @@ bool FGStartupController::hasInstruction(int id)
TrafficVectorIterator i = activeTraffic.begin();
// Search search if the current id has an entry
// This might be faster using a map instead of a vector, but let's start by taking a safe route
if (activeTraffic.size())
{
if (activeTraffic.size()) {
//while ((i->getId() != id) && i != activeTraffic.end()) {
while (i != activeTraffic.end()) {
if (i->getId() == id) {
@ -795,7 +924,8 @@ bool FGStartupController::hasInstruction(int id)
}
}
if (i == activeTraffic.end() || (activeTraffic.size() == 0)) {
SG_LOG(SG_GENERAL, SG_ALERT, "AI error: checking ATC instruction for aircraft without traffic record");
SG_LOG(SG_GENERAL, SG_ALERT,
"AI error: checking ATC instruction for aircraft without traffic record");
} else {
return i->hasInstruction();
}
@ -818,7 +948,8 @@ FGATCInstruction FGStartupController::getInstruction(int id)
}
}
if (i == activeTraffic.end() || (activeTraffic.size() == 0)) {
SG_LOG(SG_GENERAL, SG_ALERT, "AI error: requesting ATC instruction for aircraft without traffic record");
SG_LOG(SG_GENERAL, SG_ALERT,
"AI error: requesting ATC instruction for aircraft without traffic record");
} else {
return i->getInstruction();
}
@ -840,13 +971,15 @@ void FGStartupController::signOff(int id)
}
}
if (i == activeTraffic.end() || (activeTraffic.size() == 0)) {
SG_LOG(SG_GENERAL, SG_ALERT, "AI error: Aircraft without traffic record is signing off from tower");
SG_LOG(SG_GENERAL, SG_ALERT,
"AI error: Aircraft without traffic record is signing off from tower");
} else {
i = activeTraffic.erase(i);
}
}
void FGStartupController::update(int id, double lat, double lon, double heading, double speed, double alt,
void FGStartupController::update(int id, double lat, double lon,
double heading, double speed, double alt,
double dt)
{
TrafficVectorIterator i = activeTraffic.begin();
@ -862,10 +995,10 @@ void FGStartupController::update(int id, double lat, double lon, double heading,
i++;
}
}
// // update position of the current aircraft
if (i == activeTraffic.end() || (activeTraffic.size() == 0)) {
SG_LOG(SG_GENERAL, SG_ALERT, "AI error: updating aircraft without traffic record");
SG_LOG(SG_GENERAL, SG_ALERT,
"AI error: updating aircraft without traffic record");
} else {
i->setPositionAndHeading(lat, lon, heading, speed, alt);
current = i;
@ -873,7 +1006,8 @@ void FGStartupController::update(int id, double lat, double lon, double heading,
setDt(getDt() + dt);
int state = i->getState();
time_t startTime = i->getAircraft()->getTrafficRef()->getDepartureTime();
time_t startTime =
i->getAircraft()->getTrafficRef()->getDepartureTime();
time_t now = time(NULL) + fgGetLong("/sim/time/warp");
//cerr << i->getAircraft()->getTrafficRef()->getCallSign()
// << " is scheduled to depart in " << startTime-now << " seconds. Available = " << available
@ -910,7 +1044,8 @@ void FGStartupController::update(int id, double lat, double lon, double heading,
}
if ((state == 3) && available) {
if (now > startTime + 100) {
transmit(&(*i), MSG_ACKNOWLEDGE_ENGINE_START, ATC_AIR_TO_GROUND);
transmit(&(*i), MSG_ACKNOWLEDGE_ENGINE_START,
ATC_AIR_TO_GROUND);
i->updateState();
lastTransmission = now;
available = false;
@ -920,7 +1055,8 @@ void FGStartupController::update(int id, double lat, double lon, double heading,
// on a different frequency, compared to ground control
if ((state == 4) && available) {
if (now > startTime + 130) {
transmit(&(*i), MSG_ACKNOWLEDGE_SWITCH_GROUND_FREQUENCY, ATC_AIR_TO_GROUND);
transmit(&(*i), MSG_ACKNOWLEDGE_SWITCH_GROUND_FREQUENCY,
ATC_AIR_TO_GROUND);
i->updateState();
i->nextFrequency();
lastTransmission = now;
@ -937,19 +1073,20 @@ void FGStartupController::update(int id, double lat, double lon, double heading,
}
if ((state == 6) && available) {
if (now > startTime + 150) {
transmit(&(*i), MSG_ACKNOWLEDGE_INITIATE_CONTACT, ATC_GROUND_TO_AIR);
transmit(&(*i), MSG_ACKNOWLEDGE_INITIATE_CONTACT,
ATC_GROUND_TO_AIR);
i->updateState();
lastTransmission = now;
available = false;
}
}
// TODO: Switch to APRON control and request pushback Clearance.
// Get Push back clearance
if ((state == 7) && available) {
if (now > startTime + 180) {
transmit(&(*i), MSG_REQUEST_PUSHBACK_CLEARANCE, ATC_AIR_TO_GROUND);
transmit(&(*i), MSG_REQUEST_PUSHBACK_CLEARANCE,
ATC_AIR_TO_GROUND);
i->updateState();
lastTransmission = now;
available = false;
@ -959,10 +1096,12 @@ void FGStartupController::update(int id, double lat, double lon, double heading,
if (now > startTime + 200) {
if (i->pushBackAllowed()) {
i->allowRepeatedTransmissions();
transmit(&(*i), MSG_PERMIT_PUSHBACK_CLEARANCE, ATC_GROUND_TO_AIR);
transmit(&(*i), MSG_PERMIT_PUSHBACK_CLEARANCE,
ATC_GROUND_TO_AIR);
i->updateState();
} else {
transmit(&(*i), MSG_HOLD_PUSHBACK_CLEARANCE, ATC_GROUND_TO_AIR);
transmit(&(*i), MSG_HOLD_PUSHBACK_CLEARANCE,
ATC_GROUND_TO_AIR);
i->suppressRepeatedTransmissions();
}
lastTransmission = now;
@ -973,3 +1112,194 @@ void FGStartupController::update(int id, double lat, double lon, double heading,
i->setHoldPosition(false);
}
}
/***************************************************************************
* class FGApproachController
*
**************************************************************************/
FGApproachController::FGApproachController():
FGATCController()
{
}
//
void FGApproachController::announcePosition(int id,
FGAIFlightPlan * intendedRoute,
int currentPosition,
double lat, double lon,
double heading, double speed,
double alt, double radius,
int leg, FGAIAircraft * ref)
{
TrafficVectorIterator i = activeTraffic.begin();
// Search whether the current id alread has an entry
// This might be faster using a map instead of a vector, but let's start by taking a safe route
if (activeTraffic.size()) {
//while ((i->getId() != id) && i != activeTraffic.end()) {
while (i != activeTraffic.end()) {
if (i->getId() == id) {
break;
}
i++;
}
}
// Add a new TrafficRecord if no one exsists for this aircraft.
if (i == activeTraffic.end() || (activeTraffic.size() == 0)) {
FGTrafficRecord rec;
rec.setId(id);
rec.setPositionAndHeading(lat, lon, heading, speed, alt);
rec.setRunway(intendedRoute->getRunway());
rec.setLeg(leg);
//rec.setCallSign(callsign);
rec.setAircraft(ref);
activeTraffic.push_back(rec);
} else {
i->setPositionAndHeading(lat, lon, heading, speed, alt);
}
}
void FGApproachController::update(int id, double lat, double lon,
double heading, double speed, double alt,
double dt)
{
TrafficVectorIterator i = activeTraffic.begin();
// Search search if the current id has an entry
// This might be faster using a map instead of a vector, but let's start by taking a safe route
TrafficVectorIterator current, closest;
if (activeTraffic.size()) {
//while ((i->getId() != id) && i != activeTraffic.end()) {
while (i != activeTraffic.end()) {
if (i->getId() == id) {
break;
}
i++;
}
}
// // update position of the current aircraft
if (i == activeTraffic.end() || (activeTraffic.size() == 0)) {
SG_LOG(SG_GENERAL, SG_ALERT,
"AI error: updating aircraft without traffic record");
} else {
i->setPositionAndHeading(lat, lon, heading, speed, alt);
current = i;
//cerr << "ApproachController: checking for speed" << endl;
time_t time_diff =
current->getAircraft()->
checkForArrivalTime(string("final001"));
if (time_diff > 15) {
current->setSpeedAdjustment(current->getAircraft()->
getPerformance()->vDescent() *
1.35);
} else if (time_diff > 5) {
current->setSpeedAdjustment(current->getAircraft()->
getPerformance()->vDescent() *
1.2);
} else if (time_diff < -15) {
current->setSpeedAdjustment(current->getAircraft()->
getPerformance()->vDescent() *
0.65);
} else if (time_diff < -5) {
current->setSpeedAdjustment(current->getAircraft()->
getPerformance()->vDescent() *
0.8);
} else {
current->clearSpeedAdjustment();
}
//current->setSpeedAdjustment(current->getAircraft()->getPerformance()->vDescent() + time_diff);
}
setDt(getDt() + dt);
}
void FGApproachController::signOff(int id)
{
TrafficVectorIterator i = activeTraffic.begin();
// Search search if the current id alread has an entry
// This might be faster using a map instead of a vector, but let's start by taking a safe route
if (activeTraffic.size()) {
//while ((i->getId() != id) && i != activeTraffic.end()) {
while (i != activeTraffic.end()) {
if (i->getId() == id) {
break;
}
i++;
}
}
if (i == activeTraffic.end() || (activeTraffic.size() == 0)) {
SG_LOG(SG_GENERAL, SG_ALERT,
"AI error: Aircraft without traffic record is signing off from approach");
} else {
i = activeTraffic.erase(i);
}
}
bool FGApproachController::hasInstruction(int id)
{
TrafficVectorIterator i = activeTraffic.begin();
// Search search if the current id has an entry
// This might be faster using a map instead of a vector, but let's start by taking a safe route
if (activeTraffic.size()) {
//while ((i->getId() != id) && i != activeTraffic.end()) {
while (i != activeTraffic.end()) {
if (i->getId() == id) {
break;
}
i++;
}
}
if (i == activeTraffic.end() || (activeTraffic.size() == 0)) {
SG_LOG(SG_GENERAL, SG_ALERT,
"AI error: checking ATC instruction for aircraft without traffic record");
} else {
return i->hasInstruction();
}
return false;
}
FGATCInstruction FGApproachController::getInstruction(int id)
{
TrafficVectorIterator i = activeTraffic.begin();
// Search search if the current id has an entry
// This might be faster using a map instead of a vector, but let's start by taking a safe route
if (activeTraffic.size()) {
//while ((i->getId() != id) && i != activeTraffic.end()) {
while (i != activeTraffic.end()) {
if (i->getId() == id) {
break;
}
i++;
}
}
if (i == activeTraffic.end() || (activeTraffic.size() == 0)) {
SG_LOG(SG_GENERAL, SG_ALERT,
"AI error: requesting ATC instruction for aircraft without traffic record");
} else {
return i->getInstruction();
}
return FGATCInstruction();
}
ActiveRunway *FGApproachController::getRunway(string name)
{
ActiveRunwayVecIterator rwy = activeRunways.begin();
if (activeRunways.size()) {
while (rwy != activeRunways.end()) {
if (rwy->getRunwayName() == name) {
break;
}
rwy++;
}
}
if (rwy == activeRunways.end()) {
ActiveRunway aRwy(name, 0);
activeRunways.push_back(aRwy);
rwy = activeRunways.end() - 1;
}
return &(*rwy);
}

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

@ -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;
@ -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()))
{
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,6 +110,7 @@ string ScheduleTime::getName(time_t dayStart)
}
return string("");
}
/******************************************************************************
* RunwayList
*****************************************************************************/
@ -119,18 +119,22 @@ 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)
{
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)
{
//weekday = atoi(timeCopy.substr(0,1).c_str());
@ -139,8 +143,7 @@ void RunwayList::set(const string &tp, const string &lst)
type = tp;
string rwys = lst;
string rwy;
while (rwys.find(",") != string::npos)
{
while (rwys.find(",") != string::npos) {
rwy = rwys.substr(0, rwys.find(",", 0));
//cerr << "adding runway [" << rwy << "] to the list " << endl;
preferredRunways.push_back(rwy);
@ -158,6 +161,7 @@ void RunwayList::clear()
type = "";
preferredRunways.clear();
}
/****************************************************************************
*
***************************************************************************/
@ -172,6 +176,7 @@ RunwayGroup::RunwayGroup(const RunwayGroup &other)
choice[1] = other.choice[1];
nrActive = other.nrActive;
}
RunwayGroup & RunwayGroup::operator=(const RunwayGroup & other)
{
rwyList.clear();
@ -189,8 +194,7 @@ void RunwayGroup::setActive(const FGAirport* airport,
double windSpeed,
double windHeading,
double maxTail,
double maxCross,
stringVec *currentlyActive)
double maxCross, stringVec * currentlyActive)
{
FGRunway *rwy;
@ -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
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);
@ -315,8 +314,7 @@ void RunwayGroup::setActive(const FGAirport* airport,
}
if (validSelection)
{
if (validSelection) {
//cerr << "Valid runay selection : " << i << endl;
active = i;
nrActive = 2;
@ -330,21 +328,18 @@ void RunwayGroup::setActive(const FGAirport* airport,
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
****************************************************************************/
@ -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;
@ -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;