Add the AIModel based air traffic subsystem from Durk Talsma.
This commit is contained in:
parent
9227d02aa3
commit
b3e9697262
19 changed files with 1203 additions and 41 deletions
2
Thanks
2
Thanks
|
@ -145,7 +145,7 @@ Bruce Finney <bfinney@gte.net>
|
||||||
Melchior Franz <a8603365@unet.univie.ac.at>
|
Melchior Franz <a8603365@unet.univie.ac.at>
|
||||||
Made that joystick high/low support for joystick hats.
|
Made that joystick high/low support for joystick hats.
|
||||||
Nasal-ified the Saitek Cyborg Gold 3D (USB) joystick which now forms
|
Nasal-ified the Saitek Cyborg Gold 3D (USB) joystick which now forms
|
||||||
the basis of a lot of porgrammable joysticks.
|
the basis of a lot of programmable joysticks.
|
||||||
Created the led.txf font.
|
Created the led.txf font.
|
||||||
Ruthlessly hunted down memory leaks in FlightGear, SimGear, and JSBSim.
|
Ruthlessly hunted down memory leaks in FlightGear, SimGear, and JSBSim.
|
||||||
Maintains the only fully working helicopter model in FlightGear (Bolkow 105).
|
Maintains the only fully working helicopter model in FlightGear (Bolkow 105).
|
||||||
|
|
|
@ -120,7 +120,7 @@ case "${host}" in
|
||||||
if test -d /opt/X11R6 ; then
|
if test -d /opt/X11R6 ; then
|
||||||
EXTRA_DIR2="/opt/X11R6"
|
EXTRA_DIR2="/opt/X11R6"
|
||||||
fi
|
fi
|
||||||
EXTRA_DIRS="${EXTRA_DIRS} $EXTRA_DIR1 $EXTRA_DIR2"
|
EXTRA_DIRS="${EXTRA_DIRS} $EXTRA_DIR1 $EXTRA_DIR2 /usr/local/"
|
||||||
;;
|
;;
|
||||||
|
|
||||||
esac
|
esac
|
||||||
|
@ -564,6 +564,7 @@ AC_CONFIG_FILES([ \
|
||||||
src/Sound/Makefile \
|
src/Sound/Makefile \
|
||||||
src/Systems/Makefile \
|
src/Systems/Makefile \
|
||||||
src/Time/Makefile \
|
src/Time/Makefile \
|
||||||
|
src/Traffic/Makefile \
|
||||||
tests/Makefile \
|
tests/Makefile \
|
||||||
utils/Makefile \
|
utils/Makefile \
|
||||||
utils/TerraSync/Makefile \
|
utils/TerraSync/Makefile \
|
||||||
|
|
|
@ -163,6 +163,7 @@ inline void FGAIBase::setAltitude( double altitude_ft ) {
|
||||||
|
|
||||||
inline void FGAIBase::setBank( double bank ) {
|
inline void FGAIBase::setBank( double bank ) {
|
||||||
roll = tgt_roll = bank;
|
roll = tgt_roll = bank;
|
||||||
|
no_roll = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void FGAIBase::setLongitude( double longitude ) {
|
inline void FGAIBase::setLongitude( double longitude ) {
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
#include "AIFlightPlan.hxx"
|
#include "AIFlightPlan.hxx"
|
||||||
#include <simgear/misc/sg_path.hxx>
|
#include <simgear/misc/sg_path.hxx>
|
||||||
#include <simgear/debug/logstream.hxx>
|
#include <simgear/debug/logstream.hxx>
|
||||||
|
#include <simgear/route/waypoint.hxx>
|
||||||
#include <simgear/structure/exception.hxx>
|
#include <simgear/structure/exception.hxx>
|
||||||
#include <simgear/constants.h>
|
#include <simgear/constants.h>
|
||||||
#ifdef __BORLANDC__
|
#ifdef __BORLANDC__
|
||||||
|
@ -72,6 +73,124 @@ FGAIFlightPlan::FGAIFlightPlan(string filename)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// This is a modified version of the constructor,
|
||||||
|
// Which not only reads the waypoints from a
|
||||||
|
// Flight plan file, but also adds the current
|
||||||
|
// Position computed by the traffic manager, as well
|
||||||
|
// as setting speeds and altitude computed by the
|
||||||
|
// traffic manager.
|
||||||
|
FGAIFlightPlan::FGAIFlightPlan(string filename,
|
||||||
|
double lat,
|
||||||
|
double lon,
|
||||||
|
double alt,
|
||||||
|
double speed,
|
||||||
|
double course)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
bool useInitialWayPoint = true;
|
||||||
|
SGPath path( globals->get_fg_root() );
|
||||||
|
path.append( ("/Data/AI/FlightPlans/" + filename).c_str() );
|
||||||
|
SGPropertyNode root;
|
||||||
|
|
||||||
|
try {
|
||||||
|
readProperties(path.str(), &root);
|
||||||
|
} catch (const sg_exception &e) {
|
||||||
|
SG_LOG(SG_GENERAL, SG_ALERT,
|
||||||
|
"Error reading AI flight plan: ");
|
||||||
|
cout << path.str() << endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
SGPropertyNode * node = root.getNode("flightplan");
|
||||||
|
// First waypoint is current position of the aircraft as
|
||||||
|
// dictated by the traffic manager.
|
||||||
|
waypoint* init_waypoint = new waypoint;
|
||||||
|
init_waypoint->name = string("initial position");
|
||||||
|
init_waypoint->latitude = lat;
|
||||||
|
init_waypoint->longitude = lon;
|
||||||
|
init_waypoint->altitude = alt;
|
||||||
|
init_waypoint->speed = speed;
|
||||||
|
init_waypoint->crossat = - 10000;
|
||||||
|
init_waypoint->gear_down = false;
|
||||||
|
init_waypoint->flaps_down = false;
|
||||||
|
waypoints.push_back( init_waypoint );
|
||||||
|
for (i = 0; i < node->nChildren(); i++) {
|
||||||
|
//cout << "Reading waypoint " << i << endl;
|
||||||
|
waypoint* wpt = new waypoint;
|
||||||
|
SGPropertyNode * wpt_node = node->getChild(i);
|
||||||
|
wpt->name = wpt_node->getStringValue("name", "END");
|
||||||
|
wpt->latitude = wpt_node->getDoubleValue("lat", 0);
|
||||||
|
wpt->longitude = wpt_node->getDoubleValue("lon", 0);
|
||||||
|
wpt->altitude = wpt_node->getDoubleValue("alt", 0);
|
||||||
|
wpt->speed = wpt_node->getDoubleValue("ktas", 0);
|
||||||
|
//wpt->speed = speed;
|
||||||
|
wpt->crossat = wpt_node->getDoubleValue("crossat", -10000);
|
||||||
|
wpt->gear_down = wpt_node->getBoolValue("gear-down", false);
|
||||||
|
wpt->flaps_down= wpt_node->getBoolValue("flaps-down", false);
|
||||||
|
|
||||||
|
if (wpt->name == "END") wpt->finished = true;
|
||||||
|
else wpt->finished = false;
|
||||||
|
// discard this waypoint if it's bearing differs more than
|
||||||
|
// 90 degrees from the course we should fly according to the
|
||||||
|
// Traffic manager. Those are considered "behind" us.
|
||||||
|
SGWayPoint first(init_waypoint->longitude,
|
||||||
|
init_waypoint->latitude,
|
||||||
|
init_waypoint->altitude);
|
||||||
|
SGWayPoint curr (wpt->longitude,
|
||||||
|
wpt->latitude,
|
||||||
|
wpt->altitude);
|
||||||
|
double crse, crsDiff;
|
||||||
|
double dist;
|
||||||
|
first.CourseAndDistance(curr, &crse, &dist);
|
||||||
|
|
||||||
|
dist *= SG_METER_TO_NM;
|
||||||
|
|
||||||
|
// We're only interested in the absolute value of crsDiff
|
||||||
|
// wich should fall in the 0-180 deg range.
|
||||||
|
crsDiff = fabs(crse-course);
|
||||||
|
if (crsDiff > 180)
|
||||||
|
crsDiff -= 180;
|
||||||
|
// These are the threee conditions that we consder including
|
||||||
|
// in our flight plan:
|
||||||
|
// 1) current waypoint is less then 100 miles away OR
|
||||||
|
// 2) curren waypoint is ahead of us, at any distance
|
||||||
|
bool useWpt = false;
|
||||||
|
if ((dist > 100.0) && (crsDiff > 90.0) && (wpt->name != string ("EOF")))
|
||||||
|
{
|
||||||
|
//useWpt = false;
|
||||||
|
// Once we start including waypoints, we have to continue, even though
|
||||||
|
// one of the following way point would suffice.
|
||||||
|
// so once is the useWpt flag is set to true, we cannot reset it to false.
|
||||||
|
// cerr << "Discarding waypoint: " << wpt->name
|
||||||
|
// << ": Course difference = " << crsDiff << endl;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
useWpt = true;
|
||||||
|
|
||||||
|
if (useWpt)
|
||||||
|
{
|
||||||
|
if ((dist > 100.0) && (useInitialWayPoint))
|
||||||
|
{
|
||||||
|
waypoints.push_back(init_waypoint);
|
||||||
|
//cerr << "Using waypoint : " << init_waypoint->name << endl;
|
||||||
|
}
|
||||||
|
waypoints.push_back( wpt );
|
||||||
|
//cerr << "Using waypoint : " << wpt->name
|
||||||
|
// << ": course diff : " << crsDiff
|
||||||
|
// << "distance : " << dist << endl;
|
||||||
|
useInitialWayPoint = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
delete wpt;
|
||||||
|
}
|
||||||
|
|
||||||
|
wpt_iterator = waypoints.begin();
|
||||||
|
//cout << waypoints.size() << " waypoints read." << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
FGAIFlightPlan::~FGAIFlightPlan()
|
FGAIFlightPlan::~FGAIFlightPlan()
|
||||||
{
|
{
|
||||||
waypoints.clear();
|
waypoints.clear();
|
||||||
|
@ -144,32 +263,41 @@ double FGAIFlightPlan::getBearing(waypoint* first, waypoint* second){
|
||||||
|
|
||||||
|
|
||||||
double FGAIFlightPlan::getBearing(double lat, double lon, waypoint* wp){
|
double FGAIFlightPlan::getBearing(double lat, double lon, waypoint* wp){
|
||||||
double latd = lat;
|
double course, distance;
|
||||||
double lond = lon;
|
// double latd = lat;
|
||||||
double latt = wp->latitude;
|
// double lond = lon;
|
||||||
double lont = wp->longitude;
|
// double latt = wp->latitude;
|
||||||
double ft_per_deg_lat = 366468.96 - 3717.12 * cos(lat/SG_RADIANS_TO_DEGREES);
|
// double lont = wp->longitude;
|
||||||
double ft_per_deg_lon = 365228.16 * cos(lat/SG_RADIANS_TO_DEGREES);
|
// double ft_per_deg_lat = 366468.96 - 3717.12 * cos(lat/SG_RADIANS_TO_DEGREES);
|
||||||
|
// double ft_per_deg_lon = 365228.16 * cos(lat/SG_RADIANS_TO_DEGREES);
|
||||||
|
|
||||||
if (lond < 0.0) lond+=360.0;
|
// if (lond < 0.0) {
|
||||||
if (lont < 0.0) lont+=360.0;
|
// lond+=360.0;
|
||||||
latd+=90.0;
|
// lont+=360;
|
||||||
latt+=90.0;
|
// }
|
||||||
|
// if (lont < 0.0) {
|
||||||
|
// lond+=360.0;
|
||||||
|
// lont+=360.0;
|
||||||
|
// }
|
||||||
|
// latd+=90.0;
|
||||||
|
// latt+=90.0;
|
||||||
|
|
||||||
double lat_diff = (latt - latd) * ft_per_deg_lat;
|
// double lat_diff = (latt - latd) * ft_per_deg_lat;
|
||||||
double lon_diff = (lont - lond) * ft_per_deg_lon;
|
// double lon_diff = (lont - lond) * ft_per_deg_lon;
|
||||||
double angle = atan(fabs(lat_diff / lon_diff)) * SG_RADIANS_TO_DEGREES;
|
// double angle = atan(fabs(lat_diff / lon_diff)) * SG_RADIANS_TO_DEGREES;
|
||||||
|
|
||||||
bool southerly = true;
|
|
||||||
if (latt > latd) southerly = false;
|
|
||||||
bool easterly = false;
|
|
||||||
if (lont > lond) easterly = true;
|
|
||||||
if (southerly && easterly) return 90.0 + angle;
|
|
||||||
if (!southerly && easterly) return 90.0 - angle;
|
|
||||||
if (southerly && !easterly) return 270.0 - angle;
|
|
||||||
if (!southerly && !easterly) return 270.0 + angle;
|
|
||||||
|
|
||||||
|
// bool southerly = true;
|
||||||
|
// if (latt > latd) southerly = false;
|
||||||
|
// bool easterly = false;
|
||||||
|
// if (lont > lond) easterly = true;
|
||||||
|
// if (southerly && easterly) return 90.0 + angle;
|
||||||
|
// if (!southerly && easterly) return 90.0 - angle;
|
||||||
|
// if (southerly && !easterly) return 270.0 - angle;
|
||||||
|
// if (!southerly && !easterly) return 270.0 + angle;
|
||||||
|
SGWayPoint sgWp(wp->longitude,wp->latitude, wp->altitude, SGWayPoint::WGS84, string("temp"));
|
||||||
|
sgWp.CourseAndDistance(lon, lat, wp->altitude, &course, &distance);
|
||||||
|
return course;
|
||||||
// Omit a compiler warning.
|
// Omit a compiler warning.
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -44,6 +44,12 @@ public:
|
||||||
} waypoint;
|
} waypoint;
|
||||||
|
|
||||||
FGAIFlightPlan(string filename);
|
FGAIFlightPlan(string filename);
|
||||||
|
FGAIFlightPlan(string filename,
|
||||||
|
double lat,
|
||||||
|
double lon,
|
||||||
|
double alt,
|
||||||
|
double speed,
|
||||||
|
double course);
|
||||||
~FGAIFlightPlan();
|
~FGAIFlightPlan();
|
||||||
|
|
||||||
waypoint* getPreviousWaypoint( void );
|
waypoint* getPreviousWaypoint( void );
|
||||||
|
|
|
@ -123,7 +123,7 @@ int FGAIManager::assignID() {
|
||||||
int maxint = 30000;
|
int maxint = 30000;
|
||||||
int x;
|
int x;
|
||||||
bool used;
|
bool used;
|
||||||
for (x=0; x<maxint; x++) {
|
for (x=1; x<maxint; x++) {
|
||||||
used = false;
|
used = false;
|
||||||
id_itr = ids.begin();
|
id_itr = ids.begin();
|
||||||
while( id_itr != ids.end() ) {
|
while( id_itr != ids.end() ) {
|
||||||
|
|
|
@ -67,8 +67,8 @@ FGAIScenario::FGAIScenario(string filename)
|
||||||
en->azimuth = entry_node->getDoubleValue("azimuth", 0.0);
|
en->azimuth = entry_node->getDoubleValue("azimuth", 0.0);
|
||||||
en->elevation = entry_node->getDoubleValue("elevation", 0.0);
|
en->elevation = entry_node->getDoubleValue("elevation", 0.0);
|
||||||
en->rudder = entry_node->getDoubleValue("rudder", 0.0);
|
en->rudder = entry_node->getDoubleValue("rudder", 0.0);
|
||||||
en->strength = entry_node->getDoubleValue("strength", 0.0);
|
en->strength = entry_node->getDoubleValue("strength-fps", 0.0);
|
||||||
en->diameter = entry_node->getDoubleValue("diameter", 0.0);
|
en->diameter = entry_node->getDoubleValue("diameter-ft", 0.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
entry_iterator = entries.begin();
|
entry_iterator = entries.begin();
|
||||||
|
|
|
@ -291,6 +291,7 @@ void FGTrimAxis::SetThetaOnGround(double ff) {
|
||||||
bool FGTrimAxis::initTheta(void) {
|
bool FGTrimAxis::initTheta(void) {
|
||||||
int i,N,iAft, iForward;
|
int i,N,iAft, iForward;
|
||||||
double zAft,zForward,zDiff,theta;
|
double zAft,zForward,zDiff,theta;
|
||||||
|
double xAft,xForward,xDiff;
|
||||||
bool level;
|
bool level;
|
||||||
double saveAlt;
|
double saveAlt;
|
||||||
|
|
||||||
|
@ -317,17 +318,25 @@ bool FGTrimAxis::initTheta(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// now adjust theta till the wheels are the same distance from the ground
|
// now adjust theta till the wheels are the same distance from the ground
|
||||||
zAft=fdmex->GetGroundReactions()->GetGearUnit(1)->GetLocalGear(3);
|
xAft=fdmex->GetGroundReactions()->GetGearUnit(iAft)->GetLocalGear(1);
|
||||||
zForward=fdmex->GetGroundReactions()->GetGearUnit(0)->GetLocalGear(3);
|
xForward=fdmex->GetGroundReactions()->GetGearUnit(iForward)->GetLocalGear(1);
|
||||||
zDiff = zForward - zAft;
|
xDiff = xForward - xAft;
|
||||||
level=false;
|
zAft=fdmex->GetGroundReactions()->GetGearUnit(iAft)->GetLocalGear(3);
|
||||||
theta=fgic->GetPitchAngleDegIC();
|
zForward=fdmex->GetGroundReactions()->GetGearUnit(iForward)->GetLocalGear(3);
|
||||||
while(!level && (i < 100)) {
|
zDiff = zForward - zAft;
|
||||||
theta+=2.0*zDiff;
|
level=false;
|
||||||
fgic->SetPitchAngleDegIC(theta);
|
theta=fgic->GetPitchAngleDegIC();
|
||||||
fdmex->RunIC();
|
while(!level && (i < 100)) {
|
||||||
zAft=fdmex->GetGroundReactions()->GetGearUnit(iAft)->GetLocalGear(3);
|
theta+=180.0/M_PI*zDiff/fabs(xDiff);
|
||||||
zForward=fdmex->GetGroundReactions()->GetGearUnit(iForward)->GetLocalGear(3);
|
fgic->SetPitchAngleDegIC(theta);
|
||||||
|
fdmex->RunIC();
|
||||||
|
xAft=fdmex->GetGroundReactions()->GetGearUnit(iAft)->GetLocalGear(1);
|
||||||
|
xForward=fdmex->GetGroundReactions()->GetGearUnit(iForward)->GetLocalGear(1);
|
||||||
|
xDiff = xForward - xAft;
|
||||||
|
zAft=fdmex->GetGroundReactions()->GetGearUnit(iAft)->GetLocalGear(3);
|
||||||
|
zForward=fdmex->GetGroundReactions()->GetGearUnit(iForward)->GetLocalGear(3);
|
||||||
|
zDiff = zForward - zAft;
|
||||||
|
|
||||||
zDiff = zForward - zAft;
|
zDiff = zForward - zAft;
|
||||||
//cout << endl << theta << " " << zDiff << endl;
|
//cout << endl << theta << " " << zDiff << endl;
|
||||||
//cout << "0: " << fdmex->GetGroundReactions()->GetGearUnit(0)->GetLocalGear() << endl;
|
//cout << "0: " << fdmex->GetGroundReactions()->GetGearUnit(0)->GetLocalGear() << endl;
|
||||||
|
|
|
@ -83,6 +83,7 @@ fgfs_LDADD = \
|
||||||
$(top_builddir)/src/Replay/libReplay.a \
|
$(top_builddir)/src/Replay/libReplay.a \
|
||||||
$(top_builddir)/src/Systems/libSystems.a \
|
$(top_builddir)/src/Systems/libSystems.a \
|
||||||
$(top_builddir)/src/Time/libTime.a \
|
$(top_builddir)/src/Time/libTime.a \
|
||||||
|
$(top_builddir)/src/Traffic/libTraffic.a \
|
||||||
$(top_builddir)/src/Environment/libEnvironment.a \
|
$(top_builddir)/src/Environment/libEnvironment.a \
|
||||||
$(CLOUD3D_LIBS) \
|
$(CLOUD3D_LIBS) \
|
||||||
-lsgroute -lsgsky -lsgsound -lsgephem -lsgmaterial -lsgtgdb -lsgmodel \
|
-lsgroute -lsgsky -lsgsound -lsgephem -lsgmaterial -lsgtgdb -lsgmodel \
|
||||||
|
|
|
@ -111,6 +111,7 @@
|
||||||
#include <Time/sunpos.hxx>
|
#include <Time/sunpos.hxx>
|
||||||
#include <Time/sunsolver.hxx>
|
#include <Time/sunsolver.hxx>
|
||||||
#include <Time/tmp.hxx>
|
#include <Time/tmp.hxx>
|
||||||
|
#include <Traffic/TrafficMgr.hxx>
|
||||||
|
|
||||||
#ifdef FG_MPLAYER_AS
|
#ifdef FG_MPLAYER_AS
|
||||||
#include <MultiPlayer/multiplaytxmgr.hxx>
|
#include <MultiPlayer/multiplaytxmgr.hxx>
|
||||||
|
@ -1684,14 +1685,26 @@ bool fgInitSubsystems() {
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Initialise the AI Model Manager
|
// Initialise the AI Model Manager
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
SG_LOG(SG_GENERAL, SG_INFO, " AI Model Manager");
|
SG_LOG(SG_GENERAL, SG_INFO, " AI Model Manager");
|
||||||
globals->add_subsystem("ai_model", new FGAIManager);
|
globals->add_subsystem("ai_model", new FGAIManager);
|
||||||
|
|
||||||
|
|
||||||
|
// It's probably a good idea to initialize the top level traffic manager
|
||||||
|
// After the AI and ATC systems have been initialized properly.
|
||||||
|
// AI Traffic manager
|
||||||
|
globals->add_subsystem("Traffic Manager", new FGTrafficManager);
|
||||||
|
FGTrafficManager *dispatcher =
|
||||||
|
(FGTrafficManager*) globals->get_subsystem("Traffic Manager");
|
||||||
|
|
||||||
|
readXML(string(globals->get_fg_root() + string("/Traffic/fgtraffic.xml")),
|
||||||
|
*dispatcher);
|
||||||
|
globals->get_subsystem("Traffic Manager")->init();
|
||||||
|
|
||||||
globals->add_subsystem("instrumentation", new FGInstrumentMgr);
|
globals->add_subsystem("instrumentation", new FGInstrumentMgr);
|
||||||
globals->add_subsystem("systems", new FGSystemMgr);
|
globals->add_subsystem("systems", new FGSystemMgr);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Initialize the radio stack subsystem.
|
// Initialize the radio stack subsystem.
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
|
|
|
@ -62,6 +62,7 @@ class SGPropertyNode;
|
||||||
class SGTime;
|
class SGTime;
|
||||||
class SGSoundMgr;
|
class SGSoundMgr;
|
||||||
|
|
||||||
|
|
||||||
class FGAirportList;
|
class FGAirportList;
|
||||||
class FGRunwayList;
|
class FGRunwayList;
|
||||||
class FGAIMgr;
|
class FGAIMgr;
|
||||||
|
@ -69,6 +70,7 @@ class FGATCMgr;
|
||||||
class FGATCDisplay;
|
class FGATCDisplay;
|
||||||
class FGAircraftModel;
|
class FGAircraftModel;
|
||||||
class FGControls;
|
class FGControls;
|
||||||
|
class FGFlightPlanDispatcher;
|
||||||
class FGIO;
|
class FGIO;
|
||||||
class FGNavList;
|
class FGNavList;
|
||||||
class FGFixList;
|
class FGFixList;
|
||||||
|
@ -173,6 +175,8 @@ private:
|
||||||
|
|
||||||
SGModelLib *model_lib;
|
SGModelLib *model_lib;
|
||||||
|
|
||||||
|
//FGFlightPlanDispatcher *fpDispatcher;
|
||||||
|
|
||||||
FGAircraftModel *acmodel;
|
FGAircraftModel *acmodel;
|
||||||
|
|
||||||
FGModelMgr * model_mgr;
|
FGModelMgr * model_mgr;
|
||||||
|
|
|
@ -29,4 +29,5 @@ SUBDIRS = \
|
||||||
Sound \
|
Sound \
|
||||||
Systems \
|
Systems \
|
||||||
Time \
|
Time \
|
||||||
|
Traffic \
|
||||||
Main
|
Main
|
||||||
|
|
9
src/Traffic/Makefile.am
Normal file
9
src/Traffic/Makefile.am
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
noinst_LIBRARIES = libTraffic.a
|
||||||
|
|
||||||
|
libTraffic_a_SOURCES = \
|
||||||
|
SchedFlight.cxx SchedFlight.hxx \
|
||||||
|
Schedule.cxx Schedule.hxx \
|
||||||
|
TrafficMgr.cxx TrafficMgr.hxx
|
||||||
|
|
||||||
|
|
||||||
|
INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/src
|
257
src/Traffic/SchedFlight.cxx
Normal file
257
src/Traffic/SchedFlight.cxx
Normal file
|
@ -0,0 +1,257 @@
|
||||||
|
/******************************************************************************
|
||||||
|
* SchedFlight.cxx
|
||||||
|
* Written by Durk Talsma, started May 5, 2004.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License as
|
||||||
|
* published by the Free Software Foundation; either version 2 of the
|
||||||
|
* License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
/* This a prototype version of a top-level flight plan manager for Flightgear.
|
||||||
|
* It parses the fgtraffic.txt file and determine for a specific time/date,
|
||||||
|
* where each aircraft listed in this file is at the current time.
|
||||||
|
*
|
||||||
|
* I'm currently assuming the following simplifications:
|
||||||
|
* 1) The earth is a perfect sphere
|
||||||
|
* 2) Each aircraft flies a perfect great circle route.
|
||||||
|
* 3) Each aircraft flies at a constant speed (with infinite accelerations and
|
||||||
|
* decelerations)
|
||||||
|
* 4) Each aircraft leaves at exactly the departure time.
|
||||||
|
* 5) Each aircraft arrives at exactly the specified arrival time.
|
||||||
|
*
|
||||||
|
* TODO:
|
||||||
|
* - Check the code for known portability issues
|
||||||
|
* - Find an alternative for the depricated Point3D class
|
||||||
|
*
|
||||||
|
*****************************************************************************/
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <iostream>
|
||||||
|
#include <fstream>
|
||||||
|
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include <plib/sg.h>
|
||||||
|
|
||||||
|
#include <simgear/compiler.h>
|
||||||
|
#include <simgear/math/polar3d.hxx>
|
||||||
|
#include <simgear/math/sg_geodesy.hxx>
|
||||||
|
#include <simgear/props/props.hxx>
|
||||||
|
#include <simgear/route/waypoint.hxx>
|
||||||
|
#include <simgear/structure/subsystem_mgr.hxx>
|
||||||
|
#include <simgear/timing/sg_time.hxx>
|
||||||
|
#include <simgear/xml/easyxml.hxx>
|
||||||
|
|
||||||
|
#include <AIModel/AIFlightPlan.hxx>
|
||||||
|
#include <AIModel/AIManager.hxx>
|
||||||
|
#include <Airports/simple.hxx>
|
||||||
|
#include <Main/fg_init.hxx> // That's pretty ugly, but I need fgFindAirportID
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#include <Main/globals.hxx>
|
||||||
|
|
||||||
|
#include "SchedFlight.hxx"
|
||||||
|
|
||||||
|
|
||||||
|
/******************************************************************************
|
||||||
|
* FGScheduledFlight stuff
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
FGScheduledFlight::FGScheduledFlight()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
FGScheduledFlight::FGScheduledFlight(const FGScheduledFlight &other)
|
||||||
|
{
|
||||||
|
callsign = other.callsign;
|
||||||
|
fltRules = other.fltRules;
|
||||||
|
departurePort = other.departurePort;
|
||||||
|
departureTime = other.departureTime;
|
||||||
|
cruiseAltitude = other.cruiseAltitude;
|
||||||
|
arrivalPort = other.arrivalPort;
|
||||||
|
arrivalTime = other.arrivalTime;
|
||||||
|
repeatPeriod = other.repeatPeriod;
|
||||||
|
initialized = other.initialized;
|
||||||
|
}
|
||||||
|
|
||||||
|
FGScheduledFlight::FGScheduledFlight(string cs,
|
||||||
|
string fr,
|
||||||
|
string depPrt,
|
||||||
|
string arrPrt,
|
||||||
|
int cruiseAlt,
|
||||||
|
string deptime,
|
||||||
|
string arrtime,
|
||||||
|
string rep)
|
||||||
|
{
|
||||||
|
callsign = cs;
|
||||||
|
fltRules = fr;
|
||||||
|
departurePort.id = depPrt;
|
||||||
|
arrivalPort.id = arrPrt;
|
||||||
|
//departureTime = processTimeString(deptime);
|
||||||
|
//arrivalTime = processTimeString(arrtime);
|
||||||
|
cruiseAltitude = cruiseAlt;
|
||||||
|
|
||||||
|
// Process the repeat period string
|
||||||
|
if (rep.find("WEEK",0) != string::npos)
|
||||||
|
{
|
||||||
|
repeatPeriod = 7*24*60*60; // in seconds
|
||||||
|
}
|
||||||
|
else if (rep.find("Hr", 0) != string::npos)
|
||||||
|
{
|
||||||
|
repeatPeriod = 60*60*atoi(rep.substr(0,2).c_str());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cerr << "Unknown repeat period" << endl;
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// What we still need to do is preprocess the departure and
|
||||||
|
// arrival times.
|
||||||
|
departureTime = processTimeString(deptime);
|
||||||
|
arrivalTime = processTimeString(arrtime);
|
||||||
|
if (departureTime > arrivalTime)
|
||||||
|
{
|
||||||
|
departureTime -= repeatPeriod;
|
||||||
|
}
|
||||||
|
initialized = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
FGScheduledFlight:: ~FGScheduledFlight()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
time_t FGScheduledFlight::processTimeString(string theTime)
|
||||||
|
{
|
||||||
|
int weekday;
|
||||||
|
int timeOffsetInDays;
|
||||||
|
int targetDate;
|
||||||
|
int targetHour;
|
||||||
|
int targetMinute;
|
||||||
|
int targetSecond;
|
||||||
|
|
||||||
|
tm targetTimeDate;
|
||||||
|
SGTime* currTimeDate = globals->get_time_params();
|
||||||
|
|
||||||
|
string timeCopy = theTime;
|
||||||
|
|
||||||
|
|
||||||
|
// okay first split theTime string into
|
||||||
|
// weekday, hour, minute, second;
|
||||||
|
// Check if a week day is specified
|
||||||
|
if (timeCopy.find("/",0) != string::npos)
|
||||||
|
{
|
||||||
|
weekday = atoi(timeCopy.substr(0,1).c_str());
|
||||||
|
timeOffsetInDays = weekday - currTimeDate->getGmt()->tm_wday;
|
||||||
|
timeCopy = timeCopy.substr(2,timeCopy.length());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
timeOffsetInDays = 0;
|
||||||
|
}
|
||||||
|
targetHour = atoi(timeCopy.substr(0,2).c_str());
|
||||||
|
targetMinute = atoi(timeCopy.substr(3,5).c_str());
|
||||||
|
targetSecond = atoi(timeCopy.substr(6,8).c_str());
|
||||||
|
targetTimeDate.tm_year = currTimeDate->getGmt()->tm_year;
|
||||||
|
targetTimeDate.tm_mon = currTimeDate->getGmt()->tm_mon;
|
||||||
|
targetTimeDate.tm_mday = currTimeDate->getGmt()->tm_mday;
|
||||||
|
targetTimeDate.tm_hour = targetHour;
|
||||||
|
targetTimeDate.tm_min = targetMinute;
|
||||||
|
targetTimeDate.tm_sec = targetSecond;
|
||||||
|
|
||||||
|
time_t processedTime = sgTimeGetGMT(&targetTimeDate);
|
||||||
|
processedTime += timeOffsetInDays*24*60*60;
|
||||||
|
if (processedTime < currTimeDate->get_cur_time())
|
||||||
|
{
|
||||||
|
processedTime += repeatPeriod;
|
||||||
|
}
|
||||||
|
//tm *temp = currTimeDate->getGmt();
|
||||||
|
//char buffer[512];
|
||||||
|
//sgTimeFormatTime(&targetTimeDate, buffer);
|
||||||
|
//cout << "Scheduled Time " << buffer << endl;
|
||||||
|
//cout << "Time :" << time(NULL) << " SGTime : " << sgTimeGetGMT(temp) << endl;
|
||||||
|
return processedTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FGScheduledFlight::update()
|
||||||
|
{
|
||||||
|
departureTime += repeatPeriod;
|
||||||
|
arrivalTime += repeatPeriod;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FGScheduledFlight::adjustTime(time_t now)
|
||||||
|
{
|
||||||
|
//cerr << "1: Adjusting schedule please wait: " << now
|
||||||
|
// << " " << arrivalTime << " " << arrivalTime+repeatPeriod << endl;
|
||||||
|
// Make sure that the arrival time is in between
|
||||||
|
// the current time and the next repeat period.
|
||||||
|
while ((arrivalTime < now) || (arrivalTime > now+repeatPeriod))
|
||||||
|
{
|
||||||
|
if (arrivalTime < now)
|
||||||
|
{
|
||||||
|
departureTime += repeatPeriod;
|
||||||
|
arrivalTime += repeatPeriod;
|
||||||
|
}
|
||||||
|
else if (arrivalTime > now+repeatPeriod)
|
||||||
|
{
|
||||||
|
departureTime -= repeatPeriod;
|
||||||
|
arrivalTime -= repeatPeriod;
|
||||||
|
}
|
||||||
|
// cerr << "2: Adjusting schedule please wait: " << now
|
||||||
|
// << " " << arrivalTime << " " << arrivalTime+repeatPeriod << endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
FGAirport *FGScheduledFlight::getDepartureAirport()
|
||||||
|
{
|
||||||
|
if (!(initialized))
|
||||||
|
{
|
||||||
|
initializeAirports();
|
||||||
|
}
|
||||||
|
return &departurePort;
|
||||||
|
}
|
||||||
|
FGAirport * FGScheduledFlight::getArrivalAirport ()
|
||||||
|
{
|
||||||
|
if (!(initialized))
|
||||||
|
{
|
||||||
|
initializeAirports();
|
||||||
|
}
|
||||||
|
return &arrivalPort;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Upon the first time of requesting airport information
|
||||||
|
// for this scheduled flight, these data need to be
|
||||||
|
// looked up in the main FlightGear database.
|
||||||
|
// Missing or bogus Airport codes are currently ignored,
|
||||||
|
// but we should improve that. The best idea is probably to cancel
|
||||||
|
// this flight entirely by removing it from the schedule, if one
|
||||||
|
// of the airports cannot be found.
|
||||||
|
void FGScheduledFlight::initializeAirports()
|
||||||
|
{
|
||||||
|
if(!(fgFindAirportID(arrivalPort.id, &arrivalPort )))
|
||||||
|
{
|
||||||
|
//cerr << ": Could not find " << arrivalPort.id << endl;
|
||||||
|
}
|
||||||
|
if(!(fgFindAirportID(departurePort.id, &departurePort)))
|
||||||
|
{
|
||||||
|
//cerr << ": Could not find " << departurePort.id << endl;
|
||||||
|
}
|
||||||
|
initialized = true;
|
||||||
|
}
|
104
src/Traffic/SchedFlight.hxx
Normal file
104
src/Traffic/SchedFlight.hxx
Normal file
|
@ -0,0 +1,104 @@
|
||||||
|
/* -*- Mode: C++ -*- *****************************************************
|
||||||
|
* SchedFlight.hxx
|
||||||
|
* Written by Durk Talsma. Started May 5, 2004
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License as
|
||||||
|
* published by the Free Software Foundation; either version 2 of the
|
||||||
|
* License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
* ScheduledFlight is a class that is used by FlightGear's Traffic Manager
|
||||||
|
* A scheduled flight can be assigned to a schedule, which can be assigned
|
||||||
|
* to an aircraft. The traffic manager decides for each schedule which
|
||||||
|
* scheduled flight (if any) is currently active. I no scheduled flights
|
||||||
|
* are found active, it tries to position the aircraft associated with this
|
||||||
|
* schedule at departure airport of the next scheduled flight.
|
||||||
|
* The class ScheduledFlight is a software implimentation of this.
|
||||||
|
* In summary, this class stores arrival and departure information, as well
|
||||||
|
* as some administrative data, such as the callsign of this particular
|
||||||
|
* flight (used in future ATC scenarios), under which flight rules the
|
||||||
|
* flight is taking place, as well as a requested initial cruise altitude.
|
||||||
|
* Finally, the class contains a repeat period, wich indicates after how
|
||||||
|
* many seconds a flight should repeat in this schedule (which is usually
|
||||||
|
* after either a day or a week). If this value is zero, this flight won't
|
||||||
|
* repeat.
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
#ifndef _FGSCHEDFLIGHT_HXX_
|
||||||
|
#define _FGSCHEDFLIGHT_HXX_
|
||||||
|
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
SG_USING_STD(vector);
|
||||||
|
|
||||||
|
|
||||||
|
class FGScheduledFlight
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
string callsign;
|
||||||
|
string fltRules;
|
||||||
|
FGAirport departurePort;
|
||||||
|
FGAirport arrivalPort;
|
||||||
|
time_t departureTime;
|
||||||
|
time_t arrivalTime;
|
||||||
|
time_t repeatPeriod;
|
||||||
|
int cruiseAltitude;
|
||||||
|
bool initialized;
|
||||||
|
|
||||||
|
void initializeAirports();
|
||||||
|
|
||||||
|
public:
|
||||||
|
FGScheduledFlight();
|
||||||
|
FGScheduledFlight(const FGScheduledFlight &other);
|
||||||
|
// FGScheduledFlight(const string);
|
||||||
|
FGScheduledFlight::FGScheduledFlight(string cs,
|
||||||
|
string fr,
|
||||||
|
string depPrt,
|
||||||
|
string arrPrt,
|
||||||
|
int cruiseAlt,
|
||||||
|
string deptime,
|
||||||
|
string arrtime,
|
||||||
|
string rep
|
||||||
|
);
|
||||||
|
~FGScheduledFlight();
|
||||||
|
|
||||||
|
void update();
|
||||||
|
|
||||||
|
void adjustTime(time_t now);
|
||||||
|
|
||||||
|
time_t getDepartureTime() { return departureTime; };
|
||||||
|
time_t getArrivalTime () { return arrivalTime; };
|
||||||
|
|
||||||
|
FGAirport *getDepartureAirport();
|
||||||
|
FGAirport *getArrivalAirport ();
|
||||||
|
|
||||||
|
int getCruiseAlt() { return cruiseAltitude; };
|
||||||
|
|
||||||
|
bool operator<(const FGScheduledFlight &other) const
|
||||||
|
{
|
||||||
|
return (departureTime < other.departureTime);
|
||||||
|
};
|
||||||
|
|
||||||
|
time_t processTimeString(string time);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef vector<FGScheduledFlight> FGScheduledFlightVec;
|
||||||
|
typedef vector<FGScheduledFlight>::iterator FGScheduledFlightVecIterator;
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
290
src/Traffic/Schedule.cxx
Normal file
290
src/Traffic/Schedule.cxx
Normal file
|
@ -0,0 +1,290 @@
|
||||||
|
/******************************************************************************
|
||||||
|
* Schedule.cxx
|
||||||
|
* Written by Durk Talsma, started May 5, 2004.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License as
|
||||||
|
* published by the Free Software Foundation; either version 2 of the
|
||||||
|
* License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
****************************************************************************
|
||||||
|
*
|
||||||
|
*****************************************************************************/
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <iostream>
|
||||||
|
#include <fstream>
|
||||||
|
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include <plib/sg.h>
|
||||||
|
|
||||||
|
#include <simgear/compiler.h>
|
||||||
|
#include <simgear/math/polar3d.hxx>
|
||||||
|
#include <simgear/math/sg_geodesy.hxx>
|
||||||
|
#include <simgear/props/props.hxx>
|
||||||
|
#include <simgear/route/waypoint.hxx>
|
||||||
|
#include <simgear/structure/subsystem_mgr.hxx>
|
||||||
|
#include <simgear/xml/easyxml.hxx>
|
||||||
|
|
||||||
|
#include <AIModel/AIFlightPlan.hxx>
|
||||||
|
#include <AIModel/AIManager.hxx>
|
||||||
|
#include <Airports/simple.hxx>
|
||||||
|
#include <Main/fg_init.hxx> // That's pretty ugly, but I need fgFindAirportID
|
||||||
|
|
||||||
|
|
||||||
|
#include "SchedFlight.hxx"
|
||||||
|
#include "TrafficMgr.hxx"
|
||||||
|
|
||||||
|
|
||||||
|
/******************************************************************************
|
||||||
|
* the FGAISchedule class contains data members and code to maintain a
|
||||||
|
* schedule of Flights for an articically controlled aircraft.
|
||||||
|
*****************************************************************************/
|
||||||
|
FGAISchedule::FGAISchedule()
|
||||||
|
{
|
||||||
|
firstRun = true;
|
||||||
|
AIManagerRef = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
FGAISchedule::FGAISchedule(string mdl,
|
||||||
|
string liv,
|
||||||
|
string reg,
|
||||||
|
bool hvy,
|
||||||
|
FGScheduledFlightVec flt)
|
||||||
|
{
|
||||||
|
modelPath = mdl;
|
||||||
|
livery = liv;
|
||||||
|
registration = reg;
|
||||||
|
heavy = hvy;
|
||||||
|
for (FGScheduledFlightVecIterator i = flt.begin();
|
||||||
|
i != flt.end();
|
||||||
|
i++)
|
||||||
|
flights.push_back(FGScheduledFlight((*i)));
|
||||||
|
AIManagerRef = 0;
|
||||||
|
firstRun = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
FGAISchedule::FGAISchedule(const FGAISchedule &other)
|
||||||
|
{
|
||||||
|
modelPath = other.modelPath;
|
||||||
|
livery = other.livery;
|
||||||
|
registration = other.registration;
|
||||||
|
heavy = other.heavy;
|
||||||
|
flights = other.flights;
|
||||||
|
lat = other.lat;
|
||||||
|
lon = other.lon;
|
||||||
|
AIManagerRef = other.AIManagerRef;
|
||||||
|
firstRun = other.firstRun;
|
||||||
|
}
|
||||||
|
|
||||||
|
FGAISchedule::~FGAISchedule()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void FGAISchedule::update(time_t now)
|
||||||
|
{
|
||||||
|
FGAirport *dep;
|
||||||
|
FGAirport *arr;
|
||||||
|
sgdVec3 a, b, cross;
|
||||||
|
sgdVec3 newPos;
|
||||||
|
sgdMat4 matrix;
|
||||||
|
double angle;
|
||||||
|
|
||||||
|
FGAIManager *aimgr;
|
||||||
|
string airport;
|
||||||
|
|
||||||
|
double courseToUser, courseToDest;
|
||||||
|
double distanceToUser, distanceToDest;
|
||||||
|
double speed;
|
||||||
|
|
||||||
|
Point3D temp;
|
||||||
|
time_t
|
||||||
|
totalTimeEnroute,
|
||||||
|
elapsedTimeEnroute,
|
||||||
|
remainingTimeEnroute;
|
||||||
|
double
|
||||||
|
userLatitude,
|
||||||
|
userLongitude;
|
||||||
|
|
||||||
|
if (fgGetBool("/sim/ai/enabled") == false)
|
||||||
|
return;
|
||||||
|
|
||||||
|
aimgr = (FGAIManager *) globals-> get_subsystem("ai_model");
|
||||||
|
// Before the flight status of this traffic entity is updated
|
||||||
|
// for the first time, we need to roll back it's flight schedule so
|
||||||
|
// so that all the flights are centered around this simulated week's time
|
||||||
|
// table. This is to avoid the situation where the first scheduled flight is
|
||||||
|
// in the future, causing the traffic manager to not generate traffic until
|
||||||
|
// simulated time has caught up with the real world time at initialization.
|
||||||
|
// This is to counter a more general initialization bug, caused by the fact
|
||||||
|
// that warp is not yet set when the schedule is initialized. This is
|
||||||
|
// especially a problem when using a negative time offset.
|
||||||
|
// i.e let's say we specify FlightGear to run with --time-offset=-24:00:00.
|
||||||
|
// Then the schedule will initialize using today, but we will fly yesterday.
|
||||||
|
// Thus, it would take a whole day of simulation before the traffic manager
|
||||||
|
// finally kicks in.
|
||||||
|
if (firstRun)
|
||||||
|
{
|
||||||
|
for (FGScheduledFlightVecIterator i = flights.begin();
|
||||||
|
i != flights.end();
|
||||||
|
i++)
|
||||||
|
{
|
||||||
|
i->adjustTime(now);
|
||||||
|
}
|
||||||
|
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());
|
||||||
|
FGScheduledFlightVecIterator i = flights.begin();
|
||||||
|
if (!AIManagerRef)
|
||||||
|
{
|
||||||
|
userLatitude = fgGetDouble("/position/latitude-deg");
|
||||||
|
userLongitude = fgGetDouble("/position/longitude-deg");
|
||||||
|
|
||||||
|
|
||||||
|
// 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))
|
||||||
|
{
|
||||||
|
i->update();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Departure time in the past and arrival time in the future.
|
||||||
|
// 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))
|
||||||
|
{
|
||||||
|
dep = i->getDepartureAirport();
|
||||||
|
arr = i->getArrivalAirport ();
|
||||||
|
|
||||||
|
temp = sgPolarToCart3d(Point3D(dep->longitude *
|
||||||
|
SG_DEGREES_TO_RADIANS,
|
||||||
|
dep->latitude *
|
||||||
|
SG_DEGREES_TO_RADIANS,
|
||||||
|
1.0));
|
||||||
|
a[0] = temp.x();
|
||||||
|
a[1] = temp.y();
|
||||||
|
a[2] = temp.z();
|
||||||
|
|
||||||
|
temp = sgPolarToCart3d(Point3D(arr->longitude *
|
||||||
|
SG_DEGREES_TO_RADIANS,
|
||||||
|
arr->latitude *
|
||||||
|
SG_DEGREES_TO_RADIANS,
|
||||||
|
1.0));
|
||||||
|
b[0] = temp.x();
|
||||||
|
b[1] = temp.y();
|
||||||
|
b[2] = temp.z();
|
||||||
|
sgdNormaliseVec3(a);
|
||||||
|
sgdNormaliseVec3(b);
|
||||||
|
sgdVectorProductVec3(cross,b,a);
|
||||||
|
|
||||||
|
angle = sgACos(sgdScalarProductVec3(a,b));
|
||||||
|
|
||||||
|
// Okay, at this point we have the angle between departure and
|
||||||
|
// 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;
|
||||||
|
|
||||||
|
angle *= ( (double) elapsedTimeEnroute/ (double) totalTimeEnroute);
|
||||||
|
|
||||||
|
|
||||||
|
//cout << "a = " << a[0] << " " << a[1] << " " << a[2]
|
||||||
|
// << "b = " << b[0] << " " << b[1] << " " << b[2] << endl;
|
||||||
|
sgdMakeRotMat4(matrix, angle, cross);
|
||||||
|
for(int j = 0; j < 3; j++)
|
||||||
|
{
|
||||||
|
newPos[j] =0.0;
|
||||||
|
for (int k = 0; k<3; k++)
|
||||||
|
{
|
||||||
|
newPos[j] += matrix[j][k]*a[k];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
temp = sgCartToPolar3d(Point3D(newPos[0], newPos[1],newPos[2]));
|
||||||
|
|
||||||
|
lat = temp.lat() * SG_RADIANS_TO_DEGREES;
|
||||||
|
lon = temp.lon() * SG_RADIANS_TO_DEGREES;
|
||||||
|
|
||||||
|
SGWayPoint current (lon,
|
||||||
|
lat,
|
||||||
|
i->getCruiseAlt());
|
||||||
|
SGWayPoint user ( userLongitude,
|
||||||
|
userLatitude,
|
||||||
|
i->getCruiseAlt());
|
||||||
|
SGWayPoint dest ( arr->longitude,
|
||||||
|
arr->latitude,
|
||||||
|
i->getCruiseAlt());
|
||||||
|
// We really only need distance to user
|
||||||
|
// and course to destination
|
||||||
|
current.CourseAndDistance(user, &courseToUser, &distanceToUser);
|
||||||
|
current.CourseAndDistance(dest, &courseToDest, &distanceToDest);
|
||||||
|
speed = (distanceToDest*SG_METER_TO_NM) /
|
||||||
|
((double) remainingTimeEnroute/3600.0);
|
||||||
|
|
||||||
|
|
||||||
|
// If distance between user and simulated aircaft is less
|
||||||
|
// then 500nm, create this flight. At jet speeds 500 nm is roughly
|
||||||
|
// one hour flight time, so that would be a good approximate point
|
||||||
|
// to start a more detailed simulation of this aircraft.
|
||||||
|
//cerr << registration << " is currently enroute from "
|
||||||
|
// << dep->id << " to " << arr->id << "distance : " << distanceToUser*SG_METER_TO_NM << endl;
|
||||||
|
if ((distanceToUser*SG_METER_TO_NM) < 500.0)
|
||||||
|
{
|
||||||
|
string flightPlanName = dep->id + string("-") + arr->id + string(".xml");
|
||||||
|
|
||||||
|
FGAIFlightPlan* f;
|
||||||
|
// If we're less then 10 minutes behind schedule, do a normal
|
||||||
|
// full flight plan initialization, otherwise, do a modified
|
||||||
|
// in-air initializition, at the location where this flight is
|
||||||
|
// according to the Traffic Manager
|
||||||
|
if (elapsedTimeEnroute < 600)
|
||||||
|
f = new FGAIFlightPlan(flightPlanName);
|
||||||
|
else
|
||||||
|
f = new FGAIFlightPlan(flightPlanName,
|
||||||
|
lat,
|
||||||
|
lon,
|
||||||
|
i->getCruiseAlt() * 1000, // convert from FL to feet
|
||||||
|
speed,
|
||||||
|
courseToDest);
|
||||||
|
// Fixme: A non-existent model path results in an
|
||||||
|
// abort, due to an unhandled exeption, in fg main loop.
|
||||||
|
AIManagerRef = aimgr->createAircraft("jet_transport",
|
||||||
|
modelPath, f);
|
||||||
|
//cerr << "Created: " << AIManagerRef << endl;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// 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
|
||||||
|
// 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))
|
||||||
|
{
|
||||||
|
dep = i->getDepartureAirport();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
62
src/Traffic/Schedule.hxx
Normal file
62
src/Traffic/Schedule.hxx
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
/* -*- Mode: C++ -*- *****************************************************
|
||||||
|
* Schedule.hxx
|
||||||
|
* Written by Durk Talsma. Started May 5, 2004
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License as
|
||||||
|
* published by the Free Software Foundation; either version 2 of the
|
||||||
|
* License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
* This file contains the definition of the class Shedule.
|
||||||
|
*
|
||||||
|
* A schedule is basically a number of scheduled flights, wich can be
|
||||||
|
* assigned to an AI aircraft.
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
#ifndef _FGSCHEDULE_HXX_
|
||||||
|
#define _FGSCHEDULE_HXX_
|
||||||
|
|
||||||
|
|
||||||
|
class FGAISchedule
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
string modelPath;
|
||||||
|
string livery;
|
||||||
|
string registration;
|
||||||
|
bool heavy;
|
||||||
|
FGScheduledFlightVec flights;
|
||||||
|
float lat;
|
||||||
|
float lon;
|
||||||
|
int AIManagerRef;
|
||||||
|
bool firstRun;
|
||||||
|
|
||||||
|
public:
|
||||||
|
FGAISchedule(); // constructor
|
||||||
|
FGAISchedule(string, string, string, bool, FGScheduledFlightVec); // construct & init
|
||||||
|
FGAISchedule(const FGAISchedule &other); // copy constructor
|
||||||
|
|
||||||
|
~FGAISchedule(); //destructor
|
||||||
|
|
||||||
|
void update(time_t now);
|
||||||
|
// More member functions follow later
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef vector<FGAISchedule> ScheduleVector;
|
||||||
|
typedef vector<FGAISchedule>::iterator ScheduleVectorIterator;
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
207
src/Traffic/TrafficMgr.cxx
Normal file
207
src/Traffic/TrafficMgr.cxx
Normal file
|
@ -0,0 +1,207 @@
|
||||||
|
/******************************************************************************
|
||||||
|
* TrafficMGr.cxx
|
||||||
|
* Written by Durk Talsma, started May 5, 2004.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License as
|
||||||
|
* published by the Free Software Foundation; either version 2 of the
|
||||||
|
* License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
/* This a prototype version of a top-level flight plan manager for Flightgear.
|
||||||
|
* It parses the fgtraffic.txt file and determine for a specific time/date,
|
||||||
|
* where each aircraft listed in this file is at the current time.
|
||||||
|
*
|
||||||
|
* I'm currently assuming the following simplifications:
|
||||||
|
* 1) The earth is a perfect sphere
|
||||||
|
* 2) Each aircraft flies a perfect great circle route.
|
||||||
|
* 3) Each aircraft flies at a constant speed (with infinite accelerations and
|
||||||
|
* decelerations)
|
||||||
|
* 4) Each aircraft leaves at exactly the departure time.
|
||||||
|
* 5) Each aircraft arrives at exactly the specified arrival time.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*****************************************************************************/
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <iostream>
|
||||||
|
#include <fstream>
|
||||||
|
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include <plib/sg.h>
|
||||||
|
|
||||||
|
#include <simgear/compiler.h>
|
||||||
|
#include <simgear/math/polar3d.hxx>
|
||||||
|
#include <simgear/math/sg_geodesy.hxx>
|
||||||
|
#include <simgear/props/props.hxx>
|
||||||
|
#include <simgear/route/waypoint.hxx>
|
||||||
|
#include <simgear/structure/subsystem_mgr.hxx>
|
||||||
|
#include <simgear/xml/easyxml.hxx>
|
||||||
|
|
||||||
|
#include <AIModel/AIFlightPlan.hxx>
|
||||||
|
#include <AIModel/AIManager.hxx>
|
||||||
|
#include <Airports/simple.hxx>
|
||||||
|
#include <Main/fg_init.hxx> // That's pretty ugly, but I need fgFindAirportID
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#include "TrafficMgr.hxx"
|
||||||
|
|
||||||
|
|
||||||
|
/******************************************************************************
|
||||||
|
* TrafficManager
|
||||||
|
*****************************************************************************/
|
||||||
|
FGTrafficManager::FGTrafficManager()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void FGTrafficManager::init()
|
||||||
|
{
|
||||||
|
currAircraft = scheduledAircraft.begin();
|
||||||
|
}
|
||||||
|
|
||||||
|
void FGTrafficManager::update(double something)
|
||||||
|
{
|
||||||
|
|
||||||
|
//static const SGPropertyNode *warp = globals->get_props()->getNode("/sim/time/warp");
|
||||||
|
|
||||||
|
//time_t now = time(NULL) + globals->get_warp();
|
||||||
|
time_t now = time(NULL) + fgGetLong("/sim/time/warp");
|
||||||
|
// cerr << "TrafficManager update" << globals->get_warp() << endl;
|
||||||
|
if(currAircraft == scheduledAircraft.end())
|
||||||
|
currAircraft = scheduledAircraft.begin();
|
||||||
|
currAircraft->update(now);
|
||||||
|
currAircraft++;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FGTrafficManager::startXML () {
|
||||||
|
//cout << "Start XML" << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FGTrafficManager::endXML () {
|
||||||
|
//cout << "End XML" << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FGTrafficManager::startElement (const char * name, const XMLAttributes &atts) {
|
||||||
|
const char * attval;
|
||||||
|
//cout << "Start element " << name << endl;
|
||||||
|
//FGTrafficManager temp;
|
||||||
|
//for (int i = 0; i < atts.size(); i++)
|
||||||
|
// if (string(atts.getName(i)) == string("include"))
|
||||||
|
attval = atts.getValue("include");
|
||||||
|
if (attval != 0)
|
||||||
|
{
|
||||||
|
//cout << "including " << attval << endl;
|
||||||
|
string path =
|
||||||
|
globals->get_fg_root() +
|
||||||
|
string("/Traffic/") +
|
||||||
|
string(attval);
|
||||||
|
readXML(path, *this);
|
||||||
|
}
|
||||||
|
// cout << " " << atts.getName(i) << '=' << atts.getValue(i) << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FGTrafficManager::endElement (const char * name) {
|
||||||
|
//cout << "End element " << name << endl;
|
||||||
|
string element(name);
|
||||||
|
if (element == string("model"))
|
||||||
|
mdl = value;
|
||||||
|
else if (element == string("livery"))
|
||||||
|
livery = value;
|
||||||
|
else if (element == string("registration"))
|
||||||
|
registration = value;
|
||||||
|
else if (element == string("heavy"))
|
||||||
|
{
|
||||||
|
if(value == string("true"))
|
||||||
|
heavy = true;
|
||||||
|
else
|
||||||
|
heavy = false;
|
||||||
|
}
|
||||||
|
else if (element == string("callsign"))
|
||||||
|
callsign = value;
|
||||||
|
else if (element == string("fltrules"))
|
||||||
|
fltrules = value;
|
||||||
|
else if (element == string("port"))
|
||||||
|
port = value;
|
||||||
|
else if (element == string("time"))
|
||||||
|
timeString = value;
|
||||||
|
else if (element == string("departure"))
|
||||||
|
{
|
||||||
|
departurePort = port;
|
||||||
|
departureTime = timeString;
|
||||||
|
}
|
||||||
|
else if (element == string("cruise-alt"))
|
||||||
|
cruiseAlt = atoi(value.c_str());
|
||||||
|
else if (element == string("arrival"))
|
||||||
|
{
|
||||||
|
arrivalPort = port;
|
||||||
|
arrivalTime = timeString;
|
||||||
|
}
|
||||||
|
else if (element == string("repeat"))
|
||||||
|
repeat = value;
|
||||||
|
else if (element == string("flight"))
|
||||||
|
{
|
||||||
|
// We have loaded and parsed all the information belonging to this flight
|
||||||
|
// so we temporarily store it.
|
||||||
|
//cerr << "Pusing back flight " << callsign << endl;
|
||||||
|
//cerr << callsign << " " << fltrules << " "<< departurePort << " " << arrivalPort << " "
|
||||||
|
// << cruiseAlt << " " << departureTime<< " "<< arrivalTime << " " << repeat << endl;
|
||||||
|
flights.push_back(FGScheduledFlight(callsign,
|
||||||
|
fltrules,
|
||||||
|
departurePort,
|
||||||
|
arrivalPort,
|
||||||
|
cruiseAlt,
|
||||||
|
departureTime,
|
||||||
|
arrivalTime,
|
||||||
|
repeat));
|
||||||
|
}
|
||||||
|
else if (element == string("aircraft"))
|
||||||
|
{
|
||||||
|
//cerr << "Pushing back aircraft " << registration << endl;
|
||||||
|
scheduledAircraft.push_back(FGAISchedule(mdl,
|
||||||
|
livery,
|
||||||
|
registration,
|
||||||
|
heavy,
|
||||||
|
flights));
|
||||||
|
while(flights.begin() != flights.end())
|
||||||
|
flights.pop_back();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void FGTrafficManager::data (const char * s, int len) {
|
||||||
|
string token = string(s,len);
|
||||||
|
//cout << "Character data " << string(s,len) << endl;
|
||||||
|
if ((token.find(" ") == string::npos && (token.find('\n')) == string::npos))
|
||||||
|
value += token;
|
||||||
|
else
|
||||||
|
value = string("");
|
||||||
|
}
|
||||||
|
|
||||||
|
void FGTrafficManager::pi (const char * target, const char * data) {
|
||||||
|
//cout << "Processing instruction " << target << ' ' << data << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FGTrafficManager::warning (const char * message, int line, int column) {
|
||||||
|
cout << "Warning: " << message << " (" << line << ',' << column << ')'
|
||||||
|
<< endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FGTrafficManager::error (const char * message, int line, int column) {
|
||||||
|
cout << "Error: " << message << " (" << line << ',' << column << ')'
|
||||||
|
<< endl;
|
||||||
|
}
|
69
src/Traffic/TrafficMgr.hxx
Normal file
69
src/Traffic/TrafficMgr.hxx
Normal file
|
@ -0,0 +1,69 @@
|
||||||
|
/* -*- Mode: C++ -*- *****************************************************
|
||||||
|
* TrafficMgr.hxx
|
||||||
|
* Written by Durk Talsma. Started May 5, 2004
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License as
|
||||||
|
* published by the Free Software Foundation; either version 2 of the
|
||||||
|
* License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
* This file contains the class definitions for a (Top Level) traffic
|
||||||
|
* manager for FlightGear.
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
#ifndef _TRAFFICMGR_HXX_
|
||||||
|
#define _TRAFFICMGR_HXX_
|
||||||
|
|
||||||
|
#include <simgear/structure/subsystem_mgr.hxx>
|
||||||
|
#include <simgear/xml/easyxml.hxx>
|
||||||
|
|
||||||
|
#include "SchedFlight.hxx"
|
||||||
|
#include "Schedule.hxx"
|
||||||
|
|
||||||
|
|
||||||
|
class FGTrafficManager : public SGSubsystem, public XMLVisitor
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
ScheduleVector scheduledAircraft;
|
||||||
|
ScheduleVectorIterator currAircraft;
|
||||||
|
string value;
|
||||||
|
|
||||||
|
string mdl, livery, registration, callsign, fltrules,
|
||||||
|
port, timeString, departurePort, departureTime, arrivalPort, arrivalTime,
|
||||||
|
repeat;
|
||||||
|
int cruiseAlt;
|
||||||
|
bool heavy;
|
||||||
|
|
||||||
|
FGScheduledFlightVec flights;
|
||||||
|
|
||||||
|
public:
|
||||||
|
FGTrafficManager();
|
||||||
|
|
||||||
|
void init();
|
||||||
|
void update(double time);
|
||||||
|
|
||||||
|
// Some overloaded virtual XMLVisitor members
|
||||||
|
virtual void startXML ();
|
||||||
|
virtual void endXML ();
|
||||||
|
virtual void startElement (const char * name, const XMLAttributes &atts);
|
||||||
|
virtual void endElement (const char * name);
|
||||||
|
virtual void data (const char * s, int len);
|
||||||
|
virtual void pi (const char * target, const char * data);
|
||||||
|
virtual void warning (const char * message, int line, int column);
|
||||||
|
virtual void error (const char * message, int line, int column);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
Loading…
Reference in a new issue