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

@ -68,6 +68,7 @@ FGAIAircraft::FGAIAircraft(FGAISchedule *ref) :
fp = 0;
controller = 0;
prevController = 0;
towerController = 0;
dt_count = 0;
dt_elev_count = 0;
use_perf_vs = true;
@ -92,6 +93,7 @@ FGAIAircraft::FGAIAircraft(FGAISchedule *ref) :
_performance = 0; //TODO initialize to JET_TRANSPORT from PerformanceDB
dt = 0;
takeOffStatus = 0;
}
@ -249,11 +251,11 @@ void FGAIAircraft::SetFlightPlan(FGAIFlightPlan *f) {
void FGAIAircraft::ProcessFlightPlan( double dt, time_t now ) {
// the one behind you
FGAIFlightPlan::waypoint* prev = 0;
FGAIWaypoint* prev = 0;
// the one ahead
FGAIFlightPlan::waypoint* curr = 0;
FGAIWaypoint* curr = 0;
// the next plus 1
FGAIFlightPlan::waypoint* next = 0;
FGAIWaypoint* next = 0;
prev = fp->getPreviousWaypoint();
curr = fp->getCurrentWaypoint();
@ -300,7 +302,7 @@ void FGAIAircraft::ProcessFlightPlan( double dt, time_t now ) {
<< endl;
} */
} else {
if (curr->finished) //end of the flight plan
if (curr->isFinished()) //end of the flight plan
{
if (fp->getRepeat())
fp->restart();
@ -348,22 +350,22 @@ void FGAIAircraft::ProcessFlightPlan( double dt, time_t now ) {
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;
if (curr->crossat > -1000.0) {
tgt_altitude_ft = prev->getAltitude();
if (curr->getCrossat() > -1000.0) {
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);
checkTcas();
tgt_altitude_ft = curr->crossat;
tgt_altitude_ft = curr->getCrossat();
} else {
use_perf_vs = true;
}
}
AccelTo(prev->speed);
AccelTo(prev->getSpeed());
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();
}
// 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) {
int leg;
if ((leg = fp->getLeg()) == 10) {
if ((leg = fp->getLeg()) == 9) {
if (!trafficRef->next()) {
return false;
}
setCallSign(trafficRef->getCallSign());
leg = 1;
leg = 0;
fp->setLeg(leg);
}
@ -431,7 +435,7 @@ bool FGAIAircraft::loadNextLeg(double distance) {
fp->create (this,
dep,
arr,
leg,
leg+1,
cruiseAlt,
trafficRef->getSpeed(),
_getLatitude(),
@ -508,29 +512,31 @@ void FGAIAircraft::announcePositionToController() {
// 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
//
// 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) {
case 2: // Startup and Push back
case 1: // Startup and Push back
if (trafficRef->getDepartureAirport()->getDynamics())
controller = trafficRef->getDepartureAirport()->getDynamics()->getStartupController();
break;
case 3: // Taxiing to runway
case 2: // Taxiing to runway
if (trafficRef->getDepartureAirport()->getDynamics()->getGroundNetwork()->exists())
controller = trafficRef->getDepartureAirport()->getDynamics()->getGroundNetwork();
break;
case 4: //Take off tower controller
case 3: //Take off tower controller
if (trafficRef->getDepartureAirport()->getDynamics()) {
controller = trafficRef->getDepartureAirport()->getDynamics()->getTowerController();
} else {
cerr << "Error: Could not find Dynamics at airport : " << trafficRef->getDepartureAirport()->getId() << endl;
}
break;
case 7:
case 6:
if (trafficRef->getDepartureAirport()->getDynamics()) {
controller = trafficRef->getArrivalAirport()->getDynamics()->getApproachController();
}
break;
case 9: // Taxiing for parking
case 8: // Taxiing for parking
if (trafficRef->getArrivalAirport()->getDynamics()->getGroundNetwork()->exists())
controller = trafficRef->getArrivalAirport()->getDynamics()->getGroundNetwork();
break;
@ -544,13 +550,33 @@ void FGAIAircraft::announcePositionToController() {
}
prevController = controller;
if (controller) {
controller->announcePosition(getID(), fp, fp->getCurrentWaypoint()->routeIndex,
controller->announcePosition(getID(), fp, fp->getCurrentWaypoint()->getRouteIndex(),
_getLatitude(), _getLongitude(), hdg, speed, altitude_ft,
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
void FGAIAircraft::processATC(FGATCInstruction instruction) {
@ -587,7 +613,7 @@ void FGAIAircraft::processATC(FGATCInstruction instruction) {
//cerr << trafficRef->getCallSign() << " Changing Speed " << endl;
AccelTo(instruction.getSpeed());
} else {
if (fp) AccelTo(fp->getPreviousWaypoint()->speed);
if (fp) AccelTo(fp->getPreviousWaypoint()->getSpeed());
}
}
if (instruction.getChangeHeading ()) {
@ -612,9 +638,9 @@ void FGAIAircraft::handleFirstWaypoint() {
eraseWaypoints = false;
}
FGAIFlightPlan::waypoint* prev = 0; // the one behind you
FGAIFlightPlan::waypoint* curr = 0; // the one ahead
FGAIFlightPlan::waypoint* next = 0;// the next plus 1
FGAIWaypoint* prev = 0; // the one behind you
FGAIWaypoint* curr = 0; // the one ahead
FGAIWaypoint* next = 0;// the next plus 1
spinCounter = 0;
tempReg = "";
@ -631,15 +657,15 @@ void FGAIAircraft::handleFirstWaypoint() {
curr = fp->getCurrentWaypoint(); //second waypoint
next = fp->getNextWaypoint(); //third waypoint (might not exist!)
setLatitude(prev->latitude);
setLongitude(prev->longitude);
setSpeed(prev->speed);
setAltitude(prev->altitude);
setLatitude(prev->getLatitude());
setLongitude(prev->getLongitude());
setSpeed(prev->getSpeed());
setAltitude(prev->getAltitude());
if (prev->speed > 0.0)
setHeading(fp->getBearing(prev->latitude, prev->longitude, curr));
if (prev->getSpeed() > 0.0)
setHeading(fp->getBearing(prev->getLatitude(), prev->getLongitude(), curr));
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
// AI/Trafficmanager created plans,
@ -647,20 +673,20 @@ void FGAIAircraft::handleFirstWaypoint() {
if (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;
tgt_vs = (curr->crossat - prev->altitude)
tgt_vs = (curr->getCrossat() - prev->getAltitude())
/ (fp->getDistanceToGo(pos.getLatitudeDeg(), pos.getLongitudeDeg(), curr)
/ 6076.0 / prev->speed*60.0);
/ 6076.0 / prev->getSpeed()*60.0);
checkTcas();
tgt_altitude_ft = curr->crossat;
tgt_altitude_ft = curr->getCrossat();
} else {
use_perf_vs = true;
tgt_altitude_ft = prev->altitude;
tgt_altitude_ft = prev->getAltitude();
}
alt_lock = hdg_lock = true;
no_roll = prev->on_ground;
no_roll = prev->getOn_ground();
if (no_roll) {
Transform(); // make sure aip is initialized.
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
* @return
*/
bool FGAIAircraft::leadPointReached(FGAIFlightPlan::waypoint* curr) {
bool FGAIAircraft::leadPointReached(FGAIWaypoint* curr) {
double dist_to_go = fp->getDistanceToGo(pos.getLatitudeDeg(), pos.getLongitudeDeg(), curr);
//cerr << "2" << endl;
double lead_dist = fp->getLeadDistance();
// 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);
if (tgt_speed > -0.5) {
tgt_speed = -0.5;
}
if (fp->getPreviousWaypoint()->speed < tgt_speed) {
fp->getPreviousWaypoint()->speed = tgt_speed;
if (fp->getPreviousWaypoint()->getSpeed() < tgt_speed) {
fp->getPreviousWaypoint()->setSpeed(tgt_speed);
}
}
if (lead_dist < fabs(2*speed)) {
@ -768,7 +794,7 @@ bool FGAIAircraft::aiTrafficVisible() {
*/
//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
FGAirport * dep = trafficRef->getDepartureAirport();
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
// departure waypoint, so it can release the parking.
//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());
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
// 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();
// make sure to wait at least 20 minutes at parking to prevent "nervous" taxi behavior
if (nextDeparture < (now+1200)) {
nextDeparture = now + 1200;
}
fp->setTime(nextDeparture); // should be "next departure"
fp->setTime(nextDeparture);
}
return true;
@ -805,7 +839,7 @@ bool FGAIAircraft::handleAirportEndPoints(FGAIFlightPlan::waypoint* prev, time_t
*
* @param curr
*/
void FGAIAircraft::controlHeading(FGAIFlightPlan::waypoint* curr) {
void FGAIAircraft::controlHeading(FGAIWaypoint* curr) {
double calc_bearing = fp->getBearing(pos.getLatitudeDeg(), pos.getLongitudeDeg(), curr);
//cerr << "Bearing = " << calc_bearing << endl;
if (speed < 0) {
@ -824,8 +858,8 @@ void FGAIAircraft::controlHeading(FGAIFlightPlan::waypoint* curr) {
cerr << "calc_bearing is not a finite number : "
<< "Speed " << speed
<< "pos : " << pos.getLatitudeDeg() << ", " << pos.getLongitudeDeg()
<< "waypoint " << curr->latitude << ", " << curr->longitude << endl;
cerr << "waypoint name " << curr->name;
<< "waypoint " << curr->getLatitude() << ", " << curr->getLongitude() << endl;
cerr << "waypoint name " << curr->getName();
exit(1); // FIXME
}
}
@ -838,7 +872,7 @@ void FGAIAircraft::controlHeading(FGAIFlightPlan::waypoint* curr) {
* @param curr
* @param next
*/
void FGAIAircraft::controlSpeed(FGAIFlightPlan::waypoint* curr, FGAIFlightPlan::waypoint* next) {
void FGAIAircraft::controlSpeed(FGAIWaypoint* curr, FGAIWaypoint* next) {
double speed_diff = speed - prevSpeed;
if (fabs(speed_diff) > 10) {
@ -1168,8 +1202,8 @@ void FGAIAircraft::updateSecondaryTargetValues() {
bool FGAIAircraft::reachedEndOfCruise(double &distance) {
FGAIFlightPlan::waypoint* curr = fp->getCurrentWaypoint();
if (curr->name == "BOD") {
FGAIWaypoint* curr = fp->getCurrentWaypoint();
if (curr->getName() == string("BOD")) {
double dist = fp->getDistanceToGo(pos.getLatitudeDeg(), pos.getLongitudeDeg(), curr);
double descentSpeed = (getPerformance()->vDescent() * SG_NM_TO_METER) / 3600.0; // convert from kts to meter/s
double descentRate = (getPerformance()->descentRate() * SG_FEET_TO_METER) / 60.0; // convert from feet/min to meter/s
@ -1205,22 +1239,22 @@ bool FGAIAircraft::reachedEndOfCruise(double &distance) {
void FGAIAircraft::resetPositionFromFlightPlan()
{
// the one behind you
FGAIFlightPlan::waypoint* prev = 0;
FGAIWaypoint* prev = 0;
// the one ahead
FGAIFlightPlan::waypoint* curr = 0;
FGAIWaypoint* curr = 0;
// the next plus 1
FGAIFlightPlan::waypoint* next = 0;
FGAIWaypoint* next = 0;
prev = fp->getPreviousWaypoint();
curr = fp->getCurrentWaypoint();
next = fp->getNextWaypoint();
setLatitude(prev->latitude);
setLongitude(prev->longitude);
setLatitude(prev->getLatitude());
setLongitude(prev->getLongitude());
double tgt_heading = fp->getBearing(curr, next);
setHeading(tgt_heading);
setAltitude(prev->altitude);
setSpeed(prev->speed);
setAltitude(prev->getAltitude());
setSpeed(prev->getSpeed());
}
double FGAIAircraft::getBearing(double crse)
@ -1232,7 +1266,7 @@ double FGAIAircraft::getBearing(double crse)
}
time_t FGAIAircraft::checkForArrivalTime(string wptName) {
FGAIFlightPlan::waypoint* curr = 0;
FGAIWaypoint* curr = 0;
curr = fp->getCurrentWaypoint();
double tracklength = fp->checkTrackLength(wptName);

View file

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

View file

@ -46,6 +46,29 @@
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()
{
rwy = 0;
@ -88,22 +111,22 @@ FGAIFlightPlan::FGAIFlightPlan(const string& filename)
SGPropertyNode * node = root.getNode("flightplan");
for (i = 0; i < node->nChildren(); i++) {
//cout << "Reading waypoint " << i << endl;
waypoint* wpt = new waypoint;
FGAIWaypoint* wpt = new FGAIWaypoint;
SGPropertyNode * wpt_node = node->getChild(i);
wpt->name = wpt_node->getStringValue("name", "END");
wpt->latitude = wpt_node->getDoubleValue("lat", 0);
wpt->longitude = wpt_node->getDoubleValue("lon", 0);
wpt->altitude = wpt_node->getDoubleValue("alt", 0);
wpt->speed = wpt_node->getDoubleValue("ktas", 0);
wpt->crossat = wpt_node->getDoubleValue("crossat", -10000);
wpt->gear_down = wpt_node->getBoolValue("gear-down", false);
wpt->flaps_down= wpt_node->getBoolValue("flaps-down", false);
wpt->on_ground = wpt_node->getBoolValue("on-ground", false);
wpt->time_sec = wpt_node->getDoubleValue("time-sec", 0);
wpt->time = wpt_node->getStringValue("time", "");
wpt->setName (wpt_node->getStringValue("name", "END" ));
wpt->setLatitude (wpt_node->getDoubleValue("lat", 0 ));
wpt->setLongitude (wpt_node->getDoubleValue("lon", 0 ));
wpt->setAltitude (wpt_node->getDoubleValue("alt", 0 ));
wpt->setSpeed (wpt_node->getDoubleValue("ktas", 0 ));
wpt->setCrossat (wpt_node->getDoubleValue("crossat", -10000 ));
wpt->setGear_down (wpt_node->getBoolValue("gear-down", false ));
wpt->setFlaps_down (wpt_node->getBoolValue("flaps-down", false ));
wpt->setOn_ground (wpt_node->getBoolValue("on-ground", false ));
wpt->setTime_sec (wpt_node->getDoubleValue("time-sec", 0 ));
wpt->setTime (wpt_node->getStringValue("time", "" ));
if (wpt->name == "END") wpt->finished = true;
else wpt->finished = false;
if (wpt->getName() == "END") wpt->setFinished(true);
else wpt->setFinished(false);
waypoints.push_back( wpt );
}
@ -173,20 +196,19 @@ FGAIFlightPlan::FGAIFlightPlan(FGAIAircraft *ac,
//waypoints.push_back( init_waypoint );
for (int i = 0; i < node->nChildren(); i++) {
//cout << "Reading waypoint " << i << endl;
waypoint* wpt = new waypoint;
FGAIWaypoint* wpt = new FGAIWaypoint;
SGPropertyNode * wpt_node = node->getChild(i);
wpt->name = wpt_node->getStringValue("name", "END");
wpt->latitude = wpt_node->getDoubleValue("lat", 0);
wpt->longitude = wpt_node->getDoubleValue("lon", 0);
wpt->altitude = wpt_node->getDoubleValue("alt", 0);
wpt->speed = wpt_node->getDoubleValue("ktas", 0);
//wpt->speed = speed;
wpt->crossat = wpt_node->getDoubleValue("crossat", -10000);
wpt->gear_down = wpt_node->getBoolValue("gear-down", false);
wpt->flaps_down= wpt_node->getBoolValue("flaps-down", false);
wpt->setName (wpt_node->getStringValue("name", "END" ));
wpt->setLatitude (wpt_node->getDoubleValue("lat", 0 ));
wpt->setLongitude (wpt_node->getDoubleValue("lon", 0 ));
wpt->setAltitude (wpt_node->getDoubleValue("alt", 0 ));
wpt->setSpeed (wpt_node->getDoubleValue("ktas", 0 ));
wpt->setCrossat (wpt_node->getDoubleValue("crossat", -10000 ));
wpt->setGear_down (wpt_node->getBoolValue("gear-down", false ));
wpt->setFlaps_down (wpt_node->getBoolValue("flaps-down", false ));
if (wpt->name == "END") wpt->finished = true;
else wpt->finished = false;
if (wpt->getName() == "END") wpt->setFinished(true);
else wpt->setFinished(false);
waypoints.push_back(wpt);
} // of node loop
wpt_iterator = waypoints.begin();
@ -204,8 +226,10 @@ FGAIFlightPlan::FGAIFlightPlan(FGAIAircraft *ac,
if ((timeDiff > 60) && (timeDiff < 1200))
leg = 2;
else if ((timeDiff >= 1200) && (timeDiff < 1500))
else if ((timeDiff >= 1200) && (timeDiff < 1500)) {
leg = 3;
ac->setTakeOffStatus(2);
}
else if ((timeDiff >= 1500) && (timeDiff < 2000))
leg = 4;
else if (timeDiff >= 2000)
@ -324,8 +348,7 @@ FGAIFlightPlan::~FGAIFlightPlan()
}
FGAIFlightPlan::waypoint* const
FGAIFlightPlan::getPreviousWaypoint( void ) const
FGAIWaypoint* const FGAIFlightPlan::getPreviousWaypoint( void ) const
{
if (wpt_iterator == waypoints.begin()) {
return 0;
@ -335,14 +358,12 @@ FGAIFlightPlan::getPreviousWaypoint( void ) const
}
}
FGAIFlightPlan::waypoint* const
FGAIFlightPlan::getCurrentWaypoint( void ) const
FGAIWaypoint* const FGAIFlightPlan::getCurrentWaypoint( void ) const
{
return *wpt_iterator;
}
FGAIFlightPlan::waypoint* const
FGAIFlightPlan::getNextWaypoint( void ) const
FGAIWaypoint* const FGAIFlightPlan::getNextWaypoint( void ) const
{
wpt_vector_iterator i = waypoints.end();
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
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),
SGGeod::fromDeg(wp->longitude, wp->latitude));
SGGeod::fromDeg(wp->getLongitude(), wp->getLatitude()));
}
// sets distance in feet from a lead point to the current waypoint
void FGAIFlightPlan::setLeadDistance(double speed, double bearing,
waypoint* current, waypoint* next){
FGAIWaypoint* current, FGAIWaypoint* next){
double turn_radius;
// Handle Ground steering
// 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{
return getBearing(first->latitude, first->longitude, second);
double FGAIFlightPlan::getBearing(FGAIWaypoint* first, FGAIWaypoint* second) const{
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),
SGGeod::fromDeg(wp->longitude, wp->latitude));
SGGeod::fromDeg(wp->getLongitude(), wp->getLatitude()));
}
void FGAIFlightPlan::deleteWaypoints()
@ -469,19 +490,19 @@ void FGAIFlightPlan::resetWaypoints()
return;
else
{
waypoint *wpt = new waypoint;
FGAIWaypoint *wpt = new FGAIWaypoint;
wpt_vector_iterator i = waypoints.end();
i--;
wpt->name = (*i)->name;
wpt->latitude = (*i)->latitude;
wpt->longitude = (*i)->longitude;
wpt->altitude = (*i)->altitude;
wpt->speed = (*i)->speed;
wpt->crossat = (*i)->crossat;
wpt->gear_down = (*i)->gear_down;
wpt->flaps_down= (*i)->flaps_down;
wpt->finished = false;
wpt->on_ground = (*i)->on_ground;
wpt->setName ( (*i)->getName() );
wpt->setLatitude ( (*i)->getLatitude() );
wpt->setLongitude ( (*i)->getLongitude() );
wpt->setAltitude ( (*i)->getAltitude() );
wpt->setSpeed ( (*i)->getSpeed() );
wpt->setCrossat ( (*i)->getCrossat() );
wpt->setGear_down ( (*i)->getGear_down() );
wpt->setFlaps_down ( (*i)->getFlaps_down() );
wpt->setFinished ( false );
wpt->setOn_ground ( (*i)->getOn_ground() );
//cerr << "Recycling waypoint " << wpt->name << endl;
deleteWaypoints();
waypoints.push_back(wpt);
@ -504,7 +525,7 @@ void FGAIFlightPlan::deleteTaxiRoute()
int FGAIFlightPlan::getRouteIndex(int i) {
if ((i > 0) && (i < (int)waypoints.size())) {
return waypoints[i]->routeIndex;
return waypoints[i]->getRouteIndex();
}
else
return 0;
@ -517,8 +538,8 @@ double FGAIFlightPlan::checkTrackLength(string wptName) {
wpt_vector_iterator wptvec = waypoints.begin();
wptvec++;
wptvec++;
while ((wptvec != waypoints.end()) && ((*wptvec)->name != wptName)) {
trackDistance += (*wptvec)->trackLength;
while ((wptvec != waypoints.end()) && (!((*wptvec)->contains(wptName)))) {
trackDistance += (*wptvec)->getTrackLength();
wptvec++;
}
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
// - davidculp2@comcast.net
//
@ -30,11 +30,8 @@ class FGAIAircraft;
class FGAirport;
class SGGeod;
class FGAIFlightPlan {
public:
typedef struct {
class FGAIWaypoint {
private:
std::string name;
double latitude;
double longitude;
@ -47,10 +44,52 @@ public:
bool on_ground;
int routeIndex; // For AI/ATC purposes;
double time_sec;
double trackLength; // distance from previous waypoint (for AI purposes);
double trackLength; // distance from previous FGAIWaypoint (for AI purposes);
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(const std::string& filename);
FGAIFlightPlan(FGAIAircraft *,
@ -70,19 +109,20 @@ public:
const std::string& airline);
~FGAIFlightPlan();
waypoint* const getPreviousWaypoint( void ) const;
waypoint* const getCurrentWaypoint( void ) const;
waypoint* const getNextWaypoint( void ) const;
FGAIWaypoint* const getPreviousWaypoint( void ) const;
FGAIWaypoint* const getCurrentWaypoint( void ) const;
FGAIWaypoint* const getNextWaypoint( void ) const;
void IncrementWaypoint( 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;};
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);
double getLeadDistance( void ) const {return lead_distance;}
double getBearing(waypoint* previous, waypoint* next) const;
double getBearing(double lat, double lon, waypoint* next) const;
double getBearing(FGAIWaypoint* previous, FGAIWaypoint* next) const;
double getBearing(double lat, double lon, FGAIWaypoint* next) const;
double checkTrackLength(std::string wptName);
time_t getStartTime() const { return start_time; }
time_t getArrivalTime() const { return arrivalTime; }
@ -110,21 +150,25 @@ public:
std::string getRunway() { return activeRunway; }
bool isActive(time_t time) {return time >= this->getStartTime();}
void incrementLeg() { leg++;};
void setRunway(std::string rwy) { activeRunway = rwy; };
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; };
std::string getName() { return name; };
void setSID(FGAIFlightPlan* fp) { sid = fp;};
FGAIFlightPlan* getSID() { return sid; };
FGAIWaypoint *getWayPoint(int i) { return waypoints[i]; };
FGAIWaypoint *getLastWaypoint() { return waypoints.back(); };
private:
FGRunway* rwy;
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;
@ -160,10 +204,10 @@ private:
double getTurnRadius(double, bool);
waypoint* createOnGround(FGAIAircraft *, const std::string& aName, const SGGeod& aPos, double aElev, double aSpeed);
waypoint* createInAir(FGAIAircraft *, const std::string& aName, const SGGeod& aPos, double aElev, double aSpeed);
waypoint* cloneWithPos(FGAIAircraft *, waypoint* aWpt, const std::string& aName, const SGGeod& aPos);
waypoint* clone(waypoint* aWpt);
FGAIWaypoint* createOnGround(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);
FGAIWaypoint* cloneWithPos(FGAIAircraft *, FGAIWaypoint* aWpt, const std::string& aName, const SGGeod& aPos);
FGAIWaypoint* clone(FGAIWaypoint* aWpt);
//void createCruiseFallback(bool, FGAirport*, FGAirport*, double, double, double, double);

View file

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

View file

@ -1,4 +1,4 @@
/******************************************************************************
/****************************************************************************
* AIFlightPlanCreatePushBack.cxx
* Written by Durk Talsma, started August 1, 2007.
*
@ -74,22 +74,10 @@ bool FGAIFlightPlan::createPushBack(FGAIAircraft *ac,
return false;
char buffer[10];
snprintf (buffer, 10, "%d", gateId);
SGGeod coord = coord.fromDeg(lon, lat);
//FGTaxiNode *tn = dep->getDynamics()->getGroundNetwork()->findNode(node);
waypoint *wpt;
wpt = new waypoint;
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;
FGAIWaypoint *wpt = createOnGround(ac, string(buffer), coord, dep->getElevation(), vTaxiBackward);
wpt->setRouteIndex(-1);
waypoints.push_back(wpt);
}
//cerr << "Success : GateId = " << gateId << endl;
@ -119,7 +107,7 @@ bool FGAIFlightPlan::createPushBack(FGAIAircraft *ac,
pushBackRoute = parking->getPushBackRoute();
if ((pushBackNode > 0) && (pushBackRoute == 0)) {
if ((pushBackNode > 0) && (pushBackRoute == 0)) { // Load the already established route for this gate
int node, rte;
FGTaxiRoute route;
//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);
}
pushBackRoute->first();
waypoint *wpt;
while(pushBackRoute->next(&node, &rte))
{
//FGTaxiNode *tn = apt->getDynamics()->getGroundNetwork()->findSegment(node)->getEnd();
@ -142,122 +129,20 @@ bool FGAIFlightPlan::createPushBack(FGAIAircraft *ac,
snprintf (buffer, 10, "%d", node);
FGTaxiNode *tn = dep->getDynamics()->getGroundNetwork()->findNode(node);
//ids.pop_back();
wpt = new waypoint;
wpt->name = string(buffer); // fixme: should be the name of the taxiway
wpt->latitude = tn->getLatitude();
wpt->longitude = tn->getLongitude();
// 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 = rte;
//wpt = new waypoint;
SGGeod coord = coord.fromDeg(tn->getLongitude(), tn->getLatitude());
FGAIWaypoint *wpt = createOnGround(ac, string(buffer), coord, dep->getElevation(), vTaxiBackward);
wpt->setRouteIndex(rte);
waypoints.push_back(wpt);
}
// some special considerations for the last point:
wpt->name = string("PushBackPoint");
wpt->speed = vTaxi;
//for (wpt_vector_iterator i = waypoints.begin(); i != waypoints.end(); i++) {
// cerr << "Waypoint Name: " << (*i)->name << endl;
//}
} 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;
*/
waypoints.back()->setName(string("PushBackPoint"));
waypoints.back()->setSpeed(vTaxi);
ac->setTaxiClearanceRequest(true);
} else { // In case of a push forward departure...
ac->setTaxiClearanceRequest(false);
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;
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");
exit(1);
}
wpt = new waypoint;
wpt->name = "PushBackPoint";
wpt->latitude = tn->getLatitude();
wpt->longitude = 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();
double distance = (*ts)->getLength();
//cerr << "Length of push forward route = " << distance << " and heading is " << heading << endl;
lat2 = tn->getLatitude();
lon2 = tn->getLongitude();
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;
}
@ -322,50 +213,25 @@ void FGAIFlightPlan::createPushBackFallBack(FGAIAircraft *ac, bool firstFlight,
heading += 180.0;
if (heading > 360)
heading -= 360;
waypoint *wpt = new waypoint;
wpt->name = "park";
wpt->latitude = lat;
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;
SGGeod coord = coord.fromDeg(lon, lat);
FGAIWaypoint *wpt = createOnGround(ac, string("park"), coord, dep->getElevation(), vTaxiBackward);
waypoints.push_back(wpt);
geo_direct_wgs_84 ( 0, lat, lon, heading,
10,
&lat2, &lon2, &az2 );
wpt = new waypoint;
wpt->name = "park2";
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;
coord = coord.fromDeg(lon2, lat2);
wpt = createOnGround(ac, string("park2"), coord, dep->getElevation(), vTaxiBackward);
waypoints.push_back(wpt);
geo_direct_wgs_84 ( 0, lat, lon, heading,
2.2*radius,
&lat2, &lon2, &az2 );
wpt = new waypoint;
wpt->name = "taxiStart";
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;
coord = coord.fromDeg(lon2, lat2);
wpt = createOnGround(ac, string("taxiStart"), coord, dep->getElevation(), vTaxiReduced);
waypoints.push_back(wpt);
}

View file

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

View file

@ -572,25 +572,25 @@ void FGAIShip::setTunnel(bool t) {
void FGAIShip::setWPNames() {
if (prev != 0)
setPrevName(prev->name);
setPrevName(prev->getName());
else
setPrevName("");
if (curr != 0)
setCurrName(curr->name);
setCurrName(curr->getName());
else{
setCurrName("");
SG_LOG(SG_GENERAL, SG_ALERT, "AIShip: current wp name error" );
}
if (next != 0)
setNextName(next->name);
setNextName(next->getName());
else
setNextName("");
SG_LOG(SG_GENERAL, SG_DEBUG, "AIShip: prev wp name " << prev->name);
SG_LOG(SG_GENERAL, SG_DEBUG, "AIShip: current wp name " << curr->name);
SG_LOG(SG_GENERAL, SG_DEBUG, "AIShip: next wp name " << next->name);
SG_LOG(SG_GENERAL, SG_DEBUG, "AIShip: prev wp name " << prev->getName());
SG_LOG(SG_GENERAL, SG_DEBUG, "AIShip: current wp name " << curr->getName());
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
// if the range to the waypoint is less than the calculated turn
// 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;
double sp_turn_radius_nm = _sp_turn_radius_ft / 6076.1155;
// we need to try to identify a _missed waypoint
@ -687,8 +687,8 @@ void FGAIShip::ProcessFlightPlan(double dt) {
fp->IncrementWaypoint(false);
next = fp->getNextWaypoint();
if (next->name == "WAITUNTIL" || next->name == "WAIT"
|| next->name == "END" || next->name == "TUNNEL")
if (next->getName() == "WAITUNTIL" || next->getName() == "WAIT"
|| next->getName() == "END" || next->getName() == "TUNNEL")
return;
prev = curr;
@ -705,13 +705,13 @@ void FGAIShip::ProcessFlightPlan(double dt) {
curr = fp->getCurrentWaypoint();
next = fp->getNextWaypoint();
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;
_range_rate = 0;
_new_waypoint = true;
_missed_count = 0;
_lead_angle = 0;
AccelTo(prev->speed);
AccelTo(prev->getSpeed());
} else if (_restart){
SG_LOG(SG_GENERAL, SG_INFO, "AIShip: " << _name << " Flightplan restarting ");
_missed_count = 0;
@ -725,7 +725,7 @@ void FGAIShip::ProcessFlightPlan(double dt) {
} 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 ");
setSpeed(0);
_waiting = true;
@ -741,8 +741,8 @@ void FGAIShip::ProcessFlightPlan(double dt) {
fp->IncrementWaypoint(false);
next = fp->getNextWaypoint();
if (next->name == "WAITUNTIL" || next->name == "WAIT"
|| next->name == "END" || next->name == "TUNNEL")
if (next->getName() == "WAITUNTIL" || next->getName() == "WAIT"
|| next->getName() == "END" || next->getName() == "TUNNEL")
return;
prev = curr;
@ -753,12 +753,12 @@ void FGAIShip::ProcessFlightPlan(double dt) {
} else if (_next_name == "WAITUNTIL") {
time_sec = getDaySeconds();
until_time_sec = processTimeString(next->time);
_until_time = next->time;
setUntilTime(next->time);
until_time_sec = processTimeString(next->getTime());
_until_time = next->getTime();
setUntilTime(next->getTime());
if (until_time_sec > time_sec) {
SG_LOG(SG_GENERAL, SG_INFO, "AIShip: " << _name << " "
<< curr->name << " waiting until: "
<< curr->getName() << " waiting until: "
<< _until_time << " " << until_time_sec << " now " << time_sec );
setSpeed(0);
_lead_angle = 0;
@ -770,12 +770,12 @@ void FGAIShip::ProcessFlightPlan(double dt) {
setUntilTime("");
fp->IncrementWaypoint(false);
while (next->name == "WAITUNTIL") {
while (next->getName() == "WAITUNTIL") {
fp->IncrementWaypoint(false);
next = fp->getNextWaypoint();
}
if (next->name == "WAIT")
if (next->getName() == "WAIT")
return;
prev = curr;
@ -799,23 +799,23 @@ void FGAIShip::ProcessFlightPlan(double dt) {
_missed_count = 0;
_range_rate = 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;
setWPPos();
object_type type = getType();
if (type != 10)
AccelTo(prev->speed);
AccelTo(prev->getSpeed());
_curr_alt = curr->altitude;
_prev_alt = prev->altitude;
_curr_alt = curr->getAltitude();
_prev_alt = prev->getAltitude();
} else {
_new_waypoint = false;
}
// 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))
TurnTo(_course);
@ -840,7 +840,7 @@ bool FGAIShip::initFlightPlan() {
curr = fp->getCurrentWaypoint(); //second waypoint
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 ");
fp->IncrementWaypoint(false);
curr = fp->getCurrentWaypoint();
@ -874,14 +874,14 @@ bool FGAIShip::initFlightPlan() {
}
} else {
setLatitude(prev->latitude);
setLongitude(prev->longitude);
setSpeed(prev->speed);
setLatitude(prev->getLatitude());
setLongitude(prev->getLongitude());
setSpeed(prev->getSpeed());
}
setWPNames();
setHeading(getCourse(prev->latitude, prev->longitude, curr->latitude, curr->longitude));
_wp_range = getRange(prev->latitude, prev->longitude, curr->latitude, curr->longitude);
setHeading(getCourse(prev->getLatitude(), prev->getLongitude(), curr->getLatitude(), curr->getLongitude()));
_wp_range = getRange(prev->getLatitude(), prev->getLongitude(), curr->getLatitude(), curr->getLongitude());
_old_range = _wp_range;
_range_rate = 0;
_hdg_lock = true;
@ -941,7 +941,7 @@ bool FGAIShip::advanceFlightPlan (double start_sec, double day_sec) {
while ( elapsed_sec < day_sec ) {
if (next->name == "END" || fp->getNextWaypoint() == 0) {
if (next->getName() == "END" || fp->getNextWaypoint() == 0) {
if (_repeat ) {
//cout << _name << ": " << "restarting flightplan" << endl;
@ -954,11 +954,11 @@ bool FGAIShip::advanceFlightPlan (double start_sec, double day_sec) {
return false;
}
} else if (next->name == "WAIT") {
} else if (next->getName() == "WAIT") {
//cout << _name << ": begin WAIT: " << prev->name << " ";
//cout << curr->name << " " << next->name << endl;
elapsed_sec += next->time_sec;
elapsed_sec += next->getTime_sec();
if ( elapsed_sec >= day_sec)
continue;
@ -966,16 +966,16 @@ bool FGAIShip::advanceFlightPlan (double start_sec, double day_sec) {
fp->IncrementWaypoint(false);
next = fp->getNextWaypoint();
if (next->name != "WAITUNTIL" && next->name != "WAIT"
&& next->name != "END") {
if (next->getName() != "WAITUNTIL" && next->getName() != "WAIT"
&& next->getName() != "END") {
prev = curr;
fp->IncrementWaypoint(false);
curr = fp->getCurrentWaypoint();
next = fp->getNextWaypoint();
}
} else if (next->name == "WAITUNTIL") {
double until_sec = processTimeString(next->time);
} else if (next->getName() == "WAITUNTIL") {
double until_sec = processTimeString(next->getTime());
if (until_sec > _start_sec && start_sec < 0)
until_sec -= _day;
@ -989,7 +989,7 @@ bool FGAIShip::advanceFlightPlan (double start_sec, double day_sec) {
fp->IncrementWaypoint(false);
next = fp->getNextWaypoint();
if (next->name != "WAITUNTIL" && next->name != "WAIT") {
if (next->getName() != "WAITUNTIL" && next->getName() != "WAIT") {
prev = curr;
fp->IncrementWaypoint(false);
curr = fp->getCurrentWaypoint();
@ -1000,8 +1000,8 @@ bool FGAIShip::advanceFlightPlan (double start_sec, double day_sec) {
//cout << prev->name << " " << curr->name << " " << next->name << endl;
} else {
distance_nm = getRange(prev->latitude, prev->longitude, curr->latitude, curr->longitude);
elapsed_sec += distance_nm * 60 * 60 / prev->speed;
distance_nm = getRange(prev->getLatitude(), prev->getLongitude(), curr->getLatitude(), curr->getLongitude());
elapsed_sec += distance_nm * 60 * 60 / prev->getSpeed();
if (elapsed_sec >= day_sec)
continue;
@ -1026,31 +1026,31 @@ bool FGAIShip::advanceFlightPlan (double start_sec, double day_sec) {
//cout << " time diff " << time_diff << endl;
if (next->name == "WAIT" ){
if (next->getName() == "WAIT" ){
setSpeed(0);
lat = curr->latitude;
lon = curr->longitude;
lat = curr->getLatitude();
lon = curr->getLongitude();
_wait_count= time_diff;
_waiting = true;
} else if (next->name == "WAITUNTIL") {
} else if (next->getName() == "WAITUNTIL") {
setSpeed(0);
lat = curr->latitude;
lon = curr->longitude;
lat = curr->getLatitude();
lon = curr->getLongitude();
_waiting = true;
} else {
setSpeed(prev->speed);
setSpeed(prev->getSpeed());
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 << " "
// << " lat " << curr->latitude << " lon " << curr->longitude
// << " 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 );
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 );
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 );
}
@ -1062,18 +1062,18 @@ bool FGAIShip::advanceFlightPlan (double start_sec, double day_sec) {
void FGAIShip::setWPPos() {
if (curr->name == "END" || curr->name == "WAIT"
|| curr->name == "WAITUNTIL" || curr->name == "TUNNEL"){
if (curr->getName() == "END" || curr->getName() == "WAIT"
|| curr->getName() == "WAITUNTIL" || curr->getName() == "TUNNEL"){
//cout << curr->name << " returning" << endl;
return;
}
double elevation_m = 0;
wppos.setLatitudeDeg(curr->latitude);
wppos.setLongitudeDeg(curr->longitude);
wppos.setLatitudeDeg(curr->getLatitude());
wppos.setLongitudeDeg(curr->getLongitude());
wppos.setElevationM(0);
if (curr->on_ground){
if (curr->getOn_ground()){
if (globals->get_scenery()->get_elevation_m(SGGeod::fromGeodM(wppos, 3000),
elevation_m, &_material, 0)){
@ -1083,20 +1083,20 @@ void FGAIShip::setWPPos() {
//cout << curr->name << " setting measured elev " << elevation_m << endl;
} else {
wppos.setElevationM(curr->altitude);
wppos.setElevationM(curr->getAltitude());
//cout << curr->name << " setting FP elev " << elevation_m << endl;
}
curr->altitude = wppos.getElevationM();
curr->setAltitude(wppos.getElevationM());
}
void FGAIShip::setXTrackError() {
double course = getCourse(prev->latitude, prev->longitude,
curr->latitude, curr->longitude);
double course = getCourse(prev->getLatitude(), prev->getLongitude(),
curr->getLatitude(), curr->getLongitude());
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 factor = -0.0045 * speed + 1;
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 _dt_count, _next_run;
FGAIFlightPlan::waypoint* prev; // the one behind you
FGAIFlightPlan::waypoint* curr; // the one ahead
FGAIFlightPlan::waypoint* next; // the next plus 1
FGAIWaypoint* prev; // the one behind you
FGAIWaypoint* curr; // the one ahead
FGAIWaypoint* next; // the next plus 1
protected:

View file

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

View file

@ -49,7 +49,7 @@ class FGATCManager : public SGSubsystem
private:
AtcVec activeStations;
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();
bool networkVisible;

View file

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

View file

@ -86,7 +86,7 @@ time_t ActiveRunway::requestTimeSlot(time_t eta)
}
} else {
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
// i.e. eta > i AND eta < j
//
@ -193,6 +193,11 @@ void FGTrafficRecord::setPositionAndIntentions(int pos,
}
//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)
{
@ -497,10 +502,12 @@ void FGATCController::transmit(FGTrafficRecord * rec, AtcMsgId msgId,
string sender, receiver;
int stationFreq = 0;
int taxiFreq = 0;
int towerFreq = 0;
int freqId = 0;
string atisInformation;
string text;
string taxiFreqStr;
string towerFreqStr;
double heading = 0;
string activeRunway;
string fltType;
@ -509,20 +516,29 @@ void FGATCController::transmit(FGTrafficRecord * rec, AtcMsgId msgId,
string transponderCode;
FGAIFlightPlan *fp;
string fltRules;
string instructionText;
//double commFreqD;
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;
switch (rec->getLeg()) {
case 1:
case 2:
case 3:
freqId = rec->getNextFrequency();
stationFreq =
rec->getAircraft()->getTrafficRef()->getDepartureAirport()->
getDynamics()->getGroundFrequency(rec->getLeg() + freqId);
taxiFreq =
rec->getAircraft()->getTrafficRef()->getDepartureAirport()->
getDynamics()->getGroundFrequency(3);
getDynamics()->getGroundFrequency(2);
towerFreq =
rec->getAircraft()->getTrafficRef()->getDepartureAirport()->
getDynamics()->getTowerFrequency(2);
receiver =
rec->getAircraft()->getTrafficRef()->getDepartureAirport()->
getName() + "-Ground";
@ -530,7 +546,7 @@ void FGATCController::transmit(FGTrafficRecord * rec, AtcMsgId msgId,
rec->getAircraft()->getTrafficRef()->getDepartureAirport()->
getDynamics()->getAtisSequence();
break;
case 4:
case 3:
receiver =
rec->getAircraft()->getTrafficRef()->getDepartureAirport()->
getName() + "-Tower";
@ -588,7 +604,7 @@ void FGATCController::transmit(FGTrafficRecord * rec, AtcMsgId msgId,
receiver + ". Start-up approved. " + atisInformation +
" correct, runway " + activeRunway + ", " + SID + ", squawk " +
transponderCode + ". " +
"For push-back and taxi clearance call " + taxiFreqStr + ". " +
"For "+ instructionText + " clearance call " + taxiFreqStr + ". " +
sender + " control.";
break;
case MSG_DENY_ENGINE_START:
@ -606,11 +622,12 @@ void FGATCController::transmit(FGTrafficRecord * rec, AtcMsgId msgId,
taxiFreqStr = formatATCFrequency3_2(taxiFreq);
activeRunway = rec->getAircraft()->GetFlightPlan()->getRunway();
transponderCode = rec->getAircraft()->GetTransponderCode();
text =
receiver + ". Start-up approved. " + atisInformation +
" correct, runway " + activeRunway + ", " + SID + ", squawk " +
transponderCode + ". " +
"For push-back and taxi clearance call " + taxiFreqStr + ". " +
"For " + instructionText + " clearance call " + taxiFreqStr + ". " +
sender;
break;
case MSG_ACKNOWLEDGE_SWITCH_GROUND_FREQUENCY:
@ -624,10 +641,18 @@ void FGATCController::transmit(FGTrafficRecord * rec, AtcMsgId msgId,
text = receiver + ". Roger. " + sender;
break;
case MSG_REQUEST_PUSHBACK_CLEARANCE:
if (rec->getAircraft()->getTaxiClearanceRequest()) {
text = receiver + ". Request push-back. " + sender;
} else {
text = receiver + ". Request Taxi clearance. " + sender;
}
break;
case MSG_PERMIT_PUSHBACK_CLEARANCE:
if (rec->getAircraft()->getTaxiClearanceRequest()) {
text = receiver + ". Push-back approved. " + sender;
} else {
text = receiver + ". Cleared to Taxi." + sender;
}
break;
case MSG_HOLD_PUSHBACK_CLEARANCE:
text = receiver + ". Standby. " + sender;
@ -653,7 +678,37 @@ void FGATCController::transmit(FGTrafficRecord * rec, AtcMsgId msgId,
case MSG_ACKNOWLEDGE_RESUME_TAXI:
text = receiver + ". Continuing Taxi. " + sender;
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:
//text = "test3";
text = text + sender + ". Transmitting unknown Message";
break;
}
@ -716,9 +771,10 @@ void FGATCController::init()
* class FGTowerController
*
**************************************************************************/
FGTowerController::FGTowerController():
FGTowerController::FGTowerController(FGAirportDynamics *par) :
FGATCController()
{
parent = par;
}
//
@ -752,8 +808,29 @@ void FGTowerController::announcePosition(int id,
rec.setRunway(intendedRoute->getRunway());
rec.setLeg(leg);
//rec.setCallSign(callsign);
rec.setRadius(radius);
rec.setAircraft(ref);
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 {
i->setPositionAndHeading(lat, lon, heading, speed, alt);
}
@ -786,30 +863,44 @@ void FGTowerController::updateAircraftInformation(int id, double lat, double lon
}
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();
// again, a map might be more efficient here
if (activeRunways.size()) {
//while ((rwy->getRunwayName() != current->getRunway()) && (rwy != activeRunways.end())) {
while (rwy != activeRunways.end()) {
if (rwy->getRunwayName() == current->getRunway()) {
break;
}
rwy++;
}
}
if (rwy == activeRunways.end()) {
ActiveRunway aRwy(current->getRunway(), id);
activeRunways.push_back(aRwy); // Since there are no clearance records for this runway yet
current->setHoldPosition(false); // Clear the current aircraft to continue
} else {
// Okay, we have a clearance record for this runway, so check
// whether the clearence ID matches that of the current aircraft
// only bother running the following code if the current aircraft is the
// first in line for depature
/* if (current->getAircraft() == rwy->getFirstAircraftInDepartureCue()) {
if (rwy->getCleared()) {
if (id == rwy->getCleared()) {
current->setHoldPosition(false);
} else {
current->setHoldPosition(true);
}
} else {
// 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++;
}
if (rwy != activeRunways.end()) {
rwy = activeRunways.erase(rwy);
rwy->setCleared(0);
rwy->updateDepartureCue();
} else {
SG_LOG(SG_GENERAL, SG_ALERT,
"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,
"AI error: Aircraft without traffic record is signing off from tower");
} else {
i->getAircraft()->resetTakeOffStatus();
i = activeTraffic.erase(i);
//cerr << "Signing off from tower controller" << endl;
}
@ -911,6 +1004,11 @@ void FGTowerController::render(bool visible) {
//cerr << "FGTowerController::render function not yet implemented" << endl;
}
string FGTowerController::getName() {
return string(parent->getId() + "-tower");
}
/***************************************************************************
* class FGStartupController
@ -1273,13 +1371,19 @@ void FGStartupController::render(bool visible)
}
}
string FGStartupController::getName() {
return string(parent->getId() + "-startup");
}
/***************************************************************************
* class FGApproachController
*
**************************************************************************/
FGApproachController::FGApproachController():
FGApproachController::FGApproachController(FGAirportDynamics *par):
FGATCController()
{
parent = par;
}
//
@ -1467,3 +1571,9 @@ ActiveRunway *FGApproachController::getRunway(string name)
void FGApproachController::render(bool visible) {
//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>::iterator TimeVectorIterator;
typedef vector<FGAIAircraft*> AircraftVec;
typedef vector<FGAIAircraft*>::iterator AircraftVecIterator;
/***********************************************************************
* Active runway, a utility class to keep track of which aircraft has
@ -209,6 +211,8 @@ private:
int currentlyCleared;
double distanceToFinal;
TimeVector estimatedArrivalTimes;
AircraftVec departureCue;
public:
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; };
//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);
int getDepartureCueSize() { return departureCue.size(); };
FGAIAircraft* getFirstAircraftInDepartureCue() { return departureCue.size() ? *(departureCue.begin()) : NULL; };
void updateDepartureCue() { departureCue.erase(departureCue.begin()); }
};
typedef vector<ActiveRunway> ActiveRunwayVec;
@ -263,7 +273,13 @@ public:
MSG_HOLD_POSITION,
MSG_ACKNOWLEDGE_HOLD_POSITION,
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 {
ATC_AIR_TO_GROUND,
ATC_GROUND_TO_AIR } AtcMsgDir;
@ -286,6 +302,8 @@ public:
void transmit(FGTrafficRecord *rec, AtcMsgId msgId, AtcMsgDir msgDir, bool audible);
string getGateName(FGAIAircraft *aircraft);
virtual void render(bool) = 0;
virtual string getName() = 0;
private:
@ -300,9 +318,10 @@ class FGTowerController : public FGATCController
private:
TrafficVector activeTraffic;
ActiveRunwayVec activeRunways;
FGAirportDynamics *parent;
public:
FGTowerController();
FGTowerController(FGAirportDynamics *parent);
virtual ~FGTowerController() {};
virtual void announcePosition(int id, FGAIFlightPlan *intendedRoute, int currentRoute,
double lat, double lon,
@ -315,6 +334,7 @@ public:
virtual FGATCInstruction getInstruction(int id);
virtual void render(bool);
virtual string getName();
bool hasActiveTraffic() { return activeTraffic.size() != 0; };
TrafficVector &getActiveTraffic() { return activeTraffic; };
};
@ -329,7 +349,7 @@ class FGStartupController : public FGATCController
private:
TrafficVector activeTraffic;
//ActiveRunwayVec activeRunways;
FGAirportDynamics *parent;
FGAirportDynamics *parent;
public:
FGStartupController(FGAirportDynamics *parent);
@ -345,6 +365,7 @@ public:
virtual FGATCInstruction getInstruction(int id);
virtual void render(bool);
virtual string getName();
bool hasActiveTraffic() { return activeTraffic.size() != 0; };
TrafficVector &getActiveTraffic() { return activeTraffic; };
@ -363,10 +384,11 @@ class FGApproachController : public FGATCController
private:
TrafficVector activeTraffic;
ActiveRunwayVec activeRunways;
FGAirportDynamics *parent;
public:
FGApproachController();
virtual ~FGApproachController() {};
FGApproachController(FGAirportDynamics * parent);
virtual ~FGApproachController() { };
virtual void announcePosition(int id, FGAIFlightPlan *intendedRoute, int currentRoute,
double lat, double lon,
double hdg, double spd, double alt, double radius, int leg,
@ -378,6 +400,7 @@ public:
virtual FGATCInstruction getInstruction(int id);
virtual void render(bool);
virtual string getName();
ActiveRunway* getRunway(string name);

View file

@ -51,9 +51,12 @@ using std::random_shuffle;
FGAirportDynamics::FGAirportDynamics(FGAirport * ap):
_ap(ap), rwyPrefs(ap), SIDs(ap),
startupController (this),
towerController (this),
approachController (this),
atisSequenceIndex(-1),
atisSequenceTimeStamp(0.0),
startupController(this)
atisSequenceTimeStamp(0.0)
{
lastUpdate = 0;
}
@ -493,25 +496,24 @@ const string & FGAirportDynamics::getId() const
int FGAirportDynamics::getGroundFrequency(unsigned leg)
{
//return freqGround.size() ? freqGround[0] : 0; };
//cerr << "Getting frequency for : " << leg << endl;
int groundFreq = 0;
if (leg < 2) {
if (leg < 1) {
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) {
return 0;
}
if ((freqGround.size() > leg - 1) && (leg > 1)) {
groundFreq = freqGround[leg - 1];
}
if ((freqGround.size() < leg - 1) && (leg > 1)) {
if ((freqGround.size() < leg) && (leg > 0)) {
groundFreq =
(freqGround.size() <
(leg - 1)) ? freqGround[freqGround.size() -
1] : freqGround[leg - 2];
1] : freqGround[leg - 1];
}
if ((freqGround.size() >= leg - 1) && (leg > 1)) {
groundFreq = freqGround[leg - 2];
if ((freqGround.size() >= leg) && (leg > 0)) {
groundFreq = freqGround[leg - 1];
}
return groundFreq;
}

View file

@ -46,6 +46,8 @@
#include <AIModel/AIAircraft.hxx>
#include <AIModel/AIFlightPlan.hxx>
#include <ATC/atc_mgr.hxx>
#include <Scenery/scenery.hxx>
#include "groundnetwork.hxx"
@ -171,6 +173,7 @@ bool FGTaxiRoute::next(int *nde, int *rte)
return true;
};
void FGTaxiRoute::rewind(int route)
{
int currPoint;
@ -510,6 +513,7 @@ void FGGroundNetwork::announcePosition(int id,
}
}
void FGGroundNetwork::signOff(int id)
{
TrafficVectorIterator i = activeTraffic.begin();
@ -531,28 +535,40 @@ void FGGroundNetwork::signOff(int id)
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,
AtcMsgDir msgDir)
{
int state = i->getState();
if ((state >= minState) && (state <= maxState) && available) {
if ((msgDir == ATC_AIR_TO_GROUND) && isUserAircraft(i->getAircraft())) {
//cerr << "Checking state " << state << " for " << i->getAircraft()->getCallSign() << endl;
static SGPropertyNode_ptr trans_num = globals->get_props()->getNode("/sim/atc/transmission-num", true);
int n = trans_num->getIntValue();
if (n == 0) {
trans_num->setIntValue(-1);
// 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 {
//cerr << "creating message for " << i->getAircraft()->getCallSign() << endl;
transmit(&(*i), msgId, msgDir, false);
return false;
}
}
//cerr << "Transmitting startup msg" << endl;
transmit(&(*i), msgId, msgDir, true);
i->updateState();
lastTransmission = now;
@ -631,12 +647,11 @@ void FGGroundNetwork::updateAircraftInformation(int id, double lat, double lon,
if ((state == 5) && available) {
current->setState(0);
current->getAircraft()->setTaxiClearanceRequest(false);
current->setHoldPosition(true);
current->setHoldPosition(false);
available = false;
}
}
}
/**
@ -720,6 +735,10 @@ void FGGroundNetwork::checkSpeedAdjustment(int id, double lat,
if (bearing > 180)
bearing = 360 - bearing;
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;
closest = i;
minbearing = bearing;
@ -728,6 +747,8 @@ void FGGroundNetwork::checkSpeedAdjustment(int id, double lat,
}
}
// Finally, check UserPosition
// Note, as of 2011-08-01, this should no longer be necessecary.
/*
double userLatitude = fgGetDouble("/position/latitude-deg");
double userLongitude = fgGetDouble("/position/longitude-deg");
SGGeod user(SGGeod::fromDeg(userLongitude, userLatitude));
@ -742,7 +763,7 @@ void FGGroundNetwork::checkSpeedAdjustment(int id, double lat,
minbearing = bearing;
otherReasonToSlowDown = true;
}
*/
current->clearSpeedAdjustment();
if (current->checkPositionAndIntentions(*closest)
@ -755,11 +776,18 @@ void FGGroundNetwork::checkSpeedAdjustment(int id, double lat,
return;
else
current->setWaitsForId(closest->getId());
if (closest->getId() != current->getId())
if (closest->getId() != current->getId()) {
current->setSpeedAdjustment(closest->getSpeed() *
(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
}
if (mindist < maxAllowableDistance) {
//double newSpeed = (maxAllowableDistance-mindist);
//current->setSpeedAdjustment(newSpeed);
@ -860,8 +888,10 @@ void FGGroundNetwork::checkHoldPosition(int id, double lat,
//(!(current->getSpeedAdjustment())))
{
if (!(isUserAircraft(i->getAircraft()))) { // test code. Don't wait for the user, let the user wait for you.
current->setHoldPosition(true);
current->setWaitsForId(i->getId());
}
//cerr << "Hold check 5: " << current->getCallSign() <<" Setting Hold Position: distance to node (" << node << ") "
// << dist << " meters. Waiting for " << i->getCallSign();
//if (opposing)
@ -879,12 +909,13 @@ void FGGroundNetwork::checkHoldPosition(int id, double lat,
}
}
bool currStatus = current->hasHoldPosition();
current->setHoldPosition(origStatus);
// Either a Hold Position or a resume taxi transmission has been issued
time_t now = time(NULL) + fgGetLong("/sim/time/warp");
if ((now - lastTransmission) > 2) {
available = true;
}
if (current->getState() == 0) {
if ((origStatus != currStatus) && available) {
//cerr << "Issueing hold short instrudtion " << currStatus << " " << available << endl;
if (currStatus == true) { // No has a hold short instruction
@ -900,10 +931,15 @@ void FGGroundNetwork::checkHoldPosition(int id, double lat,
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();
if (checkTransmissionState(1,1, current, now, MSG_ACKNOWLEDGE_HOLD_POSITION, ATC_AIR_TO_GROUND)) {
current->setState(0);
@ -913,24 +949,22 @@ void FGGroundNetwork::checkHoldPosition(int id, double lat,
current->setState(0);
current->setHoldPosition(false);
}
/*if ((state == 1) && (available)) {
//cerr << "ACKNOWLEDGE HOLD" << endl;
transmit(&(*current), MSG_ACKNOWLEDGE_HOLD_POSITION, ATC_AIR_TO_GROUND, true);
current->setState(0);
current->setHoldPosition(true);
lastTransmission = now;
available = false;
if (current->getAircraft()->getTakeOffStatus() && (current->getState() == 0)) {
//cerr << "Scheduling " << current->getAircraft()->getCallSign() << " for hold short" << endl;
current->setState(6);
}
if ((state == 2) && (available)) {
//cerr << "ACKNOWLEDGE RESUME" << endl;
transmit(&(*current), MSG_ACKNOWLEDGE_RESUME_TAXI, ATC_AIR_TO_GROUND, true);
current->setState(0);
current->setHoldPosition(false);
lastTransmission = now;
available = false;
}*/
if (checkTransmissionState(6,6, current, now, MSG_REPORT_RUNWAY_HOLD_SHORT, ATC_AIR_TO_GROUND)) {
}
if (checkTransmissionState(7,7, current, now, MSG_ACKNOWLEDGE_REPORT_RUNWAY_HOLD_SHORT, ATC_GROUND_TO_AIR)) {
}
if (checkTransmissionState(8,8, current, now, MSG_SWITCH_TOWER_FREQUENCY, ATC_GROUND_TO_AIR)) {
}
if (checkTransmissionState(9,9, current, now, MSG_ACKNOWLEDGE_SWITCH_TOWER_FREQUENCY, ATC_AIR_TO_GROUND)) {
}
//current->setState(0);
}
/**
@ -1209,3 +1243,7 @@ void FGGroundNetwork::render(bool visible)
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(); };
int size() { return nodes.size(); };
int nodesLeft() { return nodes.end() - currNode; };
// int getDepth() { return depth; };
};
@ -288,6 +290,7 @@ public:
AtcMsgDir msgDir);
bool checkForCircularWaits(int id);
virtual void render(bool);
virtual string getName();
};

View file

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