From 7a044b3faa97ef39d0813fe95211c4e6248abfb8 Mon Sep 17 00:00:00 2001 From: daveluff Date: Wed, 10 Mar 2004 16:01:17 +0000 Subject: [PATCH] Start adding a better framework for ATC-initiated communication. There should be no user-visible change from this commit --- src/ATC/ATC.cxx | 95 +++++++++++++++++++++++++++++++++++++++++--- src/ATC/ATC.hxx | 32 +++++++++++++-- src/ATC/approach.cxx | 1 - src/ATC/approach.hxx | 8 ---- src/ATC/atis.cxx | 12 +++--- src/ATC/atis.hxx | 8 ---- src/ATC/ground.cxx | 7 +--- src/ATC/ground.hxx | 4 -- src/ATC/tower.cxx | 37 ++++++++--------- src/ATC/tower.hxx | 6 --- 10 files changed, 143 insertions(+), 67 deletions(-) diff --git a/src/ATC/ATC.cxx b/src/ATC/ATC.cxx index 085d84166..d76ba74cf 100644 --- a/src/ATC/ATC.cxx +++ b/src/ATC/ATC.cxx @@ -24,6 +24,7 @@ #include +#include
#include
#include "ATC.hxx" @@ -38,6 +39,18 @@ FGATC::FGATC() { responseID = ""; responseReqd = false; _type = INVALID; + _display = false; + _displaying = false; + + // Transmission timing stuff + pending_transmission = ""; + _timeout = 0; + _pending = false; + _callback_code = 0; + _transmit = false; + _transmitting = false; + _counter = 0.0; + _max_count = 5.0; } FGATC::~FGATC() { @@ -64,6 +77,54 @@ void FGATC::Update(double dt) { _releaseCounter += dt; } } + + // Transmission stuff cribbed from AIPlane.cxx + if(_pending) { + if(GetFreqClear()) { + //cout << "TUNED STATION FREQ CLEAR\n"; + SetFreqInUse(); + _pending = false; + _transmit = true; + _transmitting = false; + } else { + if(_timeout > 0.0) { // allows count down to be avoided by initially setting it to zero + _timeout -= dt; + if(_timeout <= 0.0) { + _timeout = 0.0; + _pending = false; + // timed out - don't render. + } + } + } + } + + if(_transmit) { + _counter = 0.0; + _max_count = 5.0; // FIXME - hardwired length of message - need to calculate it! + + //cout << "Transmission = " << pending_transmission << '\n'; + if(_display) { + //Render(pending_transmission, ident, false); + // At the moment Render only works for ATIS + globals->get_ATC_display()->RegisterSingleMessage(pending_transmission); + } + // Run the callback regardless of whether on same freq as user or not. + //cout << "_callback_code = " << _callback_code << '\n'; + if(_callback_code) { + ProcessCallback(_callback_code); + } + _transmit = false; + _transmitting = true; + } else if(_transmitting) { + if(_counter >= _max_count) { + //NoRender(plane.callsign); commented out since at the moment NoRender is designed just to stop repeating messages, + // and this will be primarily used on single messages. + _transmitting = false; + //if(tuned_station) tuned_station->NotifyTransmissionFinished(plane.callsign); + // TODO - need to let the plane the transmission is aimed at that it's finished. + } + _counter += dt; + } } void FGATC::ReceiveUserCallback(int code) { @@ -96,17 +157,41 @@ void FGATC::NotifyTransmissionFinished(string rid) { } } -void FGATC::AddPlane(string pid) { +void FGATC::Transmit(int callback_code) { + SG_LOG(SG_ATC, SG_INFO, "Transmit called by " << ident << " " << _type << ", msg = " << pending_transmission); + _pending = true; + _callback_code = callback_code; + _timeout = 0.0; } -int FGATC::RemovePlane() { - return 0; +void FGATC::ConditionalTransmit(double timeout, int callback_code) { + SG_LOG(SG_ATC, SG_INFO, "Timed transmit called by " << ident << " " << _type << ", msg = " << pending_transmission); + _pending = true; + _callback_code = callback_code; + _timeout = timeout; +} + +void FGATC::ImmediateTransmit(int callback_code) { + SG_LOG(SG_ATC, SG_INFO, "Immediate transmit called by " << ident << " " << _type << ", msg = " << pending_transmission); + if(_display) { + //Render(pending_transmission, ident, false); + // At the moment Render doesn't work except for ATIS + globals->get_ATC_display()->RegisterSingleMessage(pending_transmission); + } + if(callback_code) { + ProcessCallback(callback_code); + } } -void FGATC::SetDisplay() { +// Derived classes should override this. +void FGATC::ProcessCallback(int code) { } -void FGATC::SetNoDisplay() { +void FGATC::AddPlane(string pid) { +} + +int FGATC::RemovePlane() { + return 0; } void FGATC::SetData(ATCData* d) { diff --git a/src/ATC/ATC.hxx b/src/ATC/ATC.hxx index 0a06761a0..1bbbd846e 100644 --- a/src/ATC/ATC.hxx +++ b/src/ATC/ATC.hxx @@ -123,10 +123,10 @@ public: virtual int RemovePlane(); // Indicate that this instance should output to the display if appropriate - virtual void SetDisplay(); + inline void SetDisplay() { _display = true; } // Indicate that this instance should not output to the display - virtual void SetNoDisplay(); + inline void SetNoDisplay() { _display = false; } // Generate the text of a message from its parameters and the current context. virtual string GenText(const string& m, int c); @@ -186,6 +186,17 @@ protected: // Requires the sound manager refname if audio, else "". void NoRender(string refname); + // Transmit a message when channel becomes free of other dialog + void Transmit(int callback_code = 0); + + // Transmit a message if channel becomes free within timeout (seconds). timeout of zero implies no limit + void ConditionalTransmit(double timeout, int callback_code = 0); + + // Transmit regardless of other dialog on the channel eg emergency + void ImmediateTransmit(int callback_code = 0); + + virtual void ProcessCallback(int code); + double lon, lat, elev; double x, y, z; int freq; @@ -199,7 +210,8 @@ protected: bool playing; // Indicates a message in progress bool voiceOK; // Flag - true if at least one voice has loaded OK FGATCVoice* vPtr; - + + string pending_transmission; // derived classes set this string before calling Transmit(...) bool freqClear; // Flag to indicate if the frequency is clear of ongoing dialog bool receiving; // Flag to indicate we are receiving a transmission bool responseReqd; // Flag to indicate we should be responding to a request/report @@ -213,6 +225,20 @@ protected: bool _runReleaseCounter; // A timer for releasing the frequency after giving the message enough time to display double _releaseTime; double _releaseCounter; + + bool _display; // Flag to indicate whether we should be outputting to the ATC display. + bool _displaying; // Flag to indicate whether we are outputting to the ATC display. + +private: + // Transmission timing stuff. + bool _pending; + double _timeout; + int _callback_code; // A callback code to be notified and processed by the derived classes + // A value of zero indicates no callback required + bool _transmit; // we are to transmit + bool _transmitting; // we are transmitting + double _counter; + double _max_count; }; inline istream& diff --git a/src/ATC/approach.cxx b/src/ATC/approach.cxx index 6d7a5a869..c036a2827 100644 --- a/src/ATC/approach.cxx +++ b/src/ATC/approach.cxx @@ -77,7 +77,6 @@ FGApproach::~FGApproach(){ } void FGApproach::Init() { - display = false; } diff --git a/src/ATC/approach.hxx b/src/ATC/approach.hxx index fb2d31924..29d349060 100644 --- a/src/ATC/approach.hxx +++ b/src/ATC/approach.hxx @@ -117,8 +117,6 @@ class FGApproach : public FGATC { double active_rw_lat; double active_rw_len; - bool display; // Flag to indicate whether we should be outputting to the display. - bool displaying; // Flag to indicate whether we are outputting to the display. int num_planes; // number of planes on the stack PlaneApp planes[max_planes]; // Array of planes string transmission; @@ -160,12 +158,6 @@ public: // Remove plane from stack if out of range int RemovePlane(); - //Indicate that this instance should be outputting to the ATC display - inline void SetDisplay(void) {display = true;} - - //Indicate that this instance should not be outputting to the ATC display - inline void SetNoDisplay(void) {display = false;} - inline double get_bucket() const { return bucket; } inline int get_pnum() const { return num_planes; } inline string get_trans_ident() { return trans_ident; } diff --git a/src/ATC/atis.cxx b/src/ATC/atis.cxx index 35bb25a2e..ff0da5767 100644 --- a/src/ATC/atis.cxx +++ b/src/ATC/atis.cxx @@ -54,8 +54,6 @@ SG_USING_STD(cout); #include "ATCmgr.hxx" FGATIS::FGATIS() : - display(false), - displaying(false), transmission(""), trans_ident(""), atis_failed(false), @@ -72,8 +70,8 @@ FGATIS::~FGATIS() { // Main update function - checks whether we are displaying or not the correct message. void FGATIS::Update(double dt) { - if(display) { - if(displaying) { + if(_display) { + if(_displaying) { // Check if we need to update the message // - basically every hour and if the weather changes significantly at the station //globals->get_ATC_display()->ChangeRepeatingMessage(transmission); @@ -82,14 +80,14 @@ void FGATIS::Update(double dt) { UpdateTransmission(); //cout << "ATIS.CXX - calling ATCMgr to render transmission..." << endl; Render(transmission, refname, true); - displaying = true; + _displaying = true; } } else { // We shouldn't be displaying - if(displaying) { + if(_displaying) { //cout << "ATIS.CXX - calling NoRender()..." << endl; NoRender(refname); - displaying = false; + _displaying = false; } } } diff --git a/src/ATC/atis.hxx b/src/ATC/atis.hxx index 0d22b3efa..741e9943d 100644 --- a/src/ATC/atis.hxx +++ b/src/ATC/atis.hxx @@ -53,8 +53,6 @@ SG_USING_STD(string); class FGATIS : public FGATC { //atc_type type; - bool display; // Flag to indicate whether we should be outputting to the ATC display. - bool displaying; // Flag to indicate whether we are outputting to the ATC display. string transmission; // The actual ATIS transmission // This is not stored in default.atis but is generated // from the prevailing conditions when required. @@ -80,12 +78,6 @@ class FGATIS : public FGATC { //run the ATIS instance void Update(double dt); - //Indicate that this instance should be outputting to the ATC display - inline void SetDisplay(void) {display = true;} - - //Indicate that this instance should not be outputting to the ATC display - inline void SetNoDisplay(void) {display = false;} - //inline void set_type(const atc_type tp) {type = tp;} inline string get_trans_ident() { return trans_ident; } inline void set_refname(string r) { refname = r; } diff --git a/src/ATC/ground.cxx b/src/ATC/ground.cxx index 468560035..3e2e0f68b 100644 --- a/src/ATC/ground.cxx +++ b/src/ATC/ground.cxx @@ -54,7 +54,6 @@ a_path::a_path() { FGGround::FGGround() { ATCmgr = globals->get_ATC_mgr(); _type = GROUND; - display = false; networkLoadOK = false; ground_traffic.erase(ground_traffic.begin(), ground_traffic.end()); ground_traffic_itr = ground_traffic.begin(); @@ -69,7 +68,6 @@ FGGround::FGGround() { FGGround::FGGround(string id) { ATCmgr = globals->get_ATC_mgr(); - display = false; networkLoadOK = false; ground_traffic.erase(ground_traffic.begin(), ground_traffic.end()); ground_traffic_itr = ground_traffic.begin(); @@ -274,7 +272,6 @@ bool FGGround::LoadNetwork() { } void FGGround::Init() { - display = false; untowered = false; // Figure out which is the active runway - TODO - it would be better to have ground call tower @@ -318,7 +315,7 @@ void FGGround::Update(double dt) { trns += " taxi holding point runway "; // TODO - add the holding point name // eg " taxi holding point G2 runway " trns += ConvertRwyNumToSpokenString(activeRwy); - if(display) { + if(_display) { globals->get_ATC_display()->RegisterSingleMessage(trns, 0); } g->planePtr->RegisterTransmission(1); // cleared to taxi @@ -336,7 +333,7 @@ void FGGround::Update(double dt) { char buf[10]; sprintf(buf, "%.2f", f); trns += buf; - if(display) { + if(_display) { globals->get_ATC_display()->RegisterSingleMessage(trns, 0); } g->planePtr->RegisterTransmission(2); // contact tower diff --git a/src/ATC/ground.hxx b/src/ATC/ground.hxx index b0cf1f3d8..ffc668c4a 100644 --- a/src/ATC/ground.hxx +++ b/src/ATC/ground.hxx @@ -232,8 +232,6 @@ public: void Update(double dt); inline string get_trans_ident() { return trans_ident; } - inline void SetDisplay() {display = true;} - inline void SetNoDisplay() {display = false;} // Contact ground control on arrival, assumed to request any gate //void NewArrival(plane_rec plane); @@ -313,8 +311,6 @@ private: SGPropertyNode* wind_from_hdg; //degrees SGPropertyNode* wind_speed_knots; //knots - bool display; // Flag to indicate whether we should be outputting to the ATC display. - bool displaying; // Flag to indicate whether we are outputting to the ATC display. // for failure modeling string trans_ident; // transmitted ident bool ground_failed; // ground failed? diff --git a/src/ATC/tower.cxx b/src/ATC/tower.cxx index c10d63143..b77670e0c 100644 --- a/src/ATC/tower.cxx +++ b/src/ATC/tower.cxx @@ -231,7 +231,6 @@ FGTower::~FGTower() { void FGTower::Init() { //cout << "Initialising tower " << ident << '\n'; - display = false; // Pointers to user's position user_lon_node = fgGetNode("/position/longitude-deg", true); @@ -256,7 +255,7 @@ void FGTower::Init() { ground = new FGGround(ident); separateGround = false; ground->Init(); - if(display) { + if(_display) { ground->SetDisplay(); } else { ground->SetNoDisplay(); @@ -268,7 +267,7 @@ void FGTower::Init() { ground = new FGGround(ident); separateGround = false; ground->Init(); - if(display) { + if(_display) { ground->SetDisplay(); } else { ground->SetNoDisplay(); @@ -280,7 +279,7 @@ void FGTower::Init() { ground = new FGGround(ident); separateGround = false; ground->Init(); - if(display) { + if(_display) { ground->SetDisplay(); } else { ground->SetNoDisplay(); @@ -407,7 +406,8 @@ void FGTower::Update(double dt) { // The display stuff might have to get more clever than this when not separate // since the tower and ground might try communicating simultaneously even though // they're mean't to be the same contoller/frequency!! - if(display) { + // We could also get rid of this by overloading FGATC's Set(No)Display() functions. + if(_display) { ground->SetDisplay(); } else { ground->SetNoDisplay(); @@ -503,7 +503,7 @@ void FGTower::Respond() { } } trns += ConvertRwyNumToSpokenString(activeRwy); - if(display) { + if(_display) { globals->get_ATC_display()->RegisterSingleMessage(trns, 0); } else { //cout << "Not displaying, trns was " << trns << '\n'; @@ -526,7 +526,7 @@ void FGTower::Respond() { t->clearedToLand = true; if(!t->isUser) t->planePtr->RegisterTransmission(7); } - if(display) { + if(_display) { globals->get_ATC_display()->RegisterSingleMessage(trns); } if(t->isUser) { @@ -562,7 +562,7 @@ void FGTower::Respond() { // Not currently sure under which circumstances we do or don't bother transmitting this. string trns = t->plane.callsign; trns += " hold position"; - if(display) { + if(_display) { globals->get_ATC_display()->RegisterSingleMessage(trns, 0); } // TODO - add some idea of what traffic is blocking him. @@ -600,7 +600,7 @@ void FGTower::Respond() { trns += " continue approach"; t->clearedToLand = false; } - if(display && disp) { + if(_display && disp) { globals->get_ATC_display()->RegisterSingleMessage(trns); } t->finalAcknowledged = true; @@ -634,7 +634,7 @@ void FGTower::ProcessRunwayVacatedReport(TowerPlaneRec* t) { if(!t->isUser) t->planePtr->RegisterTransmission(6); // TODO - this is a mega-hack!! } //cout << "trns = " << trns << '\n'; - if(display) { + if(_display) { globals->get_ATC_display()->RegisterSingleMessage(trns); } // Maybe we should check that the plane really *has* vacated the runway! @@ -741,7 +741,7 @@ void FGTower::ClearHoldingPlane(TowerPlaneRec* t) { departed = false; timeSinceLastDeparture = 0.0; } - if(display) { + if(_display) { globals->get_ATC_display()->RegisterSingleMessage(trns, 0); } //cout << "Done ClearHoldingPlane " << endl; @@ -961,9 +961,8 @@ void FGTower::CheckCircuitList(double dt) { // For now this should stop the AI plane landing on top of the user. string trns = t->plane.callsign; trns += " GO AROUND TRAFFIC ON RUNWAY I REPEAT GO AROUND"; - if(display) { - globals->get_ATC_display()->RegisterSingleMessage(trns, 0); - } + pending_transmission = trns; + ImmediateTransmit(); t->instructedToGoAround = true; t->clearedToLand = false; // Assume it complies!!! @@ -1082,9 +1081,8 @@ void FGTower::CheckApproachList(double dt) { // For now this should stop the AI plane landing on top of the user. string trns = t->plane.callsign; trns += " GO AROUND TRAFFIC ON RUNWAY I REPEAT GO AROUND"; - if(display) { - globals->get_ATC_display()->RegisterSingleMessage(trns, 0); - } + pending_transmission = trns; + ImmediateTransmit(); t->instructedToGoAround = true; t->clearedToLand = false; t->nextOnRwy = false; // But note this is recalculated so don't rely on it @@ -1159,9 +1157,8 @@ void FGTower::CheckDepartureList(double dt) { if(distout > 10000) { string trns = t->plane.callsign; trns += " You are now clear of my airspace, good day"; - if(display) { - globals->get_ATC_display()->RegisterSingleMessage(trns, 0); - } + pending_transmission = trns; + Transmit(); if(t->isUser) { // Change the communication options RemoveAllUserDialogOptions(); diff --git a/src/ATC/tower.hxx b/src/ATC/tower.hxx index 9d0a55734..1fd3d65ed 100644 --- a/src/ATC/tower.hxx +++ b/src/ATC/tower.hxx @@ -168,9 +168,6 @@ public: // Get the pattern direction of the active rwy. inline int GetPatternDirection() { return rwy.patternDirection; } - inline void SetDisplay() { display = true; } - inline void SetNoDisplay() { display = false; } - inline string get_trans_ident() { return trans_ident; } inline FGGround* GetGroundPtr() { return ground; } @@ -247,9 +244,6 @@ private: unsigned int update_count; // Convienince counter for speading computational load over several updates unsigned int update_count_max; // ditto. - bool display; // Flag to indicate whether we should be outputting to the ATC display. - bool displaying; // Flag to indicate whether we are outputting to the ATC display. - double timeSinceLastDeparture; // Time in seconds since last departure from active rwy. bool departed; // set true when the above needs incrementing with time, false when it doesn't. -- 2.39.5