Development for two new features:
* Some support for geometry information provided by the custom scenery project. Current support is for AI groundnets and runway use files only since this is a switch that involves a lot of data verification and updating, during the transistion the actual path where the data can be read from is user configurable. setting the property /sim/traffic-manager/use-custom-scenery-data to true will cause flightgear to read the ground networks from the scenery directory (--{fg-scenery}/Airports/[I]/[C]/[A]/[ICAO].groundnet.xml to be precise). Setting this property to false will retain the original behvior. * For departing aircraft, runway takeoff calculations will be done on the basis of the performance database. For testing purposes, a performance estimate for a heavy jet has been added.
This commit is contained in:
parent
5efca258c1
commit
c6f88e5b9b
11 changed files with 160 additions and 83 deletions
|
@ -353,7 +353,6 @@ bool FGAIAircraft::loadNextLeg() {
|
|||
return false;
|
||||
}
|
||||
setCallSign(trafficRef->getCallSign());
|
||||
//props->setStringValue("callsign", callsign.c_str());
|
||||
leg = 1;
|
||||
fp->setLeg(leg);
|
||||
}
|
||||
|
@ -366,10 +365,11 @@ bool FGAIAircraft::loadNextLeg() {
|
|||
} 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(),
|
||||
|
|
|
@ -76,6 +76,7 @@ public:
|
|||
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; };
|
||||
|
|
|
@ -101,7 +101,8 @@ FGAIFlightPlan::FGAIFlightPlan(const string& filename)
|
|||
// 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,
|
||||
|
@ -202,7 +203,7 @@ FGAIFlightPlan::FGAIFlightPlan(const std::string& p,
|
|||
|
||||
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;
|
||||
|
|
|
@ -23,16 +23,20 @@
|
|||
#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 {
|
||||
|
||||
|
@ -56,7 +60,8 @@ public:
|
|||
} waypoint;
|
||||
|
||||
FGAIFlightPlan(const string& filename);
|
||||
FGAIFlightPlan(const std::string& p,
|
||||
FGAIFlightPlan(FGAIAircraft *,
|
||||
const std::string& p,
|
||||
double course,
|
||||
time_t start,
|
||||
FGAirport *dep,
|
||||
|
@ -86,7 +91,7 @@ public:
|
|||
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;}
|
||||
|
@ -126,7 +131,7 @@ private:
|
|||
|
||||
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&);
|
||||
|
|
|
@ -26,6 +26,8 @@
|
|||
#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>
|
||||
|
@ -41,7 +43,7 @@
|
|||
|
||||
|
||||
// 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,
|
||||
|
@ -58,7 +60,7 @@ void FGAIFlightPlan::create(FGAirport *dep, FGAirport *arr, int legNr,
|
|||
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);
|
||||
|
@ -336,13 +338,24 @@ void FGAIFlightPlan::createLandingTaxi(FGAirport *apt,
|
|||
* 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)
|
||||
{
|
||||
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);
|
||||
|
@ -358,7 +371,8 @@ void FGAIFlightPlan::createTakeOff(bool firstFlight, FGAirport *apt, double spee
|
|||
|
||||
//Start Climbing to 3000 ft. Let's do this
|
||||
// at the center of the runway for now:
|
||||
wpt = cloneWithPos(wpt, "SOC", rwy->geod());
|
||||
SGGeod rotate = rwy->pointOnCenterline(105.0+accelDistance);
|
||||
wpt = cloneWithPos(wpt, "SOC", rotate);
|
||||
wpt->altitude = airportElev+1000;
|
||||
wpt->on_ground = false;
|
||||
waypoints.push_back(wpt);
|
||||
|
@ -367,7 +381,7 @@ void FGAIFlightPlan::createTakeOff(bool firstFlight, FGAirport *apt, double spee
|
|||
wpt->altitude = airportElev+3000;
|
||||
waypoints.push_back(wpt);
|
||||
|
||||
// Finally, add two more waypoints, so that aircraft will remain under
|
||||
// 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);
|
||||
|
|
|
@ -9,7 +9,7 @@ class FGAIAircraft;
|
|||
/**
|
||||
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<EFBFBD>rster <t.foerster@biologie.hu-berlin.de>
|
||||
*/
|
||||
class PerformanceData
|
||||
{
|
||||
|
@ -38,10 +38,11 @@ public:
|
|||
|
||||
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;
|
||||
|
|
|
@ -3,6 +3,9 @@
|
|||
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(
|
||||
|
|
|
@ -26,40 +26,89 @@
|
|||
XMLLoader::XMLLoader() {}
|
||||
XMLLoader::~XMLLoader() {}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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) {
|
||||
//cerr << "unable to read " << parkpath.str() << endl;
|
||||
}
|
||||
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);
|
||||
|
||||
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 (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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -22,11 +22,12 @@ class FGAirportDynamics;
|
|||
class FGRunwayPreference;
|
||||
|
||||
|
||||
|
||||
class XMLLoader {
|
||||
public:
|
||||
XMLLoader();
|
||||
~XMLLoader();
|
||||
|
||||
static string expandICAODirs(const string in);
|
||||
static void load(FGRunwayPreference* p);
|
||||
static void load(FGAirportDynamics* d);
|
||||
|
||||
|
|
|
@ -208,9 +208,11 @@ void FGGlobals::set_fg_scenery (const string &scenery) {
|
|||
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 );
|
||||
|
@ -219,7 +221,7 @@ void FGGlobals::set_fg_scenery (const string &scenery) {
|
|||
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", ""]
|
||||
|
|
|
@ -427,7 +427,7 @@ bool FGAISchedule::update(time_t now)
|
|||
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,
|
||||
|
|
Loading…
Add table
Reference in a new issue