1
0
Fork 0

Merge branch 'durk-atc' into next

This commit is contained in:
Durk Talsma 2011-08-10 21:42:12 +02:00
commit cfa08438ae
19 changed files with 799 additions and 632 deletions

View file

@ -65,9 +65,10 @@ FGAIAircraft::FGAIAircraft(FGAISchedule *ref) :
else else
groundOffset = 0; groundOffset = 0;
fp = 0; fp = 0;
controller = 0; controller = 0;
prevController = 0; prevController = 0;
towerController = 0;
dt_count = 0; dt_count = 0;
dt_elev_count = 0; dt_elev_count = 0;
use_perf_vs = true; use_perf_vs = true;
@ -92,6 +93,7 @@ FGAIAircraft::FGAIAircraft(FGAISchedule *ref) :
_performance = 0; //TODO initialize to JET_TRANSPORT from PerformanceDB _performance = 0; //TODO initialize to JET_TRANSPORT from PerformanceDB
dt = 0; dt = 0;
takeOffStatus = 0;
} }
@ -249,11 +251,11 @@ void FGAIAircraft::SetFlightPlan(FGAIFlightPlan *f) {
void FGAIAircraft::ProcessFlightPlan( double dt, time_t now ) { void FGAIAircraft::ProcessFlightPlan( double dt, time_t now ) {
// the one behind you // the one behind you
FGAIFlightPlan::waypoint* prev = 0; FGAIWaypoint* prev = 0;
// the one ahead // the one ahead
FGAIFlightPlan::waypoint* curr = 0; FGAIWaypoint* curr = 0;
// the next plus 1 // the next plus 1
FGAIFlightPlan::waypoint* next = 0; FGAIWaypoint* next = 0;
prev = fp->getPreviousWaypoint(); prev = fp->getPreviousWaypoint();
curr = fp->getCurrentWaypoint(); curr = fp->getCurrentWaypoint();
@ -300,7 +302,7 @@ void FGAIAircraft::ProcessFlightPlan( double dt, time_t now ) {
<< endl; << endl;
} */ } */
} else { } else {
if (curr->finished) //end of the flight plan if (curr->isFinished()) //end of the flight plan
{ {
if (fp->getRepeat()) if (fp->getRepeat())
fp->restart(); fp->restart();
@ -348,22 +350,22 @@ void FGAIAircraft::ProcessFlightPlan( double dt, time_t now ) {
fp->setLeadDistance(tgt_speed, tgt_heading, curr, next); fp->setLeadDistance(tgt_speed, tgt_heading, curr, next);
} }
if (!(prev->on_ground)) // only update the tgt altitude from flightplan if not on the ground if (!(prev->getOn_ground())) // only update the tgt altitude from flightplan if not on the ground
{ {
tgt_altitude_ft = prev->altitude; tgt_altitude_ft = prev->getAltitude();
if (curr->crossat > -1000.0) { if (curr->getCrossat() > -1000.0) {
use_perf_vs = false; use_perf_vs = false;
tgt_vs = (curr->crossat - altitude_ft) / (fp->getDistanceToGo(pos.getLatitudeDeg(), pos.getLongitudeDeg(), curr) tgt_vs = (curr->getCrossat() - altitude_ft) / (fp->getDistanceToGo(pos.getLatitudeDeg(), pos.getLongitudeDeg(), curr)
/ 6076.0 / speed*60.0); / 6076.0 / speed*60.0);
checkTcas(); checkTcas();
tgt_altitude_ft = curr->crossat; tgt_altitude_ft = curr->getCrossat();
} else { } else {
use_perf_vs = true; use_perf_vs = true;
} }
} }
AccelTo(prev->speed); AccelTo(prev->getSpeed());
hdg_lock = alt_lock = true; hdg_lock = alt_lock = true;
no_roll = prev->on_ground; no_roll = prev->getOn_ground();
} }
} }
@ -407,16 +409,18 @@ const char * FGAIAircraft::_getTransponderCode() const {
return transponderCode.c_str(); return transponderCode.c_str();
} }
// NOTE: Check whether the new (delayed leg increment code has any effect on this code.
// Probably not, because it should only be executed after we have already passed the leg incrementing waypoint.
bool FGAIAircraft::loadNextLeg(double distance) { bool FGAIAircraft::loadNextLeg(double distance) {
int leg; int leg;
if ((leg = fp->getLeg()) == 10) { if ((leg = fp->getLeg()) == 9) {
if (!trafficRef->next()) { if (!trafficRef->next()) {
return false; return false;
} }
setCallSign(trafficRef->getCallSign()); setCallSign(trafficRef->getCallSign());
leg = 1; leg = 0;
fp->setLeg(leg); fp->setLeg(leg);
} }
@ -431,7 +435,7 @@ bool FGAIAircraft::loadNextLeg(double distance) {
fp->create (this, fp->create (this,
dep, dep,
arr, arr,
leg, leg+1,
cruiseAlt, cruiseAlt,
trafficRef->getSpeed(), trafficRef->getSpeed(),
_getLatitude(), _getLatitude(),
@ -508,29 +512,31 @@ void FGAIAircraft::announcePositionToController() {
// Note that leg has been incremented after creating the current leg, so we should use // Note that leg has been incremented after creating the current leg, so we should use
// leg numbers here that are one higher than the number that is used to create the leg // leg numbers here that are one higher than the number that is used to create the leg
// // NOTE: As of July, 30, 2011, the post-creation leg updating is no longer happening.
// Leg numbers are updated only once the aircraft passes the last waypoint created for that legm so I should probably just use
// the original leg numbers here!
switch (leg) { switch (leg) {
case 2: // Startup and Push back case 1: // Startup and Push back
if (trafficRef->getDepartureAirport()->getDynamics()) if (trafficRef->getDepartureAirport()->getDynamics())
controller = trafficRef->getDepartureAirport()->getDynamics()->getStartupController(); controller = trafficRef->getDepartureAirport()->getDynamics()->getStartupController();
break; break;
case 3: // Taxiing to runway case 2: // Taxiing to runway
if (trafficRef->getDepartureAirport()->getDynamics()->getGroundNetwork()->exists()) if (trafficRef->getDepartureAirport()->getDynamics()->getGroundNetwork()->exists())
controller = trafficRef->getDepartureAirport()->getDynamics()->getGroundNetwork(); controller = trafficRef->getDepartureAirport()->getDynamics()->getGroundNetwork();
break; break;
case 4: //Take off tower controller case 3: //Take off tower controller
if (trafficRef->getDepartureAirport()->getDynamics()) { if (trafficRef->getDepartureAirport()->getDynamics()) {
controller = trafficRef->getDepartureAirport()->getDynamics()->getTowerController(); controller = trafficRef->getDepartureAirport()->getDynamics()->getTowerController();
} else { } else {
cerr << "Error: Could not find Dynamics at airport : " << trafficRef->getDepartureAirport()->getId() << endl; cerr << "Error: Could not find Dynamics at airport : " << trafficRef->getDepartureAirport()->getId() << endl;
} }
break; break;
case 7: case 6:
if (trafficRef->getDepartureAirport()->getDynamics()) { if (trafficRef->getDepartureAirport()->getDynamics()) {
controller = trafficRef->getArrivalAirport()->getDynamics()->getApproachController(); controller = trafficRef->getArrivalAirport()->getDynamics()->getApproachController();
} }
break; break;
case 9: // Taxiing for parking case 8: // Taxiing for parking
if (trafficRef->getArrivalAirport()->getDynamics()->getGroundNetwork()->exists()) if (trafficRef->getArrivalAirport()->getDynamics()->getGroundNetwork()->exists())
controller = trafficRef->getArrivalAirport()->getDynamics()->getGroundNetwork(); controller = trafficRef->getArrivalAirport()->getDynamics()->getGroundNetwork();
break; break;
@ -544,13 +550,33 @@ void FGAIAircraft::announcePositionToController() {
} }
prevController = controller; prevController = controller;
if (controller) { if (controller) {
controller->announcePosition(getID(), fp, fp->getCurrentWaypoint()->routeIndex, controller->announcePosition(getID(), fp, fp->getCurrentWaypoint()->getRouteIndex(),
_getLatitude(), _getLongitude(), hdg, speed, altitude_ft, _getLatitude(), _getLongitude(), hdg, speed, altitude_ft,
trafficRef->getRadius(), leg, this); trafficRef->getRadius(), leg, this);
} }
} }
} }
void FGAIAircraft::scheduleForATCTowerDepartureControl(int state) {
if (!takeOffStatus) {
int leg = fp->getLeg();
if (trafficRef) {
if (trafficRef->getDepartureAirport()->getDynamics()) {
towerController = trafficRef->getDepartureAirport()->getDynamics()->getTowerController();
} else {
cerr << "Error: Could not find Dynamics at airport : " << trafficRef->getDepartureAirport()->getId() << endl;
}
if (towerController) {
towerController->announcePosition(getID(), fp, fp->getCurrentWaypoint()->getRouteIndex(),
_getLatitude(), _getLongitude(), hdg, speed, altitude_ft,
trafficRef->getRadius(), leg, this);
//cerr << "Scheduling " << trafficRef->getCallSign() << " for takeoff " << endl;
}
}
}
takeOffStatus = state;
}
// Process ATC instructions and report back // Process ATC instructions and report back
void FGAIAircraft::processATC(FGATCInstruction instruction) { void FGAIAircraft::processATC(FGATCInstruction instruction) {
@ -587,7 +613,7 @@ void FGAIAircraft::processATC(FGATCInstruction instruction) {
//cerr << trafficRef->getCallSign() << " Changing Speed " << endl; //cerr << trafficRef->getCallSign() << " Changing Speed " << endl;
AccelTo(instruction.getSpeed()); AccelTo(instruction.getSpeed());
} else { } else {
if (fp) AccelTo(fp->getPreviousWaypoint()->speed); if (fp) AccelTo(fp->getPreviousWaypoint()->getSpeed());
} }
} }
if (instruction.getChangeHeading ()) { if (instruction.getChangeHeading ()) {
@ -612,9 +638,9 @@ void FGAIAircraft::handleFirstWaypoint() {
eraseWaypoints = false; eraseWaypoints = false;
} }
FGAIFlightPlan::waypoint* prev = 0; // the one behind you FGAIWaypoint* prev = 0; // the one behind you
FGAIFlightPlan::waypoint* curr = 0; // the one ahead FGAIWaypoint* curr = 0; // the one ahead
FGAIFlightPlan::waypoint* next = 0;// the next plus 1 FGAIWaypoint* next = 0;// the next plus 1
spinCounter = 0; spinCounter = 0;
tempReg = ""; tempReg = "";
@ -631,15 +657,15 @@ void FGAIAircraft::handleFirstWaypoint() {
curr = fp->getCurrentWaypoint(); //second waypoint curr = fp->getCurrentWaypoint(); //second waypoint
next = fp->getNextWaypoint(); //third waypoint (might not exist!) next = fp->getNextWaypoint(); //third waypoint (might not exist!)
setLatitude(prev->latitude); setLatitude(prev->getLatitude());
setLongitude(prev->longitude); setLongitude(prev->getLongitude());
setSpeed(prev->speed); setSpeed(prev->getSpeed());
setAltitude(prev->altitude); setAltitude(prev->getAltitude());
if (prev->speed > 0.0) if (prev->getSpeed() > 0.0)
setHeading(fp->getBearing(prev->latitude, prev->longitude, curr)); setHeading(fp->getBearing(prev->getLatitude(), prev->getLongitude(), curr));
else else
setHeading(fp->getBearing(curr->latitude, curr->longitude, prev)); setHeading(fp->getBearing(curr->getLatitude(), curr->getLongitude(), prev));
// If next doesn't exist, as in incrementally created flightplans for // If next doesn't exist, as in incrementally created flightplans for
// AI/Trafficmanager created plans, // AI/Trafficmanager created plans,
@ -647,20 +673,20 @@ void FGAIAircraft::handleFirstWaypoint() {
if (next) if (next)
fp->setLeadDistance(speed, hdg, curr, next); fp->setLeadDistance(speed, hdg, curr, next);
if (curr->crossat > -1000.0) //use a calculated descent/climb rate if (curr->getCrossat() > -1000.0) //use a calculated descent/climb rate
{ {
use_perf_vs = false; use_perf_vs = false;
tgt_vs = (curr->crossat - prev->altitude) tgt_vs = (curr->getCrossat() - prev->getAltitude())
/ (fp->getDistanceToGo(pos.getLatitudeDeg(), pos.getLongitudeDeg(), curr) / (fp->getDistanceToGo(pos.getLatitudeDeg(), pos.getLongitudeDeg(), curr)
/ 6076.0 / prev->speed*60.0); / 6076.0 / prev->getSpeed()*60.0);
checkTcas(); checkTcas();
tgt_altitude_ft = curr->crossat; tgt_altitude_ft = curr->getCrossat();
} else { } else {
use_perf_vs = true; use_perf_vs = true;
tgt_altitude_ft = prev->altitude; tgt_altitude_ft = prev->getAltitude();
} }
alt_lock = hdg_lock = true; alt_lock = hdg_lock = true;
no_roll = prev->on_ground; no_roll = prev->getOn_ground();
if (no_roll) { if (no_roll) {
Transform(); // make sure aip is initialized. Transform(); // make sure aip is initialized.
getGroundElev(60.1); // make sure it's executed first time around, so force a large dt value getGroundElev(60.1); // make sure it's executed first time around, so force a large dt value
@ -693,19 +719,19 @@ bool FGAIAircraft::fpExecutable(time_t now) {
* @param curr * @param curr
* @return * @return
*/ */
bool FGAIAircraft::leadPointReached(FGAIFlightPlan::waypoint* curr) { bool FGAIAircraft::leadPointReached(FGAIWaypoint* curr) {
double dist_to_go = fp->getDistanceToGo(pos.getLatitudeDeg(), pos.getLongitudeDeg(), curr); double dist_to_go = fp->getDistanceToGo(pos.getLatitudeDeg(), pos.getLongitudeDeg(), curr);
//cerr << "2" << endl; //cerr << "2" << endl;
double lead_dist = fp->getLeadDistance(); double lead_dist = fp->getLeadDistance();
// experimental: Use fabs, because speed can be negative (I hope) during push_back. // experimental: Use fabs, because speed can be negative (I hope) during push_back.
if ((dist_to_go < fabs(10.0* speed)) && (speed < 0) && (tgt_speed < 0) && fp->getCurrentWaypoint()->name == string("PushBackPoint")) { if ((dist_to_go < fabs(10.0* speed)) && (speed < 0) && (tgt_speed < 0) && fp->getCurrentWaypoint()->contains("PushBackPoint")) {
tgt_speed = -(dist_to_go / 10.0); tgt_speed = -(dist_to_go / 10.0);
if (tgt_speed > -0.5) { if (tgt_speed > -0.5) {
tgt_speed = -0.5; tgt_speed = -0.5;
} }
if (fp->getPreviousWaypoint()->speed < tgt_speed) { if (fp->getPreviousWaypoint()->getSpeed() < tgt_speed) {
fp->getPreviousWaypoint()->speed = tgt_speed; fp->getPreviousWaypoint()->setSpeed(tgt_speed);
} }
} }
if (lead_dist < fabs(2*speed)) { if (lead_dist < fabs(2*speed)) {
@ -768,7 +794,7 @@ bool FGAIAircraft::aiTrafficVisible() {
*/ */
//TODO the trafficRef is the right place for the method //TODO the trafficRef is the right place for the method
bool FGAIAircraft::handleAirportEndPoints(FGAIFlightPlan::waypoint* prev, time_t now) { bool FGAIAircraft::handleAirportEndPoints(FGAIWaypoint* prev, time_t now) {
// prepare routing from one airport to another // prepare routing from one airport to another
FGAirport * dep = trafficRef->getDepartureAirport(); FGAirport * dep = trafficRef->getDepartureAirport();
FGAirport * arr = trafficRef->getArrivalAirport(); FGAirport * arr = trafficRef->getArrivalAirport();
@ -779,21 +805,29 @@ bool FGAIAircraft::handleAirportEndPoints(FGAIFlightPlan::waypoint* prev, time_t
// This waypoint marks the fact that the aircraft has passed the initial taxi // This waypoint marks the fact that the aircraft has passed the initial taxi
// departure waypoint, so it can release the parking. // departure waypoint, so it can release the parking.
//cerr << trafficRef->getCallSign() << " has passed waypoint " << prev->name << " at speed " << speed << endl; //cerr << trafficRef->getCallSign() << " has passed waypoint " << prev->name << " at speed " << speed << endl;
if (prev->name == "PushBackPoint") { //cerr << "Passing waypoint : " << prev->getName() << endl;
if (prev->contains("PushBackPoint")) {
dep->getDynamics()->releaseParking(fp->getGate()); dep->getDynamics()->releaseParking(fp->getGate());
AccelTo(0.0); AccelTo(0.0);
setTaxiClearanceRequest(true); //setTaxiClearanceRequest(true);
}
if (prev->contains("legend")) {
fp->incrementLeg();
}
if (prev->contains(string("DepartureHold"))) {
//cerr << "Passing point DepartureHold" << endl;
scheduleForATCTowerDepartureControl(2);
} }
// This is the last taxi waypoint, and marks the the end of the flight plan // This is the last taxi waypoint, and marks the the end of the flight plan
// so, the schedule should update and wait for the next departure time. // so, the schedule should update and wait for the next departure time.
if (prev->name == "END") { if (prev->contains("END")) {
time_t nextDeparture = trafficRef->getDepartureTime(); time_t nextDeparture = trafficRef->getDepartureTime();
// make sure to wait at least 20 minutes at parking to prevent "nervous" taxi behavior // make sure to wait at least 20 minutes at parking to prevent "nervous" taxi behavior
if (nextDeparture < (now+1200)) { if (nextDeparture < (now+1200)) {
nextDeparture = now + 1200; nextDeparture = now + 1200;
} }
fp->setTime(nextDeparture); // should be "next departure" fp->setTime(nextDeparture);
} }
return true; return true;
@ -805,7 +839,7 @@ bool FGAIAircraft::handleAirportEndPoints(FGAIFlightPlan::waypoint* prev, time_t
* *
* @param curr * @param curr
*/ */
void FGAIAircraft::controlHeading(FGAIFlightPlan::waypoint* curr) { void FGAIAircraft::controlHeading(FGAIWaypoint* curr) {
double calc_bearing = fp->getBearing(pos.getLatitudeDeg(), pos.getLongitudeDeg(), curr); double calc_bearing = fp->getBearing(pos.getLatitudeDeg(), pos.getLongitudeDeg(), curr);
//cerr << "Bearing = " << calc_bearing << endl; //cerr << "Bearing = " << calc_bearing << endl;
if (speed < 0) { if (speed < 0) {
@ -824,8 +858,8 @@ void FGAIAircraft::controlHeading(FGAIFlightPlan::waypoint* curr) {
cerr << "calc_bearing is not a finite number : " cerr << "calc_bearing is not a finite number : "
<< "Speed " << speed << "Speed " << speed
<< "pos : " << pos.getLatitudeDeg() << ", " << pos.getLongitudeDeg() << "pos : " << pos.getLatitudeDeg() << ", " << pos.getLongitudeDeg()
<< "waypoint " << curr->latitude << ", " << curr->longitude << endl; << "waypoint " << curr->getLatitude() << ", " << curr->getLongitude() << endl;
cerr << "waypoint name " << curr->name; cerr << "waypoint name " << curr->getName();
exit(1); // FIXME exit(1); // FIXME
} }
} }
@ -838,7 +872,7 @@ void FGAIAircraft::controlHeading(FGAIFlightPlan::waypoint* curr) {
* @param curr * @param curr
* @param next * @param next
*/ */
void FGAIAircraft::controlSpeed(FGAIFlightPlan::waypoint* curr, FGAIFlightPlan::waypoint* next) { void FGAIAircraft::controlSpeed(FGAIWaypoint* curr, FGAIWaypoint* next) {
double speed_diff = speed - prevSpeed; double speed_diff = speed - prevSpeed;
if (fabs(speed_diff) > 10) { if (fabs(speed_diff) > 10) {
@ -1168,8 +1202,8 @@ void FGAIAircraft::updateSecondaryTargetValues() {
bool FGAIAircraft::reachedEndOfCruise(double &distance) { bool FGAIAircraft::reachedEndOfCruise(double &distance) {
FGAIFlightPlan::waypoint* curr = fp->getCurrentWaypoint(); FGAIWaypoint* curr = fp->getCurrentWaypoint();
if (curr->name == "BOD") { if (curr->getName() == string("BOD")) {
double dist = fp->getDistanceToGo(pos.getLatitudeDeg(), pos.getLongitudeDeg(), curr); 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 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 descentRate = (getPerformance()->descentRate() * SG_FEET_TO_METER) / 60.0; // convert from feet/min to meter/s
@ -1205,22 +1239,22 @@ bool FGAIAircraft::reachedEndOfCruise(double &distance) {
void FGAIAircraft::resetPositionFromFlightPlan() void FGAIAircraft::resetPositionFromFlightPlan()
{ {
// the one behind you // the one behind you
FGAIFlightPlan::waypoint* prev = 0; FGAIWaypoint* prev = 0;
// the one ahead // the one ahead
FGAIFlightPlan::waypoint* curr = 0; FGAIWaypoint* curr = 0;
// the next plus 1 // the next plus 1
FGAIFlightPlan::waypoint* next = 0; FGAIWaypoint* next = 0;
prev = fp->getPreviousWaypoint(); prev = fp->getPreviousWaypoint();
curr = fp->getCurrentWaypoint(); curr = fp->getCurrentWaypoint();
next = fp->getNextWaypoint(); next = fp->getNextWaypoint();
setLatitude(prev->latitude); setLatitude(prev->getLatitude());
setLongitude(prev->longitude); setLongitude(prev->getLongitude());
double tgt_heading = fp->getBearing(curr, next); double tgt_heading = fp->getBearing(curr, next);
setHeading(tgt_heading); setHeading(tgt_heading);
setAltitude(prev->altitude); setAltitude(prev->getAltitude());
setSpeed(prev->speed); setSpeed(prev->getSpeed());
} }
double FGAIAircraft::getBearing(double crse) double FGAIAircraft::getBearing(double crse)
@ -1232,7 +1266,7 @@ double FGAIAircraft::getBearing(double crse)
} }
time_t FGAIAircraft::checkForArrivalTime(string wptName) { time_t FGAIAircraft::checkForArrivalTime(string wptName) {
FGAIFlightPlan::waypoint* curr = 0; FGAIWaypoint* curr = 0;
curr = fp->getCurrentWaypoint(); curr = fp->getCurrentWaypoint();
double tracklength = fp->checkTrackLength(wptName); double tracklength = fp->checkTrackLength(wptName);

View file

@ -77,6 +77,11 @@ public:
bool getTaxiClearanceRequest() { return needsTaxiClearance; }; bool getTaxiClearanceRequest() { return needsTaxiClearance; };
FGAISchedule * getTrafficRef() { return trafficRef; }; FGAISchedule * getTrafficRef() { return trafficRef; };
void setTrafficRef(FGAISchedule *ref) { trafficRef = ref; }; void setTrafficRef(FGAISchedule *ref) { trafficRef = ref; };
void resetTakeOffStatus() { takeOffStatus = 0;};
void setTakeOffStatus(int status) { takeOffStatus = status; };
void scheduleForATCTowerDepartureControl(int state);
//inline bool isScheduledForTakeoff() { return scheduledForTakeoff; };
virtual const char* getTypeString(void) const { return "aircraft"; } virtual const char* getTypeString(void) const { return "aircraft"; }
@ -95,6 +100,8 @@ public:
inline double airspeed() const { return props->getFloatValue("velocities/airspeed-kt");}; inline double airspeed() const { return props->getFloatValue("velocities/airspeed-kt");};
std::string atGate(); std::string atGate();
int getTakeOffStatus() { return takeOffStatus; };
void checkTcas(); void checkTcas();
FGATCController * getATCController() { return controller; }; FGATCController * getATCController() { return controller; };
@ -104,7 +111,9 @@ protected:
private: private:
FGAISchedule *trafficRef; FGAISchedule *trafficRef;
FGATCController *controller, *prevController; FGATCController *controller,
*prevController,
*towerController; // Only needed to make a pre-announcement
bool hdg_lock; bool hdg_lock;
bool alt_lock; bool alt_lock;
@ -126,13 +135,13 @@ private:
//subclasses to override specific behaviour //subclasses to override specific behaviour
bool fpExecutable(time_t now); bool fpExecutable(time_t now);
void handleFirstWaypoint(void); void handleFirstWaypoint(void);
bool leadPointReached(FGAIFlightPlan::waypoint* curr); bool leadPointReached(FGAIWaypoint* curr);
bool handleAirportEndPoints(FGAIFlightPlan::waypoint* prev, time_t now); bool handleAirportEndPoints(FGAIWaypoint* prev, time_t now);
bool reachedEndOfCruise(double&); bool reachedEndOfCruise(double&);
bool aiTrafficVisible(void); bool aiTrafficVisible(void);
void controlHeading(FGAIFlightPlan::waypoint* curr); void controlHeading(FGAIWaypoint* curr);
void controlSpeed(FGAIFlightPlan::waypoint* curr, void controlSpeed(FGAIWaypoint* curr,
FGAIFlightPlan::waypoint* next); FGAIWaypoint* next);
void updatePrimaryTargetValues(bool& flightplanActive, bool& aiOutOfSight); void updatePrimaryTargetValues(bool& flightplanActive, bool& aiOutOfSight);
@ -147,6 +156,7 @@ private:
void checkVisibility(); void checkVisibility();
inline bool isStationary() { return ((fabs(speed)<=0.0001)&&(fabs(tgt_speed)<=0.0001));} inline bool isStationary() { return ((fabs(speed)<=0.0001)&&(fabs(tgt_speed)<=0.0001));}
inline bool needGroundElevation() { if (!isStationary()) _needsGroundElevation=true;return _needsGroundElevation;} inline bool needGroundElevation() { if (!isStationary()) _needsGroundElevation=true;return _needsGroundElevation;}
double sign(double x); double sign(double x);
@ -167,6 +177,7 @@ private:
bool reachedWaypoint; bool reachedWaypoint;
bool needsTaxiClearance; bool needsTaxiClearance;
bool _needsGroundElevation; bool _needsGroundElevation;
int takeOffStatus; // 1 = joined departure cue; 2 = Passed DepartureHold waypoint; handover control to tower; 0 = any other state.
time_t timeElapsed; time_t timeElapsed;
PerformanceData* _performance; // the performance data for this aircraft PerformanceData* _performance; // the performance data for this aircraft

View file

@ -46,6 +46,29 @@
using std::cerr; using std::cerr;
FGAIWaypoint::FGAIWaypoint() {
latitude = 0;
longitude = 0;
altitude = 0;
speed = 0;
crossat = 0;
finished = 0;
gear_down = 0;
flaps_down = 0;
on_ground = 0;
routeIndex = 0;
time_sec = 0;
trackLength = 0;
}
bool FGAIWaypoint::contains(string target) {
size_t found = name.find(target);
if (found == string::npos)
return false;
else
return true;
}
FGAIFlightPlan::FGAIFlightPlan() FGAIFlightPlan::FGAIFlightPlan()
{ {
rwy = 0; rwy = 0;
@ -88,22 +111,22 @@ FGAIFlightPlan::FGAIFlightPlan(const string& filename)
SGPropertyNode * node = root.getNode("flightplan"); SGPropertyNode * node = root.getNode("flightplan");
for (i = 0; i < node->nChildren(); i++) { for (i = 0; i < node->nChildren(); i++) {
//cout << "Reading waypoint " << i << endl; //cout << "Reading waypoint " << i << endl;
waypoint* wpt = new waypoint; FGAIWaypoint* wpt = new FGAIWaypoint;
SGPropertyNode * wpt_node = node->getChild(i); SGPropertyNode * wpt_node = node->getChild(i);
wpt->name = wpt_node->getStringValue("name", "END"); wpt->setName (wpt_node->getStringValue("name", "END" ));
wpt->latitude = wpt_node->getDoubleValue("lat", 0); wpt->setLatitude (wpt_node->getDoubleValue("lat", 0 ));
wpt->longitude = wpt_node->getDoubleValue("lon", 0); wpt->setLongitude (wpt_node->getDoubleValue("lon", 0 ));
wpt->altitude = wpt_node->getDoubleValue("alt", 0); wpt->setAltitude (wpt_node->getDoubleValue("alt", 0 ));
wpt->speed = wpt_node->getDoubleValue("ktas", 0); wpt->setSpeed (wpt_node->getDoubleValue("ktas", 0 ));
wpt->crossat = wpt_node->getDoubleValue("crossat", -10000); wpt->setCrossat (wpt_node->getDoubleValue("crossat", -10000 ));
wpt->gear_down = wpt_node->getBoolValue("gear-down", false); wpt->setGear_down (wpt_node->getBoolValue("gear-down", false ));
wpt->flaps_down= wpt_node->getBoolValue("flaps-down", false); wpt->setFlaps_down (wpt_node->getBoolValue("flaps-down", false ));
wpt->on_ground = wpt_node->getBoolValue("on-ground", false); wpt->setOn_ground (wpt_node->getBoolValue("on-ground", false ));
wpt->time_sec = wpt_node->getDoubleValue("time-sec", 0); wpt->setTime_sec (wpt_node->getDoubleValue("time-sec", 0 ));
wpt->time = wpt_node->getStringValue("time", ""); wpt->setTime (wpt_node->getStringValue("time", "" ));
if (wpt->name == "END") wpt->finished = true; if (wpt->getName() == "END") wpt->setFinished(true);
else wpt->finished = false; else wpt->setFinished(false);
waypoints.push_back( wpt ); waypoints.push_back( wpt );
} }
@ -173,20 +196,19 @@ FGAIFlightPlan::FGAIFlightPlan(FGAIAircraft *ac,
//waypoints.push_back( init_waypoint ); //waypoints.push_back( init_waypoint );
for (int i = 0; i < node->nChildren(); i++) { for (int i = 0; i < node->nChildren(); i++) {
//cout << "Reading waypoint " << i << endl; //cout << "Reading waypoint " << i << endl;
waypoint* wpt = new waypoint; FGAIWaypoint* wpt = new FGAIWaypoint;
SGPropertyNode * wpt_node = node->getChild(i); SGPropertyNode * wpt_node = node->getChild(i);
wpt->name = wpt_node->getStringValue("name", "END"); wpt->setName (wpt_node->getStringValue("name", "END" ));
wpt->latitude = wpt_node->getDoubleValue("lat", 0); wpt->setLatitude (wpt_node->getDoubleValue("lat", 0 ));
wpt->longitude = wpt_node->getDoubleValue("lon", 0); wpt->setLongitude (wpt_node->getDoubleValue("lon", 0 ));
wpt->altitude = wpt_node->getDoubleValue("alt", 0); wpt->setAltitude (wpt_node->getDoubleValue("alt", 0 ));
wpt->speed = wpt_node->getDoubleValue("ktas", 0); wpt->setSpeed (wpt_node->getDoubleValue("ktas", 0 ));
//wpt->speed = speed; wpt->setCrossat (wpt_node->getDoubleValue("crossat", -10000 ));
wpt->crossat = wpt_node->getDoubleValue("crossat", -10000); wpt->setGear_down (wpt_node->getBoolValue("gear-down", false ));
wpt->gear_down = wpt_node->getBoolValue("gear-down", false); wpt->setFlaps_down (wpt_node->getBoolValue("flaps-down", false ));
wpt->flaps_down= wpt_node->getBoolValue("flaps-down", false);
if (wpt->name == "END") wpt->finished = true; if (wpt->getName() == "END") wpt->setFinished(true);
else wpt->finished = false; else wpt->setFinished(false);
waypoints.push_back(wpt); waypoints.push_back(wpt);
} // of node loop } // of node loop
wpt_iterator = waypoints.begin(); wpt_iterator = waypoints.begin();
@ -204,8 +226,10 @@ FGAIFlightPlan::FGAIFlightPlan(FGAIAircraft *ac,
if ((timeDiff > 60) && (timeDiff < 1200)) if ((timeDiff > 60) && (timeDiff < 1200))
leg = 2; leg = 2;
else if ((timeDiff >= 1200) && (timeDiff < 1500)) else if ((timeDiff >= 1200) && (timeDiff < 1500)) {
leg = 3; leg = 3;
ac->setTakeOffStatus(2);
}
else if ((timeDiff >= 1500) && (timeDiff < 2000)) else if ((timeDiff >= 1500) && (timeDiff < 2000))
leg = 4; leg = 4;
else if (timeDiff >= 2000) else if (timeDiff >= 2000)
@ -324,8 +348,7 @@ FGAIFlightPlan::~FGAIFlightPlan()
} }
FGAIFlightPlan::waypoint* const FGAIWaypoint* const FGAIFlightPlan::getPreviousWaypoint( void ) const
FGAIFlightPlan::getPreviousWaypoint( void ) const
{ {
if (wpt_iterator == waypoints.begin()) { if (wpt_iterator == waypoints.begin()) {
return 0; return 0;
@ -335,14 +358,12 @@ FGAIFlightPlan::getPreviousWaypoint( void ) const
} }
} }
FGAIFlightPlan::waypoint* const FGAIWaypoint* const FGAIFlightPlan::getCurrentWaypoint( void ) const
FGAIFlightPlan::getCurrentWaypoint( void ) const
{ {
return *wpt_iterator; return *wpt_iterator;
} }
FGAIFlightPlan::waypoint* const FGAIWaypoint* const FGAIFlightPlan::getNextWaypoint( void ) const
FGAIFlightPlan::getNextWaypoint( void ) const
{ {
wpt_vector_iterator i = waypoints.end(); wpt_vector_iterator i = waypoints.end();
i--; // end() points to one element after the last one. i--; // end() points to one element after the last one.
@ -394,14 +415,14 @@ void FGAIFlightPlan::DecrementWaypoint(bool eraseWaypoints )
// gives distance in feet from a position to a waypoint // gives distance in feet from a position to a waypoint
double FGAIFlightPlan::getDistanceToGo(double lat, double lon, waypoint* wp) const{ double FGAIFlightPlan::getDistanceToGo(double lat, double lon, FGAIWaypoint* wp) const{
return SGGeodesy::distanceM(SGGeod::fromDeg(lon, lat), return SGGeodesy::distanceM(SGGeod::fromDeg(lon, lat),
SGGeod::fromDeg(wp->longitude, wp->latitude)); SGGeod::fromDeg(wp->getLongitude(), wp->getLatitude()));
} }
// sets distance in feet from a lead point to the current waypoint // sets distance in feet from a lead point to the current waypoint
void FGAIFlightPlan::setLeadDistance(double speed, double bearing, void FGAIFlightPlan::setLeadDistance(double speed, double bearing,
waypoint* current, waypoint* next){ FGAIWaypoint* current, FGAIWaypoint* next){
double turn_radius; double turn_radius;
// Handle Ground steering // Handle Ground steering
// At a turn rate of 30 degrees per second, it takes 12 seconds to do a full 360 degree turn // At a turn rate of 30 degrees per second, it takes 12 seconds to do a full 360 degree turn
@ -444,14 +465,14 @@ void FGAIFlightPlan::setLeadDistance(double distance_ft){
} }
double FGAIFlightPlan::getBearing(waypoint* first, waypoint* second) const{ double FGAIFlightPlan::getBearing(FGAIWaypoint* first, FGAIWaypoint* second) const{
return getBearing(first->latitude, first->longitude, second); return getBearing(first->getLatitude(), first->getLongitude(), second);
} }
double FGAIFlightPlan::getBearing(double lat, double lon, waypoint* wp) const{ double FGAIFlightPlan::getBearing(double lat, double lon, FGAIWaypoint* wp) const{
return SGGeodesy::courseDeg(SGGeod::fromDeg(lon, lat), return SGGeodesy::courseDeg(SGGeod::fromDeg(lon, lat),
SGGeod::fromDeg(wp->longitude, wp->latitude)); SGGeod::fromDeg(wp->getLongitude(), wp->getLatitude()));
} }
void FGAIFlightPlan::deleteWaypoints() void FGAIFlightPlan::deleteWaypoints()
@ -469,19 +490,19 @@ void FGAIFlightPlan::resetWaypoints()
return; return;
else else
{ {
waypoint *wpt = new waypoint; FGAIWaypoint *wpt = new FGAIWaypoint;
wpt_vector_iterator i = waypoints.end(); wpt_vector_iterator i = waypoints.end();
i--; i--;
wpt->name = (*i)->name; wpt->setName ( (*i)->getName() );
wpt->latitude = (*i)->latitude; wpt->setLatitude ( (*i)->getLatitude() );
wpt->longitude = (*i)->longitude; wpt->setLongitude ( (*i)->getLongitude() );
wpt->altitude = (*i)->altitude; wpt->setAltitude ( (*i)->getAltitude() );
wpt->speed = (*i)->speed; wpt->setSpeed ( (*i)->getSpeed() );
wpt->crossat = (*i)->crossat; wpt->setCrossat ( (*i)->getCrossat() );
wpt->gear_down = (*i)->gear_down; wpt->setGear_down ( (*i)->getGear_down() );
wpt->flaps_down= (*i)->flaps_down; wpt->setFlaps_down ( (*i)->getFlaps_down() );
wpt->finished = false; wpt->setFinished ( false );
wpt->on_ground = (*i)->on_ground; wpt->setOn_ground ( (*i)->getOn_ground() );
//cerr << "Recycling waypoint " << wpt->name << endl; //cerr << "Recycling waypoint " << wpt->name << endl;
deleteWaypoints(); deleteWaypoints();
waypoints.push_back(wpt); waypoints.push_back(wpt);
@ -504,7 +525,7 @@ void FGAIFlightPlan::deleteTaxiRoute()
int FGAIFlightPlan::getRouteIndex(int i) { int FGAIFlightPlan::getRouteIndex(int i) {
if ((i > 0) && (i < (int)waypoints.size())) { if ((i > 0) && (i < (int)waypoints.size())) {
return waypoints[i]->routeIndex; return waypoints[i]->getRouteIndex();
} }
else else
return 0; return 0;
@ -517,8 +538,8 @@ double FGAIFlightPlan::checkTrackLength(string wptName) {
wpt_vector_iterator wptvec = waypoints.begin(); wpt_vector_iterator wptvec = waypoints.begin();
wptvec++; wptvec++;
wptvec++; wptvec++;
while ((wptvec != waypoints.end()) && ((*wptvec)->name != wptName)) { while ((wptvec != waypoints.end()) && (!((*wptvec)->contains(wptName)))) {
trackDistance += (*wptvec)->trackLength; trackDistance += (*wptvec)->getTrackLength();
wptvec++; wptvec++;
} }
if (wptvec == waypoints.end()) { if (wptvec == waypoints.end()) {

View file

@ -1,4 +1,4 @@
// // FGAIFlightPlan - class for loading and storing AI flight plans // FGAIFlightPlan - class for loading and storing AI flight plans
// Written by David Culp, started May 2004 // Written by David Culp, started May 2004
// - davidculp2@comcast.net // - davidculp2@comcast.net
// //
@ -30,11 +30,8 @@ class FGAIAircraft;
class FGAirport; class FGAirport;
class SGGeod; class SGGeod;
class FGAIFlightPlan { class FGAIWaypoint {
private:
public:
typedef struct {
std::string name; std::string name;
double latitude; double latitude;
double longitude; double longitude;
@ -47,10 +44,52 @@ public:
bool on_ground; bool on_ground;
int routeIndex; // For AI/ATC purposes; int routeIndex; // For AI/ATC purposes;
double time_sec; double time_sec;
double trackLength; // distance from previous waypoint (for AI purposes); double trackLength; // distance from previous FGAIWaypoint (for AI purposes);
std::string time; std::string time;
} waypoint; public:
FGAIWaypoint();
~FGAIWaypoint() {};
void setName (std::string nam) { name = nam; };
void setLatitude (double lat) { latitude = lat; };
void setLongitude (double lon) { longitude = lon; };
void setAltitude (double alt) { altitude = alt; };
void setSpeed (double spd) { speed = spd; };
void setCrossat (double val) { crossat = val; };
void setFinished (bool fin) { finished = fin; };
void setGear_down (bool grd) { gear_down = grd; };
void setFlaps_down (bool fld) { flaps_down = fld; };
void setOn_ground (bool grn) { on_ground = grn; };
void setRouteIndex (int rte) { routeIndex = rte; };
void setTime_sec (double ts ) { time_sec = ts; };
void setTrackLength (double tl ) { trackLength = tl; };
void setTime (std::string tme) { time = tme; };
bool contains(std::string name);
std::string getName () { return name; };
double getLatitude () { return latitude; };
double getLongitude () { return longitude; };
double getAltitude () { return altitude; };
double getSpeed () { return speed; };
double getCrossat () { return crossat; };
bool getGear_down () { return gear_down; };
bool getFlaps_down () { return flaps_down; };
bool getOn_ground () { return on_ground; };
int getRouteIndex () { return routeIndex; };
bool isFinished () { return finished; };
double getTime_sec () { return time_sec; };
double getTrackLength() { return trackLength; };
std::string getTime () { return time; };
};
class FGAIFlightPlan {
public:
FGAIFlightPlan(); FGAIFlightPlan();
FGAIFlightPlan(const std::string& filename); FGAIFlightPlan(const std::string& filename);
FGAIFlightPlan(FGAIAircraft *, FGAIFlightPlan(FGAIAircraft *,
@ -70,19 +109,20 @@ public:
const std::string& airline); const std::string& airline);
~FGAIFlightPlan(); ~FGAIFlightPlan();
waypoint* const getPreviousWaypoint( void ) const; FGAIWaypoint* const getPreviousWaypoint( void ) const;
waypoint* const getCurrentWaypoint( void ) const; FGAIWaypoint* const getCurrentWaypoint( void ) const;
waypoint* const getNextWaypoint( void ) const; FGAIWaypoint* const getNextWaypoint( void ) const;
void IncrementWaypoint( bool erase ); void IncrementWaypoint( bool erase );
void DecrementWaypoint( bool erase ); void DecrementWaypoint( bool erase );
double getDistanceToGo(double lat, double lon, waypoint* wp) const; double getDistanceToGo(double lat, double lon, FGAIWaypoint* wp) const;
int getLeg () const { return leg;}; int getLeg () const { return leg;};
void setLeadDistance(double speed, double bearing, waypoint* current, waypoint* next);
void setLeadDistance(double speed, double bearing, FGAIWaypoint* current, FGAIWaypoint* next);
void setLeadDistance(double distance_ft); void setLeadDistance(double distance_ft);
double getLeadDistance( void ) const {return lead_distance;} double getLeadDistance( void ) const {return lead_distance;}
double getBearing(waypoint* previous, waypoint* next) const; double getBearing(FGAIWaypoint* previous, FGAIWaypoint* next) const;
double getBearing(double lat, double lon, waypoint* next) const; double getBearing(double lat, double lon, FGAIWaypoint* next) const;
double checkTrackLength(std::string wptName); double checkTrackLength(std::string wptName);
time_t getStartTime() const { return start_time; } time_t getStartTime() const { return start_time; }
time_t getArrivalTime() const { return arrivalTime; } time_t getArrivalTime() const { return arrivalTime; }
@ -110,21 +150,25 @@ public:
std::string getRunway() { return activeRunway; } std::string getRunway() { return activeRunway; }
bool isActive(time_t time) {return time >= this->getStartTime();} bool isActive(time_t time) {return time >= this->getStartTime();}
void incrementLeg() { leg++;};
void setRunway(std::string rwy) { activeRunway = rwy; }; void setRunway(std::string rwy) { activeRunway = rwy; };
std::string getRunwayClassFromTrafficType(std::string fltType); std::string getRunwayClassFromTrafficType(std::string fltType);
void addWaypoint(waypoint* wpt) { waypoints.push_back(wpt); }; void addWaypoint(FGAIWaypoint* wpt) { waypoints.push_back(wpt); };
void setName(std::string n) { name = n; }; void setName(std::string n) { name = n; };
std::string getName() { return name; }; std::string getName() { return name; };
void setSID(FGAIFlightPlan* fp) { sid = fp;}; void setSID(FGAIFlightPlan* fp) { sid = fp;};
FGAIFlightPlan* getSID() { return sid; }; FGAIFlightPlan* getSID() { return sid; };
FGAIWaypoint *getWayPoint(int i) { return waypoints[i]; };
FGAIWaypoint *getLastWaypoint() { return waypoints.back(); };
private: private:
FGRunway* rwy; FGRunway* rwy;
FGAIFlightPlan *sid; FGAIFlightPlan *sid;
typedef std::vector <waypoint*> wpt_vector_type; typedef std::vector <FGAIWaypoint*> wpt_vector_type;
typedef wpt_vector_type::const_iterator wpt_vector_iterator; typedef wpt_vector_type::const_iterator wpt_vector_iterator;
@ -160,10 +204,10 @@ private:
double getTurnRadius(double, bool); double getTurnRadius(double, bool);
waypoint* createOnGround(FGAIAircraft *, const std::string& aName, const SGGeod& aPos, double aElev, double aSpeed); FGAIWaypoint* 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); FGAIWaypoint* 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); FGAIWaypoint* cloneWithPos(FGAIAircraft *, FGAIWaypoint* aWpt, const std::string& aName, const SGGeod& aPos);
waypoint* clone(waypoint* aWpt); FGAIWaypoint* clone(FGAIWaypoint* aWpt);
//void createCruiseFallback(bool, FGAirport*, FGAirport*, double, double, double, double); //void createCruiseFallback(bool, FGAirport*, FGAirport*, double, double, double, double);
@ -172,6 +216,6 @@ private:
wpt_vector_iterator getFirstWayPoint() { return waypoints.begin(); }; wpt_vector_iterator getFirstWayPoint() { return waypoints.begin(); };
wpt_vector_iterator getLastWayPoint() { return waypoints.end(); }; wpt_vector_iterator getLastWayPoint() { return waypoints.end(); };
bool isValidPlan() { return isValid; }; bool isValidPlan() { return isValid; };
}; };
#endif // _FG_AIFLIGHTPLAN_HXX #endif // _FG_AIFLIGHTPLAN_HXX

View file

@ -22,6 +22,7 @@
# include <config.h> # include <config.h>
#endif #endif
#include "AIFlightPlan.hxx" #include "AIFlightPlan.hxx"
#include <simgear/math/sg_geodesy.hxx> #include <simgear/math/sg_geodesy.hxx>
#include <simgear/props/props.hxx> #include <simgear/props/props.hxx>
@ -96,92 +97,81 @@ bool FGAIFlightPlan::create(FGAIAircraft * ac, FGAirport * dep,
" this is probably an internal program error"); " this is probably an internal program error");
} }
wpt_iterator = waypoints.begin() + currWpt; wpt_iterator = waypoints.begin() + currWpt;
leg++; //don't increment leg right away, but only once we pass the actual last waypoint that was created.
// to do so, mark the last waypoint with a special status flag
if (retVal) {
waypoints.back()->setName( waypoints.back()->getName() + string("legend"));
// "It's pronounced Leg-end" (Roger Glover (Deep Purple): come Hell or High Water DvD, 1993)
}
//leg++;
return retVal; return retVal;
} }
FGAIFlightPlan::waypoint * FGAIWaypoint * FGAIFlightPlan::createOnGround(FGAIAircraft * ac,
FGAIFlightPlan::createOnGround(FGAIAircraft * ac,
const std::string & aName, const std::string & aName,
const SGGeod & aPos, double aElev, const SGGeod & aPos, double aElev,
double aSpeed) double aSpeed)
{ {
waypoint *wpt = new waypoint; FGAIWaypoint *wpt = new FGAIWaypoint;
wpt->name = aName; wpt->setName (aName );
wpt->longitude = aPos.getLongitudeDeg(); wpt->setLongitude (aPos.getLongitudeDeg() );
wpt->latitude = aPos.getLatitudeDeg(); wpt->setLatitude (aPos.getLatitudeDeg() );
wpt->altitude = aElev; wpt->setAltitude (aElev );
wpt->speed = aSpeed; wpt->setSpeed (aSpeed );
wpt->crossat = -10000.1; wpt->setCrossat (-10000.1 );
wpt->gear_down = true; wpt->setGear_down (true );
wpt->flaps_down = true; wpt->setFlaps_down (true );
wpt->finished = false; wpt->setFinished (false );
wpt->on_ground = true; wpt->setOn_ground (true );
wpt->routeIndex = 0; wpt->setRouteIndex (0 );
return wpt; return wpt;
} }
FGAIFlightPlan::waypoint * FGAIWaypoint * FGAIFlightPlan::createInAir(FGAIAircraft * ac,
FGAIFlightPlan::createInAir(FGAIAircraft * ac,
const std::string & aName, const std::string & aName,
const SGGeod & aPos, double aElev, const SGGeod & aPos, double aElev,
double aSpeed) double aSpeed)
{ {
waypoint *wpt = new waypoint; FGAIWaypoint * wpt = createOnGround(ac, aName, aPos, aElev, aSpeed);
wpt->name = aName; wpt->setGear_down (false );
wpt->longitude = aPos.getLongitudeDeg(); wpt->setFlaps_down (false );
wpt->latitude = aPos.getLatitudeDeg(); wpt->setOn_ground (false );
wpt->altitude = aElev;
wpt->speed = aSpeed;
wpt->crossat = -10000.1;
wpt->gear_down = false;
wpt->flaps_down = false;
wpt->finished = false;
wpt->on_ground = false;
wpt->routeIndex = 0;
return wpt; return wpt;
} }
FGAIFlightPlan::waypoint * FGAIWaypoint * FGAIFlightPlan::clone(FGAIWaypoint * aWpt)
FGAIFlightPlan::cloneWithPos(FGAIAircraft * ac, waypoint * aWpt, {
FGAIWaypoint *wpt = new FGAIWaypoint;
wpt->setName ( aWpt->getName () );
wpt->setLongitude ( aWpt->getLongitude() );
wpt->setLatitude ( aWpt->getLatitude() );
wpt->setAltitude ( aWpt->getAltitude() );
wpt->setSpeed ( aWpt->getSpeed() );
wpt->setCrossat ( aWpt->getCrossat() );
wpt->setGear_down ( aWpt->getGear_down() );
wpt->setFlaps_down ( aWpt->getFlaps_down() );
wpt->setFinished ( aWpt->isFinished() );
wpt->setOn_ground ( aWpt->getOn_ground() );
wpt->setRouteIndex ( 0 );
return wpt;
}
FGAIWaypoint * FGAIFlightPlan::cloneWithPos(FGAIAircraft * ac, FGAIWaypoint * aWpt,
const std::string & aName, const std::string & aName,
const SGGeod & aPos) const SGGeod & aPos)
{ {
waypoint *wpt = new waypoint; FGAIWaypoint *wpt = clone(aWpt);
wpt->name = aName; wpt->setName ( aName );
wpt->longitude = aPos.getLongitudeDeg(); wpt->setLongitude ( aPos.getLongitudeDeg () );
wpt->latitude = aPos.getLatitudeDeg(); wpt->setLatitude ( aPos.getLatitudeDeg () );
wpt->altitude = aWpt->altitude;
wpt->speed = aWpt->speed;
wpt->crossat = aWpt->crossat;
wpt->gear_down = aWpt->gear_down;
wpt->flaps_down = aWpt->flaps_down;
wpt->finished = aWpt->finished;
wpt->on_ground = aWpt->on_ground;
wpt->routeIndex = 0;
return wpt; return wpt;
} }
FGAIFlightPlan::waypoint * FGAIFlightPlan::clone(waypoint * aWpt)
{
waypoint *wpt = new waypoint;
wpt->name = aWpt->name;
wpt->longitude = aWpt->longitude;
wpt->latitude = aWpt->latitude;
wpt->altitude = aWpt->altitude;
wpt->speed = aWpt->speed;
wpt->crossat = aWpt->crossat;
wpt->gear_down = aWpt->gear_down;
wpt->flaps_down = aWpt->flaps_down;
wpt->finished = aWpt->finished;
wpt->on_ground = aWpt->on_ground;
wpt->routeIndex = 0;
return wpt;
}
void FGAIFlightPlan::createDefaultTakeoffTaxi(FGAIAircraft * ac, void FGAIFlightPlan::createDefaultTakeoffTaxi(FGAIAircraft * ac,
@ -191,7 +181,7 @@ void FGAIFlightPlan::createDefaultTakeoffTaxi(FGAIAircraft * ac,
SGGeod runwayTakeoff = aRunway->pointOnCenterline(5.0); SGGeod runwayTakeoff = aRunway->pointOnCenterline(5.0);
double airportElev = aAirport->getElevation(); double airportElev = aAirport->getElevation();
waypoint *wpt; FGAIWaypoint *wpt;
wpt = wpt =
createOnGround(ac, "Airport Center", aAirport->geod(), airportElev, createOnGround(ac, "Airport Center", aAirport->geod(), airportElev,
ac->getPerformance()->vTaxi()); ac->getPerformance()->vTaxi());
@ -304,17 +294,30 @@ bool FGAIFlightPlan::createTakeoffTaxi(FGAIAircraft * ac, bool firstFlight,
// push each node on the taxi route as a waypoint // push each node on the taxi route as a waypoint
int route; int route;
//cerr << "Building taxi route" << endl;
while (taxiRoute->next(&node, &route)) { while (taxiRoute->next(&node, &route)) {
char buffer[10]; char buffer[10];
snprintf(buffer, 10, "%d", node); snprintf(buffer, 10, "%d", node);
FGTaxiNode *tn = FGTaxiNode *tn =
apt->getDynamics()->getGroundNetwork()->findNode(node); apt->getDynamics()->getGroundNetwork()->findNode(node);
waypoint *wpt = FGAIWaypoint *wpt =
createOnGround(ac, buffer, tn->getGeod(), apt->getElevation(), createOnGround(ac, buffer, tn->getGeod(), apt->getElevation(),
ac->getPerformance()->vTaxi()); ac->getPerformance()->vTaxi());
wpt->routeIndex = route; wpt->setRouteIndex(route);
//cerr << "Nodes left " << taxiRoute->nodesLeft() << " ";
if (taxiRoute->nodesLeft() == 1) {
// Note that we actually have hold points in the ground network, but this is just an initial test.
//cerr << "Setting departurehold point: " << endl;
wpt->setName( wpt->getName() + string("DepartureHold"));
}
waypoints.push_back(wpt); waypoints.push_back(wpt);
} }
// Acceleration point, 105 meters into the runway,
SGGeod accelPoint = rwy->pointOnCenterline(105.0);
FGAIWaypoint *wpt = createOnGround(ac, "accel", accelPoint, apt->getElevation(), ac->getPerformance()->vRotate());
waypoints.push_back(wpt);
//cerr << "[done]" << endl;
return true; return true;
} }
@ -322,11 +325,11 @@ void FGAIFlightPlan::createDefaultLandingTaxi(FGAIAircraft * ac,
FGAirport * aAirport) FGAirport * aAirport)
{ {
SGGeod lastWptPos = SGGeod lastWptPos =
SGGeod::fromDeg(waypoints.back()->longitude, SGGeod::fromDeg(waypoints.back()->getLongitude(),
waypoints.back()->latitude); waypoints.back()->getLatitude());
double airportElev = aAirport->getElevation(); double airportElev = aAirport->getElevation();
waypoint *wpt; FGAIWaypoint *wpt;
wpt = wpt =
createOnGround(ac, "Runway Exit", lastWptPos, airportElev, createOnGround(ac, "Runway Exit", lastWptPos, airportElev,
ac->getPerformance()->vTaxi()); ac->getPerformance()->vTaxi());
@ -356,8 +359,8 @@ bool FGAIFlightPlan::createLandingTaxi(FGAIAircraft * ac, FGAirport * apt,
acType, airline); acType, airline);
SGGeod lastWptPos = SGGeod lastWptPos =
SGGeod::fromDeg(waypoints.back()->longitude, SGGeod::fromDeg(waypoints.back()->getLongitude(),
waypoints.back()->latitude); waypoints.back()->getLatitude());
FGGroundNetwork *gn = apt->getDynamics()->getGroundNetwork(); FGGroundNetwork *gn = apt->getDynamics()->getGroundNetwork();
// Find a route from runway end to parking/gate. // Find a route from runway end to parking/gate.
@ -396,10 +399,10 @@ bool FGAIFlightPlan::createLandingTaxi(FGAIAircraft * ac, FGAirport * apt,
char buffer[10]; char buffer[10];
snprintf(buffer, 10, "%d", node); snprintf(buffer, 10, "%d", node);
FGTaxiNode *tn = gn->findNode(node); FGTaxiNode *tn = gn->findNode(node);
waypoint *wpt = FGAIWaypoint *wpt =
createOnGround(ac, buffer, tn->getGeod(), apt->getElevation(), createOnGround(ac, buffer, tn->getGeod(), apt->getElevation(),
ac->getPerformance()->vTaxi()); ac->getPerformance()->vTaxi());
wpt->routeIndex = route; wpt->setRouteIndex(route);
waypoints.push_back(wpt); waypoints.push_back(wpt);
} }
return true; return true;
@ -441,7 +444,7 @@ bool FGAIFlightPlan::createTakeOff(FGAIAircraft * ac, bool firstFlight,
(vRotateMetric * vRotateMetric - (vRotateMetric * vRotateMetric -
vTaxiMetric * vTaxiMetric) / (2 * accelMetric); vTaxiMetric * vTaxiMetric) / (2 * accelMetric);
//cerr << "Using " << accelDistance << " " << accelMetric << " " << vRotateMetric << endl; //cerr << "Using " << accelDistance << " " << accelMetric << " " << vRotateMetric << endl;
waypoint *wpt; FGAIWaypoint *wpt;
// Get the current active runway, based on code from David Luff // Get the current active runway, based on code from David Luff
// This should actually be unified and extended to include // This should actually be unified and extended to include
// Preferential runway use schema's // Preferential runway use schema's
@ -458,17 +461,13 @@ bool FGAIFlightPlan::createTakeOff(FGAIAircraft * ac, bool firstFlight,
double airportElev = apt->getElevation(); double airportElev = apt->getElevation();
// Acceleration point, 105 meters into the runway,
SGGeod accelPoint = rwy->pointOnCenterline(105.0);
wpt = createOnGround(ac, "accel", accelPoint, airportElev, vRotate);
waypoints.push_back(wpt);
accelDistance = accelDistance =
(vTakeoffMetric * vTakeoffMetric - (vTakeoffMetric * vTakeoffMetric -
vTaxiMetric * vTaxiMetric) / (2 * accelMetric); vTaxiMetric * vTaxiMetric) / (2 * accelMetric);
//cerr << "Using " << accelDistance << " " << accelMetric << " " << vTakeoffMetric << endl; //cerr << "Using " << accelDistance << " " << accelMetric << " " << vTakeoffMetric << endl;
accelPoint = rwy->pointOnCenterline(105.0 + accelDistance); SGGeod accelPoint = rwy->pointOnCenterline(105.0 + accelDistance);
wpt = createOnGround(ac, "rotate", accelPoint, airportElev, vTakeoff); wpt = createOnGround(ac, "rotate", accelPoint, airportElev, vTakeoff);
waypoints.push_back(wpt); waypoints.push_back(wpt);
@ -480,18 +479,18 @@ bool FGAIFlightPlan::createTakeOff(FGAIAircraft * ac, bool firstFlight,
wpt = wpt =
createOnGround(ac, "rotate", accelPoint, airportElev + 1000, createOnGround(ac, "rotate", accelPoint, airportElev + 1000,
vTakeoff * 1.1); vTakeoff * 1.1);
wpt->on_ground = false; wpt->setOn_ground(false);
waypoints.push_back(wpt); waypoints.push_back(wpt);
wpt = cloneWithPos(ac, wpt, "3000 ft", rwy->end()); wpt = cloneWithPos(ac, wpt, "3000 ft", rwy->end());
wpt->altitude = airportElev + 3000; wpt->setAltitude(airportElev + 3000);
waypoints.push_back(wpt); waypoints.push_back(wpt);
// Finally, add two more waypoints, so that aircraft will remain under // Finally, add two more waypoints, so that aircraft will remain under
// Tower control until they have reached the 3000 ft climb point // Tower control until they have reached the 3000 ft climb point
SGGeod pt = rwy->pointOnCenterline(5000 + rwy->lengthM() * 0.5); SGGeod pt = rwy->pointOnCenterline(5000 + rwy->lengthM() * 0.5);
wpt = cloneWithPos(ac, wpt, "5000 ft", pt); wpt = cloneWithPos(ac, wpt, "5000 ft", pt);
wpt->altitude = airportElev + 5000; wpt->setAltitude(airportElev + 5000);
waypoints.push_back(wpt); waypoints.push_back(wpt);
return true; return true;
} }
@ -504,7 +503,7 @@ bool FGAIFlightPlan::createClimb(FGAIAircraft * ac, bool firstFlight,
FGAirport * apt, double speed, double alt, FGAirport * apt, double speed, double alt,
const string & fltType) const string & fltType)
{ {
waypoint *wpt; FGAIWaypoint *wpt;
// bool planLoaded = false; // bool planLoaded = false;
string fPLName; string fPLName;
double vClimb = ac->getPerformance()->vClimb(); double vClimb = ac->getPerformance()->vClimb();
@ -525,13 +524,13 @@ bool FGAIFlightPlan::createClimb(FGAIAircraft * ac, bool firstFlight,
} else { } else {
SGGeod climb1 = rwy->pointOnCenterline(10 * SG_NM_TO_METER); SGGeod climb1 = rwy->pointOnCenterline(10 * SG_NM_TO_METER);
wpt = createInAir(ac, "10000ft climb", climb1, vClimb, 10000); wpt = createInAir(ac, "10000ft climb", climb1, vClimb, 10000);
wpt->gear_down = true; wpt->setGear_down(true);
wpt->flaps_down = true; wpt->setFlaps_down(true);
waypoints.push_back(wpt); waypoints.push_back(wpt);
SGGeod climb2 = rwy->pointOnCenterline(20 * SG_NM_TO_METER); SGGeod climb2 = rwy->pointOnCenterline(20 * SG_NM_TO_METER);
wpt = cloneWithPos(ac, wpt, "18000ft climb", climb2); wpt = cloneWithPos(ac, wpt, "18000ft climb", climb2);
wpt->altitude = 18000; wpt->setAltitude(18000);
waypoints.push_back(wpt); waypoints.push_back(wpt);
} }
return true; return true;
@ -551,7 +550,7 @@ bool FGAIFlightPlan::createDescent(FGAIAircraft * ac, FGAirport * apt,
double requiredDistance) double requiredDistance)
{ {
bool reposition = false; bool reposition = false;
waypoint *wpt; FGAIWaypoint *wpt;
double vDescent = ac->getPerformance()->vDescent(); double vDescent = ac->getPerformance()->vDescent();
double vApproach = ac->getPerformance()->vApproach(); double vApproach = ac->getPerformance()->vApproach();
@ -729,8 +728,8 @@ bool FGAIFlightPlan::createDescent(FGAIAircraft * ac, FGAirport * apt,
SGGeodesy::direct(origin, azimuth, currentDist, result, dummyAz2); SGGeodesy::direct(origin, azimuth, currentDist, result, dummyAz2);
snprintf(buffer, 16, "descent%03d", i); snprintf(buffer, 16, "descent%03d", i);
wpt = createInAir(ac, buffer, result, currentAltitude, vDescent); wpt = createInAir(ac, buffer, result, currentAltitude, vDescent);
wpt->crossat = currentAltitude; wpt->setCrossat(currentAltitude);
wpt->trackLength = (newDistance / nPoints); wpt->setTrackLength((newDistance / nPoints));
waypoints.push_back(wpt); waypoints.push_back(wpt);
//cerr << "Track Length : " << wpt->trackLength; //cerr << "Track Length : " << wpt->trackLength;
//cerr << " Position : " << result.getLatitudeDeg() << " " << result.getLongitudeDeg() << " " << currentAltitude << endl; //cerr << " Position : " << result.getLatitudeDeg() << " " << result.getLongitudeDeg() << " " << currentAltitude << endl;
@ -772,8 +771,8 @@ bool FGAIFlightPlan::createDescent(FGAIAircraft * ac, FGAirport * apt,
initialTurnRadius, result, dummyAz2); initialTurnRadius, result, dummyAz2);
snprintf(buffer, 16, "turn%03d", i); snprintf(buffer, 16, "turn%03d", i);
wpt = createInAir(ac, buffer, result, currentAltitude, vDescent); wpt = createInAir(ac, buffer, result, currentAltitude, vDescent);
wpt->crossat = currentAltitude; wpt->setCrossat(currentAltitude);
wpt->trackLength = trackLength; wpt->setTrackLength(trackLength);
//cerr << "Track Length : " << wpt->trackLength; //cerr << "Track Length : " << wpt->trackLength;
waypoints.push_back(wpt); waypoints.push_back(wpt);
//cerr << " Position : " << result.getLatitudeDeg() << " " << result.getLongitudeDeg() << " " << currentAltitude << endl; //cerr << " Position : " << result.getLatitudeDeg() << " " << result.getLongitudeDeg() << " " << currentAltitude << endl;
@ -791,11 +790,11 @@ bool FGAIFlightPlan::createDescent(FGAIAircraft * ac, FGAirport * apt,
snprintf(buffer, 16, "final%03d", i); snprintf(buffer, 16, "final%03d", i);
result = rwy->pointOnCenterline((-distanceOut) + currentDist); result = rwy->pointOnCenterline((-distanceOut) + currentDist);
wpt = createInAir(ac, buffer, result, currentAltitude, vApproach); wpt = createInAir(ac, buffer, result, currentAltitude, vApproach);
wpt->crossat = currentAltitude; wpt->setCrossat(currentAltitude);
wpt->trackLength = (distanceOut / nPoints); wpt->setTrackLength((distanceOut / nPoints));
// account for the extra distance due to an extended downwind leg // account for the extra distance due to an extended downwind leg
if (i == 1) { if (i == 1) {
wpt->trackLength += distanceCovered; wpt->setTrackLength(wpt->getTrackLength() + distanceCovered);
} }
//cerr << "Track Length : " << wpt->trackLength; //cerr << "Track Length : " << wpt->trackLength;
waypoints.push_back(wpt); waypoints.push_back(wpt);
@ -831,6 +830,7 @@ bool FGAIFlightPlan::createDescent(FGAIAircraft * ac, FGAirport * apt,
//cerr << "Repositioning to waypoint " << (*waypoints.begin())->name << endl; //cerr << "Repositioning to waypoint " << (*waypoints.begin())->name << endl;
ac->resetPositionFromFlightPlan(); ac->resetPositionFromFlightPlan();
} }
waypoints[1]->setName( (waypoints[1]->getName() + string("legend")));
return true; return true;
} }
@ -852,7 +852,7 @@ bool FGAIFlightPlan::createLanding(FGAIAircraft * ac, FGAirport * apt,
//rwy = apt->getRunwayByIdent(activeRunway); //rwy = apt->getRunwayByIdent(activeRunway);
waypoint *wpt; FGAIWaypoint *wpt;
double aptElev = apt->getElevation(); double aptElev = apt->getElevation();
SGGeod coord; SGGeod coord;
@ -861,7 +861,7 @@ bool FGAIFlightPlan::createLanding(FGAIAircraft * ac, FGAirport * apt,
snprintf(buffer, 12, "wpt%d", i); snprintf(buffer, 12, "wpt%d", i);
coord = rwy->pointOnCenterline(rwy->lengthM() * (i / 10.0)); coord = rwy->pointOnCenterline(rwy->lengthM() * (i / 10.0));
wpt = createOnGround(ac, buffer, coord, aptElev, (vTouchdown / i)); wpt = createOnGround(ac, buffer, coord, aptElev, (vTouchdown / i));
wpt->crossat = apt->getElevation(); wpt->setCrossat(apt->getElevation());
waypoints.push_back(wpt); waypoints.push_back(wpt);
} }
@ -890,7 +890,7 @@ bool FGAIFlightPlan::createLanding(FGAIAircraft * ac, FGAirport * apt,
bool FGAIFlightPlan::createParking(FGAIAircraft * ac, FGAirport * apt, bool FGAIFlightPlan::createParking(FGAIAircraft * ac, FGAirport * apt,
double radius) double radius)
{ {
waypoint *wpt; FGAIWaypoint *wpt;
double aptElev = apt->getElevation(); double aptElev = apt->getElevation();
double lat = 0.0, lat2 = 0.0; double lat = 0.0, lat2 = 0.0;
double lon = 0.0, lon2 = 0.0; double lon = 0.0, lon2 = 0.0;

View file

@ -292,7 +292,7 @@ bool FGAIFlightPlan::createCruise(FGAIAircraft *ac, bool firstFlight, FGAirport
double alt, const string& fltType) double alt, const string& fltType)
{ {
double vCruise = ac->getPerformance()->vCruise(); double vCruise = ac->getPerformance()->vCruise();
waypoint *wpt; FGAIWaypoint *wpt;
wpt = createInAir(ac, "Cruise", SGGeod::fromDeg(longitude, latitude), alt, vCruise); wpt = createInAir(ac, "Cruise", SGGeod::fromDeg(longitude, latitude), alt, vCruise);
waypoints.push_back(wpt); waypoints.push_back(wpt);

View file

@ -1,4 +1,4 @@
/****************************************************************************** /****************************************************************************
* AIFlightPlanCreatePushBack.cxx * AIFlightPlanCreatePushBack.cxx
* Written by Durk Talsma, started August 1, 2007. * Written by Durk Talsma, started August 1, 2007.
* *
@ -74,22 +74,10 @@ bool FGAIFlightPlan::createPushBack(FGAIAircraft *ac,
return false; return false;
char buffer[10]; char buffer[10];
snprintf (buffer, 10, "%d", gateId); snprintf (buffer, 10, "%d", gateId);
SGGeod coord = coord.fromDeg(lon, lat);
//FGTaxiNode *tn = dep->getDynamics()->getGroundNetwork()->findNode(node); //FGTaxiNode *tn = dep->getDynamics()->getGroundNetwork()->findNode(node);
waypoint *wpt; FGAIWaypoint *wpt = createOnGround(ac, string(buffer), coord, dep->getElevation(), vTaxiBackward);
wpt = new waypoint; wpt->setRouteIndex(-1);
wpt->name = string(buffer); // fixme: should be the name of the taxiway
wpt->latitude = lat;
wpt->longitude = lon;
// Elevation is currently disregarded when on_ground is true
// because the AIModel obtains a periodic ground elevation estimate.
wpt->altitude = dep->getElevation();
wpt->speed = vTaxiBackward;
wpt->crossat = -10000;
wpt->gear_down = true;
wpt->flaps_down= true;
wpt->finished = false;
wpt->on_ground = true;
wpt->routeIndex = -1;
waypoints.push_back(wpt); waypoints.push_back(wpt);
} }
//cerr << "Success : GateId = " << gateId << endl; //cerr << "Success : GateId = " << gateId << endl;
@ -119,7 +107,7 @@ bool FGAIFlightPlan::createPushBack(FGAIAircraft *ac,
pushBackRoute = parking->getPushBackRoute(); pushBackRoute = parking->getPushBackRoute();
if ((pushBackNode > 0) && (pushBackRoute == 0)) { if ((pushBackNode > 0) && (pushBackRoute == 0)) { // Load the already established route for this gate
int node, rte; int node, rte;
FGTaxiRoute route; FGTaxiRoute route;
//cerr << "Creating push-back for " << gateId << " (" << parking->getName() << ") using push-back point " << pushBackNode << endl; //cerr << "Creating push-back for " << gateId << " (" << parking->getName() << ") using push-back point " << pushBackNode << endl;
@ -134,7 +122,6 @@ bool FGAIFlightPlan::createPushBack(FGAIAircraft *ac,
SG_LOG(SG_GENERAL, SG_WARN, "Using " << pushBackNode); SG_LOG(SG_GENERAL, SG_WARN, "Using " << pushBackNode);
} }
pushBackRoute->first(); pushBackRoute->first();
waypoint *wpt;
while(pushBackRoute->next(&node, &rte)) while(pushBackRoute->next(&node, &rte))
{ {
//FGTaxiNode *tn = apt->getDynamics()->getGroundNetwork()->findSegment(node)->getEnd(); //FGTaxiNode *tn = apt->getDynamics()->getGroundNetwork()->findSegment(node)->getEnd();
@ -142,122 +129,20 @@ bool FGAIFlightPlan::createPushBack(FGAIAircraft *ac,
snprintf (buffer, 10, "%d", node); snprintf (buffer, 10, "%d", node);
FGTaxiNode *tn = dep->getDynamics()->getGroundNetwork()->findNode(node); FGTaxiNode *tn = dep->getDynamics()->getGroundNetwork()->findNode(node);
//ids.pop_back(); //ids.pop_back();
wpt = new waypoint; //wpt = new waypoint;
wpt->name = string(buffer); // fixme: should be the name of the taxiway SGGeod coord = coord.fromDeg(tn->getLongitude(), tn->getLatitude());
wpt->latitude = tn->getLatitude(); FGAIWaypoint *wpt = createOnGround(ac, string(buffer), coord, dep->getElevation(), vTaxiBackward);
wpt->longitude = tn->getLongitude();
// Elevation is currently disregarded when on_ground is true wpt->setRouteIndex(rte);
// because the AIModel obtains a periodic ground elevation estimate.
wpt->altitude = dep->getElevation();
wpt->speed = vTaxiBackward;
wpt->crossat = -10000;
wpt->gear_down = true;
wpt->flaps_down= true;
wpt->finished = false;
wpt->on_ground = true;
wpt->routeIndex = rte;
waypoints.push_back(wpt); waypoints.push_back(wpt);
} }
// some special considerations for the last point: // some special considerations for the last point:
wpt->name = string("PushBackPoint"); waypoints.back()->setName(string("PushBackPoint"));
wpt->speed = vTaxi; waypoints.back()->setSpeed(vTaxi);
//for (wpt_vector_iterator i = waypoints.begin(); i != waypoints.end(); i++) { ac->setTaxiClearanceRequest(true);
// cerr << "Waypoint Name: " << (*i)->name << endl; } else { // In case of a push forward departure...
//} ac->setTaxiClearanceRequest(false);
} else {
/*
string rwyClass = getRunwayClassFromTrafficType(fltType);
// Only set this if it hasn't been set by ATC already.
if (activeRunway.empty()) {
//cerr << "Getting runway for " << ac->getTrafficRef()->getCallSign() << " at " << apt->getId() << endl;
double depHeading = ac->getTrafficRef()->getCourse();
dep->getDynamics()->getActiveRunway(rwyClass, 1, activeRunway,
depHeading);
}
rwy = dep->getRunwayByIdent(activeRunway);
SGGeod runwayTakeoff = rwy->pointOnCenterline(5.0);
FGGroundNetwork *gn = dep->getDynamics()->getGroundNetwork();
if (!gn->exists()) {
createDefaultTakeoffTaxi(ac, dep, rwy);
return true;
}
int runwayId = gn->findNearestNode(runwayTakeoff);
int node = 0;
// Find out which node to start from
FGParking *park = dep->getDynamics()->getParking(gateId);
if (park) {
node = park->getPushBackPoint();
}
if (node == -1) {
node = gateId;
}
// HAndle case where parking doens't have a node
if ((node == 0) && park) {
if (firstFlight) {
node = gateId;
} else {
node = gateId;
}
}
//delete taxiRoute;
//taxiRoute = new FGTaxiRoute;
FGTaxiRoute tr = gn->findShortestRoute(node, runwayId);
int route;
FGTaxiNode *tn;
waypoint *wpt;
int nr = 0;
cerr << "Creating taxiroute from gate: " << gateId << " at " << dep->getId() << endl;
while (tr.next(&node, &route) && (nr++ < 3)) {
char buffer[10];
snprintf(buffer, 10, "%d", node);
tn = dep->getDynamics()->getGroundNetwork()->findNode(node);
wpt = createOnGround(ac, buffer, tn->getGeod(), dep->getElevation(),
vTaxiReduced);
wpt->routeIndex = route;
waypoints.push_back(wpt);
}
wpt->name = "PushBackPoint";
lastNodeVisited = tn->getIndex();
//FGTaxiNode *firstNode = findNode(gateId);
//FGTaxiNode *lastNode = findNode(runwayId);
//cerr << "Creating direct forward departure route fragment" << endl;
*/
double lat2 = 0.0, lon2 = 0.0, az2 = 0.0; double lat2 = 0.0, lon2 = 0.0, az2 = 0.0;
waypoint *wpt;
geo_direct_wgs_84 ( 0, lat, lon, heading,
2, &lat2, &lon2, &az2 );
wpt = new waypoint;
wpt->name = "park2";
wpt->latitude = lat2;
wpt->longitude = lon2;
wpt->altitude = dep->getElevation();
wpt->speed = vTaxiReduced;
wpt->crossat = -10000;
wpt->gear_down = true;
wpt->flaps_down= true;
wpt->finished = false;
wpt->on_ground = true;
wpt->routeIndex = 0;
waypoints.push_back(wpt);
geo_direct_wgs_84 ( 0, lat, lon, heading,
4, &lat2, &lon2, &az2 );
wpt = new waypoint;
wpt->name = "name";
wpt->latitude = lat2;
wpt->longitude = lon2;
wpt->altitude = dep->getElevation();
wpt->speed = vTaxiReduced;
wpt->crossat = -10000;
wpt->gear_down = true;
wpt->flaps_down= true;
wpt->finished = false;
wpt->on_ground = true;
wpt->routeIndex = 0;
waypoints.push_back(wpt);
//cerr << "Creating final push forward point for gate " << gateId << endl; //cerr << "Creating final push forward point for gate " << gateId << endl;
FGTaxiNode *tn = dep->getDynamics()->getGroundNetwork()->findNode(gateId); FGTaxiNode *tn = dep->getDynamics()->getGroundNetwork()->findNode(gateId);
@ -273,21 +158,27 @@ bool FGAIFlightPlan::createPushBack(FGAIAircraft *ac,
SG_LOG(SG_GENERAL, SG_ALERT, "No valid taxinode found"); SG_LOG(SG_GENERAL, SG_ALERT, "No valid taxinode found");
exit(1); exit(1);
} }
wpt = new waypoint; double distance = (*ts)->getLength();
wpt->name = "PushBackPoint"; //cerr << "Length of push forward route = " << distance << " and heading is " << heading << endl;
wpt->latitude = tn->getLatitude(); lat2 = tn->getLatitude();
wpt->longitude = tn->getLongitude(); lon2 = tn->getLongitude();
wpt->altitude = dep->getElevation();
wpt->speed = vTaxiReduced;
wpt->crossat = -10000;
wpt->gear_down = true;
wpt->flaps_down= true;
wpt->finished = false;
wpt->on_ground = true;
wpt->routeIndex = (*ts)->getIndex();
waypoints.push_back(wpt);
}
for (int i = 1; i < 10; i++) {
geo_direct_wgs_84 ( 0, lat, lon, heading,
((i / 10.0) * distance), &lat2, &lon2, &az2 );
char buffer[16];
snprintf(buffer, 16, "pushback-%02d", i);
SGGeod coord = coord.fromDeg(lon2, lat2);
//cerr << i << endl;
FGAIWaypoint *wpt = createOnGround(ac, string(buffer), coord, dep->getElevation(), vTaxiReduced);
wpt->setRouteIndex((*ts)->getIndex());
waypoints.push_back(wpt);
}
// cerr << "Done " << endl;
waypoints.back()->setName(string("PushBackPoint"));
// cerr << "Done assinging new name" << endl;
}
} }
return true; return true;
} }
@ -321,51 +212,26 @@ void FGAIFlightPlan::createPushBackFallBack(FGAIAircraft *ac, bool firstFlight,
heading += 180.0; heading += 180.0;
if (heading > 360) if (heading > 360)
heading -= 360; heading -= 360;
waypoint *wpt = new waypoint;
wpt->name = "park"; SGGeod coord = coord.fromDeg(lon, lat);
wpt->latitude = lat; FGAIWaypoint *wpt = createOnGround(ac, string("park"), coord, dep->getElevation(), vTaxiBackward);
wpt->longitude = lon;
wpt->altitude = dep->getElevation();
wpt->speed = vTaxiBackward;
wpt->crossat = -10000;
wpt->gear_down = true;
wpt->flaps_down= true;
wpt->finished = false;
wpt->on_ground = true;
waypoints.push_back(wpt); waypoints.push_back(wpt);
geo_direct_wgs_84 ( 0, lat, lon, heading, geo_direct_wgs_84 ( 0, lat, lon, heading,
10, 10,
&lat2, &lon2, &az2 ); &lat2, &lon2, &az2 );
wpt = new waypoint; coord = coord.fromDeg(lon2, lat2);
wpt->name = "park2"; wpt = createOnGround(ac, string("park2"), coord, dep->getElevation(), vTaxiBackward);
wpt->latitude = lat2;
wpt->longitude = lon2;
wpt->altitude = dep->getElevation();
wpt->speed = vTaxiBackward;
wpt->crossat = -10000;
wpt->gear_down = true;
wpt->flaps_down= true;
wpt->finished = false;
wpt->on_ground = true;
wpt->routeIndex = 0;
waypoints.push_back(wpt); waypoints.push_back(wpt);
geo_direct_wgs_84 ( 0, lat, lon, heading, geo_direct_wgs_84 ( 0, lat, lon, heading,
2.2*radius, 2.2*radius,
&lat2, &lon2, &az2 ); &lat2, &lon2, &az2 );
wpt = new waypoint; coord = coord.fromDeg(lon2, lat2);
wpt->name = "taxiStart"; wpt = createOnGround(ac, string("taxiStart"), coord, dep->getElevation(), vTaxiReduced);
wpt->latitude = lat2;
wpt->longitude = lon2;
wpt->altitude = dep->getElevation();
wpt->speed = vTaxiReduced;
wpt->crossat = -10000;
wpt->gear_down = true;
wpt->flaps_down= true;
wpt->finished = false;
wpt->on_ground = true;
wpt->routeIndex = 0;
waypoints.push_back(wpt); waypoints.push_back(wpt);
} }

View file

@ -280,7 +280,7 @@ bool FGAIGroundVehicle::getPitch() {
} else { } else {
if (prev->altitude == 0 || curr->altitude == 0) return false; if (prev->getAltitude() == 0 || curr->getAltitude() == 0) return false;
static double distance; static double distance;
static double d_alt; static double d_alt;
@ -289,20 +289,20 @@ bool FGAIGroundVehicle::getPitch() {
if (_new_waypoint){ if (_new_waypoint){
//cout << "new waypoint, calculating pitch " << endl; //cout << "new waypoint, calculating pitch " << endl;
curr_alt = curr->altitude; curr_alt = curr->getAltitude();
prev_alt = prev->altitude; prev_alt = prev->getAltitude();
//cout << "prev_alt" <<prev_alt << endl; //cout << "prev_alt" <<prev_alt << endl;
d_alt = (curr_alt - prev_alt) * SG_METER_TO_FEET; d_alt = (curr_alt - prev_alt) * SG_METER_TO_FEET;
//_elevation = prev->altitude; //_elevation = prev->altitude;
distance = SGGeodesy::distanceM(SGGeod::fromDeg(prev->longitude, prev->latitude), distance = SGGeodesy::distanceM(SGGeod::fromDeg(prev->getLongitude(), prev->getLatitude()),
SGGeod::fromDeg(curr->longitude, curr->latitude)); SGGeod::fromDeg(curr->getLongitude(), curr->getLatitude()));
_pitch = atan2(d_alt, distance * SG_METER_TO_FEET) * SG_RADIANS_TO_DEGREES; _pitch = atan2(d_alt, distance * SG_METER_TO_FEET) * SG_RADIANS_TO_DEGREES;
//cout << "new waypoint, calculating pitch " << _pitch << //cout << "new waypoint, calculating pitch " << _pitch <<
// " " << _pitch_offset << " " << _elevation <<endl; // " " << _pitch_offset << " " << _elevation <<endl;
} }
double distance_to_go = SGGeodesy::distanceM(SGGeod::fromDeg(pos.getLongitudeDeg(), pos.getLatitudeDeg()), double distance_to_go = SGGeodesy::distanceM(SGGeod::fromDeg(pos.getLongitudeDeg(), pos.getLatitudeDeg()),
SGGeod::fromDeg(curr->longitude, curr->latitude)); SGGeod::fromDeg(curr->getLongitude(), curr->getLatitude()));
/*cout << "tunnel " << _tunnel /*cout << "tunnel " << _tunnel
<< " distance prev & curr " << prev->name << " " << curr->name << " " << distance * SG_METER_TO_FEET << " distance prev & curr " << prev->name << " " << curr->name << " " << distance * SG_METER_TO_FEET
@ -385,13 +385,13 @@ void FGAIGroundVehicle::AdvanceFP(){
double count = 0; double count = 0;
string parent_next_name =_selected_ac->getStringValue("waypoint/name-next"); string parent_next_name =_selected_ac->getStringValue("waypoint/name-next");
while(fp->getNextWaypoint() != 0 && fp->getNextWaypoint()->name != "END" && count < 5){ while(fp->getNextWaypoint() != 0 && fp->getNextWaypoint()->getName() != "END" && count < 5){
SG_LOG(SG_GENERAL, SG_DEBUG, "AIGroundVeh1cle: " << _name SG_LOG(SG_GENERAL, SG_DEBUG, "AIGroundVeh1cle: " << _name
<<" advancing waypoint to: " << parent_next_name); <<" advancing waypoint to: " << parent_next_name);
if (fp->getNextWaypoint()->name == parent_next_name){ if (fp->getNextWaypoint()->getName() == parent_next_name){
SG_LOG(SG_GENERAL, SG_DEBUG, "AIGroundVeh1cle: " << _name SG_LOG(SG_GENERAL, SG_DEBUG, "AIGroundVeh1cle: " << _name
<< " not setting waypoint already at: " << fp->getNextWaypoint()->name); << " not setting waypoint already at: " << fp->getNextWaypoint()->getName());
return; return;
} }
@ -400,9 +400,9 @@ void FGAIGroundVehicle::AdvanceFP(){
curr = fp->getCurrentWaypoint(); curr = fp->getCurrentWaypoint();
next = fp->getNextWaypoint(); next = fp->getNextWaypoint();
if (fp->getNextWaypoint()->name == parent_next_name){ if (fp->getNextWaypoint()->getName() == parent_next_name){
SG_LOG(SG_GENERAL, SG_DEBUG, "AIGroundVeh1cle: " << _name SG_LOG(SG_GENERAL, SG_DEBUG, "AIGroundVeh1cle: " << _name
<< " waypoint set to: " << fp->getNextWaypoint()->name); << " waypoint set to: " << fp->getNextWaypoint()->getName());
return; return;
} }
@ -410,15 +410,15 @@ void FGAIGroundVehicle::AdvanceFP(){
}// end while loop }// end while loop
while(fp->getPreviousWaypoint() != 0 && fp->getPreviousWaypoint()->name != "END" while(fp->getPreviousWaypoint() != 0 && fp->getPreviousWaypoint()->getName() != "END"
&& count > -10){ && count > -10){
SG_LOG(SG_GENERAL, SG_DEBUG, "AIGroundVeh1cle: " << _name SG_LOG(SG_GENERAL, SG_DEBUG, "AIGroundVeh1cle: " << _name
<< " retreating waypoint to: " << parent_next_name << " retreating waypoint to: " << parent_next_name
<< " at: " << fp->getNextWaypoint()->name); << " at: " << fp->getNextWaypoint()->getName());
if (fp->getNextWaypoint()->name == parent_next_name){ if (fp->getNextWaypoint()->getName() == parent_next_name){
SG_LOG(SG_GENERAL, SG_DEBUG, "AIGroundVeh1cle: " << _name SG_LOG(SG_GENERAL, SG_DEBUG, "AIGroundVeh1cle: " << _name
<< " not setting waypoint already at:" << fp->getNextWaypoint()->name ); << " not setting waypoint already at:" << fp->getNextWaypoint()->getName() );
return; return;
} }
@ -427,9 +427,9 @@ void FGAIGroundVehicle::AdvanceFP(){
curr = fp->getCurrentWaypoint(); curr = fp->getCurrentWaypoint();
next = fp->getNextWaypoint(); next = fp->getNextWaypoint();
if (fp->getNextWaypoint()->name == parent_next_name){ if (fp->getNextWaypoint()->getName() == parent_next_name){
SG_LOG(SG_GENERAL, SG_DEBUG, "AIGroundVeh1cle: " << _name SG_LOG(SG_GENERAL, SG_DEBUG, "AIGroundVeh1cle: " << _name
<< " waypoint set to: " << fp->getNextWaypoint()->name); << " waypoint set to: " << fp->getNextWaypoint()->getName());
return; return;
} }
@ -488,7 +488,7 @@ void FGAIGroundVehicle::RunGroundVehicle(double dt){
} }
if(_parent == ""){ if(_parent == ""){
AccelTo(prev->speed); AccelTo(prev->getSpeed());
_dt_count = 0; _dt_count = 0;
return; return;
} }
@ -499,7 +499,7 @@ void FGAIGroundVehicle::RunGroundVehicle(double dt){
bool parent_waiting = _selected_ac->getBoolValue("waypoint/waiting"); bool parent_waiting = _selected_ac->getBoolValue("waypoint/waiting");
//bool parent_restart = _selected_ac->getBoolValue("controls/restart"); //bool parent_restart = _selected_ac->getBoolValue("controls/restart");
if (parent_next_name == "END" && fp->getNextWaypoint()->name != "END" ){ if (parent_next_name == "END" && fp->getNextWaypoint()->getName() != "END" ){
SG_LOG(SG_GENERAL, SG_DEBUG, "AIGroundVeh1cle: " << _name SG_LOG(SG_GENERAL, SG_DEBUG, "AIGroundVeh1cle: " << _name
<< " setting END: getting new waypoints "); << " setting END: getting new waypoints ");
AdvanceFP(); AdvanceFP();
@ -513,7 +513,7 @@ void FGAIGroundVehicle::RunGroundVehicle(double dt){
AdvanceFP(); AdvanceFP();
setWPNames(); setWPNames();
_waiting = true; _waiting = true;
} else if (parent_next_name != "WAIT" && fp->getNextWaypoint()->name == "WAIT"){ } else if (parent_next_name != "WAIT" && fp->getNextWaypoint()->getName() == "WAIT"){
SG_LOG(SG_GENERAL, SG_DEBUG, "AIGroundVeh1cle: " << _name SG_LOG(SG_GENERAL, SG_DEBUG, "AIGroundVeh1cle: " << _name
<< " wait done: getting new waypoints "); << " wait done: getting new waypoints ");
_waiting = false; _waiting = false;
@ -521,8 +521,8 @@ void FGAIGroundVehicle::RunGroundVehicle(double dt){
fp->IncrementWaypoint(false); fp->IncrementWaypoint(false);
next = fp->getNextWaypoint(); next = fp->getNextWaypoint();
if (next->name == "WAITUNTIL" || next->name == "WAIT" if (next->getName() == "WAITUNTIL" || next->getName() == "WAIT"
|| next->name == "END"){ || next->getName() == "END"){
} else { } else {
prev = curr; prev = curr;
fp->IncrementWaypoint(false); fp->IncrementWaypoint(false);

View file

@ -572,25 +572,25 @@ void FGAIShip::setTunnel(bool t) {
void FGAIShip::setWPNames() { void FGAIShip::setWPNames() {
if (prev != 0) if (prev != 0)
setPrevName(prev->name); setPrevName(prev->getName());
else else
setPrevName(""); setPrevName("");
if (curr != 0) if (curr != 0)
setCurrName(curr->name); setCurrName(curr->getName());
else{ else{
setCurrName(""); setCurrName("");
SG_LOG(SG_GENERAL, SG_ALERT, "AIShip: current wp name error" ); SG_LOG(SG_GENERAL, SG_ALERT, "AIShip: current wp name error" );
} }
if (next != 0) if (next != 0)
setNextName(next->name); setNextName(next->getName());
else else
setNextName(""); setNextName("");
SG_LOG(SG_GENERAL, SG_DEBUG, "AIShip: prev wp name " << prev->name); SG_LOG(SG_GENERAL, SG_DEBUG, "AIShip: prev wp name " << prev->getName());
SG_LOG(SG_GENERAL, SG_DEBUG, "AIShip: current wp name " << curr->name); SG_LOG(SG_GENERAL, SG_DEBUG, "AIShip: current wp name " << curr->getName());
SG_LOG(SG_GENERAL, SG_DEBUG, "AIShip: next wp name " << next->name); SG_LOG(SG_GENERAL, SG_DEBUG, "AIShip: next wp name " << next->getName());
} }
@ -647,7 +647,7 @@ void FGAIShip::ProcessFlightPlan(double dt) {
// check to see if we've reached the point for our next turn // check to see if we've reached the point for our next turn
// if the range to the waypoint is less than the calculated turn // if the range to the waypoint is less than the calculated turn
// radius we can start the turn to the next leg // radius we can start the turn to the next leg
_wp_range = getRange(pos.getLatitudeDeg(), pos.getLongitudeDeg(), curr->latitude, curr->longitude); _wp_range = getRange(pos.getLatitudeDeg(), pos.getLongitudeDeg(), curr->getLatitude(), curr->getLongitude());
_range_rate = (_wp_range - _old_range) / _dt_count; _range_rate = (_wp_range - _old_range) / _dt_count;
double sp_turn_radius_nm = _sp_turn_radius_ft / 6076.1155; double sp_turn_radius_nm = _sp_turn_radius_ft / 6076.1155;
// we need to try to identify a _missed waypoint // we need to try to identify a _missed waypoint
@ -687,8 +687,8 @@ void FGAIShip::ProcessFlightPlan(double dt) {
fp->IncrementWaypoint(false); fp->IncrementWaypoint(false);
next = fp->getNextWaypoint(); next = fp->getNextWaypoint();
if (next->name == "WAITUNTIL" || next->name == "WAIT" if (next->getName() == "WAITUNTIL" || next->getName() == "WAIT"
|| next->name == "END" || next->name == "TUNNEL") || next->getName() == "END" || next->getName() == "TUNNEL")
return; return;
prev = curr; prev = curr;
@ -705,13 +705,13 @@ void FGAIShip::ProcessFlightPlan(double dt) {
curr = fp->getCurrentWaypoint(); curr = fp->getCurrentWaypoint();
next = fp->getNextWaypoint(); next = fp->getNextWaypoint();
setWPNames(); setWPNames();
_wp_range = getRange(pos.getLatitudeDeg(), pos.getLongitudeDeg(), curr->latitude, curr->longitude); _wp_range = getRange(pos.getLatitudeDeg(), pos.getLongitudeDeg(), curr->getLatitude(), curr->getLongitude());
_old_range = _wp_range; _old_range = _wp_range;
_range_rate = 0; _range_rate = 0;
_new_waypoint = true; _new_waypoint = true;
_missed_count = 0; _missed_count = 0;
_lead_angle = 0; _lead_angle = 0;
AccelTo(prev->speed); AccelTo(prev->getSpeed());
} else if (_restart){ } else if (_restart){
SG_LOG(SG_GENERAL, SG_INFO, "AIShip: " << _name << " Flightplan restarting "); SG_LOG(SG_GENERAL, SG_INFO, "AIShip: " << _name << " Flightplan restarting ");
_missed_count = 0; _missed_count = 0;
@ -725,7 +725,7 @@ void FGAIShip::ProcessFlightPlan(double dt) {
} else if (_next_name == "WAIT") { } else if (_next_name == "WAIT") {
if (_wait_count < next->time_sec) { if (_wait_count < next->getTime_sec()) {
SG_LOG(SG_GENERAL, SG_DEBUG, "AIShip: " << _name << " waiting "); SG_LOG(SG_GENERAL, SG_DEBUG, "AIShip: " << _name << " waiting ");
setSpeed(0); setSpeed(0);
_waiting = true; _waiting = true;
@ -741,8 +741,8 @@ void FGAIShip::ProcessFlightPlan(double dt) {
fp->IncrementWaypoint(false); fp->IncrementWaypoint(false);
next = fp->getNextWaypoint(); next = fp->getNextWaypoint();
if (next->name == "WAITUNTIL" || next->name == "WAIT" if (next->getName() == "WAITUNTIL" || next->getName() == "WAIT"
|| next->name == "END" || next->name == "TUNNEL") || next->getName() == "END" || next->getName() == "TUNNEL")
return; return;
prev = curr; prev = curr;
@ -753,12 +753,12 @@ void FGAIShip::ProcessFlightPlan(double dt) {
} else if (_next_name == "WAITUNTIL") { } else if (_next_name == "WAITUNTIL") {
time_sec = getDaySeconds(); time_sec = getDaySeconds();
until_time_sec = processTimeString(next->time); until_time_sec = processTimeString(next->getTime());
_until_time = next->time; _until_time = next->getTime();
setUntilTime(next->time); setUntilTime(next->getTime());
if (until_time_sec > time_sec) { if (until_time_sec > time_sec) {
SG_LOG(SG_GENERAL, SG_INFO, "AIShip: " << _name << " " SG_LOG(SG_GENERAL, SG_INFO, "AIShip: " << _name << " "
<< curr->name << " waiting until: " << curr->getName() << " waiting until: "
<< _until_time << " " << until_time_sec << " now " << time_sec ); << _until_time << " " << until_time_sec << " now " << time_sec );
setSpeed(0); setSpeed(0);
_lead_angle = 0; _lead_angle = 0;
@ -770,12 +770,12 @@ void FGAIShip::ProcessFlightPlan(double dt) {
setUntilTime(""); setUntilTime("");
fp->IncrementWaypoint(false); fp->IncrementWaypoint(false);
while (next->name == "WAITUNTIL") { while (next->getName() == "WAITUNTIL") {
fp->IncrementWaypoint(false); fp->IncrementWaypoint(false);
next = fp->getNextWaypoint(); next = fp->getNextWaypoint();
} }
if (next->name == "WAIT") if (next->getName() == "WAIT")
return; return;
prev = curr; prev = curr;
@ -799,23 +799,23 @@ void FGAIShip::ProcessFlightPlan(double dt) {
_missed_count = 0; _missed_count = 0;
_range_rate = 0; _range_rate = 0;
_lead_angle = 0; _lead_angle = 0;
_wp_range = getRange(pos.getLatitudeDeg(), pos.getLongitudeDeg(), curr->latitude, curr->longitude); _wp_range = getRange(pos.getLatitudeDeg(), pos.getLongitudeDeg(), curr->getLatitude(), curr->getLongitude());
_old_range = _wp_range; _old_range = _wp_range;
setWPPos(); setWPPos();
object_type type = getType(); object_type type = getType();
if (type != 10) if (type != 10)
AccelTo(prev->speed); AccelTo(prev->getSpeed());
_curr_alt = curr->altitude; _curr_alt = curr->getAltitude();
_prev_alt = prev->altitude; _prev_alt = prev->getAltitude();
} else { } else {
_new_waypoint = false; _new_waypoint = false;
} }
// now revise the required course for the next way point // now revise the required course for the next way point
_course = getCourse(pos.getLatitudeDeg(), pos.getLongitudeDeg(), curr->latitude, curr->longitude); _course = getCourse(pos.getLatitudeDeg(), pos.getLongitudeDeg(), curr->getLatitude(), curr->getLongitude());
if (finite(_course)) if (finite(_course))
TurnTo(_course); TurnTo(_course);
@ -840,7 +840,7 @@ bool FGAIShip::initFlightPlan() {
curr = fp->getCurrentWaypoint(); //second waypoint curr = fp->getCurrentWaypoint(); //second waypoint
next = fp->getNextWaypoint(); //third waypoint (might not exist!) next = fp->getNextWaypoint(); //third waypoint (might not exist!)
while (curr->name == "WAIT" || curr->name == "WAITUNTIL") { // don't wait when initialising while (curr->getName() == "WAIT" || curr->getName() == "WAITUNTIL") { // don't wait when initialising
SG_LOG(SG_GENERAL, SG_DEBUG, "AIShip: " << _name << " re-initializing waypoints "); SG_LOG(SG_GENERAL, SG_DEBUG, "AIShip: " << _name << " re-initializing waypoints ");
fp->IncrementWaypoint(false); fp->IncrementWaypoint(false);
curr = fp->getCurrentWaypoint(); curr = fp->getCurrentWaypoint();
@ -874,14 +874,14 @@ bool FGAIShip::initFlightPlan() {
} }
} else { } else {
setLatitude(prev->latitude); setLatitude(prev->getLatitude());
setLongitude(prev->longitude); setLongitude(prev->getLongitude());
setSpeed(prev->speed); setSpeed(prev->getSpeed());
} }
setWPNames(); setWPNames();
setHeading(getCourse(prev->latitude, prev->longitude, curr->latitude, curr->longitude)); setHeading(getCourse(prev->getLatitude(), prev->getLongitude(), curr->getLatitude(), curr->getLongitude()));
_wp_range = getRange(prev->latitude, prev->longitude, curr->latitude, curr->longitude); _wp_range = getRange(prev->getLatitude(), prev->getLongitude(), curr->getLatitude(), curr->getLongitude());
_old_range = _wp_range; _old_range = _wp_range;
_range_rate = 0; _range_rate = 0;
_hdg_lock = true; _hdg_lock = true;
@ -941,7 +941,7 @@ bool FGAIShip::advanceFlightPlan (double start_sec, double day_sec) {
while ( elapsed_sec < day_sec ) { while ( elapsed_sec < day_sec ) {
if (next->name == "END" || fp->getNextWaypoint() == 0) { if (next->getName() == "END" || fp->getNextWaypoint() == 0) {
if (_repeat ) { if (_repeat ) {
//cout << _name << ": " << "restarting flightplan" << endl; //cout << _name << ": " << "restarting flightplan" << endl;
@ -954,11 +954,11 @@ bool FGAIShip::advanceFlightPlan (double start_sec, double day_sec) {
return false; return false;
} }
} else if (next->name == "WAIT") { } else if (next->getName() == "WAIT") {
//cout << _name << ": begin WAIT: " << prev->name << " "; //cout << _name << ": begin WAIT: " << prev->name << " ";
//cout << curr->name << " " << next->name << endl; //cout << curr->name << " " << next->name << endl;
elapsed_sec += next->time_sec; elapsed_sec += next->getTime_sec();
if ( elapsed_sec >= day_sec) if ( elapsed_sec >= day_sec)
continue; continue;
@ -966,16 +966,16 @@ bool FGAIShip::advanceFlightPlan (double start_sec, double day_sec) {
fp->IncrementWaypoint(false); fp->IncrementWaypoint(false);
next = fp->getNextWaypoint(); next = fp->getNextWaypoint();
if (next->name != "WAITUNTIL" && next->name != "WAIT" if (next->getName() != "WAITUNTIL" && next->getName() != "WAIT"
&& next->name != "END") { && next->getName() != "END") {
prev = curr; prev = curr;
fp->IncrementWaypoint(false); fp->IncrementWaypoint(false);
curr = fp->getCurrentWaypoint(); curr = fp->getCurrentWaypoint();
next = fp->getNextWaypoint(); next = fp->getNextWaypoint();
} }
} else if (next->name == "WAITUNTIL") { } else if (next->getName() == "WAITUNTIL") {
double until_sec = processTimeString(next->time); double until_sec = processTimeString(next->getTime());
if (until_sec > _start_sec && start_sec < 0) if (until_sec > _start_sec && start_sec < 0)
until_sec -= _day; until_sec -= _day;
@ -989,7 +989,7 @@ bool FGAIShip::advanceFlightPlan (double start_sec, double day_sec) {
fp->IncrementWaypoint(false); fp->IncrementWaypoint(false);
next = fp->getNextWaypoint(); next = fp->getNextWaypoint();
if (next->name != "WAITUNTIL" && next->name != "WAIT") { if (next->getName() != "WAITUNTIL" && next->getName() != "WAIT") {
prev = curr; prev = curr;
fp->IncrementWaypoint(false); fp->IncrementWaypoint(false);
curr = fp->getCurrentWaypoint(); curr = fp->getCurrentWaypoint();
@ -1000,8 +1000,8 @@ bool FGAIShip::advanceFlightPlan (double start_sec, double day_sec) {
//cout << prev->name << " " << curr->name << " " << next->name << endl; //cout << prev->name << " " << curr->name << " " << next->name << endl;
} else { } else {
distance_nm = getRange(prev->latitude, prev->longitude, curr->latitude, curr->longitude); distance_nm = getRange(prev->getLatitude(), prev->getLongitude(), curr->getLatitude(), curr->getLongitude());
elapsed_sec += distance_nm * 60 * 60 / prev->speed; elapsed_sec += distance_nm * 60 * 60 / prev->getSpeed();
if (elapsed_sec >= day_sec) if (elapsed_sec >= day_sec)
continue; continue;
@ -1026,31 +1026,31 @@ bool FGAIShip::advanceFlightPlan (double start_sec, double day_sec) {
//cout << " time diff " << time_diff << endl; //cout << " time diff " << time_diff << endl;
if (next->name == "WAIT" ){ if (next->getName() == "WAIT" ){
setSpeed(0); setSpeed(0);
lat = curr->latitude; lat = curr->getLatitude();
lon = curr->longitude; lon = curr->getLongitude();
_wait_count= time_diff; _wait_count= time_diff;
_waiting = true; _waiting = true;
} else if (next->name == "WAITUNTIL") { } else if (next->getName() == "WAITUNTIL") {
setSpeed(0); setSpeed(0);
lat = curr->latitude; lat = curr->getLatitude();
lon = curr->longitude; lon = curr->getLongitude();
_waiting = true; _waiting = true;
} else { } else {
setSpeed(prev->speed); setSpeed(prev->getSpeed());
distance_nm = speed * time_diff / (60 * 60); distance_nm = speed * time_diff / (60 * 60);
double brg = getCourse(curr->latitude, curr->longitude, prev->latitude, prev->longitude); double brg = getCourse(curr->getLatitude(), curr->getLongitude(), prev->getLatitude(), prev->getLongitude());
//cout << " brg " << brg << " from " << curr->name << " to " << prev->name << " " //cout << " brg " << brg << " from " << curr->name << " to " << prev->name << " "
// << " lat " << curr->latitude << " lon " << curr->longitude // << " lat " << curr->latitude << " lon " << curr->longitude
// << " distance m " << distance_nm * SG_NM_TO_METER << endl; // << " distance m " << distance_nm * SG_NM_TO_METER << endl;
lat = geo_direct_wgs_84 (curr->latitude, curr->longitude, brg, lat = geo_direct_wgs_84 (curr->getLatitude(), curr->getLongitude(), brg,
distance_nm * SG_NM_TO_METER, &lat, &lon, &recip ); distance_nm * SG_NM_TO_METER, &lat, &lon, &recip );
lon = geo_direct_wgs_84 (curr->latitude, curr->longitude, brg, lon = geo_direct_wgs_84 (curr->getLatitude(), curr->getLongitude(), brg,
distance_nm * SG_NM_TO_METER, &lat, &lon, &recip ); distance_nm * SG_NM_TO_METER, &lat, &lon, &recip );
recip = geo_direct_wgs_84 (curr->latitude, curr->longitude, brg, recip = geo_direct_wgs_84 (curr->getLatitude(), curr->getLongitude(), brg,
distance_nm * SG_NM_TO_METER, &lat, &lon, &recip ); distance_nm * SG_NM_TO_METER, &lat, &lon, &recip );
} }
@ -1062,18 +1062,18 @@ bool FGAIShip::advanceFlightPlan (double start_sec, double day_sec) {
void FGAIShip::setWPPos() { void FGAIShip::setWPPos() {
if (curr->name == "END" || curr->name == "WAIT" if (curr->getName() == "END" || curr->getName() == "WAIT"
|| curr->name == "WAITUNTIL" || curr->name == "TUNNEL"){ || curr->getName() == "WAITUNTIL" || curr->getName() == "TUNNEL"){
//cout << curr->name << " returning" << endl; //cout << curr->name << " returning" << endl;
return; return;
} }
double elevation_m = 0; double elevation_m = 0;
wppos.setLatitudeDeg(curr->latitude); wppos.setLatitudeDeg(curr->getLatitude());
wppos.setLongitudeDeg(curr->longitude); wppos.setLongitudeDeg(curr->getLongitude());
wppos.setElevationM(0); wppos.setElevationM(0);
if (curr->on_ground){ if (curr->getOn_ground()){
if (globals->get_scenery()->get_elevation_m(SGGeod::fromGeodM(wppos, 3000), if (globals->get_scenery()->get_elevation_m(SGGeod::fromGeodM(wppos, 3000),
elevation_m, &_material, 0)){ elevation_m, &_material, 0)){
@ -1083,20 +1083,20 @@ void FGAIShip::setWPPos() {
//cout << curr->name << " setting measured elev " << elevation_m << endl; //cout << curr->name << " setting measured elev " << elevation_m << endl;
} else { } else {
wppos.setElevationM(curr->altitude); wppos.setElevationM(curr->getAltitude());
//cout << curr->name << " setting FP elev " << elevation_m << endl; //cout << curr->name << " setting FP elev " << elevation_m << endl;
} }
curr->altitude = wppos.getElevationM(); curr->setAltitude(wppos.getElevationM());
} }
void FGAIShip::setXTrackError() { void FGAIShip::setXTrackError() {
double course = getCourse(prev->latitude, prev->longitude, double course = getCourse(prev->getLatitude(), prev->getLongitude(),
curr->latitude, curr->longitude); curr->getLatitude(), curr->getLongitude());
double brg = getCourse(pos.getLatitudeDeg(), pos.getLongitudeDeg(), double brg = getCourse(pos.getLatitudeDeg(), pos.getLongitudeDeg(),
curr->latitude, curr->longitude); curr->getLatitude(), curr->getLongitude());
double xtrack_error_nm = sin((course - brg)* SG_DEGREES_TO_RADIANS) * _wp_range; double xtrack_error_nm = sin((course - brg)* SG_DEGREES_TO_RADIANS) * _wp_range;
double factor = -0.0045 * speed + 1; double factor = -0.0045 * speed + 1;
double limit = _lead_angle_limit * factor; double limit = _lead_angle_limit * factor;

View file

@ -81,9 +81,9 @@ public:
double _missed_range, _tow_angle, _wait_count, _missed_count,_wp_range; double _missed_range, _tow_angle, _wait_count, _missed_count,_wp_range;
double _dt_count, _next_run; double _dt_count, _next_run;
FGAIFlightPlan::waypoint* prev; // the one behind you FGAIWaypoint* prev; // the one behind you
FGAIFlightPlan::waypoint* curr; // the one ahead FGAIWaypoint* curr; // the one ahead
FGAIFlightPlan::waypoint* next; // the next plus 1 FGAIWaypoint* next; // the next plus 1
protected: protected:

View file

@ -34,6 +34,8 @@
FGATCManager::FGATCManager() { FGATCManager::FGATCManager() {
controller = 0;
prevController = 0;
networkVisible = false; networkVisible = false;
} }
@ -115,16 +117,17 @@ void FGATCManager::init() {
int stationFreq = apt->getDynamics()->getTowerFrequency(2); int stationFreq = apt->getDynamics()->getTowerFrequency(2);
//cerr << "Setting radio frequency to in airfrequency: " << stationFreq << endl; //cerr << "Setting radio frequency to in airfrequency: " << stationFreq << endl;
fgSetDouble("/instrumentation/comm[0]/frequencies/selected-mhz", ((double) stationFreq / 100.0)); fgSetDouble("/instrumentation/comm[0]/frequencies/selected-mhz", ((double) stationFreq / 100.0));
leg = 4; leg = 3;
string fltType = "ga"; string fltType = "ga";
fp->setRunway(runway); fp->setRunway(runway);
fp->createTakeOff(&ai_ac, false, apt, 0, fltType); fp->createTakeOff(&ai_ac, false, apt, 0, fltType);
ai_ac.setTakeOffStatus(2);
} else { } else {
controller = apt->getDynamics()->getStartupController(); controller = apt->getDynamics()->getStartupController();
int stationFreq = apt->getDynamics()->getGroundFrequency(2); int stationFreq = apt->getDynamics()->getGroundFrequency(1);
//cerr << "Setting radio frequency to : " << stationFreq << endl; //cerr << "Setting radio frequency to : " << stationFreq << endl;
fgSetDouble("/instrumentation/comm[0]/frequencies/selected-mhz", ((double) stationFreq / 100.0)); fgSetDouble("/instrumentation/comm[0]/frequencies/selected-mhz", ((double) stationFreq / 100.0));
leg = 2; leg = 1;
//double, lat, lon, head; // Unused variables; //double, lat, lon, head; // Unused variables;
//int getId = apt->getDynamics()->getParking(gateId, &lat, &lon, &head); //int getId = apt->getDynamics()->getParking(gateId, &lat, &lon, &head);
FGParking* parking = dcs->getParking(park_index); FGParking* parking = dcs->getParking(park_index);
@ -142,7 +145,9 @@ void FGATCManager::init() {
fltType, fltType,
aircraftType, aircraftType,
airline); airline);
}
}
fp->getLastWaypoint()->setName( fp->getLastWaypoint()->getName() + string("legend"));
} else { } else {
controller = 0; controller = 0;
} }
@ -155,7 +160,7 @@ void FGATCManager::init() {
ai_ac.SetFlightPlan(fp); ai_ac.SetFlightPlan(fp);
} }
if (controller) { if (controller) {
controller->announcePosition(ai_ac.getID(), fp, fp->getCurrentWaypoint()->routeIndex, controller->announcePosition(ai_ac.getID(), fp, fp->getCurrentWaypoint()->getRouteIndex(),
ai_ac._getLatitude(), ai_ac._getLongitude(), heading, speed, altitude, ai_ac._getLatitude(), ai_ac._getLongitude(), heading, speed, altitude,
aircraftRadius, leg, &ai_ac); aircraftRadius, leg, &ai_ac);
@ -180,20 +185,23 @@ void FGATCManager::update ( double time ) {
FGAIFlightPlan *fp = ai_ac.GetFlightPlan(); FGAIFlightPlan *fp = ai_ac.GetFlightPlan();
/* test code : find out how the routing develops */ /* test code : find out how the routing develops */
//if (fp) { if (fp) {
// int size = fp->getNrOfWayPoints(); int size = fp->getNrOfWayPoints();
// //cerr << "Setting pos" << pos << " "; // //cerr << "Setting pos" << pos << " ";
// //cerr << "setting intentions " ; // //cerr << "setting intentions " ;
// for (int i = 0; i < size; i++) { for (int i = 0; i < size; i++) {
// int val = fp->getRouteIndex(i); // int val = fp->getRouteIndex(i);
// cerr << val << " "; //cerr << fp->getWayPoint(i)->getName() << " ";
//if ((val) && (val != pos)) { //if ((val) && (val != pos)) {
//intentions.push_back(val); //intentions.push_back(val);
//cerr << "[done ] " << endl; //cerr << "[done ] " << endl;
//} //}
// } }
//} }
//cerr << "[done ] " << endl; //cerr << "[done ] " << endl;
if (fp) {
//cerr << "Currently at leg : " << fp->getLeg() << endl;
}
double longitude = fgGetDouble("/position/longitude-deg"); double longitude = fgGetDouble("/position/longitude-deg");
double latitude = fgGetDouble("/position/latitude-deg"); double latitude = fgGetDouble("/position/latitude-deg");
double heading = fgGetDouble("/orientation/heading-deg"); double heading = fgGetDouble("/orientation/heading-deg");
@ -208,9 +216,10 @@ void FGATCManager::update ( double time ) {
controller = ai_ac.getATCController(); controller = ai_ac.getATCController();
currentATCDialog->update(time); currentATCDialog->update(time);
if (controller) { if (controller) {
//cerr << "name of previous waypoint : " << fp->getPreviousWaypoint()->getName() << endl;
//cerr << "Running FGATCManager::update()" << endl; //cerr << "Running FGATCManager::update()" << endl;
//cerr << "Currently under control of " << controller->getName() << endl;
controller->updateAircraftInformation(ai_ac.getID(), controller->updateAircraftInformation(ai_ac.getID(),
latitude, latitude,
longitude, longitude,
@ -227,9 +236,13 @@ void FGATCManager::update ( double time ) {
networkVisible = !networkVisible; networkVisible = !networkVisible;
trans_num->setIntValue(-1); trans_num->setIntValue(-1);
} }
if ((controller != prevController) && (prevController)) {
prevController->render(false);
}
controller->render(networkVisible); controller->render(networkVisible);
//cerr << "Adding groundnetWork to the scenegraph::update" << endl; //cerr << "Adding groundnetWork to the scenegraph::update" << endl;
prevController = controller;
} }
//globals->get_scenery()->get_scene_graph()->addChild(node); //globals->get_scenery()->get_scene_graph()->addChild(node);
} }

View file

@ -49,7 +49,7 @@ class FGATCManager : public SGSubsystem
private: private:
AtcVec activeStations; AtcVec activeStations;
FGAIAircraft ai_ac; FGAIAircraft ai_ac;
FGATCController *controller; // The ATC controller that is responsible for the user's aircraft. FGATCController *controller, *prevController; // The ATC controller that is responsible for the user's aircraft.
//FGATCDialogNew dialog; // note that this variable should really replace the ugly global "currentATCDialog(); //FGATCDialogNew dialog; // note that this variable should really replace the ugly global "currentATCDialog();
bool networkVisible; bool networkVisible;

View file

@ -36,7 +36,7 @@
FGATCDialogNew *currentATCDialog; FGATCDialogNew *currentATCDialog;
static bool doATCDialog(const SGPropertyNode* arg) { static bool doATCDialog(const SGPropertyNode* arg) {
cerr << "Running doATCDialog" << endl; //cerr << "Running doATCDialog" << endl;
currentATCDialog->PopupDialog(); currentATCDialog->PopupDialog();
return(true); return(true);
} }

View file

@ -86,7 +86,7 @@ time_t ActiveRunway::requestTimeSlot(time_t eta)
} }
} else { } else {
if ((((*j) - (*i)) > (separation * 2))) { // found a potential slot if ((((*j) - (*i)) > (separation * 2))) { // found a potential slot
// now check whether this slow is usable: // now check whether this slot is usable:
// 1) eta should fall between the two points // 1) eta should fall between the two points
// i.e. eta > i AND eta < j // i.e. eta > i AND eta < j
// //
@ -193,6 +193,11 @@ void FGTrafficRecord::setPositionAndIntentions(int pos,
} }
//exit(1); //exit(1);
} }
/**
* Check if another aircraft is ahead of the current one, and on the same
* return true / false is the is/isn't the case.
*
****************************************************************************/
bool FGTrafficRecord::checkPositionAndIntentions(FGTrafficRecord & other) bool FGTrafficRecord::checkPositionAndIntentions(FGTrafficRecord & other)
{ {
@ -497,10 +502,12 @@ void FGATCController::transmit(FGTrafficRecord * rec, AtcMsgId msgId,
string sender, receiver; string sender, receiver;
int stationFreq = 0; int stationFreq = 0;
int taxiFreq = 0; int taxiFreq = 0;
int towerFreq = 0;
int freqId = 0; int freqId = 0;
string atisInformation; string atisInformation;
string text; string text;
string taxiFreqStr; string taxiFreqStr;
string towerFreqStr;
double heading = 0; double heading = 0;
string activeRunway; string activeRunway;
string fltType; string fltType;
@ -509,20 +516,29 @@ void FGATCController::transmit(FGTrafficRecord * rec, AtcMsgId msgId,
string transponderCode; string transponderCode;
FGAIFlightPlan *fp; FGAIFlightPlan *fp;
string fltRules; string fltRules;
string instructionText;
//double commFreqD; //double commFreqD;
sender = rec->getAircraft()->getTrafficRef()->getCallSign(); sender = rec->getAircraft()->getTrafficRef()->getCallSign();
if (rec->getAircraft()->getTaxiClearanceRequest()) {
instructionText = "push-back and taxi";
} else {
instructionText = "taxi";
}
//cerr << "transmitting for: " << sender << "Leg = " << rec->getLeg() << endl; //cerr << "transmitting for: " << sender << "Leg = " << rec->getLeg() << endl;
switch (rec->getLeg()) { switch (rec->getLeg()) {
case 1:
case 2: case 2:
case 3:
freqId = rec->getNextFrequency(); freqId = rec->getNextFrequency();
stationFreq = stationFreq =
rec->getAircraft()->getTrafficRef()->getDepartureAirport()-> rec->getAircraft()->getTrafficRef()->getDepartureAirport()->
getDynamics()->getGroundFrequency(rec->getLeg() + freqId); getDynamics()->getGroundFrequency(rec->getLeg() + freqId);
taxiFreq = taxiFreq =
rec->getAircraft()->getTrafficRef()->getDepartureAirport()-> rec->getAircraft()->getTrafficRef()->getDepartureAirport()->
getDynamics()->getGroundFrequency(3); getDynamics()->getGroundFrequency(2);
towerFreq =
rec->getAircraft()->getTrafficRef()->getDepartureAirport()->
getDynamics()->getTowerFrequency(2);
receiver = receiver =
rec->getAircraft()->getTrafficRef()->getDepartureAirport()-> rec->getAircraft()->getTrafficRef()->getDepartureAirport()->
getName() + "-Ground"; getName() + "-Ground";
@ -530,7 +546,7 @@ void FGATCController::transmit(FGTrafficRecord * rec, AtcMsgId msgId,
rec->getAircraft()->getTrafficRef()->getDepartureAirport()-> rec->getAircraft()->getTrafficRef()->getDepartureAirport()->
getDynamics()->getAtisSequence(); getDynamics()->getAtisSequence();
break; break;
case 4: case 3:
receiver = receiver =
rec->getAircraft()->getTrafficRef()->getDepartureAirport()-> rec->getAircraft()->getTrafficRef()->getDepartureAirport()->
getName() + "-Tower"; getName() + "-Tower";
@ -588,7 +604,7 @@ void FGATCController::transmit(FGTrafficRecord * rec, AtcMsgId msgId,
receiver + ". Start-up approved. " + atisInformation + receiver + ". Start-up approved. " + atisInformation +
" correct, runway " + activeRunway + ", " + SID + ", squawk " + " correct, runway " + activeRunway + ", " + SID + ", squawk " +
transponderCode + ". " + transponderCode + ". " +
"For push-back and taxi clearance call " + taxiFreqStr + ". " + "For "+ instructionText + " clearance call " + taxiFreqStr + ". " +
sender + " control."; sender + " control.";
break; break;
case MSG_DENY_ENGINE_START: case MSG_DENY_ENGINE_START:
@ -606,11 +622,12 @@ void FGATCController::transmit(FGTrafficRecord * rec, AtcMsgId msgId,
taxiFreqStr = formatATCFrequency3_2(taxiFreq); taxiFreqStr = formatATCFrequency3_2(taxiFreq);
activeRunway = rec->getAircraft()->GetFlightPlan()->getRunway(); activeRunway = rec->getAircraft()->GetFlightPlan()->getRunway();
transponderCode = rec->getAircraft()->GetTransponderCode(); transponderCode = rec->getAircraft()->GetTransponderCode();
text = text =
receiver + ". Start-up approved. " + atisInformation + receiver + ". Start-up approved. " + atisInformation +
" correct, runway " + activeRunway + ", " + SID + ", squawk " + " correct, runway " + activeRunway + ", " + SID + ", squawk " +
transponderCode + ". " + transponderCode + ". " +
"For push-back and taxi clearance call " + taxiFreqStr + ". " + "For " + instructionText + " clearance call " + taxiFreqStr + ". " +
sender; sender;
break; break;
case MSG_ACKNOWLEDGE_SWITCH_GROUND_FREQUENCY: case MSG_ACKNOWLEDGE_SWITCH_GROUND_FREQUENCY:
@ -624,10 +641,18 @@ void FGATCController::transmit(FGTrafficRecord * rec, AtcMsgId msgId,
text = receiver + ". Roger. " + sender; text = receiver + ". Roger. " + sender;
break; break;
case MSG_REQUEST_PUSHBACK_CLEARANCE: case MSG_REQUEST_PUSHBACK_CLEARANCE:
text = receiver + ". Request push-back. " + sender; if (rec->getAircraft()->getTaxiClearanceRequest()) {
text = receiver + ". Request push-back. " + sender;
} else {
text = receiver + ". Request Taxi clearance. " + sender;
}
break; break;
case MSG_PERMIT_PUSHBACK_CLEARANCE: case MSG_PERMIT_PUSHBACK_CLEARANCE:
text = receiver + ". Push-back approved. " + sender; if (rec->getAircraft()->getTaxiClearanceRequest()) {
text = receiver + ". Push-back approved. " + sender;
} else {
text = receiver + ". Cleared to Taxi." + sender;
}
break; break;
case MSG_HOLD_PUSHBACK_CLEARANCE: case MSG_HOLD_PUSHBACK_CLEARANCE:
text = receiver + ". Standby. " + sender; text = receiver + ". Standby. " + sender;
@ -653,7 +678,37 @@ void FGATCController::transmit(FGTrafficRecord * rec, AtcMsgId msgId,
case MSG_ACKNOWLEDGE_RESUME_TAXI: case MSG_ACKNOWLEDGE_RESUME_TAXI:
text = receiver + ". Continuing Taxi. " + sender; text = receiver + ". Continuing Taxi. " + sender;
break; break;
case MSG_REPORT_RUNWAY_HOLD_SHORT:
activeRunway = rec->getAircraft()->GetFlightPlan()->getRunway();
//activeRunway = "test";
text = receiver + ". Holding short runway "
+ activeRunway
+ ". " + sender;
//text = "test1";
//cerr << "1 Currently at leg " << rec->getLeg() << endl;
break;
case MSG_ACKNOWLEDGE_REPORT_RUNWAY_HOLD_SHORT:
activeRunway = rec->getAircraft()->GetFlightPlan()->getRunway();
text = receiver + "Roger. Holding short runway "
// + activeRunway
+ ". " + sender;
//text = "test2";
//cerr << "2 Currently at leg " << rec->getLeg() << endl;
break;
case MSG_SWITCH_TOWER_FREQUENCY:
towerFreqStr = formatATCFrequency3_2(towerFreq);
text = receiver + "Contact Tower at " + towerFreqStr + ". " + sender;
//text = "test3";
//cerr << "3 Currently at leg " << rec->getLeg() << endl;
break;
case MSG_ACKNOWLEDGE_SWITCH_TOWER_FREQUENCY:
towerFreqStr = formatATCFrequency3_2(towerFreq);
text = receiver + "Roger, switching to tower at " + towerFreqStr + ". " + sender;
//text = "test4";
//cerr << "4 Currently at leg " << rec->getLeg() << endl;
break;
default: default:
//text = "test3";
text = text + sender + ". Transmitting unknown Message"; text = text + sender + ". Transmitting unknown Message";
break; break;
} }
@ -716,9 +771,10 @@ void FGATCController::init()
* class FGTowerController * class FGTowerController
* *
**************************************************************************/ **************************************************************************/
FGTowerController::FGTowerController(): FGTowerController::FGTowerController(FGAirportDynamics *par) :
FGATCController() FGATCController()
{ {
parent = par;
} }
// //
@ -752,8 +808,29 @@ void FGTowerController::announcePosition(int id,
rec.setRunway(intendedRoute->getRunway()); rec.setRunway(intendedRoute->getRunway());
rec.setLeg(leg); rec.setLeg(leg);
//rec.setCallSign(callsign); //rec.setCallSign(callsign);
rec.setRadius(radius);
rec.setAircraft(ref); rec.setAircraft(ref);
activeTraffic.push_back(rec); activeTraffic.push_back(rec);
// Don't just schedule the aircraft for the tower controller, also assign if to the correct active runway.
ActiveRunwayVecIterator rwy = activeRunways.begin();
if (activeRunways.size()) {
while (rwy != activeRunways.end()) {
if (rwy->getRunwayName() == intendedRoute->getRunway()) {
break;
}
rwy++;
}
}
if (rwy == activeRunways.end()) {
ActiveRunway aRwy(intendedRoute->getRunway(), id);
aRwy.addToDepartureCue(ref);
activeRunways.push_back(aRwy);
rwy = (activeRunways.end()-1);
} else {
rwy->addToDepartureCue(ref);
}
//cerr << ref->getTrafficRef()->getCallSign() << " You are number " << rwy->getDepartureCueSize() << " for takeoff " << endl;
} else { } else {
i->setPositionAndHeading(lat, lon, heading, speed, alt); i->setPositionAndHeading(lat, lon, heading, speed, alt);
} }
@ -786,29 +863,43 @@ void FGTowerController::updateAircraftInformation(int id, double lat, double lon
} }
setDt(getDt() + dt); setDt(getDt() + dt);
// // see if we already have a clearance record for the currently active runway // see if we already have a clearance record for the currently active runway
// NOTE: dd. 2011-08-07: Because the active runway has been constructed in the announcePosition function, we may safely assume that is
// already exists here. So, we can simplify the current code.
ActiveRunwayVecIterator rwy = activeRunways.begin(); ActiveRunwayVecIterator rwy = activeRunways.begin();
// again, a map might be more efficient here while (rwy != activeRunways.end()) {
if (activeRunways.size()) { if (rwy->getRunwayName() == current->getRunway()) {
//while ((rwy->getRunwayName() != current->getRunway()) && (rwy != activeRunways.end())) { break;
while (rwy != activeRunways.end()) {
if (rwy->getRunwayName() == current->getRunway()) {
break;
}
rwy++;
} }
rwy++;
} }
if (rwy == activeRunways.end()) {
ActiveRunway aRwy(current->getRunway(), id); // only bother running the following code if the current aircraft is the
activeRunways.push_back(aRwy); // Since there are no clearance records for this runway yet // first in line for depature
current->setHoldPosition(false); // Clear the current aircraft to continue /* if (current->getAircraft() == rwy->getFirstAircraftInDepartureCue()) {
} else { if (rwy->getCleared()) {
// Okay, we have a clearance record for this runway, so check if (id == rwy->getCleared()) {
// whether the clearence ID matches that of the current aircraft current->setHoldPosition(false);
if (id == rwy->getCleared()) { } else {
current->setHoldPosition(false); current->setHoldPosition(true);
}
} else { } else {
current->setHoldPosition(true); // For now. At later stages, this will probably be the place to check for inbound traffc.
rwy->setCleared(id);
}
} */
// only bother with aircraft that have a takeoff status of 2, since those are essentially under tower control
if (current->getAircraft()->getTakeOffStatus() == 2) {
current->setHoldPosition(true);
int clearanceId = rwy->getCleared();
if (clearanceId) {
if (id == clearanceId) {
current->setHoldPosition(false);
}
} else {
if (current->getAircraft() == rwy->getFirstAircraftInDepartureCue()) {
rwy->setCleared(id);
}
} }
} }
} }
@ -839,7 +930,8 @@ void FGTowerController::signOff(int id)
rwy++; rwy++;
} }
if (rwy != activeRunways.end()) { if (rwy != activeRunways.end()) {
rwy = activeRunways.erase(rwy); rwy->setCleared(0);
rwy->updateDepartureCue();
} else { } else {
SG_LOG(SG_GENERAL, SG_ALERT, SG_LOG(SG_GENERAL, SG_ALERT,
"AI error: Attempting to erase non-existing runway clearance record in FGTowerController::signoff"); "AI error: Attempting to erase non-existing runway clearance record in FGTowerController::signoff");
@ -849,6 +941,7 @@ void FGTowerController::signOff(int id)
SG_LOG(SG_GENERAL, SG_ALERT, SG_LOG(SG_GENERAL, SG_ALERT,
"AI error: Aircraft without traffic record is signing off from tower"); "AI error: Aircraft without traffic record is signing off from tower");
} else { } else {
i->getAircraft()->resetTakeOffStatus();
i = activeTraffic.erase(i); i = activeTraffic.erase(i);
//cerr << "Signing off from tower controller" << endl; //cerr << "Signing off from tower controller" << endl;
} }
@ -911,6 +1004,11 @@ void FGTowerController::render(bool visible) {
//cerr << "FGTowerController::render function not yet implemented" << endl; //cerr << "FGTowerController::render function not yet implemented" << endl;
} }
string FGTowerController::getName() {
return string(parent->getId() + "-tower");
}
/*************************************************************************** /***************************************************************************
* class FGStartupController * class FGStartupController
@ -1273,13 +1371,19 @@ void FGStartupController::render(bool visible)
} }
} }
string FGStartupController::getName() {
return string(parent->getId() + "-startup");
}
/*************************************************************************** /***************************************************************************
* class FGApproachController * class FGApproachController
* *
**************************************************************************/ **************************************************************************/
FGApproachController::FGApproachController(): FGApproachController::FGApproachController(FGAirportDynamics *par):
FGATCController() FGATCController()
{ {
parent = par;
} }
// //
@ -1467,3 +1571,9 @@ ActiveRunway *FGApproachController::getRunway(string name)
void FGApproachController::render(bool visible) { void FGApproachController::render(bool visible) {
//cerr << "FGApproachController::render function not yet implemented" << endl; //cerr << "FGApproachController::render function not yet implemented" << endl;
} }
string FGApproachController::getName() {
return string(parent->getId() + "-approach");
}

View file

@ -197,6 +197,8 @@ typedef vector<FGTrafficRecord>::iterator TrafficVectorIterator;
typedef vector<time_t> TimeVector; typedef vector<time_t> TimeVector;
typedef vector<time_t>::iterator TimeVectorIterator; typedef vector<time_t>::iterator TimeVectorIterator;
typedef vector<FGAIAircraft*> AircraftVec;
typedef vector<FGAIAircraft*>::iterator AircraftVecIterator;
/*********************************************************************** /***********************************************************************
* Active runway, a utility class to keep track of which aircraft has * Active runway, a utility class to keep track of which aircraft has
@ -209,6 +211,8 @@ private:
int currentlyCleared; int currentlyCleared;
double distanceToFinal; double distanceToFinal;
TimeVector estimatedArrivalTimes; TimeVector estimatedArrivalTimes;
AircraftVec departureCue;
public: public:
ActiveRunway(string r, int cc) { rwy = r; currentlyCleared = cc; distanceToFinal = 6.0 * SG_NM_TO_METER; }; ActiveRunway(string r, int cc) { rwy = r; currentlyCleared = cc; distanceToFinal = 6.0 * SG_NM_TO_METER; };
@ -218,7 +222,13 @@ public:
//time_t getEstApproachTime() { return estimatedArrival; }; //time_t getEstApproachTime() { return estimatedArrival; };
//void setEstApproachTime(time_t time) { estimatedArrival = time; }; //void setEstApproachTime(time_t time) { estimatedArrival = time; };
void addToDepartureCue(FGAIAircraft *ac) { departureCue.push_back(ac); };
void setCleared(int number) { currentlyCleared = number; };
time_t requestTimeSlot(time_t eta); time_t requestTimeSlot(time_t eta);
int getDepartureCueSize() { return departureCue.size(); };
FGAIAircraft* getFirstAircraftInDepartureCue() { return departureCue.size() ? *(departureCue.begin()) : NULL; };
void updateDepartureCue() { departureCue.erase(departureCue.begin()); }
}; };
typedef vector<ActiveRunway> ActiveRunwayVec; typedef vector<ActiveRunway> ActiveRunwayVec;
@ -263,7 +273,13 @@ public:
MSG_HOLD_POSITION, MSG_HOLD_POSITION,
MSG_ACKNOWLEDGE_HOLD_POSITION, MSG_ACKNOWLEDGE_HOLD_POSITION,
MSG_RESUME_TAXI, MSG_RESUME_TAXI,
MSG_ACKNOWLEDGE_RESUME_TAXI } AtcMsgId; MSG_ACKNOWLEDGE_RESUME_TAXI,
MSG_REPORT_RUNWAY_HOLD_SHORT,
MSG_ACKNOWLEDGE_REPORT_RUNWAY_HOLD_SHORT,
MSG_SWITCH_TOWER_FREQUENCY,
MSG_ACKNOWLEDGE_SWITCH_TOWER_FREQUENCY
} AtcMsgId;
typedef enum { typedef enum {
ATC_AIR_TO_GROUND, ATC_AIR_TO_GROUND,
ATC_GROUND_TO_AIR } AtcMsgDir; ATC_GROUND_TO_AIR } AtcMsgDir;
@ -286,6 +302,8 @@ public:
void transmit(FGTrafficRecord *rec, AtcMsgId msgId, AtcMsgDir msgDir, bool audible); void transmit(FGTrafficRecord *rec, AtcMsgId msgId, AtcMsgDir msgDir, bool audible);
string getGateName(FGAIAircraft *aircraft); string getGateName(FGAIAircraft *aircraft);
virtual void render(bool) = 0; virtual void render(bool) = 0;
virtual string getName() = 0;
private: private:
@ -300,9 +318,10 @@ class FGTowerController : public FGATCController
private: private:
TrafficVector activeTraffic; TrafficVector activeTraffic;
ActiveRunwayVec activeRunways; ActiveRunwayVec activeRunways;
FGAirportDynamics *parent;
public: public:
FGTowerController(); FGTowerController(FGAirportDynamics *parent);
virtual ~FGTowerController() {}; virtual ~FGTowerController() {};
virtual void announcePosition(int id, FGAIFlightPlan *intendedRoute, int currentRoute, virtual void announcePosition(int id, FGAIFlightPlan *intendedRoute, int currentRoute,
double lat, double lon, double lat, double lon,
@ -315,6 +334,7 @@ public:
virtual FGATCInstruction getInstruction(int id); virtual FGATCInstruction getInstruction(int id);
virtual void render(bool); virtual void render(bool);
virtual string getName();
bool hasActiveTraffic() { return activeTraffic.size() != 0; }; bool hasActiveTraffic() { return activeTraffic.size() != 0; };
TrafficVector &getActiveTraffic() { return activeTraffic; }; TrafficVector &getActiveTraffic() { return activeTraffic; };
}; };
@ -329,7 +349,7 @@ class FGStartupController : public FGATCController
private: private:
TrafficVector activeTraffic; TrafficVector activeTraffic;
//ActiveRunwayVec activeRunways; //ActiveRunwayVec activeRunways;
FGAirportDynamics *parent; FGAirportDynamics *parent;
public: public:
FGStartupController(FGAirportDynamics *parent); FGStartupController(FGAirportDynamics *parent);
@ -345,6 +365,7 @@ public:
virtual FGATCInstruction getInstruction(int id); virtual FGATCInstruction getInstruction(int id);
virtual void render(bool); virtual void render(bool);
virtual string getName();
bool hasActiveTraffic() { return activeTraffic.size() != 0; }; bool hasActiveTraffic() { return activeTraffic.size() != 0; };
TrafficVector &getActiveTraffic() { return activeTraffic; }; TrafficVector &getActiveTraffic() { return activeTraffic; };
@ -363,10 +384,11 @@ class FGApproachController : public FGATCController
private: private:
TrafficVector activeTraffic; TrafficVector activeTraffic;
ActiveRunwayVec activeRunways; ActiveRunwayVec activeRunways;
FGAirportDynamics *parent;
public: public:
FGApproachController(); FGApproachController(FGAirportDynamics * parent);
virtual ~FGApproachController() {}; virtual ~FGApproachController() { };
virtual void announcePosition(int id, FGAIFlightPlan *intendedRoute, int currentRoute, virtual void announcePosition(int id, FGAIFlightPlan *intendedRoute, int currentRoute,
double lat, double lon, double lat, double lon,
double hdg, double spd, double alt, double radius, int leg, double hdg, double spd, double alt, double radius, int leg,
@ -378,6 +400,7 @@ public:
virtual FGATCInstruction getInstruction(int id); virtual FGATCInstruction getInstruction(int id);
virtual void render(bool); virtual void render(bool);
virtual string getName();
ActiveRunway* getRunway(string name); ActiveRunway* getRunway(string name);

View file

@ -51,9 +51,12 @@ using std::random_shuffle;
FGAirportDynamics::FGAirportDynamics(FGAirport * ap): FGAirportDynamics::FGAirportDynamics(FGAirport * ap):
_ap(ap), rwyPrefs(ap), SIDs(ap), _ap(ap), rwyPrefs(ap), SIDs(ap),
startupController (this),
towerController (this),
approachController (this),
atisSequenceIndex(-1), atisSequenceIndex(-1),
atisSequenceTimeStamp(0.0), atisSequenceTimeStamp(0.0)
startupController(this)
{ {
lastUpdate = 0; lastUpdate = 0;
} }
@ -493,25 +496,24 @@ const string & FGAirportDynamics::getId() const
int FGAirportDynamics::getGroundFrequency(unsigned leg) int FGAirportDynamics::getGroundFrequency(unsigned leg)
{ {
//return freqGround.size() ? freqGround[0] : 0; }; //return freqGround.size() ? freqGround[0] : 0; };
//cerr << "Getting frequency for : " << leg << endl;
int groundFreq = 0; int groundFreq = 0;
if (leg < 2) { if (leg < 1) {
SG_LOG(SG_ATC, SG_ALERT, SG_LOG(SG_ATC, SG_ALERT,
"Leg value is smaller than two at " << SG_ORIGIN); "Leg value is smaller than one at " << SG_ORIGIN);
} }
if (freqGround.size() == 0) { if (freqGround.size() == 0) {
return 0; return 0;
} }
if ((freqGround.size() > leg - 1) && (leg > 1)) {
groundFreq = freqGround[leg - 1]; if ((freqGround.size() < leg) && (leg > 0)) {
}
if ((freqGround.size() < leg - 1) && (leg > 1)) {
groundFreq = groundFreq =
(freqGround.size() < (freqGround.size() <
(leg - 1)) ? freqGround[freqGround.size() - (leg - 1)) ? freqGround[freqGround.size() -
1] : freqGround[leg - 2]; 1] : freqGround[leg - 1];
} }
if ((freqGround.size() >= leg - 1) && (leg > 1)) { if ((freqGround.size() >= leg) && (leg > 0)) {
groundFreq = freqGround[leg - 2]; groundFreq = freqGround[leg - 1];
} }
return groundFreq; return groundFreq;
} }

View file

@ -46,6 +46,8 @@
#include <AIModel/AIAircraft.hxx> #include <AIModel/AIAircraft.hxx>
#include <AIModel/AIFlightPlan.hxx> #include <AIModel/AIFlightPlan.hxx>
#include <ATC/atc_mgr.hxx>
#include <Scenery/scenery.hxx> #include <Scenery/scenery.hxx>
#include "groundnetwork.hxx" #include "groundnetwork.hxx"
@ -171,6 +173,7 @@ bool FGTaxiRoute::next(int *nde, int *rte)
return true; return true;
}; };
void FGTaxiRoute::rewind(int route) void FGTaxiRoute::rewind(int route)
{ {
int currPoint; int currPoint;
@ -510,6 +513,7 @@ void FGGroundNetwork::announcePosition(int id,
} }
} }
void FGGroundNetwork::signOff(int id) void FGGroundNetwork::signOff(int id)
{ {
TrafficVectorIterator i = activeTraffic.begin(); TrafficVectorIterator i = activeTraffic.begin();
@ -531,28 +535,40 @@ void FGGroundNetwork::signOff(int id)
i = activeTraffic.erase(i); i = activeTraffic.erase(i);
} }
} }
/**
* The ground network can deal with the following states:
* 0 = Normal; no action required
* 1 = "Acknowledge "Hold position
* 2 = "Acknowledge "Resume taxi".
* 3 = "Issue TaxiClearance"
* 4 = Acknowledge Taxi Clearance"
* 5 = Post acknowlegde taxiclearance: Start taxiing
* 6 = Report runway
* 7 = Acknowledge report runway
* 8 = Switch tower frequency
* 9 = Acknowledge switch tower frequency
*************************************************************************************************************************/
bool FGGroundNetwork::checkTransmissionState(int minState, int maxState, TrafficVectorIterator i, time_t now, AtcMsgId msgId, bool FGGroundNetwork::checkTransmissionState(int minState, int maxState, TrafficVectorIterator i, time_t now, AtcMsgId msgId,
AtcMsgDir msgDir) AtcMsgDir msgDir)
{ {
int state = i->getState(); int state = i->getState();
if ((state >= minState) && (state <= maxState) && available) { if ((state >= minState) && (state <= maxState) && available) {
if ((msgDir == ATC_AIR_TO_GROUND) && isUserAircraft(i->getAircraft())) { if ((msgDir == ATC_AIR_TO_GROUND) && isUserAircraft(i->getAircraft())) {
//cerr << "Checking state " << state << " for " << i->getAircraft()->getCallSign() << endl; //cerr << "Checking state " << state << " for " << i->getAircraft()->getCallSign() << endl;
static SGPropertyNode_ptr trans_num = globals->get_props()->getNode("/sim/atc/transmission-num", true); static SGPropertyNode_ptr trans_num = globals->get_props()->getNode("/sim/atc/transmission-num", true);
int n = trans_num->getIntValue(); int n = trans_num->getIntValue();
if (n == 0) { if (n == 0) {
trans_num->setIntValue(-1); trans_num->setIntValue(-1);
// PopupCallback(n); // PopupCallback(n);
cerr << "Selected transmission message " << n << endl; //cerr << "Selected transmission message " << n << endl;
FGATCManager *atc = (FGATCManager*) globals->get_subsystem("atc");
atc->getATCDialog()->removeEntry(1);
} else { } else {
//cerr << "creating message for " << i->getAircraft()->getCallSign() << endl; //cerr << "creating message for " << i->getAircraft()->getCallSign() << endl;
transmit(&(*i), msgId, msgDir, false); transmit(&(*i), msgId, msgDir, false);
return false; return false;
} }
} }
//cerr << "Transmitting startup msg" << endl;
transmit(&(*i), msgId, msgDir, true); transmit(&(*i), msgId, msgDir, true);
i->updateState(); i->updateState();
lastTransmission = now; lastTransmission = now;
@ -631,12 +647,11 @@ void FGGroundNetwork::updateAircraftInformation(int id, double lat, double lon,
if ((state == 5) && available) { if ((state == 5) && available) {
current->setState(0); current->setState(0);
current->getAircraft()->setTaxiClearanceRequest(false); current->getAircraft()->setTaxiClearanceRequest(false);
current->setHoldPosition(true); current->setHoldPosition(false);
available = false; available = false;
} }
} }
} }
/** /**
@ -720,6 +735,10 @@ void FGGroundNetwork::checkSpeedAdjustment(int id, double lat,
if (bearing > 180) if (bearing > 180)
bearing = 360 - bearing; bearing = 360 - bearing;
if ((dist < mindist) && (bearing < 60.0)) { if ((dist < mindist) && (bearing < 60.0)) {
//cerr << "Current aircraft " << current->getAircraft()->getTrafficRef()->getCallSign()
// << " is closest to " << i->getAircraft()->getTrafficRef()->getCallSign()
// << ", which has status " << i->getAircraft()->isScheduledForTakeoff()
// << endl;
mindist = dist; mindist = dist;
closest = i; closest = i;
minbearing = bearing; minbearing = bearing;
@ -728,6 +747,8 @@ void FGGroundNetwork::checkSpeedAdjustment(int id, double lat,
} }
} }
// Finally, check UserPosition // Finally, check UserPosition
// Note, as of 2011-08-01, this should no longer be necessecary.
/*
double userLatitude = fgGetDouble("/position/latitude-deg"); double userLatitude = fgGetDouble("/position/latitude-deg");
double userLongitude = fgGetDouble("/position/longitude-deg"); double userLongitude = fgGetDouble("/position/longitude-deg");
SGGeod user(SGGeod::fromDeg(userLongitude, userLatitude)); SGGeod user(SGGeod::fromDeg(userLongitude, userLatitude));
@ -742,7 +763,7 @@ void FGGroundNetwork::checkSpeedAdjustment(int id, double lat,
minbearing = bearing; minbearing = bearing;
otherReasonToSlowDown = true; otherReasonToSlowDown = true;
} }
*/
current->clearSpeedAdjustment(); current->clearSpeedAdjustment();
if (current->checkPositionAndIntentions(*closest) if (current->checkPositionAndIntentions(*closest)
@ -755,11 +776,18 @@ void FGGroundNetwork::checkSpeedAdjustment(int id, double lat,
return; return;
else else
current->setWaitsForId(closest->getId()); current->setWaitsForId(closest->getId());
if (closest->getId() != current->getId()) if (closest->getId() != current->getId()) {
current->setSpeedAdjustment(closest->getSpeed() * current->setSpeedAdjustment(closest->getSpeed() *
(mindist / 100)); (mindist / 100));
else if (
closest->getAircraft()->getTakeOffStatus() &&
(current->getAircraft()->getTrafficRef()->getDepartureAirport() == closest->getAircraft()->getTrafficRef()->getDepartureAirport()) &&
(current->getAircraft()->GetFlightPlan()->getRunway() == closest->getAircraft()->GetFlightPlan()->getRunway())
)
current->getAircraft()->scheduleForATCTowerDepartureControl(1);
} else {
current->setSpeedAdjustment(0); // This can only happen when the user aircraft is the one closest current->setSpeedAdjustment(0); // This can only happen when the user aircraft is the one closest
}
if (mindist < maxAllowableDistance) { if (mindist < maxAllowableDistance) {
//double newSpeed = (maxAllowableDistance-mindist); //double newSpeed = (maxAllowableDistance-mindist);
//current->setSpeedAdjustment(newSpeed); //current->setSpeedAdjustment(newSpeed);
@ -860,8 +888,10 @@ void FGGroundNetwork::checkHoldPosition(int id, double lat,
//(!(current->getSpeedAdjustment()))) //(!(current->getSpeedAdjustment())))
{ {
current->setHoldPosition(true); if (!(isUserAircraft(i->getAircraft()))) { // test code. Don't wait for the user, let the user wait for you.
current->setWaitsForId(i->getId()); current->setHoldPosition(true);
current->setWaitsForId(i->getId());
}
//cerr << "Hold check 5: " << current->getCallSign() <<" Setting Hold Position: distance to node (" << node << ") " //cerr << "Hold check 5: " << current->getCallSign() <<" Setting Hold Position: distance to node (" << node << ") "
// << dist << " meters. Waiting for " << i->getCallSign(); // << dist << " meters. Waiting for " << i->getCallSign();
//if (opposing) //if (opposing)
@ -879,31 +909,37 @@ void FGGroundNetwork::checkHoldPosition(int id, double lat,
} }
} }
bool currStatus = current->hasHoldPosition(); bool currStatus = current->hasHoldPosition();
current->setHoldPosition(origStatus);
// Either a Hold Position or a resume taxi transmission has been issued // Either a Hold Position or a resume taxi transmission has been issued
time_t now = time(NULL) + fgGetLong("/sim/time/warp"); time_t now = time(NULL) + fgGetLong("/sim/time/warp");
if ((now - lastTransmission) > 2) { if ((now - lastTransmission) > 2) {
available = true; available = true;
} }
if ((origStatus != currStatus) && available) { if (current->getState() == 0) {
//cerr << "Issueing hold short instrudtion " << currStatus << " " << available << endl; if ((origStatus != currStatus) && available) {
if (currStatus == true) { // No has a hold short instruction //cerr << "Issueing hold short instrudtion " << currStatus << " " << available << endl;
transmit(&(*current), MSG_HOLD_POSITION, ATC_GROUND_TO_AIR, true); if (currStatus == true) { // No has a hold short instruction
//cerr << "Transmittin hold short instrudtion " << currStatus << " " << available << endl; transmit(&(*current), MSG_HOLD_POSITION, ATC_GROUND_TO_AIR, true);
current->setState(1); //cerr << "Transmittin hold short instrudtion " << currStatus << " " << available << endl;
} else { current->setState(1);
transmit(&(*current), MSG_RESUME_TAXI, ATC_GROUND_TO_AIR, true); } else {
//cerr << "Transmittig resume instrudtion " << currStatus << " " << available << endl; transmit(&(*current), MSG_RESUME_TAXI, ATC_GROUND_TO_AIR, true);
current->setState(2); //cerr << "Transmittig resume instrudtion " << currStatus << " " << available << endl;
current->setState(2);
}
lastTransmission = now;
available = false;
// Don't act on the changed instruction until the transmission is confirmed
// So set back to original status
//cerr << "Current state " << current->getState() << endl;
} }
lastTransmission = now;
available = false;
// Don't act on the changed instruction until the transmission is confirmed
// So set back to original status
current->setHoldPosition(origStatus);
//cerr << "Current state " << current->getState() << endl;
} else {
} }
// 6 = Report runway
// 7 = Acknowledge report runway
// 8 = Switch tower frequency
//9 = Acknowledge switch tower frequency
//int state = current->getState(); //int state = current->getState();
if (checkTransmissionState(1,1, current, now, MSG_ACKNOWLEDGE_HOLD_POSITION, ATC_AIR_TO_GROUND)) { if (checkTransmissionState(1,1, current, now, MSG_ACKNOWLEDGE_HOLD_POSITION, ATC_AIR_TO_GROUND)) {
current->setState(0); current->setState(0);
@ -913,24 +949,22 @@ void FGGroundNetwork::checkHoldPosition(int id, double lat,
current->setState(0); current->setState(0);
current->setHoldPosition(false); current->setHoldPosition(false);
} }
if (current->getAircraft()->getTakeOffStatus() && (current->getState() == 0)) {
/*if ((state == 1) && (available)) { //cerr << "Scheduling " << current->getAircraft()->getCallSign() << " for hold short" << endl;
//cerr << "ACKNOWLEDGE HOLD" << endl; current->setState(6);
transmit(&(*current), MSG_ACKNOWLEDGE_HOLD_POSITION, ATC_AIR_TO_GROUND, true); }
current->setState(0); if (checkTransmissionState(6,6, current, now, MSG_REPORT_RUNWAY_HOLD_SHORT, ATC_AIR_TO_GROUND)) {
current->setHoldPosition(true);
lastTransmission = now;
available = false;
} }
if ((state == 2) && (available)) { if (checkTransmissionState(7,7, current, now, MSG_ACKNOWLEDGE_REPORT_RUNWAY_HOLD_SHORT, ATC_GROUND_TO_AIR)) {
//cerr << "ACKNOWLEDGE RESUME" << endl; }
transmit(&(*current), MSG_ACKNOWLEDGE_RESUME_TAXI, ATC_AIR_TO_GROUND, true); if (checkTransmissionState(8,8, current, now, MSG_SWITCH_TOWER_FREQUENCY, ATC_GROUND_TO_AIR)) {
current->setState(0); }
current->setHoldPosition(false); if (checkTransmissionState(9,9, current, now, MSG_ACKNOWLEDGE_SWITCH_TOWER_FREQUENCY, ATC_AIR_TO_GROUND)) {
lastTransmission = now; }
available = false;
}*/
//current->setState(0);
} }
/** /**
@ -1208,4 +1242,8 @@ void FGGroundNetwork::render(bool visible)
} }
globals->get_scenery()->get_scene_graph()->addChild(group); globals->get_scenery()->get_scene_graph()->addChild(group);
} }
} }
string FGGroundNetwork::getName() {
return string(parent->getId() + "-ground");
}

View file

@ -212,6 +212,8 @@ public:
void first() { currNode = nodes.begin(); currRoute = routes.begin(); }; void first() { currNode = nodes.begin(); currRoute = routes.begin(); };
int size() { return nodes.size(); }; int size() { return nodes.size(); };
int nodesLeft() { return nodes.end() - currNode; };
// int getDepth() { return depth; }; // int getDepth() { return depth; };
}; };
@ -288,6 +290,7 @@ public:
AtcMsgDir msgDir); AtcMsgDir msgDir);
bool checkForCircularWaits(int id); bool checkForCircularWaits(int id);
virtual void render(bool); virtual void render(bool);
virtual string getName();
}; };

View file

@ -73,23 +73,25 @@ void FGSidStar::load(SGPath filename) {
fp->setName(name); fp->setName(name);
SGPropertyNode * wpts_node = fpl_node->getNode("wpts"); SGPropertyNode * wpts_node = fpl_node->getNode("wpts");
for (int j = 0; j < wpts_node->nChildren(); j++) { for (int j = 0; j < wpts_node->nChildren(); j++) {
FGAIFlightPlan::waypoint* wpt = new FGAIFlightPlan::waypoint; FGAIWaypoint* wpt = new FGAIWaypoint;
SGPropertyNode * wpt_node = wpts_node->getChild(j); SGPropertyNode * wpt_node = wpts_node->getChild(j);
//cerr << "Reading waypoint " << j << wpt_node->getStringValue("name", "END") << endl; //cerr << "Reading waypoint " << j << wpt_node->getStringValue("name", "END") << endl;
wpt->name = wpt_node->getStringValue("name", "END"); wpt->setName (wpt_node->getStringValue("name", "END"));
wpt->latitude = wpt_node->getDoubleValue("lat", 0); wpt->setLatitude (wpt_node->getDoubleValue("lat", 0));
wpt->longitude = wpt_node->getDoubleValue("lon", 0); wpt->setLongitude (wpt_node->getDoubleValue("lon", 0));
wpt->altitude = wpt_node->getDoubleValue("alt", 0); wpt->setAltitude (wpt_node->getDoubleValue("alt", 0));
wpt->speed = wpt_node->getDoubleValue("ktas", 0); wpt->setSpeed (wpt_node->getDoubleValue("ktas", 0));
wpt->crossat = wpt_node->getDoubleValue("crossat", -10000); wpt->setCrossat (wpt_node->getDoubleValue("crossat", -10000));
wpt->gear_down = wpt_node->getBoolValue("gear-down", false); wpt->setGear_down (wpt_node->getBoolValue("gear-down", false));
wpt->flaps_down= wpt_node->getBoolValue("flaps-down", false); wpt->setFlaps_down (wpt_node->getBoolValue("flaps-down", false));
wpt->on_ground = wpt_node->getBoolValue("on-ground", false); wpt->setOn_ground (wpt_node->getBoolValue("on-ground", false));
wpt->time_sec = wpt_node->getDoubleValue("time-sec", 0); wpt->setTime_sec (wpt_node->getDoubleValue("time-sec", 0));
wpt->time = wpt_node->getStringValue("time", ""); wpt->setTime (wpt_node->getStringValue("time", ""));
if (wpt->name == "END") wpt->finished = true; if (wpt->contains("END"))
else wpt->finished = false; wpt->setFinished(true);
else
wpt->setFinished(false);
// //
fp->addWaypoint( wpt ); fp->addWaypoint( wpt );