]> git.mxchange.org Git - flightgear.git/commitdiff
Merge branch 'next' into comm-subsystem
authoradrian <adrian@localhost.com>
Sat, 29 Oct 2011 09:22:00 +0000 (12:22 +0300)
committeradrian <adrian@localhost.com>
Sat, 29 Oct 2011 09:22:00 +0000 (12:22 +0300)
1  2 
src/ATC/trafficcontrol.cxx
src/Airports/groundnetwork.cxx

index 945f9d9c425acb6b5e403870d4b7db348d66e25a,124b1740fcbc4d09f7eb524e38b748deae181404..aefc39b429b2e7927ecb820263dc83eb29886811
@@@ -140,6 -140,27 +140,27 @@@ time_t ActiveRunway::requestTimeSlot(ti
      return newEta;
  }
  
+ void ActiveRunway::printDepartureCue()
+ {
+     cout << "Departure cue for " << rwy << ": " << endl;
+     for (AircraftVecIterator atc = departureCue.begin(); atc != departureCue.end(); atc++) {
+         cout << "     " << (*atc)->getCallSign() << " "  << (*atc)->getTakeOffStatus();
+         cout << " " << (*atc)->_getLatitude() << " " << (*atc)->_getLongitude() << (*atc)-> getSpeed() << " " << (*atc)->getAltitude() << endl;
+     }
+     
+ }
+ FGAIAircraft* ActiveRunway::getFirstOfStatus(int stat)
+ {
+     for (AircraftVecIterator atc =departureCue.begin(); atc != departureCue.end(); atc++) {
+         if ((*atc)->getTakeOffStatus() == stat)
+             return (*atc);
+     }
+     return 0;
+ }
  /***************************************************************************
   * FGTrafficRecord
   **************************************************************************/
@@@ -165,13 -186,13 +186,13 @@@ void FGTrafficRecord::setPositionAndInt
          intVecIterator i = intentions.begin();
          if ((*i) != pos) {
              SG_LOG(SG_GENERAL, SG_ALERT,
-                    "Error in FGTrafficRecord::setPositionAndIntentions");
-             //cerr << "Pos : " << pos << " Curr " << *(intentions.begin())  << endl;
+                    "Error in FGTrafficRecord::setPositionAndIntentions at " << SG_ORIGIN);
+             cerr << "Pos : " << pos << " Curr " << *(intentions.begin())  << endl;
              for (intVecIterator i = intentions.begin();
                      i != intentions.end(); i++) {
-                 //cerr << (*i) << " ";
+                 cerr << (*i) << " ";
              }
