]> git.mxchange.org Git - flightgear.git/blobdiff - src/ATC/trafficcontrol.cxx
Merge branch 'next' into durk-atc
[flightgear.git] / src / ATC / trafficcontrol.cxx
index 53ddf28b5ec394dfdfd65cb83fbe513eccef230e..dc7d8c5f30743e5e150486055a3f8d45299c13d3 100644 (file)
 #include <algorithm>
 
 #include "trafficcontrol.hxx"
+#include "atc_mgr.hxx"
 #include <AIModel/AIAircraft.hxx>
 #include <AIModel/AIFlightPlan.hxx>
 #include <AIModel/performancedata.hxx>
 #include <AIModel/performancedb.hxx>
+#include <ATC/atc_mgr.hxx>
 #include <Traffic/TrafficMgr.hxx>
 #include <Airports/groundnetwork.hxx>
 #include <Airports/dynamics.hxx>
-
+#include <Airports/simple.hxx>
 
 using std::sort;
 
@@ -397,6 +399,10 @@ void FGTrafficRecord::setHeadingAdjustment(double heading)
 
 bool FGTrafficRecord::pushBackAllowed()
 {
+    // With the user ATC / AI integration, checking whether the user's aircraft is near no longer works, because
+    // this will effectively block the user's aircraft itself from receiving pushback clearance. 
+    // So, what can we do?
+    /*
     double course, az2, dist;
     SGGeod curr(SGGeod::fromDegM(getLongitude(),
                                  getLatitude(), getAltitude()));
@@ -407,7 +413,13 @@ bool FGTrafficRecord::pushBackAllowed()
     SGGeodesy::inverse(curr, user, course, az2, dist);
     //cerr << "Distance to user : " << dist << endl;
     return (dist > 250);
+    */
+
 
+    // In essence, we should check whether the pusbback route itself, as well as the associcated
+    // taxiways near the pushback point are free of traffic. 
+    // To do so, we need to 
+    return true;
 }
 
 
@@ -447,9 +459,16 @@ bool FGATCInstruction::hasInstruction()
 
 FGATCController::FGATCController()
 {
+    cerr << "running FGATController constructor" << endl;
     dt_count = 0;
     available = true;
     lastTransmission = 0;
+    initialized = false;
+}
+
+FGATCController::~FGATCController()
+{
+     cerr << "running FGATController destructor" << endl;
 }
 
 string FGATCController::getGateName(FGAIAircraft * ref)
@@ -457,8 +476,13 @@ string FGATCController::getGateName(FGAIAircraft * ref)
     return ref->atGate();
 }
 
+bool FGATCController::isUserAircraft(FGAIAircraft* ac) 
+{ 
+    return (ac->getCallSign() == fgGetString("/sim/multiplay/callsign")) ? true : false; 
+};
+
 void FGATCController::transmit(FGTrafficRecord * rec, AtcMsgId msgId,
-                               AtcMsgDir msgDir)
+                               AtcMsgDir msgDir, bool audible)
 {
     string sender, receiver;
     int stationFreq = 0;
@@ -623,22 +647,28 @@ void FGATCController::transmit(FGTrafficRecord * rec, AtcMsgId msgId,
         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");
-    int onBoardRadioFreqI0 = (int) floor(onBoardRadioFreq0 * 100 + 0.5);
-    int onBoardRadioFreqI1 = (int) floor(onBoardRadioFreq1 * 100 + 0.5);
-    //cerr << "Using " << onBoardRadioFreq0 << ", " << onBoardRadioFreq1 << " and " << stationFreq << " for " << text << endl;
-
-    // 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());
+    if (audible) {
+        double onBoardRadioFreq0 =
+            fgGetDouble("/instrumentation/comm[0]/frequencies/selected-mhz");
+        double onBoardRadioFreq1 =
+            fgGetDouble("/instrumentation/comm[1]/frequencies/selected-mhz");
+        int onBoardRadioFreqI0 = (int) floor(onBoardRadioFreq0 * 100 + 0.5);
+        int onBoardRadioFreqI1 = (int) floor(onBoardRadioFreq1 * 100 + 0.5);
+        //cerr << "Using " << onBoardRadioFreq0 << ", " << onBoardRadioFreq1 << " and " << stationFreq << " for " << text << endl;
+
+        // 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());
+            }
         }
+    } else {
+        FGATCManager *atc = (FGATCManager*) globals->get_subsystem("atc");
+        atc->getATCDialog()->addEntry(1, text);
+        
     }
 }
 
