FlightGear next
performancedata.cxx
Go to the documentation of this file.
1
2#include "config.h"
3
4
5
6#include <simgear/props/props.hxx>
7
8#include "AIAircraft.hxx"
9
10#include "performancedata.hxx"
11
12// For now, make this a define
13// Later on, additional class variables can simulate settings such as braking power
14// also, the performance parameters can be tweaked a little to add some personality
15// to the AIAircraft.
16#define BRAKE_SETTING 1.6
17
18
24
25PerformanceData::PerformanceData() : _acceleration(4.0),
26 _deceleration(2.0),
27 _brakeDeceleration(20.0),
28 _climbRate(3000.0),
29 _descentRate(1500.0),
30 _vRotate(150.0),
31 _vTakeOff(160.0),
32 _vClimb(300.0),
33 _vCruise(430.0),
34 _vDescent(300.0),
35 _vApproach(170.0),
36 _vTouchdown(150.0),
37 _vTaxi(15.0),
38 _wingSpan(100.0),
39 _wingChord(12.0),
40 _weight(90000.0)
41{
42 _rollrate = 9.0; // degrees per second
43 _maxbank = 30.0; // passenger friendly bank angle
44}
45
46PerformanceData::PerformanceData(const PerformanceData* clone) : _acceleration(clone->_acceleration),
47 _deceleration(clone->_deceleration),
48 _brakeDeceleration(clone->_brakeDeceleration),
49 _climbRate(clone->_climbRate),
50 _descentRate(clone->_descentRate),
51 _vRotate(clone->_vRotate),
52 _vTakeOff(clone->_vTakeOff),
53 _vClimb(clone->_vClimb),
54 _vCruise(clone->_vCruise),
55 _vDescent(clone->_vDescent),
56 _vApproach(clone->_vApproach),
57 _vTouchdown(clone->_vTouchdown),
58 _vTaxi(clone->_vTaxi),
59 _wingSpan(clone->_wingSpan),
60 _wingChord(clone->_wingChord),
61 _weight(clone->_weight)
62{
63 _rollrate = clone->_rollrate;
64 _maxbank = clone->_maxbank;
65}
66
67// helper to try various names of a property, in order.
68static double readRenamedProp(SGPropertyNode_ptr db, const string_list& namesToTry, double defValue)
69{
70 for (const auto& n : namesToTry) {
71 auto node = db->getChild(n);
72 if (node) {
73 return node->getDoubleValue();
74 }
75 }
76
77 return defValue;
78}
79
80void PerformanceData::initFromProps(SGPropertyNode* db_node)
81{
82 // read the values, using the existing values as defaults
83 _acceleration = db_node->getDoubleValue("acceleration-kts-hour", _acceleration);
84 _deceleration = db_node->getDoubleValue("deceleration-kts-hour", _deceleration);
85 _brakeDeceleration = db_node->getDoubleValue("brake-deceleration-kts-hour", _brakeDeceleration);
86
87 _climbRate = readRenamedProp(db_node, {"climb-rate-fpm", "climbrate-fpm"}, _climbRate);
88 _descentRate = readRenamedProp(db_node, {"descent-rate-fpm", "decentrate-fpm"}, _descentRate);
89
90 _vRotate = db_node->getDoubleValue("rotate-speed-kts", _vRotate);
91 _vTakeOff = db_node->getDoubleValue("takeoff-speed-kts", _vTakeOff);
92 _vClimb = db_node->getDoubleValue("climb-speed-kts", _vClimb);
93 _vCruise = db_node->getDoubleValue("cruise-speed-kts", _vCruise);
94
95 _vDescent = readRenamedProp(db_node, {"descent-speed-kts", "decent-speed-kts"}, _vDescent);
96
97 _vApproach = db_node->getDoubleValue("approach-speed-kts", _vApproach);
98 _vTouchdown = db_node->getDoubleValue("touchdown-speed-kts", _vTouchdown);
99 _vTaxi = db_node->getDoubleValue("taxi-speed-kts", _vTaxi);
100 _wingSpan = db_node->getDoubleValue("geometry/wing/span-ft", _wingSpan);
101 _wingChord = db_node->getDoubleValue("geometry/wing/chord-ft", _wingChord);
102 _weight = db_node->getDoubleValue("geometry/weight-lbs", _weight);
103}
104
105double PerformanceData::actualSpeed(const FGAIAircraft* ac, double tgt_speed, double dt, bool maxBrakes)
106{
107 // if (tgt_speed > _vTaxi & ac->onGround()) // maximum taxi speed on ground
108 // tgt_speed = _vTaxi;
109 // bad idea for a take off roll :-)
110
111 double speed = ac->getSpeed();
112 double speed_diff = tgt_speed - speed;
113
114 if (speed_diff > 0.0) // need to accelerate
115 {
116 speed += _acceleration * dt;
117 if (speed > tgt_speed)
118 speed = tgt_speed;
119
120 } else if (speed_diff < 0.0) { // decelerate
121 if (ac->onGround()) {
122 // deceleration performance is better due to wheel brakes.
123 double brakePower = 0;
124 if (maxBrakes) {
125 brakePower = 2;
126 } else {
127 brakePower = 1;
128 }
129 speed -= brakePower * _brakeDeceleration * dt;
130 } else {
131 speed -= _deceleration * dt;
132 }
133
134 if (speed < tgt_speed)
135 speed = tgt_speed;
136 }
137
138 return speed;
139}
140
142{
143 return _brakeDeceleration;
144}
145
146double PerformanceData::actualBankAngle(const FGAIAircraft* ac, double tgt_roll, double dt)
147{
148 // check maximum bank angle
149 if (fabs(tgt_roll) > _maxbank)
150 tgt_roll = _maxbank * tgt_roll / fabs(tgt_roll);
151
152 double roll = ac->getRoll();
153 double bank_diff = tgt_roll - roll;
154
155 if (fabs(bank_diff) > 0.2) {
156 if (bank_diff > 0.0) {
157 roll += _rollrate * dt;
158 if (roll > tgt_roll)
159 roll = tgt_roll;
160 } else if (bank_diff < 0.0) {
161 roll -= _rollrate * dt;
162
163 if (roll < tgt_roll)
164 roll = tgt_roll;
165 }
166 //while (roll > 180) roll -= 360;
167 //while (roll < 180) roll += 360;
168 }
169
170 return roll;
171}
172
173double PerformanceData::actualPitch(const FGAIAircraft* ac, double tgt_pitch, double dt)
174{
175 double pitch = ac->getPitch();
176 double pdiff = tgt_pitch - pitch;
177
178 if (pdiff > 0.0) { // nose up
179 pitch += 0.005 * _climbRate * dt / 3.0; // TODO: avoid hardcoded 3 secs
180
181 if (pitch > tgt_pitch)
182 pitch = tgt_pitch;
183 } else if (pdiff < 0.0) { // nose down
184 pitch -= 0.002 * _descentRate * dt / 3.0;
185
186 if (pitch < tgt_pitch)
187 pitch = tgt_pitch;
188 }
189
190 return pitch;
191}
192
193double PerformanceData::actualAltitude(const FGAIAircraft* ac, double tgt_altitude, double dt)
194{
195 if (ac->onGround()) {
196 //FIXME: a return sensible value here
197 return 0.0; // 0 for now to avoid compiler errors
198 } else
199 return ac->getAltitude() + ac->getVerticalSpeedFPM() * dt / 60.0;
200}
201
202double PerformanceData::actualVerticalSpeed(const FGAIAircraft* ac, double tgt_vs, double dt)
203{
204 double vs = ac->getVerticalSpeedFPM();
205 double vs_diff = tgt_vs - vs;
206
207 if (fabs(vs_diff) > .001) {
208 if (vs_diff > 0.0) {
209 vs += _climbRate * dt / 3.0; // TODO: avoid hardcoded 3 secs to attain climb rate from level flight
210
211 if (vs > tgt_vs)
212 vs = tgt_vs;
213 } else if (vs_diff < 0.0) {
214 vs -= _descentRate * dt / 3.0;
215
216 if (vs < tgt_vs)
217 vs = tgt_vs;
218 }
219 }
220
221 return vs;
222}
223
225{
226 return (ac->altitudeAGL() < 900.0) && (ac->airspeed() < _vTouchdown * 1.25);
227}
static std::unique_ptr< FavouriteAircraftData > static_instance
double getVerticalSpeedFPM() const
double getRoll() const
double getAltitude() const
double getSpeed() const
double getPitch() const
double airspeed() const
double altitudeAGL() const
bool onGround() const
double actualAltitude(const FGAIAircraft *ac, double tgt_altitude, double dt)
double actualVerticalSpeed(const FGAIAircraft *ac, double tgt_vs, double dt)
double actualBankAngle(const FGAIAircraft *ac, double tgt_roll, double dt)
bool gearExtensible(const FGAIAircraft *ac)
double decelerationOnGround() const
double actualPitch(const FGAIAircraft *ac, double tgt_pitch, double dt)
double actualSpeed(const FGAIAircraft *ac, double tgt_speed, double dt, bool needMaxBrake)
static PerformanceData * getDefaultData()
Last-resort fallback performance data.
void initFromProps(SGPropertyNode *props)
std::vector< std::string > string_list
Definition globals.hxx:36
static double readRenamedProp(SGPropertyNode_ptr db, const string_list &namesToTry, double defValue)