Durk Talsma:
Okay, here's the latest update to the tarffic manager/AI Manager. AITraffic can now fly multiple routes and be initialized while sitting statically at airports.
This commit is contained in:
parent
ffafb573b2
commit
c537267f96
13 changed files with 284 additions and 42 deletions
|
@ -51,7 +51,8 @@ const FGAIAircraft::PERF_STRUCT FGAIAircraft::settings[] = {
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
FGAIAircraft::FGAIAircraft(FGAIManager* mgr) {
|
FGAIAircraft::FGAIAircraft(FGAIManager* mgr, FGAISchedule *ref) {
|
||||||
|
trafficRef = ref;
|
||||||
manager = mgr;
|
manager = mgr;
|
||||||
_type_str = "aircraft";
|
_type_str = "aircraft";
|
||||||
_otype = otAircraft;
|
_otype = otAircraft;
|
||||||
|
@ -114,7 +115,14 @@ void FGAIAircraft::Run(double dt) {
|
||||||
|
|
||||||
FGAIAircraft::dt = dt;
|
FGAIAircraft::dt = dt;
|
||||||
|
|
||||||
if (fp) ProcessFlightPlan(dt);
|
if (fp)
|
||||||
|
{
|
||||||
|
ProcessFlightPlan(dt);
|
||||||
|
time_t now = time(NULL) + fgGetLong("/sim/time/warp");
|
||||||
|
if (now < fp->getStartTime())
|
||||||
|
return;
|
||||||
|
//ProcessFlightPlan(dt);
|
||||||
|
}
|
||||||
|
|
||||||
double turn_radius_ft;
|
double turn_radius_ft;
|
||||||
double turn_circum_ft;
|
double turn_circum_ft;
|
||||||
|
@ -295,6 +303,8 @@ void FGAIAircraft::SetFlightPlan(FGAIFlightPlan *f) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void FGAIAircraft::ProcessFlightPlan( double dt ) {
|
void FGAIAircraft::ProcessFlightPlan( double dt ) {
|
||||||
|
|
||||||
|
|
||||||
FGAIFlightPlan::waypoint* prev = 0; // the one behind you
|
FGAIFlightPlan::waypoint* prev = 0; // the one behind you
|
||||||
FGAIFlightPlan::waypoint* curr = 0; // the one ahead
|
FGAIFlightPlan::waypoint* curr = 0; // the one ahead
|
||||||
FGAIFlightPlan::waypoint* next = 0; // the next plus 1
|
FGAIFlightPlan::waypoint* next = 0; // the next plus 1
|
||||||
|
@ -348,10 +358,35 @@ void FGAIAircraft::ProcessFlightPlan( double dt ) {
|
||||||
|
|
||||||
if ( dist_to_go < lead_dist ) {
|
if ( dist_to_go < lead_dist ) {
|
||||||
if (curr->finished) { //end of the flight plan, so terminate
|
if (curr->finished) { //end of the flight plan, so terminate
|
||||||
setDie(true);
|
if (trafficRef)
|
||||||
return;
|
{
|
||||||
|
delete fp;
|
||||||
|
//time_t now = time(NULL) + fgGetLong("/sim/time/warp");
|
||||||
|
trafficRef->next();
|
||||||
|
|
||||||
|
FGAIModelEntity entity;
|
||||||
|
entity.m_class = "jet_transport";
|
||||||
|
//entity.path = modelPath.c_str();
|
||||||
|
entity.flightplan = "none";
|
||||||
|
entity.latitude = _getLatitude();
|
||||||
|
entity.longitude = _getLongitude();
|
||||||
|
entity.altitude = trafficRef->getCruiseAlt() * 100; // convert from FL to feet
|
||||||
|
entity.speed = 450;
|
||||||
|
//entity.fp = new FGAIFlightPlan(&entity, courseToDest, i->getDepartureTime(), dep, arr);
|
||||||
|
entity.fp = new FGAIFlightPlan(&entity,
|
||||||
|
999, // A hack
|
||||||
|
trafficRef->getDepartureTime(),
|
||||||
|
trafficRef->getDepartureAirport(),
|
||||||
|
trafficRef->getArrivalAirport());
|
||||||
|
SetFlightPlan(entity.fp);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
setDie(true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// we've reached the lead-point for the waypoint ahead
|
// we've reached the lead-point for the waypoint ahead
|
||||||
if (next) tgt_heading = fp->getBearing(curr, next);
|
if (next) tgt_heading = fp->getBearing(curr, next);
|
||||||
fp->IncrementWaypoint();
|
fp->IncrementWaypoint();
|
||||||
prev = fp->getPreviousWaypoint();
|
prev = fp->getPreviousWaypoint();
|
||||||
|
@ -386,6 +421,7 @@ void FGAIAircraft::ProcessFlightPlan( double dt ) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool FGAIAircraft::_getGearDown() const {
|
bool FGAIAircraft::_getGearDown() const {
|
||||||
return ((props->getFloatValue("position/altitude-agl-ft") < 900.0)
|
return ((props->getFloatValue("position/altitude-agl-ft") < 900.0)
|
||||||
&& (props->getFloatValue("velocities/airspeed-kt")
|
&& (props->getFloatValue("velocities/airspeed-kt")
|
||||||
|
|
|
@ -24,6 +24,9 @@
|
||||||
#include "AIManager.hxx"
|
#include "AIManager.hxx"
|
||||||
#include "AIBase.hxx"
|
#include "AIBase.hxx"
|
||||||
|
|
||||||
|
#include <Traffic/SchedFlight.hxx>
|
||||||
|
#include <Traffic/Schedule.hxx>
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
SG_USING_STD(string);
|
SG_USING_STD(string);
|
||||||
|
|
||||||
|
@ -49,7 +52,7 @@ public:
|
||||||
enum aircraft_e {LIGHT=0, WW2_FIGHTER, JET_TRANSPORT, JET_FIGHTER, TANKER};
|
enum aircraft_e {LIGHT=0, WW2_FIGHTER, JET_TRANSPORT, JET_FIGHTER, TANKER};
|
||||||
static const PERF_STRUCT settings[];
|
static const PERF_STRUCT settings[];
|
||||||
|
|
||||||
FGAIAircraft(FGAIManager* mgr);
|
FGAIAircraft(FGAIManager* mgr, FGAISchedule *ref=0);
|
||||||
~FGAIAircraft();
|
~FGAIAircraft();
|
||||||
|
|
||||||
bool init();
|
bool init();
|
||||||
|
@ -70,7 +73,8 @@ public:
|
||||||
inline void SetTanker(bool setting) { isTanker = setting; };
|
inline void SetTanker(bool setting) { isTanker = setting; };
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
FGAISchedule *trafficRef;
|
||||||
|
|
||||||
bool hdg_lock;
|
bool hdg_lock;
|
||||||
bool alt_lock;
|
bool alt_lock;
|
||||||
double dt_count;
|
double dt_count;
|
||||||
|
|
|
@ -136,7 +136,7 @@ bool FGAIBase::init() {
|
||||||
props = root->getNode(_type_str.c_str(), index, true);
|
props = root->getNode(_type_str.c_str(), index, true);
|
||||||
|
|
||||||
if (model_path != "") {
|
if (model_path != "") {
|
||||||
model = sgLoad3DModel( globals->get_fg_root(),
|
model = load3DModel( globals->get_fg_root(),
|
||||||
model_path.c_str(),
|
model_path.c_str(),
|
||||||
props,
|
props,
|
||||||
globals->get_sim_time_sec() );
|
globals->get_sim_time_sec() );
|
||||||
|
@ -157,6 +157,36 @@ bool FGAIBase::init() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ssgBranch * FGAIBase::load3DModel(const string& fg_root,
|
||||||
|
const string &path,
|
||||||
|
SGPropertyNode *prop_root,
|
||||||
|
double sim_time_sec)
|
||||||
|
{
|
||||||
|
// some more code here to check whether a model with this name has already been loaded
|
||||||
|
// if not load it, otherwise, get the memory pointer and do something like
|
||||||
|
// SetModel as in ATC/AIEntity.cxx
|
||||||
|
//SSGBranch *model;
|
||||||
|
model = manager->getModel(path);
|
||||||
|
if (!(model))
|
||||||
|
{
|
||||||
|
model = sgLoad3DModel(fg_root,
|
||||||
|
path,
|
||||||
|
prop_root,
|
||||||
|
sim_time_sec);
|
||||||
|
manager->setModel(path, model);
|
||||||
|
model->ref();
|
||||||
|
}
|
||||||
|
//else
|
||||||
|
// {
|
||||||
|
// model->ref();
|
||||||
|
// aip.init(model);
|
||||||
|
// aip.setVisible(false);
|
||||||
|
// globals->get_scenery()->get_scene_graph()->addKid(aip.getSceneGraph());
|
||||||
|
// do some setModel stuff.
|
||||||
|
return model;
|
||||||
|
}
|
||||||
|
|
||||||
bool FGAIBase::isa( object_type otype ) {
|
bool FGAIBase::isa( object_type otype ) {
|
||||||
if ( otype == _otype ) { return true; }
|
if ( otype == _otype ) { return true; }
|
||||||
else { return false; }
|
else { return false; }
|
||||||
|
|
|
@ -202,6 +202,10 @@ public:
|
||||||
int _getID() const;
|
int _getID() const;
|
||||||
|
|
||||||
inline double _getRange() { return range; };
|
inline double _getRange() { return range; };
|
||||||
|
ssgBranch * load3DModel(const string& fg_root,
|
||||||
|
const string &path,
|
||||||
|
SGPropertyNode *prop_root,
|
||||||
|
double sim_time_sec);
|
||||||
|
|
||||||
static bool _isNight();
|
static bool _isNight();
|
||||||
};
|
};
|
||||||
|
|
|
@ -44,6 +44,7 @@
|
||||||
FGAIFlightPlan::FGAIFlightPlan(string filename)
|
FGAIFlightPlan::FGAIFlightPlan(string filename)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
start_time = 0;
|
||||||
SGPath path( globals->get_fg_root() );
|
SGPath path( globals->get_fg_root() );
|
||||||
path.append( ("/Data/AI/FlightPlans/" + filename).c_str() );
|
path.append( ("/Data/AI/FlightPlans/" + filename).c_str() );
|
||||||
SGPropertyNode root;
|
SGPropertyNode root;
|
||||||
|
@ -90,16 +91,30 @@ FGAIFlightPlan::FGAIFlightPlan(string filename)
|
||||||
// as setting speeds and altitude computed by the
|
// as setting speeds and altitude computed by the
|
||||||
// traffic manager.
|
// traffic manager.
|
||||||
FGAIFlightPlan::FGAIFlightPlan(FGAIModelEntity *entity,
|
FGAIFlightPlan::FGAIFlightPlan(FGAIModelEntity *entity,
|
||||||
double course,
|
double course,
|
||||||
|
time_t start,
|
||||||
FGAirport *dep,
|
FGAirport *dep,
|
||||||
FGAirport *arr)
|
FGAirport *arr)
|
||||||
{
|
{
|
||||||
|
start_time = start;
|
||||||
bool useInitialWayPoint = true;
|
bool useInitialWayPoint = true;
|
||||||
bool useCurrentWayPoint = false;
|
bool useCurrentWayPoint = false;
|
||||||
SGPath path( globals->get_fg_root() );
|
SGPath path( globals->get_fg_root() );
|
||||||
path.append( "/Data/AI/FlightPlans" );
|
path.append( "/Data/AI/FlightPlans" );
|
||||||
path.append( entity->path );
|
path.append( entity->path );
|
||||||
SGPropertyNode root;
|
SGPropertyNode root;
|
||||||
|
|
||||||
|
// This is a bit of a hack:
|
||||||
|
// Normally the value of course will be used to evaluate whether
|
||||||
|
// or not a waypoint will be used for midair initialization of
|
||||||
|
// an AI aircraft. However, if a course value of 999 will be passed
|
||||||
|
// when an update request is received, which will by definition always be
|
||||||
|
// on the ground and should include all waypoints.
|
||||||
|
if (course == 999)
|
||||||
|
{
|
||||||
|
useInitialWayPoint = false;
|
||||||
|
useCurrentWayPoint = true;
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
readProperties(path.str(), &root);
|
readProperties(path.str(), &root);
|
||||||
|
@ -160,7 +175,7 @@ FGAIFlightPlan::FGAIFlightPlan(FGAIModelEntity *entity,
|
||||||
(*i)->altitude);
|
(*i)->altitude);
|
||||||
double crse, crsDiff;
|
double crse, crsDiff;
|
||||||
double dist;
|
double dist;
|
||||||
first.CourseAndDistance(curr, &crse, &dist);
|
curr.CourseAndDistance(first, &crse, &dist);
|
||||||
|
|
||||||
dist *= SG_METER_TO_NM;
|
dist *= SG_METER_TO_NM;
|
||||||
|
|
||||||
|
@ -182,8 +197,8 @@ FGAIFlightPlan::FGAIFlightPlan(FGAIModelEntity *entity,
|
||||||
// so once is the useWpt flag is set to true, we cannot reset it to false.
|
// so once is the useWpt flag is set to true, we cannot reset it to false.
|
||||||
//cerr << "Discarding waypoint: " << (*i)->name
|
//cerr << "Discarding waypoint: " << (*i)->name
|
||||||
// << ": Course difference = " << crsDiff
|
// << ": Course difference = " << crsDiff
|
||||||
// << "Course = " << course
|
// << "Course = " << course
|
||||||
// << "crse = " << crse << endl;
|
// << "crse = " << crse << endl;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
useCurrentWayPoint = true;
|
useCurrentWayPoint = true;
|
||||||
|
@ -192,10 +207,14 @@ FGAIFlightPlan::FGAIFlightPlan(FGAIModelEntity *entity,
|
||||||
{
|
{
|
||||||
if ((dist > 100.0) && (useInitialWayPoint))
|
if ((dist > 100.0) && (useInitialWayPoint))
|
||||||
{
|
{
|
||||||
//waypoints.push_back(init_waypoint);
|
//waypoints.push_back(init_waypoint);;
|
||||||
waypoints.insert(i, init_waypoint);
|
waypoints.insert(i, init_waypoint);
|
||||||
//cerr << "Using waypoint : " << init_waypoint->name << endl;
|
//cerr << "Using waypoint : " << init_waypoint->name << endl;
|
||||||
}
|
}
|
||||||
|
//if (useInitialWayPoint)
|
||||||
|
// {
|
||||||
|
// (*i)->speed = dist; // A hack
|
||||||
|
// }
|
||||||
//waypoints.push_back( wpt );
|
//waypoints.push_back( wpt );
|
||||||
//cerr << "Using waypoint : " << (*i)->name
|
//cerr << "Using waypoint : " << (*i)->name
|
||||||
// << ": course diff : " << crsDiff
|
// << ": course diff : " << crsDiff
|
||||||
|
@ -342,26 +361,35 @@ double FGAIFlightPlan::getBearing(double lat, double lon, waypoint* wp){
|
||||||
*/
|
*/
|
||||||
void FGAIFlightPlan::create(FGAirport *dep, FGAirport *arr, double alt, double speed)
|
void FGAIFlightPlan::create(FGAirport *dep, FGAirport *arr, double alt, double speed)
|
||||||
{
|
{
|
||||||
double wind_speed;
|
double wind_speed;
|
||||||
double wind_heading;
|
double wind_heading;
|
||||||
FGRunway rwy;
|
FGRunway rwy;
|
||||||
|
double lat, lon, az;
|
||||||
|
double lat2, lon2, az2;
|
||||||
|
int direction;
|
||||||
|
|
||||||
//waypoints.push_back(wpt);
|
//waypoints.push_back(wpt);
|
||||||
// Create the outbound taxi leg, for now simplified as a
|
// Create the outbound taxi leg, for now simplified as a
|
||||||
// Direct route from the airport center point to the start
|
// Direct route from the airport center point to the start
|
||||||
// of the runway.
|
// of the runway.
|
||||||
///////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////
|
||||||
//cerr << "Cruise Alt << " << alt << endl;
|
//cerr << "Cruise Alt << " << alt << endl;
|
||||||
|
// Temporary code to add some small random variation to aircraft parking positions;
|
||||||
|
direction = (rand() % 360);
|
||||||
|
geo_direct_wgs_84 ( 0, dep->latitude, dep->longitude, direction,
|
||||||
|
100,
|
||||||
|
&lat2, &lon2, &az2 );
|
||||||
waypoint *wpt = new waypoint;
|
waypoint *wpt = new waypoint;
|
||||||
wpt->name = dep->id; //wpt_node->getStringValue("name", "END");
|
wpt->name = dep->id; //wpt_node->getStringValue("name", "END");
|
||||||
wpt->latitude = dep->latitude;
|
wpt->latitude = lat2;
|
||||||
wpt->longitude = dep->longitude;
|
wpt->longitude = lon2;
|
||||||
wpt->altitude = dep->elevation + 19; // probably need to add some model height to it
|
wpt->altitude = dep->elevation + 19; // probably need to add some model height to it
|
||||||
wpt->speed = 15;
|
wpt->speed = 15;
|
||||||
wpt->crossat = -10000;
|
wpt->crossat = -10000;
|
||||||
wpt->gear_down = true;
|
wpt->gear_down = true;
|
||||||
wpt->flaps_down= true;
|
wpt->flaps_down= true;
|
||||||
wpt->finished = false;
|
wpt->finished = false;
|
||||||
|
wpt->on_ground = true;
|
||||||
waypoints.push_back(wpt);
|
waypoints.push_back(wpt);
|
||||||
|
|
||||||
// Get the current active runway, based on code from David Luff
|
// Get the current active runway, based on code from David Luff
|
||||||
|
@ -384,8 +412,7 @@ void FGAIFlightPlan::create(FGAirport *dep, FGAirport *arr, double alt, double s
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
double lat, lon, az;
|
|
||||||
double lat2, lon2, az2;
|
|
||||||
double heading = rwy.heading;
|
double heading = rwy.heading;
|
||||||
double azimuth = heading + 180.0;
|
double azimuth = heading + 180.0;
|
||||||
while ( azimuth >= 360.0 ) { azimuth -= 360.0; }
|
while ( azimuth >= 360.0 ) { azimuth -= 360.0; }
|
||||||
|
@ -546,7 +573,7 @@ void FGAIFlightPlan::create(FGAirport *dep, FGAirport *arr, double alt, double s
|
||||||
waypoints.push_back(wpt);
|
waypoints.push_back(wpt);
|
||||||
//Runway Threshold
|
//Runway Threshold
|
||||||
geo_direct_wgs_84 ( 0, rwy.lat, rwy.lon, azimuth,
|
geo_direct_wgs_84 ( 0, rwy.lat, rwy.lon, azimuth,
|
||||||
rwy.length*0.45,
|
rwy.length*0.45 * SG_FEET_TO_METER,
|
||||||
&lat2, &lon2, &az2 );
|
&lat2, &lon2, &az2 );
|
||||||
wpt = new waypoint;
|
wpt = new waypoint;
|
||||||
wpt->name = "Threshold"; //wpt_node->getStringValue("name", "END");
|
wpt->name = "Threshold"; //wpt_node->getStringValue("name", "END");
|
||||||
|
@ -575,28 +602,33 @@ void FGAIFlightPlan::create(FGAirport *dep, FGAirport *arr, double alt, double s
|
||||||
wpt->gear_down = true;
|
wpt->gear_down = true;
|
||||||
wpt->flaps_down= true;
|
wpt->flaps_down= true;
|
||||||
wpt->finished = false;
|
wpt->finished = false;
|
||||||
wpt->on_ground = false;
|
wpt->on_ground = true;
|
||||||
waypoints.push_back(wpt);
|
waypoints.push_back(wpt);
|
||||||
|
|
||||||
|
direction = (rand() % 360);
|
||||||
|
geo_direct_wgs_84 ( 0, arr->latitude, arr->longitude, direction,
|
||||||
|
100,
|
||||||
|
&lat2, &lon2, &az2 );
|
||||||
|
|
||||||
// Add the final destination waypoint
|
// Add the final destination waypoint
|
||||||
wpt = new waypoint;
|
wpt = new waypoint;
|
||||||
wpt->name = arr->id; //wpt_node->getStringValue("name", "END");
|
wpt->name = arr->id; //wpt_node->getStringValue("name", "END");
|
||||||
wpt->latitude = arr->latitude;
|
wpt->latitude = lat2;
|
||||||
wpt->longitude = arr->longitude;
|
wpt->longitude = lon2;
|
||||||
wpt->altitude = arr->elevation+19;
|
wpt->altitude = arr->elevation+19;
|
||||||
wpt->speed = 15;
|
wpt->speed = 15;
|
||||||
wpt->crossat = -10000;
|
wpt->crossat = -10000;
|
||||||
wpt->gear_down = true;
|
wpt->gear_down = true;
|
||||||
wpt->flaps_down= true;
|
wpt->flaps_down= true;
|
||||||
wpt->finished = false;
|
wpt->finished = false;
|
||||||
wpt->on_ground = false;
|
wpt->on_ground = true;
|
||||||
waypoints.push_back(wpt);
|
waypoints.push_back(wpt);
|
||||||
|
|
||||||
// And finally one more named "END"
|
// And finally one more named "END"
|
||||||
wpt = new waypoint;
|
wpt = new waypoint;
|
||||||
wpt->name = "END"; //wpt_node->getStringValue("name", "END");
|
wpt->name = "END"; //wpt_node->getStringValue("name", "END");
|
||||||
wpt->latitude = arr->latitude;
|
wpt->latitude = lat2;
|
||||||
wpt->longitude = arr->longitude;
|
wpt->longitude = lon2;
|
||||||
wpt->altitude = 19;
|
wpt->altitude = 19;
|
||||||
wpt->speed = 15;
|
wpt->speed = 15;
|
||||||
wpt->crossat = -10000;
|
wpt->crossat = -10000;
|
||||||
|
@ -609,14 +641,14 @@ void FGAIFlightPlan::create(FGAirport *dep, FGAirport *arr, double alt, double s
|
||||||
// And finally one more named "EOF"
|
// And finally one more named "EOF"
|
||||||
wpt = new waypoint;
|
wpt = new waypoint;
|
||||||
wpt->name = "EOF"; //wpt_node->getStringValue("name", "END");
|
wpt->name = "EOF"; //wpt_node->getStringValue("name", "END");
|
||||||
wpt->latitude = arr->latitude;
|
wpt->latitude = lat2;
|
||||||
wpt->longitude = arr->longitude;
|
wpt->longitude = lon2;
|
||||||
wpt->altitude = 19;
|
wpt->altitude = 19;
|
||||||
wpt->speed = 15;
|
wpt->speed = 15;
|
||||||
wpt->crossat = -10000;
|
wpt->crossat = -10000;
|
||||||
wpt->gear_down = true;
|
wpt->gear_down = true;
|
||||||
wpt->flaps_down= true;
|
wpt->flaps_down= true;
|
||||||
wpt->finished = true;
|
wpt->finished = true;
|
||||||
wpt->finished = true;
|
wpt->on_ground = true;
|
||||||
waypoints.push_back(wpt);
|
waypoints.push_back(wpt);
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,6 +51,7 @@ public:
|
||||||
FGAIFlightPlan(string filename);
|
FGAIFlightPlan(string filename);
|
||||||
FGAIFlightPlan(FGAIModelEntity *entity,
|
FGAIFlightPlan(FGAIModelEntity *entity,
|
||||||
double course,
|
double course,
|
||||||
|
time_t start,
|
||||||
FGAirport *dep,
|
FGAirport *dep,
|
||||||
FGAirport *arr);
|
FGAirport *arr);
|
||||||
~FGAIFlightPlan();
|
~FGAIFlightPlan();
|
||||||
|
@ -66,6 +67,7 @@ public:
|
||||||
double getLeadDistance( void ) const {return lead_distance;}
|
double getLeadDistance( void ) const {return lead_distance;}
|
||||||
double getBearing(waypoint* previous, waypoint* next);
|
double getBearing(waypoint* previous, waypoint* next);
|
||||||
double getBearing(double lat, double lon, waypoint* next);
|
double getBearing(double lat, double lon, waypoint* next);
|
||||||
|
time_t getStartTime() { return start_time; };
|
||||||
|
|
||||||
void create(FGAirport *dep, FGAirport *arr, double alt, double speed);
|
void create(FGAirport *dep, FGAirport *arr, double alt, double speed);
|
||||||
|
|
||||||
|
@ -79,6 +81,7 @@ private:
|
||||||
|
|
||||||
double distance_to_go;
|
double distance_to_go;
|
||||||
double lead_distance;
|
double lead_distance;
|
||||||
|
time_t start_time;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -22,6 +22,11 @@
|
||||||
#include <Main/fg_props.hxx>
|
#include <Main/fg_props.hxx>
|
||||||
#include <Main/globals.hxx>
|
#include <Main/globals.hxx>
|
||||||
|
|
||||||
|
#include <Airports/simple.hxx>
|
||||||
|
#include <Traffic/SchedFlight.hxx>
|
||||||
|
#include <Traffic/Schedule.hxx>
|
||||||
|
#include <Traffic/TrafficMgr.hxx>
|
||||||
|
|
||||||
#include <list>
|
#include <list>
|
||||||
|
|
||||||
#include "AIManager.hxx"
|
#include "AIManager.hxx"
|
||||||
|
@ -53,6 +58,11 @@ FGAIManager::~FGAIManager() {
|
||||||
++ai_list_itr;
|
++ai_list_itr;
|
||||||
}
|
}
|
||||||
ai_list.clear();
|
ai_list.clear();
|
||||||
|
ModelVecIterator i = loadedModels.begin();
|
||||||
|
while (i != loadedModels.end())
|
||||||
|
{
|
||||||
|
i->getModelId()->deRef();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -88,6 +98,7 @@ void FGAIManager::update(double dt) {
|
||||||
// initialize these for finding nearest thermals
|
// initialize these for finding nearest thermals
|
||||||
range_nearest = 10000.0;
|
range_nearest = 10000.0;
|
||||||
strength = 0.0;
|
strength = 0.0;
|
||||||
|
FGTrafficManager *tmgr = (FGTrafficManager*) globals->get_subsystem("Traffic Manager");
|
||||||
|
|
||||||
if (!enabled)
|
if (!enabled)
|
||||||
return;
|
return;
|
||||||
|
@ -97,6 +108,7 @@ void FGAIManager::update(double dt) {
|
||||||
ai_list_itr = ai_list.begin();
|
ai_list_itr = ai_list.begin();
|
||||||
while(ai_list_itr != ai_list.end()) {
|
while(ai_list_itr != ai_list.end()) {
|
||||||
if ((*ai_list_itr)->getDie()) {
|
if ((*ai_list_itr)->getDie()) {
|
||||||
|
tmgr->release((*ai_list_itr)->getID());
|
||||||
--numObjects[(*ai_list_itr)->getType()];
|
--numObjects[(*ai_list_itr)->getType()];
|
||||||
--numObjects[0];
|
--numObjects[0];
|
||||||
(*ai_list_itr)->unbind();
|
(*ai_list_itr)->unbind();
|
||||||
|
@ -124,9 +136,9 @@ void FGAIManager::update(double dt) {
|
||||||
|
|
||||||
|
|
||||||
void*
|
void*
|
||||||
FGAIManager::createAircraft( FGAIModelEntity *entity ) {
|
FGAIManager::createAircraft( FGAIModelEntity *entity, FGAISchedule *ref) {
|
||||||
|
|
||||||
FGAIAircraft* ai_plane = new FGAIAircraft(this);
|
FGAIAircraft* ai_plane = new FGAIAircraft(this, ref);
|
||||||
ai_list.push_back(ai_plane);
|
ai_list.push_back(ai_plane);
|
||||||
++numObjects[0];
|
++numObjects[0];
|
||||||
++numObjects[FGAIBase::otAircraft];
|
++numObjects[FGAIBase::otAircraft];
|
||||||
|
@ -352,4 +364,25 @@ void FGAIManager::processScenario( string &filename ) {
|
||||||
delete s;
|
delete s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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)
|
||||||
|
{
|
||||||
|
ModelVecIterator i = loadedModels.begin();
|
||||||
|
while (i != loadedModels.end())
|
||||||
|
{
|
||||||
|
if (i->getPath() == path)
|
||||||
|
return i->getModelId();
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FGAIManager::setModel(const string& path, ssgBranch *model)
|
||||||
|
{
|
||||||
|
loadedModels.push_back(FGModelID(path,model));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//end AIManager.cxx
|
//end AIManager.cxx
|
||||||
|
|
|
@ -33,7 +33,26 @@
|
||||||
#include <AIModel/AIScenario.hxx>
|
#include <AIModel/AIScenario.hxx>
|
||||||
#include <AIModel/AIFlightPlan.hxx>
|
#include <AIModel/AIFlightPlan.hxx>
|
||||||
|
|
||||||
|
#include <Traffic/SchedFlight.hxx>
|
||||||
|
#include <Traffic/Schedule.hxx>
|
||||||
|
|
||||||
SG_USING_STD(list);
|
SG_USING_STD(list);
|
||||||
|
SG_USING_STD(vector);
|
||||||
|
|
||||||
|
class FGModelID
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
ssgBranch * model;
|
||||||
|
string path;
|
||||||
|
public:
|
||||||
|
FGModelID(const string& pth, ssgBranch * mdl) { path =pth; model=mdl;};
|
||||||
|
ssgBranch *getModelId() { return model;};
|
||||||
|
const string & getPath() { return path;};
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef vector<FGModelID> ModelVec;
|
||||||
|
typedef vector<FGModelID>::iterator ModelVecIterator;
|
||||||
|
|
||||||
class FGAIThermal;
|
class FGAIThermal;
|
||||||
|
|
||||||
|
|
||||||
|
@ -51,6 +70,7 @@ private:
|
||||||
// on the heap and ***DELETED WHEN REMOVED!!!!!***
|
// on the heap and ***DELETED WHEN REMOVED!!!!!***
|
||||||
ai_list_type ai_list;
|
ai_list_type ai_list;
|
||||||
ai_list_iterator ai_list_itr;
|
ai_list_iterator ai_list_itr;
|
||||||
|
ModelVec loadedModels;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
@ -63,7 +83,7 @@ public:
|
||||||
void update(double dt);
|
void update(double dt);
|
||||||
|
|
||||||
void* createBallistic( FGAIModelEntity *entity );
|
void* createBallistic( FGAIModelEntity *entity );
|
||||||
void* createAircraft( FGAIModelEntity *entity );
|
void* createAircraft( FGAIModelEntity *entity, FGAISchedule *ref=0 );
|
||||||
void* createThermal( FGAIModelEntity *entity );
|
void* createThermal( FGAIModelEntity *entity );
|
||||||
void* createStorm( FGAIModelEntity *entity );
|
void* createStorm( FGAIModelEntity *entity );
|
||||||
void* createShip( FGAIModelEntity *entity );
|
void* createShip( FGAIModelEntity *entity );
|
||||||
|
@ -85,6 +105,9 @@ public:
|
||||||
|
|
||||||
void processScenario( string &filename );
|
void processScenario( string &filename );
|
||||||
|
|
||||||
|
ssgBranch * getModel(const string& path);
|
||||||
|
void setModel(const string& path, ssgBranch *model);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
bool initDone;
|
bool initDone;
|
||||||
|
|
|
@ -167,7 +167,6 @@ bool FGRunwayList::search( const string& aptid, const string& rwyno,
|
||||||
}
|
}
|
||||||
revrwyno = GetReverseRunwayNo(runwayno);
|
revrwyno = GetReverseRunwayNo(runwayno);
|
||||||
}
|
}
|
||||||
|
|
||||||
runway_map_iterator pos;
|
runway_map_iterator pos;
|
||||||
for ( pos = runways.lower_bound( aptid );
|
for ( pos = runways.lower_bound( aptid );
|
||||||
pos != runways.upper_bound( aptid ); ++pos)
|
pos != runways.upper_bound( aptid ); ++pos)
|
||||||
|
|
|
@ -155,6 +155,14 @@ void FGAISchedule::update(time_t now)
|
||||||
// of the first listed flight.
|
// of the first listed flight.
|
||||||
sort(flights.begin(), flights.end());
|
sort(flights.begin(), flights.end());
|
||||||
FGScheduledFlightVecIterator i = flights.begin();
|
FGScheduledFlightVecIterator i = flights.begin();
|
||||||
|
if (AIManagerRef)
|
||||||
|
{
|
||||||
|
// Check if this aircraft has been released.
|
||||||
|
FGTrafficManager *tmgr = (FGTrafficManager *) globals->get_subsystem("Traffic Manager");
|
||||||
|
if (tmgr->isReleased(AIManagerRef))
|
||||||
|
AIManagerRef = 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (!AIManagerRef)
|
if (!AIManagerRef)
|
||||||
{
|
{
|
||||||
userLatitude = fgGetDouble("/position/latitude-deg");
|
userLatitude = fgGetDouble("/position/latitude-deg");
|
||||||
|
@ -173,7 +181,11 @@ void FGAISchedule::update(time_t now)
|
||||||
// This flight is in progress, so we need to calculate it's
|
// This flight is in progress, so we need to calculate it's
|
||||||
// approximate position and -if in range- create an AIAircraft
|
// approximate position and -if in range- create an AIAircraft
|
||||||
// object for it.
|
// object for it.
|
||||||
if ((i->getDepartureTime() < now) && (i->getArrivalTime() > now))
|
//if ((i->getDepartureTime() < now) && (i->getArrivalTime() > now))
|
||||||
|
|
||||||
|
|
||||||
|
// Part of this flight is in the future.
|
||||||
|
if (i->getArrivalTime() > now)
|
||||||
{
|
{
|
||||||
dep = i->getDepartureAirport();
|
dep = i->getDepartureAirport();
|
||||||
arr = i->getArrivalAirport ();
|
arr = i->getArrivalAirport ();
|
||||||
|
@ -205,6 +217,7 @@ void FGAISchedule::update(time_t now)
|
||||||
// arrival airport, in degrees. From here we can interpolate the
|
// arrival airport, in degrees. From here we can interpolate the
|
||||||
// position of the aircraft by calculating the ratio between
|
// position of the aircraft by calculating the ratio between
|
||||||
// total time enroute and elapsed time enroute.
|
// total time enroute and elapsed time enroute.
|
||||||
|
|
||||||
totalTimeEnroute = i->getArrivalTime() - i->getDepartureTime();
|
totalTimeEnroute = i->getArrivalTime() - i->getDepartureTime();
|
||||||
elapsedTimeEnroute = now - i->getDepartureTime();
|
elapsedTimeEnroute = now - i->getDepartureTime();
|
||||||
remainingTimeEnroute = i->getArrivalTime() - now;
|
remainingTimeEnroute = i->getArrivalTime() - now;
|
||||||
|
@ -226,8 +239,20 @@ void FGAISchedule::update(time_t now)
|
||||||
|
|
||||||
temp = sgCartToPolar3d(Point3D(newPos[0], newPos[1],newPos[2]));
|
temp = sgCartToPolar3d(Point3D(newPos[0], newPos[1],newPos[2]));
|
||||||
|
|
||||||
lat = temp.lat() * SG_RADIANS_TO_DEGREES;
|
if (now > i->getDepartureTime())
|
||||||
lon = temp.lon() * SG_RADIANS_TO_DEGREES;
|
{
|
||||||
|
//cerr << "Lat = " << lat << ", lon = " << lon << endl;
|
||||||
|
//cerr << "Time diff: " << now-i->getDepartureTime() << endl;
|
||||||
|
lat = temp.lat() * SG_RADIANS_TO_DEGREES;
|
||||||
|
lon = temp.lon() * SG_RADIANS_TO_DEGREES;
|
||||||
|
//err << "Lat = " << lat << ", lon = " << lon << endl;
|
||||||
|
//cerr << "Time diff: " << now-i->getDepartureTime() << endl;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
lat = dep->latitude;
|
||||||
|
lon = dep->longitude;
|
||||||
|
}
|
||||||
|
|
||||||
SGWayPoint current (lon,
|
SGWayPoint current (lon,
|
||||||
lat,
|
lat,
|
||||||
|
@ -240,8 +265,8 @@ void FGAISchedule::update(time_t now)
|
||||||
i->getCruiseAlt());
|
i->getCruiseAlt());
|
||||||
// We really only need distance to user
|
// We really only need distance to user
|
||||||
// and course to destination
|
// and course to destination
|
||||||
current.CourseAndDistance(user, &courseToUser, &distanceToUser);
|
user.CourseAndDistance(current, &courseToUser, &distanceToUser);
|
||||||
current.CourseAndDistance(dest, &courseToDest, &distanceToDest);
|
dest.CourseAndDistance(current, &courseToDest, &distanceToDest);
|
||||||
speed = (distanceToDest*SG_METER_TO_NM) /
|
speed = (distanceToDest*SG_METER_TO_NM) /
|
||||||
((double) remainingTimeEnroute/3600.0);
|
((double) remainingTimeEnroute/3600.0);
|
||||||
|
|
||||||
|
@ -257,6 +282,15 @@ void FGAISchedule::update(time_t now)
|
||||||
{
|
{
|
||||||
string flightPlanName = dep->id + string("-") + arr->id +
|
string flightPlanName = dep->id + string("-") + arr->id +
|
||||||
string(".xml");
|
string(".xml");
|
||||||
|
int alt;
|
||||||
|
//if ((i->getDepartureTime() < now))
|
||||||
|
//{
|
||||||
|
// alt = i->getCruiseAlt() *100;
|
||||||
|
// }
|
||||||
|
//else
|
||||||
|
//{
|
||||||
|
// alt = dep->elevation+19;
|
||||||
|
// }
|
||||||
|
|
||||||
FGAIModelEntity entity;
|
FGAIModelEntity entity;
|
||||||
|
|
||||||
|
@ -265,13 +299,13 @@ void FGAISchedule::update(time_t now)
|
||||||
entity.flightplan = flightPlanName.c_str();
|
entity.flightplan = flightPlanName.c_str();
|
||||||
entity.latitude = lat;
|
entity.latitude = lat;
|
||||||
entity.longitude = lon;
|
entity.longitude = lon;
|
||||||
entity.altitude = i->getCruiseAlt() * 100; // convert from FL to feet
|
entity.altitude = i->getCruiseAlt() *100; // convert from FL to feet
|
||||||
entity.speed = 450;
|
entity.speed = 450;
|
||||||
entity.fp = new FGAIFlightPlan(&entity, courseToDest, dep, arr);
|
entity.fp = new FGAIFlightPlan(&entity, courseToDest, i->getDepartureTime(), dep, arr);
|
||||||
|
|
||||||
// Fixme: A non-existent model path results in an
|
// Fixme: A non-existent model path results in an
|
||||||
// abort, due to an unhandled exeption, in fg main loop.
|
// abort, due to an unhandled exeption, in fg main loop.
|
||||||
AIManagerRef = aimgr->createAircraft( &entity );
|
AIManagerRef = aimgr->createAircraft( &entity, this);
|
||||||
//cerr << "Created: " << AIManagerRef << endl;
|
//cerr << "Created: " << AIManagerRef << endl;
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
@ -279,7 +313,7 @@ void FGAISchedule::update(time_t now)
|
||||||
|
|
||||||
// Both departure and arrival time are in the future, so this
|
// Both departure and arrival time are in the future, so this
|
||||||
// the aircraft is parked at the departure airport.
|
// the aircraft is parked at the departure airport.
|
||||||
// Currently this status is mostly ignored, but in furture
|
// Currently this status is mostly ignored, but in future
|
||||||
// versions, code should go here that -if within user range-
|
// versions, code should go here that -if within user range-
|
||||||
// positions these aircraft at parking locations at the airport.
|
// positions these aircraft at parking locations at the airport.
|
||||||
if ((i->getDepartureTime() > now) && (i->getArrivalTime() > now))
|
if ((i->getDepartureTime() > now) && (i->getArrivalTime() > now))
|
||||||
|
@ -289,3 +323,11 @@ void FGAISchedule::update(time_t now)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void FGAISchedule::next()
|
||||||
|
{
|
||||||
|
flights.begin()->update();
|
||||||
|
sort(flights.begin(), flights.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
#define _FGSCHEDULE_HXX_
|
#define _FGSCHEDULE_HXX_
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class FGAISchedule
|
class FGAISchedule
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
@ -43,6 +44,7 @@ class FGAISchedule
|
||||||
void* AIManagerRef;
|
void* AIManagerRef;
|
||||||
bool firstRun;
|
bool firstRun;
|
||||||
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
FGAISchedule(); // constructor
|
FGAISchedule(); // constructor
|
||||||
FGAISchedule(string, string, string, bool, FGScheduledFlightVec); // construct & init
|
FGAISchedule(string, string, string, bool, FGScheduledFlightVec); // construct & init
|
||||||
|
@ -51,6 +53,12 @@ class FGAISchedule
|
||||||
~FGAISchedule(); //destructor
|
~FGAISchedule(); //destructor
|
||||||
|
|
||||||
void update(time_t now);
|
void update(time_t now);
|
||||||
|
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 (); };
|
||||||
// More member functions follow later
|
// More member functions follow later
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -89,6 +89,26 @@ void FGTrafficManager::update(double something)
|
||||||
currAircraft++;
|
currAircraft++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FGTrafficManager::release(void *id)
|
||||||
|
{
|
||||||
|
releaseList.push_back(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FGTrafficManager::isReleased(void *id)
|
||||||
|
{
|
||||||
|
IdListIterator i = releaseList.begin();
|
||||||
|
while (i != releaseList.end())
|
||||||
|
{
|
||||||
|
if ((*i) == id)
|
||||||
|
{
|
||||||
|
releaseList.erase(i);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
void FGTrafficManager::startXML () {
|
void FGTrafficManager::startXML () {
|
||||||
//cout << "Start XML" << endl;
|
//cout << "Start XML" << endl;
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,6 +34,10 @@
|
||||||
#include "Schedule.hxx"
|
#include "Schedule.hxx"
|
||||||
|
|
||||||
|
|
||||||
|
typedef vector<void *> IdList;
|
||||||
|
typedef vector<void *>::iterator IdListIterator;
|
||||||
|
|
||||||
|
|
||||||
class FGTrafficManager : public SGSubsystem, public XMLVisitor
|
class FGTrafficManager : public SGSubsystem, public XMLVisitor
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
@ -46,6 +50,8 @@ private:
|
||||||
repeat;
|
repeat;
|
||||||
int cruiseAlt;
|
int cruiseAlt;
|
||||||
bool heavy;
|
bool heavy;
|
||||||
|
|
||||||
|
IdList releaseList;
|
||||||
|
|
||||||
FGScheduledFlightVec flights;
|
FGScheduledFlightVec flights;
|
||||||
|
|
||||||
|
@ -54,6 +60,8 @@ public:
|
||||||
|
|
||||||
void init();
|
void init();
|
||||||
void update(double time);
|
void update(double time);
|
||||||
|
void release(void *ref);
|
||||||
|
bool isReleased(void *id);
|
||||||
|
|
||||||
// Some overloaded virtual XMLVisitor members
|
// Some overloaded virtual XMLVisitor members
|
||||||
virtual void startXML ();
|
virtual void startXML ();
|
||||||
|
|
Loading…
Add table
Reference in a new issue