return false;
}
setCallSign(trafficRef->getCallSign());
- //props->setStringValue("callsign", callsign.c_str());
leg = 1;
fp->setLeg(leg);
}
} else {
double cruiseAlt = trafficRef->getCruiseAlt() * 100;
- fp->create (dep,
+ fp->create (this,
+ dep,
arr,
leg,
- cruiseAlt, //(trafficRef->getCruiseAlt() * 100), // convert from FL to feet
+ cruiseAlt,
trafficRef->getSpeed(),
_getLatitude(),
_getLongitude(),
virtual const char* getTypeString(void) const { return "aircraft"; }
// included as performance data needs them, who else?
+ inline PerformanceData* getPerformance() { return _performance; };
inline bool onGround() const { return no_roll; };
inline double getSpeed() const { return speed; };
inline double getRoll() const { return roll; };
// Position computed by the traffic manager, as well
// as setting speeds and altitude computed by the
// traffic manager.
-FGAIFlightPlan::FGAIFlightPlan(const std::string& p,
+FGAIFlightPlan::FGAIFlightPlan(FGAIAircraft *ac,
+ const std::string& p,
double course,
time_t start,
FGAirport *dep,
SG_LOG(SG_GENERAL, SG_INFO, "Route from " << dep->getId() << " to " << arr->getId() << ". Set leg to : " << leg);
wpt_iterator = waypoints.begin();
- create(dep,arr, leg, alt, speed, lat, lon,
+ create(ac, dep,arr, leg, alt, speed, lat, lon,
firstLeg, radius, fltType, acType, airline);
wpt_iterator = waypoints.begin();
//cerr << "after create: " << (*wpt_iterator)->name << endl;
#include <vector>
#include <string>
+
#include <Airports/simple.hxx>
#include <Navaids/awynet.hxx>
#include "AIBase.hxx"
+
+
using std::vector;
using std::string;
class FGTaxiRoute;
class FGRunway;
+class FGAIAircraft;
class FGAIFlightPlan {
} waypoint;
FGAIFlightPlan(const string& filename);
- FGAIFlightPlan(const std::string& p,
+ FGAIFlightPlan(FGAIAircraft *,
+ const std::string& p,
double course,
time_t start,
FGAirport *dep,
double getBearing(double lat, double lon, waypoint* next) const;
time_t getStartTime() const { return start_time; }
- void create(FGAirport *dep, FGAirport *arr, int leg, double alt, double speed, double lat, double lon,
+ void create(FGAIAircraft *, FGAirport *dep, FGAirport *arr, int leg, double alt, double speed, double lat, double lon,
bool firstLeg, double radius, const string& fltType, const string& aircraftType, const string& airline);
void setLeg(int val) { leg = val;}
void createPushBack(bool, FGAirport*, double, double, double, const string&, const string&, const string&);
void createPushBackFallBack(bool, FGAirport*, double, double, double, const string&, const string&, const string&);
- void createTakeOff(bool, FGAirport *, double, const string&);
+ void createTakeOff(FGAIAircraft *, bool, FGAirport *, double, const string&);
void createClimb(bool, FGAirport *, double, double, const string&);
void createCruise(bool, FGAirport*, FGAirport*, double, double, double, double, const string&);
void createDecent(FGAirport *, const string&);
#include <simgear/math/sg_geodesy.hxx>
#include <Airports/runways.hxx>
#include <Airports/dynamics.hxx>
+#include <AIAircraft.hxx>
+#include <performancedata.hxx>
#include <Environment/environment_mgr.hxx>
#include <Environment/environment.hxx>
// Check lat/lon values during initialization;
-void FGAIFlightPlan::create(FGAirport *dep, FGAirport *arr, int legNr,
+void FGAIFlightPlan::create(FGAIAircraft *ac, FGAirport *dep, FGAirport *arr, int legNr,
double alt, double speed, double latitude,
double longitude, bool firstFlight,double radius,
const string& fltType, const string& aircraftType,
createTakeoffTaxi(firstFlight, dep, radius, fltType, aircraftType, airline);
break;
case 3:
- createTakeOff(firstFlight, dep, speed, fltType);
+ createTakeOff(ac, firstFlight, dep, speed, fltType);
break;
case 4:
createClimb(firstFlight, dep, speed, alt, fltType);
* CreateTakeOff
* initialize the Aircraft at the parking location
******************************************************************/
-void FGAIFlightPlan::createTakeOff(bool firstFlight, FGAirport *apt, double speed, const string &fltType)
+void FGAIFlightPlan::createTakeOff(FGAIAircraft *ac, bool firstFlight, FGAirport *apt, double speed, const string &fltType)
{
- waypoint *wpt;
-
- // Get the current active runway, based on code from David Luff
- // This should actually be unified and extended to include
- // Preferential runway use schema's
- if (firstFlight)
- {
- string rwyClass = getRunwayClassFromTrafficType(fltType);
- apt->getDynamics()->getActiveRunway(rwyClass, 1, activeRunway);
- rwy = apt->getRunwayByIdent(activeRunway);
- }
-
- double airportElev = apt->getElevation();
- // Acceleration point, 105 meters into the runway,
- SGGeod accelPoint = rwy->pointOnCenterline(105.0);
- wpt = createOnGround("accel", accelPoint, airportElev, speed);
- waypoints.push_back(wpt);
+ double accel = ac->getPerformance()->acceleration();
+ double vRotate = ac->getPerformance()->vRotate();
+ // Acceleration = dV / dT
+ // Acceleration X dT = dV
+ // dT = dT / Acceleration
+ //d = (Vf^2 - Vo^2) / (2*a)
+ double accelTime = (vRotate - 15) / accel;
+ cerr << "Using " << accelTime << " as total acceleration time" << endl;
+ double accelDistance = (vRotate*vRotate - 15*15) / (2*accel);
+ cerr << "Using " << accelDistance << " " << accel << " " << vRotate << endl;
+ waypoint *wpt;
+ // Get the current active runway, based on code from David Luff
+ // This should actually be unified and extended to include
+ // Preferential runway use schema's
+ // NOTE: DT (2009-01-18: IIRC, this is currently already the case,
+ // because the getActive runway function takes care of that.
+ if (firstFlight)
+ {
+ string rwyClass = getRunwayClassFromTrafficType(fltType);
+ apt->getDynamics()->getActiveRunway(rwyClass, 1, activeRunway);
+ rwy = apt->getRunwayByIdent(activeRunway);
+ }
+
+ double airportElev = apt->getElevation();
+ // Acceleration point, 105 meters into the runway,
+ SGGeod accelPoint = rwy->pointOnCenterline(105.0);
+ wpt = createOnGround("accel", accelPoint, airportElev, speed);
+ waypoints.push_back(wpt);
- //Start Climbing to 3000 ft. Let's do this
- // at the center of the runway for now:
- wpt = cloneWithPos(wpt, "SOC", rwy->geod());
- wpt->altitude = airportElev+1000;
- wpt->on_ground = false;
- waypoints.push_back(wpt);
-
- wpt = cloneWithPos(wpt, "3000 ft", rwy->end());
- wpt->altitude = airportElev+3000;
- waypoints.push_back(wpt);
-
-// Finally, add two more waypoints, so that aircraft will remain under
- // Tower control until they have reached the 3000 ft climb point
- SGGeod pt = rwy->pointOnCenterline(5000 + rwy->lengthM() * 0.5);
- wpt = cloneWithPos(wpt, "5000 ft", pt);
- wpt->altitude = airportElev+5000;
- waypoints.push_back(wpt);
+ //Start Climbing to 3000 ft. Let's do this
+ // at the center of the runway for now:
+ SGGeod rotate = rwy->pointOnCenterline(105.0+accelDistance);
+ wpt = cloneWithPos(wpt, "SOC", rotate);
+ wpt->altitude = airportElev+1000;
+ wpt->on_ground = false;
+ waypoints.push_back(wpt);
+
+ wpt = cloneWithPos(wpt, "3000 ft", rwy->end());
+ wpt->altitude = airportElev+3000;
+ waypoints.push_back(wpt);
+
+ // Finally, add two more waypoints, so that aircraft will remain under
+ // Tower control until they have reached the 3000 ft climb point
+ SGGeod pt = rwy->pointOnCenterline(5000 + rwy->lengthM() * 0.5);
+ wpt = cloneWithPos(wpt, "5000 ft", pt);
+ wpt->altitude = airportElev+5000;
+ waypoints.push_back(wpt);
}
/*******************************************************************
/**
Data storage for aircraft performance data. This is used to properly simulate the flight of AIAircrafts.
- @author Thomas Förster <t.foerster@biologie.hu-berlin.de>
+ @author Thomas F�rster <t.foerster@biologie.hu-berlin.de>
*/
class PerformanceData
{
bool gearExtensible(const FGAIAircraft* ac);
- inline double climbRate() { return _climbRate; };
- inline double descentRate() { return _descentRate; };
- inline double vRotate() { return _vRotate; };
- inline double maximumBankAngle() { return _maxbank; };
+ inline double climbRate () { return _climbRate; };
+ inline double descentRate () { return _descentRate; };
+ inline double vRotate () { return _vRotate; };
+ inline double maximumBankAngle () { return _maxbank; };
+ inline double acceleration () { return _acceleration; };
private:
double _acceleration;
PerformanceDB::PerformanceDB()
{
// these are the 6 classes originally defined in the PERFSTRUCT
+ // Plus a few more for testing
+ registerPerformanceData("heavy_jet", new PerformanceData(
+ 4.0, 2.0, 3000.0, 1500.0, 150.0, 160.0, 300.0, 430.0, 300.0, 170.0, 150.0, 15.0));
registerPerformanceData("light", new PerformanceData(
2.0, 2.0, 450.0, 1000.0, 70.0, 70.0, 80.0, 100.0, 80.0, 70.0, 60.0, 15.0));
registerPerformanceData("ww2_fighter", new PerformanceData(
XMLLoader::XMLLoader() {}
XMLLoader::~XMLLoader() {}
-void XMLLoader::load(FGAirportDynamics* d) {
- FGAirportDynamicsXMLLoader visitor(d);
+string XMLLoader::expandICAODirs(const string in){
+ cerr << "Expanding " << in << endl;
+ if (in.size() == 4) {
+ char buffer[11];
+ snprintf(buffer, 11, "%c/%c/%c", in[0], in[1], in[2]);
+ cerr << "result: " << buffer << endl;
+ return string(buffer);
+ } else {
+ return in;
+ }
+ //exit(1);
+}
- SGPath parkpath( globals->get_fg_root() );
- parkpath.append( "/AI/Airports/" );
- parkpath.append( d->getId() );
- parkpath.append( "parking.xml" );
-
- if (parkpath.exists()) {
- try {
- readXML(parkpath.str(), visitor);
- d->init();
- } catch (const sg_exception &e) {
- //cerr << "unable to read " << parkpath.str() << endl;
+void XMLLoader::load(FGAirportDynamics* d) {
+ FGAirportDynamicsXMLLoader visitor(d);
+ if (fgGetBool("/sim/traffic-manager/use-custom-scenery-data") == false) {
+ SGPath parkpath( globals->get_fg_root() );
+ parkpath.append( "/AI/Airports/" );
+ parkpath.append( d->getId() );
+ parkpath.append( "parking.xml" );
+ if (parkpath.exists()) {
+ try {
+ readXML(parkpath.str(), visitor);
+ d->init();
+ }
+ catch (const sg_exception &e) {
+ }
+ } else {
+ string_list sc = globals->get_fg_scenery();
+ char buffer[32];
+ snprintf(buffer, 32, "%s.groundnet.xml", d->getId().c_str() );
+ string airportDir = XMLLoader::expandICAODirs(d->getId());
+ for (string_list_iterator i = sc.begin(); i != sc.end(); i++) {
+ SGPath parkpath( *i );
+ parkpath.append( "Airports" );
+ parkpath.append ( airportDir );
+ parkpath.append( string (buffer) );
+ if (parkpath.exists()) {
+ try {
+ readXML(parkpath.str(), visitor);
+ d->init();
+ }
+ catch (const sg_exception &e) {
+ }
+ return;
+ }
+ }
}
- }
-
}
void XMLLoader::load(FGRunwayPreference* p) {
- FGRunwayPreferenceXMLLoader visitor(p);
-
- SGPath rwyPrefPath( globals->get_fg_root() );
- rwyPrefPath.append( "AI/Airports/" );
- rwyPrefPath.append( p->getId() );
- rwyPrefPath.append( "rwyuse.xml" );
-
- //if (ai_dirs.find(id.c_str()) != ai_dirs.end()
- // && rwyPrefPath.exists())
- if (rwyPrefPath.exists()) {
- try {
- readXML(rwyPrefPath.str(), visitor);
- } catch (const sg_exception &e) {
- //cerr << "unable to read " << rwyPrefPath.str() << endl;
+ FGRunwayPreferenceXMLLoader visitor(p);
+ if (fgGetBool("/sim/traffic-manager/use-custom-scenery-data") == false) {
+ SGPath rwyPrefPath( globals->get_fg_root() );
+ rwyPrefPath.append( "AI/Airports/" );
+ rwyPrefPath.append( p->getId() );
+ rwyPrefPath.append( "rwyuse.xml" );
+ if (rwyPrefPath.exists()) {
+ try {
+ readXML(rwyPrefPath.str(), visitor);
+ }
+ catch (const sg_exception &e) {
+ }
+ }
+ } else {
+ string_list sc = globals->get_fg_scenery();
+ char buffer[32];
+ snprintf(buffer, 32, "%s.rwyuse.xml", p->getId().c_str() );
+ string airportDir = expandICAODirs(p->getId());
+ for (string_list_iterator i = sc.begin(); i != sc.end(); i++) {
+ SGPath rwypath( *i );
+ rwypath.append( "Airports" );
+ rwypath.append ( airportDir );
+ rwypath.append( string(buffer) );
+ if (rwypath.exists()) {
+ try {
+ readXML(rwypath.str(), visitor);
+ }
+ catch (const sg_exception &e) {
+ }
+ return;
+ }
+ }
}
- }
}
+
class FGRunwayPreference;
+
class XMLLoader {
public:
XMLLoader();
~XMLLoader();
-
+ static string expandICAODirs(const string in);
static void load(FGRunwayPreference* p);
static void load(FGAirportDynamics* d);
ulDir *td = ulOpenDir( pt.c_str() );
ulDir *od = ulOpenDir( po.c_str() );
- if (td == NULL && od == NULL)
+ // "Terrain" and "Airports" directory don't exist. add directory as is
+ // otherwise, automatically append either Terrain, Objects, or both
+ //if (td == NULL && od == NULL)
fg_scenery.push_back( path_list[i] );
- else {
+ //else {
if (td != NULL) {
fg_scenery.push_back( pt.str() );
ulCloseDir( td );
fg_scenery.push_back( po.str() );
ulCloseDir( od );
}
- }
+ //}
// insert a marker for FGTileEntry::load(), so that
// FG_SCENERY=A:B becomes list ["A/Terrain", "A/Objects", "",
// "B/Terrain", "B/Objects", ""]
aircraft->setAltitude((*i)->getCruiseAlt()*100); // convert from FL to feet
aircraft->setSpeed(speed);
aircraft->setBank(0);
- aircraft->SetFlightPlan(new FGAIFlightPlan(flightPlanName, courseToDest, deptime,
+ aircraft->SetFlightPlan(new FGAIFlightPlan(aircraft, flightPlanName, courseToDest, deptime,
dep, arr,true, radius,
(*i)->getCruiseAlt()*100,
lat, lon, speed, flightType, acType,