-             //cerr << endl;
+             cerr << endl;
          }
          intentions.erase(i);
      } else {
@@@ -487,7 -508,7 +508,7 @@@ bool FGATCController::isUserAircraft(FG
      return (ac->getCallSign() == fgGetString("/sim/multiplay/callsign")) ? true : false;
  };
  
 -void FGATCController::transmit(FGTrafficRecord * rec, AtcMsgId msgId,
 +void FGATCController::transmit(FGTrafficRecord * rec, FGAirportDynamics *parent, AtcMsgId msgId,
                                 AtcMsgDir msgDir, bool audible)
  {
      string sender, receiver;
      FGAIFlightPlan *fp;
      string fltRules;
      string instructionText;
 +    int ground_to_air=0;
  
      //double commFreqD;
      sender = rec->getAircraft()->getTrafficRef()->getCallSign();
          string tmp = sender;
          sender = receiver;
          receiver = tmp;
 +        ground_to_air=1;
      }
      switch (msgId) {
      case MSG_ANNOUNCE_ENGINE_START:
          // Display ATC message only when one of the radios is tuned
          // the relevant frequency.
          // Note that distance attenuation is currently not yet implemented
 +                
          if ((onBoardRadioFreqI0 == stationFreq)
                  || (onBoardRadioFreqI1 == stationFreq)) {
              if (rec->allowTransmissions()) {
 +              
                  fgSetString("/sim/messages/atc", text.c_str());
              }
          }
      }
  }
  
 +
  string FGATCController::formatATCFrequency3_2(int freq)
  {
      char buffer[7];
@@@ -850,7 -866,7 +871,7 @@@ void FGTowerController::updateAircraftI
  //    // 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");
+                "AI error: updating aircraft without traffic record at " << SG_ORIGIN);
      } else {
          i->setPositionAndHeading(lat, lon, heading, speed, alt);
          current = i;
      // see if we already have a clearance record for the currently active runway
      // NOTE: dd. 2011-08-07: Because the active runway has been constructed in the announcePosition function, we may safely assume that is
      // already exists here. So, we can simplify the current code.
+     
      ActiveRunwayVecIterator rwy = activeRunways.begin();
+     //if (parent->getId() == fgGetString("/sim/presets/airport-id")) {
+     //    for (rwy = activeRunways.begin(); rwy != activeRunways.end(); rwy++) {
+     //        rwy->printDepartureCue();
+     //    }
+     //}
+     
+     rwy = activeRunways.begin();
      while (rwy != activeRunways.end()) {
          if (rwy->getRunwayName() == current->getRunway()) {
              break;
          }
      } */
      // only bother with aircraft that have a takeoff status of 2, since those are essentially under tower control
+     FGAIAircraft* ac= rwy->getFirstAircraftInDepartureCue();
+     if (ac->getTakeOffStatus() == 1) {
+         ac->setTakeOffStatus(2);
+     }
      if (current->getAircraft()->getTakeOffStatus() == 2) {
+         current -> setHoldPosition(false);
+     } else {
          current->setHoldPosition(true);
-         int clearanceId = rwy->getCleared();
-         if (clearanceId) {
-             if (id == clearanceId) {
-                 current->setHoldPosition(false);
-             }
-         } else {
-             if (current->getAircraft() == rwy->getFirstAircraftInDepartureCue()) {
-                 rwy->setCleared(id);
-             }
+     }
+     int clearanceId = rwy->getCleared();
+     if (clearanceId) {
+         if (id == clearanceId) {
+             current->setHoldPosition(false);
          }
      } else {
-         
+         if (current->getAircraft() == rwy->getFirstAircraftInDepartureCue()) {
+             rwy->setCleared(id);
+             FGAIAircraft *ac = rwy->getFirstOfStatus(1);
+             if (ac)
+                 ac->setTakeOffStatus(2);
+         }
      }
- }
+ } 
  
  
  void FGTowerController::signOff(int id)
              rwy->updateDepartureCue();
          } else {
              SG_LOG(SG_GENERAL, SG_ALERT,
-                    "AI error: Attempting to erase non-existing runway clearance record in FGTowerController::signoff");
+                    "AI error: Attempting to erase non-existing runway clearance record in FGTowerController::signoff at " << SG_ORIGIN);
          }
      }
      if (i == activeTraffic.end() || (activeTraffic.size() == 0)) {
          SG_LOG(SG_GENERAL, SG_ALERT,
-                "AI error: Aircraft without traffic record is signing off from tower");
+                "AI error: Aircraft without traffic record is signing off from tower at " << SG_ORIGIN);
      } else {
          i->getAircraft()->resetTakeOffStatus();
          i = activeTraffic.erase(i);
@@@ -965,7 -996,7 +1001,7 @@@ bool FGTowerController::hasInstruction(
      }
      if (i == activeTraffic.end() || (activeTraffic.size() == 0)) {
          SG_LOG(SG_GENERAL, SG_ALERT,
-                "AI error: checking ATC instruction for aircraft without traffic record");
+                "AI error: checking ATC instruction for aircraft without traffic record at " << SG_ORIGIN);
      } else {
          return i->hasInstruction();
      }
@@@ -989,7 -1020,7 +1025,7 @@@ FGATCInstruction FGTowerController::get
      }
      if (i == activeTraffic.end() || (activeTraffic.size() == 0)) {
          SG_LOG(SG_GENERAL, SG_ALERT,
-                "AI error: requesting ATC instruction for aircraft without traffic record");
+                "AI error: requesting ATC instruction for aircraft without traffic record at " << SG_ORIGIN);
      } else {
          return i->getInstruction();
      }
@@@ -1084,7 -1115,7 +1120,7 @@@ bool FGStartupController::hasInstructio
      }
      if (i == activeTraffic.end() || (activeTraffic.size() == 0)) {
          SG_LOG(SG_GENERAL, SG_ALERT,
-                "AI error: checking ATC instruction for aircraft without traffic record");
+                "AI error: checking ATC instruction for aircraft without traffic record at " << SG_ORIGIN);
      } else {
          return i->hasInstruction();
      }
