1
0
Fork 0

Thomas Foerster: Prepare for the inclusion of aircraft specific performance

data for AI traffic. Default performance classes are still available as a
backup. This database will allow the calculation of aircraft-specific
take-off speed and estimate runway lenght requirements. Further added
rudimentary support for take-off and landing rotation of AIAircraft.
This commit is contained in:
durk 2007-06-28 07:47:20 +00:00
parent 0b84cddee7
commit 1613d7e63e
7 changed files with 448 additions and 214 deletions

View file

@ -43,28 +43,15 @@
SG_USING_STD(string);
#include "AIAircraft.hxx"
#include "performancedata.hxx"
#include "performancedb.hxx"
//#include <Airports/trafficcontroller.hxx>
static string tempReg;
//
// accel, decel, climb_rate, descent_rate, takeoff_speed, climb_speed,
// cruise_speed, descent_speed, land_speed
//
const FGAIAircraft::PERF_STRUCT FGAIAircraft::settings[] = {
// light aircraft
{2.0, 2.0, 450.0, 1000.0, 70.0, 80.0, 100.0, 80.0, 60.0},
// ww2_fighter
{4.0, 2.0, 3000.0, 1500.0, 110.0, 180.0, 250.0, 200.0, 100.0},
// jet_transport
{5.0, 2.0, 3000.0, 1500.0, 140.0, 300.0, 430.0, 300.0, 130.0},
// jet_fighter
{7.0, 3.0, 4000.0, 2000.0, 150.0, 350.0, 500.0, 350.0, 150.0},
// tanker
{5.0, 2.0, 3000.0, 1500.0, 140.0, 300.0, 430.0, 300.0, 130.0},
// ufo (extreme accel/decel)
{30.0, 30.0, 6000.0, 6000.0, 150.0, 300.0, 430.0, 300.0, 130.0}
};
class AI_OutOfSight{};
class FP_Inactive{};
FGAIAircraft::FGAIAircraft(FGAISchedule *ref) : FGAIBase(otAircraft) {
trafficRef = ref;
@ -92,6 +79,8 @@ FGAIAircraft::FGAIAircraft(FGAISchedule *ref) : FGAIBase(otAircraft) {
headingChangeRate = 0.0;
holdPos = false;
_performance = 0; //TODO initialize to JET_TRANSPORT from PerformanceDB
}
@ -138,62 +127,36 @@ void FGAIAircraft::update(double dt) {
Transform();
}
void FGAIAircraft::setPerformance(const std::string& acclass) {
if (acclass == "light") {
SetPerformance(&FGAIAircraft::settings[FGAIAircraft::LIGHT]);
} else if (acclass == "ww2_fighter") {
SetPerformance(&FGAIAircraft::settings[FGAIAircraft::WW2_FIGHTER]);
} else if (acclass == "jet_transport") {
SetPerformance(&FGAIAircraft::settings[FGAIAircraft::JET_TRANSPORT]);
} else if (acclass == "jet_fighter") {
SetPerformance(&FGAIAircraft::settings[FGAIAircraft::JET_FIGHTER]);
} else if (acclass == "tanker") {
SetPerformance(&FGAIAircraft::settings[FGAIAircraft::JET_TRANSPORT]);
} else if (acclass == "ufo") {
SetPerformance(&FGAIAircraft::settings[FGAIAircraft::UFO]);
} else {
SetPerformance(&FGAIAircraft::settings[FGAIAircraft::JET_TRANSPORT]);
}
}
static PerformanceDB perfdb; //TODO make it a global service
setPerformance(perfdb.getDataFor(acclass));
}
void FGAIAircraft::SetPerformance(const PERF_STRUCT *ps) {
performance = ps;
}
void FGAIAircraft::setPerformance(PerformanceData *ps) {
_performance = ps;
}
void FGAIAircraft::Run(double dt) {
void FGAIAircraft::Run(double dt) {
FGAIAircraft::dt = dt;
FGAIAircraft::dt = dt;
if (!updateTargetValues())
return;
try {
updatePrimaryTargetValues(); // target hdg, alt, speed
}
catch (AI_OutOfSight) {
return;
}
catch (FP_Inactive) {
return;
}
if (controller) {
controller->update(getID(),
pos.getLatitudeDeg(),
pos.getLongitudeDeg(),
hdg,
speed,
altitude_ft, dt);
processATC(controller->getInstruction(getID()));
}
handleATCRequests(); // ATC also has a word to say
updateSecondaryTargetValues(); // target roll, vertical speed, pitch
updateActualState();
UpdateRadar(manager);
}
if (no_roll) {
adjustSpeed(groundTargetSpeed);
} else {
adjustSpeed(tgt_speed);
}
updatePosition();
updateHeading();
updateBankAngles();
updateAltitudes();
updateVerticalSpeed();
matchPitchAngle();
UpdateRadar(manager);
}
void FGAIAircraft::AccelTo(double speed) {
@ -352,9 +315,7 @@ void FGAIAircraft::initializeFlightPlan() {
bool FGAIAircraft::_getGearDown() const {
return ((props->getFloatValue("position/altitude-agl-ft") < 900.0)
&& (props->getFloatValue("velocities/airspeed-kt")
< performance->land_speed*1.25));
return _performance->gearExtensible(this);
}
@ -403,8 +364,8 @@ void FGAIAircraft::getGroundElev(double dt) {
// to prevent all IA objects doing this in synchrony
if (dt_elev_count < (3.0) + (rand() % 10))
return;
else
dt_elev_count = 0;
dt_elev_count = 0;
// Only do the proper hitlist stuff if we are within visible range of the viewer.
if (!invisible) {
@ -511,6 +472,17 @@ void FGAIAircraft::announcePositionToController() {
void FGAIAircraft::processATC(FGATCInstruction instruction) {
if (instruction.getCheckForCircularWait()) {
// This is not exactly an elegant solution,
// but at least it gives me a chance to check
// if circular waits are resolved.
// For now, just take the offending aircraft
// out of the scene
setDie(true);
// a more proper way should be - of course - to
// let an offending aircraft take an evasive action
// for instance taxi back a little bit.
}
//cerr << "Processing ATC instruction (not Implimented yet)" << endl;
if (instruction.getHoldPattern ()) {}
@ -755,7 +727,7 @@ void FGAIAircraft::controlSpeed(FGAIFlightPlan::waypoint* curr, FGAIFlightPlan::
/**
* Update target values (heading, alt, speed) depending on flight plan or control properties
*/
bool FGAIAircraft::updateTargetValues() {
void FGAIAircraft::updatePrimaryTargetValues() {
if (fp) // AI object has a flightplan
{
//TODO make this a function of AIBase
@ -767,13 +739,13 @@ bool FGAIAircraft::updateTargetValues() {
// Are repositioned to the correct ground altitude when the user flies within visibility range.
// In addition, check whether we are out of user range, so this aircraft
// can be deleted.
if (no_roll) {
if (onGround()) {
Transform(); // make sure aip is initialized.
if (trafficRef) {
//cerr << trafficRef->getRegistration() << " Setting altitude to " << altitude_ft;
if (! aiTrafficVisible()) {
setDie(true);
return false;
throw AI_OutOfSight();
}
getGroundElev(dt);
doGroundAltitude();
@ -781,7 +753,7 @@ bool FGAIAircraft::updateTargetValues() {
pos.setElevationFt(altitude_ft);
}
}
return false;
throw FP_Inactive();
}
}
else {
@ -813,39 +785,8 @@ bool FGAIAircraft::updateTargetValues() {
AccelTo( props->getDoubleValue("controls/flight/target-spd" ) );
}
return true;
}
/**
* Adjust the speed (accelerate/decelerate) to tgt_speed.
*/
void FGAIAircraft::adjustSpeed(double tgt_speed) {
double speed_diff = tgt_speed - speed;
speed_diff = groundTargetSpeed - speed;
if (speed_diff > 0.0) // need to accelerate
{
speed += performance->accel * dt;
if ( speed > tgt_speed )
speed = tgt_speed;
} else if (speed_diff < 0.0) {
if (no_roll) {
// on ground (aircraft can't roll)
// deceleration performance is better due to wheel brakes.
speed -= performance->decel * dt * 3;
} else {
speed -= performance->decel * dt;
}
if ( speed < tgt_speed )
speed = tgt_speed;
}
}
void FGAIAircraft::updatePosition() {
// convert speed to degrees per second
double speed_north_deg_sec = cos( hdg * SGD_DEGREES_TO_RADIANS )
@ -871,7 +812,7 @@ void FGAIAircraft::updateHeading() {
//else
// turnConstant = 0.088362;
// If on ground, calculate heading change directly
if (no_roll) {
if (onGround()) {
double headingDiff = fabs(hdg-tgt_heading);
if (headingDiff > 180)
@ -922,7 +863,7 @@ void FGAIAircraft::updateHeading() {
}
void FGAIAircraft::updateBankAngles() {
void FGAIAircraft::updateBankAngleTarget() {
// adjust target bank angle if heading lock engaged
if (hdg_lock) {
double bank_sense = 0.0;
@ -938,55 +879,37 @@ void FGAIAircraft::updateBankAngles() {
} else {
bank_sense = -1.0; // left turn
}
if (diff < 30) {
if (diff < _performance->maximumBankAngle()) {
tgt_roll = diff * bank_sense;
} else {
tgt_roll = 30.0 * bank_sense;
tgt_roll = _performance->maximumBankAngle() * bank_sense;
}
if ((fabs((double) spinCounter) > 1) && (diff > 30)) {
if ((fabs((double) spinCounter) > 1) && (diff > _performance->maximumBankAngle())) {
tgt_speed *= 0.999; // Ugly hack: If aircraft get stuck, they will continually spin around.
// The only way to resolve this is to make them slow down.
}
}
// adjust bank angle, use 9 degrees per second
double bank_diff = tgt_roll - roll;
if (fabs(bank_diff) > 0.2) {
if (bank_diff > 0.0)
roll += 9.0 * dt;
if (bank_diff < 0.0)
roll -= 9.0 * dt;
//while (roll > 180) roll -= 360;
//while (roll < 180) roll += 360;
}
}
void FGAIAircraft::updateAltitudes() {
// adjust altitude (meters) based on current vertical speed (fpm)
altitude_ft += vs / 60.0 * dt;
pos.setElevationFt(altitude_ft);
void FGAIAircraft::updateVerticalSpeedTarget() {
// adjust target Altitude, based on ground elevation when on ground
if (no_roll) {
if (onGround()) {
getGroundElev(dt);
doGroundAltitude();
} else {
// find target vertical speed if altitude lock engaged
if (alt_lock && use_perf_vs) {
} else if (alt_lock) {
// find target vertical speed
if (use_perf_vs) {
if (altitude_ft < tgt_altitude_ft) {
tgt_vs = tgt_altitude_ft - altitude_ft;
if (tgt_vs > performance->climb_rate)
tgt_vs = performance->climb_rate;
if (tgt_vs > _performance->climbRate())
tgt_vs = _performance->climbRate();
} else {
tgt_vs = tgt_altitude_ft - altitude_ft;
if (tgt_vs < (-performance->descent_rate))
tgt_vs = -performance->descent_rate;
if (tgt_vs < (-_performance->descentRate()))
tgt_vs = -_performance->descentRate();
}
}
if (alt_lock && !use_perf_vs) {
} else {
double max_vs = 4*(tgt_altitude_ft - altitude_ft);
double min_vs = 100;
if (tgt_altitude_ft < altitude_ft)
@ -998,34 +921,64 @@ void FGAIAircraft::updateAltitudes() {
if (fabs(tgt_vs) < fabs(min_vs))
tgt_vs = min_vs;
}
}
} //else
// tgt_vs = 0.0;
}
void FGAIAircraft::updatePitchAngleTarget() {
// if on ground and above vRotate -> initial rotation
if (onGround() && (speed > _performance->vRotate()))
tgt_pitch = 8.0; // some rough B737 value
void FGAIAircraft::updateVerticalSpeed() {
// adjust vertical speed
double vs_diff = tgt_vs - vs;
if (fabs(vs_diff) > 10.0) {
if (vs_diff > 0.0) {
vs += (performance->climb_rate / 3.0) * dt;
if (vs > tgt_vs)
vs = tgt_vs;
} else {
vs -= (performance->descent_rate / 3.0) * dt;
if (vs < tgt_vs)
vs = tgt_vs;
}
}
}
void FGAIAircraft::matchPitchAngle() {
//TODO pitch angle on approach and landing
// match pitch angle to vertical speed
if (vs > 0) {
pitch = vs * 0.005;
else if (tgt_vs > 0) {
tgt_pitch = tgt_vs * 0.005;
} else {
pitch = vs * 0.002;
tgt_pitch = tgt_vs * 0.002;
}
}
void FGAIAircraft::handleATCRequests() {
//TODO implement NullController for having no ATC to save the conditionals
if (controller) {
controller->update(getID(),
pos.getLatitudeDeg(),
pos.getLongitudeDeg(),
hdg,
speed,
altitude_ft, dt);
processATC(controller->getInstruction(getID()));
}
}
void FGAIAircraft::updateActualState() {
//update current state
//TODO have a single tgt_speed and check speed limit on ground on setting tgt_speed
updatePosition();
if (onGround())
speed = _performance->actualSpeed(this, groundTargetSpeed, dt);
else
speed = _performance->actualSpeed(this, tgt_speed, dt);
updateHeading();
roll = _performance->actualBankAngle(this, tgt_roll, dt);
// adjust altitude (meters) based on current vertical speed (fpm)
altitude_ft += vs / 60.0 * dt;
pos.setElevationFt(altitude_ft);
vs = _performance->actualVerticalSpeed(this, tgt_vs, dt);
pitch = _performance->actualPitch(this, tgt_pitch, dt);
}
void FGAIAircraft::updateSecondaryTargetValues() {
// derived target state values
updateBankAngleTarget();
updateVerticalSpeedTarget();
updatePitchAngleTarget();
//TODO calculate wind correction angle (tgt_yaw)
}

View file

@ -30,33 +30,11 @@
#include <string>
SG_USING_STD(string);
class PerformanceData;
class FGAIAircraft : public FGAIBase {
private:
typedef struct {
double accel;
double decel;
double climb_rate;
double descent_rate;
double takeoff_speed;
double climb_speed;
double cruise_speed;
double descent_speed;
double land_speed;
} PERF_STRUCT;
public:
enum aircraft_e {
LIGHT = 0,
WW2_FIGHTER,
JET_TRANSPORT,
JET_FIGHTER,
TANKER,
UFO
};
static const PERF_STRUCT settings[];
FGAIAircraft(FGAISchedule *ref=0);
~FGAIAircraft();
@ -68,32 +46,45 @@ public:
virtual void update(double dt);
void setPerformance(const std::string& perfString);
void SetPerformance(const PERF_STRUCT *ps);
void setPerformance(PerformanceData *ps);
void setFlightPlan(const std::string& fp, bool repat = false);
void SetFlightPlan(FGAIFlightPlan *f);
void initializeFlightPlan();
FGAIFlightPlan* GetFlightPlan() const { return fp; };
void ProcessFlightPlan( double dt, time_t now );
void AccelTo(double speed);
void PitchTo(double angle);
void RollTo(double angle);
void YawTo(double angle);
void ClimbTo(double altitude);
void TurnTo(double heading);
void ProcessFlightPlan( double dt, time_t now );
void setCallSign(const string& );
void getGroundElev(double dt);
void getGroundElev(double dt); //TODO these 3 really need to be public?
void doGroundAltitude();
void loadNextLeg ();
void setAcType(const string& ac) { acType = ac; };
void setCompany(const string& comp) { company = comp;};
void announcePositionToController();
void announcePositionToController(); //TODO have to be public?
void processATC(FGATCInstruction instruction);
virtual const char* getTypeString(void) const { return "aircraft"; }
// included as performance data needs them, who else?
inline bool onGround() const { return no_roll; };
inline double getSpeed() const { return speed; };
inline double getRoll() const { return roll; };
inline double getPitch() const { return pitch; };
inline double getAltitude() const { return altitude_ft; };
inline double getVerticalSpeed() const { return vs; };
inline double altitudeAGL() const { return props->getFloatValue("position/altitude-agl-ft");};
inline double airspeed() const { return props->getFloatValue("velocities/airspeed-kt");};
protected:
void Run(double dt);
@ -110,11 +101,12 @@ private:
double groundOffset;
double dt;
const PERF_STRUCT *performance;
bool use_perf_vs;
SGPropertyNode_ptr refuel_node;
// helpers for Run
//TODO sort out which ones are better protected virtuals to allow
//subclasses to override specific behaviour
bool fpExecutable(time_t now);
void handleFirstWaypoint(void);
bool leadPointReached(FGAIFlightPlan::waypoint* curr);
@ -122,16 +114,17 @@ private:
bool aiTrafficVisible(void);
void controlHeading(FGAIFlightPlan::waypoint* curr);
void controlSpeed(FGAIFlightPlan::waypoint* curr,
FGAIFlightPlan::waypoint* next);
bool updateTargetValues();
void adjustSpeed(double tgt_speed);
FGAIFlightPlan::waypoint* next);
void updatePrimaryTargetValues();
void updateSecondaryTargetValues();
void updatePosition();
void updateHeading();
void updateBankAngles();
void updateAltitudes();
void updateVerticalSpeed();
void matchPitchAngle();
void updateBankAngleTarget();
void updateVerticalSpeedTarget();
void updatePitchAngleTarget();
void updateActualState();
void handleATCRequests();
double sign(double x);
string acType;
@ -146,6 +139,8 @@ private:
bool _getGearDown() const;
bool reachedWaypoint;
string callsign; // The callsign of this tanker.
PerformanceData* _performance; // the performance data for this aircraft
};

View file

@ -1,19 +1,20 @@
noinst_LIBRARIES = libAIModel.a
libAIModel_a_SOURCES = submodel.cxx submodel.hxx \
AIManager.hxx AIManager.cxx \
AIBase.hxx AIBase.cxx \
AIAircraft.hxx AIAircraft.cxx AIMultiplayer.hxx \
AIMultiplayer.cxx \
AIShip.hxx AIShip.cxx \
AIBallistic.hxx AIBallistic.cxx \
AIStorm.hxx AIStorm.cxx \
AIThermal.hxx AIThermal.cxx \
AIFlightPlan.hxx AIFlightPlan.cxx \
AIFlightPlanCreate.cxx \
AIFlightPlanCreateCruise.cxx \
AICarrier.hxx AICarrier.cxx \
AIStatic.hxx AIStatic.cxx \
AITanker.cxx AITanker.hxx
libAIModel_a_SOURCES = submodel.cxx submodel.hxx \
AIManager.hxx AIManager.cxx \
AIBase.hxx AIBase.cxx \
AIAircraft.hxx AIAircraft.cxx \
AIMultiplayer.hxx AIMultiplayer.cxx \
AIShip.hxx AIShip.cxx \
AIBallistic.hxx AIBallistic.cxx \
AIStorm.hxx AIStorm.cxx \
AIThermal.hxx AIThermal.cxx \
AIFlightPlan.hxx AIFlightPlan.cxx \
AIFlightPlanCreate.cxx AIFlightPlanCreateCruise.cxx \
AICarrier.hxx AICarrier.cxx \
AIStatic.hxx AIStatic.cxx \
AITanker.cxx AITanker.hxx \
performancedata.cxx performancedata.hxx \
performancedb.cxx performancedb.hxx
INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/src

View file

@ -0,0 +1,148 @@
#include "performancedata.hxx"
#include "AIAircraft.hxx"
PerformanceData::PerformanceData(double acceleration,
double deceleration,
double climbRate,
double descentRate,
double vRotate,
double vTakeOff,
double vClimb,
double vCruise,
double vDescent,
double vApproach,
double vTouchdown,
double vTaxi) :
_acceleration(acceleration),
_deceleration(deceleration),
_climbRate(climbRate),
_descentRate(descentRate),
_vRotate(vRotate),
_vTakeOff(vTakeOff),
_vClimb(vClimb),
_vCruise(vCruise),
_vDescent(vDescent),
_vApproach(vApproach),
_vTouchdown(vTouchdown),
_vTaxi(vTaxi)
{
_rollrate = 9.0; // degrees per second
_maxbank = 30.0; // passenger friendly bank angle
}
// read perf data from file
PerformanceData::PerformanceData( const std::string& filename)
{}
PerformanceData::~PerformanceData()
{}
double PerformanceData::actualSpeed(FGAIAircraft* ac, double tgt_speed, double dt) {
// if (tgt_speed > _vTaxi & ac->onGround()) // maximum taxi speed on ground
// tgt_speed = _vTaxi;
// bad idea for a take off roll :-)
double speed = ac->getSpeed();
double speed_diff = tgt_speed - speed;
if (speed_diff > 0.0) // need to accelerate
{
speed += _acceleration * dt;
if ( speed > tgt_speed )
speed = tgt_speed;
} else if (speed_diff < 0.0) { // decelerate
if (ac->onGround()) {
// deceleration performance is better due to wheel brakes.
speed -= 3 * _deceleration * dt;
} else {
speed -= _deceleration * dt;
}
if ( speed < tgt_speed )
speed = tgt_speed;
}
return speed;
}
double PerformanceData::actualBankAngle(FGAIAircraft* ac, double tgt_roll, double dt) {
// check maximum bank angle
if (fabs(tgt_roll) > _maxbank)
tgt_roll = _maxbank * tgt_roll/fabs(tgt_roll);
double roll = ac->getRoll();
double bank_diff = tgt_roll - roll;
if (fabs(bank_diff) > 0.2) {
if (bank_diff > 0.0) {
roll += _rollrate * dt;
if (roll > tgt_roll)
roll = tgt_roll;
}
else if (bank_diff < 0.0) {
roll -= _rollrate * dt;
if (roll < tgt_roll)
roll = tgt_roll;
}
//while (roll > 180) roll -= 360;
//while (roll < 180) roll += 360;
}
return roll;
}
double PerformanceData::actualPitch(FGAIAircraft* ac, double tgt_pitch, double dt) {
double pitch = ac->getPitch();
double pdiff = tgt_pitch - pitch;
if (pdiff > 0.0) { // nose up
pitch += 0.005*_climbRate * dt / 3.0; //TODO avoid hardcoded 3 secs
if (pitch > tgt_pitch)
pitch = tgt_pitch;
} else if (pdiff < 0.0) { // nose down
pitch -= 0.002*_descentRate * dt / 3.0;
if (pitch < tgt_pitch)
pitch = tgt_pitch;
}
return pitch;
}
double PerformanceData::actualAltitude(FGAIAircraft* ac, double tgt_altitude, double dt) {
if (ac->onGround()) {
} else
return ac->getAltitude() + ac->getVerticalSpeed()*dt/60.0;
}
double PerformanceData::actualVerticalSpeed(FGAIAircraft* ac, double tgt_vs, double dt) {
double vs = ac->getVerticalSpeed();
double vs_diff = tgt_vs - vs;
if (fabs(vs_diff) > 10.0) {
if (vs_diff > 0.0) {
vs += _climbRate * dt / 3.0; //TODO avoid hardcoded 3 secs to attain climb rate from level flight
if (vs > tgt_vs)
vs = tgt_vs;
} else if (vs_diff < 0.0) {
vs -= _descentRate * dt / 3.0;
if (vs < tgt_vs)
vs = tgt_vs;
}
}
return vs;
}
bool PerformanceData::gearExtensible(const FGAIAircraft* ac) {
return (ac->altitudeAGL() < 900.0)
&& (ac->airspeed() < _vTouchdown * 1.25);
}

View file

@ -0,0 +1,64 @@
#ifndef PERFORMANCEDATA_HXX
#define PERFORMANCEDATA_HXX
#include <string>
#include <map>
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>
*/
class PerformanceData
{
public:
PerformanceData(double acceleration,
double deceleration,
double climbRate,
double descentRate,
double vRotate,
double vTakeOff,
double vClimb,
double vCruise,
double vDescent,
double vApproach,
double vTouchdown,
double vTaxi);
PerformanceData(const std::string& filename);
~PerformanceData();
double actualSpeed(FGAIAircraft* ac, double tgt_speed, double dt);
double actualBankAngle(FGAIAircraft* ac, double tgt_roll, double dt);
double actualPitch(FGAIAircraft* ac, double tgt_pitch, double dt);
double actualHeading(FGAIAircraft* ac, double tgt_heading, double dt);
double actualAltitude(FGAIAircraft* ac, double tgt_altitude, double dt);
double actualVerticalSpeed(FGAIAircraft* ac, double tgt_vs, double dt);
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; };
private:
double _acceleration;
double _deceleration;
double _climbRate;
double _descentRate;
double _vRotate;
double _vTakeOff;
double _vClimb;
double _vCruise;
double _vDescent;
double _vApproach;
double _vTouchdown;
double _vTaxi;
double _rollrate;
double _maxbank;
};
#endif

View file

@ -0,0 +1,40 @@
#include "performancedb.hxx"
PerformanceDB::PerformanceDB()
{
// these are the 6 classes originally defined in the PERFSTRUCT
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(
4.0, 2.0, 3000.0, 1500.0, 110.0, 110.0, 180.0, 250.0, 200.0, 130.0, 100.0, 15.0));
registerPerformanceData("jet_fighter", new PerformanceData(
7.0, 3.0, 4000.0, 2000.0, 120.0, 150.0, 350.0, 500.0, 350.0, 170.0, 150.0, 15.0));
registerPerformanceData("jet_transport", new PerformanceData(
5.0, 2.0, 3000.0, 1500.0, 100.0, 140.0, 300.0, 430.0, 300.0, 170.0, 130.0, 15.0));
registerPerformanceData("tanker", new PerformanceData(
5.0, 2.0, 3000.0, 1500.0, 100.0, 140.0, 300.0, 430.0, 300.0, 170.0, 130.0, 15.0));
registerPerformanceData("ufo", new PerformanceData(
30.0, 30.0, 6000.0, 6000.0, 150.0, 150.0, 300.0, 430.0, 300.0, 170.0, 130.0, 15.0));
}
PerformanceDB::~PerformanceDB()
{}
void PerformanceDB::registerPerformanceData(const std::string& id, PerformanceData* data) {
//TODO if key exists already replace data "inplace", i.e. copy to existing PerfData instance
// this updates all aircraft currently using the PerfData instance.
_db[id] = data;
}
void PerformanceDB::registerPerformanceData(const std::string& id, const std::string& filename) {
registerPerformanceData(id, new PerformanceData(filename));
}
PerformanceData* PerformanceDB::getDataFor(const std::string& id) {
if (_db.find(id) == _db.end()) // id not found -> return jet_transport data
return _db["jet_transport"];
return _db[id];
}

View file

@ -0,0 +1,33 @@
#ifndef PERFORMANCEDB_HXX
#define PERFORMANCEDB_HXX
#include <string>
#include <map>
#include "performancedata.hxx"
/**
* Registry for performance data.
*
* Allows to store performance data for later reuse/retrieval. Just
* a simple map for now.
*
* @author Thomas Förster <t.foerster@biologie.hu-berlin.de>
*/
//TODO provide std::map interface?
class PerformanceDB
{
public:
PerformanceDB();
~PerformanceDB();
void registerPerformanceData(const std::string& id, PerformanceData* data);
void registerPerformanceData(const std::string& id, const std::string& filename);
PerformanceData* getDataFor(const std::string& id);
private:
std::map<std::string, PerformanceData*> _db;
};
#endif