Start adding a better framework for ATC-initiated communication. There should be no user-visible change from this commit
This commit is contained in:
parent
1e3a4f312b
commit
7a044b3faa
10 changed files with 144 additions and 68 deletions
|
@ -24,6 +24,7 @@
|
|||
|
||||
#include <simgear/sound/soundmgr.hxx>
|
||||
|
||||
#include <Main/globals.hxx>
|
||||
#include <Main/fg_props.hxx>
|
||||
|
||||
#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,6 +157,36 @@ void FGATC::NotifyTransmissionFinished(string rid) {
|
|||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
// Derived classes should override this.
|
||||
void FGATC::ProcessCallback(int code) {
|
||||
}
|
||||
|
||||
void FGATC::AddPlane(string pid) {
|
||||
}
|
||||
|
||||
|
@ -103,12 +194,6 @@ int FGATC::RemovePlane() {
|
|||
return 0;
|
||||
}
|
||||
|
||||
void FGATC::SetDisplay() {
|
||||
}
|
||||
|
||||
void FGATC::SetNoDisplay() {
|
||||
}
|
||||
|
||||
void FGATC::SetData(ATCData* d) {
|
||||
lon = d->lon;
|
||||
lat = d->lat;
|
||||
|
|
|
@ -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&
|
||||
|
|
|
@ -77,7 +77,6 @@ FGApproach::~FGApproach(){
|
|||
}
|
||||
|
||||
void FGApproach::Init() {
|
||||
display = false;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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; }
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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; }
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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?
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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.
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue