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;
headingChangeRate = 0.0;
holdPos = false;
+
+ _performance = 0; //TODO initialize to JET_TRANSPORT from PerformanceDB
}
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) {
+ void FGAIAircraft::setPerformance(PerformanceData *ps) {
+ _performance = ps;
+ }
- performance = ps;
-}
+ void FGAIAircraft::Run(double dt) {
+ FGAIAircraft::dt = dt;
-void FGAIAircraft::Run(double dt) {
+ try {
+ updatePrimaryTargetValues(); // target hdg, alt, speed
+ }
+ catch (AI_OutOfSight) {
+ return;
+ }
+ catch (FP_Inactive) {
+ return;
+ }
- FGAIAircraft::dt = dt;
- if (!updateTargetValues())
- return;
+ handleATCRequests(); // ATC also has a word to say
+ updateSecondaryTargetValues(); // target roll, vertical speed, pitch
+ updateActualState();
+ UpdateRadar(manager);
+ }
- if (controller) {
- controller->update(getID(),
- pos.getLatitudeDeg(),
- pos.getLongitudeDeg(),
- hdg,
- speed,
- altitude_ft, dt);
- processATC(controller->getInstruction(getID()));
- }
-
- if (no_roll) {
- adjustSpeed(groundTargetSpeed);
- } else {
- adjustSpeed(tgt_speed);
- }
-
- updatePosition();
- updateHeading();
- updateBankAngles();
- updateAltitudes();
- updateVerticalSpeed();
- matchPitchAngle();
- UpdateRadar(manager);
-}
void FGAIAircraft::AccelTo(double speed) {
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);
}
// 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) {
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 ()) {}
/**
* 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
// 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();
pos.setElevationFt(altitude_ft);
}
}
- return false;
+ throw FP_Inactive();
}
}
else {
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 )
//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)
}
-void FGAIAircraft::updateBankAngles() {
+void FGAIAircraft::updateBankAngleTarget() {
// adjust target bank angle if heading lock engaged
if (hdg_lock) {
double bank_sense = 0.0;
} 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)
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
+
+ //TODO pitch angle on approach and landing
+
+ // match pitch angle to vertical speed
+ else if (tgt_vs > 0) {
+ tgt_pitch = tgt_vs * 0.005;
+ } else {
+ 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::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;
+void FGAIAircraft::updateActualState() {
+ //update current state
+ //TODO have a single tgt_speed and check speed limit on ground on setting tgt_speed
+ updatePosition();
- if (vs > tgt_vs)
- vs = tgt_vs;
- } else {
- vs -= (performance->descent_rate / 3.0) * dt;
+ if (onGround())
+ speed = _performance->actualSpeed(this, groundTargetSpeed, dt);
+ else
+ speed = _performance->actualSpeed(this, tgt_speed, dt);
- if (vs < tgt_vs)
- vs = tgt_vs;
- }
- }
+ 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();
-void FGAIAircraft::matchPitchAngle() {
- // match pitch angle to vertical speed
- if (vs > 0) {
- pitch = vs * 0.005;
- } else {
- pitch = vs * 0.002;
- }
+ //TODO calculate wind correction angle (tgt_yaw)
}
#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();
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);
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);
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;
bool _getGearDown() const;
bool reachedWaypoint;
string callsign; // The callsign of this tanker.
+
+ PerformanceData* _performance; // the performance data for this aircraft
};
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
--- /dev/null
+#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);
+}
--- /dev/null
+#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
--- /dev/null
+#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];
+}
--- /dev/null
+#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