]> git.mxchange.org Git - flightgear.git/blobdiff - src/ATC/trafficcontrol.cxx
Merge branch 'next' of gitorious.org:fg/flightgear into next
[flightgear.git] / src / ATC / trafficcontrol.cxx
index 685df21da7773ebe825f4f9d4b951e8fceedbca7..a25f9195646b2f5da7915b6f010cedba82a6cfb3 100644 (file)
@@ -47,6 +47,8 @@
 #include <Airports/groundnetwork.hxx>
 #include <Airports/dynamics.hxx>
 #include <Airports/simple.hxx>
+#include <Radio/radio.hxx>
+#include <signal.h>
 
 using std::sort;
 
@@ -140,6 +142,27 @@ time_t ActiveRunway::requestTimeSlot(time_t eta)
     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
  **************************************************************************/
@@ -164,14 +187,8 @@ void FGTrafficRecord::setPositionAndIntentions(int pos,
     if (intentions.size()) {
         intVecIterator i = intentions.begin();
         if ((*i) != pos) {
-            SG_LOG(SG_GENERAL, SG_ALERT,
-                   "Error in FGTrafficRecord::setPositionAndIntentions");
-            //cerr << "Pos : " << pos << " Curr " << *(intentions.begin())  << endl;
-            for (intVecIterator i = intentions.begin();
-                    i != intentions.end(); i++) {
-                //cerr << (*i) << " ";
-            }
-            //cerr << endl;
+            SG_LOG(SG_ATC, SG_ALERT,
+                   "Error in FGTrafficRecord::setPositionAndIntentions at " << SG_ORIGIN);
         }
         intentions.erase(i);
     } else {
@@ -179,21 +196,11 @@ void FGTrafficRecord::setPositionAndIntentions(int pos,
         int size = route->getNrOfWayPoints();
         //cerr << "Setting pos" << pos << " ";
         //cerr << "setting intentions ";
-        for (int i = 0; i < size; i++) {
+        for (int i = 2; i < size; i++) {
             int val = route->getRouteIndex(i);
-            //cerr << val<< " ";
-            if ((val) && (val != pos)) {
-                intentions.push_back(val);
-                //cerr << "[set] ";
-            }
+            intentions.push_back(val);
         }
-        //cerr << endl;
-        //while (route->next(&legNr, &routeNr)) {
-        //intentions.push_back(routeNr);
-        //}
-        //route->rewind(currentPos);
     }
-    //exit(1);
 }
 /**
  * Check if another aircraft is ahead of the current one, and on the same
@@ -266,8 +273,8 @@ int FGTrafficRecord::crosses(FGGroundNetwork * net,
     if (intentions.size()) {
         for (i = intentions.begin(); i != intentions.end(); i++) {
             if ((*i) > 0) {
-                if ((currentTargetNode ==
-                        net->findSegment(*i)->getEnd()->getIndex())) {
+                if (currentTargetNode ==
+                        net->findSegment(*i)->getEnd()->getIndex()) {
                     //cerr << "Current crosses at " << currentTargetNode <<endl;
                     return currentTargetNode;
                 }
@@ -487,7 +494,7 @@ bool FGATCController::isUserAircraft(FGAIAircraft* ac)
     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;
@@ -508,6 +515,7 @@ void FGATCController::transmit(FGTrafficRecord * rec, AtcMsgId msgId,
     FGAIFlightPlan *fp;
     string fltRules;
     string instructionText;
+    int ground_to_air=0;
 
     //double commFreqD;
     sender = rec->getAircraft()->getTrafficRef()->getCallSign();
@@ -548,6 +556,7 @@ void FGATCController::transmit(FGTrafficRecord * rec, AtcMsgId msgId,
         string tmp = sender;
         sender = receiver;
         receiver = tmp;
+        ground_to_air=1;
     }
     switch (msgId) {
     case MSG_ANNOUNCE_ENGINE_START:
@@ -715,10 +724,36 @@ void FGATCController::transmit(FGTrafficRecord * rec, AtcMsgId msgId,
         // 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 ((stationFreq > 0)&&
+            ((onBoardRadioFreqI0 == stationFreq)||
+             (onBoardRadioFreqI1 == stationFreq))) {
             if (rec->allowTransmissions()) {
-                fgSetString("/sim/messages/atc", text.c_str());
+               
+               if( fgGetBool( "/sim/radio/use-itm-attenuation", false ) ) {
+                       //cerr << "Using ITM radio propagation" << endl;
+                       FGRadioTransmission* radio = new FGRadioTransmission();
+                       SGGeod sender_pos;
+                       double sender_alt_ft, sender_alt;
+                       if(ground_to_air) {
+                                     sender_alt_ft = parent->getElevation();
+                                     sender_alt = sender_alt_ft * SG_FEET_TO_METER;
+                                     sender_pos= SGGeod::fromDegM( parent->getLongitude(),
+                                     parent->getLatitude(), sender_alt );
+                               }
+                               else {
+                                     sender_alt_ft = rec->getAltitude();
+                                     sender_alt = sender_alt_ft * SG_FEET_TO_METER;
+                                     sender_pos= SGGeod::fromDegM( rec->getLongitude(),
+                                            rec->getLatitude(), sender_alt );
+                               }
+                               double frequency = ((double)stationFreq) / 100;
+                       radio->receiveATC(sender_pos, frequency, text, ground_to_air);
+                       delete radio;
+               }
+               else {
+                       fgSetString("/sim/messages/atc", text.c_str());
+               }
             }
         }
     } else {
@@ -726,6 +761,7 @@ void FGATCController::transmit(FGTrafficRecord * rec, AtcMsgId msgId,
     }
 }
 
+
 string FGATCController::formatATCFrequency3_2(int freq)
 {
     char buffer[7];
@@ -844,8 +880,8 @@ void FGTowerController::updateAircraftInformation(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");
+        SG_LOG(SG_ATC, SG_ALERT,
+               "AI error: updating aircraft without traffic record at " << SG_ORIGIN);
     } else {
         i->setPositionAndHeading(lat, lon, heading, speed, alt);
         current = i;
@@ -855,7 +891,15 @@ void FGTowerController::updateAircraftInformation(int id, double lat, double lon
     // 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;
@@ -878,22 +922,29 @@ void FGTowerController::updateAircraftInformation(int id, double lat, double lon
         }
     } */
     // 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)
@@ -924,13 +975,13 @@ void FGTowerController::signOff(int id)
             rwy->setCleared(0);
             rwy->updateDepartureCue();
         } else {
-            SG_LOG(SG_GENERAL, SG_ALERT,
-                   "AI error: Attempting to erase non-existing runway clearance record in FGTowerController::signoff");
+            SG_LOG(SG_ATC, SG_ALERT,
+                   "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");
+        SG_LOG(SG_ATC, SG_ALERT,
+               "AI error: Aircraft without traffic record is signing off from tower at " << SG_ORIGIN);
     } else {
         i->getAircraft()->resetTakeOffStatus();
         i = activeTraffic.erase(i);
@@ -959,8 +1010,8 @@ bool FGTowerController::hasInstruction(int id)
         }
     }
     if (i == activeTraffic.end() || (activeTraffic.size() == 0)) {
-        SG_LOG(SG_GENERAL, SG_ALERT,
-               "AI error: checking ATC instruction for aircraft without traffic record");
+        SG_LOG(SG_ATC, SG_ALERT,
+               "AI error: checking ATC instruction for aircraft without traffic record at " << SG_ORIGIN);
     } else {
         return i->hasInstruction();
     }
