]> git.mxchange.org Git - flightgear.git/commitdiff
Changes towards ground control and AI taxiing currently very hardwired to KEMT
authordaveluff <daveluff>
Wed, 4 Dec 2002 19:36:39 +0000 (19:36 +0000)
committerdaveluff <daveluff>
Wed, 4 Dec 2002 19:36:39 +0000 (19:36 +0000)
src/ATC/ground.cxx
src/ATC/ground.hxx

index d70957e43590389e321ce1386799378e295b7f25..cb9ba7c313fcc2c409168ea7adf56d18c35315c1 100644 (file)
 // along with this program; if not, write to the Free Software
 // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
+#include <simgear/math/sg_random.h>
+#include <simgear/constants.h>
+
 #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
index 18dd100e9ab5caa7adeac219e434f3bc20367d73..1fab75c1eef317c4d640a3993e15a90c696173f0 100644 (file)
 #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 <map>
 #include <vector>
 #include <list>
-//#include <map>
+#include <simgear/math/point3d.hxx>
+#include <simgear/misc/sgstream.hxx>
+#include <simgear/math/sg_geodesy.hxx>
+
+#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> 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> node_array_type;
-typedef node_array_type::iterator node_array_itr;
-typedef node_array_type::const_iterator node_array_const_itr;
+typedef vector <arc*> 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*> 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 <PlaneRec> 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*> 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
+