]> git.mxchange.org Git - flightgear.git/blobdiff - src/ATC/trafficcontrol.cxx
Fix two bugs in the new autopilot code
[flightgear.git] / src / ATC / trafficcontrol.cxx
index 57f718812ce242bbf680a8eb9371ffd278e3b3fa..ba00b60194f2288f4d3c6c1dc927983706867095 100644 (file)
@@ -38,13 +38,16 @@ FGTrafficRecord::FGTrafficRecord() :
   id(0), waitsForId(0),
   currentPos(0),
   leg(0),
+  frequencyId(0),
   state(0),
+   allowTransmission(true),
   latitude(0),
   longitude(0), 
    heading(0), 
    speed(0), 
    altitude(0), 
-   radius(0) {
+   radius(0)
+{
 }
 
 void FGTrafficRecord::setPositionAndIntentions(int pos, FGAIFlightPlan *route)
@@ -63,7 +66,6 @@ void FGTrafficRecord::setPositionAndIntentions(int pos, FGAIFlightPlan *route)
      }
      intentions.erase(i);
    } else {
-     //int legNr, routeNr;
      //FGAIFlightPlan::waypoint* const wpt= route->getCurrentWaypoint();
      int size = route->getNrOfWayPoints();
      //cerr << "Setting pos" << pos << " ";
@@ -264,7 +266,7 @@ bool FGTrafficRecord::isOpposing (FGGroundNetwork *net, FGTrafficRecord &other,
          if (other.intentions.size())
            {
              for (intVecIterator j = other.intentions.begin(); j != other.intentions.end(); j++)
-               {  
+               {
                  // cerr << "Current segment 1 " << (*i) << endl;
                  if ((*i) > 0) {
                    if ((opp = net->findSegment(*i)->opposite()))
@@ -303,6 +305,21 @@ void FGTrafficRecord::setHeadingAdjustment(double heading)
   instruction.setHeading(heading); 
 }
 
+bool FGTrafficRecord::pushBackAllowed() {
+      double course, az2,dist;
+       SGGeod curr(SGGeod::fromDegM(getLongitude(),
+                                       getLatitude(), 
+                                       getAltitude()));
+
+      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);
+      //cerr << "Distance to user : " << dist << endl;
+      return (dist > 250);
+
+}
+
 
 
 /***************************************************************************
@@ -323,11 +340,27 @@ FGATCInstruction::FGATCInstruction()
   alt     = 0;
 }
 
+
 bool FGATCInstruction::hasInstruction()
 {
   return (holdPattern || holdPosition || changeSpeed || changeHeading || changeAltitude || resolveCircularWait);
 }
 
+/***************************************************************************
+ * FGATCController
+ *
+ **************************************************************************/
+
+
+
+
+FGATCController::FGATCController() 
+{
+     dt_count = 0; 
+     available = true; 
+     lastTransmission = 0;
+}
+
 string FGATCController::getGateName(FGAIAircraft *ref) 
 {
     return ref->atGate();
@@ -338,45 +371,8 @@ void FGATCController::transmit(FGTrafficRecord *rec, AtcMsgId msgId, AtcMsgDir m
     string sender, receiver;
     int stationFreq = 0;
     int taxiFreq    = 0;
+    int freqId      = 0;
     string atisInformation;
-    //double commFreqD;
-    switch (msgDir) {
-         case ATC_AIR_TO_GROUND:
-             sender = rec->getAircraft()->getTrafficRef()->getCallSign();
-             switch (rec->getLeg()) {
-                 case 2:
-                 case 3:
-                     stationFreq =
-                        rec->getAircraft()->getTrafficRef()->getDepartureAirport()->getDynamics()->getGroundFrequency(rec->getLeg());
-                     taxiFreq =
-                        rec->getAircraft()->getTrafficRef()->getDepartureAirport()->getDynamics()->getGroundFrequency(3);
-                     receiver = rec->getAircraft()->getTrafficRef()->getDepartureAirport()->getName() + "-Ground";
-                     atisInformation = rec->getAircraft()->getTrafficRef()->getDepartureAirport()->getDynamics()->getAtisInformation();
-                     break;
-                 case 4: 
-                     receiver = rec->getAircraft()->getTrafficRef()->getDepartureAirport()->getName() + "-Tower";
-                     break;
-             }
-             break;
-         case ATC_GROUND_TO_AIR:
-             receiver = rec->getAircraft()->getTrafficRef()->getCallSign();
-             switch (rec->getLeg()) {
-                 case 2:
-                 case 3:
-                 stationFreq =
-                        rec->getAircraft()->getTrafficRef()->getDepartureAirport()->getDynamics()->getGroundFrequency(rec->getLeg());
-                     taxiFreq =
-                        rec->getAircraft()->getTrafficRef()->getDepartureAirport()->getDynamics()->getGroundFrequency(3);
-                     sender = rec->getAircraft()->getTrafficRef()->getDepartureAirport()->getName() + "-Ground";
-                     atisInformation = rec->getAircraft()->getTrafficRef()->getDepartureAirport()->getDynamics()->getAtisInformation();
-                     break;
-
-                 case 4: 
-                     sender = rec->getAircraft()->getTrafficRef()->getDepartureAirport()->getName() + "-Tower";
-                     break;
-             }
-             break;
-         }
     string text;
     string taxiFreqStr;
     double heading = 0;
@@ -387,6 +383,31 @@ void FGATCController::transmit(FGTrafficRecord *rec, AtcMsgId msgId, AtcMsgDir m
     string transponderCode;
     FGAIFlightPlan *fp;
     string fltRules;
+
+    //double commFreqD;
+    sender = rec->getAircraft()->getTrafficRef()->getCallSign();
+    //cerr << "transmitting for: " << sender << "Leg = " << rec->getLeg() << endl;
+    switch (rec->getLeg()) {
+        case 2:
+        case 3:
+            freqId = rec->getNextFrequency();
+            stationFreq =
+            rec->getAircraft()->getTrafficRef()->getDepartureAirport()->getDynamics()->getGroundFrequency(rec->getLeg()+freqId);
+            taxiFreq =
+            rec->getAircraft()->getTrafficRef()->getDepartureAirport()->getDynamics()->getGroundFrequency(3);
+            receiver = rec->getAircraft()->getTrafficRef()->getDepartureAirport()->getName() + "-Ground";
+            atisInformation = rec->getAircraft()->getTrafficRef()->getDepartureAirport()->getDynamics()->getAtisInformation();
+            break;
+        case 4: 
+            receiver = rec->getAircraft()->getTrafficRef()->getDepartureAirport()->getName() + "-Tower";
+            break;
+    }
+    // Swap sender and receiver value in case of a ground to air transmission
+    if (msgDir == ATC_GROUND_TO_AIR) {
+       string tmp = sender;
+       sender = receiver;
+       receiver = tmp;
+    }
     switch (msgId) {
           case MSG_ANNOUNCE_ENGINE_START:
                text = sender + ". Ready to Start up";
@@ -402,7 +423,7 @@ void FGATCController::transmit(FGTrafficRecord *rec, AtcMsgId msgId, AtcMsgDir m
           // Assign SID, if necessery (TODO)
           case MSG_PERMIT_ENGINE_START:
                taxiFreqStr = formatATCFrequency3_2(taxiFreq);
-               
+
                heading = rec->getAircraft()->getTrafficRef()->getCourse();
                fltType = rec->getAircraft()->getTrafficRef()->getFlightType();
                rwyClass= rec->getAircraft()->GetFlightPlan()->getRunwayClassFromTrafficType(fltType);
@@ -441,8 +462,49 @@ void FGATCController::transmit(FGTrafficRecord *rec, AtcMsgId msgId, AtcMsgDir m
                       activeRunway + ", " + SID + ", squawk " + transponderCode + ". " +
                       "For push-back and taxi clearance call " + taxiFreqStr + ". " + sender;
                break;
-           default:
+           case MSG_ACKNOWLEDGE_SWITCH_GROUND_FREQUENCY:
+               taxiFreqStr = formatATCFrequency3_2(taxiFreq);
+               text = receiver + ". Switching to " + taxiFreqStr + ". " + sender;
+               break;
+           case MSG_INITIATE_CONTACT:
+                text = receiver + ". With you. " + sender;
+                break;
+           case MSG_ACKNOWLEDGE_INITIATE_CONTACT:
+                text = receiver + ". Roger. " + sender;
+                break;
+           case MSG_REQUEST_PUSHBACK_CLEARANCE:
+               text = receiver + ". Request push-back. " + sender;
                break;
+           case MSG_PERMIT_PUSHBACK_CLEARANCE:
+               text = receiver + ". Push-back approved. " + sender;
+               break;
+           case MSG_HOLD_PUSHBACK_CLEARANCE:
+                text = receiver + ". Standby. " + sender;
+                break;
+           case MSG_REQUEST_TAXI_CLEARANCE:
+                text = receiver + ". Ready to Taxi. " + sender;
+                break;
+           case MSG_ISSUE_TAXI_CLEARANCE:
+                text = receiver + ". Cleared to taxi. " + sender;
+                break;
+           case MSG_ACKNOWLEDGE_TAXI_CLEARANCE:
+                text = receiver + ". Cleared to taxi. " + sender;
+                break;
+           case MSG_HOLD_POSITION:
+                text = receiver + ". Hold Position. " + sender;
+                break;
+           case MSG_ACKNOWLEDGE_HOLD_POSITION:
+                text = receiver + ". Holding Position. " + sender;
+                break;
+           case MSG_RESUME_TAXI:
+                text = receiver + ". Resume Taxiing. " + sender;
+                break;
+           case MSG_ACKNOWLEDGE_RESUME_TAXI:
+                text = receiver + ". Continuing Taxi. " + sender;
+                break;
+           default:
+                 text = text + sender + ". Transmitting unknown Message";
+                  break;
     }
     double onBoardRadioFreq0 = fgGetDouble("/instrumentation/comm[0]/frequencies/selected-mhz");
     double onBoardRadioFreq1 = fgGetDouble("/instrumentation/comm[1]/frequencies/selected-mhz");
@@ -453,10 +515,10 @@ void FGATCController::transmit(FGTrafficRecord *rec, AtcMsgId msgId, AtcMsgDir m
     // Display ATC message only when one of the radios is tuned
     // the relevant frequency.
     // Note that distance attenuation is currently not yet implemented
-    //cerr << "Transmitting " << text << " at " << stationFreq;
     if ((onBoardRadioFreqI0 == stationFreq) || (onBoardRadioFreqI1 == stationFreq)) {
-        fgSetString("/sim/messages/atc", text.c_str());
-        //cerr << "Printing Message: " << endl;
+        if (rec->allowTransmissions()) {
+            fgSetString("/sim/messages/atc", text.c_str());
+        }
     }
 }
 
@@ -466,6 +528,8 @@ string FGATCController::formatATCFrequency3_2(int freq) {
     return string(buffer);
 }
 
+// TODO: Set transponder codes according to real-world routes.
+// The current version just returns a random string of four octal numbers. 
 string FGATCController::genTransponderCode(string fltRules) {
     if (fltRules == "VFR") {
         return string("1200");
@@ -671,8 +735,6 @@ FGATCInstruction FGTowerController::getInstruction(int id)
 FGStartupController::FGStartupController() :
   FGATCController()
 {
-    available        = false;
-    lastTransmission = 0;
 }
 
 void FGStartupController::announcePosition(int id, FGAIFlightPlan *intendedRoute, int currentPosition,
@@ -854,9 +916,60 @@ void FGStartupController::update(int id, double lat, double lon, double heading,
              available = false;
         }
      }
+     // Note: The next four stages are only necessesary when Startup control is
+     //  on a different frequency, compared to ground control
+     if ((state == 4) && available){
+        if (now > startTime+130) {
+            transmit(&(*i), MSG_ACKNOWLEDGE_SWITCH_GROUND_FREQUENCY, ATC_AIR_TO_GROUND);
+            i->updateState();
+            i->nextFrequency();
+            lastTransmission = now;
+             available = false;
+        }
+     }
+     if ((state == 5) && available){
+        if (now > startTime+140) {
+            transmit(&(*i), MSG_INITIATE_CONTACT, ATC_AIR_TO_GROUND);
+            i->updateState();
+            lastTransmission = now;
+             available = false;
+        }
+     }
+     if ((state == 6) && available){
+        if (now > startTime+150) {
+            transmit(&(*i), MSG_ACKNOWLEDGE_INITIATE_CONTACT, ATC_GROUND_TO_AIR);
+            i->updateState();
+            lastTransmission = now;
+             available = false;
+        }
+     }
+
+
      // TODO: Switch to APRON control and request pushback Clearance.
      // Get Push back clearance
-     if ((state == 4) && available){
+     if ((state == 7) && available){
+        if (now > startTime+180) {
+            transmit(&(*i), MSG_REQUEST_PUSHBACK_CLEARANCE, ATC_AIR_TO_GROUND);
+            i->updateState();
+            lastTransmission = now;
+             available = false;
+        }
+     }
+     if ((state == 8) && available){
+        if (now > startTime+200) {
+            if (i->pushBackAllowed()) {
+                 i->allowRepeatedTransmissions();
+                 transmit(&(*i), MSG_PERMIT_PUSHBACK_CLEARANCE, ATC_GROUND_TO_AIR);
+                 i->updateState();
+            } else {
+                 transmit(&(*i), MSG_HOLD_PUSHBACK_CLEARANCE, ATC_GROUND_TO_AIR);
+                 i->suppressRepeatedTransmissions();
+            }
+            lastTransmission = now;
+             available = false;
+        }
+     }
+     if ((state == 9) && available){
           i->setHoldPosition(false);
      }
 }