#include "simple.hxx"
#include "dynamics.hxx"
-FGAirportDynamics::FGAirportDynamics(FGAirport* ap) :
- _ap(ap), rwyPrefs(ap), SIDs(ap) {
- lastUpdate = 0;
+FGAirportDynamics::FGAirportDynamics(FGAirport * ap):
+_ap(ap), rwyPrefs(ap), SIDs(ap)
+{
+ lastUpdate = 0;
- // For testing only. This needs to be refined when we move ATIS functionality over.
- atisInformation = "Sierra";
+ // For testing only. This needs to be refined when we move ATIS functionality over.
+ atisInformation = "Sierra";
}
// Note that the ground network should also be copied
-FGAirportDynamics::FGAirportDynamics(const FGAirportDynamics& other) :
- rwyPrefs(other.rwyPrefs),
- SIDs(other.SIDs)
+FGAirportDynamics::
+FGAirportDynamics(const FGAirportDynamics & other):rwyPrefs(other.
+ rwyPrefs),
+SIDs(other.SIDs)
{
- for (FGParkingVecConstIterator ip= other.parkings.begin(); ip != other.parkings.end(); ip++)
- parkings.push_back(*(ip));
- // rwyPrefs = other.rwyPrefs;
- lastUpdate = other.lastUpdate;
-
- stringVecConstIterator il;
- for (il = other.landing.begin(); il != other.landing.end(); il++)
- landing.push_back(*il);
- for (il = other.takeoff.begin(); il != other.takeoff.end(); il++)
- takeoff.push_back(*il);
- lastUpdate = other.lastUpdate;
- atisInformation = other.atisInformation;
+ for (FGParkingVecConstIterator ip = other.parkings.begin();
+ ip != other.parkings.end(); ip++)
+ parkings.push_back(*(ip));
+ // rwyPrefs = other.rwyPrefs;
+ lastUpdate = other.lastUpdate;
+
+ stringVecConstIterator il;
+ for (il = other.landing.begin(); il != other.landing.end(); il++)
+ landing.push_back(*il);
+ for (il = other.takeoff.begin(); il != other.takeoff.end(); il++)
+ takeoff.push_back(*il);
+ lastUpdate = other.lastUpdate;
+ atisInformation = other.atisInformation;
}
// Destructor
// Initialization required after XMLRead
-void FGAirportDynamics::init()
+void FGAirportDynamics::init()
{
- // This may seem a bit weird to first randomly shuffle the parkings
- // and then sort them again. However, parkings are sorted here by ascending
- // radius. Since many parkings have similar radii, with each radius class they will
- // still be allocated relatively systematically. Randomizing prior to sorting will
- // prevent any initial orderings to be destroyed, leading (hopefully) to a more
- // naturalistic gate assignment.
- random_shuffle(parkings.begin(), parkings.end());
- sort(parkings.begin(), parkings.end());
- // add the gate positions to the ground network.
- groundNetwork.addNodes(&parkings);
- groundNetwork.init();
- groundNetwork.setTowerController(&towerController);
- groundNetwork.setParent(_ap);
+ // This may seem a bit weird to first randomly shuffle the parkings
+ // and then sort them again. However, parkings are sorted here by ascending
+ // radius. Since many parkings have similar radii, with each radius class they will
+ // still be allocated relatively systematically. Randomizing prior to sorting will
+ // prevent any initial orderings to be destroyed, leading (hopefully) to a more
+ // naturalistic gate assignment.
+ random_shuffle(parkings.begin(), parkings.end());
+ sort(parkings.begin(), parkings.end());
+ // add the gate positions to the ground network.
+ groundNetwork.addNodes(&parkings);
+ groundNetwork.init();
+ groundNetwork.setTowerController(&towerController);
+ groundNetwork.setParent(_ap);
}
-bool FGAirportDynamics::getAvailableParking(double *lat, double *lon, double *heading, int *gateId, double rad, const string &flType, const string &acType, const string &airline)
+bool FGAirportDynamics::getAvailableParking(double *lat, double *lon,
+ double *heading, int *gateId,
+ double rad,
+ const string & flType,
+ const string & acType,
+ const string & airline)
{
- bool found = false;
- bool available = false;
- //string gateType;
-
- FGParkingVecIterator i;
-// if (flType == "cargo")
-// {
-// gateType = "RAMP_CARGO";
-// }
-// else if (flType == "ga")
-// {
-// gateType = "RAMP_GA";
-// }
-// else gateType = "GATE";
-
- if (parkings.begin() == parkings.end())
- {
- //cerr << "Could not find parking spot at " << _ap->getId() << endl;
- *lat = _ap->getLatitude();
- *lon = _ap->getLongitude();
- *heading = 0;
- found = true;
+ bool found = false;
+ bool available = false;
+
+
+ FGParkingVecIterator i;
+ if (parkings.begin() == parkings.end()) {
+ //cerr << "Could not find parking spot at " << _ap->getId() << endl;
+ *lat = _ap->getLatitude();
+ *lon = _ap->getLongitude();
+ *heading = 0;
+ found = true;
+ } else {
+ // First try finding a parking with a designated airline code
+ for (i = parkings.begin(); !(i == parkings.end() || found); i++) {
+ available = true;
+ // Taken by another aircraft
+ if (!(i->isAvailable())) {
+ available = false;
+ continue;
+ }
+ // No airline codes, so skip
+ if (i->getCodes().empty()) {
+ available = false;
+ continue;
+ } else { // Airline code doesn't match
+ //cerr << "Code = " << airline << ": Codes " << i->getCodes();
+ if (i->getCodes().find(airline, 0) == string::npos) {
+ available = false;
+ //cerr << "Unavailable" << endl;
+ continue;
+ } else {
+ //cerr << "Available" << endl;
+ }
+ }
+ // Type doesn't match
+ if (i->getType() != flType) {
+ available = false;
+ continue;
+ }
+ // too small
+ if (i->getRadius() < rad) {
+ available = false;
+ continue;
+ }
+
+ if (available) {
+ *lat = i->getLatitude();
+ *lon = i->getLongitude();
+ *heading = i->getHeading();
+ *gateId = i->getIndex();
+ i->setAvailable(false);
+ found = true;
+ }
+ }
+ // then try again for those without codes.
+ for (i = parkings.begin(); !(i == parkings.end() || found); i++) {
+ available = true;
+ if (!(i->isAvailable())) {
+ available = false;
+ continue;
+ }
+ if (!(i->getCodes().empty())) {
+ if ((i->getCodes().find(airline, 0) == string::npos)) {
+ available = false;
+ continue;
+ }
+ }
+ if (i->getType() != flType) {
+ available = false;
+ continue;
+ }
+
+ if (i->getRadius() < rad) {
+ available = false;
+ continue;
+ }
+
+ if (available) {
+ *lat = i->getLatitude();
+ *lon = i->getLongitude();
+ *heading = i->getHeading();
+ *gateId = i->getIndex();
+ i->setAvailable(false);
+ found = true;
+ }
+ }
+ // And finally once more if that didn't work. Now ignore the airline codes, as a last resort
+ for (i = parkings.begin(); !(i == parkings.end() || found); i++) {
+ available = true;
+ if (!(i->isAvailable())) {
+ available = false;
+ continue;
+ }
+ if (i->getType() != flType) {
+ available = false;
+ continue;
+ }
+
+ if (i->getRadius() < rad) {
+ available = false;
+ continue;
+ }
+
+ if (available) {
+ *lat = i->getLatitude();
+ *lon = i->getLongitude();
+ *heading = i->getHeading();
+ *gateId = i->getIndex();
+ i->setAvailable(false);
+ found = true;
+ }
+ }
}
- else
- {
- // First try finding a parking with a designated airline code
- for (i = parkings.begin(); !(i == parkings.end() || found); i++)
- {
- //cerr << "Gate Id: " << i->getIndex()
- // << " Type : " << i->getType()
- // << " Codes : " << i->getCodes()
- // << " Radius: " << i->getRadius()
- // << " Name : " << i->getName()
- // << " Available: " << i->isAvailable() << endl;
- available = true;
- // Taken by another aircraft
- if (!(i->isAvailable()))
- {
- available = false;
- continue;
- }
- // No airline codes, so skip
- if (i->getCodes().empty())
- {
- available = false;
- continue;
- }
- else // Airline code doesn't match
- {
- //cerr << "Code = " << airline << ": Codes " << i->getCodes();
- if (i->getCodes().find(airline, 0) == string::npos)
- {
- available = false;
- //cerr << "Unavailable" << endl;
- continue;
- }
- else
- {
- //cerr << "Available" << endl;
- }
- }
- // Type doesn't match
- if (i->getType() != flType)
- {
- available = false;
- continue;
- }
- // too small
- if (i->getRadius() < rad)
- {
- available = false;
- continue;
- }
-
- if (available)
- {
- *lat = i->getLatitude ();
- *lon = i->getLongitude();
- *heading = i->getHeading ();
- *gateId = i->getIndex ();
- i->setAvailable(false);
- found = true;
- }
- }
- // then try again for those without codes.
- for (i = parkings.begin(); !(i == parkings.end() || found); i++)
- {
- available = true;
- if (!(i->isAvailable()))
- {
- available = false;
- continue;
- }
- if (!(i->getCodes().empty()))
- {
- if ((i->getCodes().find(airline,0) == string::npos))
- {
- available = false;
- continue;
- }
- }
- if (i->getType() != flType)
- {
- available = false;
- continue;
- }
-
- if (i->getRadius() < rad)
- {
- available = false;
- continue;
- }
-
- if (available)
- {
- *lat = i->getLatitude ();
- *lon = i->getLongitude();
- *heading = i->getHeading ();
- *gateId = i->getIndex ();
- i->setAvailable(false);
- found = true;
- }
- }
- // And finally once more if that didn't work. Now ignore the airline codes, as a last resort
- for (i = parkings.begin(); !(i == parkings.end() || found); i++)
- {
- available = true;
- if (!(i->isAvailable()))
- {
- available = false;
- continue;
- }
- if (i->getType() != flType)
- {
- available = false;
- continue;
- }
-
- if (i->getRadius() < rad)
- {
- available = false;
- continue;
- }
-
- if (available)
- {
- *lat = i->getLatitude ();
- *lon = i->getLongitude();
- *heading = i->getHeading ();
- *gateId = i->getIndex ();
- i->setAvailable(false);
- found = true;
- }
- }
+ if (!found) {
+ //cerr << "Traffic overflow at" << _ap->getId()
+ // << ". flType = " << flType
+ // << ". airline = " << airline
+ // << " Radius = " <<rad
+ // << endl;
+ *lat = _ap->getLatitude();
+ *lon = _ap->getLongitude();
+ *heading = 0;
+ *gateId = -1;
+ //exit(1);
}
- if (!found)
- {
- //cerr << "Traffic overflow at" << _ap->getId()
- // << ". flType = " << flType
- // << ". airline = " << airline
- // << " Radius = " <<rad
- // << endl;
- *lat = _ap->getLatitude();
- *lon = _ap->getLongitude();
- *heading = 0;
- *gateId = -1;
- //exit(1);
- }
- return found;
+ return found;
}
-void FGAirportDynamics::getParking (int id, double *lat, double* lon, double *heading)
+void FGAirportDynamics::getParking(int id, double *lat, double *lon,
+ double *heading)
{
- if (id < 0)
- {
- *lat = _ap->getLatitude();
- *lon = _ap->getLongitude();
- *heading = 0;
- }
- else
- {
- FGParkingVecIterator i = parkings.begin();
- for (i = parkings.begin(); i != parkings.end(); i++)
- {
- if (id == i->getIndex())
- {
- *lat = i->getLatitude();
- *lon = i->getLongitude();
- *heading = i->getHeading();
- }
- }
+ if (id < 0) {
+ *lat = _ap->getLatitude();
+ *lon = _ap->getLongitude();
+ *heading = 0;
+ } else {
+ FGParkingVecIterator i = parkings.begin();
+ for (i = parkings.begin(); i != parkings.end(); i++) {
+ if (id == i->getIndex()) {
+ *lat = i->getLatitude();
+ *lon = i->getLongitude();
+ *heading = i->getHeading();
+ }
+ }
}
-}
+}
-FGParking *FGAirportDynamics::getParking(int id)
-{
+FGParking *FGAirportDynamics::getParking(int id)
+{
FGParkingVecIterator i = parkings.begin();
- for (i = parkings.begin(); i != parkings.end(); i++)
- {
- if (id == i->getIndex()) {
- return &(*i);
- }
+ for (i = parkings.begin(); i != parkings.end(); i++) {
+ if (id == i->getIndex()) {
+ return &(*i);
}
+ }
return 0;
}
-string FGAirportDynamics::getParkingName(int id)
-{
+
+string FGAirportDynamics::getParkingName(int id)
+{
FGParkingVecIterator i = parkings.begin();
- for (i = parkings.begin(); i != parkings.end(); i++)
- {
- if (id == i->getIndex()) {
- return i->getName();
- }
+ for (i = parkings.begin(); i != parkings.end(); i++) {
+ if (id == i->getIndex()) {
+ return i->getName();
}
+ }
return string("overflow");
}
+
void FGAirportDynamics::releaseParking(int id)
{
- if (id >= 0)
- {
-
- FGParkingVecIterator i = parkings.begin();
- for (i = parkings.begin(); i != parkings.end(); i++)
- {
- if (id == i->getIndex())
- {
- i -> setAvailable(true);
- }
- }
+ if (id >= 0) {
+
+ FGParkingVecIterator i = parkings.begin();
+ for (i = parkings.begin(); i != parkings.end(); i++) {
+ if (id == i->getIndex()) {
+ i->setAvailable(true);
+ }
+ }
}
}
-
-void FGAirportDynamics::setRwyUse(const FGRunwayPreference& ref)
+
+void FGAirportDynamics::setRwyUse(const FGRunwayPreference & ref)
{
- rwyPrefs = ref;
- //cerr << "Exiting due to not implemented yet" << endl;
- //exit(1);
+ rwyPrefs = ref;
+ //cerr << "Exiting due to not implemented yet" << endl;
+ //exit(1);
}
-bool FGAirportDynamics::innerGetActiveRunway(const string &trafficType, int action, string &runway, double heading)
+bool FGAirportDynamics::innerGetActiveRunway(const string & trafficType,
+ int action, string & runway,
+ double heading)
{
-double windSpeed;
- double windHeading;
- double maxTail;
- double maxCross;
- string name;
- string type;
-
- if (!rwyPrefs.available()) {
- return false;
- }
-
- RunwayGroup *currRunwayGroup = 0;
- int nrActiveRunways = 0;
- time_t dayStart = fgGetLong("/sim/time/utc/day-seconds");
- if ((abs((long)(dayStart - lastUpdate)) > 600) || trafficType != prevTrafficType)
- {
- landing.clear();
- takeoff.clear();
- lastUpdate = dayStart;
- prevTrafficType = trafficType;
-
- FGEnvironment
- stationweather = ((FGEnvironmentMgr *) globals->get_subsystem("environment"))
- ->getEnvironment(getLatitude(),
- getLongitude(),
- getElevation());
-
- windSpeed = stationweather.get_wind_speed_kt();
- windHeading = stationweather.get_wind_from_heading_deg();
- string scheduleName;
- //cerr << "finding active Runway for" << _ap->getId() << endl;
- //cerr << "Nr of seconds since day start << " << dayStart << endl;
-
- ScheduleTime *currSched;
- //cerr << "A"<< endl;
- currSched = rwyPrefs.getSchedule(trafficType.c_str());
- if (!(currSched))
- return false;
- //cerr << "B"<< endl;
- scheduleName = currSched->getName(dayStart);
- maxTail = currSched->getTailWind ();
- maxCross = currSched->getCrossWind ();
- //cerr << "SChedule anme = " << scheduleName << endl;
- if (scheduleName.empty())
- return false;
- //cerr << "C"<< endl;
- currRunwayGroup = rwyPrefs.getGroup(scheduleName);
- //cerr << "D"<< endl;
- if (!(currRunwayGroup))
- return false;
- nrActiveRunways = currRunwayGroup->getNrActiveRunways();
+ double windSpeed;
+ double windHeading;
+ double maxTail;
+ double maxCross;
+ string name;
+ string type;
+
+ if (!rwyPrefs.available()) {
+ return false;
+ }
+
+ RunwayGroup *currRunwayGroup = 0;
+ int nrActiveRunways = 0;
+ time_t dayStart = fgGetLong("/sim/time/utc/day-seconds");
+ if ((abs((long) (dayStart - lastUpdate)) > 600)
+ || trafficType != prevTrafficType) {
+ landing.clear();
+ takeoff.clear();
+ lastUpdate = dayStart;
+ prevTrafficType = trafficType;
+
+ FGEnvironment
+ stationweather =
+ ((FGEnvironmentMgr *) globals->get_subsystem("environment"))
+ ->getEnvironment(getLatitude(), getLongitude(),
+ getElevation());
+
+ windSpeed = stationweather.get_wind_speed_kt();
+ windHeading = stationweather.get_wind_from_heading_deg();
+ string scheduleName;
+ //cerr << "finding active Runway for" << _ap->getId() << endl;
+ //cerr << "Nr of seconds since day start << " << dayStart << endl;
+
+ ScheduleTime *currSched;
+ //cerr << "A"<< endl;
+ currSched = rwyPrefs.getSchedule(trafficType.c_str());
+ if (!(currSched))
+ return false;
+ //cerr << "B"<< endl;
+ scheduleName = currSched->getName(dayStart);
+ maxTail = currSched->getTailWind();
+ maxCross = currSched->getCrossWind();
+ //cerr << "SChedule anme = " << scheduleName << endl;
+ if (scheduleName.empty())
+ return false;
+ //cerr << "C"<< endl;
+ currRunwayGroup = rwyPrefs.getGroup(scheduleName);
+ //cerr << "D"<< endl;
+ if (!(currRunwayGroup))
+ return false;
+ nrActiveRunways = currRunwayGroup->getNrActiveRunways();
// Keep a history of the currently active runways, to ensure
// that an already established selection of runways will not
// be overridden once a more preferred selection becomes
// available as that can lead to random runway swapping.
- if (trafficType == "com") {
- currentlyActive = &comActive;
+ if (trafficType == "com") {
+ currentlyActive = &comActive;
} else if (trafficType == "gen") {
- currentlyActive = &genActive;
+ currentlyActive = &genActive;
} else if (trafficType == "mil") {
- currentlyActive = &milActive;
+ currentlyActive = &milActive;
} else if (trafficType == "ul") {
- currentlyActive = &ulActive;
+ currentlyActive = &ulActive;
+ }
+
+ currRunwayGroup->setActive(_ap,
+ windSpeed,
+ windHeading,
+ maxTail, maxCross, currentlyActive);
+
+ // Note that I SHOULD keep multiple lists in memory, one for
+ // general aviation, one for commercial and one for military
+ // traffic.
+ currentlyActive->clear();
+ nrActiveRunways = currRunwayGroup->getNrActiveRunways();
+ //cerr << "Choosing runway for " << trafficType << endl;
+ for (int i = 0; i < nrActiveRunways; i++) {
+ type = "unknown"; // initialize to something other than landing or takeoff
+ currRunwayGroup->getActive(i, name, type);
+ if (type == "landing") {
+ landing.push_back(name);
+ currentlyActive->push_back(name);
+ //cerr << "Landing " << name << endl;
+ }
+ if (type == "takeoff") {
+ takeoff.push_back(name);
+ currentlyActive->push_back(name);
+ //cerr << "takeoff " << name << endl;
+ }
}
- //
- currRunwayGroup->setActive(_ap,
- windSpeed,
- windHeading,
- maxTail,
- maxCross,
- currentlyActive);
-
- // Note that I SHOULD keep multiple lists in memory, one for
- // general aviation, one for commercial and one for military
- // traffic.
- currentlyActive->clear();
- nrActiveRunways = currRunwayGroup->getNrActiveRunways();
- //cerr << "Choosing runway for " << trafficType << endl;
- for (int i = 0; i < nrActiveRunways; i++)
- {
- type = "unknown"; // initialize to something other than landing or takeoff
- currRunwayGroup->getActive(i, name, type);
- if (type == "landing")
- {
- landing.push_back(name);
- currentlyActive->push_back(name);
- //cerr << "Landing " << name << endl;
- }
- if (type == "takeoff")
- {
- takeoff.push_back(name);
- currentlyActive->push_back(name);
- //cerr << "takeoff " << name << endl;
- }
- }
- //cerr << endl;
- }
-
- if (action == 1) // takeoff
- {
- int nr = takeoff.size();
- if (nr)
- {
- // Note that the randomization below, is just a placeholder to choose between
- // multiple active runways for this action. This should be
- // under ATC control.
- runway = chooseRwyByHeading (takeoff, heading);
- }
- else
- { // Fallback
- runway = chooseRunwayFallback();
- }
- }
-
- if (action == 2) // landing
- {
- int nr = landing.size();
- if (nr)
- {
- runway = chooseRwyByHeading (landing, heading);
- }
- else
- { //fallback
- runway = chooseRunwayFallback();
- }
- }
-
- return true;
+ //cerr << endl;
+ }
+
+ if (action == 1) // takeoff
+ {
+ int nr = takeoff.size();
+ if (nr) {
+ // Note that the randomization below, is just a placeholder to choose between
+ // multiple active runways for this action. This should be
+ // under ATC control.
+ runway = chooseRwyByHeading(takeoff, heading);
+ } else { // Fallback
+ runway = chooseRunwayFallback();
+ }
+ }
+
+ if (action == 2) // landing
+ {
+ int nr = landing.size();
+ if (nr) {
+ runway = chooseRwyByHeading(landing, heading);
+ } else { //fallback
+ runway = chooseRunwayFallback();
+ }
+ }
+
+ return true;
}
-string FGAirportDynamics::chooseRwyByHeading(stringVec rwys, double heading) {
- double bestError = 360.0;
- double rwyHeading, headingError;
- string runway;
- for (stringVecIterator i = rwys.begin(); i != rwys.end(); i++) {
- FGRunway *rwy = _ap->getRunwayByIdent((*i));
- rwyHeading = rwy->headingDeg();
- headingError = fabs(heading - rwyHeading);
+string FGAirportDynamics::chooseRwyByHeading(stringVec rwys,
+ double heading)
+{
+ double bestError = 360.0;
+ double rwyHeading, headingError;
+ string runway;
+ for (stringVecIterator i = rwys.begin(); i != rwys.end(); i++) {
+ FGRunway *rwy = _ap->getRunwayByIdent((*i));
+ rwyHeading = rwy->headingDeg();
+ headingError = fabs(heading - rwyHeading);
if (headingError > 180)
headingError = fabs(headingError - 360);
if (headingError < bestError) {
runway = (*i);
bestError = headingError;
}
- }
- //cerr << "Using active runway " << runway << " for heading " << heading << endl;
- return runway;
+ }
+ //cerr << "Using active runway " << runway << " for heading " << heading << endl;
+ return runway;
}
-void FGAirportDynamics::getActiveRunway(const string &trafficType, int action, string &runway, double heading)
+void FGAirportDynamics::getActiveRunway(const string & trafficType,
+ int action, string & runway,
+ double heading)
{
- bool ok = innerGetActiveRunway(trafficType, action, runway, heading);
- if (!ok) {
- runway = chooseRunwayFallback();
- }
+ bool ok = innerGetActiveRunway(trafficType, action, runway, heading);
+ if (!ok) {
+ runway = chooseRunwayFallback();
+ }
}
string FGAirportDynamics::chooseRunwayFallback()
-{
- FGRunway* rwy = _ap->getActiveRunwayForUsage();
- return rwy->ident();
+{
+ FGRunway *rwy = _ap->getActiveRunwayForUsage();
+ return rwy->ident();
}
-void FGAirportDynamics::addParking(FGParking& park) {
- parkings.push_back(park);
+void FGAirportDynamics::addParking(FGParking & park)
+{
+ parkings.push_back(park);
}
-double FGAirportDynamics::getLatitude() const {
- return _ap->getLatitude();
+double FGAirportDynamics::getLatitude() const
+{
+ return _ap->getLatitude();
}
-double FGAirportDynamics::getLongitude() const {
- return _ap->getLongitude();
+double FGAirportDynamics::getLongitude() const
+{
+ return _ap->getLongitude();
}
-double FGAirportDynamics::getElevation() const {
- return _ap->getElevation();
+double FGAirportDynamics::getElevation() const
+{
+ return _ap->getElevation();
}
-const string& FGAirportDynamics::getId() const {
- return _ap->getId();
+const string & FGAirportDynamics::getId() const
+{
+ return _ap->getId();
}
// Experimental: Return a different ground frequency depending on the leg of the
// so that at least I can start working on assigning different frequencies to different
// operations.
-int FGAirportDynamics::getGroundFrequency(unsigned leg) {
- //return freqGround.size() ? freqGround[0] : 0; };
- int groundFreq = 0;
- if (leg < 2) {
- SG_LOG(SG_ATC, SG_ALERT, "Leg value is smaller than two 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)) {
- groundFreq = (freqGround.size() < (leg-1)) ? freqGround[freqGround.size()-1] : freqGround[leg-2];
- }
- if ((freqGround.size() >= leg-1) && (leg > 1)) {
- groundFreq = freqGround[leg-2];
- }
+int FGAirportDynamics::getGroundFrequency(unsigned leg)
+{
+ //return freqGround.size() ? freqGround[0] : 0; };
+ int groundFreq = 0;
+ if (leg < 2) {
+ SG_LOG(SG_ATC, SG_ALERT,
+ "Leg value is smaller than two 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)) {
+ groundFreq =
+ (freqGround.size() <
+ (leg - 1)) ? freqGround[freqGround.size() -
+ 1] : freqGround[leg - 2];
+ }
+ if ((freqGround.size() >= leg - 1) && (leg > 1)) {
+ groundFreq = freqGround[leg - 2];
+ }
return groundFreq;
}
-FGAIFlightPlan *FGAirportDynamics::getSID(string activeRunway, double heading)
+FGAIFlightPlan *FGAirportDynamics::getSID(string activeRunway,
+ double heading)
{
- return SIDs.getBest(activeRunway, heading);
+ return SIDs.getBest(activeRunway, heading);
}
#include <Airports/dynamics.hxx>
+#include <AIModel/AIAircraft.hxx>
#include <AIModel/AIFlightPlan.hxx>
#include "groundnetwork.hxx"
* FGTaxiSegment
**************************************************************************/
-void FGTaxiSegment::setStart(FGTaxiNodeVector *nodes)
+void FGTaxiSegment::setStart(FGTaxiNodeVector * nodes)
{
- FGTaxiNodeVectorIterator i = nodes->begin();
- while (i != nodes->end())
- {
- //cerr << "Scanning start node index" << (*i)->getIndex() << endl;
- if ((*i)->getIndex() == startNode)
- {
- start = (*i)->getAddress();
- (*i)->addSegment(this);
- return;
- }
- i++;
- }
- SG_LOG(SG_GENERAL, SG_ALERT, "Could not find start node " << startNode << endl);
+ FGTaxiNodeVectorIterator i = nodes->begin();
+ while (i != nodes->end()) {
+ //cerr << "Scanning start node index" << (*i)->getIndex() << endl;
+ if ((*i)->getIndex() == startNode) {
+ start = (*i)->getAddress();
+ (*i)->addSegment(this);
+ return;
+ }
+ i++;
+ }
+ SG_LOG(SG_GENERAL, SG_ALERT,
+ "Could not find start node " << startNode << endl);
}
-void FGTaxiSegment::setEnd(FGTaxiNodeVector *nodes)
+void FGTaxiSegment::setEnd(FGTaxiNodeVector * nodes)
{
- FGTaxiNodeVectorIterator i = nodes->begin();
- while (i != nodes->end())
- {
- //cerr << "Scanning end node index" << (*i)->getIndex() << endl;
- if ((*i)->getIndex() == endNode)
- {
- end = (*i)->getAddress();
- return;
- }
- i++;
- }
- SG_LOG(SG_GENERAL, SG_ALERT, "Could not find end node " << endNode << endl);
+ FGTaxiNodeVectorIterator i = nodes->begin();
+ while (i != nodes->end()) {
+ //cerr << "Scanning end node index" << (*i)->getIndex() << endl;
+ if ((*i)->getIndex() == endNode) {
+ end = (*i)->getAddress();
+ return;
+ }
+ i++;
+ }
+ SG_LOG(SG_GENERAL, SG_ALERT,
+ "Could not find end node " << endNode << endl);
}
// doing this.
void FGTaxiSegment::setTrackDistance()
{
- length = SGGeodesy::distanceM(start->getGeod(), end->getGeod());
+ length = SGGeodesy::distanceM(start->getGeod(), end->getGeod());
}
void FGTaxiSegment::setCourseDiff(double crse)
{
- headingDiff = fabs(course-crse);
-
- if (headingDiff > 180)
- headingDiff = fabs(headingDiff - 360);
+ headingDiff = fabs(course - crse);
+
+ if (headingDiff > 180)
+ headingDiff = fabs(headingDiff - 360);
}
/***************************************************************************
* FGTaxiRoute
**************************************************************************/
-bool FGTaxiRoute::next(int *nde)
-{
- //for (intVecIterator i = nodes.begin(); i != nodes.end(); i++)
- // cerr << "FGTaxiRoute contains : " << *(i) << endl;
- //cerr << "Offset from end: " << nodes.end() - currNode << endl;
- //if (currNode != nodes.end())
- // cerr << "true" << endl;
- //else
- // cerr << "false" << endl;
- //if (nodes.size() != (routes.size()) +1)
- // cerr << "ALERT: Misconfigured TaxiRoute : " << nodes.size() << " " << routes.size() << endl;
-
- if (currNode == nodes.end())
- return false;
- *nde = *(currNode);
- if (currNode != nodes.begin()) // make sure route corresponds to the end node
- currRoute++;
- currNode++;
- return true;
+bool FGTaxiRoute::next(int *nde)
+{
+ //for (intVecIterator i = nodes.begin(); i != nodes.end(); i++)
+ // cerr << "FGTaxiRoute contains : " << *(i) << endl;
+ //cerr << "Offset from end: " << nodes.end() - currNode << endl;
+ //if (currNode != nodes.end())
+ // cerr << "true" << endl;
+ //else
+ // cerr << "false" << endl;
+ //if (nodes.size() != (routes.size()) +1)
+ // cerr << "ALERT: Misconfigured TaxiRoute : " << nodes.size() << " " << routes.size() << endl;
+
+ if (currNode == nodes.end())
+ return false;
+ *nde = *(currNode);
+ if (currNode != nodes.begin()) // make sure route corresponds to the end node
+ currRoute++;
+ currNode++;
+ return true;
};
-bool FGTaxiRoute::next(int *nde, int *rte)
-{
- //for (intVecIterator i = nodes.begin(); i != nodes.end(); i++)
- // cerr << "FGTaxiRoute contains : " << *(i) << endl;
- //cerr << "Offset from end: " << nodes.end() - currNode << endl;
- //if (currNode != nodes.end())
- // cerr << "true" << endl;
- //else
- // cerr << "false" << endl;
- if (nodes.size() != (routes.size()) +1) {
- SG_LOG(SG_GENERAL, SG_ALERT, "ALERT: Misconfigured TaxiRoute : " << nodes.size() << " " << routes.size());
- exit(1);
- }
- if (currNode == nodes.end())
- return false;
- *nde = *(currNode);
- //*rte = *(currRoute);
- if (currNode != nodes.begin()) // Make sure route corresponds to the end node
- {
- *rte = *(currRoute);
- currRoute++;
+bool FGTaxiRoute::next(int *nde, int *rte)
+{
+ //for (intVecIterator i = nodes.begin(); i != nodes.end(); i++)
+ // cerr << "FGTaxiRoute contains : " << *(i) << endl;
+ //cerr << "Offset from end: " << nodes.end() - currNode << endl;
+ //if (currNode != nodes.end())
+ // cerr << "true" << endl;
+ //else
+ // cerr << "false" << endl;
+ if (nodes.size() != (routes.size()) + 1) {
+ SG_LOG(SG_GENERAL, SG_ALERT,
+ "ALERT: Misconfigured TaxiRoute : " << nodes.
+ size() << " " << routes.size());
+ exit(1);
}
- else
+ if (currNode == nodes.end())
+ return false;
+ *nde = *(currNode);
+ //*rte = *(currRoute);
+ if (currNode != nodes.begin()) // Make sure route corresponds to the end node
{
- // If currNode points to the first node, this means the aircraft is not on the taxi node
- // yet. Make sure to return a unique identifyer in this situation though, because otherwise
- // the speed adjust AI code may be unable to resolve whether two aircraft are on the same
- // taxi route or not. the negative of the preceding route seems a logical choice, as it is
- // unique for any starting location.
- // Note that this is probably just a temporary fix until I get Parking / tower control working.
- *rte = -1 * *(currRoute);
- }
- currNode++;
- return true;
+ *rte = *(currRoute);
+ currRoute++;
+ } else {
+ // If currNode points to the first node, this means the aircraft is not on the taxi node
+ // yet. Make sure to return a unique identifyer in this situation though, because otherwise
+ // the speed adjust AI code may be unable to resolve whether two aircraft are on the same
+ // taxi route or not. the negative of the preceding route seems a logical choice, as it is
+ // unique for any starting location.
+ // Note that this is probably just a temporary fix until I get Parking / tower control working.
+ *rte = -1 * *(currRoute);
+ }
+ currNode++;
+ return true;
};
void FGTaxiRoute::rewind(int route)
{
- int currPoint;
- int currRoute;
- first();
- do {
- if (!(next(&currPoint, &currRoute))) {
- SG_LOG(SG_GENERAL,SG_ALERT, "Error in rewinding TaxiRoute: current" << currRoute
- << " goal " << route);
- }
- } while (currRoute != route);
+ int currPoint;
+ int currRoute;
+ first();
+ do {
+ if (!(next(&currPoint, &currRoute))) {
+ SG_LOG(SG_GENERAL, SG_ALERT,
+ "Error in rewinding TaxiRoute: current" << currRoute <<
+ " goal " << route);
+ }
+ } while (currRoute != route);
}
/***************************************************************************
* FGGroundNetwork()
**************************************************************************/
-bool compare_nodes(FGTaxiNode *a, FGTaxiNode *b) {
-return (*a) < (*b);
+bool compare_nodes(FGTaxiNode * a, FGTaxiNode * b)
+{
+ return (*a) < (*b);
}
-bool compare_segments(FGTaxiSegment *a, FGTaxiSegment *b) {
-return (*a) < (*b);
+bool compare_segments(FGTaxiSegment * a, FGTaxiSegment * b)
+{
+ return (*a) < (*b);
}
FGGroundNetwork::FGGroundNetwork()
{
- hasNetwork = false;
- foundRoute = false;
- totalDistance = 0;
- maxDistance = 0;
- //maxDepth = 1000;
- count = 0;
- currTraffic = activeTraffic.begin();
+ hasNetwork = false;
+ foundRoute = false;
+ totalDistance = 0;
+ maxDistance = 0;
+ //maxDepth = 1000;
+ count = 0;
+ currTraffic = activeTraffic.begin();
}
FGGroundNetwork::~FGGroundNetwork()
{
- for (FGTaxiNodeVectorIterator node = nodes.begin();
- node != nodes.end();
- node++)
- {
- delete (*node);
+ for (FGTaxiNodeVectorIterator node = nodes.begin();
+ node != nodes.end(); node++) {
+ delete(*node);
}
- nodes.clear();
- pushBackNodes.clear();
- for (FGTaxiSegmentVectorIterator seg = segments.begin();
- seg != segments.end();
- seg++)
- {
- delete (*seg);
+ nodes.clear();
+ pushBackNodes.clear();
+ for (FGTaxiSegmentVectorIterator seg = segments.begin();
+ seg != segments.end(); seg++) {
+ delete(*seg);
}
- segments.clear();
+ segments.clear();
}
-void FGGroundNetwork::addSegment(const FGTaxiSegment &seg)
+void FGGroundNetwork::addSegment(const FGTaxiSegment & seg)
{
- segments.push_back(new FGTaxiSegment(seg));
+ segments.push_back(new FGTaxiSegment(seg));
}
-void FGGroundNetwork::addNode(const FGTaxiNode &node)
+void FGGroundNetwork::addNode(const FGTaxiNode & node)
{
- nodes.push_back(new FGTaxiNode(node));
+ nodes.push_back(new FGTaxiNode(node));
}
-void FGGroundNetwork::addNodes(FGParkingVec *parkings)
+void FGGroundNetwork::addNodes(FGParkingVec * parkings)
{
- FGTaxiNode n;
- FGParkingVecIterator i = parkings->begin();
- while (i != parkings->end())
- {
- n.setIndex(i->getIndex());
- n.setLatitude(i->getLatitude());
- n.setLongitude(i->getLongitude());
- nodes.push_back(new FGTaxiNode(n));
-
- i++;
+ FGTaxiNode n;
+ FGParkingVecIterator i = parkings->begin();
+ while (i != parkings->end()) {
+ n.setIndex(i->getIndex());
+ n.setLatitude(i->getLatitude());
+ n.setLongitude(i->getLongitude());
+ nodes.push_back(new FGTaxiNode(n));
+
+ i++;
}
}
void FGGroundNetwork::init()
{
- hasNetwork = true;
- int index = 1;
- sort(nodes.begin(), nodes.end(), compare_nodes);
- //sort(segments.begin(), segments.end(), compare_segments());
- FGTaxiSegmentVectorIterator i = segments.begin();
- while(i != segments.end()) {
- (*i)->setStart(&nodes);
- (*i)->setEnd (&nodes);
- (*i)->setTrackDistance();
- (*i)->setIndex(index);
- if ((*i)->isPushBack()) {
- pushBackNodes.push_back((*i)->getEnd());
- }
- //SG_LOG(SG_GENERAL, SG_BULK, "initializing segment " << (*i)->getIndex() << endl);
- //SG_LOG(SG_GENERAL, SG_BULK, "Track distance = " << (*i)->getLength() << endl);
- //SG_LOG(SG_GENERAL, SG_BULK, "Track runs from " << (*i)->getStart()->getIndex() << " to "
- // << (*i)->getEnd()->getIndex() << endl);
- i++;
- index++;
- }
-
- i = segments.begin();
- while(i != segments.end()) {
- FGTaxiSegmentVectorIterator j = (*i)->getEnd()->getBeginRoute();
- while (j != (*i)->getEnd()->getEndRoute())
- {
- if ((*j)->getEnd()->getIndex() == (*i)->getStart()->getIndex())
- {
-// int start1 = (*i)->getStart()->getIndex();
-// int end1 = (*i)->getEnd() ->getIndex();
-// int start2 = (*j)->getStart()->getIndex();
-// int end2 = (*j)->getEnd()->getIndex();
-// int oppIndex = (*j)->getIndex();
- //cerr << "Opposite of " << (*i)->getIndex() << " (" << start1 << "," << end1 << ") "
- // << "happens to be " << oppIndex << " (" << start2 << "," << end2 << ") " << endl;
- (*i)->setOpposite(*j);
- break;
- }
- j++;
- }
- i++;
- }
- //FGTaxiNodeVectorIterator j = nodes.begin();
- //while (j != nodes.end()) {
- // if ((*j)->getHoldPointType() == 3) {
- // pushBackNodes.push_back((*j));
- // }
- // j++;
- //}
- //cerr << "Done initializing ground network" << endl;
- //exit(1);
+ hasNetwork = true;
+ int index = 1;
+ sort(nodes.begin(), nodes.end(), compare_nodes);
+ //sort(segments.begin(), segments.end(), compare_segments());
+ FGTaxiSegmentVectorIterator i = segments.begin();
+ while (i != segments.end()) {
+ (*i)->setStart(&nodes);
+ (*i)->setEnd(&nodes);
+ (*i)->setTrackDistance();
+ (*i)->setIndex(index);
+ if ((*i)->isPushBack()) {
+ pushBackNodes.push_back((*i)->getEnd());
+ }
+ //SG_LOG(SG_GENERAL, SG_BULK, "initializing segment " << (*i)->getIndex() << endl);
+ //SG_LOG(SG_GENERAL, SG_BULK, "Track distance = " << (*i)->getLength() << endl);
+ //SG_LOG(SG_GENERAL, SG_BULK, "Track runs from " << (*i)->getStart()->getIndex() << " to "
+ // << (*i)->getEnd()->getIndex() << endl);
+ i++;
+ index++;
+ }
+
+ i = segments.begin();
+ while (i != segments.end()) {
+ FGTaxiSegmentVectorIterator j = (*i)->getEnd()->getBeginRoute();
+ while (j != (*i)->getEnd()->getEndRoute()) {
+ if ((*j)->getEnd()->getIndex() == (*i)->getStart()->getIndex()) {
+// int start1 = (*i)->getStart()->getIndex();
+// int end1 = (*i)->getEnd() ->getIndex();
+// int start2 = (*j)->getStart()->getIndex();
+// int end2 = (*j)->getEnd()->getIndex();
+// int oppIndex = (*j)->getIndex();
+ //cerr << "Opposite of " << (*i)->getIndex() << " (" << start1 << "," << end1 << ") "
+ // << "happens to be " << oppIndex << " (" << start2 << "," << end2 << ") " << endl;
+ (*i)->setOpposite(*j);
+ break;
+ }
+ j++;
+ }
+ i++;
+ }
+ //FGTaxiNodeVectorIterator j = nodes.begin();
+ //while (j != nodes.end()) {
+ // if ((*j)->getHoldPointType() == 3) {
+ // pushBackNodes.push_back((*j));
+ // }
+ // j++;
+ //}
+ //cerr << "Done initializing ground network" << endl;
+ //exit(1);
}
-int FGGroundNetwork::findNearestNode(const SGGeod& aGeod)
+int FGGroundNetwork::findNearestNode(const SGGeod & aGeod)
{
- double minDist = HUGE_VAL;
- int index = -1;
-
- for (FGTaxiNodeVectorIterator itr = nodes.begin(); itr != nodes.end(); itr++)
- {
- double d = SGGeodesy::distanceM(aGeod, (*itr)->getGeod());
- if (d < minDist)
- {
- minDist = d;
- index = (*itr)->getIndex();
- //cerr << "Minimum distance of " << minDist << " for index " << index << endl;
+ double minDist = HUGE_VAL;
+ int index = -1;
+
+ for (FGTaxiNodeVectorIterator itr = nodes.begin(); itr != nodes.end();
+ itr++) {
+ double d = SGGeodesy::distanceM(aGeod, (*itr)->getGeod());
+ if (d < minDist) {
+ minDist = d;
+ index = (*itr)->getIndex();
+ //cerr << "Minimum distance of " << minDist << " for index " << index << endl;
+ }
}
- }
-
- return index;
+
+ return index;
}
int FGGroundNetwork::findNearestNode(double lat, double lon)
{
- return findNearestNode(SGGeod::fromDeg(lon, lat));
+ return findNearestNode(SGGeod::fromDeg(lon, lat));
}
FGTaxiNode *FGGroundNetwork::findNode(unsigned idx)
-{ /*
- for (FGTaxiNodeVectorIterator
- itr = nodes.begin();
- itr != nodes.end(); itr++)
- {
- if (itr->getIndex() == idx)
- return itr->getAddress();
- }*/
-
- if ((idx >= 0) && (idx < nodes.size()))
- return nodes[idx]->getAddress();
- else
- return 0;
+{ /*
+ for (FGTaxiNodeVectorIterator
+ itr = nodes.begin();
+ itr != nodes.end(); itr++)
+ {
+ if (itr->getIndex() == idx)
+ return itr->getAddress();
+ } */
+
+ if ((idx >= 0) && (idx < nodes.size()))
+ return nodes[idx]->getAddress();
+ else
+ return 0;
}
FGTaxiSegment *FGGroundNetwork::findSegment(unsigned idx)
-{/*
- for (FGTaxiSegmentVectorIterator
- itr = segments.begin();
- itr != segments.end(); itr++)
- {
- if (itr->getIndex() == idx)
- return itr->getAddress();
- }
- */
- if ((idx > 0) && (idx <= segments.size()))
- return segments[idx-1]->getAddress();
- else
- {
- //cerr << "Alert: trying to find invalid segment " << idx << endl;
- return 0;
+{ /*
+ for (FGTaxiSegmentVectorIterator
+ itr = segments.begin();
+ itr != segments.end(); itr++)
+ {
+ if (itr->getIndex() == idx)
+ return itr->getAddress();
+ }
+ */
+ if ((idx > 0) && (idx <= segments.size()))
+ return segments[idx - 1]->getAddress();
+ else {
+ //cerr << "Alert: trying to find invalid segment " << idx << endl;
+ return 0;
}
}
-FGTaxiRoute FGGroundNetwork::findShortestRoute(int start, int end, bool fullSearch)
+FGTaxiRoute FGGroundNetwork::findShortestRoute(int start, int end,
+ bool fullSearch)
{
//implements Dijkstra's algorithm to find shortest distance route from start to end
//taken from http://en.wikipedia.org/wiki/Dijkstra's_algorithm
int nParkings = parent->getDynamics()->getNrOfParkings();
FGTaxiNodeVector *currNodesSet;
if (fullSearch) {
- currNodesSet = &nodes;
+ currNodesSet = &nodes;
} else {
- currNodesSet = &pushBackNodes;
+ currNodesSet = &pushBackNodes;
}
for (FGTaxiNodeVectorIterator
- itr = currNodesSet->begin();
- itr != currNodesSet->end(); itr++) {
- (*itr)->setPathScore(HUGE_VAL); //infinity by all practical means
- (*itr)->setPreviousNode(0); //
- (*itr)->setPreviousSeg (0); //
- }
+ itr = currNodesSet->begin(); itr != currNodesSet->end(); itr++) {
+ (*itr)->setPathScore(HUGE_VAL); //infinity by all practical means
+ (*itr)->setPreviousNode(0); //
+ (*itr)->setPreviousSeg(0); //
+ }
FGTaxiNode *firstNode = findNode(start);
firstNode->setPathScore(0);
- FGTaxiNode *lastNode = findNode(end);
+ FGTaxiNode *lastNode = findNode(end);
- FGTaxiNodeVector unvisited(*currNodesSet); // working copy
+ FGTaxiNodeVector unvisited(*currNodesSet); // working copy
while (!unvisited.empty()) {
- FGTaxiNode* best = *(unvisited.begin());
+ FGTaxiNode *best = *(unvisited.begin());
for (FGTaxiNodeVectorIterator
- itr = unvisited.begin();
- itr != unvisited.end(); itr++) {
- if ((*itr)->getPathScore() < best->getPathScore())
- best = (*itr);
+ itr = unvisited.begin(); itr != unvisited.end(); itr++) {
+ if ((*itr)->getPathScore() < best->getPathScore())
+ best = (*itr);
}
- FGTaxiNodeVectorIterator newend = remove(unvisited.begin(), unvisited.end(), best);
+ FGTaxiNodeVectorIterator newend =
+ remove(unvisited.begin(), unvisited.end(), best);
unvisited.erase(newend, unvisited.end());
-
+
if (best == lastNode) { // found route or best not connected
break;
} else {
seg = best->getBeginRoute();
seg != best->getEndRoute(); seg++) {
if (fullSearch || (*seg)->isPushBack()) {
- FGTaxiNode* tgt = (*seg)->getEnd();
- double alt = best->getPathScore() + (*seg)->getLength() + (*seg)->getPenalty(nParkings);
- if (alt < tgt->getPathScore()) { // Relax (u,v)
+ FGTaxiNode *tgt = (*seg)->getEnd();
+ double alt =
+ best->getPathScore() + (*seg)->getLength() +
+ (*seg)->getPenalty(nParkings);
+ if (alt < tgt->getPathScore()) { // Relax (u,v)
tgt->setPathScore(alt);
tgt->setPreviousNode(best);
- tgt->setPreviousSeg(*seg); //
- }
+ tgt->setPreviousSeg(*seg); //
+ }
} else {
- // // cerr << "Skipping TaxiSegment " << (*seg)->getIndex() << endl;
+ // // cerr << "Skipping TaxiSegment " << (*seg)->getIndex() << endl;
}
}
}
if (lastNode->getPathScore() == HUGE_VAL) {
// no valid route found
- if (fullSearch) {
- SG_LOG( SG_GENERAL, SG_ALERT, "Failed to find route from waypoint " << start << " to " << end << " at " <<
- parent->getId());
+ if (fullSearch) {
+ SG_LOG(SG_GENERAL, SG_ALERT,
+ "Failed to find route from waypoint " << start << " to "
+ << end << " at " << parent->getId());
}
- FGTaxiRoute empty;
- return empty;
+ FGTaxiRoute empty;
+ return empty;
//exit(1); //TODO exit more gracefully, no need to stall the whole sim with broken GN's
} else {
// assemble route from backtrace information
intVec nodes, routes;
- FGTaxiNode* bt = lastNode;
+ FGTaxiNode *bt = lastNode;
while (bt->getPreviousNode() != 0) {
nodes.push_back(bt->getIndex());
routes.push_back(bt->getPreviousSegment()->getIndex());
}
}
-int FGTaxiSegment::getPenalty(int nGates) {
- int penalty = 0;
- if (end->getIndex() < nGates) {
- penalty += 10000;
- }
- if (end->getIsOnRunway()) { // For now. In future versions, need to find out whether runway is active.
- penalty += 1000;
- }
- return penalty;
+int FGTaxiSegment::getPenalty(int nGates)
+{
+ int penalty = 0;
+ if (end->getIndex() < nGates) {
+ penalty += 10000;
+ }
+ if (end->getIsOnRunway()) { // For now. In future versions, need to find out whether runway is active.
+ penalty += 1000;
+ }
+ return penalty;
}
/* ATC Related Functions */
-void FGGroundNetwork::announcePosition(int id, FGAIFlightPlan *intendedRoute, int currentPosition,
- double lat, double lon, double heading,
- double speed, double alt, double radius, int leg,
- FGAIAircraft *aircraft)
+void FGGroundNetwork::announcePosition(int id,
+ FGAIFlightPlan * intendedRoute,
+ int currentPosition, double lat,
+ double lon, double heading,
+ double speed, double alt,
+ double radius, int leg,
+ FGAIAircraft * aircraft)
{
- TrafficVectorIterator i = activeTraffic.begin();
- // Search search if the current id alread has an entry
- // This might be faster using a map instead of a vector, but let's start by taking a safe route
- if (activeTraffic.size()) {
- //while ((i->getId() != id) && i != activeTraffic.end()) {
- while (i != activeTraffic.end()) {
- if (i->getId() == id) {
- break;
- }
- i++;
- }
- }
- // Add a new TrafficRecord if no one exsists for this aircraft.
- if (i == activeTraffic.end() || (activeTraffic.size() == 0)) {
- FGTrafficRecord rec;
- rec.setId(id);
- rec.setPositionAndIntentions(currentPosition, intendedRoute);
- rec.setPositionAndHeading(lat, lon, heading, speed, alt);
- rec.setRadius(radius); // only need to do this when creating the record.
- rec.setAircraft(aircraft);
- activeTraffic.push_back(rec);
- } else {
- i->setPositionAndIntentions(currentPosition, intendedRoute);
- i->setPositionAndHeading(lat, lon, heading, speed, alt);
- }
+ TrafficVectorIterator i = activeTraffic.begin();
+ // Search search if the current id alread has an entry
+ // This might be faster using a map instead of a vector, but let's start by taking a safe route
+ if (activeTraffic.size()) {
+ //while ((i->getId() != id) && i != activeTraffic.end()) {
+ while (i != activeTraffic.end()) {
+ if (i->getId() == id) {
+ break;
+ }
+ i++;
+ }
+ }
+ // Add a new TrafficRecord if no one exsists for this aircraft.
+ if (i == activeTraffic.end() || (activeTraffic.size() == 0)) {
+ FGTrafficRecord rec;
+ rec.setId(id);
+ rec.setLeg(leg);
+ rec.setPositionAndIntentions(currentPosition, intendedRoute);
+ rec.setPositionAndHeading(lat, lon, heading, speed, alt);
+ rec.setRadius(radius); // only need to do this when creating the record.
+ rec.setAircraft(aircraft);
+ activeTraffic.push_back(rec);
+ } else {
+ i->setPositionAndIntentions(currentPosition, intendedRoute);
+ i->setPositionAndHeading(lat, lon, heading, speed, alt);
+ }
}
-void FGGroundNetwork::signOff(int id) {
- TrafficVectorIterator i = activeTraffic.begin();
- // Search search if the current id alread has an entry
- // This might be faster using a map instead of a vector, but let's start by taking a safe route
- if (activeTraffic.size()) {
- //while ((i->getId() != id) && i != activeTraffic.end()) {
- while (i != activeTraffic.end()) {
- if (i->getId() == id) {
- break;
- }
- i++;
- }
- }
- if (i == activeTraffic.end() || (activeTraffic.size() == 0)) {
- SG_LOG(SG_GENERAL, SG_ALERT, "AI error: Aircraft without traffic record is signing off");
- } else {
- i = activeTraffic.erase(i);
- }
+void FGGroundNetwork::signOff(int id)
+{
+ TrafficVectorIterator i = activeTraffic.begin();
+ // Search search if the current id alread has an entry
+ // This might be faster using a map instead of a vector, but let's start by taking a safe route
+ if (activeTraffic.size()) {
+ //while ((i->getId() != id) && i != activeTraffic.end()) {
+ while (i != activeTraffic.end()) {
+ if (i->getId() == id) {
+ break;
+ }
+ i++;
+ }
+ }
+ if (i == activeTraffic.end() || (activeTraffic.size() == 0)) {
+ SG_LOG(SG_GENERAL, SG_ALERT,
+ "AI error: Aircraft without traffic record is signing off");
+ } else {
+ i = activeTraffic.erase(i);
+ }
}
-void FGGroundNetwork::update(int id, double lat, double lon, double heading, double speed, double alt,
- double dt) {
- // Check whether aircraft are on hold due to a preceding pushback. If so, make sure to
- // Transmit air-to-ground "Ready to taxi request:
- // Transmit ground to air approval / hold
- // Transmit confirmation ...
- // Probably use a status mechanism similar to the Engine start procedure in the startup controller.
-
-
- TrafficVectorIterator i = activeTraffic.begin();
- // Search search if the current id has an entry
- // This might be faster using a map instead of a vector, but let's start by taking a safe route
- TrafficVectorIterator current, closest;
- if (activeTraffic.size()) {
- //while ((i->getId() != id) && i != activeTraffic.end()) {
- while (i != activeTraffic.end()) {
- if (i->getId() == id) {
- break;
- }
- i++;
- }
- }
- // update position of the current aircraft
- if (i == activeTraffic.end() || (activeTraffic.size() == 0)) {
- SG_LOG(SG_GENERAL, SG_ALERT, "AI error: updating aircraft without traffic record");
- } else {
- i->setPositionAndHeading(lat, lon, heading, speed, alt);
- current = i;
- }
-
- setDt(getDt() + dt);
-
- // Update every three secs, but add some randomness
- // to prevent all IA objects doing this in synchrony
- //if (getDt() < (3.0) + (rand() % 10))
- // return;
- //else
- // setDt(0);
- current->clearResolveCircularWait();
- current->setWaitsForId(0);
- checkSpeedAdjustment(id, lat, lon, heading, speed, alt);
- checkHoldPosition (id, lat, lon, heading, speed, alt);
- if (checkForCircularWaits(id)) {
- i->setResolveCircularWait();
- }
+void FGGroundNetwork::update(int id, double lat, double lon,
+ double heading, double speed, double alt,
+ double dt)
+{
+ // Check whether aircraft are on hold due to a preceding pushback. If so, make sure to
+ // Transmit air-to-ground "Ready to taxi request:
+ // Transmit ground to air approval / hold
+ // Transmit confirmation ...
+ // Probably use a status mechanism similar to the Engine start procedure in the startup controller.
+
+
+ TrafficVectorIterator i = activeTraffic.begin();
+ // Search search if the current id has an entry
+ // This might be faster using a map instead of a vector, but let's start by taking a safe route
+ TrafficVectorIterator current, closest;
+ if (activeTraffic.size()) {
+ //while ((i->getId() != id) && i != activeTraffic.end()) {
+ while (i != activeTraffic.end()) {
+ if (i->getId() == id) {
+ break;
+ }
+ i++;
+ }
+ }
+ // update position of the current aircraft
+ if (i == activeTraffic.end() || (activeTraffic.size() == 0)) {
+ SG_LOG(SG_GENERAL, SG_ALERT,
+ "AI error: updating aircraft without traffic record");
+ } else {
+ i->setPositionAndHeading(lat, lon, heading, speed, alt);
+ current = i;
+ }
+
+ setDt(getDt() + dt);
+
+ // Update every three secs, but add some randomness
+ // to prevent all IA objects doing this in synchrony
+ //if (getDt() < (3.0) + (rand() % 10))
+ // return;
+ //else
+ // setDt(0);
+ current->clearResolveCircularWait();
+ current->setWaitsForId(0);
+ checkSpeedAdjustment(id, lat, lon, heading, speed, alt);
+ checkHoldPosition(id, lat, lon, heading, speed, alt);
+ if (checkForCircularWaits(id)) {
+ i->setResolveCircularWait();
+ }
+ bool needsTaxiClearance = current->getAircraft()->getTaxiClearanceRequest();
+ int state = current->getState();
+ time_t now = time(NULL) + fgGetLong("/sim/time/warp");
+ if ((now - lastTransmission) > 15) {
+ available = true;
+ }
+ if (needsTaxiClearance && available) {
+ transmit(&(*current), MSG_REQUEST_TAXI_CLEARANCE, ATC_AIR_TO_GROUND);
+ current->getAircraft()->setTaxiClearanceRequest(false);
+ current->setState(3);
+ lastTransmission = now;
+ available = false;
+ }
+ if ((state == 3) && available) {
+ transmit(&(*current), MSG_ISSUE_TAXI_CLEARANCE, ATC_GROUND_TO_AIR);
+ current->setState(4);
+ lastTransmission = now;
+ available = false;
+ }
+ if ((state == 4) && available) {
+ transmit(&(*current), MSG_ACKNOWLEDGE_TAXI_CLEARANCE, ATC_AIR_TO_GROUND);
+ current->setState(0);
+ lastTransmission = now;
+ available = false;
+ }
}
/**
not addressed yet, but should be.
*/
-void FGGroundNetwork::checkSpeedAdjustment(int id, double lat,
- double lon, double heading,
- double speed, double alt)
+void FGGroundNetwork::checkSpeedAdjustment(int id, double lat,
+ double lon, double heading,
+ double speed, double alt)
{
-
- TrafficVectorIterator current, closest;
- TrafficVectorIterator i = activeTraffic.begin();
- bool otherReasonToSlowDown = false;
- bool previousInstruction;
- if (activeTraffic.size())
- {
- //while ((i->getId() != id) && (i != activeTraffic.end()))
- while (i != activeTraffic.end()) {
- if (i->getId() == id) {
- break;
- }
- i++;
- }
- }
- else
- {
- return;
- }
- if (i == activeTraffic.end() || (activeTraffic.size() == 0)) {
- SG_LOG(SG_GENERAL, SG_ALERT, "AI error: Trying to access non-existing aircraft in FGGroundNetwork::checkSpeedAdjustment");
- }
- current = i;
- //closest = current;
-
- previousInstruction = current->getSpeedAdjustment();
- double mindist = HUGE_VAL;
- if (activeTraffic.size())
- {
- double course, dist, bearing, minbearing, az2;
- SGGeod curr(SGGeod::fromDegM(lon, lat, alt));
- //TrafficVector iterator closest;
- closest = current;
- for (TrafficVectorIterator i = activeTraffic.begin();
- i != activeTraffic.end(); i++)
- {
- if (i == current) {
- continue;
- }
-
- SGGeod other(SGGeod::fromDegM(i->getLongitude(),
- i->getLatitude(), i->getAltitude()));
- SGGeodesy::inverse(curr, other, course, az2, dist);
- bearing = fabs(heading-course);
- if (bearing > 180)
- bearing = 360-bearing;
- if ((dist < mindist) && (bearing < 60.0))
- {
- mindist = dist;
- closest = i;
- minbearing = bearing;
- }
- }
- //Check traffic at the tower controller
- if (towerController->hasActiveTraffic())
- {
- for (TrafficVectorIterator i = towerController->getActiveTraffic().begin();
- i != towerController->getActiveTraffic().end(); i++)
- {
- //cerr << "Comparing " << current->getId() << " and " << i->getId() << endl;
- SGGeod other(SGGeod::fromDegM(i->getLongitude(),
- i->getLatitude(),
- i->getAltitude()));
- SGGeodesy::inverse(curr, other, course, az2, dist);
- bearing = fabs(heading-course);
- if (bearing > 180)
- bearing = 360-bearing;
- if ((dist < mindist) && (bearing < 60.0))
- {
- mindist = dist;
- closest = i;
- minbearing = bearing;
- otherReasonToSlowDown = true;
- }
- }
- }
- // Finally, check UserPosition
- double userLatitude = fgGetDouble("/position/latitude-deg");
- double userLongitude = fgGetDouble("/position/longitude-deg");
- SGGeod user(SGGeod::fromDeg(userLongitude,userLatitude));
- SGGeodesy::inverse(curr, user, course, az2, dist);
-
- bearing = fabs(heading-course);
- if (bearing > 180)
- bearing = 360-bearing;
- if ((dist < mindist) && (bearing < 60.0))
- {
- mindist = dist;
- //closest = i;
- minbearing = bearing;
- otherReasonToSlowDown = true;
- }
-
- current->clearSpeedAdjustment();
-
- if (current->checkPositionAndIntentions(*closest) || otherReasonToSlowDown)
- {
- double maxAllowableDistance = (1.1*current->getRadius()) + (1.1*closest->getRadius());
- if (mindist < 2*maxAllowableDistance)
- {
- if (current->getId() == closest->getWaitsForId())
- return;
- else
- current->setWaitsForId(closest->getId());
- if (closest->getId() != current->getId())
- current->setSpeedAdjustment(closest->getSpeed()* (mindist/100));
- 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);
- //if (mindist < 0.5* maxAllowableDistance)
- // {
- current->setSpeedAdjustment(0);
- // }
- }
- }
- }
+
+ TrafficVectorIterator current, closest;
+ TrafficVectorIterator i = activeTraffic.begin();
+ bool otherReasonToSlowDown = false;
+ bool previousInstruction;
+ if (activeTraffic.size()) {
+ //while ((i->getId() != id) && (i != activeTraffic.end()))
+ while (i != activeTraffic.end()) {
+ if (i->getId() == id) {
+ break;
+ }
+ i++;
+ }
+ } else {
+ return;
+ }
+ if (i == activeTraffic.end() || (activeTraffic.size() == 0)) {
+ SG_LOG(SG_GENERAL, SG_ALERT,
+ "AI error: Trying to access non-existing aircraft in FGGroundNetwork::checkSpeedAdjustment");
+ }
+ current = i;
+ //closest = current;
+
+ previousInstruction = current->getSpeedAdjustment();
+ double mindist = HUGE_VAL;
+ if (activeTraffic.size()) {
+ double course, dist, bearing, minbearing, az2;
+ SGGeod curr(SGGeod::fromDegM(lon, lat, alt));
+ //TrafficVector iterator closest;
+ closest = current;
+ for (TrafficVectorIterator i = activeTraffic.begin();
+ i != activeTraffic.end(); i++) {
+ if (i == current) {
+ continue;
+ }
+
+ SGGeod other(SGGeod::fromDegM(i->getLongitude(),
+ i->getLatitude(),
+ i->getAltitude()));
+ SGGeodesy::inverse(curr, other, course, az2, dist);
+ bearing = fabs(heading - course);
+ if (bearing > 180)
+ bearing = 360 - bearing;
+ if ((dist < mindist) && (bearing < 60.0)) {
+ mindist = dist;
+ closest = i;
+ minbearing = bearing;
+ }
+ }
+ //Check traffic at the tower controller
+ if (towerController->hasActiveTraffic()) {
+ for (TrafficVectorIterator i =
+ towerController->getActiveTraffic().begin();
+ i != towerController->getActiveTraffic().end(); i++) {
+ //cerr << "Comparing " << current->getId() << " and " << i->getId() << endl;
+ SGGeod other(SGGeod::fromDegM(i->getLongitude(),
+ i->getLatitude(),
+ i->getAltitude()));
+ SGGeodesy::inverse(curr, other, course, az2, dist);
+ bearing = fabs(heading - course);
+ if (bearing > 180)
+ bearing = 360 - bearing;
+ if ((dist < mindist) && (bearing < 60.0)) {
+ mindist = dist;
+ closest = i;
+ minbearing = bearing;
+ otherReasonToSlowDown = true;
+ }
+ }
+ }
+ // Finally, check UserPosition
+ double userLatitude = fgGetDouble("/position/latitude-deg");
+ double userLongitude = fgGetDouble("/position/longitude-deg");
+ SGGeod user(SGGeod::fromDeg(userLongitude, userLatitude));
+ SGGeodesy::inverse(curr, user, course, az2, dist);
+
+ bearing = fabs(heading - course);
+ if (bearing > 180)
+ bearing = 360 - bearing;
+ if ((dist < mindist) && (bearing < 60.0)) {
+ mindist = dist;
+ //closest = i;
+ minbearing = bearing;
+ otherReasonToSlowDown = true;
+ }
+
+ current->clearSpeedAdjustment();
+
+ if (current->checkPositionAndIntentions(*closest)
+ || otherReasonToSlowDown) {
+ double maxAllowableDistance =
+ (1.1 * current->getRadius()) +
+ (1.1 * closest->getRadius());
+ if (mindist < 2 * maxAllowableDistance) {
+ if (current->getId() == closest->getWaitsForId())
+ return;
+ else
+ current->setWaitsForId(closest->getId());
+ if (closest->getId() != current->getId())
+ current->setSpeedAdjustment(closest->getSpeed() *
+ (mindist / 100));
+ 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);
+ //if (mindist < 0.5* maxAllowableDistance)
+ // {
+ current->setSpeedAdjustment(0);
+ // }
+ }
+ }
+ }
}
}
3) For crossing or merging taxiroutes.
*/
-void FGGroundNetwork::checkHoldPosition(int id, double lat,
- double lon, double heading,
- double speed, double alt)
+void FGGroundNetwork::checkHoldPosition(int id, double lat,
+ double lon, double heading,
+ double speed, double alt)
{
-
- TrafficVectorIterator current;
- TrafficVectorIterator i = activeTraffic.begin();
- if (activeTraffic.size())
- {
- //while ((i->getId() != id) && i != activeTraffic.end())
- while (i != activeTraffic.end()) {
- if (i->getId() == id) {
- break;
- }
- i++;
- }
- }
- else
- {
- return ;
- }
- if (i == activeTraffic.end() || (activeTraffic.size() == 0)) {
- SG_LOG(SG_GENERAL, SG_ALERT, "AI error: Trying to access non-existing aircraft in FGGroundNetwork::checkHoldPosition");
- }
- current = i;
- current->setHoldPosition(false);
- SGGeod curr(SGGeod::fromDegM(lon, lat, alt));
-
- for (i = activeTraffic.begin();
- i != activeTraffic.end(); i++)
- {
- if (i->getId() != current->getId())
- {
- int node = current->crosses(this, *i);
- if (node != -1)
- {
- FGTaxiNode* taxiNode = findNode(node);
-
- // Determine whether it's save to continue or not.
- // If we have a crossing route, there are two possibilities:
- // 1) This is an interestion
- // 2) This is oncoming two-way traffic, using the same taxiway.
- //cerr << "Hold check 1 : " << id << " has common node " << node << endl;
-
- SGGeod other(SGGeod::fromDegM(i->getLongitude(), i->getLatitude(), i->getAltitude()));
- bool needsToWait;
- bool opposing;
- if (current->isOpposing(this, *i, node))
- {
- needsToWait = true;
- opposing = true;
- //cerr << "Hold check 2 : " << node << " has opposing segment " << endl;
- // issue a "Hold Position" as soon as we're close to the offending node
- // For now, I'm doing this as long as the other aircraft doesn't
- // have a hold instruction as soon as we're within a reasonable
- // distance from the offending node.
- // This may be a bit of a conservative estimate though, as it may
- // be well possible that both aircraft can both continue to taxi
- // without crashing into each other.
- }
- else
- {
- opposing = false;
- if (SGGeodesy::distanceM(other, taxiNode->getGeod()) > 200) // 2.0*i->getRadius())
- {
- needsToWait = false;
- //cerr << "Hold check 3 : " << id <<" Other aircraft approaching node is still far away. (" << dist << " nm). Can safely continue "
- // << endl;
- }
- else
- {
- needsToWait = true;
- //cerr << "Hold check 4: " << id << " Would need to wait for other aircraft : distance = " << dist << " meters" << endl;
- }
- }
-
- double dist = SGGeodesy::distanceM(curr, taxiNode->getGeod());
- if (!(i->hasHoldPosition()))
- {
-
- if ((dist < 200) && //2.5*current->getRadius()) &&
- (needsToWait) &&
- (i->onRoute(this, *current)) &&
- //((i->onRoute(this, *current)) || ((!(i->getSpeedAdjustment())))) &&
- (!(current->getId() == i->getWaitsForId())))
- //(!(i->getSpeedAdjustment()))) // &&
- //(!(current->getSpeedAdjustment())))
-
- {
- 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)
- //cerr <<" [opposing] " << endl;
- //else
- // cerr << "[non-opposing] " << endl;
- //if (i->hasSpeefAdjustment())
- // {
- // cerr << " (which in turn waits for ) " << i->
- }
- else
- {
- //cerr << "Hold check 6: " << id << " No need to hold yet: Distance to node : " << dist << " nm"<< endl;
- }
- }
- }
- }
+ TrafficVectorIterator current;
+ TrafficVectorIterator i = activeTraffic.begin();
+ if (activeTraffic.size()) {
+ //while ((i->getId() != id) && i != activeTraffic.end())
+ while (i != activeTraffic.end()) {
+ if (i->getId() == id) {
+ break;
+ }
+ i++;
+ }
+ } else {
+ return;
+ }
+ if (i == activeTraffic.end() || (activeTraffic.size() == 0)) {
+ SG_LOG(SG_GENERAL, SG_ALERT,
+ "AI error: Trying to access non-existing aircraft in FGGroundNetwork::checkHoldPosition");
+ }
+ current = i;
+ bool origStatus = current->hasHoldPosition();
+ current->setHoldPosition(false);
+ SGGeod curr(SGGeod::fromDegM(lon, lat, alt));
+
+ for (i = activeTraffic.begin(); i != activeTraffic.end(); i++) {
+ if (i->getId() != current->getId()) {
+ int node = current->crosses(this, *i);
+ if (node != -1) {
+ FGTaxiNode *taxiNode = findNode(node);
+
+ // Determine whether it's save to continue or not.
+ // If we have a crossing route, there are two possibilities:
+ // 1) This is an interestion
+ // 2) This is oncoming two-way traffic, using the same taxiway.
+ //cerr << "Hold check 1 : " << id << " has common node " << node << endl;
+
+ SGGeod other(SGGeod::
+ fromDegM(i->getLongitude(), i->getLatitude(),
+ i->getAltitude()));
+ bool needsToWait;
+ bool opposing;
+ if (current->isOpposing(this, *i, node)) {
+ needsToWait = true;
+ opposing = true;
+ //cerr << "Hold check 2 : " << node << " has opposing segment " << endl;
+ // issue a "Hold Position" as soon as we're close to the offending node
+ // For now, I'm doing this as long as the other aircraft doesn't
+ // have a hold instruction as soon as we're within a reasonable
+ // distance from the offending node.
+ // This may be a bit of a conservative estimate though, as it may
+ // be well possible that both aircraft can both continue to taxi
+ // without crashing into each other.
+ } else {
+ opposing = false;
+ if (SGGeodesy::distanceM(other, taxiNode->getGeod()) > 200) // 2.0*i->getRadius())
+ {
+ needsToWait = false;
+ //cerr << "Hold check 3 : " << id <<" Other aircraft approaching node is still far away. (" << dist << " nm). Can safely continue "
+ // << endl;
+ } else {
+ needsToWait = true;
+ //cerr << "Hold check 4: " << id << " Would need to wait for other aircraft : distance = " << dist << " meters" << endl;
+ }
+ }
+
+ double dist =
+ SGGeodesy::distanceM(curr, taxiNode->getGeod());
+ if (!(i->hasHoldPosition())) {
+
+ if ((dist < 200) && //2.5*current->getRadius()) &&
+ (needsToWait) && (i->onRoute(this, *current)) &&
+ //((i->onRoute(this, *current)) || ((!(i->getSpeedAdjustment())))) &&
+ (!(current->getId() == i->getWaitsForId())))
+ //(!(i->getSpeedAdjustment()))) // &&
+ //(!(current->getSpeedAdjustment())))
+
+ {
+ 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)
+ //cerr <<" [opposing] " << endl;
+ //else
+ // cerr << "[non-opposing] " << endl;
+ //if (i->hasSpeefAdjustment())
+ // {
+ // cerr << " (which in turn waits for ) " << i->
+ } else {
+ //cerr << "Hold check 6: " << id << " No need to hold yet: Distance to node : " << dist << " nm"<< endl;
+ }
+ }
+ }
+ }
+ }
+ bool currStatus = current->hasHoldPosition();
+
+ // 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 ((origStatus != currStatus) && available) {
+ //cerr << "Issueing hold short instrudtion " << currStatus << " " << available << endl;
+ if (currStatus == true) { // No has a hold short instruction
+ transmit(&(*current), MSG_HOLD_POSITION, ATC_GROUND_TO_AIR);
+ //cerr << "Transmittin hold short instrudtion " << currStatus << " " << available << endl;
+ current->setState(1);
+ } else {
+ transmit(&(*current), MSG_RESUME_TAXI, ATC_GROUND_TO_AIR);
+ //cerr << "Transmittig resume instrudtion " << currStatus << " " << available << endl;
+ current->setState(2);
+ }
+ lastTransmission = now;
+ available = false;
+ // Don't act on the changed instruction until the transmission is confirmed
+ // So set back to original status
+ current->setHoldPosition(origStatus);
+ //cerr << "Current state " << current->getState() << endl;
+ } else {
+ }
+ int state = current->getState();
+ if ((state == 1) && (available)) {
+ //cerr << "ACKNOWLEDGE HOLD" << endl;
+ transmit(&(*current), MSG_ACKNOWLEDGE_HOLD_POSITION, ATC_AIR_TO_GROUND);
+ current->setState(0);
+ current->setHoldPosition(true);
+ lastTransmission = now;
+ available = false;
+
+ }
+ if ((state == 2) && (available)) {
+ //cerr << "ACKNOWLEDGE RESUME" << endl;
+ transmit(&(*current), MSG_ACKNOWLEDGE_RESUME_TAXI, ATC_AIR_TO_GROUND);
+ current->setState(0);
+ current->setHoldPosition(false);
+ lastTransmission = now;
+ available = false;
}
}
*/
bool FGGroundNetwork::checkForCircularWaits(int id)
-{
- //cerr << "Performing Wait check " << id << endl;
- int target = 0;
- TrafficVectorIterator current, other;
- TrafficVectorIterator i = activeTraffic.begin();
- int trafficSize = activeTraffic.size();
- if (trafficSize) {
+{
+ //cerr << "Performing Wait check " << id << endl;
+ int target = 0;
+ TrafficVectorIterator current, other;
+ TrafficVectorIterator i = activeTraffic.begin();
+ int trafficSize = activeTraffic.size();
+ if (trafficSize) {
while (i != activeTraffic.end()) {
- if (i->getId() == id) {
- break;
- }
- i++;
- }
- }
- else {
- return false;
- }
- if (i == activeTraffic.end() || (trafficSize == 0)) {
- SG_LOG(SG_GENERAL, SG_ALERT, "AI error: Trying to access non-existing aircraft in FGGroundNetwork::checkForCircularWaits");
- }
-
- current = i;
- target = current->getWaitsForId();
- //bool printed = false; // Note that this variable is for debugging purposes only.
- int counter = 0;
-
- if (id == target) {
- //cerr << "aircraft waits for user" << endl;
- return false;
- }
-
-
- while ((target > 0) && (target != id) && counter++ < trafficSize) {
- //printed = true;
- TrafficVectorIterator i = activeTraffic.begin();
- if (trafficSize) {
- //while ((i->getId() != id) && i != activeTraffic.end())
- while (i != activeTraffic.end()) {
- if (i->getId() == target) {
- break;
- }
- i++;
+ if (i->getId() == id) {
+ break;
+ }
+ i++;
}
- }
- else {
+ } else {
return false;
- }
+ }
if (i == activeTraffic.end() || (trafficSize == 0)) {
- //cerr << "[Waiting for traffic at Runway: DONE] " << endl << endl;;
- // The target id is not found on the current network, which means it's at the tower
- //SG_LOG(SG_GENERAL, SG_ALERT, "AI error: Trying to access non-existing aircraft in FGGroundNetwork::checkForCircularWaits");
- return false;
- }
- other = i;
- target = other->getWaitsForId();
-
- // actually this trap isn't as impossible as it first seemed:
- // the setWaitsForID(id) is set to current when the aircraft
- // is waiting for the user controlled aircraft.
- //if (current->getId() == other->getId()) {
- // cerr << "Caught the impossible trap" << endl;
- // cerr << "Current = " << current->getId() << endl;
- // cerr << "Other = " << other ->getId() << endl;
- // for (TrafficVectorIterator at = activeTraffic.begin();
- // at != activeTraffic.end();
- // at++) {
- // cerr << "currently active aircraft : " << at->getCallSign() << " with Id " << at->getId() << " waits for " << at->getWaitsForId() << endl;
- // }
- // exit(1);
- if (current->getId() == other->getId())
- return false;
- //}
- //cerr << current->getCallSign() << " (" << current->getId() << ") " << " -> " << other->getCallSign()
- // << " (" << other->getId() << "); " << endl;;
- //current = other;
- }
+ SG_LOG(SG_GENERAL, SG_ALERT,
+ "AI error: Trying to access non-existing aircraft in FGGroundNetwork::checkForCircularWaits");
+ }
+
+ current = i;
+ target = current->getWaitsForId();
+ //bool printed = false; // Note that this variable is for debugging purposes only.
+ int counter = 0;
+
+ if (id == target) {
+ //cerr << "aircraft waits for user" << endl;
+ return false;
+ }
+
+
+ while ((target > 0) && (target != id) && counter++ < trafficSize) {
+ //printed = true;
+ TrafficVectorIterator i = activeTraffic.begin();
+ if (trafficSize) {
+ //while ((i->getId() != id) && i != activeTraffic.end())
+ while (i != activeTraffic.end()) {
+ if (i->getId() == target) {
+ break;
+ }
+ i++;
+ }
+ } else {
+ return false;
+ }
+ if (i == activeTraffic.end() || (trafficSize == 0)) {
+ //cerr << "[Waiting for traffic at Runway: DONE] " << endl << endl;;
+ // The target id is not found on the current network, which means it's at the tower
+ //SG_LOG(SG_GENERAL, SG_ALERT, "AI error: Trying to access non-existing aircraft in FGGroundNetwork::checkForCircularWaits");
+ return false;
+ }
+ other = i;
+ target = other->getWaitsForId();
+
+ // actually this trap isn't as impossible as it first seemed:
+ // the setWaitsForID(id) is set to current when the aircraft
+ // is waiting for the user controlled aircraft.
+ //if (current->getId() == other->getId()) {
+ // cerr << "Caught the impossible trap" << endl;
+ // cerr << "Current = " << current->getId() << endl;
+ // cerr << "Other = " << other ->getId() << endl;
+ // for (TrafficVectorIterator at = activeTraffic.begin();
+ // at != activeTraffic.end();
+ // at++) {
+ // cerr << "currently active aircraft : " << at->getCallSign() << " with Id " << at->getId() << " waits for " << at->getWaitsForId() << endl;
+ // }
+ // exit(1);
+ if (current->getId() == other->getId())
+ return false;
+ //}
+ //cerr << current->getCallSign() << " (" << current->getId() << ") " << " -> " << other->getCallSign()
+ // << " (" << other->getId() << "); " << endl;;
+ //current = other;
+ }
- //if (printed)
- // cerr << "[done] " << endl << endl;;
- if (id == target) {
- SG_LOG(SG_GENERAL, SG_WARN, "Detected circular wait condition: Id = " << id << "target = " << target);
- return true;
- } else {
- return false;
- }
+ //if (printed)
+ // cerr << "[done] " << endl << endl;;
+ if (id == target) {
+ SG_LOG(SG_GENERAL, SG_WARN,
+ "Detected circular wait condition: Id = " << id <<
+ "target = " << target);
+ return true;
+ } else {
+ return false;
+ }
}
// Note that this function is probably obsolete...
bool FGGroundNetwork::hasInstruction(int id)
{
TrafficVectorIterator i = activeTraffic.begin();
- // Search search if the current id has an entry
- // This might be faster using a map instead of a vector, but let's start by taking a safe route
- if (activeTraffic.size())
- {
- //while ((i->getId() != id) && i != activeTraffic.end()) {
- while (i != activeTraffic.end()) {
- if (i->getId() == id) {
- break;
- }
- i++;
- }
- }
- if (i == activeTraffic.end() || (activeTraffic.size() == 0)) {
- SG_LOG(SG_GENERAL, SG_ALERT, "AI error: checking ATC instruction for aircraft without traffic record");
- } else {
- return i->hasInstruction();
- }
- return false;
+ // Search search if the current id has an entry
+ // This might be faster using a map instead of a vector, but let's start by taking a safe route
+ if (activeTraffic.size()) {
+ //while ((i->getId() != id) && i != activeTraffic.end()) {
+ while (i != activeTraffic.end()) {
+ if (i->getId() == id) {
+ break;
+ }
+ i++;
+ }
+ }
+ if (i == activeTraffic.end() || (activeTraffic.size() == 0)) {
+ SG_LOG(SG_GENERAL, SG_ALERT,
+ "AI error: checking ATC instruction for aircraft without traffic record");
+ } else {
+ return i->hasInstruction();
+ }
+ return false;
}
FGATCInstruction FGGroundNetwork::getInstruction(int id)
{
- TrafficVectorIterator i = activeTraffic.begin();
- // Search search if the current id has an entry
- // This might be faster using a map instead of a vector, but let's start by taking a safe route
- if (activeTraffic.size()) {
- //while ((i->getId() != id) && i != activeTraffic.end()) {
- while (i != activeTraffic.end()) {
- if (i->getId() == id) {
- break;
- }
- i++;
- }
- }
- if (i == activeTraffic.end() || (activeTraffic.size() == 0)) {
- SG_LOG(SG_GENERAL, SG_ALERT, "AI error: requesting ATC instruction for aircraft without traffic record");
- } else {
- return i->getInstruction();
- }
- return FGATCInstruction();
+ TrafficVectorIterator i = activeTraffic.begin();
+ // Search search if the current id has an entry
+ // This might be faster using a map instead of a vector, but let's start by taking a safe route
+ if (activeTraffic.size()) {
+ //while ((i->getId() != id) && i != activeTraffic.end()) {
+ while (i != activeTraffic.end()) {
+ if (i->getId() == id) {
+ break;
+ }
+ i++;
+ }
+ }
+ if (i == activeTraffic.end() || (activeTraffic.size() == 0)) {
+ SG_LOG(SG_GENERAL, SG_ALERT,
+ "AI error: requesting ATC instruction for aircraft without traffic record");
+ } else {
+ return i->getInstruction();
+ }
+ return FGATCInstruction();
}
-
-