@@ -983,8 +1034,8 @@ FGATCInstruction FGTowerController::getInstruction(int id)
         }
     }
     if (i == activeTraffic.end() || (activeTraffic.size() == 0)) {
-        SG_LOG(SG_GENERAL, SG_ALERT,
-               "AI error: requesting ATC instruction for aircraft without traffic record");
+        SG_LOG(SG_ATC, SG_ALERT,
+               "AI error: requesting ATC instruction for aircraft without traffic record at " << SG_ORIGIN);
     } else {
         return i->getInstruction();
     }
@@ -1078,8 +1129,8 @@ bool FGStartupController::hasInstruction(int id)
         }
     }
     if (i == activeTraffic.end() || (activeTraffic.size() == 0)) {
-        SG_LOG(SG_GENERAL, SG_ALERT,
-               "AI error: checking ATC instruction for aircraft without traffic record");
+        SG_LOG(SG_ATC, SG_ALERT,
+               "AI error: checking ATC instruction for aircraft without traffic record at " << SG_ORIGIN);
     } else {
         return i->hasInstruction();
     }
@@ -1102,8 +1153,8 @@ FGATCInstruction FGStartupController::getInstruction(int id)
         }
     }
     if (i == activeTraffic.end() || (activeTraffic.size() == 0)) {
-        SG_LOG(SG_GENERAL, SG_ALERT,
-               "AI error: requesting ATC instruction for aircraft without traffic record");
+        SG_LOG(SG_ATC, SG_ALERT,
+               "AI error: requesting ATC instruction for aircraft without traffic record at " << SG_ORIGIN);
     } else {
         return i->getInstruction();
     }
