Major update of traffic manager and AI related airport facilities.
- Moved AIModels/Traffic Manager related AI functions to a new file - Rewrote the traffic manager so that the containers use pointers to objects instead of the objects themselves, which will allow for a more flexible memory management. - Rewrote parts of the airport groundnetwork code, also because the stl containers now contain object pointers instead of the objects themselves. - Fixed an uninitialized iterator in the AI distance tracking code - Fixed flawed logic in some of the traffic controller's while loops - Added a tower controller, which paces take-off behavior of AITraffic in a more realistic way. - Various other minor fixes and fine tuning.
This commit is contained in:
parent
8be61d7813
commit
666910a793
18 changed files with 631 additions and 681 deletions
|
@ -43,6 +43,7 @@
|
|||
SG_USING_STD(string);
|
||||
|
||||
#include "AIAircraft.hxx"
|
||||
//#include <Airports/trafficcontroller.hxx>
|
||||
static string tempReg;
|
||||
//
|
||||
// accel, decel, climb_rate, descent_rate, takeoff_speed, climb_speed,
|
||||
|
@ -93,6 +94,8 @@ FGAIAircraft::FGAIAircraft(FGAISchedule *ref) :
|
|||
|
||||
FGAIAircraft::~FGAIAircraft() {
|
||||
//delete fp;
|
||||
if (controller)
|
||||
controller->signOff(getID());
|
||||
}
|
||||
|
||||
|
||||
|
@ -180,15 +183,29 @@ void FGAIAircraft::Run(double dt) {
|
|||
if (now < fp->getStartTime()) {
|
||||
// Do execute Ground elev for inactive aircraft, so they
|
||||
// Are repositioned to the correct ground altitude when the user flies within visibility range.
|
||||
// In addition, check whether we are out of user range, so this aircraft
|
||||
// can be deleted.
|
||||
if (no_roll) {
|
||||
Transform(); // make sure aip is initialized.
|
||||
getGroundElev(dt); // make sure it's exectuted first time around, so force a large dt value
|
||||
//getGroundElev(dt); // Need to do this twice.
|
||||
//cerr << trafficRef->getRegistration() << " Setting altitude to " << tgt_altitude;
|
||||
doGroundAltitude();
|
||||
//cerr << " Actual altitude " << altitude << endl;
|
||||
// Transform();
|
||||
pos.setElevationFt(altitude_ft);
|
||||
if (trafficRef) {
|
||||
double userLatitude = fgGetDouble("/position/latitude-deg");
|
||||
double userLongitude = fgGetDouble("/position/longitude-deg");
|
||||
double course, distance;
|
||||
SGWayPoint current(pos.getLongitudeDeg(), pos.getLatitudeDeg(), 0);
|
||||
SGWayPoint user (userLongitude, userLatitude, 0);
|
||||
user.CourseAndDistance(current, &course, &distance);
|
||||
if ((distance * SG_METER_TO_NM) > TRAFFICTOAIDIST) {
|
||||
setDie(true);
|
||||
return;
|
||||
}
|
||||
getGroundElev(dt); // make sure it's exectuted first time around, so force a large dt value
|
||||
//getGroundElev(dt); // Need to do this twice.
|
||||
//cerr << trafficRef->getRegistration() << " Setting altitude to " << tgt_altitude;
|
||||
doGroundAltitude();
|
||||
//cerr << " Actual altitude " << altitude << endl;
|
||||
// Transform();
|
||||
pos.setElevationFt(altitude_ft);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -229,10 +246,7 @@ void FGAIAircraft::Run(double dt) {
|
|||
hdg,
|
||||
speed,
|
||||
altitude_ft, dt);
|
||||
//if (controller->hasInstruction(getID()))
|
||||
// {
|
||||
processATC(controller->getInstruction(getID()));
|
||||
// }
|
||||
processATC(controller->getInstruction(getID()));
|
||||
}
|
||||
|
||||
double turn_radius_ft;
|
||||
|
@ -972,29 +986,34 @@ void FGAIAircraft::announcePositionToController()
|
|||
|
||||
int leg = fp->getLeg();
|
||||
|
||||
// For starters, I'll only do this for departure and arrival taxi. The mechanism
|
||||
// could be extended to include any controller however.
|
||||
//int node, currentTaxiSegment;
|
||||
//if (taxiRoute->next(&node, ¤tTaxiSegment)) {
|
||||
if (fp->getCurrentWaypoint()->routeIndex != 0) {
|
||||
//if (fp->getCurrentWaypoint()->routeIndex != 0) {
|
||||
//char buffer[10];
|
||||
//snprintf (buffer, 10, "%d", node);
|
||||
// Note that leg was been incremented after creating the current leg, so we should use
|
||||
// leg numbers here that are one higher than the number that is used to create the leg
|
||||
//
|
||||
switch (leg) {
|
||||
case 3:
|
||||
//cerr << trafficRef->getRegistration()
|
||||
// << " taxiing to runway at segment "
|
||||
// << fp->getCurrentWaypoint()->routeIndex
|
||||
// << endl;
|
||||
//cerr << "Match check between taxisegment and taxiroute : " << node << " "
|
||||
// << fp->getCurrentWaypoint()->name << endl;
|
||||
case 3: // Taxiing to runway
|
||||
if (trafficRef->getDepartureAirport()->getDynamics()->getGroundNetwork()->exists())
|
||||
controller = trafficRef->getDepartureAirport()->getDynamics()->getGroundNetwork();
|
||||
break;
|
||||
case 9:
|
||||
//cerr << trafficRef->getRegistration()
|
||||
// << " taxiing to parking at segment "
|
||||
// << fp->getCurrentWaypoint()->routeIndex
|
||||
// << endl;
|
||||
case 4: //Take off tower controller
|
||||
if (trafficRef->getDepartureAirport()->getDynamics())
|
||||
{
|
||||
controller = trafficRef->getDepartureAirport()->getDynamics()->getTowerController();
|
||||
//if (trafficRef->getDepartureAirport()->getId() == "EHAM") {
|
||||
//cerr << trafficRef->getCallSign() << " at runway " << fp->getRunway() << "Ready for departure "
|
||||
// << trafficRef->getFlightType() << " to " << trafficRef->getArrivalAirport()->getId() << endl;
|
||||
// if (controller == 0) {
|
||||
//cerr << "Error in assigning controller at " << trafficRef->getDepartureAirport()->getId() << endl;
|
||||
//}
|
||||
|
||||
}
|
||||
else {
|
||||
cerr << "Error: Could not find Dynamics at airport : " << trafficRef->getDepartureAirport()->getId() << endl;
|
||||
}
|
||||
break;
|
||||
case 9: // Taxiing for parking
|
||||
if (trafficRef->getArrivalAirport()->getDynamics()->getGroundNetwork()->exists())
|
||||
controller = trafficRef->getArrivalAirport()->getDynamics()->getGroundNetwork();
|
||||
break;
|
||||
|
@ -1002,20 +1021,27 @@ void FGAIAircraft::announcePositionToController()
|
|||
controller = 0;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
//fp->deleteTaxiRoute();
|
||||
controller = 0;
|
||||
}
|
||||
|
||||
if ((controller != prevController) && (prevController != 0)) {
|
||||
prevController->signOff(getID());
|
||||
//cerr << trafficRef->getRegistration()
|
||||
// << " signing off " << endl;
|
||||
string callsign = trafficRef->getCallSign();
|
||||
if ( trafficRef->getHeavy())
|
||||
callsign += "Heavy";
|
||||
switch (leg) {
|
||||
case 3:
|
||||
cerr << callsign << " ready to taxi to runway " << fp->getRunway() << endl;
|
||||
break;
|
||||
case 4:
|
||||
cerr << callsign << " at runway " << fp->getRunway() << "Ready for take-off. "
|
||||
<< trafficRef->getFlightRules() << " to " << trafficRef->getArrivalAirport()->getId()
|
||||
<< "(" << trafficRef->getArrivalAirport()->getName() << ")."<< endl;
|
||||
}
|
||||
}
|
||||
prevController = controller;
|
||||
if (controller) {
|
||||
controller->announcePosition(getID(), fp, fp->getCurrentWaypoint()->routeIndex,
|
||||
_getLatitude(), _getLongitude(), hdg, speed, altitude_ft,
|
||||
trafficRef->getRadius());
|
||||
_getLatitude(), _getLongitude(), hdg, speed, altitude_ft,
|
||||
trafficRef->getRadius(), leg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -176,6 +176,7 @@ ssgBranch * FGAIBase::load3DModel(const string& fg_root,
|
|||
personality_branch->addKid( model );
|
||||
|
||||
return personality_branch;
|
||||
//return model;
|
||||
}
|
||||
|
||||
bool FGAIBase::isa( object_type otype ) {
|
||||
|
|
|
@ -98,6 +98,7 @@ public:
|
|||
int getRouteIndex(int i); // returns the AI related index of this current routes.
|
||||
FGTaxiRoute *getTaxiRoute() { return taxiRoute; };
|
||||
void deleteTaxiRoute();
|
||||
string getRunway() { return activeRunway; };
|
||||
|
||||
|
||||
private:
|
||||
|
|
|
@ -598,6 +598,7 @@ void FGAIFlightPlan::createTakeOff(bool firstFlight, FGAirport *apt, double spee
|
|||
exit(1);
|
||||
}
|
||||
}
|
||||
// Acceleration point, 105 meters into the runway,
|
||||
heading = rwy._heading;
|
||||
double azimuth = heading + 180.0;
|
||||
while ( azimuth >= 360.0 ) { azimuth -= 360.0; }
|
||||
|
@ -622,13 +623,34 @@ void FGAIFlightPlan::createTakeOff(bool firstFlight, FGAirport *apt, double spee
|
|||
lon = lon2;
|
||||
az = az2;
|
||||
|
||||
//Next: the Start of Climb
|
||||
//Start Climbing to 3000 ft. Let's do this
|
||||
// at the center of the runway for now:
|
||||
//
|
||||
geo_direct_wgs_84 ( 0, lat, lon, heading,
|
||||
2560 * SG_FEET_TO_METER,
|
||||
&lat2, &lon2, &az2 );
|
||||
|
||||
wpt = new waypoint;
|
||||
wpt->name = "SOC";
|
||||
wpt->latitude = rwy._lat;
|
||||
wpt->longitude = rwy._lon;
|
||||
wpt->altitude = apt->getElevation()+1000;
|
||||
wpt->speed = speed;
|
||||
wpt->crossat = -10000;
|
||||
wpt->gear_down = true;
|
||||
wpt->flaps_down= true;
|
||||
wpt->finished = false;
|
||||
wpt->on_ground = false;
|
||||
wpt->routeIndex = 0;
|
||||
waypoints.push_back(wpt);
|
||||
|
||||
|
||||
geo_direct_wgs_84 ( 0, rwy._lat, rwy._lon, heading,
|
||||
rwy._length * SG_FEET_TO_METER,
|
||||
&lat2, &lon2, &az2 );
|
||||
|
||||
wpt = new waypoint;
|
||||
wpt->name = "3000 ft";
|
||||
wpt->latitude = lat2;
|
||||
wpt->longitude = lon2;
|
||||
wpt->altitude = apt->getElevation()+3000;
|
||||
|
@ -640,6 +662,46 @@ void FGAIFlightPlan::createTakeOff(bool firstFlight, FGAirport *apt, double spee
|
|||
wpt->on_ground = false;
|
||||
wpt->routeIndex = 0;
|
||||
waypoints.push_back(wpt);
|
||||
|
||||
// Finally, add two more waypoints, so that aircraft will remain under
|
||||
// Tower control until they have reached the 3000 ft climb point
|
||||
|
||||
|
||||
geo_direct_wgs_84 ( 0, rwy._lat, rwy._lon, heading,
|
||||
5000,
|
||||
&lat2, &lon2, &az2 );
|
||||
|
||||
|
||||
wpt = new waypoint;
|
||||
wpt->name = "5000 ft";
|
||||
wpt->latitude = lat2;
|
||||
wpt->longitude = lon2;
|
||||
wpt->altitude = apt->getElevation()+5000;
|
||||
wpt->speed = speed;
|
||||
wpt->crossat = -10000;
|
||||
wpt->gear_down = true;
|
||||
wpt->flaps_down= true;
|
||||
wpt->finished = false;
|
||||
wpt->on_ground = false;
|
||||
wpt->routeIndex = 0;
|
||||
waypoints.push_back(wpt);
|
||||
|
||||
// geo_direct_wgs_84 ( 0, rwy._lat, rwy._lon, heading,
|
||||
// 100000,
|
||||
// &lat2, &lon2, &az2 );
|
||||
// wpt = new waypoint;
|
||||
// wpt->name = "5100 ft";
|
||||
// wpt->latitude = lat2;
|
||||
// wpt->longitude = lon2;
|
||||
// wpt->altitude = apt->getElevation()+5100;
|
||||
// wpt->speed = speed;
|
||||
// wpt->crossat = -10000;
|
||||
// wpt->gear_down = true;
|
||||
// wpt->flaps_down= true;
|
||||
// wpt->finished = false;
|
||||
// wpt->on_ground = false;
|
||||
// wpt->routeIndex = 0;
|
||||
// waypoints.push_back(wpt);
|
||||
}
|
||||
|
||||
/*******************************************************************
|
||||
|
|
|
@ -259,10 +259,30 @@ FGAIManager::loadScenarioFile(const std::string& filename)
|
|||
// This code keeps track of models that have already been loaded
|
||||
// Eventually we'd prbably need to find a way to keep track of models
|
||||
// that are unloaded again
|
||||
ssgBranch * FGAIManager::getModel(const string& path) const
|
||||
ssgBranch * FGAIManager::getModel(const string& path)
|
||||
{
|
||||
ModelVecIterator i = loadedModels.begin();
|
||||
cerr << "Reference count summary " << endl;
|
||||
int count = 0;
|
||||
while (i != loadedModels.end())
|
||||
{
|
||||
count += i->getNumRefs() -1;
|
||||
cerr << "Model " << i->getPath() << " has reference count of " << i->getNumRefs() << " ";
|
||||
if (i->getNumRefs() == 1)
|
||||
{
|
||||
i = loadedModels.erase(i);
|
||||
cerr << "[ Deleted ]" << endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
i++;
|
||||
cerr << endl;
|
||||
}
|
||||
}
|
||||
cerr << "Reference summary end : " << count << "models allocated" << endl;
|
||||
i = loadedModels.begin();
|
||||
|
||||
while (i != loadedModels.end())
|
||||
{
|
||||
if (i->getPath() == path)
|
||||
return i->getModelId();
|
||||
|
|
|
@ -49,10 +49,11 @@ public:
|
|||
FGModelID(const string& pth, ssgBranch * mdl) { path =pth; model=mdl;};
|
||||
ssgBranch * const getModelId() const { return model;};
|
||||
const string & getPath() const { return path;};
|
||||
int getNumRefs() const { return model.getNumRefs(); };
|
||||
};
|
||||
|
||||
typedef vector<FGModelID> ModelVec;
|
||||
typedef vector<FGModelID>::const_iterator ModelVecIterator;
|
||||
typedef vector<FGModelID>::iterator ModelVecIterator;
|
||||
|
||||
class FGAIThermal;
|
||||
|
||||
|
@ -99,7 +100,7 @@ public:
|
|||
|
||||
void processScenario( const string &filename );
|
||||
|
||||
ssgBranch * getModel(const string& path) const;
|
||||
ssgBranch * getModel(const string& path);
|
||||
void setModel(const string& path, ssgBranch *model);
|
||||
|
||||
static SGPropertyNode_ptr loadScenarioFile(const std::string& filename);
|
||||
|
|
|
@ -9,7 +9,8 @@ libAirports_a_SOURCES = \
|
|||
runwayprefs.cxx runwayprefs.hxx \
|
||||
parking.cxx parking.hxx \
|
||||
groundnetwork.cxx groundnetwork.hxx \
|
||||
dynamics.cxx dynamics.hxx
|
||||
dynamics.cxx dynamics.hxx \
|
||||
trafficcontrol.hxx trafficcontrol.cxx
|
||||
|
||||
calc_loc_SOURCES = calc_loc.cxx
|
||||
calc_loc_LDADD = -lsgmath -lsgdebug -lsgmisc -lz $(base_LIBS)
|
||||
|
|
|
@ -91,7 +91,6 @@ FGAirportDynamics::FGAirportDynamics(const FGAirportDynamics& other)
|
|||
// Destructor
|
||||
FGAirportDynamics::~FGAirportDynamics()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -109,6 +108,7 @@ void FGAirportDynamics::init()
|
|||
// add the gate positions to the ground network.
|
||||
groundNetwork.addNodes(&parkings);
|
||||
groundNetwork.init();
|
||||
groundNetwork .setTowerController(&towerController);
|
||||
}
|
||||
|
||||
bool FGAirportDynamics::getAvailableParking(double *lat, double *lon, double *heading, int *gateId, double rad, const string &flType, const string &acType, const string &airline)
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
#include "parking.hxx"
|
||||
#include "groundnetwork.hxx"
|
||||
#include "runwayprefs.hxx"
|
||||
#include "trafficcontrol.hxx"
|
||||
|
||||
|
||||
class FGAirportDynamics : public XMLVisitor {
|
||||
|
@ -42,9 +43,10 @@ private:
|
|||
double _elevation; // ft
|
||||
string _id;
|
||||
|
||||
FGParkingVec parkings;
|
||||
FGParkingVec parkings;
|
||||
FGRunwayPreference rwyPrefs;
|
||||
FGGroundNetwork groundNetwork;
|
||||
FGGroundNetwork groundNetwork;
|
||||
FGTowerController towerController;
|
||||
|
||||
time_t lastUpdate;
|
||||
string prevTrafficType;
|
||||
|
@ -86,7 +88,8 @@ public:
|
|||
//const string &getName() const { return _name;};
|
||||
// Returns degrees
|
||||
|
||||
FGGroundNetwork* getGroundNetwork() { return &groundNetwork; };
|
||||
FGGroundNetwork *getGroundNetwork() { return &groundNetwork; };
|
||||
FGTowerController *getTowerController() { return &towerController; };
|
||||
|
||||
|
||||
void setRwyUse(const FGRunwayPreference& ref);
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -35,17 +35,18 @@ SG_USING_STD(vector);
|
|||
|
||||
|
||||
#include "parking.hxx"
|
||||
//#include <AIModel/AIBase.hxx>
|
||||
#include "trafficcontrol.hxx"
|
||||
|
||||
|
||||
|
||||
class FGTaxiSegment; // forward reference
|
||||
class FGAIFlightPlan; // forward reference
|
||||
|
||||
typedef vector<FGTaxiSegment> FGTaxiSegmentVector;
|
||||
typedef vector<FGTaxiSegment*> FGTaxiSegmentPointerVector;
|
||||
typedef vector<FGTaxiSegment>::iterator FGTaxiSegmentVectorIterator;
|
||||
typedef vector<FGTaxiSegment*>::iterator FGTaxiSegmentPointerVectorIterator;
|
||||
typedef vector<FGTaxiSegment*> FGTaxiSegmentVector;
|
||||
typedef vector<FGTaxiSegment*>::iterator FGTaxiSegmentVectorIterator;
|
||||
|
||||
//typedef vector<FGTaxiSegment*> FGTaxiSegmentPointerVector;
|
||||
//typedef vector<FGTaxiSegment*>::iterator FGTaxiSegmentPointerVectorIterator;
|
||||
|
||||
/**************************************************************************************
|
||||
* class FGTaxiNode
|
||||
|
@ -56,7 +57,7 @@ private:
|
|||
double lat;
|
||||
double lon;
|
||||
int index;
|
||||
FGTaxiSegmentPointerVector next; // a vector to all the segments leaving from this node
|
||||
FGTaxiSegmentVector next; // a vector of pointers to all the segments leaving from this node
|
||||
|
||||
public:
|
||||
FGTaxiNode();
|
||||
|
@ -74,13 +75,13 @@ public:
|
|||
|
||||
int getIndex() { return index; };
|
||||
FGTaxiNode *getAddress() { return this;};
|
||||
FGTaxiSegmentPointerVectorIterator getBeginRoute() { return next.begin(); };
|
||||
FGTaxiSegmentPointerVectorIterator getEndRoute() { return next.end(); };
|
||||
FGTaxiSegmentVectorIterator getBeginRoute() { return next.begin(); };
|
||||
FGTaxiSegmentVectorIterator getEndRoute() { return next.end(); };
|
||||
bool operator<(const FGTaxiNode &other) const { return index < other.index; };
|
||||
};
|
||||
|
||||
typedef vector<FGTaxiNode> FGTaxiNodeVector;
|
||||
typedef vector<FGTaxiNode>::iterator FGTaxiNodeVectorIterator;
|
||||
typedef vector<FGTaxiNode*> FGTaxiNodeVector;
|
||||
typedef vector<FGTaxiNode*>::iterator FGTaxiNodeVectorIterator;
|
||||
|
||||
/***************************************************************************************
|
||||
* class FGTaxiSegment
|
||||
|
@ -160,133 +161,6 @@ public:
|
|||
typedef vector<FGTaxiRoute> TaxiRouteVector;
|
||||
typedef vector<FGTaxiRoute>::iterator TaxiRouteVectorIterator;
|
||||
|
||||
/**************************************************************************************
|
||||
* class FGATCInstruction
|
||||
* like class FGATC Controller, this class definition should go into its own file
|
||||
* and or directory... For now, just testing this stuff out though...
|
||||
*************************************************************************************/
|
||||
class FGATCInstruction
|
||||
{
|
||||
private:
|
||||
bool holdPattern;
|
||||
bool holdPosition;
|
||||
bool changeSpeed;
|
||||
bool changeHeading;
|
||||
bool changeAltitude;
|
||||
|
||||
double speed;
|
||||
double heading;
|
||||
double alt;
|
||||
public:
|
||||
|
||||
FGATCInstruction();
|
||||
bool hasInstruction ();
|
||||
bool getHoldPattern () { return holdPattern; };
|
||||
bool getHoldPosition () { return holdPosition; };
|
||||
bool getChangeSpeed () { return changeSpeed; };
|
||||
bool getChangeHeading () { return changeHeading; };
|
||||
bool getChangeAltitude() { return changeAltitude; };
|
||||
|
||||
double getSpeed () { return speed; };
|
||||
double getHeading () { return heading; };
|
||||
double getAlt () { return alt; };
|
||||
|
||||
void setHoldPattern (bool val) { holdPattern = val; };
|
||||
void setHoldPosition (bool val) { holdPosition = val; };
|
||||
void setChangeSpeed (bool val) { changeSpeed = val; };
|
||||
void setChangeHeading (bool val) { changeHeading = val; };
|
||||
void setChangeAltitude(bool val) { changeAltitude = val; };
|
||||
|
||||
void setSpeed (double val) { speed = val; };
|
||||
void setHeading (double val) { heading = val; };
|
||||
void setAlt (double val) { alt = val; };
|
||||
};
|
||||
|
||||
class FGGroundNetwork;
|
||||
|
||||
/**************************************************************************************
|
||||
* class FGTrafficRecord
|
||||
*************************************************************************************/
|
||||
class FGTrafficRecord
|
||||
{
|
||||
private:
|
||||
int id, waitsForId;
|
||||
int currentPos;
|
||||
intVec intentions;
|
||||
FGATCInstruction instruction;
|
||||
double latitude, longitude, heading, speed, altitude, radius;
|
||||
|
||||
|
||||
public:
|
||||
FGTrafficRecord() {};
|
||||
|
||||
void setId(int val) { id = val; };
|
||||
void setRadius(double rad) { radius = rad;};
|
||||
void setPositionAndIntentions(int pos, FGAIFlightPlan *route);
|
||||
int getId() { return id;};
|
||||
FGATCInstruction getInstruction() { return instruction;};
|
||||
bool hasInstruction() { return instruction.hasInstruction(); };
|
||||
void setPositionAndHeading(double lat, double lon, double hdg, double spd, double alt);
|
||||
bool checkPositionAndIntentions(FGTrafficRecord &other);
|
||||
int crosses (FGGroundNetwork *, FGTrafficRecord &other);
|
||||
bool isOpposing (FGGroundNetwork *, FGTrafficRecord &other, int node);
|
||||
|
||||
bool getSpeedAdjustment() { return instruction.getChangeSpeed(); };
|
||||
|
||||
double getLatitude () { return latitude ; };
|
||||
double getLongitude() { return longitude; };
|
||||
double getHeading () { return heading ; };
|
||||
double getSpeed () { return speed ; };
|
||||
double getAltitude () { return altitude ; };
|
||||
double getRadius () { return radius ; };
|
||||
|
||||
int getWaitsForId () { return waitsForId; };
|
||||
|
||||
void setSpeedAdjustment(double spd) { instruction.setChangeSpeed(true);
|
||||
instruction.setSpeed(spd); };
|
||||
void setHeadingAdjustment(double heading) { instruction.setChangeHeading(true);
|
||||
instruction.setHeading(heading); };
|
||||
void clearSpeedAdjustment () { instruction.setChangeSpeed (false); };
|
||||
void clearHeadingAdjustment() { instruction.setChangeHeading(false); };
|
||||
|
||||
bool hasHeadingAdjustment() { return instruction.getChangeHeading(); };
|
||||
bool hasHoldPosition() { return instruction.getHoldPosition(); };
|
||||
void setHoldPosition (bool inst) { instruction.setHoldPosition(inst); };
|
||||
|
||||
void setWaitsForId(int id) { waitsForId = id; };
|
||||
|
||||
};
|
||||
|
||||
typedef vector<FGTrafficRecord> TrafficVector;
|
||||
typedef vector<FGTrafficRecord>::iterator TrafficVectorIterator;
|
||||
|
||||
|
||||
|
||||
|
||||
/**************************************************************************************
|
||||
* class FGATCController
|
||||
* NOTE: this class serves as an abstraction layer for all sorts of ATC controller,
|
||||
* Ground and air, so eventually it should move to its own file / directory.
|
||||
*************************************************************************************/
|
||||
class FGATCController
|
||||
{
|
||||
private:
|
||||
double dt_count;
|
||||
public:
|
||||
FGATCController() { dt_count = 0;};
|
||||
virtual ~FGATCController() {};
|
||||
virtual void announcePosition(int id, FGAIFlightPlan *intendedRoute, int currentRoute,
|
||||
double lat, double lon,
|
||||
double hdg, double spd, double alt, double radius) = 0;
|
||||
virtual void signOff(int id) = 0;
|
||||
virtual void update(int id, double lat, double lon,
|
||||
double heading, double speed, double alt, double dt) = 0;
|
||||
virtual bool hasInstruction(int id) = 0;
|
||||
virtual FGATCInstruction getInstruction(int id) = 0;
|
||||
|
||||
double getDt() { return dt_count; };
|
||||
void setDt(double dt) { dt_count = dt;};
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
@ -308,6 +182,7 @@ private:
|
|||
|
||||
bool foundRoute;
|
||||
double totalDistance, maxDistance;
|
||||
FGTowerController *towerController;
|
||||
|
||||
void printRoutingError(string);
|
||||
|
||||
|
@ -318,6 +193,7 @@ private:
|
|||
|
||||
public:
|
||||
FGGroundNetwork();
|
||||
~FGGroundNetwork();
|
||||
|
||||
void addNode (const FGTaxiNode& node);
|
||||
void addNodes (FGParkingVec *parkings);
|
||||
|
@ -325,6 +201,7 @@ public:
|
|||
|
||||
void init();
|
||||
bool exists() { return hasNetwork; };
|
||||
void setTowerController(FGTowerController *twrCtrlr) { towerController = twrCtrlr; };
|
||||
int findNearestNode(double lat, double lon);
|
||||
FGTaxiNode *findNode(int idx);
|
||||
FGTaxiSegment *findSegment(int idx);
|
||||
|
@ -332,7 +209,7 @@ public:
|
|||
void trace(FGTaxiNode *, int, int, double dist);
|
||||
|
||||
virtual void announcePosition(int id, FGAIFlightPlan *intendedRoute, int currentRoute,
|
||||
double lat, double lon, double hdg, double spd, double alt, double radius);
|
||||
double lat, double lon, double hdg, double spd, double alt, double radius, int leg);
|
||||
virtual void signOff(int id);
|
||||
virtual void update(int id, double lat, double lon, double heading, double speed, double alt, double dt);
|
||||
virtual bool hasInstruction(int id);
|
||||
|
|
|
@ -90,7 +90,7 @@ FGAirportDynamics * FGAirport::getDynamics()
|
|||
return dynamics;
|
||||
} else {
|
||||
FGRunwayPreference rwyPrefs;
|
||||
//cerr << "Trying to load dynamics for " << _id << endl;
|
||||
cerr << "Trying to load dynamics for " << _id << endl;
|
||||
dynamics = new FGAirportDynamics(_latitude, _longitude, _elevation, _id);
|
||||
|
||||
SGPath parkpath( globals->get_fg_root() );
|
||||
|
|
|
@ -280,3 +280,9 @@ bool FGScheduledFlight::initializeAirports()
|
|||
initialized = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool compareScheduledFlights(FGScheduledFlight *a, FGScheduledFlight *b)
|
||||
{
|
||||
return (*a) < (*b);
|
||||
};
|
||||
|
|
|
@ -95,13 +95,16 @@ public:
|
|||
{
|
||||
return (departureTime < other.departureTime);
|
||||
};
|
||||
string& getFlightRules() { return fltRules; };
|
||||
|
||||
time_t processTimeString(const string& time);
|
||||
const string& getCallSign() {return callsign; };
|
||||
};
|
||||
|
||||
typedef vector<FGScheduledFlight> FGScheduledFlightVec;
|
||||
typedef vector<FGScheduledFlight>::iterator FGScheduledFlightVecIterator;
|
||||
typedef vector<FGScheduledFlight*> FGScheduledFlightVec;
|
||||
typedef vector<FGScheduledFlight*>::iterator FGScheduledFlightVecIterator;
|
||||
|
||||
bool compareScheduledFlights(FGScheduledFlight *a, FGScheduledFlight *b);
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
@ -106,7 +106,7 @@ FGAISchedule::FGAISchedule(string mdl,
|
|||
for (FGScheduledFlightVecIterator i = flt.begin();
|
||||
i != flt.end();
|
||||
i++)
|
||||
flights.push_back(FGScheduledFlight((*i)));
|
||||
flights.push_back(new FGScheduledFlight((*(*i))));
|
||||
AIManagerRef = 0;
|
||||
score = scre;
|
||||
firstRun = true;
|
||||
|
@ -136,7 +136,11 @@ FGAISchedule::FGAISchedule(const FGAISchedule &other)
|
|||
|
||||
FGAISchedule::~FGAISchedule()
|
||||
{
|
||||
|
||||
for (FGScheduledFlightVecIterator flt = flights.begin(); flt != flights.end(); flt++)
|
||||
{
|
||||
delete (*flt);
|
||||
}
|
||||
flights.clear();
|
||||
}
|
||||
|
||||
bool FGAISchedule::init()
|
||||
|
@ -154,7 +158,7 @@ bool FGAISchedule::init()
|
|||
i++)
|
||||
{
|
||||
//i->adjustTime(now);
|
||||
if (!(i->initializeAirports()))
|
||||
if (!((*i)->initializeAirports()))
|
||||
return false;
|
||||
}
|
||||
//sort(flights.begin(), flights.end());
|
||||
|
@ -216,19 +220,20 @@ bool FGAISchedule::update(time_t now)
|
|||
i != flights.end();
|
||||
i++)
|
||||
{
|
||||
i->adjustTime(now);
|
||||
(*i)->adjustTime(now);
|
||||
}
|
||||
if (fgGetBool("/sim/traffic-manager/instantaneous-action") == true)
|
||||
deptime = now;
|
||||
deptime = now + rand() % 300; // Wait up to 5 minutes until traffic starts moving to prevent too many aircraft
|
||||
// from cluttering the gate areas.
|
||||
firstRun = false;
|
||||
}
|
||||
|
||||
// Sort all the scheduled flights according to scheduled departure time.
|
||||
// Because this is done at every update, we only need to check the status
|
||||
// of the first listed flight.
|
||||
sort(flights.begin(), flights.end());
|
||||
sort(flights.begin(), flights.end(), compareScheduledFlights);
|
||||
if (!deptime)
|
||||
deptime = flights.begin()->getDepartureTime();
|
||||
deptime = (*flights.begin())->getDepartureTime();
|
||||
FGScheduledFlightVecIterator i = flights.begin();
|
||||
if (AIManagerRef)
|
||||
{
|
||||
|
@ -246,9 +251,9 @@ bool FGAISchedule::update(time_t now)
|
|||
//cerr << "Estimated minimum distance to user: " << distanceToUser << endl;
|
||||
// This flight entry is entirely in the past, do we need to
|
||||
// push it forward in time to the next scheduled departure.
|
||||
if ((i->getDepartureTime() < now) && (i->getArrivalTime() < now))
|
||||
if (((*i)->getDepartureTime() < now) && ((*i)->getArrivalTime() < now))
|
||||
{
|
||||
i->update();
|
||||
(*i)->update();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -260,10 +265,10 @@ bool FGAISchedule::update(time_t now)
|
|||
|
||||
|
||||
// Part of this flight is in the future.
|
||||
if (i->getArrivalTime() > now)
|
||||
if ((*i)->getArrivalTime() > now)
|
||||
{
|
||||
dep = i->getDepartureAirport();
|
||||
arr = i->getArrivalAirport ();
|
||||
dep = (*i)->getDepartureAirport();
|
||||
arr = (*i)->getArrivalAirport ();
|
||||
if (!(dep && arr))
|
||||
return false;
|
||||
|
||||
|
@ -295,13 +300,13 @@ bool FGAISchedule::update(time_t now)
|
|||
// position of the aircraft by calculating the ratio between
|
||||
// total time enroute and elapsed time enroute.
|
||||
|
||||
totalTimeEnroute = i->getArrivalTime() - i->getDepartureTime();
|
||||
if (now > i->getDepartureTime())
|
||||
totalTimeEnroute = (*i)->getArrivalTime() - (*i)->getDepartureTime();
|
||||
if (now > (*i)->getDepartureTime())
|
||||
{
|
||||
//err << "Lat = " << lat << ", lon = " << lon << endl;
|
||||
//cerr << "Time diff: " << now-i->getDepartureTime() << endl;
|
||||
elapsedTimeEnroute = now - i->getDepartureTime();
|
||||
remainingTimeEnroute = i->getArrivalTime() - now;
|
||||
elapsedTimeEnroute = now - (*i)->getDepartureTime();
|
||||
remainingTimeEnroute = (*i)->getArrivalTime() - now;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -327,7 +332,7 @@ bool FGAISchedule::update(time_t now)
|
|||
}
|
||||
|
||||
temp = sgCartToPolar3d(Point3D(newPos[0], newPos[1],newPos[2]));
|
||||
if (now > i->getDepartureTime())
|
||||
if (now > (*i)->getDepartureTime())
|
||||
{
|
||||
//cerr << "Lat = " << lat << ", lon = " << lon << endl;
|
||||
//cerr << "Time diff: " << now-i->getDepartureTime() << endl;
|
||||
|
@ -343,13 +348,13 @@ bool FGAISchedule::update(time_t now)
|
|||
|
||||
SGWayPoint current (lon,
|
||||
lat,
|
||||
i->getCruiseAlt());
|
||||
(*i)->getCruiseAlt());
|
||||
SGWayPoint user ( userLongitude,
|
||||
userLatitude,
|
||||
i->getCruiseAlt());
|
||||
(*i)->getCruiseAlt());
|
||||
SGWayPoint dest ( arr->getLongitude(),
|
||||
arr->getLatitude(),
|
||||
i->getCruiseAlt());
|
||||
(*i)->getCruiseAlt());
|
||||
// We really only need distance to user
|
||||
// and course to destination
|
||||
user.CourseAndDistance(current, &courseToUser, &distanceToUser);
|
||||
|
@ -392,12 +397,12 @@ bool FGAISchedule::update(time_t now)
|
|||
//aircraft->setFlightPlan(flightPlanName);
|
||||
aircraft->setLatitude(lat);
|
||||
aircraft->setLongitude(lon);
|
||||
aircraft->setAltitude(i->getCruiseAlt()*100); // convert from FL to feet
|
||||
aircraft->setAltitude((*i)->getCruiseAlt()*100); // convert from FL to feet
|
||||
aircraft->setSpeed(speed);
|
||||
aircraft->setBank(0);
|
||||
aircraft->SetFlightPlan(new FGAIFlightPlan(flightPlanName, courseToDest, deptime,
|
||||
dep, arr,true, radius,
|
||||
i->getCruiseAlt()*100,
|
||||
(*i)->getCruiseAlt()*100,
|
||||
lat, lon, speed, flightType, acType,
|
||||
airline));
|
||||
aimgr->attach(aircraft);
|
||||
|
@ -425,9 +430,9 @@ bool FGAISchedule::update(time_t now)
|
|||
// Currently this status is mostly ignored, but in future
|
||||
// versions, code should go here that -if within user range-
|
||||
// positions these aircraft at parking locations at the airport.
|
||||
if ((i->getDepartureTime() > now) && (i->getArrivalTime() > now))
|
||||
if (((*i)->getDepartureTime() > now) && ((*i)->getArrivalTime() > now))
|
||||
{
|
||||
dep = i->getDepartureAirport();
|
||||
dep = (*i)->getDepartureAirport();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -445,8 +450,8 @@ bool FGAISchedule::update(time_t now)
|
|||
|
||||
void FGAISchedule::next()
|
||||
{
|
||||
flights.begin()->update();
|
||||
sort(flights.begin(), flights.end());
|
||||
(*flights.begin())->update();
|
||||
sort(flights.begin(), flights.end(), compareScheduledFlights);
|
||||
}
|
||||
|
||||
double FGAISchedule::getSpeed()
|
||||
|
@ -457,24 +462,29 @@ double FGAISchedule::getSpeed()
|
|||
FGAirport *dep, *arr;
|
||||
|
||||
FGScheduledFlightVecIterator i = flights.begin();
|
||||
dep = i->getDepartureAirport();
|
||||
arr = i->getArrivalAirport ();
|
||||
dep = (*i)->getDepartureAirport();
|
||||
arr = (*i)->getArrivalAirport ();
|
||||
if (!(dep && arr))
|
||||
return 0;
|
||||
|
||||
SGWayPoint dest ( dep->getLongitude(),
|
||||
dep->getLatitude(),
|
||||
i->getCruiseAlt());
|
||||
(*i)->getCruiseAlt());
|
||||
SGWayPoint curr ( arr->getLongitude(),
|
||||
arr->getLatitude(),
|
||||
i->getCruiseAlt());
|
||||
remainingTimeEnroute = i->getArrivalTime() - i->getDepartureTime();
|
||||
(*i)->getCruiseAlt());
|
||||
remainingTimeEnroute = (*i)->getArrivalTime() - (*i)->getDepartureTime();
|
||||
dest.CourseAndDistance(curr, &courseToDest, &distanceToDest);
|
||||
speed = (distanceToDest*SG_METER_TO_NM) /
|
||||
((double) remainingTimeEnroute/3600.0);
|
||||
return speed;
|
||||
}
|
||||
|
||||
bool compareSchedules(FGAISchedule*a, FGAISchedule*b)
|
||||
{
|
||||
return (*a) < (*b);
|
||||
}
|
||||
|
||||
|
||||
// void FGAISchedule::setClosestDistanceToUser()
|
||||
// {
|
||||
|
@ -520,3 +530,4 @@ double FGAISchedule::getSpeed()
|
|||
// }
|
||||
// //return distToUser;
|
||||
// }
|
||||
|
||||
|
|
|
@ -71,29 +71,31 @@ class FGAISchedule
|
|||
//void setClosestDistanceToUser();
|
||||
void next(); // forces the schedule to move on to the next flight.
|
||||
|
||||
time_t getDepartureTime () { return flights.begin()->getDepartureTime (); };
|
||||
FGAirport * getDepartureAirport () { return flights.begin()->getDepartureAirport(); };
|
||||
FGAirport * getArrivalAirport () { return flights.begin()->getArrivalAirport (); };
|
||||
int getCruiseAlt () { return flights.begin()->getCruiseAlt (); };
|
||||
time_t getDepartureTime () { return (*flights.begin())->getDepartureTime (); };
|
||||
FGAirport * getDepartureAirport () { return (*flights.begin())->getDepartureAirport(); };
|
||||
FGAirport * getArrivalAirport () { return (*flights.begin())->getArrivalAirport (); };
|
||||
int getCruiseAlt () { return (*flights.begin())->getCruiseAlt (); };
|
||||
double getRadius () { return radius; };
|
||||
double getGroundOffset () { return groundOffset;};
|
||||
const string& getFlightType () { return flightType;};
|
||||
const string& getAirline () { return airline; };
|
||||
const string& getAircraft () { return acType; };
|
||||
const string& getCallSign () { return flights.begin()->getCallSign (); };
|
||||
const string& getCallSign () { return (*flights.begin())->getCallSign (); };
|
||||
const string& getRegistration () { return registration;};
|
||||
const string& getFlightRules () { return (*flights.begin())->getFlightRules (); };
|
||||
bool getHeavy () { return heavy; };
|
||||
// used to sort in decending order of score: I've probably found a better way to
|
||||
// decending order sorting, but still need to test that.
|
||||
bool operator< (const FGAISchedule &other) const { return (score > other.score); };
|
||||
//void * getAiRef () { return AIManagerRef; };
|
||||
//FGAISchedule* getAddress () { return this;};
|
||||
// More member functions follow later
|
||||
|
||||
};
|
||||
|
||||
typedef vector<FGAISchedule > ScheduleVector;
|
||||
typedef vector<FGAISchedule >::iterator ScheduleVectorIterator;
|
||||
typedef vector<FGAISchedule*> ScheduleVector;
|
||||
typedef vector<FGAISchedule*>::iterator ScheduleVectorIterator;
|
||||
|
||||
bool compareSchedules(FGAISchedule*a, FGAISchedule*b);
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -79,6 +79,20 @@ FGTrafficManager::FGTrafficManager()
|
|||
score = 0;
|
||||
}
|
||||
|
||||
FGTrafficManager:: ~FGTrafficManager()
|
||||
{
|
||||
for (ScheduleVectorIterator sched = scheduledAircraft.begin(); sched != scheduledAircraft.end(); sched++)
|
||||
{
|
||||
delete (*sched);
|
||||
}
|
||||
scheduledAircraft.clear();
|
||||
// for (FGScheduledFlightVecIterator flt = flights.begin(); flt != flights.end(); flt++)
|
||||
// {
|
||||
// delete (*flt);
|
||||
// }
|
||||
// flights.clear();
|
||||
}
|
||||
|
||||
|
||||
void FGTrafficManager::init()
|
||||
{
|
||||
|
@ -97,8 +111,9 @@ void FGTrafficManager::init()
|
|||
// currAircraft++;
|
||||
// }
|
||||
// }
|
||||
//cerr << "Sorting by distance " << endl;
|
||||
sort(scheduledAircraft.begin(), scheduledAircraft.end());
|
||||
// Sort by points: Aircraft with frequent visits to the
|
||||
// startup airport will be processed first
|
||||
sort(scheduledAircraft.begin(), scheduledAircraft.end(), compareSchedules);
|
||||
currAircraft = scheduledAircraft.begin();
|
||||
currAircraftClosest = scheduledAircraft.begin();
|
||||
//cerr << "Done initializing schedules" << endl;
|
||||
|
@ -114,7 +129,7 @@ void FGTrafficManager::update(double something)
|
|||
//cerr << "resetting schedule " << endl;
|
||||
currAircraft = scheduledAircraft.begin();
|
||||
}
|
||||
if (!(currAircraft->update(now)))
|
||||
if (!((*currAircraft)->update(now)))
|
||||
{
|
||||
// after proper initialization, we shouldnt get here.
|
||||
// But let's make sure
|
||||
|
@ -232,7 +247,7 @@ void FGTrafficManager::endElement (const char * name) {
|
|||
string apt = fgGetString("/sim/presets/airport-id");
|
||||
//cerr << "Airport information: " << apt << " " << departurePort << " " << arrivalPort << endl;
|
||||
if (departurePort == apt) score++;
|
||||
flights.push_back(FGScheduledFlight(callsign,
|
||||
flights.push_back(new FGScheduledFlight(callsign,
|
||||
fltrules,
|
||||
departurePort,
|
||||
arrivalPort,
|
||||
|
@ -244,7 +259,7 @@ void FGTrafficManager::endElement (const char * name) {
|
|||
else if (element == string("aircraft"))
|
||||
{
|
||||
//cerr << "Pushing back aircraft " << registration << endl;
|
||||
scheduledAircraft.push_back(FGAISchedule(mdl,
|
||||
scheduledAircraft.push_back(new FGAISchedule(mdl,
|
||||
livery,
|
||||
registration,
|
||||
heavy,
|
||||
|
@ -256,8 +271,14 @@ void FGTrafficManager::endElement (const char * name) {
|
|||
offset,
|
||||
score,
|
||||
flights));
|
||||
while(flights.begin() != flights.end())
|
||||
flights.pop_back();
|
||||
// while(flights.begin() != flights.end()) {
|
||||
// flights.pop_back();
|
||||
// }
|
||||
for (FGScheduledFlightVecIterator flt = flights.begin(); flt != flights.end(); flt++)
|
||||
{
|
||||
delete (*flt);
|
||||
}
|
||||
flights.clear();
|
||||
SG_LOG( SG_GENERAL, SG_BULK, "Reading aircraft : "
|
||||
<< registration
|
||||
<< " with prioritization score "
|
||||
|
|
|
@ -59,7 +59,7 @@ private:
|
|||
|
||||
public:
|
||||
FGTrafficManager();
|
||||
|
||||
~FGTrafficManager();
|
||||
void init();
|
||||
void update(double time);
|
||||
void release(int ref);
|
||||
|
|
Loading…
Reference in a new issue