diff --git a/src/ATC/AILocalTraffic.cxx b/src/ATC/AILocalTraffic.cxx index 8404f3237..fe52749c9 100644 --- a/src/ATC/AILocalTraffic.cxx +++ b/src/ATC/AILocalTraffic.cxx @@ -169,25 +169,14 @@ bool FGAILocalTraffic::Init(string ICAO, OperatingState initialState, PatternLeg 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"; @@ -199,7 +188,7 @@ bool FGAILocalTraffic::Init(string ICAO, OperatingState initialState, PatternLeg // 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: diff --git a/src/ATC/tower.cxx b/src/ATC/tower.cxx index 5f6920f70..ee7828614 100644 --- a/src/ATC/tower.cxx +++ b/src/ATC/tower.cxx @@ -76,13 +76,55 @@ finalAcknowledged(false) // 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() { @@ -94,15 +136,59 @@ 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"; } diff --git a/src/ATC/tower.hxx b/src/ATC/tower.hxx index cd4b1e46a..430604e8f 100644 --- a/src/ATC/tower.hxx +++ b/src/ATC/tower.hxx @@ -40,6 +40,14 @@ SG_USING_STD(ios); //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 { @@ -64,8 +72,12 @@ 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; @@ -73,7 +85,7 @@ typedef tower_plane_rec_list_type::const_iterator tower_plane_rec_list_const_ite class FGTower : public FGATC { - public: +public: FGTower(); ~FGTower(); @@ -92,20 +104,27 @@ class FGTower : public FGATC { 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! - private: + // 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(); + + void doCommunication(); void IssueLandingClearance(TowerPlaneRec* tpr); void IssueGoAround(TowerPlaneRec* tpr); @@ -114,10 +133,12 @@ class FGTower : public FGATC { 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. @@ -131,12 +152,16 @@ class FGTower : public FGATC { // 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