1
0
Fork 0

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:
ehofman 2004-11-29 09:41:43 +00:00
parent ffafb573b2
commit c537267f96
13 changed files with 284 additions and 42 deletions

View file

@ -51,7 +51,8 @@ const FGAIAircraft::PERF_STRUCT FGAIAircraft::settings[] = {
};
FGAIAircraft::FGAIAircraft(FGAIManager* mgr) {
FGAIAircraft::FGAIAircraft(FGAIManager* mgr, FGAISchedule *ref) {
trafficRef = ref;
manager = mgr;
_type_str = "aircraft";
_otype = otAircraft;
@ -114,7 +115,14 @@ void FGAIAircraft::Run(double 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_circum_ft;
@ -295,6 +303,8 @@ void FGAIAircraft::SetFlightPlan(FGAIFlightPlan *f) {
}
void FGAIAircraft::ProcessFlightPlan( double dt ) {
FGAIFlightPlan::waypoint* prev = 0; // the one behind you
FGAIFlightPlan::waypoint* curr = 0; // the one ahead
FGAIFlightPlan::waypoint* next = 0; // the next plus 1
@ -348,9 +358,34 @@ void FGAIAircraft::ProcessFlightPlan( double dt ) {
if ( dist_to_go < lead_dist ) {
if (curr->finished) { //end of the flight plan, so terminate
if (trafficRef)
{
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
if (next) tgt_heading = fp->getBearing(curr, next);
fp->IncrementWaypoint();
@ -386,6 +421,7 @@ void FGAIAircraft::ProcessFlightPlan( double dt ) {
}
bool FGAIAircraft::_getGearDown() const {
return ((props->getFloatValue("position/altitude-agl-ft") < 900.0)
&& (props->getFloatValue("velocities/airspeed-kt")

View file

@ -24,6 +24,9 @@
#include "AIManager.hxx"
#include "AIBase.hxx"
#include <Traffic/SchedFlight.hxx>
#include <Traffic/Schedule.hxx>
#include <string>
SG_USING_STD(string);
@ -49,7 +52,7 @@ public:
enum aircraft_e {LIGHT=0, WW2_FIGHTER, JET_TRANSPORT, JET_FIGHTER, TANKER};
static const PERF_STRUCT settings[];
FGAIAircraft(FGAIManager* mgr);
FGAIAircraft(FGAIManager* mgr, FGAISchedule *ref=0);
~FGAIAircraft();
bool init();
@ -70,6 +73,7 @@ public:
inline void SetTanker(bool setting) { isTanker = setting; };
private:
FGAISchedule *trafficRef;
bool hdg_lock;
bool alt_lock;

View file

@ -136,7 +136,7 @@ bool FGAIBase::init() {
props = root->getNode(_type_str.c_str(), index, true);
if (model_path != "") {
model = sgLoad3DModel( globals->get_fg_root(),
model = load3DModel( globals->get_fg_root(),
model_path.c_str(),
props,
globals->get_sim_time_sec() );
@ -157,6 +157,36 @@ bool FGAIBase::init() {
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 ) {
if ( otype == _otype ) { return true; }
else { return false; }

View file

@ -202,6 +202,10 @@ public:
int _getID() const;
inline double _getRange() { return range; };
ssgBranch * load3DModel(const string& fg_root,
const string &path,
SGPropertyNode *prop_root,
double sim_time_sec);
static bool _isNight();
};

View file

@ -44,6 +44,7 @@
FGAIFlightPlan::FGAIFlightPlan(string filename)
{
int i;
start_time = 0;
SGPath path( globals->get_fg_root() );
path.append( ("/Data/AI/FlightPlans/" + filename).c_str() );
SGPropertyNode root;
@ -91,9 +92,11 @@ FGAIFlightPlan::FGAIFlightPlan(string filename)
// traffic manager.
FGAIFlightPlan::FGAIFlightPlan(FGAIModelEntity *entity,
double course,
time_t start,
FGAirport *dep,
FGAirport *arr)
{
start_time = start;
bool useInitialWayPoint = true;
bool useCurrentWayPoint = false;
SGPath path( globals->get_fg_root() );
@ -101,6 +104,18 @@ FGAIFlightPlan::FGAIFlightPlan(FGAIModelEntity *entity,
path.append( entity->path );
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 {
readProperties(path.str(), &root);
@ -160,7 +175,7 @@ FGAIFlightPlan::FGAIFlightPlan(FGAIModelEntity *entity,
(*i)->altitude);
double crse, crsDiff;
double dist;
first.CourseAndDistance(curr, &crse, &dist);
curr.CourseAndDistance(first, &crse, &dist);
dist *= SG_METER_TO_NM;
@ -192,10 +207,14 @@ FGAIFlightPlan::FGAIFlightPlan(FGAIModelEntity *entity,
{
if ((dist > 100.0) && (useInitialWayPoint))
{
//waypoints.push_back(init_waypoint);
//waypoints.push_back(init_waypoint);;
waypoints.insert(i, init_waypoint);
//cerr << "Using waypoint : " << init_waypoint->name << endl;
}
//if (useInitialWayPoint)
// {
// (*i)->speed = dist; // A hack
// }
//waypoints.push_back( wpt );
//cerr << "Using waypoint : " << (*i)->name
// << ": course diff : " << crsDiff
@ -345,6 +364,9 @@ void FGAIFlightPlan::create(FGAirport *dep, FGAirport *arr, double alt, double s
double wind_speed;
double wind_heading;
FGRunway rwy;
double lat, lon, az;
double lat2, lon2, az2;
int direction;
//waypoints.push_back(wpt);
// Create the outbound taxi leg, for now simplified as a
@ -352,16 +374,22 @@ void FGAIFlightPlan::create(FGAirport *dep, FGAirport *arr, double alt, double s
// of the runway.
///////////////////////////////////////////////////////////
//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;
wpt->name = dep->id; //wpt_node->getStringValue("name", "END");
wpt->latitude = dep->latitude;
wpt->longitude = dep->longitude;
wpt->latitude = lat2;
wpt->longitude = lon2;
wpt->altitude = dep->elevation + 19; // probably need to add some model height to it
wpt->speed = 15;
wpt->crossat = -10000;
wpt->gear_down = true;
wpt->flaps_down= true;
wpt->finished = false;
wpt->on_ground = true;
waypoints.push_back(wpt);
// 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);
}
double lat, lon, az;
double lat2, lon2, az2;
double heading = rwy.heading;
double azimuth = heading + 180.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);
//Runway Threshold
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 );
wpt = new waypoint;
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->flaps_down= true;
wpt->finished = false;
wpt->on_ground = false;
wpt->on_ground = true;
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
wpt = new waypoint;
wpt->name = arr->id; //wpt_node->getStringValue("name", "END");
wpt->latitude = arr->latitude;
wpt->longitude = arr->longitude;
wpt->latitude = lat2;
wpt->longitude = lon2;
wpt->altitude = arr->elevation+19;
wpt->speed = 15;
wpt->crossat = -10000;
wpt->gear_down = true;
wpt->flaps_down= true;
wpt->finished = false;
wpt->on_ground = false;
wpt->on_ground = true;
waypoints.push_back(wpt);
// And finally one more named "END"
wpt = new waypoint;
wpt->name = "END"; //wpt_node->getStringValue("name", "END");
wpt->latitude = arr->latitude;
wpt->longitude = arr->longitude;
wpt->latitude = lat2;
wpt->longitude = lon2;
wpt->altitude = 19;
wpt->speed = 15;
wpt->crossat = -10000;
@ -609,14 +641,14 @@ void FGAIFlightPlan::create(FGAirport *dep, FGAirport *arr, double alt, double s
// And finally one more named "EOF"
wpt = new waypoint;
wpt->name = "EOF"; //wpt_node->getStringValue("name", "END");
wpt->latitude = arr->latitude;
wpt->longitude = arr->longitude;
wpt->latitude = lat2;
wpt->longitude = lon2;
wpt->altitude = 19;
wpt->speed = 15;
wpt->crossat = -10000;
wpt->gear_down = true;
wpt->flaps_down= true;
wpt->finished = true;
wpt->finished = true;
wpt->on_ground = true;
waypoints.push_back(wpt);
}

View file

@ -51,6 +51,7 @@ public:
FGAIFlightPlan(string filename);
FGAIFlightPlan(FGAIModelEntity *entity,
double course,
time_t start,
FGAirport *dep,
FGAirport *arr);
~FGAIFlightPlan();
@ -66,6 +67,7 @@ public:
double getLeadDistance( void ) const {return lead_distance;}
double getBearing(waypoint* previous, 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);
@ -79,6 +81,7 @@ private:
double distance_to_go;
double lead_distance;
time_t start_time;
};

View file

@ -22,6 +22,11 @@
#include <Main/fg_props.hxx>
#include <Main/globals.hxx>
#include <Airports/simple.hxx>
#include <Traffic/SchedFlight.hxx>
#include <Traffic/Schedule.hxx>
#include <Traffic/TrafficMgr.hxx>
#include <list>
#include "AIManager.hxx"
@ -53,6 +58,11 @@ FGAIManager::~FGAIManager() {
++ai_list_itr;
}
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
range_nearest = 10000.0;
strength = 0.0;
FGTrafficManager *tmgr = (FGTrafficManager*) globals->get_subsystem("Traffic Manager");
if (!enabled)
return;
@ -97,6 +108,7 @@ void FGAIManager::update(double dt) {
ai_list_itr = ai_list.begin();
while(ai_list_itr != ai_list.end()) {
if ((*ai_list_itr)->getDie()) {
tmgr->release((*ai_list_itr)->getID());
--numObjects[(*ai_list_itr)->getType()];
--numObjects[0];
(*ai_list_itr)->unbind();
@ -124,9 +136,9 @@ void FGAIManager::update(double dt) {
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);
++numObjects[0];
++numObjects[FGAIBase::otAircraft];
@ -352,4 +364,25 @@ void FGAIManager::processScenario( string &filename ) {
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

View file

@ -33,7 +33,26 @@
#include <AIModel/AIScenario.hxx>
#include <AIModel/AIFlightPlan.hxx>
#include <Traffic/SchedFlight.hxx>
#include <Traffic/Schedule.hxx>
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;
@ -51,6 +70,7 @@ private:
// on the heap and ***DELETED WHEN REMOVED!!!!!***
ai_list_type ai_list;
ai_list_iterator ai_list_itr;
ModelVec loadedModels;
public:
@ -63,7 +83,7 @@ public:
void update(double dt);
void* createBallistic( FGAIModelEntity *entity );
void* createAircraft( FGAIModelEntity *entity );
void* createAircraft( FGAIModelEntity *entity, FGAISchedule *ref=0 );
void* createThermal( FGAIModelEntity *entity );
void* createStorm( FGAIModelEntity *entity );
void* createShip( FGAIModelEntity *entity );
@ -85,6 +105,9 @@ public:
void processScenario( string &filename );
ssgBranch * getModel(const string& path);
void setModel(const string& path, ssgBranch *model);
private:
bool initDone;

View file

@ -167,7 +167,6 @@ bool FGRunwayList::search( const string& aptid, const string& rwyno,
}
revrwyno = GetReverseRunwayNo(runwayno);
}
runway_map_iterator pos;
for ( pos = runways.lower_bound( aptid );
pos != runways.upper_bound( aptid ); ++pos)

View file

@ -155,6 +155,14 @@ void FGAISchedule::update(time_t now)
// of the first listed flight.
sort(flights.begin(), flights.end());
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)
{
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
// approximate position and -if in range- create an AIAircraft
// 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();
arr = i->getArrivalAirport ();
@ -205,6 +217,7 @@ void FGAISchedule::update(time_t now)
// arrival airport, in degrees. From here we can interpolate the
// position of the aircraft by calculating the ratio between
// total time enroute and elapsed time enroute.
totalTimeEnroute = i->getArrivalTime() - i->getDepartureTime();
elapsedTimeEnroute = now - i->getDepartureTime();
remainingTimeEnroute = i->getArrivalTime() - now;
@ -226,8 +239,20 @@ void FGAISchedule::update(time_t now)
temp = sgCartToPolar3d(Point3D(newPos[0], newPos[1],newPos[2]));
if (now > i->getDepartureTime())
{
//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,
lat,
@ -240,8 +265,8 @@ void FGAISchedule::update(time_t now)
i->getCruiseAlt());
// We really only need distance to user
// and course to destination
current.CourseAndDistance(user, &courseToUser, &distanceToUser);
current.CourseAndDistance(dest, &courseToDest, &distanceToDest);
user.CourseAndDistance(current, &courseToUser, &distanceToUser);
dest.CourseAndDistance(current, &courseToDest, &distanceToDest);
speed = (distanceToDest*SG_METER_TO_NM) /
((double) remainingTimeEnroute/3600.0);
@ -257,6 +282,15 @@ void FGAISchedule::update(time_t now)
{
string flightPlanName = dep->id + string("-") + arr->id +
string(".xml");
int alt;
//if ((i->getDepartureTime() < now))
//{
// alt = i->getCruiseAlt() *100;
// }
//else
//{
// alt = dep->elevation+19;
// }
FGAIModelEntity entity;
@ -267,11 +301,11 @@ void FGAISchedule::update(time_t now)
entity.longitude = lon;
entity.altitude = i->getCruiseAlt() *100; // convert from FL to feet
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
// abort, due to an unhandled exeption, in fg main loop.
AIManagerRef = aimgr->createAircraft( &entity );
AIManagerRef = aimgr->createAircraft( &entity, this);
//cerr << "Created: " << AIManagerRef << endl;
}
return;
@ -279,7 +313,7 @@ void FGAISchedule::update(time_t now)
// Both departure and arrival time are in the future, so this
// 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-
// positions these aircraft at parking locations at the airport.
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());
}

View file

@ -30,6 +30,7 @@
#define _FGSCHEDULE_HXX_
class FGAISchedule
{
private:
@ -43,6 +44,7 @@ class FGAISchedule
void* AIManagerRef;
bool firstRun;
public:
FGAISchedule(); // constructor
FGAISchedule(string, string, string, bool, FGScheduledFlightVec); // construct & init
@ -51,6 +53,12 @@ class FGAISchedule
~FGAISchedule(); //destructor
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
};

View file

@ -89,6 +89,26 @@ void FGTrafficManager::update(double something)
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 () {
//cout << "Start XML" << endl;
}

View file

@ -34,6 +34,10 @@
#include "Schedule.hxx"
typedef vector<void *> IdList;
typedef vector<void *>::iterator IdListIterator;
class FGTrafficManager : public SGSubsystem, public XMLVisitor
{
private:
@ -47,6 +51,8 @@ private:
int cruiseAlt;
bool heavy;
IdList releaseList;
FGScheduledFlightVec flights;
public:
@ -54,6 +60,8 @@ public:
void init();
void update(double time);
void release(void *ref);
bool isReleased(void *id);
// Some overloaded virtual XMLVisitor members
virtual void startXML ();