@@ -1125,8 +1176,8 @@ void FGStartupController::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 from tower");
+        SG_LOG(SG_ATC, SG_ALERT,
+               "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);
@@ -1150,13 +1201,13 @@ bool FGStartupController::checkTransmissionState(int st, time_t now, time_t star
                 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;
@@ -1186,8 +1237,8 @@ void FGStartupController::updateAircraftInformation(int id, double lat, double l
 //    // 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");
+        SG_LOG(SG_ATC, SG_ALERT,
+               "AI error: updating aircraft without traffic record at " << SG_ORIGIN);
     } else {
         i->setPositionAndHeading(lat, lon, heading, speed, alt);
         current = i;
@@ -1225,11 +1276,11 @@ void FGStartupController::updateAircraftInformation(int id, double lat, double l
         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();
             }
@@ -1247,7 +1298,7 @@ static void WorldCoordinate(osg::Matrix& obj_pos, double lat,
                             double lon, double elev, double hdg, double slope)
 {
     SGGeod geod = SGGeod::fromDegM(lon, lat, elev);
-    obj_pos = geod.makeZUpFrame();
+    obj_pos = makeZUpFrame(geod);
     // hdg is not a compass heading, but a counter-clockwise rotation
     // around the Z axis
     obj_pos.preMult(osg::Matrix::rotate(hdg * SGD_DEGREES_TO_RADIANS,
@@ -1276,12 +1327,13 @@ void FGStartupController::render(bool visible)
     if (visible) {
         group = new osg::Group;
         FGScenery * local_scenery = globals->get_scenery();
-        double elevation_meters = 0.0;
-        double elevation_feet = 0.0;
+        //double elevation_meters = 0.0;
+        //double elevation_feet = 0.0;
 
 
         //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
@@ -1313,12 +1365,12 @@ void FGStartupController::render(bool visible)
                     } 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);
                         if (local_scenery->get_elevation_m( center2, elevationEnd, NULL )) {
-                            elevation_feet = elevationEnd * SG_METER_TO_FEET + 0.5;
+                            //elevation_feet = elevationEnd * SG_METER_TO_FEET + 0.5;
                             //elevation_meters += 0.5;
                         }
                         else {
@@ -1351,7 +1403,7 @@ void FGStartupController::render(bool visible)
                     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");
@@ -1375,13 +1427,13 @@ void FGStartupController::render(bool visible)
                         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);
                             if (local_scenery->get_elevation_m( center2, elevationStart, NULL )) {
-                                elevation_feet = elevationStart * SG_METER_TO_FEET + 0.5;
+                                //elevation_feet = elevationStart * SG_METER_TO_FEET + 0.5;
                                 //elevation_meters += 0.5;
                             }
                             else {
@@ -1393,7 +1445,7 @@ void FGStartupController::render(bool visible)
                             SGGeod center2 = segment->getEnd()->getGeod();
                             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_feet = elevationEnd * SG_METER_TO_FEET + 0.5;
                                 //elevation_meters += 0.5;
                             }
                             else {
@@ -1428,7 +1480,7 @@ void FGStartupController::render(bool visible)
                         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");
@@ -1528,8 +1580,8 @@ void FGApproachController::updateAircraftInformation(int id, double lat, double
     }
 //    // 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");
+        SG_LOG(SG_ATC, SG_ALERT,
+               "AI error: updating aircraft without traffic record at " << SG_ORIGIN);
     } else {
         i->setPositionAndHeading(lat, lon, heading, speed, alt);
         current = i;
@@ -1576,8 +1628,8 @@ void FGApproachController::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 from approach");
+        SG_LOG(SG_ATC, SG_ALERT,
+               "AI error: Aircraft without traffic record is signing off from approach at " << SG_ORIGIN);
     } else {
         i = activeTraffic.erase(i);
     }
@@ -1605,8 +1657,8 @@ bool FGApproachController::hasInstruction(int id)
         }
     }
     if (i == activeTraffic.end() || (activeTraffic.size() == 0)) {
-        SG_LOG(SG_GENERAL, SG_ALERT,
-               "AI error: checking ATC instruction for aircraft without traffic record");
+        SG_LOG(SG_ATC, SG_ALERT,
+               "AI error: checking ATC instruction for aircraft without traffic record at " << SG_ORIGIN);
     } else {
         return i->hasInstruction();
     }
@@ -1629,8 +1681,8 @@ FGATCInstruction FGApproachController::getInstruction(int id)
         }
     }
     if (i == activeTraffic.end() || (activeTraffic.size() == 0)) {
-        SG_LOG(SG_GENERAL, SG_ALERT,
-               "AI error: requesting ATC instruction for aircraft without traffic record");
+        SG_LOG(SG_ATC, SG_ALERT,
+               "AI error: requesting ATC instruction for aircraft without traffic record at " << SG_ORIGIN);
     } else {
         return i->getInstruction();
     }