From: durk Date: Thu, 28 Jun 2007 07:47:20 +0000 (+0000) Subject: Thomas Foerster: Prepare for the inclusion of aircraft specific performance X-Git-Url: https://git.mxchange.org/?a=commitdiff_plain;h=1613d7e63e02ccad8ebdfaaf8359ab34e0b88e7a;p=flightgear.git 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. --- diff --git a/src/AIModel/AIAircraft.cxx b/src/AIModel/AIAircraft.cxx index 19f57f5c2..8cc5089ad 100644 --- a/src/AIModel/AIAircraft.cxx +++ b/src/AIModel/AIAircraft.cxx @@ -43,28 +43,15 @@ SG_USING_STD(string); #include "AIAircraft.hxx" +#include "performancedata.hxx" +#include "performancedb.hxx" + //#include 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) { + 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) { @@ -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 + + //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) } diff --git a/src/AIModel/AIAircraft.hxx b/src/AIModel/AIAircraft.hxx index 035b44bc7..b70c1ea62 100644 --- a/src/AIModel/AIAircraft.hxx +++ b/src/AIModel/AIAircraft.hxx @@ -30,33 +30,11 @@ #include 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 }; diff --git a/src/AIModel/Makefile.am b/src/AIModel/Makefile.am index 4c768c681..30ba83f4b 100644 --- a/src/AIModel/Makefile.am +++ b/src/AIModel/Makefile.am @@ -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 diff --git a/src/AIModel/performancedata.cxx b/src/AIModel/performancedata.cxx new file mode 100644 index 000000000..5c0ebb593 --- /dev/null +++ b/src/AIModel/performancedata.cxx @@ -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); +} diff --git a/src/AIModel/performancedata.hxx b/src/AIModel/performancedata.hxx new file mode 100644 index 000000000..5df158e8e --- /dev/null +++ b/src/AIModel/performancedata.hxx @@ -0,0 +1,64 @@ +#ifndef PERFORMANCEDATA_HXX +#define PERFORMANCEDATA_HXX + +#include +#include + +class FGAIAircraft; + +/** +Data storage for aircraft performance data. This is used to properly simulate the flight of AIAircrafts. + + @author Thomas Förster +*/ +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 diff --git a/src/AIModel/performancedb.cxx b/src/AIModel/performancedb.cxx new file mode 100644 index 000000000..aec66f3d6 --- /dev/null +++ b/src/AIModel/performancedb.cxx @@ -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]; +} diff --git a/src/AIModel/performancedb.hxx b/src/AIModel/performancedb.hxx new file mode 100644 index 000000000..4e397ac27 --- /dev/null +++ b/src/AIModel/performancedb.hxx @@ -0,0 +1,33 @@ +#ifndef PERFORMANCEDB_HXX +#define PERFORMANCEDB_HXX + +#include +#include + +#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 +*/ +//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 _db; +}; + +#endif