From 5f543a2fd196ac2be7f54420306d885a4ed3e93e Mon Sep 17 00:00:00 2001 From: daveluff Date: Wed, 4 Dec 2002 19:36:39 +0000 Subject: [PATCH] Changes towards ground control and AI taxiing currently very hardwired to KEMT --- src/ATC/ground.cxx | 550 +++++++++++++++++++++++++++++++++++++++++---- src/ATC/ground.hxx | 299 ++++++++++++++++++++---- 2 files changed, 758 insertions(+), 91 deletions(-) diff --git a/src/ATC/ground.cxx b/src/ATC/ground.cxx index d70957e43..cb9ba7c31 100644 --- a/src/ATC/ground.cxx +++ b/src/ATC/ground.cxx @@ -18,63 +18,529 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +#include +#include + #include "ground.hxx" +FGGround::FGGround() { + display = false; +} + +FGGround::~FGGround() { +} + void FGGround::Init() { - display = false; + display = false; + + // Build hardwired (very simplified) logical network for KEMT for now + // Once it works we'll progress to reading KEMT data from file, + // and finally to reading any airport with specified taxiway data from file. + + node* np; + arc* ap; + Gate* gp; + + // For now we'll hardwire the threshold end + Point3D P010(-118.037483, 34.081358, 296 * SG_FEET_TO_METER); + double hdg = 25.32; + ortho.Init(P010, hdg); + + // HARDWIRED FOR TESTING - for now we'll only allow exit at each end of runway + + /////////////////////////////////////////////////////// + // NODES + /////////////////////////////////////////////////////// + + // node - runway01 threshold + Point3D p1(-118.0372167, 34.08178333, 0.0); + np = new node; + np->struct_type = NODE; + np->pos = p1; + np->orthoPos = ortho.ConvertToLocal(p1); + np->name = "rwy 01"; + np->nodeID = 0; + np->type = JUNCTION; + runways[1].exits.push_back(np); + runways[19].exits.push_back(np); + //np->max_turn_radius = ... + network.push_back(np); + + // node - runway19 threshold + Point3D p2(-118.0321833, 34.09066667, 0.0); + np = new node; + np->struct_type = NODE; + np->pos = p2; + np->orthoPos = ortho.ConvertToLocal(p2); + np->name = "rwy 19"; + np->nodeID = 1; + np->type = JUNCTION; + runways[1].exits.push_back(np); + runways[19].exits.push_back(np); + //np->max_turn_radius = ... + network.push_back(np); + + // node - AlphaSouth + Point3D p3(-118.0369167, 34.08166667, 0.0); + np = new node; + np->struct_type = NODE; + np->pos = p3; + np->orthoPos = ortho.ConvertToLocal(p3); + np->name = ""; + np->nodeID = 2; + np->type = HOLD; + //np->max_turn_radius = ... + network.push_back(np); + + // node - AlphaNorth + Point3D p4(-118.03185, 34.0906, 0.0); + np = new node; + np->struct_type = NODE; + np->pos = p4; + np->orthoPos = ortho.ConvertToLocal(p4); + np->name = ""; + np->nodeID = 3; + np->type = HOLD; + //np->max_turn_radius = ... + network.push_back(np); + + // node - southern turnoff to parking + Point3D p5(-118.03515, 34.0848, 0.0); + np = new node; + np->struct_type = NODE; + np->pos = p5; + np->orthoPos = ortho.ConvertToLocal(p5); + np->name = ""; + np->nodeID = 4; + np->type = TJUNCTION; + //np->max_turn_radius = ... + network.push_back(np); + + // node - northern turnoff to parking + Point3D p6(-118.0349667, 34.08511667, 0.0); + np = new node; + np->struct_type = NODE; + np->pos = p6; + np->orthoPos = ortho.ConvertToLocal(p6); + np->name = ""; + np->nodeID = 5; + np->type = TJUNCTION; + //np->max_turn_radius = ... + network.push_back(np); + + // GATES + + // node - Turn into gate 1 (Western-most gate, ie. nearest rwy) + Point3D p7(-118.0348333, 34.08466667, 0.0); + np = new node; + np->struct_type = NODE; + np->pos = p7; + np->orthoPos = ortho.ConvertToLocal(p7); + np->name = ""; + np->nodeID = 6; + np->type = TJUNCTION; + //np->max_turn_radius = ... + network.push_back(np); + + // node - Gate 1 + Point3D p8(-118.0347333, 34.08483333, 0.0); + gp = new Gate; + gp->struct_type = NODE; + gp->pos = p8; + gp->orthoPos = ortho.ConvertToLocal(p8); + gp->name = ""; + gp->nodeID = 7; + gp->type = GATE; + gp->heading = 10; + //np->max_turn_radius = ... + network.push_back(gp); + gates[1] = *gp; + + // node - Turn out of gate 1 + Point3D p9(-118.03465, 34.08498333, 0.0); + np = new node; + np->struct_type = NODE; + np->pos = p9; + np->orthoPos = ortho.ConvertToLocal(p9); + np->name = ""; + np->nodeID = 8; + np->type = TJUNCTION; + //np->max_turn_radius = ... + network.push_back(np); + + // node - Turn into gate 2 + Point3D p10(-118.0346, 34.08456667, 0.0); + np = new node; + np->struct_type = NODE; + np->pos = p10; + np->orthoPos = ortho.ConvertToLocal(p10); + np->name = ""; + np->nodeID = 9; + np->type = TJUNCTION; + //np->max_turn_radius = ... + network.push_back(np); + gates[2] = *gp; + + // node - Gate 2 + Point3D p11(-118.0345167, 34.08473333, 0.0); + gp = new Gate; + gp->struct_type = NODE; + gp->pos = p11; + gp->orthoPos = ortho.ConvertToLocal(p11); + gp->name = ""; + gp->nodeID = 10; + gp->type = GATE; + gp->heading = 10; + //np->max_turn_radius = ... + network.push_back(gp); + + // node - Turn out of gate 2 + Point3D p12(-118.0344167, 34.0849, 0.0); + np = new node; + np->struct_type = NODE; + np->pos = p12; + np->orthoPos = ortho.ConvertToLocal(p12); + np->name = ""; + np->nodeID = 11; + np->type = TJUNCTION; + //np->max_turn_radius = ... + network.push_back(np); + + ///////////////////////////////////////////////////////// + // ARCS + ///////////////////////////////////////////////////////// + + // Each arc connects two nodes + // Eventually the nodeID of the nodes that the arc connects will be read from file + // For now we just 'know' them !! + + // arc - the runway - connects nodes 0 and 1 + ap = new arc; + ap->struct_type = ARC; + ap->name = ""; + ap->type = RUNWAY; + ap->directed = false; + ap->n1 = 0; + ap->n2 = 1; + network[0]->arcs.push_back(ap); + network[1]->arcs.push_back(ap); + + // arc - the exit from 01 threshold to alpha - connects nodes 0 and 2 + ap = new arc; + ap->struct_type = ARC; + ap->name = ""; + ap->type = TAXIWAY; + ap->directed = false; + ap->n1 = 0; + ap->n2 = 2; + network[0]->arcs.push_back(ap); + network[2]->arcs.push_back(ap); + + // arc - the exit from 19 threshold to alpha - connects nodes 1 and 3 + ap = new arc; + ap->struct_type = ARC; + ap->name = ""; + ap->type = TAXIWAY; + ap->directed = false; + ap->n1 = 1; + ap->n2 = 3; + network[1]->arcs.push_back(ap); + network[3]->arcs.push_back(ap); + + // arc - Alpha south - connects nodes 2 and 4 + ap = new arc; + ap->struct_type = ARC; + ap->name = ""; + ap->type = TAXIWAY; + ap->directed = false; + ap->n1 = 2; + ap->n2 = 4; + network[2]->arcs.push_back(ap); + network[4]->arcs.push_back(ap); + + // arc - Alpha middle - connects nodes 4 and 5 + ap = new arc; + ap->struct_type = ARC; + ap->name = ""; + ap->type = TAXIWAY; + ap->directed = false; + ap->n1 = 4; + ap->n2 = 5; + network[4]->arcs.push_back(ap); + network[5]->arcs.push_back(ap); + + // arc - Alpha North - connects nodes 3 and 5 + ap = new arc; + ap->struct_type = ARC; + ap->name = ""; + ap->type = TAXIWAY; + ap->directed = false; + ap->n1 = 3; + ap->n2 = 5; + network[3]->arcs.push_back(ap); + network[5]->arcs.push_back(ap); + + // arc - connects nodes 4 and 6 + ap = new arc; + ap->struct_type = ARC; + ap->name = ""; + ap->type = TAXIWAY; + ap->directed = true; + ap->n1 = 4; + ap->n2 = 6; + network[4]->arcs.push_back(ap); + network[6]->arcs.push_back(ap); + + // arc - connects nodes 6 and 9 + ap = new arc; + ap->struct_type = ARC; + ap->name = ""; + ap->type = TAXIWAY; + ap->directed = true; + ap->n1 = 6; + ap->n2 = 9; + network[6]->arcs.push_back(ap); + network[9]->arcs.push_back(ap); + + // arc - connects nodes 5 and 8 + ap = new arc; + ap->struct_type = ARC; + ap->name = ""; + ap->type = TAXIWAY; + ap->directed = true; + ap->n1 = 5; + ap->n2 = 8; + network[5]->arcs.push_back(ap); + network[8]->arcs.push_back(ap); + + // arc - connects nodes 8 and 11 + ap = new arc; + ap->struct_type = ARC; + ap->name = ""; + ap->type = TAXIWAY; + ap->directed = true; + ap->n1 = 8; + ap->n2 = 11; + network[8]->arcs.push_back(ap); + network[11]->arcs.push_back(ap); + + // arc - connects nodes 6 and 7 + ap = new arc; + ap->struct_type = ARC; + ap->name = ""; + ap->type = TAXIWAY; + ap->directed = true; + ap->n1 = 6; + ap->n2 = 7; + network[6]->arcs.push_back(ap); + network[7]->arcs.push_back(ap); + + // arc - connects nodes 7 and 8 + ap = new arc; + ap->struct_type = ARC; + ap->name = ""; + ap->type = TAXIWAY; + ap->directed = true; + ap->n1 = 7; + ap->n2 = 8; + network[7]->arcs.push_back(ap); + network[8]->arcs.push_back(ap); + + // arc - connects nodes 9 and 10 + ap = new arc; + ap->struct_type = ARC; + ap->name = ""; + ap->type = TAXIWAY; + ap->directed = true; + ap->n1 = 9; + ap->n2 = 10; + network[9]->arcs.push_back(ap); + network[10]->arcs.push_back(ap); + + // arc - connects nodes 10 and 11 + ap = new arc; + ap->struct_type = ARC; + ap->name = ""; + ap->type = TAXIWAY; + ap->directed = true; + ap->n1 = 10; + ap->n2 = 11; + network[10]->arcs.push_back(ap); + network[11]->arcs.push_back(ap); } void FGGround::Update() { - // Each time step, what do we need to do? - // We need to go through the list of outstanding requests and acknowedgements - // and process at least one of them. - // We need to go through the list of planes under our control and check if - // any need to be addressed. - // We need to check for planes not under our control coming within our - // control area and address if necessary. - - // Lets take the example of a plane which has just contacted ground - // following landing - presumably requesting where to go? - // First we need to establish the position of the plane within the logical network. - // Next we need to decide where its going. + // Each time step, what do we need to do? + // We need to go through the list of outstanding requests and acknowedgements + // and process at least one of them. + // We need to go through the list of planes under our control and check if + // any need to be addressed. + // We need to check for planes not under our control coming within our + // control area and address if necessary. + + // Lets take the example of a plane which has just contacted ground + // following landing - presumably requesting where to go? + // First we need to establish the position of the plane within the logical network. + // Next we need to decide where its going. +} + +// FIXME - at the moment this assumes there is at least one gate and crashes if none +// FIXME - In fact, at the moment this routine doesn't work at all and hence is munged to always return Gate 1 !!!! +int FGGround::GetRandomGateID() { + //cout << "GetRandomGateID called" << endl; + return(1); + + gate_vec_type gateVec; + //gate_vec_iterator gateVecItr; + int num = 0; + int thenum; + int ID; + + gatesItr = gates.begin(); + while(gatesItr != gates.end()) { + if(gatesItr->second.used == false) { + gateVec.push_back(gatesItr->second); + num++; + } + ++gatesItr; + } + + // Randomly select one from the list + thenum = (int)(sg_random() * gateVec.size()); + ID = gateVec[thenum].id; + //cout << "Returning gate ID " << ID << " from GetRandomGateID" << endl; + return(ID); +} + +// Return a pointer to a gate node based on the gate ID +Gate* FGGround::GetGateNode(int gateID) { + //TODO - ought to add some sanity checking here - ie does a gate of this ID exist?! + return(&(gates[gateID])); } +// Get a path from a point on a runway to a gate + +// Get a path from a node to another node +// Eventually we will need complex algorithms for this taking other traffic, +// shortest path and suitable paths into accout. For now we're going to hardwire for KEMT!!!! +ground_network_path_type FGGround::GetPath(node* A, node* B) { + ground_network_path_type path; + //arc_array_iterator arcItr; + //bool found; + + // VERY HARDWIRED - this hardwires a path from the far end of R01 to Gate 1. + // In fact in real life the area between R01/19 and Taxiway Alpha at KEMT is tarmaced and planes + // are supposed to exit the rwy asap. + // OK - for now very hardwire this for testing + path.push_back(network[1]); + path.push_back(network[1]->arcs[1]); // ONLY BECAUSE WE KNOW THIS IS THE ONE !!!!! + path.push_back(network[3]); + path.push_back(network[3]->arcs[1]); + path.push_back(network[5]); + path.push_back(network[5]->arcs[0]); + path.push_back(network[4]); + path.push_back(network[4]->arcs[2]); + path.push_back(network[6]); + path.push_back(network[6]->arcs[2]); + path.push_back(network[7]); // THE GATE!! Note that for now we're not even looking at the requested exit and gate passed in !!!!! + +#if 0 + // In this hardwired scheme there are two possibilities - taxiing from rwy to gate or gate to rwy. + if(B->type == GATE) { + //return an inward path + path.push_back(A); + // In this hardwired scheme we know A is a rwy exit and should have one taxiway arc only + // THIS WILL NOT HOLD TRUE IN THE GENERAL CASE + arcItr = A->arcs.begin(); + found = false; + while(arcItr != A->arcs.end()) { + if(arcItr->type == TAXIWAY) { + path.push_back(&(*arcItr)); + found = true; + break; + } + } + if(found == false) { + //cout << "AI/ATC SUBSYSTEM ERROR - no taxiway from runway exit in airport.cxx" << endl; + } + // Then push back the start of taxiway node + // Then push back the taxiway arc + arcItr = A->arcs.begin(); + found = false; + while(arcItr != A->arcs.end()) { + if(arcItr->type == TAXIWAY) { // FIXME - OOPS - two taxiways go off this node + // How are we going to differentiate, apart from one called Alpha. + // I suppose eventually the traversal algorithms will select. + path.push_back(&(*arcItr)); + found = true; + break; + } + } + if(found == false) { + //cout << "AI/ATC SUBSYSTEM ERROR - no taxiway from runway exit in airport.cxx" << endl; + } + // Then push back the junction node + // Planes always face one way in the parking, so depending on which parking exit we have either take it or push back another taxiway node + // Repeat if necessary + // Then push back the gate B + path.push_back(B); + } else { + //return an outward path + } + + // WARNING TODO FIXME - this is VERY FRAGILE - eg taxi to apron!!! but should be enough to + // see an AI plane physically taxi. +#endif // 0 + + return(path); +}; + + +// Randomly or otherwise populate some of the gates with parked planes +// (might eventually be done by the AIMgr if and when lots of AI traffic is generated) + +// Return a list of exits from a given runway +node_array_type FGGround::GetExits(int rwyID) { + return(runways[rwyID].exits); +} +#if 0 void FGGround::NewArrival(plane_rec plane) { - // What are we going to do here? - // We need to start a new ground_rec and add the plane_rec to it - // We need to decide what gate we are going to clear it to. - // Then we need to add clearing it to that gate to the pending transmissions queue? - or simply transmit? - // Probably simply transmit for now and think about a transmission queue later if we need one. - // We might need one though in order to add a little delay for response time. - ground_rec* g = new ground_rec; - g->plane_rec = plane; - g->current_pos = ConvertWGS84ToXY(plane.pos); - g->node = GetNode(g->current_pos); // TODO - might need to sort out node/arc here - AssignGate(g); - g->cleared = false; - ground_traffic.push_back(g); - NextClearance(g); + // What are we going to do here? + // We need to start a new ground_rec and add the plane_rec to it + // We need to decide what gate we are going to clear it to. + // Then we need to add clearing it to that gate to the pending transmissions queue? - or simply transmit? + // Probably simply transmit for now and think about a transmission queue later if we need one. + // We might need one though in order to add a little delay for response time. + ground_rec* g = new ground_rec; + g->plane_rec = plane; + g->current_pos = ConvertWGS84ToXY(plane.pos); + g->node = GetNode(g->current_pos); // TODO - might need to sort out node/arc here + AssignGate(g); + g->cleared = false; + ground_traffic.push_back(g); + NextClearance(g); } void FGGround::NewContact(plane_rec plane) { - // This is a bit of a convienience function at the moment and is likely to change. - if(at a gate or apron) - NewDeparture(plane); - else - NewArrival(plane); + // This is a bit of a convienience function at the moment and is likely to change. + if(at a gate or apron) + NewDeparture(plane); + else + NewArrival(plane); } void FGGround::NextClearance(ground_rec &g) { - // Need to work out where we can clear g to. - // Assume the pilot doesn't need progressive instructions - // We *should* already have a gate or holding point assigned by the time we get here - // but it wouldn't do any harm to check. - - // For now though we will hardwire it to clear to the final destination. + // Need to work out where we can clear g to. + // Assume the pilot doesn't need progressive instructions + // We *should* already have a gate or holding point assigned by the time we get here + // but it wouldn't do any harm to check. + + // For now though we will hardwire it to clear to the final destination. } void FGGround::AssignGate(ground_rec &g) { - // We'll cheat for now - since we only have the user's aircraft and a couple of airports implemented - // we'll hardwire the gate! - // In the long run the logic of which gate or area to send the plane to could be somewhat non-trivial. -} \ No newline at end of file + // We'll cheat for now - since we only have the user's aircraft and a couple of airports implemented + // we'll hardwire the gate! + // In the long run the logic of which gate or area to send the plane to could be somewhat non-trivial. +} +#endif //0 \ No newline at end of file diff --git a/src/ATC/ground.hxx b/src/ATC/ground.hxx index 18dd100e9..1fab75c1e 100644 --- a/src/ATC/ground.hxx +++ b/src/ATC/ground.hxx @@ -21,54 +21,146 @@ #ifndef _FG_GROUND_HXX #define _FG_GROUND_HXX +#include STL_IOSTREAM +#include STL_STRING + +SG_USING_STD(string); +#ifndef SG_HAVE_NATIVE_SGI_COMPILERS +SG_USING_STD(ios); +#endif + +#include #include #include -//#include +#include +#include +#include + +#include "ATC.hxx" +#include "ATCProjection.hxx" +SG_USING_STD(map); SG_USING_STD(vector); SG_USING_STD(list); -//SG_USING_STD(map); ////////////////////////////////////////////////////// // Types for the logical network data structure typedef enum arc_type { - RUNWAY, - TAXIWAY + RUNWAY, + TAXIWAY }; typedef enum node_type { - GATE, - APRON, - HOLD + GATE, + APRON, + HOLD, + JUNCTION, + TJUNCTION }; -typedef struct arc { - int distance; - char* name; - arc_type type; +enum GateType { + TRANSPORT_PASSENGER, + TRANSPORT_PASSENGER_NARROWBODY, + TRANSPORT_PASSENGER_WIDEBODY, + TRANSPORT_CARGO, + GA_LOCAL, + GA_LOCAL_SINGLE, + GA_LOCAL_TWIN, + GA_TRANSIENT, + GA_TRANSIENT_SINGLE, + GA_TRANSIENT_TWIN, + OTHER // ie. anything goes!! }; -typedef list arc_list_type; -typedef arc_list_type::iterator arc_list_itr; -typedef arc_list_type::const_iterator arc_list_const_itr; +typedef enum network_element_type { + NODE, + ARC +}; + +struct ground_network_element { + network_element_type struct_type; +}; -typedef struct node { - point pos; - char* name; - node_type node; - arc_list arcs; +struct arc : public ground_network_element { + int distance; + char* name; + arc_type type; + bool directed; //false if 2-way, true if 1-way. + //This is a can of worms since arcs might be one way in different directions under different circumstances + unsigned int n1; // The nodeID of the first node + unsigned int n2; // The nodeID of the second node + // If the arc is directed then flow is normally from n1 to n2. See the above can of worms comment though. }; -typedef vector node_array_type; -typedef node_array_type::iterator node_array_itr; -typedef node_array_type::const_iterator node_array_const_itr; +typedef vector arc_array_type; // This was and may become again a list instead of vector +typedef arc_array_type::iterator arc_array_iterator; +typedef arc_array_type::const_iterator arc_array_const_iterator; + +struct node : public ground_network_element { + unsigned int nodeID; //each node in an airport needs a unique ID number - this is ZERO-BASED to match array position + Point3D pos; + Point3D orthoPos; + char* name; + node_type type; + arc_array_type arcs; + double max_turn_radius; +}; + +typedef vector node_array_type; +typedef node_array_type::iterator node_array_iterator; +typedef node_array_type::const_iterator node_array_const_iterator; + +struct Gate : public node { + GateType gateType; + int max_weight; //units?? + //airline_code airline; //For the future - we don't have any airline codes ATM + int id; // The gate number in the logical scheme of things + string sid; // The real-world gate letter/number + //node* pNode; + bool used; + double heading; // The direction the parked-up plane should point in degrees +}; + +typedef vector < Gate > gate_vec_type; +typedef gate_vec_type::iterator gate_vec_iterator; +typedef gate_vec_type::const_iterator gate_vec_const_iterator; + +// A map of gate vs. the logical (internal FGFS) gate ID +typedef map < int, Gate > gate_map_type; +typedef gate_map_type::iterator gate_map_iterator; +typedef gate_map_type::const_iterator gate_map_const_iterator; + +// Runways - all the runway stuff is likely to change in the future +typedef struct Rwy { + int id; //note this is a very simplified scheme for now - R & L are not differentiated + //It should work for simple one rwy airports + node_array_type exits; //Array of available exits from runway + // should probably add an FGRunway structure here as well eventually + // Eventually we will also want some encoding of real-life preferred runways + // This will get us up and running for single runway airports though. +}; +typedef vector < Rwy > runway_array_type; +typedef runway_array_type::iterator runway_array_iterator; +typedef runway_array_type::const_iterator runway_array_const_iterator; + // end logical network types /////////////////////////////////////////////////////// +/////////////////////////////////////////////////////// +// Structures to use the network + +// A path through the network +typedef vector < ground_network_element* > ground_network_path_type; +typedef ground_network_path_type::iterator ground_network_path_iterator; +typedef ground_network_path_type::const_iterator ground_network_path_const_iterator; + +////////////////////////////////////////////////////////////////////////////////////////// + +// Planes active within the ground network. // somewhere in the ATC/AI system we are going to have defined something like // typedef struct plane_rec // list plane_rec_list_type - +/* // A more specialist plane rec to include ground information typedef struct ground_rec { plane_rec plane; @@ -84,6 +176,8 @@ typedef struct ground_rec { typedef list ground_rec_list; typedef ground_rec_list::iterator ground_rec_list_itr; typedef ground_rec_list::const_iterator ground_rec_list_const_itr; +*/ +////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// // @@ -92,26 +186,26 @@ typedef ground_rec_list::const_iterator ground_rec_list_const_itr; /////////////////////////////////////////////////////////////////////////////// class FGGround : public FGATC { -private: - - // Need a data structure to hold details of the various active planes - // Need a data structure to hold details of the logical network - // including which gates are filled - or possibly another data structure - // with the positions of the inactive planes. - // Need a data structure to hold outstanding communications from aircraft. - // Possibly need a data structure to hold outstanding communications to aircraft. - - // logical network - node_array_type network; - - // Planes currently active - ground_rec_list ground_traffic; - public: - + FGGround(); + ~FGGround(); void Init(); void Update(); + + inline char get_type() const { return type; } + inline double get_lon() const { return lon; } + inline double get_lat() const { return lat; } + inline double get_elev() const { return elev; } + inline double get_x() const { return x; } + inline double get_y() const { return y; } + inline double get_z() const { return z; } + inline int get_freq() const { return freq; } + inline int get_range() const { return range; } + inline const char* GetIdent() { return ident.c_str(); } + inline string get_trans_ident() { return trans_ident; } + inline string get_name() { return name; } + inline atc_type GetType() { return GROUND; } inline void SetDisplay() {display = true;} inline void SetNoDisplay() {display = false;} @@ -119,32 +213,139 @@ public: // Its possible that NewArrival and NewDeparture should simply be rolled into Request. // Contact ground control on arrival, assumed to request any gate - void NewArrival(plane_rec plane); + //void NewArrival(plane_rec plane); // Contact ground control on departure, assumed to request currently active runway. - void NewDeparture(plane_rec plane); + //void NewDeparture(plane_rec plane); // Contact ground control when the calling routine doesn't know if arrival // or departure is appropriate. - void NewContact(plane_rec plane); + //void NewContact(plane_rec plane); // Make a request of ground control. - void Request(ground_request request); + //void Request(ground_request request); + + // Randomly fill some of the available gates and GA parking spots with planes + void PopulateGates(); + + // Return a suitable gate (maybe this should be a list of suitable gates so the plane or controller can choose the closest one) + void ReturnGate(Gate &gate, GateType type); + + //The following two functions have been made public for now but may go private with a higher level accessor at some point + // Return the internal ID of a random, suitable, unused gate + // For now we are simply implementing as any random unused gate + int GetRandomGateID(); + // Return a pointer to a node based on the gate ID + Gate* GetGateNode(int gateID); + + // Runway stuff - this might change in the future. + // Get a list of exits from a given runway + node_array_type GetExits(int rwyID); + + // Get a path from one node to another + ground_network_path_type GetPath(node* A, node* B); private: + // Need a data structure to hold details of the various active planes + // Need a data structure to hold details of the logical network + // including which gates are filled - or possibly another data structure + // with the positions of the inactive planes. + // Need a data structure to hold outstanding communications from aircraft. + // Possibly need a data structure to hold outstanding communications to aircraft. + + // The logical network + // NODES WILL BE STORED IN THE NETWORK IN ORDER OF nodeID NUMBER + // ie. NODE 5 WILL BE AT network[5] + node_array_type network; + + // A map of all the gates indexed against internal (FGFS) ID + gate_map_type gates; + gate_map_iterator gatesItr; + + // Runway stuff - this might change in the future. + //runway_array_type runways; // STL way + Rwy runways[36]; // quick hack! + + FGATCAlignedProjection ortho; + + // Planes currently active + //ground_rec_list ground_traffic; + // Find the shortest route through the logical network between two points. - FindShortestRoute(point a, point b); + //FindShortestRoute(point a, point b); // Project a point in WGS84 lat/lon onto the local gnomonic. - ConvertWGS84ToXY(sgVec3 wgs84, point xy); + //ConvertWGS84ToXY(sgVec3 wgs84, point xy); // Assign a gate or parking location to a new arrival - AssignGate(ground_rec &g); + //AssignGate(ground_rec &g); // Generate the next clearance for an airplane - NextClearance(ground_rec &g); - + //NextClearance(ground_rec &g); + + char type; + double lon, lat; + double elev; + double x, y, z; + int freq; + int range; + 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 ident; // Code of the airport its at. + string name; // Name generally used in transmissions. + // for failure modeling + string trans_ident; // transmitted ident + bool ground_failed; // ground failed? + + friend istream& operator>> ( istream&, FGGround& ); }; -#endif //_FG_GROUND_HXX \ No newline at end of file +inline istream& +operator >> ( istream& in, FGGround& g ) +{ + double f; + char ch; + + in >> g.type; + + if ( g.type == '[' ) + return in >> skipeol; + + in >> g.lat >> g.lon >> g.elev >> f >> g.range + >> g.ident; + + g.name = ""; + in >> ch; + g.name += ch; + while(1) { + //in >> noskipws + in.unsetf(ios::skipws); + in >> ch; + g.name += ch; + if((ch == '"') || (ch == 0x0A)) { + break; + } // we shouldn't need the 0x0A but it makes a nice safely in case someone leaves off the " + } + in.setf(ios::skipws); + //cout << "tower.name = " << t.name << '\n'; + + g.freq = (int)(f*100.0 + 0.5); + + // cout << g.ident << endl; + + // generate cartesian coordinates + Point3D geod( g.lon * SGD_DEGREES_TO_RADIANS, g.lat * SGD_DEGREES_TO_RADIANS, g.elev ); + Point3D cart = sgGeodToCart( geod ); + g.x = cart.x(); + g.y = cart.y(); + g.z = cart.z(); + + g.trans_ident = g.ident; + g.ground_failed = false; + + return in >> skipeol; +} + +#endif // _FG_GROUND_HXX + -- 2.39.5