// 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
#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;
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;
+*/
+//////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
//
///////////////////////////////////////////////////////////////////////////////
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;}
// 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
+