Changes towards ground control and AI taxiing currently very hardwired to KEMT
This commit is contained in:
parent
75e51b0d81
commit
5f543a2fd1
2 changed files with 768 additions and 101 deletions
src/ATC
|
@ -18,10 +18,355 @@
|
|||
// 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;
|
||||
|
||||
// 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() {
|
||||
|
@ -39,6 +384,126 @@ void FGGround::Update() {
|
|||
// 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
|
||||
|
@ -78,3 +543,4 @@ void FGGround::AssignGate(ground_rec &g) {
|
|||
// 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
|
|
@ -21,13 +21,27 @@
|
|||
#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
|
||||
|
@ -39,36 +53,114 @@ typedef enum arc_type {
|
|||
typedef enum node_type {
|
||||
GATE,
|
||||
APRON,
|
||||
HOLD
|
||||
HOLD,
|
||||
JUNCTION,
|
||||
TJUNCTION
|
||||
};
|
||||
|
||||
typedef struct arc {
|
||||
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 enum network_element_type {
|
||||
NODE,
|
||||
ARC
|
||||
};
|
||||
|
||||
struct ground_network_element {
|
||||
network_element_type struct_type;
|
||||
};
|
||||
|
||||
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 list<arc> arc_list_type;
|
||||
typedef arc_list_type::iterator arc_list_itr;
|
||||
typedef arc_list_type::const_iterator arc_list_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;
|
||||
|
||||
typedef struct node {
|
||||
point pos;
|
||||
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 node;
|
||||
arc_list arcs;
|
||||
node_type type;
|
||||
arc_array_type arcs;
|
||||
double max_turn_radius;
|
||||
};
|
||||
|
||||
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 <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,6 +186,65 @@ typedef ground_rec_list::const_iterator ground_rec_list_const_itr;
|
|||
///////////////////////////////////////////////////////////////////////////////
|
||||
class FGGround : public FGATC {
|
||||
|
||||
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);
|
||||
|
||||
// Contact ground control on departure, assumed to request currently active runway.
|
||||
//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);
|
||||
|
||||
// Make a request of ground control.
|
||||
//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
|
||||
|
@ -101,50 +254,98 @@ private:
|
|||
// Need a data structure to hold outstanding communications from aircraft.
|
||||
// Possibly need a data structure to hold outstanding communications to aircraft.
|
||||
|
||||
// logical network
|
||||
// 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;
|
||||
|
||||
public:
|
||||
|
||||
void Init();
|
||||
|
||||
void Update();
|
||||
|
||||
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);
|
||||
|
||||
// Contact ground control on departure, assumed to request currently active runway.
|
||||
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);
|
||||
|
||||
// Make a request of ground control.
|
||||
void Request(ground_request request);
|
||||
|
||||
private:
|
||||
//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
|
||||
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
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue