-// There is probably a computationally cheaper way of
+// There is probably a computationally cheaper way of
// doing this.
void FGTaxiSegment::setDimensions(double elevation)
{
} 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.
+ // 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);
}
return (*a) < (*b);
}
+bool compare_trafficrecords(FGTrafficRecord a, FGTrafficRecord b)
+{
+ return (a.getIntentions().size() < b.getIntentions().size());
+}
+
FGGroundNetwork::FGGroundNetwork()
{
hasNetwork = false;
}
cachefile << "[GroundNetcachedata:ref:2011:09:04]" << endl;
for (FGTaxiNodeVectorIterator node = nodes.begin();
- node != nodes.end(); node++) {
- if (saveData) {
+ node != nodes.end(); node++) {
+ if (saveData) {
cachefile << (*node)->getIndex () << " "
- << (*node)->getElevation () << " "
- << endl;
- }
+ << (*node)->getElevation () << " "
+ << endl;
+ }
delete(*node);
}
nodes.clear();
pushBackNodes.clear();
for (FGTaxiSegmentVectorIterator seg = segments.begin();
- seg != segments.end(); seg++) {
+ seg != segments.end(); seg++) {
delete(*seg);
}
segments.clear();
}
cachefile << "[GroundNetcachedata:ref:2011:09:04]" << endl;
for (FGTaxiNodeVectorIterator node = nodes.begin();
- node != nodes.end(); node++) {
- if (saveData) {
+ node != nodes.end(); node++) {
+ if (saveData) {
cachefile << (*node)->getIndex () << " "
- << (*node)->getElevation () << " "
- << endl;
- }
+ << (*node)->getElevation () << " "
+ << endl;
+ }
}
if (saveData) {
cachefile.close();
string revisionStr;
data >> revisionStr;
if (revisionStr != "[GroundNetcachedata:ref:2011:09:04]") {
- SG_LOG(SG_GENERAL, SG_ALERT,"GroundNetwork Warning: discarding outdated cachefile " <<
- cacheData.c_str() << " for Airport " << airport);
+ SG_LOG(SG_GENERAL, SG_ALERT,"GroundNetwork Warning: discarding outdated cachefile " <<
+ cacheData.c_str() << " for Airport " << airport);
} else {
for (FGTaxiNodeVectorIterator i = nodes.begin();
- i != nodes.end();
- i++) {
+ i != nodes.end();
+ i++) {
(*i)->setElevation(parent->getElevation() * SG_FEET_TO_METER);
data >> index >> elev;
if (data.eof())
int index = -1;
for (FGTaxiNodeVectorIterator itr = nodes.begin(); itr != nodes.end();
- itr++) {
+ itr++) {
double d = SGGeodesy::distanceM(aGeod, (*itr)->getGeod());
if (d < minDist) {
minDist = d;
FGTaxiNode *FGGroundNetwork::findNode(unsigned idx)
{ /*
- for (FGTaxiNodeVectorIterator
+ for (FGTaxiNodeVectorIterator
itr = nodes.begin();
itr != nodes.end(); itr++)
{
FGTaxiSegment *FGGroundNetwork::findSegment(unsigned idx)
{ /*
- for (FGTaxiSegmentVectorIterator
+ 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();
FGTaxiRoute FGGroundNetwork::findShortestRoute(int start, int end,
- bool fullSearch)
+ 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
}
for (FGTaxiNodeVectorIterator
- itr = currNodesSet->begin(); itr != currNodesSet->end(); itr++) {
+ itr = currNodesSet->begin(); itr != currNodesSet->end(); itr++) {
(*itr)->setPathScore(HUGE_VAL); //infinity by all practical means
(*itr)->setPreviousNode(0); //
(*itr)->setPreviousSeg(0); //
while (!unvisited.empty()) {
FGTaxiNode *best = *(unvisited.begin());
for (FGTaxiNodeVectorIterator
- itr = unvisited.begin(); itr != unvisited.end(); itr++) {
+ itr = unvisited.begin(); itr != unvisited.end(); itr++) {
if ((*itr)->getPathScore() < best->getPathScore())
best = (*itr);
}
break;
} else {
for (FGTaxiSegmentVectorIterator
- seg = best->getBeginRoute();
- seg != best->getEndRoute(); seg++) {
+ seg = best->getBeginRoute();
+ seg != best->getEndRoute(); seg++) {
if (fullSearch || (*seg)->isPushBack()) {
FGTaxiNode *tgt = (*seg)->getEnd();
double alt =
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);
+ activeTraffic.push_front(rec);
+
} else {
i->setPositionAndIntentions(currentPosition, intendedRoute);
i->setPositionAndHeading(lat, lon, heading, speed, alt);
* 9 = Acknowledge switch tower frequency
*************************************************************************************************************************/
bool FGGroundNetwork::checkTransmissionState(int minState, int maxState, TrafficVectorIterator i, time_t now, AtcMsgId msgId,
- AtcMsgDir msgDir)
+ AtcMsgDir msgDir)
{
int state = i->getState();
if ((state >= minState) && (state <= maxState) && available) {
int n = trans_num->getIntValue();
if (n == 0) {
trans_num->setIntValue(-1);
- // PopupCallback(n);
- //cerr << "Selected transmission message " << n << endl;
- FGATCManager *atc = (FGATCManager*) globals->get_subsystem("atc");
- FGATCDialogNew::instance()->removeEntry(1);
+ // PopupCallback(n);
+ //cerr << "Selected transmission message " << n << endl;
+ FGATCManager *atc = (FGATCManager*) globals->get_subsystem("atc");
+ FGATCDialogNew::instance()->removeEntry(1);
} else {
//cerr << "creating message for " << i->getAircraft()->getCallSign() << endl;
- transmit(&(*i), msgId, msgDir, false);
+ transmit(&(*i), &(*parent->getDynamics()), msgId, msgDir, false);
return false;
}
}
- transmit(&(*i), msgId, msgDir, true);
+ transmit(&(*i), &(*parent->getDynamics()), msgId, msgDir, true);
i->updateState();
lastTransmission = now;
available = false;
}
void FGGroundNetwork::updateAircraftInformation(int id, double lat, double lon,
- double heading, double speed, double alt,
- double dt)
+ double heading, double speed, double alt,
+ double dt)
{
time_t currentTime = time(NULL);
if (nextSave < currentTime) {
saveElevationCache();
nextSave = currentTime + 100 + rand() % 200;
}
- // Check whether aircraft are on hold due to a preceding pushback. If so, make sure to
+ // 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 ...
+ // Transmit confirmation ...
// Probably use a status mechanism similar to the Engine start procedure in the startup controller.
bool needsTaxiClearance = current->getAircraft()->getTaxiClearanceRequest();
if (!needsTaxiClearance) {
checkHoldPosition(id, lat, lon, heading, speed, alt);
- if (checkForCircularWaits(id)) {
- i->setResolveCircularWait();
- }
+ //if (checkForCircularWaits(id)) {
+ // i->setResolveCircularWait();
+ //}
} else {
current->setHoldPosition(true);
int state = current->getState();
aircraft. For traffic that is on other routes we need to issue a "HOLD Position"
instruction. See below for the hold position instruction.
- Note that there currently still is one flaw in the logic that needs to be addressed.
+ Note that there currently still is one flaw in the logic that needs to be addressed.
There can be situations where one aircraft is in front of the current aircraft, on a separate
route, but really close after an intersection coming off the current route. This
aircraft is still close enough to block the current aircraft. This situation is currently
*/
void FGGroundNetwork::checkSpeedAdjustment(int id, double lat,
- double lon, double heading,
- double speed, double alt)
+ double lon, double heading,
+ double speed, double alt)
{
- TrafficVectorIterator current, closest;
+ TrafficVectorIterator current, closest, closestOnNetwork;
TrafficVectorIterator i = activeTraffic.begin();
bool otherReasonToSlowDown = false;
bool previousInstruction;
//TrafficVector iterator closest;
closest = current;
for (TrafficVectorIterator i = activeTraffic.begin();
- i != activeTraffic.end(); i++) {
+ i != activeTraffic.end(); i++) {
if (i == current) {
continue;
}
if ((dist < mindist) && (bearing < 60.0)) {
mindist = dist;
closest = i;
+ closestOnNetwork = i;
minbearing = bearing;
+
}
}
//Check traffic at the tower controller
if (towerController->hasActiveTraffic()) {
for (TrafficVectorIterator i =
- towerController->getActiveTraffic().begin();
- i != towerController->getActiveTraffic().end(); 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(),
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()
+ // << " is closest to " << i->getAircraft()->getTrafficRef()->getCallSign()
+ // << ", which has status " << i->getAircraft()->isScheduledForTakeoff()
// << endl;
mindist = dist;
closest = i;
}
*/
current->clearSpeedAdjustment();
-
+ bool needBraking = false;
if (current->checkPositionAndIntentions(*closest)
- || otherReasonToSlowDown) {
+ || otherReasonToSlowDown) {
double maxAllowableDistance =
(1.1 * current->getRadius()) +
(1.1 * closest->getRadius());
if (closest->getId() != current->getId()) {
current->setSpeedAdjustment(closest->getSpeed() *
(mindist / 100));
- if (
- closest->getAircraft()->getTakeOffStatus() &&
+ needBraking = true;
+ if (
+ closest->getAircraft()->getTakeOffStatus() &&
(current->getAircraft()->getTrafficRef()->getDepartureAirport() == closest->getAircraft()->getTrafficRef()->getDepartureAirport()) &&
(current->getAircraft()->GetFlightPlan()->getRunway() == closest->getAircraft()->GetFlightPlan()->getRunway())
- )
- current->getAircraft()->scheduleForATCTowerDepartureControl(1);
+ )
+ current->getAircraft()->scheduleForATCTowerDepartureControl(1);
} else {
current->setSpeedAdjustment(0); // This can only happen when the user aircraft is the one closest
}
}
}
}
+ if ((closest == closestOnNetwork) && (current->getPriority() < closest->getPriority()) && needBraking) {
+ swap(current, closest);
+ }
}
}
TrafficVectorIterator current;
TrafficVectorIterator i = activeTraffic.begin();
if (activeTraffic.size()) {
- //while ((i->getId() != id) && i != activeTraffic.end())
+ //while ((i->getId() != id) && i != activeTraffic.end())
while (i != activeTraffic.end()) {
if (i->getId() == id) {
break;
bool origStatus = current->hasHoldPosition();
current->setHoldPosition(false);
SGGeod curr(SGGeod::fromDegM(lon, lat, alt));
+ int currentRoute = i->getCurrentPosition();
+ int nextRoute;
+ if (i->getIntentions().size()) {
+ nextRoute = (*(i->getIntentions().begin()));
+ } else {
+ nextRoute = 0;
+ }
+ if (currentRoute > 0) {
+ FGTaxiSegment *tx = findSegment(currentRoute);
+ FGTaxiSegment *nx;
+ if (nextRoute) {
+ nx = findSegment(nextRoute);
+ } else {
+ nx = tx;
+ }
+ if (tx->hasBlock() || nx->hasBlock() ) {
+ current->setHoldPosition(true);
+ }
+ }
- 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 {
+
+ /* 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;
- //cerr << "Hold check 4: " << id << " Would need to wait for other aircraft : distance = " << dist << " meters" << endl;
+ 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())))
-
- {
- 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());
+ 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())))
+
+ {
+ 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)
+ //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;
}
- //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();
current->setHoldPosition(origStatus);
// Either a Hold Position or a resume taxi transmission has been issued
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, true);
+ transmit(&(*current), &(*parent->getDynamics()), MSG_HOLD_POSITION, ATC_GROUND_TO_AIR, true);
//cerr << "Transmittin hold short instrudtion " << currStatus << " " << available << endl;
current->setState(1);
} else {
- transmit(&(*current), MSG_RESUME_TAXI, ATC_GROUND_TO_AIR, true);
+ transmit(&(*current), &(*parent->getDynamics()), MSG_RESUME_TAXI, ATC_GROUND_TO_AIR, true);
//cerr << "Transmittig resume instrudtion " << currStatus << " " << available << endl;
current->setState(2);
}
//int state = current->getState();
if (checkTransmissionState(1,1, current, now, MSG_ACKNOWLEDGE_HOLD_POSITION, ATC_AIR_TO_GROUND)) {
- current->setState(0);
- current->setHoldPosition(true);
+ current->setState(0);
+ current->setHoldPosition(true);
}
if (checkTransmissionState(2,2, current, now, MSG_ACKNOWLEDGE_RESUME_TAXI, ATC_AIR_TO_GROUND)) {
- current->setState(0);
- current->setHoldPosition(false);
+ current->setState(0);
+ current->setHoldPosition(false);
}
if (current->getAircraft()->getTakeOffStatus() && (current->getState() == 0)) {
- //cerr << "Scheduling " << current->getAircraft()->getCallSign() << " for hold short" << endl;
- current->setState(6);
- }
+ //cerr << "Scheduling " << current->getAircraft()->getCallSign() << " for hold short" << endl;
+ current->setState(6);
+ }
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)) {
- //current->setState(0);
-}
+ //current->setState(0);
+}
/**
* Check whether situations occur where the current aircraft is waiting for itself
- * due to higher order interactions.
+ * due to higher order interactions.
* A 'circular' wait is a situation where a waits for b, b waits for c, and c waits
- * for a. Ideally each aircraft only waits for one other aircraft, so by tracing
- * through this list of waiting aircraft, we can check if we'd eventually end back
+ * for a. Ideally each aircraft only waits for one other aircraft, so by tracing
+ * through this list of waiting aircraft, we can check if we'd eventually end back
* at the current aircraft.
*
* Note that we should consider the situation where we are actually checking aircraft
//printed = true;
TrafficVectorIterator i = activeTraffic.begin();
if (trafficSize) {
- //while ((i->getId() != id) && i != activeTraffic.end())
+ //while ((i->getId() != id) && i != activeTraffic.end())
while (i != activeTraffic.end()) {
if (i->getId() == target) {
break;
// 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.
+ // is waiting for the user controlled aircraft.
//if (current->getId() == other->getId()) {
// cerr << "Caught the impossible trap" << endl;
// cerr << "Current = " << current->getId() << endl;
if (current->getId() == other->getId())
return false;
//}
- //cerr << current->getCallSign() << " (" << current->getId() << ") " << " -> " << other->getCallSign()
+ //cerr << current->getCallSign() << " (" << current->getId() << ") " << " -> " << other->getCallSign()
// << " (" << other->getId() << "); " << endl;;
//current = other;
}
//while (group->getNumChildren()) {
// cerr << "Number of children: " << group->getNumChildren() << endl;
//simgear::EffectGeode* geode = (simgear::EffectGeode*) group->getChild(0);
- //osg::MatrixTransform *obj_trans = (osg::MatrixTransform*) group->getChild(0);
- //geode->releaseGLObjects();
- //group->removeChild(geode);
- //delete geode;
+ //osg::MatrixTransform *obj_trans = (osg::MatrixTransform*) group->getChild(0);
+ //geode->releaseGLObjects();
+ //group->removeChild(geode);
+ //delete geode;
group = 0;
}
if (visible) {
// Handle start point
int pos = i->getCurrentPosition() - 1;
if (pos >= 0) {
-
+
SGGeod start(SGGeod::fromDeg((i->getLongitude()), (i->getLatitude())));
SGGeod end (SGGeod::fromDeg(segments[pos]->getEnd()->getLongitude(), segments[pos]->getEnd()->getLatitude()));
SGGeod center;
SGGeodesy::direct(start, heading, coveredDistance, center, az2);
//cerr << "Active Aircraft : Centerpoint = (" << center.getLatitudeDeg() << ", " << center.getLongitudeDeg() << "). Heading = " << heading << endl;
- ///////////////////////////////////////////////////////////////////////////////
+ ///////////////////////////////////////////////////////////////////////////////
// Make a helper function out of this
osg::Matrix obj_pos;
osg::MatrixTransform *obj_trans = new osg::MatrixTransform;
if (isUserAircraft((i)->getAircraft())) {
elevationStart = fgGetDouble("/position/ground-elev-m");
} else {
- elevationStart = ((i)->getAircraft()->_getAltitude());
+ elevationStart = ((i)->getAircraft()->_getAltitude());
}
double elevationEnd = segments[pos]->getEnd()->getElevation();
//cerr << "Using elevation " << elevationEnd << endl;
center2.setElevationM(SG_MAX_ELEVATION_M);
if (local_scenery->get_elevation_m( center2, elevationEnd, NULL )) {
elevation_feet = elevationEnd * SG_METER_TO_FEET + 0.5;
- //elevation_meters += 0.5;
+ //elevation_meters += 0.5;
}
- else {
+ else {
elevationEnd = parent->getElevation();
}
segments[pos]->getEnd()->setElevation(elevationEnd);
}
double elevationMean = (elevationStart + elevationEnd) / 2.0;
double elevDiff = elevationEnd - elevationStart;
-
- double slope = atan2(elevDiff, length) * SGD_RADIANS_TO_DEGREES;
-
- //cerr << "1. Using mean elevation : " << elevationMean << " and " << slope << endl;
+
+ double slope = atan2(elevDiff, length) * SGD_RADIANS_TO_DEGREES;
+
+ //cerr << "1. Using mean elevation : " << elevationMean << " and " << slope << endl;
WorldCoordinate( obj_pos, center.getLatitudeDeg(), center.getLongitudeDeg(), elevationMean+ 0.5, -(heading), slope );
geode->setName("test");
geode->addDrawable(geometry);
//osg::Node *custom_obj;
- SGMaterial *mat = matlib->find("UnidirectionalTaper");
+ SGMaterial *mat;
+ if (segments[pos]->hasBlock()) {
+ mat = matlib->find("UnidirectionalTaperRed");
+ } else {
+ mat = matlib->find("UnidirectionalTaperGreen");
+ }
if (mat)
geode->setEffect(mat->get_effect());
obj_trans->addChild(geode);
// wire as much of the scene graph together as we can
//->addChild( obj_trans );
group->addChild( obj_trans );
- /////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////
} else {
//cerr << "BIG FAT WARNING: current position is here : " << pos << endl;
}
- for(intVecIterator j = (i)->getIntentions().begin(); j != (i)->getIntentions().end(); j++) {
+ for (intVecIterator j = (i)->getIntentions().begin(); j != (i)->getIntentions().end(); j++) {
osg::Matrix obj_pos;
int k = (*j)-1;
if (k >= 0) {
elevation_feet = elevationStart * SG_METER_TO_FEET + 0.5;
//elevation_meters += 0.5;
}
- else {
+ else {
elevationStart = parent->getElevation();
}
segments[k]->getStart()->setElevation(elevationStart);
elevation_feet = elevationEnd * SG_METER_TO_FEET + 0.5;
//elevation_meters += 0.5;
}
- else {
+ else {
elevationEnd = parent->getElevation();
}
segments[k]->getEnd()->setElevation(elevationEnd);
double elevDiff = elevationEnd - elevationStart;
double length = segments[k]->getLength();
double slope = atan2(elevDiff, length) * SGD_RADIANS_TO_DEGREES;
-
- // cerr << "2. Using mean elevation : " << elevationMean << " and " << slope << endl;
+
+ // cerr << "2. Using mean elevation : " << elevationMean << " and " << slope << endl;
WorldCoordinate( obj_pos, segments[k]->getLatitude(), segments[k]->getLongitude(), elevationMean+ 0.5, -(segments[k]->getHeading()), slope );
geode->setName("test");
geode->addDrawable(geometry);
//osg::Node *custom_obj;
- SGMaterial *mat = matlib->find("UnidirectionalTaper");
+ SGMaterial *mat;
+ if (segments[k]->hasBlock()) {
+ mat = matlib->find("UnidirectionalTaperRed");
+ } else {
+ mat = matlib->find("UnidirectionalTaperGreen");
+ }
if (mat)
geode->setEffect(mat->get_effect());
obj_trans->addChild(geode);
string FGGroundNetwork::getName() {
return string(parent->getId() + "-ground");
}
+
+void FGGroundNetwork::update(double dt)
+{
+ for (FGTaxiSegmentVectorIterator tsi = segments.begin(); tsi != segments.end(); tsi++) {
+ (*tsi)->unblock();
+ }
+ int priority = 1;
+ //sort(activeTraffic.begin(), activeTraffic.end(), compare_trafficrecords);
+ // Handle traffic that is under ground control first; this way we'll prevent clutter at the gate areas.
+ // Don't allow an aircraft to pushback when a taxiing aircraft is currently using part of the intended route.
+ for (TrafficVectorIterator i = parent->getDynamics()->getStartupController()->getActiveTraffic().begin();
+ i != parent->getDynamics()->getStartupController()->getActiveTraffic().end(); i++) {
+ i->allowPushBack();
+ i->setPriority(priority++);
+ if (i->isActive(60)) {
+
+ // Check for all active aircraft whether it's current pos segment is
+ // an opposite of one of the departing aircraft's intentions
+ for (TrafficVectorIterator j = activeTraffic.begin(); j != activeTraffic.end(); j++) {
+ int pos = j->getCurrentPosition();
+ if (pos > 0) {
+ FGTaxiSegment *seg = segments[pos-1]->opposite();
+ if (seg) {
+ int posReverse = seg->getIndex();
+ for (intVecIterator k = i->getIntentions().begin(); k != i->getIntentions().end(); k++) {
+ if ((*k) == posReverse) {
+ i->denyPushBack();
+ segments[posReverse-1]->block();
+ }
+ }
+ }
+ }
+ }
+ // if the current aircraft is still allowed to pushback, we can start reserving a route for if by blocking all the entry taxiways.
+ if (i->pushBackAllowed()) {
+ int pos = i->getCurrentPosition();
+ if (pos > 0) {
+ FGTaxiSegment *seg = segments[pos-1];
+ FGTaxiNode *node = seg->getEnd();
+ for (FGTaxiSegmentVectorIterator tsi = segments.begin(); tsi != segments.end(); tsi++) {
+ if (((*tsi)->getEnd() == node) && ((*tsi) != seg)) {
+ (*tsi)->block();
+ }
+ }
+ }
+ for (intVecIterator j = i->getIntentions().begin(); j != i->getIntentions().end(); j++) {
+ int pos = (*j);
+ if (pos > 0) {
+ FGTaxiSegment *seg = segments[pos-1];
+ FGTaxiNode *node = seg->getEnd();
+ for (FGTaxiSegmentVectorIterator tsi = segments.begin(); tsi != segments.end(); tsi++) {
+ if (((*tsi)->getEnd() == node) && ((*tsi) != seg)) {
+ (*tsi)->block();
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ for (TrafficVectorIterator i = activeTraffic.begin(); i != activeTraffic.end(); i++) {
+ i->setPriority(priority++);
+ int pos = i->getCurrentPosition();
+ if (pos > 0) {
+ if (segments[pos-1]->hasBlock()) {
+ SG_LOG(SG_GENERAL, SG_ALERT, "Taxiway incursion for AI aircraft" << i->getAircraft()->getCallSign());
+ }
+
+ }
+ intVecIterator ivi;
+ for (ivi = i->getIntentions().begin(); ivi != i->getIntentions().end(); ivi++) {
+ int segIndex = (*ivi);
+ if (segIndex > 0) {
+ if (segments[segIndex-1]->hasBlock())
+ break;
+ }
+ }
+ //after this, ivi points just behind the last valid unblocked taxi segment.
+ for (intVecIterator j = i->getIntentions().begin(); j != ivi; j++) {
+ int pos = (*j);
+ if (pos > 0) {
+ FGTaxiSegment *seg = segments[pos-1];
+ FGTaxiNode *node = seg->getEnd();
+ for (FGTaxiSegmentVectorIterator tsi = segments.begin(); tsi != segments.end(); tsi++) {
+ if (((*tsi)->getEnd() == node) && ((*tsi) != seg)) {
+ (*tsi)->block();
+ }
+ }
+ }
+ }
+ }
+}
+