@@@ -1108,7 -1139,7 +1144,7 @@@ FGATCInstruction FGStartupController::g
      }
      if (i == activeTraffic.end() || (activeTraffic.size() == 0)) {
          SG_LOG(SG_GENERAL, SG_ALERT,
-                "AI error: requesting ATC instruction for aircraft without traffic record");
+                "AI error: requesting ATC instruction for aircraft without traffic record at " << SG_ORIGIN);
      } else {
          return i->getInstruction();
      }
@@@ -1131,7 -1162,7 +1167,7 @@@ void FGStartupController::signOff(int i
      }
      if (i == activeTraffic.end() || (activeTraffic.size() == 0)) {
          SG_LOG(SG_GENERAL, SG_ALERT,
-                "AI error: Aircraft without traffic record is signing off from tower");
+                "AI error: Aircraft without traffic record is signing off from tower at " << SG_ORIGIN);
      } else {
          //cerr << i->getAircraft()->getCallSign() << " signing off from startupcontroller" << endl;
          i = activeTraffic.erase(i);
@@@ -1155,13 -1186,13 +1191,13 @@@ bool FGStartupController::checkTransmis
                  FGATCDialogNew::instance()->removeEntry(1);
              } else {
                  //cerr << "creading message for " << i->getAircraft()->getCallSign() << endl;
 -                transmit(&(*i), msgId, msgDir, false);
 +                transmit(&(*i), &(*parent), msgId, msgDir, false);
                  return false;
              }
          }
          if (now > startTime) {
              //cerr << "Transmitting startup msg" << endl;
 -            transmit(&(*i), msgId, msgDir, true);
 +            transmit(&(*i), &(*parent), msgId, msgDir, true);
              i->updateState();
              lastTransmission = now;
              available = false;
@@@ -1192,7 -1223,7 +1228,7 @@@ void FGStartupController::updateAircraf
  
      if (i == activeTraffic.end() || (activeTraffic.size() == 0)) {
          SG_LOG(SG_GENERAL, SG_ALERT,
-                "AI error: updating aircraft without traffic record");
+                "AI error: updating aircraft without traffic record at " << SG_ORIGIN);
      } else {
          i->setPositionAndHeading(lat, lon, heading, speed, alt);
          current = i;
          if (now > startTime + 200) {
              if (i->pushBackAllowed()) {
                  i->allowRepeatedTransmissions();
 -                transmit(&(*i), MSG_PERMIT_PUSHBACK_CLEARANCE,
 +                transmit(&(*i), &(*parent), MSG_PERMIT_PUSHBACK_CLEARANCE,
                           ATC_GROUND_TO_AIR, true);
                  i->updateState();
              } else {
 -                transmit(&(*i), MSG_HOLD_PUSHBACK_CLEARANCE,
 +                transmit(&(*i), &(*parent), MSG_HOLD_PUSHBACK_CLEARANCE,
                           ATC_GROUND_TO_AIR, true);
                  i->suppressRepeatedTransmissions();
              }
@@@ -1287,6 -1318,7 +1323,7 @@@ void FGStartupController::render(bool v
  
          //for ( FGTaxiSegmentVectorIterator i = segments.begin(); i != segments.end(); i++) {
          double dx = 0;
+         time_t now = time(NULL) + fgGetLong("/sim/time/warp");
          for   (TrafficVectorIterator i = activeTraffic.begin(); i != activeTraffic.end(); i++) {
              if (i->isActive(300)) {
                  // Handle start point
                      } else {
                          elevationStart = ((i)->getAircraft()->_getAltitude() * SG_FEET_TO_METER);
                      }
-                     double elevationEnd   = segment->getEnd()->getElevation();
+                     double elevationEnd   = segment->getEnd()->getElevationM(parent->getElevation()*SG_FEET_TO_METER);
                      if ((elevationEnd == 0) || (elevationEnd == parent->getElevation())) {
                          SGGeod center2 = end;
                          center2.setElevationM(SG_MAX_ELEVATION_M);
                      geode->addDrawable(geometry);
                      //osg::Node *custom_obj;
                      SGMaterial *mat;
-                     if (segment->hasBlock()) {
+                     if (segment->hasBlock(now)) {
                          mat = matlib->find("UnidirectionalTaperRed");
                      } else {
                          mat = matlib->find("UnidirectionalTaperGreen");
                          obj_trans->setDataVariance(osg::Object::STATIC);
                          FGTaxiSegment *segment  = parent->getGroundNetwork()->findSegment(k);
  
-                         double elevationStart = segment->getStart()->getElevation();
-                         double elevationEnd   = segment->getEnd  ()->getElevation();
+                         double elevationStart = segment->getStart()->getElevationM(parent->getElevation()*SG_FEET_TO_METER);
+                         double elevationEnd   = segment->getEnd  ()->getElevationM(parent->getElevation()*SG_FEET_TO_METER);
                          if ((elevationStart == 0) || (elevationStart == parent->getElevation())) {
                              SGGeod center2 = segment->getStart()->getGeod();
                              center2.setElevationM(SG_MAX_ELEVATION_M);
                          geode->addDrawable(geometry);
                          //osg::Node *custom_obj;
                          SGMaterial *mat;
-                         if (segment->hasBlock()) {
+                         if (segment->hasBlock(now)) {
                              mat = matlib->find("UnidirectionalTaperRed");
                          } else {
                              mat = matlib->find("UnidirectionalTaperGreen");
@@@ -1534,7 -1566,7 +1571,7 @@@ void FGApproachController::updateAircra
  //    // 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");
+                "AI error: updating aircraft without traffic record at " << SG_ORIGIN);
      } else {
          i->setPositionAndHeading(lat, lon, heading, speed, alt);
          current = i;
@@@ -1582,7 -1614,7 +1619,7 @@@ void FGApproachController::signOff(int 
      }
      if (i == activeTraffic.end() || (activeTraffic.size() == 0)) {
          SG_LOG(SG_GENERAL, SG_ALERT,
-                "AI error: Aircraft without traffic record is signing off from approach");
+                "AI error: Aircraft without traffic record is signing off from approach at " << SG_ORIGIN);
      } else {
          i = activeTraffic.erase(i);
      }
@@@ -1611,7 -1643,7 +1648,7 @@@ bool FGApproachController::hasInstructi
      }
      if (i == activeTraffic.end() || (activeTraffic.size() == 0)) {
          SG_LOG(SG_GENERAL, SG_ALERT,
-                "AI error: checking ATC instruction for aircraft without traffic record");
+                "AI error: checking ATC instruction for aircraft without traffic record at " << SG_ORIGIN);
      } else {
          return i->hasInstruction();
      }
@@@ -1635,7 -1667,7 +1672,7 @@@ FGATCInstruction FGApproachController::
      }
      if (i == activeTraffic.end() || (activeTraffic.size() == 0)) {
          SG_LOG(SG_GENERAL, SG_ALERT,
-                "AI error: requesting ATC instruction for aircraft without traffic record");
+                "AI error: requesting ATC instruction for aircraft without traffic record at " << SG_ORIGIN);
      } else {
          return i->getInstruction();
      }
index c4995f1201be8470723fb46f5898392a453b978e,f817e30351f6935370094579b5a87b42acc64f4c..8036319a5cc093e4161a2b90772ef8c0190b1b8e
@@@ -43,6 -43,7 +43,7 @@@
  #include <Airports/dynamics.hxx>
  
  #include <AIModel/AIAircraft.hxx>
+ #include <AIModel/performancedata.hxx>
  #include <AIModel/AIFlightPlan.hxx>
  
  #include <ATC/atc_mgr.hxx>
@@@ -51,6 -52,7 +52,7 @@@
  
  #include "groundnetwork.hxx"
  
  /***************************************************************************
   * FGTaxiSegment
   **************************************************************************/
@@@ -113,6 -115,44 +115,44 @@@ void FGTaxiSegment::setDimensions(doubl
  //        headingDiff = fabs(headingDiff - 360);
  //}
  
+ void FGTaxiSegment::block(int id, time_t blockTime, time_t now)
+ {
+     BlockListIterator i = blockTimes.begin();
+     while (i != blockTimes.end()) {
+         if (i->getId() == id) 
+             break;
+         i++;
+     }
+     if (i == blockTimes.end()) {
+         blockTimes.push_back(Block(id, blockTime, now));
+         sort(blockTimes.begin(), blockTimes.end());
+     } else {
+         i->updateTimeStamps(blockTime, now);
+     }
+ }
+ // The segment has a block if any of the block times listed in the block list is
+ // smaller than the current time.
+ bool FGTaxiSegment::hasBlock(time_t now)
+ {
+     for (BlockListIterator i = blockTimes.begin(); i != blockTimes.end(); i++) {
+         if (i->getBlockTime() < now)
+             return true;
+     }
+     return false;
+ }
+ void FGTaxiSegment::unblock(time_t now)
+ {
+     if (blockTimes.size()) {
+         BlockListIterator i = blockTimes.begin();
+         if (i->getTimeStamp() < (now - 30)) {
+             blockTimes.erase(i);
+         }
+     }
+ }
  
  /***************************************************************************
   * FGTaxiRoute
@@@ -220,6 -260,7 +260,7 @@@ FGGroundNetwork::FGGroundNetwork(
      count = 0;
      currTraffic = activeTraffic.begin();
      group = 0;
+     version = 0;
      networkInitialized = false;
  
  }
@@@ -252,7 -293,7 +293,7 @@@ FGGroundNetwork::~FGGroundNetwork(
              node != nodes.end(); node++) {
          if (saveData) {
              cachefile << (*node)->getIndex     () << " "
-             << (*node)->getElevation ()   << " "
+             << (*node)->getElevationM (parent->getElevation()*SG_FEET_TO_METER)   << " "
              << endl;
          }
          delete(*node);
@@@ -296,7 -337,7 +337,7 @@@ void FGGroundNetwork::saveElevationCach
              node != nodes.end(); node++) {
          if (saveData) {
              cachefile << (*node)->getIndex     () << " "
-             << (*node)->getElevation () << " "
+             << (*node)->getElevationM (parent->getElevation()*SG_FEET_TO_METER) << " "
              << endl;
          }
      }
@@@ -323,7 -364,7 +364,7 @@@ void FGGroundNetwork::addNodes(FGParkin
          n.setIndex(i->getIndex());
          n.setLatitude(i->getLatitude());
          n.setLongitude(i->getLongitude());
-         n.setElevation(parent->getElevation());
+         n.setElevation(parent->getElevation()*SG_FEET_TO_METER);
          nodes.push_back(new FGTaxiNode(n));
  
          i++;
@@@ -452,6 -493,28 +493,28 @@@ int FGGroundNetwork::findNearestNode(co
      return index;
  }
  
+ int FGGroundNetwork::findNearestNodeOnRunway(const SGGeod & aGeod)
+ {
+     double minDist = HUGE_VAL;
+     int index = -1;
+     for (FGTaxiNodeVectorIterator itr = nodes.begin(); itr != nodes.end();
+             itr++) {
+         if (!((*itr)->getIsOnRunway())) {
+             continue;
+         }
+         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;
+ }
  int FGGroundNetwork::findNearestNode(double lat, double lon)
  {
      return findNearestNode(SGGeod::fromDeg(lon, lat));
@@@ -628,7 -691,11 +691,11 @@@ void FGGroundNetwork::announcePosition(
          rec.setPositionAndHeading(lat, lon, heading, speed, alt);
          rec.setRadius(radius);  // only need to do this when creating the record.
          rec.setAircraft(aircraft);
-         activeTraffic.push_front(rec);
+         if (leg == 2) {
+             activeTraffic.push_front(rec);
+         } else {
+             activeTraffic.push_back(rec);   
+         }
          
      } else {
          i->setPositionAndIntentions(currentPosition, intendedRoute);
@@@ -653,7 -720,7 +720,7 @@@ void FGGroundNetwork::signOff(int id
      }
      if (i == activeTraffic.end() || (activeTraffic.size() == 0)) {
          SG_LOG(SG_GENERAL, SG_ALERT,
-                "AI error: Aircraft without traffic record is signing off");
+                "AI error: Aircraft without traffic record is signing off at " << SG_ORIGIN);
      } else {
          i = activeTraffic.erase(i);
      }
@@@ -684,15 -751,15 +751,15 @@@ bool FGGroundNetwork::checkTransmission
                  trans_num->setIntValue(-1);
                  // PopupCallback(n);
                  //cerr << "Selected transmission message " << n << endl;
-                 FGATCManager *atc = (FGATCManager*) globals->get_subsystem("atc");
+                 //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;
@@@ -733,7 -800,7 +800,7 @@@ void FGGroundNetwork::updateAircraftInf
      // 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");
+                "AI error: updating aircraft without traffic record at " << SG_ORIGIN);
      } else {
          i->setPositionAndHeading(lat, lon, heading, speed, alt);
          current = i;
@@@ -818,7 -885,7 +885,7 @@@ void FGGroundNetwork::checkSpeedAdjustm
      }
      if (i == activeTraffic.end() || (activeTraffic.size() == 0)) {
          SG_LOG(SG_GENERAL, SG_ALERT,
-                "AI error: Trying to access non-existing aircraft in FGGroundNetwork::checkSpeedAdjustment");
+                "AI error: Trying to access non-existing aircraft in FGGroundNetwork::checkSpeedAdjustment at " << SG_ORIGIN);
      }
      current = i;
      //closest = current;
          SGGeod curr(SGGeod::fromDegM(lon, lat, alt));
          //TrafficVector iterator closest;
          closest = current;
+         closestOnNetwork = current;
          for (TrafficVectorIterator i = activeTraffic.begin();
                  i != activeTraffic.end(); i++) {
              if (i == current) {
                      current->setSpeedAdjustment(closest->getSpeed() *
                                                  (mindist / 100));
                      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);
+                     
+ //                     if (
+ //                         closest->getAircraft()->getTakeOffStatus() &&
+ //                         (current->getAircraft()->getTrafficRef()->getDepartureAirport() ==  closest->getAircraft()->getTrafficRef()->getDepartureAirport()) &&
+ //                         (current->getAircraft()->GetFlightPlan()->getRunway() == closest->getAircraft()->GetFlightPlan()->getRunway())
+ //                     )
+ //                         current->getAircraft()->scheduleForATCTowerDepartureControl(1);
                  } else {
                      current->setSpeedAdjustment(0);     // This can only happen when the user aircraft is the one closest
                  }
                  }
              }
          }
-         if ((closest == closestOnNetwork) && (current->getPriority() < closest->getPriority()) && needBraking) {
+         if ((closest->getId() == closestOnNetwork->getId()) && (current->getPriority() < closest->getPriority()) && needBraking) {
              swap(current, closest);
          }
      }
@@@ -960,11 -1029,23 +1029,23 @@@ void FGGroundNetwork::checkHoldPosition
      } else {
          return;
      }
+     time_t now = time(NULL) + fgGetLong("/sim/time/warp");
      if (i == activeTraffic.end() || (activeTraffic.size() == 0)) {
          SG_LOG(SG_GENERAL, SG_ALERT,
-                "AI error: Trying to access non-existing aircraft in FGGroundNetwork::checkHoldPosition");
+                "AI error: Trying to access non-existing aircraft in FGGroundNetwork::checkHoldPosition at " << SG_ORIGIN);
      }
      current = i;
+     // 
+     if (current->getAircraft()->getTakeOffStatus() == 1) {
+         current->setHoldPosition(true);
+         return;
+     }
+     if (current->getAircraft()->getTakeOffStatus() == 2) {
+         //cerr << current->getAircraft()->getCallSign() << ". Taxi in position and hold" << endl;
+         current->setHoldPosition(false);
+         current->clearSpeedAdjustment();
+         return;
+     }
      bool origStatus = current->hasHoldPosition();
      current->setHoldPosition(false);
      SGGeod curr(SGGeod::fromDegM(lon, lat, alt));
          } 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 {
-                             needsToWait = true;
-                             //cerr << "Hold check 4: " << id << "  Would need to wait for other aircraft : distance = " << dist << " meters" << endl;
-                         }
-                     }
+         //if (tx->hasBlock(now) || nx->hasBlock(now) ) {
+         //   current->setHoldPosition(true);
+         //}
+         SGGeod start(SGGeod::fromDeg((i->getLongitude()), (i->getLatitude())));
+         SGGeod end  (SGGeod::fromDeg(nx->getStart()->getLongitude(), nx->getStart()->getLatitude()));
  
-                     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;
-                         }
+         double distance = SGGeodesy::distanceM(start, end);
+         if (nx->hasBlock(now) && (distance < i->getRadius() * 4)) {
+             current->setHoldPosition(true);
+         } else {
+             intVecIterator ivi = i->getIntentions().begin();
+             while (ivi != i->getIntentions().end()) {
+                 if ((*ivi) > 0) {
+                     distance += segments[(*ivi)-1]->getLength();
+                     if ((segments[(*ivi)-1]->hasBlock(now)) && (distance < i->getRadius() * 4)) {
+                         current->setHoldPosition(true);
+                         break;
                      }
                  }
+                 ivi++;
              }
-         } */
+         } 
+     }
      bool currStatus = current->hasHoldPosition();
      current->setHoldPosition(origStatus);
      // Either a Hold Position or a resume taxi transmission has been issued
-     time_t now = time(NULL) + fgGetLong("/sim/time/warp");
      if ((now - lastTransmission) > 2) {
          available = true;
      }
          if ((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);
              }
@@@ -1154,7 -1178,7 +1178,7 @@@ bool FGGroundNetwork::checkForCircularW
      }
      if (i == activeTraffic.end() || (trafficSize == 0)) {
          SG_LOG(SG_GENERAL, SG_ALERT,
-                "AI error: Trying to access non-existing aircraft in FGGroundNetwork::checkForCircularWaits");
+                "AI error: Trying to access non-existing aircraft in FGGroundNetwork::checkForCircularWaits at " << SG_ORIGIN);
      }
  
      current = i;
@@@ -1246,7 -1270,7 +1270,7 @@@ bool FGGroundNetwork::hasInstruction(in
      }
      if (i == activeTraffic.end() || (activeTraffic.size() == 0)) {
          SG_LOG(SG_GENERAL, SG_ALERT,
-                "AI error: checking ATC instruction for aircraft without traffic record");
+                "AI error: checking ATC instruction for aircraft without traffic record at " << SG_ORIGIN);
      } else {
          return i->hasInstruction();
      }
@@@ -1269,7 -1293,7 +1293,7 @@@ FGATCInstruction FGGroundNetwork::getIn
      }
      if (i == activeTraffic.end() || (activeTraffic.size() == 0)) {
          SG_LOG(SG_GENERAL, SG_ALERT,
-                "AI error: requesting ATC instruction for aircraft without traffic record");
+                "AI error: requesting ATC instruction for aircraft without traffic record at " << SG_ORIGIN);
      } else {
          return i->getInstruction();
      }