@@ -663,6 +693,15 @@ string FGATCController::genTransponderCode(string fltRules)
     }
 }
 
+void FGATCController::init() 
+{
+   if (!initialized) {
+       FGATCManager *mgr = (FGATCManager*) globals->get_subsystem("ATC");
+       mgr->addController(this);
+       initialized = true;
+    }
+}
+
 /***************************************************************************
  * class FGTowerController
  *
@@ -681,6 +720,7 @@ void FGTowerController::announcePosition(int id,
                                          double radius, int leg,
                                          FGAIAircraft * ref)
 {
+    init();
     TrafficVectorIterator i = activeTraffic.begin();
     // Search whether 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
@@ -709,9 +749,9 @@ void FGTowerController::announcePosition(int id,
     }
 }
 
-void FGTowerController::update(int id, double lat, double lon,
-                               double heading, double speed, double alt,
-                               double dt)
+void FGTowerController::updateAircraftInformation(int id, double lat, double lon,
+                                                  double heading, double speed, double alt,
+                                                  double dt)
 {
     TrafficVectorIterator i = activeTraffic.begin();
     // Search whether the current id has an entry
@@ -873,6 +913,7 @@ void FGStartupController::announcePosition(int id,
                                            double radius, int leg,
                                            FGAIAircraft * ref)
 {
+    init();
     TrafficVectorIterator i = activeTraffic.begin();
     // Search whether 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
@@ -978,9 +1019,43 @@ void FGStartupController::signOff(int id)
     }
 }
 
-void FGStartupController::update(int id, double lat, double lon,
-                                 double heading, double speed, double alt,
-                                 double dt)
+bool FGStartupController::checkTransmissionState(int st, time_t now, time_t startTime, TrafficVectorIterator i, AtcMsgId msgId,
+                               AtcMsgDir msgDir)
+{
+    int state = i->getState();
+    if ((state == st) && available) {
+        if ((msgDir == ATC_AIR_TO_GROUND) && isUserAircraft(i->getAircraft())) {
+            
+            cerr << "Checking state " << st << " for " << i->getAircraft()->getCallSign() << endl;
+            static SGPropertyNode_ptr trans_num = globals->get_props()->getNode("/sim/atc/transmission-num", true);
+            int n = trans_num->getIntValue();
+            if (n >= 0) {
+                trans_num->setIntValue(-1);
+                 // PopupCallback(n);
+                 cerr << "Selected transmission message" << n << endl;
+                 FGATCManager *atc = (FGATCManager*) globals->get_subsystem("atc");
+                 atc->getATCDialog()->removeEntry(1);
+            } else {
+                cerr << "creading message for " << i->getAircraft()->getCallSign() << endl;
+                transmit(&(*i), msgId, msgDir, false);
+                return false;
+            }
+        }
+        if (now > startTime) {
+            //cerr << "Transmitting startup msg" << endl;
+            transmit(&(*i), msgId, msgDir, true);
+            i->updateState();
+            lastTransmission = now;
+            available = false;
+            return true;
+        }
+    }
+    return false;
+}
+
+void FGStartupController::updateAircraftInformation(int id, double lat, double lon,
+                                                    double heading, double speed, double alt,
+                                                    double dt)
 {
     TrafficVectorIterator i = activeTraffic.begin();
     // Search search if the current id has an entry
@@ -996,6 +1071,7 @@ void FGStartupController::update(int id, double lat, double lon,
         }
     }
 //    // 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");
@@ -1006,8 +1082,10 @@ void FGStartupController::update(int id, double lat, double lon,
     setDt(getDt() + dt);
 
     int state = i->getState();
-    time_t startTime =
-        i->getAircraft()->getTrafficRef()->getDepartureTime();
+
+    // The user controlled aircraft should have crased here, because it doesn't have a traffic reference. 
+    // NOTE: if we create a traffic schedule for the user aircraft, we can use this to plan a flight.
+    time_t startTime = i->getAircraft()->getTrafficRef()->getDepartureTime();
     time_t now = time(NULL) + fgGetLong("/sim/time/warp");
     //cerr << i->getAircraft()->getTrafficRef()->getCallSign() 
     //     << " is scheduled to depart in " << startTime-now << " seconds. Available = " << available
@@ -1017,91 +1095,29 @@ void FGStartupController::update(int id, double lat, double lon,
         available = true;
     }
 
-    if ((state == 0) && available) {
-        if (now > startTime) {
-            //cerr << "Transmitting startup msg" << endl;
-            transmit(&(*i), MSG_ANNOUNCE_ENGINE_START, ATC_AIR_TO_GROUND);
-            i->updateState();
-            lastTransmission = now;
-            available = false;
-        }
-    }
-    if ((state == 1) && available) {
-        if (now > startTime + 60) {
-            transmit(&(*i), MSG_REQUEST_ENGINE_START, ATC_AIR_TO_GROUND);
-            i->updateState();
-            lastTransmission = now;
-            available = false;
-        }
-    }
-    if ((state == 2) && available) {
-        if (now > startTime + 80) {
-            transmit(&(*i), MSG_PERMIT_ENGINE_START, ATC_GROUND_TO_AIR);
-            i->updateState();
-            lastTransmission = now;
-            available = false;
-        }
-    }
-    if ((state == 3) && available) {
-        if (now > startTime + 100) {
-            transmit(&(*i), MSG_ACKNOWLEDGE_ENGINE_START,
-                     ATC_AIR_TO_GROUND);
-            i->updateState();
-            lastTransmission = now;
-            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;
-        }
+    checkTransmissionState(0, now, (startTime + 0  ), i, MSG_ANNOUNCE_ENGINE_START,                     ATC_AIR_TO_GROUND);
+    checkTransmissionState(1, now, (startTime + 60 ), i, MSG_REQUEST_ENGINE_START,                      ATC_AIR_TO_GROUND);
+    checkTransmissionState(2, now, (startTime + 80 ), i, MSG_PERMIT_ENGINE_START,                       ATC_GROUND_TO_AIR);
+    checkTransmissionState(3, now, (startTime + 100), i, MSG_ACKNOWLEDGE_ENGINE_START,                  ATC_AIR_TO_GROUND);
+    if (checkTransmissionState(4, now, (startTime + 130), i, MSG_ACKNOWLEDGE_SWITCH_GROUND_FREQUENCY,       ATC_AIR_TO_GROUND)) {
+        i->nextFrequency();
     }
+    checkTransmissionState(5, now, (startTime + 140), i, MSG_INITIATE_CONTACT,                          ATC_AIR_TO_GROUND);
+    checkTransmissionState(6, now, (startTime + 150), i, MSG_ACKNOWLEDGE_INITIATE_CONTACT,              ATC_GROUND_TO_AIR);
+    checkTransmissionState(7, now, (startTime + 180), i, MSG_REQUEST_PUSHBACK_CLEARANCE,                ATC_AIR_TO_GROUND);
 
-    // TODO: Switch to APRON control and request pushback Clearance.
-    // Get Push back clearance
-    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);
+                         ATC_GROUND_TO_AIR, true);
                 i->updateState();
             } else {
                 transmit(&(*i), MSG_HOLD_PUSHBACK_CLEARANCE,
-                         ATC_GROUND_TO_AIR);
+                         ATC_GROUND_TO_AIR, true);
                 i->suppressRepeatedTransmissions();
             }
             lastTransmission = now;
@@ -1132,6 +1148,7 @@ void FGApproachController::announcePosition(int id,
                                             double alt, double radius,
                                             int leg, FGAIAircraft * ref)
 {
+    init();
     TrafficVectorIterator i = activeTraffic.begin();
     // Search whether 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
@@ -1160,9 +1177,9 @@ void FGApproachController::announcePosition(int id,
     }
 }
 
-void FGApproachController::update(int id, double lat, double lon,
-                                  double heading, double speed, double alt,
-                                  double dt)
+void FGApproachController::updateAircraftInformation(int id, double lat, double lon,
+                                                     double heading, double speed, double alt,
+                                                     double dt)
 {
     TrafficVectorIterator i = activeTraffic.begin();
     // Search search if the current id has an entry