return(false);
}
freq = (double)tower->get_freq() / 100.0;
- } else {
- // Check CTAF, unicom etc
- }
- if(a.ground_freq) { // Ground control
- ground = (FGGround*)ATC->GetATCPointer((string)airportID, GROUND); // Maybe need some error checking here
+ ground = tower->GetGroundPtr();
if(ground == NULL) {
// Something has gone wrong :-(
- cout << "ERROR - ground has frequency but can't get ground pointer :-(\n";
+ cout << "ERROR - can't get a ground pointer from tower control in FGAILocalTraffic::Init() :-(\n";
return(false);
}
- freq = (double)tower->get_freq() / 100.0;
} else {
- // Initialise ground anyway to do the shortest path stuff!
- // This is a bit of a hack - might need to be altered sometime, but
- // in theory AILocalTraffic doesn't get called unless we have a logical
- // network for ground to use so it should work for now!
- ground = new FGGround(airportID); // TODO - ought to set a flag saying that we're responsible
- // for deleting ground in this instance, since normally we're not.
- ground->Init();
+ // Check CTAF, unicom etc
}
} else {
//cout << "Unable to find airport details in FGAILocalTraffic::Init()\n";
// WARNING - we use this elev for the whole airport - some assumptions in the code
// might fall down with very slopey airports.
- //cout << "In Init(), initialState = " << initialState << '\n';
+ //cout << "In Init(), initialState = " << initialState << endl;
operatingState = initialState;
switch(operatingState) {
case PARKED:
// FGTower
FGTower::FGTower() {
+ ATCmgr = globals->get_ATC_mgr();
}
FGTower::~FGTower() {
+ if(!separateGround) {
+ delete ground;
+ }
}
void FGTower::Init() {
display = false;
+
+ // Need some way to initialise rwyOccupied flag correctly if the user is on the runway and to know its the user.
+ // I'll punt the startup issue for now though!!!
+ rwyOccupied = false;
+
+ // Setup the ground control at this airport
+ AirportATC a;
+ if(ATCmgr->GetAirportATCDetails(ident, &a)) {
+ if(a.ground_freq) { // Ground control
+ ground = (FGGround*)ATCmgr->GetATCPointer(ident, GROUND);
+ separateGround = true;
+ if(ground == NULL) {
+ // Something has gone wrong :-(
+ cout << "ERROR - ground has frequency but can't get ground pointer :-(\n";
+ ground = new FGGround(ident);
+ separateGround = false;
+ ground->Init();
+ if(display) {
+ ground->SetDisplay();
+ } else {
+ ground->SetNoDisplay();
+ }
+ }
+ } else {
+ // Initialise ground anyway to do the shortest path stuff!
+ // Note that we're now responsible for updating and deleting this - NOT the ATCMgr.
+ ground = new FGGround(ident);
+ separateGround = false;
+ ground->Init();
+ if(display) {
+ ground->SetDisplay();
+ } else {
+ ground->SetNoDisplay();
+ }
+ }
+ } else {
+ //cout << "Unable to find airport details in FGTower::Init()\n";
+ }
}
void FGTower::Update() {
// We need to check for planes not under our control coming within our
// control area and address if necessary.
- // Hardwired for testing
- static int play = 0;
- if(play == 200) {
- //cout << "Registering message in tower.cxx ****************************\n";
- //globals->get_ATC_display()->RegisterSingleMessage((string)"Cessna eight-two-zero Cleared for takeoff", 2);
- }
- ++play;
+ // TODO - a lot of the below probably doesn't need to be called every frame and should be staggered.
+
+ // Sort the arriving planes
+
+ // Calculate the eta of each plane to the threshold.
+ // For ground traffic this is the fastest they can get there.
+ // For air traffic this is the middle approximation.
+ doThresholdETACalc();
+
+ // Order the list of traffic as per expected threshold use and flag any conflicts
+ bool conflicts = doThresholdUseOrder();
+
+ // sortConficts() !!!
+
+ doCommunication();
+
+ if(!separateGround) {
+ // 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) {
+ ground->SetDisplay();
+ } else {
+ ground->SetNoDisplay();
+ }
+ ground->Update();
+ }
+}
+
+// Calculate the eta of each plane to the threshold.
+// For ground traffic this is the fastest they can get there.
+// For air traffic this is the middle approximation.
+void FGTower::doThresholdETACalc() {
+ // For now we'll be very crude and hardwire expected speeds to C172-like values
+ double app_ias = 100.0; // Speed during straight-in approach
+ double circuit_ias = 80.0; // Speed around circuit
+ double final_ias = 70.0; // Speed during final approach
+
+ tower_plane_rec_list_iterator twrItr;
+
+ for(twrItr = trafficList.begin(); twrItr != trafficList.end(); twrItr++) {
+ }
+
+}
+
+bool FGTower::doThresholdUseOrder() {
+ return(true);
+}
+
+void FGTower::doCommunication() {
}
+
void FGTower::RequestLandingClearance(string ID) {
cout << "Request Landing Clearance called...\n";
//DCL - a complete guess for now.
#define FG_TOWER_DEFAULT_RANGE 30
+enum tower_traffic_type {
+ CIRCUIT,
+ INBOUND,
+ OUTBOUND,
+ STRAIGHT_IN
+ // Umm - what's the difference between INBOUND and STRAIGHT_IN ?
+};
+
// Structure for holding details of a plane under tower control.
// Not fixed yet - may include more stuff later.
class TowerPlaneRec {
bool finalAcknowledged;
bool onRwy;
// enum type - light, medium, heavy etc - we need someway of approximating the aircraft type and performance.
+
+ // Type of operation the plane is doing
+ tower_traffic_type opType;
};
+
typedef list < TowerPlaneRec* > tower_plane_rec_list_type;
typedef tower_plane_rec_list_type::iterator tower_plane_rec_list_iterator;
typedef tower_plane_rec_list_type::const_iterator tower_plane_rec_list_const_iterator;
class FGTower : public FGATC {
- public:
+public:
FGTower();
~FGTower();
void ReportGoingAround(string ID);
void ReportRunwayVacated(string ID);
- // Parse a literal message to decide which of above it represents.
- // (a long term project that eventually will hopefully receive the output from voice recognition software.)
- void LiteralTransmission(string trns, string ID);
-
inline void SetDisplay() {display = true;}
inline void SetNoDisplay() {display = false;}
inline string get_trans_ident() { return trans_ident; }
inline atc_type GetType() { return TOWER; }
- // Make a request of tower control
- //void Request(tower_request request);
+ inline FGGround* GetGroundPtr() {return ground; }
+
+private:
+ FGATCMgr* ATCmgr;
+ // This is purely for synactic convienience to avoid writing globals->get_ATC_mgr()-> all through the code!
+
+ // Calculate the eta of each plane to the threshold.
+ // For ground traffic this is the fastest they can get there.
+ // For air traffic this is the middle approximation.
+ void doThresholdETACalc();
+
+ // Order the list of traffic as per expected threshold use and flag any conflicts
+ bool doThresholdUseOrder();
- private:
+ void doCommunication();
void IssueLandingClearance(TowerPlaneRec* tpr);
void IssueGoAround(TowerPlaneRec* tpr);
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.
+ bool rwyOccupied; // Active runway occupied flag. For now we'll disregard multiple runway and land-and-hold-short operations
+
// Need a data structure to hold details of the various active planes
// or possibly another data structure with the positions of the inactive planes.
// Need a data structure to hold outstanding communications from aircraft.
-
+/*
// Linked-list of planes on approach ordered with nearest first (timewise).
// Includes planes that have landed but not yet vacated runway.
// Somewhat analagous to the paper strips used (used to be used?) in real life.
// List of planes on rwy
tower_plane_rec_list_type rwyList;
+*/
+
+ // Linked list of all planes due to use a given rwy arranged in projected order of rwy use
+ tower_plane_rec_list_type trafficList; // TODO - needs to be expandable to more than one rwy
// Ground can be separate or handled by tower in real life.
// In the program we will always use a separate FGGround class, but we need to know
// whether it is supposed to be separate or not to give the correct instructions.
bool separateGround; // true if ground control is separate
- FGGround* groundPtr; // The ground control associated with this airport.
+ FGGround* ground; // The ground control associated with this airport.
// for failure modeling