@@@ -1314,6 -1338,7 +1338,7 @@@ void FGGroundNetwork::render(bool visib
          FGScenery * local_scenery = globals->get_scenery();
          double elevation_meters = 0.0;
          double elevation_feet = 0.0;
+         time_t now = time(NULL) + fgGetLong("/sim/time/warp");
          //for ( FGTaxiSegmentVectorIterator i = segments.begin(); i != segments.end(); i++) {
          double dx = 0;
          for   (TrafficVectorIterator i = activeTraffic.begin(); i != activeTraffic.end(); i++) {
                  } else {
                      elevationStart = ((i)->getAircraft()->_getAltitude());
                  }
-                 double elevationEnd   = segments[pos]->getEnd()->getElevation();
+                 double elevationEnd   = segments[pos]->getEnd()->getElevationM(parent->getElevation()*SG_FEET_TO_METER);
                  //cerr << "Using elevation " << elevationEnd << endl;
  
                  if ((elevationEnd == 0) || (elevationEnd = parent->getElevation())) {
                  geode->addDrawable(geometry);
                  //osg::Node *custom_obj;
                  SGMaterial *mat;
-                 if (segments[pos]->hasBlock()) {
+                 if (segments[pos]->hasBlock(now)) {
                      mat = matlib->find("UnidirectionalTaperRed");
                  } else {
                      mat = matlib->find("UnidirectionalTaperGreen");
                      obj_trans->setDataVariance(osg::Object::STATIC);
  
                      // Experimental: Calculate slope here, based on length, and the individual elevations
-                     double elevationStart = segments[k]->getStart()->getElevation();
-                     double elevationEnd   = segments[k]->getEnd  ()->getElevation();
+                     double elevationStart = segments[k]->getStart()->getElevationM(parent->getElevation()*SG_FEET_TO_METER);
+                     double elevationEnd   = segments[k]->getEnd  ()->getElevationM(parent->getElevation()*SG_FEET_TO_METER);
                      if ((elevationStart == 0)  || (elevationStart == parent->getElevation())) {
                          SGGeod center2 = segments[k]->getStart()->getGeod();
                          center2.setElevationM(SG_MAX_ELEVATION_M);
                      geode->addDrawable(geometry);
                      //osg::Node *custom_obj;
                      SGMaterial *mat;
-                     if (segments[k]->hasBlock()) {
+                     if (segments[k]->hasBlock(now)) {
                          mat = matlib->find("UnidirectionalTaperRed");
                      } else {
                          mat = matlib->find("UnidirectionalTaperGreen");
@@@ -1482,8 -1507,9 +1507,9 @@@ string FGGroundNetwork::getName() 
  
  void FGGroundNetwork::update(double dt)
  {
+     time_t now = time(NULL) + fgGetLong("/sim/time/warp");
      for (FGTaxiSegmentVectorIterator tsi = segments.begin(); tsi != segments.end(); tsi++) {
-         (*tsi)->unblock();
+         (*tsi)->unblock(now);
      }
      int priority = 1;
      //sort(activeTraffic.begin(), activeTraffic.end(), compare_trafficrecords);
              i != parent->getDynamics()->getStartupController()->getActiveTraffic().end(); i++) {
          i->allowPushBack();
          i->setPriority(priority++);
+         // in meters per second;
+         double vTaxi = (i->getAircraft()->getPerformance()->vTaxi() * SG_NM_TO_METER) / 3600;
          if (i->isActive(60)) {
  
              // Check for all active aircraft whether it's current pos segment is
                          for (intVecIterator k = i->getIntentions().begin(); k != i->getIntentions().end(); k++) {
                              if ((*k) == posReverse) {
                                  i->denyPushBack();
-                                 segments[posReverse-1]->block();
+                                 segments[posReverse-1]->block(i->getId(), now, now);
                              }
                          }
                      }
              }
              // 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()) {
+                 double length = 0;
                  int pos = i->getCurrentPosition();
                  if (pos > 0) {
                      FGTaxiSegment *seg = segments[pos-1];
                      FGTaxiNode *node = seg->getEnd();
+                     length = seg->getLength();
                      for (FGTaxiSegmentVectorIterator tsi = segments.begin(); tsi != segments.end(); tsi++) {
                          if (((*tsi)->getEnd() == node) && ((*tsi) != seg)) {
-                             (*tsi)->block();
+                             (*tsi)->block(i->getId(), now, now);
                          }
                      }
                  }
                      if (pos > 0) {
                          FGTaxiSegment *seg = segments[pos-1];
                          FGTaxiNode *node = seg->getEnd();
+                         length += seg->getLength();
+                         time_t blockTime = now + (length / vTaxi);
                          for (FGTaxiSegmentVectorIterator tsi = segments.begin(); tsi != segments.end(); tsi++) {
                              if (((*tsi)->getEnd() == node) && ((*tsi) != seg)) {
-                                 (*tsi)->block();
+                                 (*tsi)->block(i->getId(), blockTime-30, now);
                              }
                          }
                      }
          }
      }
      for   (TrafficVectorIterator i = activeTraffic.begin(); i != activeTraffic.end(); i++) {
+         double length = 0;
+         double vTaxi = (i->getAircraft()->getPerformance()->vTaxi() * SG_NM_TO_METER) / 3600;
          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());
+             length = segments[pos-1]->getLength();
+             if (segments[pos-1]->hasBlock(now)) {
+                 //SG_LOG(SG_GENERAL, SG_ALERT, "Taxiway incursion for AI aircraft" << i->getAircraft()->getCallSign());
              }
  
          }
          for (ivi = i->getIntentions().begin(); ivi != i->getIntentions().end(); ivi++) {
              int segIndex = (*ivi);
              if (segIndex > 0) {
-                 if (segments[segIndex-1]->hasBlock())
+                 if (segments[segIndex-1]->hasBlock(now))
                      break;
              }
          }
              if (pos > 0) {
                  FGTaxiSegment *seg = segments[pos-1];
                  FGTaxiNode *node = seg->getEnd();
+                 length += seg->getLength();
                  for (FGTaxiSegmentVectorIterator tsi = segments.begin(); tsi != segments.end(); tsi++) {
                      if (((*tsi)->getEnd() == node) && ((*tsi) != seg)) {
-                         (*tsi)->block();
+                         time_t blockTime = now + (length / vTaxi);
+                         (*tsi)->block(i->getId(), blockTime - 30, now);
                      }
                  }
              }