]> git.mxchange.org Git - flightgear.git/blob - src/AIModel/performancedata.cxx
Support helipad names in the --runway startup option
[flightgear.git] / src / AIModel / performancedata.cxx
1
2 #ifdef HAVE_CONFIG_H
3 #  include "config.h"
4 #endif
5
6 #include "performancedata.hxx"
7
8 #include <simgear/props/props.hxx>
9 #include "AIAircraft.hxx"
10
11 // For now, make this a define
12 // Later on, additional class variables can simulate settings such as braking power
13 // also, the performance parameters can be tweaked a little to add some personality
14 // to the AIAircraft.
15 #define BRAKE_SETTING 1.6
16
17 PerformanceData::PerformanceData() :
18   _acceleration(4.0),
19   _deceleration(2.0),
20   _climbRate(3000.0),
21   _descentRate(1500.0),
22   _vRotate(150.0),
23   _vTakeOff(160.0),
24   _vClimb(300.0),
25   _vCruise(430.0),
26   _vDescent(300.0),
27   _vApproach(170.0),
28   _vTouchdown(150.0),
29   _vTaxi(15.0)
30 {
31   _rollrate = 9.0; // degrees per second
32   _maxbank = 30.0; // passenger friendly bank angle
33
34 }
35
36 PerformanceData::PerformanceData(PerformanceData* clone) :
37   _acceleration(clone->_acceleration),
38   _deceleration(clone->_deceleration),
39   _climbRate(clone->_climbRate),
40   _descentRate(clone->_descentRate),
41   _vRotate(clone->_vRotate),
42   _vTakeOff(clone->_vTakeOff),
43   _vClimb(clone->_vClimb),
44   _vCruise(clone->_vCruise),
45   _vDescent(clone->_vDescent),
46   _vApproach(clone->_vApproach),
47   _vTouchdown(clone->_vTouchdown),
48   _vTaxi(clone->_vTaxi)
49 {
50   _rollrate = clone->_rollrate;
51   _maxbank = clone->_maxbank;
52 }
53
54 PerformanceData::~PerformanceData()
55 {}
56
57 void PerformanceData::initFromProps(SGPropertyNode *db_node)
58 {
59 // read the values, using the existing values as defaults
60   _acceleration = db_node->getDoubleValue("acceleration-kts-hour", _acceleration);
61   _deceleration = db_node->getDoubleValue("deceleration-kts-hour", _deceleration);
62   _climbRate    = db_node->getDoubleValue("climbrate-fpm", _climbRate);
63   _descentRate  = db_node->getDoubleValue("decentrate-fpm", _descentRate);
64   _vRotate      = db_node->getDoubleValue("rotate-speed-kts", _vRotate);
65   _vTakeOff     = db_node->getDoubleValue("takeoff-speed-kts", _vTakeOff);
66   _vClimb       = db_node->getDoubleValue("climb-speed-kts", _vClimb);
67   _vCruise      = db_node->getDoubleValue("cruise-speed-kts", _vCruise);
68   _vDescent     = db_node->getDoubleValue("decent-speed-kts", _vDescent);
69   _vApproach    = db_node->getDoubleValue("approach-speed-kts", _vApproach);
70   _vTouchdown   = db_node->getDoubleValue("touchdown-speed-kts", _vTouchdown);
71   _vTaxi        = db_node->getDoubleValue("taxi-speed-kts", _vTaxi);
72 }
73
74 double PerformanceData::actualSpeed(FGAIAircraft* ac, double tgt_speed, double dt, bool maxBrakes) {
75     // if (tgt_speed > _vTaxi & ac->onGround()) // maximum taxi speed on ground
76     //    tgt_speed = _vTaxi;
77     // bad idea for a take off roll :-)
78
79     double speed = ac->getSpeed();
80     double speed_diff = tgt_speed - speed;
81
82     if (speed_diff > 0.0)        // need to accelerate
83     {
84         speed += _acceleration * dt;
85         if ( speed > tgt_speed )
86             speed = tgt_speed;
87
88     } else if (speed_diff < 0.0) { // decelerate
89         if (ac->onGround()) {
90             // deceleration performance is better due to wheel brakes.
91             double brakePower = 0;
92             if (maxBrakes) {
93                 brakePower = 3;
94             } else {
95                 brakePower = BRAKE_SETTING;
96             }
97             speed -= brakePower * _deceleration * dt;
98         } else {
99             speed -= _deceleration * dt;
100         }
101
102         if ( speed < tgt_speed )
103             speed = tgt_speed;
104
105     }
106
107     return speed;
108 }
109
110 double PerformanceData::decelerationOnGround() const
111 {
112   return _deceleration * BRAKE_SETTING;
113 }
114
115 double PerformanceData::actualBankAngle(FGAIAircraft* ac, double tgt_roll, double dt) {
116     // check maximum bank angle
117     if (fabs(tgt_roll) > _maxbank)
118         tgt_roll = _maxbank * tgt_roll/fabs(tgt_roll);
119
120     double roll = ac->getRoll();
121     double bank_diff = tgt_roll - roll;
122
123     if (fabs(bank_diff) > 0.2) {
124         if (bank_diff > 0.0) {
125             roll += _rollrate * dt;
126             if (roll > tgt_roll)
127                 roll = tgt_roll;
128         }
129         else if (bank_diff < 0.0) {
130             roll -= _rollrate * dt;
131
132             if (roll < tgt_roll)
133                 roll = tgt_roll;
134         }
135         //while (roll > 180) roll -= 360;
136         //while (roll < 180) roll += 360;
137     }
138
139     return roll;
140 }
141
142 double PerformanceData::actualPitch(FGAIAircraft* ac, double tgt_pitch, double dt) {
143     double pitch = ac->getPitch();
144     double pdiff = tgt_pitch - pitch;
145
146     if (pdiff > 0.0) { // nose up
147         pitch += 0.005*_climbRate * dt / 3.0; //TODO avoid hardcoded 3 secs
148
149         if (pitch > tgt_pitch)
150             pitch = tgt_pitch;
151     } else if (pdiff < 0.0) { // nose down
152         pitch -= 0.002*_descentRate * dt / 3.0;
153
154         if (pitch < tgt_pitch)
155             pitch = tgt_pitch;
156     }
157
158     return pitch;
159 }
160
161 double PerformanceData::actualAltitude(FGAIAircraft* ac, double tgt_altitude, double dt) {
162     if (ac->onGround()) {
163         //FIXME: a return sensible value here
164         return 0.0; // 0 for now to avoid compiler errors
165     } else
166         return ac->getAltitude() + ac->getVerticalSpeed()*dt/60.0;
167 }
168
169 double PerformanceData::actualVerticalSpeed(FGAIAircraft* ac, double tgt_vs, double dt) {
170     double vs = ac->getVerticalSpeed();
171     double vs_diff = tgt_vs - vs;
172
173     if (fabs(vs_diff) > .001) {
174         if (vs_diff > 0.0) {
175             vs += _climbRate * dt / 3.0; //TODO avoid hardcoded 3 secs to attain climb rate from level flight
176
177             if (vs > tgt_vs)
178                 vs = tgt_vs;
179         } else if (vs_diff < 0.0) {
180             vs -= _descentRate * dt / 3.0;
181
182             if (vs < tgt_vs)
183                 vs = tgt_vs;
184         }
185     }
186
187     return vs;
188 }
189
190 bool PerformanceData::gearExtensible(const FGAIAircraft* ac) {
191     return (ac->altitudeAGL() < 900.0)
192             && (ac->airspeed() < _vTouchdown * 1.25);
193 }