PX4 Firmware
PX4 Autopilot Software http://px4.io
tecs.cpp
Go to the documentation of this file.
1 /****************************************************************************
2  *
3  * Copyright (c) 2017 Estimation and Control Library (ECL). All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * 1. Redistributions of source code must retain the above copyright
10  * notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  * notice, this list of conditions and the following disclaimer in
13  * the documentation and/or other materials provided with the
14  * distribution.
15  * 3. Neither the name ECL nor the names of its contributors may be
16  * used to endorse or promote products derived from this software
17  * without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
22  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
23  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
24  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
25  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
26  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
27  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
29  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30  * POSSIBILITY OF SUCH DAMAGE.
31  *
32  ****************************************************************************/
33 
34 #include "tecs.h"
35 
36 #include <ecl.h>
37 #include <geo/geo.h>
38 
39 using math::constrain;
40 using math::max;
41 using math::min;
42 
43 static constexpr float DT_MIN = 0.001f; ///< minimum allowed value of _dt (sec)
44 static constexpr float DT_MAX = 1.0f; ///< max value of _dt allowed before a filter state reset is performed (sec)
45 
46 /**
47  * @file tecs.cpp
48  *
49  * @author Paul Riseborough
50  */
51 
52 /*
53  * This function implements a complementary filter to estimate the climb rate when
54  * inertial nav data is not available. It also calculates a true airspeed derivative
55  * which is used by the airspeed complimentary filter.
56  */
57 void TECS::update_vehicle_state_estimates(float airspeed, const matrix::Dcmf &rotMat,
58  const matrix::Vector3f &accel_body, bool altitude_lock, bool in_air,
59  float altitude, bool vz_valid, float vz, float az)
60 {
61  // calculate the time lapsed since the last update
62  uint64_t now = ecl_absolute_time();
63  float dt = constrain((now - _state_update_timestamp) * 1.0e-6f, DT_MIN, DT_MAX);
64 
65  bool reset_altitude = false;
66 
67  if (_state_update_timestamp == 0 || dt > DT_MAX) {
68  dt = DT_DEFAULT;
69  reset_altitude = true;
70  }
71 
72  if (!altitude_lock || !in_air) {
73  reset_altitude = true;
74  }
75 
76  if (reset_altitude) {
77  _vert_pos_state = altitude;
78 
79  if (vz_valid) {
80  _vert_vel_state = -vz;
81 
82  } else {
83  _vert_vel_state = 0.0f;
84  }
85 
86  _vert_accel_state = 0.0f;
87  _states_initalized = false;
88  }
89 
91  _EAS = airspeed;
92 
93  _in_air = in_air;
94 
95  // Generate the height and climb rate state estimates
96  if (vz_valid) {
97  // Set the velocity and position state to the the INS data
98  _vert_vel_state = -vz;
99  _vert_pos_state = altitude;
100 
101  } else {
102  // Get height acceleration
103  float hgt_ddot_mea = -az;
104 
105  // If we have no vertical INS data, estimate the vertical velocity using a complementary filter
106  // Perform filter calculation using backwards Euler integration
107  // Coefficients selected to place all three filter poles at omega
108  // Reference Paper: Optimising the Gains of the Baro-Inertial Vertical Channel
109  // Widnall W.S, Sinha P.K, AIAA Journal of Guidance and Control, 78-1307R
110  float omega2 = _hgt_estimate_freq * _hgt_estimate_freq;
111  float hgt_err = altitude - _vert_pos_state;
112  float vert_accel_input = hgt_err * omega2 * _hgt_estimate_freq;
113  _vert_accel_state = _vert_accel_state + vert_accel_input * dt;
114  float vert_vel_input = _vert_accel_state + hgt_ddot_mea + hgt_err * omega2 * 3.0f;
115  _vert_vel_state = _vert_vel_state + vert_vel_input * dt;
116  float vert_pos_input = _vert_vel_state + hgt_err * _hgt_estimate_freq * 3.0f;
117 
118  // If more than 1 second has elapsed since last update then reset the position state
119  // to the measured height
120  if (reset_altitude) {
121  _vert_pos_state = altitude;
122 
123  } else {
124  _vert_pos_state = _vert_pos_state + vert_pos_input * dt;
125 
126  }
127 
128  }
129 
130  // Update and average speed rate of change if airspeed is being measured
131  if (ISFINITE(airspeed) && airspeed_sensor_enabled()) {
132  // Assuming the vehicle is flying X axis forward, use the X axis measured acceleration
133  // compensated for gravity to estimate the rate of change of speed
134  float speed_deriv_raw = rotMat(2, 0) * CONSTANTS_ONE_G + accel_body(0);
135 
136  // Apply some noise filtering
137  _speed_derivative = 0.95f * _speed_derivative + 0.05f * speed_deriv_raw;
138 
139  } else {
140  _speed_derivative = 0.0f;
141  }
142 
143  if (!_in_air) {
144  _states_initalized = false;
145  }
146 
147 }
148 
149 void TECS::_update_speed_states(float airspeed_setpoint, float indicated_airspeed, float EAS2TAS)
150 {
151  // Calculate the time in seconds since the last update and use the default time step value if out of bounds
152  uint64_t now = ecl_absolute_time();
153  const float dt = constrain((now - _speed_update_timestamp) * 1.0e-6f, DT_MIN, DT_MAX);
154 
155  // Convert equivalent airspeed quantities to true airspeed
156  _EAS_setpoint = airspeed_setpoint;
157  _TAS_setpoint = _EAS_setpoint * EAS2TAS;
158  _TAS_max = _indicated_airspeed_max * EAS2TAS;
159  _TAS_min = _indicated_airspeed_min * EAS2TAS;
160 
161  // If airspeed measurements are not being used, fix the airspeed estimate to halfway between
162  // min and max limits
163  if (!ISFINITE(indicated_airspeed) || !airspeed_sensor_enabled()) {
165 
166  } else {
167  _EAS = indicated_airspeed;
168  }
169 
170  // If first time through or not flying, reset airspeed states
171  if (_speed_update_timestamp == 0 || !_in_air) {
172  _tas_rate_state = 0.0f;
173  _tas_state = (_EAS * EAS2TAS);
174  }
175 
176  // Obtain a smoothed airspeed estimate using a second order complementary filter
177 
178  // Update TAS rate state
179  float tas_error = (_EAS * EAS2TAS) - _tas_state;
180  float tas_rate_state_input = tas_error * _tas_estimate_freq * _tas_estimate_freq;
181 
182  // limit integrator input to prevent windup
183  if (_tas_state < 3.1f) {
184  tas_rate_state_input = max(tas_rate_state_input, 0.0f);
185 
186  }
187 
188  // Update TAS state
189  _tas_rate_state = _tas_rate_state + tas_rate_state_input * dt;
190  float tas_state_input = _tas_rate_state + _speed_derivative + tas_error * _tas_estimate_freq * 1.4142f;
191  _tas_state = _tas_state + tas_state_input * dt;
192 
193  // Limit the airspeed state to a minimum of 3 m/s
194  _tas_state = max(_tas_state, 3.0f);
196 
197 }
198 
200 {
201  // Set the airspeed demand to the minimum value if an underspeed or
202  // or a uncontrolled descent condition exists to maximise climb rate
205  }
206 
208 
209  // Calculate limits for the demanded rate of change of speed based on physical performance limits
210  // with a 50% margin to allow the total energy controller to correct for errors.
211  float velRateMax = 0.5f * _STE_rate_max / _tas_state;
212  float velRateMin = 0.5f * _STE_rate_min / _tas_state;
213 
215 
216  // calculate the demanded rate of change of speed proportional to speed error
217  // and apply performance limits
219 
220 }
221 
222 void TECS::_update_height_setpoint(float desired, float state)
223 {
224  // Detect first time through and initialize previous value to demand
225  if (ISFINITE(desired) && fabsf(_hgt_setpoint_in_prev) < 0.1f) {
226  _hgt_setpoint_in_prev = desired;
227  }
228 
229  // Apply a 2 point moving average to demanded height to reduce
230  // intersampling noise effects.
231  if (ISFINITE(desired)) {
232  _hgt_setpoint = 0.5f * (desired + _hgt_setpoint_in_prev);
233 
234  } else {
236  }
237 
239 
240  // Apply a rate limit to respect vehicle performance limitations
243 
244  } else if ((_hgt_setpoint - _hgt_setpoint_prev) < (-_max_sink_rate * _dt)) {
246  }
247 
249 
250  // Apply a first order noise filter
252 
253  // Calculate the demanded climb rate proportional to height error plus a feedforward term to provide
254  // tight tracking during steady climb and descent manoeuvres.
258 
259  // Limit the rate of change of height demand to respect vehicle performance limits
262 
263  } else if (_hgt_rate_setpoint < -_max_sink_rate) {
265  }
266 }
267 
269 {
271  _underspeed_detected = false;
272  return;
273  }
274 
275  if (((_tas_state < _TAS_min * 0.9f) && (_throttle_setpoint >= _throttle_setpoint_max * 0.95f))
277 
278  _underspeed_detected = true;
279 
280  } else {
281  _underspeed_detected = false;
282  }
283 }
284 
286 {
287  // Calculate specific energy demands in units of (m**2/sec**2)
288  _SPE_setpoint = _hgt_setpoint_adj * CONSTANTS_ONE_G; // potential energy
289  _SKE_setpoint = 0.5f * _TAS_setpoint_adj * _TAS_setpoint_adj; // kinetic energy
290 
291  // Calculate specific energy rate demands in units of (m**2/sec**3)
292  _SPE_rate_setpoint = _hgt_rate_setpoint * CONSTANTS_ONE_G; // potential energy rate of change
293  _SKE_rate_setpoint = _tas_state * _TAS_rate_setpoint; // kinetic energy rate of change
294 
295  // Calculate specific energies in units of (m**2/sec**2)
296  _SPE_estimate = _vert_pos_state * CONSTANTS_ONE_G; // potential energy
297  _SKE_estimate = 0.5f * _tas_state * _tas_state; // kinetic energy
298 
299  // Calculate specific energy rates in units of (m**2/sec**3)
300  _SPE_rate = _vert_vel_state * CONSTANTS_ONE_G; // potential energy rate of change
301  _SKE_rate = _tas_state * _speed_derivative;// kinetic energy rate of change
302 }
303 
304 void TECS::_update_throttle_setpoint(const float throttle_cruise, const matrix::Dcmf &rotMat)
305 {
306  // Calculate total energy error
308 
309  // Calculate demanded rate of change of total energy, respecting vehicle limits
311 
312  // Calculate the total energy rate error, applying a first order IIR filter
313  // to reduce the effect of accelerometer noise
314  _STE_rate_error = 0.2f * (STE_rate_setpoint - _SPE_rate - _SKE_rate) + 0.8f * _STE_rate_error;
315 
316  // Calculate the throttle demand
317  if (_underspeed_detected) {
318  // always use full throttle to recover from an underspeed condition
319  _throttle_setpoint = 1.0f;
320 
321  } else {
322  // Adjust the demanded total energy rate to compensate for induced drag rise in turns.
323  // Assume induced drag scales linearly with normal load factor.
324  // The additional normal load factor is given by (1/cos(bank angle) - 1)
325  float cosPhi = sqrtf((rotMat(0, 1) * rotMat(0, 1)) + (rotMat(1, 1) * rotMat(1, 1)));
326  STE_rate_setpoint = STE_rate_setpoint + _load_factor_correction * (1.0f / constrain(cosPhi, 0.1f, 1.0f) - 1.0f);
327 
328  // Calculate a predicted throttle from the demanded rate of change of energy, using the cruise throttle
329  // as the starting point. Assume:
330  // Specific total energy rate = _STE_rate_max is achieved when throttle is set to _throttle_setpoint_max
331  // Specific total energy rate = 0 at cruise throttle
332  // Specific total energy rate = _STE_rate_min is achieved when throttle is set to _throttle_setpoint_min
333  float throttle_predicted = 0.0f;
334 
335  if (STE_rate_setpoint >= 0) {
336  // throttle is between cruise and maximum
337  throttle_predicted = throttle_cruise + STE_rate_setpoint / _STE_rate_max * (_throttle_setpoint_max - throttle_cruise);
338 
339  } else {
340  // throttle is between cruise and minimum
341  throttle_predicted = throttle_cruise + STE_rate_setpoint / _STE_rate_min * (_throttle_setpoint_min - throttle_cruise);
342 
343  }
344 
345  // Calculate gain scaler from specific energy error to throttle
346  float STE_to_throttle = 1.0f / (_throttle_time_constant * (_STE_rate_max - _STE_rate_min));
347 
348  // Add proportional and derivative control feedback to the predicted throttle and constrain to throttle limits
349  _throttle_setpoint = (_STE_error + _STE_rate_error * _throttle_damping_gain) * STE_to_throttle + throttle_predicted;
351 
352  // Rate limit the throttle demand
353  if (fabsf(_throttle_slewrate) > 0.01f) {
354  float throttle_increment_limit = _dt * (_throttle_setpoint_max - _throttle_setpoint_min) * _throttle_slewrate;
355  _throttle_setpoint = constrain(_throttle_setpoint, _last_throttle_setpoint - throttle_increment_limit,
356  _last_throttle_setpoint + throttle_increment_limit);
357  }
358 
360 
361  if (_integrator_gain > 0.0f) {
362  // Calculate throttle integrator state upper and lower limits with allowance for
363  // 10% throttle saturation to accommodate noise on the demand.
364  float integ_state_max = _throttle_setpoint_max - _throttle_setpoint + 0.1f;
365  float integ_state_min = _throttle_setpoint_min - _throttle_setpoint - 0.1f;
366 
367  // Calculate a throttle demand from the integrated total energy error
368  // This will be added to the total throttle demand to compensate for steady state errors
370 
371  if (_climbout_mode_active) {
372  // During climbout, set the integrator to maximum throttle to prevent transient throttle drop
373  // at end of climbout when we transition to closed loop throttle control
374  _throttle_integ_state = integ_state_max;
375 
376  } else {
377  // Respect integrator limits during closed loop operation.
378  _throttle_integ_state = constrain(_throttle_integ_state, integ_state_min, integ_state_max);
379  }
380 
381  } else {
382  _throttle_integ_state = 0.0f;
383  }
384 
385  if (airspeed_sensor_enabled()) {
386  // Add the integrator feedback during closed loop operation with an airspeed sensor
388 
389  } else {
390  // when flying without an airspeed sensor, use the predicted throttle only
391  _throttle_setpoint = throttle_predicted;
392 
393  }
394 
396  }
397 }
398 
400 {
401  /*
402  * This function detects a condition that can occur when the demanded airspeed is greater than the
403  * aircraft can achieve in level flight. When this occurs, the vehicle will continue to reduce height
404  * while attempting to maintain speed.
405  */
406 
407  // Calculate rate of change of total specific energy
408  float STE_rate = _SPE_rate + _SKE_rate;
409 
410  // If total energy is very low and reducing, throttle is high, and we are not in an underspeed condition, then enter uncommanded descent recovery mode
411  bool enter_mode = !_uncommanded_descent_recovery && !_underspeed_detected && (_STE_error > 200.0f) && (STE_rate < 0.0f)
413 
414  // If we enter an underspeed condition or recover the required total energy, then exit uncommanded descent recovery mode
415  bool exit_mode = _uncommanded_descent_recovery && (_underspeed_detected || (_STE_error < 0.0f));
416 
417  if (enter_mode) {
419 
420  } else if (exit_mode) {
422 
423  }
424 }
425 
427 {
428  /*
429  * The SKE_weighting variable controls how speed and height control are prioritised by the pitch demand calculation.
430  * A weighting of 1 givea equal speed and height priority
431  * A weighting of 0 gives 100% priority to height control and must be used when no airspeed measurement is available.
432  * A weighting of 2 provides 100% priority to speed control and is used when:
433  * a) an underspeed condition is detected.
434  * b) during climbout where a minimum pitch angle has been set to ensure height is gained. If the airspeed
435  * rises above the demanded value, the pitch angle demand is increased by the TECS controller to prevent the vehicle overspeeding.
436  * The weighting can be adjusted between 0 and 2 depending on speed and height accuracy requirements.
437  */
438 
439  // Calculate the weighting applied to control of specific kinetic energy error
440  float SKE_weighting = constrain(_pitch_speed_weight, 0.0f, 2.0f);
441 
443  SKE_weighting = 2.0f;
444 
445  } else if (!airspeed_sensor_enabled()) {
446  SKE_weighting = 0.0f;
447  }
448 
449  // Calculate the weighting applied to control of specific potential energy error
450  float SPE_weighting = 2.0f - SKE_weighting;
451 
452  // Calculate the specific energy balance demand which specifies how the available total
453  // energy should be allocated to speed (kinetic energy) and height (potential energy)
454  float SEB_setpoint = _SPE_setpoint * SPE_weighting - _SKE_setpoint * SKE_weighting;
455 
456  // Calculate the specific energy balance rate demand
457  float SEB_rate_setpoint = _SPE_rate_setpoint * SPE_weighting - _SKE_rate_setpoint * SKE_weighting;
458 
459  // Calculate the specific energy balance and balance rate error
460  _SEB_error = SEB_setpoint - (_SPE_estimate * SPE_weighting - _SKE_estimate * SKE_weighting);
461  _SEB_rate_error = SEB_rate_setpoint - (_SPE_rate * SPE_weighting - _SKE_rate * SKE_weighting);
462 
463  // Calculate derivative from change in climb angle to rate of change of specific energy balance
464  float climb_angle_to_SEB_rate = _tas_state * _pitch_time_constant * CONSTANTS_ONE_G;
465 
466  if (_integrator_gain > 0.0f) {
467  // Calculate pitch integrator input term
468  float pitch_integ_input = _SEB_error * _integrator_gain;
469 
470  // Prevent the integrator changing in a direction that will increase pitch demand saturation
471  // Decay the integrator at the control loop time constant if the pitch demand from the previous time step is saturated
473  pitch_integ_input = min(pitch_integ_input,
474  min((_pitch_setpoint_max - _pitch_setpoint_unc) * climb_angle_to_SEB_rate / _pitch_time_constant, 0.0f));
475 
477  pitch_integ_input = max(pitch_integ_input,
478  max((_pitch_setpoint_min - _pitch_setpoint_unc) * climb_angle_to_SEB_rate / _pitch_time_constant, 0.0f));
479  }
480 
481  // Update the pitch integrator state.
482  _pitch_integ_state = _pitch_integ_state + pitch_integ_input * _dt;
483 
484  } else {
485  _pitch_integ_state = 0.0f;
486  }
487 
488  // Calculate a specific energy correction that doesn't include the integrator contribution
489  float SEB_correction = _SEB_error + _SEB_rate_error * _pitch_damping_gain + SEB_rate_setpoint * _pitch_time_constant;
490 
491  // During climbout, bias the demanded pitch angle so that a zero speed error produces a pitch angle
492  // demand equal to the minimum pitch angle set by the mission plan. This prevents the integrator
493  // having to catch up before the nose can be raised to reduce excess speed during climbout.
494  if (_climbout_mode_active) {
495  SEB_correction += _pitch_setpoint_min * climb_angle_to_SEB_rate;
496  }
497 
498  // Sum the correction terms and convert to a pitch angle demand. This calculation assumes:
499  // a) The climb angle follows pitch angle with a lag that is small enough not to destabilise the control loop.
500  // b) The offset between climb angle and pitch angle (angle of attack) is constant, excluding the effect of
501  // pitch transients due to control action or turbulence.
502  _pitch_setpoint_unc = (SEB_correction + _pitch_integ_state) / climb_angle_to_SEB_rate;
504 
505  // Comply with the specified vertical acceleration limit by applying a pitch rate limit
506  float ptchRateIncr = _dt * _vert_accel_limit / _tas_state;
507 
508  if ((_pitch_setpoint - _last_pitch_setpoint) > ptchRateIncr) {
509  _pitch_setpoint = _last_pitch_setpoint + ptchRateIncr;
510 
511  } else if ((_pitch_setpoint - _last_pitch_setpoint) < -ptchRateIncr) {
512  _pitch_setpoint = _last_pitch_setpoint - ptchRateIncr;
513  }
514 
516 }
517 
518 void TECS::_initialize_states(float pitch, float throttle_cruise, float baro_altitude, float pitch_min_climbout,
519  float EAS2TAS)
520 {
522  // On first time through or when not using TECS of if there has been a large time slip,
523  // states must be reset to allow filters to a clean start
524  _vert_accel_state = 0.0f;
525  _vert_vel_state = 0.0f;
526  _vert_pos_state = baro_altitude;
527  _tas_rate_state = 0.0f;
528  _tas_state = _EAS * EAS2TAS;
529  _throttle_integ_state = 0.0f;
530  _pitch_integ_state = 0.0f;
531  _last_throttle_setpoint = (_in_air ? throttle_cruise : 0.0f);;
534  _hgt_setpoint_adj_prev = baro_altitude;
538  _TAS_setpoint_last = _EAS * EAS2TAS;
540  _underspeed_detected = false;
542  _STE_rate_error = 0.0f;
543 
544  if (_dt > DT_MAX || _dt < DT_MIN) {
545  _dt = DT_DEFAULT;
546  }
547 
548  } else if (_climbout_mode_active) {
549  // During climbout use the lower pitch angle limit specified by the
550  // calling controller
551  _pitch_setpoint_min = pitch_min_climbout;
552 
553  // throttle lower limit is set to a value that prevents throttle reduction
555 
556  // height demand and associated states are set to track the measured height
557  _hgt_setpoint_adj_prev = baro_altitude;
560 
561  // airspeed demand states are set to track the measured airspeed
562  _TAS_setpoint_last = _EAS * EAS2TAS;
563  _TAS_setpoint_adj = _EAS * EAS2TAS;
564 
565  // disable speed and decent error condition checks
566  _underspeed_detected = false;
568  }
569 
570  _states_initalized = true;
571 }
572 
574 {
575  // Calculate the specific total energy upper rate limits from the max throttle climb rate
577 
578  // Calculate the specific total energy lower rate limits from the min throttle sink rate
580 }
581 
582 void TECS::update_pitch_throttle(const matrix::Dcmf &rotMat, float pitch, float baro_altitude, float hgt_setpoint,
583  float EAS_setpoint, float indicated_airspeed, float eas_to_tas, bool climb_out_setpoint, float pitch_min_climbout,
584  float throttle_min, float throttle_max, float throttle_cruise, float pitch_limit_min, float pitch_limit_max)
585 {
586  // Calculate the time since last update (seconds)
587  uint64_t now = ecl_absolute_time();
588  _dt = constrain((now - _pitch_update_timestamp) * 1e-6f, DT_MIN, DT_MAX);
589 
590  // Set class variables from inputs
591  _throttle_setpoint_max = throttle_max;
592  _throttle_setpoint_min = throttle_min;
593  _pitch_setpoint_max = pitch_limit_max;
594  _pitch_setpoint_min = pitch_limit_min;
595  _climbout_mode_active = climb_out_setpoint;
596 
597  // Initialize selected states and variables as required
598  _initialize_states(pitch, throttle_cruise, baro_altitude, pitch_min_climbout, eas_to_tas);
599 
600  // Don't run TECS control algorithms when not in flight
601  if (!_in_air) {
602  return;
603  }
604 
605  // Update the true airspeed state estimate
606  _update_speed_states(EAS_setpoint, indicated_airspeed, eas_to_tas);
607 
608  // Calculate rate limits for specific total energy
610 
611  // Detect an underspeed condition
613 
614  // Detect an uncommanded descent caused by an unachievable airspeed demand
616 
617  // Calculate the demanded true airspeed
619 
620  // Calculate the demanded height
621  _update_height_setpoint(hgt_setpoint, baro_altitude);
622 
623  // Calculate the specific energy values required by the control loop
625 
626  // Calculate the throttle demand
627  _update_throttle_setpoint(throttle_cruise, rotMat);
628 
629  // Calculate the pitch demand
631 
632  // Update time stamps
634 
635  // Set TECS mode for next frame
636  if (_underspeed_detected) {
637  _tecs_mode = ECL_TECS_MODE_UNDERSPEED;
638 
639  } else if (_uncommanded_descent_recovery) {
640  _tecs_mode = ECL_TECS_MODE_BAD_DESCENT;
641 
642  } else if (_climbout_mode_active) {
643  _tecs_mode = ECL_TECS_MODE_CLIMBOUT;
644 
645  } else {
646  // This is the default operation mode
647  _tecs_mode = ECL_TECS_MODE_NORMAL;
648  }
649 
650 }
constexpr _Tp constrain(_Tp val, _Tp min_val, _Tp max_val)
Definition: Limits.hpp:66
float _TAS_min
true airpeed demand lower limit (m/sec)
Definition: tecs.h:227
float _pitch_setpoint_unc
pitch demand before limiting (rad)
Definition: tecs.h:243
float _SPE_rate
specific potential energy rate estimate (m**2/sec**3)
Definition: tecs.h:258
float _integrator_gain
integrator gain used by the throttle and pitch demand calculation
Definition: tecs.h:195
float _hgt_rate_setpoint
demanded climb rate tracked by the TECS algorithm
Definition: tecs.h:240
Adapter / shim layer for system calls needed by ECL.
float _vert_vel_state
complimentary filter state - height rate (m/sec)
Definition: tecs.h:212
float _SPE_setpoint
specific potential energy demand (m**2/sec**2)
Definition: tecs.h:252
static constexpr float DT_MAX
max value of _dt allowed before a filter state reset is performed (sec)
Definition: tecs.cpp:44
float _hgt_setpoint
demanded height tracked by the TECS algorithm (m)
Definition: tecs.h:235
float _height_error_gain
gain from height error to demanded climb rate (1/sec)
Definition: tecs.h:199
float _pitch_setpoint_max
pitch demand upper limit (rad)
Definition: tecs.h:248
float _hgt_setpoint_prev
previous value of _hgt_setpoint after noise filtering and rate limiting (m)
Definition: tecs.h:237
bool _uncommanded_descent_recovery
true when a continuous descent caused by an unachievable airspeed demand has been detected ...
Definition: tecs.h:274
float _vert_accel_limit
magnitude of the maximum vertical acceleration allowed (m/sec**2)
Definition: tecs.h:196
float _tas_rate_state
complimentary filter state - true airspeed first derivative (m/sec**2)
Definition: tecs.h:214
void _update_speed_states(float airspeed_setpoint, float indicated_airspeed, float eas_to_tas)
Update the airspeed internal state using a second order complementary filter.
Definition: tecs.cpp:149
static enum @74 state
float _throttle_slewrate
throttle demand slew rate limit (1/sec)
Definition: tecs.h:204
void _detect_underspeed()
Detect if the system is not capable of maintaining airspeed.
Definition: tecs.cpp:268
Definition of geo / math functions to perform geodesic calculations.
float _min_sink_rate
sink rate produced by min allowed throttle (m/sec)
Definition: tecs.h:189
float _throttle_integ_state
throttle integrator state
Definition: tecs.h:218
uint64_t _pitch_update_timestamp
last timestamp of the pitch function call
Definition: tecs.h:183
bool _climbout_mode_active
true when in climbout mode
Definition: tecs.h:275
static constexpr float DT_MIN
minimum allowed value of _dt (sec)
Definition: tecs.cpp:43
float _STE_rate_min
specific total energy rate lower limit acheived when throttle is at _throttle_setpoint_min (m**2/sec*...
Definition: tecs.h:245
void _update_throttle_setpoint(float throttle_cruise, const matrix::Dcmf &rotMat)
Update throttle setpoint.
Definition: tecs.cpp:304
float _throttle_setpoint_min
normalised throttle lower limit
Definition: tecs.h:247
float _SKE_estimate
specific kinetic energy estimate (m**2/sec**2)
Definition: tecs.h:257
float _speed_derivative
rate of change of speed along X axis (m/sec**2)
Definition: tecs.h:222
float _pitch_integ_state
pitch integrator state (rad)
Definition: tecs.h:219
float _STE_rate_error
specific total energy rate error (m**2/sec**3)
Definition: tecs.h:263
float _pitch_damping_gain
damping gain of the pitch demand calculation (sec)
Definition: tecs.h:193
float _tas_state
complimentary filter state - true airspeed (m/sec)
Definition: tecs.h:215
float _pitch_time_constant
control time constant used by the pitch demand calculation (sec)
Definition: tecs.h:191
float _SKE_setpoint
specific kinetic energy demand (m**2/sec**2)
Definition: tecs.h:253
float _indicated_airspeed_min
equivalent airspeed demand lower limit (m/sec)
Definition: tecs.h:202
float _throttle_damping_gain
damping gain of the throttle demand calculation (sec)
Definition: tecs.h:194
static constexpr float CONSTANTS_ONE_G
Definition: geo.h:51
void _update_pitch_setpoint()
Update the pitch setpoint.
Definition: tecs.cpp:426
float _TAS_max
true airpeed demand upper limit (m/sec)
Definition: tecs.h:226
#define ecl_absolute_time()
Definition: ecl.h:85
float _pitch_speed_weight
speed control weighting used by pitch demand calculation
Definition: tecs.h:198
float _TAS_setpoint_last
previous true airpeed demand (m/sec)
Definition: tecs.h:229
float _last_throttle_setpoint
throttle demand rate limiter state (1/sec)
Definition: tecs.h:220
float _SKE_rate
specific kinetic energy rate estimate (m**2/sec**3)
Definition: tecs.h:259
uint64_t _state_update_timestamp
last timestamp of the 50 Hz function call
Definition: tecs.h:181
float _STE_error
specific total energy error (m**2/sec**2)
Definition: tecs.h:262
float _max_sink_rate
maximum safe sink rate (m/sec)
Definition: tecs.h:190
float _SEB_error
specific energy balance error (m**2/sec**2)
Definition: tecs.h:264
float _throttle_setpoint_max
normalised throttle upper limit
Definition: tecs.h:246
float _load_factor_correction
gain from normal load factor increase to total energy rate demand (m**2/sec**3)
Definition: tecs.h:197
float _hgt_setpoint_in_prev
previous value of _hgt_setpoint after noise filtering (m)
Definition: tecs.h:236
bool airspeed_sensor_enabled()
Get the current airspeed status.
Definition: tecs.h:62
float _last_pitch_setpoint
pitch demand rate limiter state (rad/sec)
Definition: tecs.h:221
float _pitch_setpoint_min
pitch demand lower limit (rad)
Definition: tecs.h:249
void _initialize_states(float pitch, float throttle_cruise, float baro_altitude, float pitch_min_climbout, float eas_to_tas)
Initialize the controller.
Definition: tecs.cpp:518
float _TAS_setpoint
current airpeed demand (m/sec)
Definition: tecs.h:228
float _EAS
equivalent airspeed (m/sec)
Definition: tecs.h:225
bool _detect_underspeed_enabled
true when underspeed detection is enabled
Definition: tecs.h:273
float _dt
Time since last update of main TECS loop (sec)
Definition: tecs.h:268
float _SPE_estimate
specific potential energy estimate (m**2/sec**2)
Definition: tecs.h:256
Vector< float, 6 > f(float t, const Matrix< float, 6, 1 > &, const Matrix< float, 3, 1 > &)
Definition: integration.cpp:8
bool _in_air
true when the vehicle is flying
Definition: tecs.h:278
float _hgt_setpoint_adj
demanded height used by the control loops after all filtering has been applied (m) ...
Definition: tecs.h:238
float _SEB_rate_error
specific energy balance rate error (m**2/sec**3)
Definition: tecs.h:265
float _height_setpoint_gain_ff
gain from height demand derivative to demanded climb rate
Definition: tecs.h:200
float _pitch_setpoint
pitch angle demand (radians)
Definition: tecs.h:208
float _TAS_rate_setpoint
true airspeed rate demand tracked by the TECS algorithm (m/sec**2)
Definition: tecs.h:232
float _vert_accel_state
complimentary filter state - height second derivative (m/sec**2)
Definition: tecs.h:211
bool _states_initalized
true when TECS states have been iniitalized
Definition: tecs.h:277
constexpr _Tp min(_Tp a, _Tp b)
Definition: Limits.hpp:54
bool _underspeed_detected
true when an underspeed condition has been detected
Definition: tecs.h:272
float _SPE_rate_setpoint
specific potential energy rate demand (m**2/sec**3)
Definition: tecs.h:254
float _EAS_setpoint
Equivalent airspeed demand (m/sec)
Definition: tecs.h:230
void update_pitch_throttle(const matrix::Dcmf &rotMat, float pitch, float baro_altitude, float hgt_setpoint, float EAS_setpoint, float indicated_airspeed, float eas_to_tas, bool climb_out_setpoint, float pitch_min_climbout, float throttle_min, float throttle_setpoint_max, float throttle_cruise, float pitch_limit_min, float pitch_limit_max)
Update the control loop calculations.
Definition: tecs.cpp:582
float _STE_rate_max
specific total energy rate upper limit achieved when throttle is at _throttle_setpoint_max (m**2/sec*...
Definition: tecs.h:244
float _hgt_setpoint_adj_prev
value of _hgt_setpoint_adj from previous frame (m)
Definition: tecs.h:239
void _detect_uncommanded_descent()
Detect an uncommanded descent.
Definition: tecs.cpp:399
void _update_STE_rate_lim()
Calculate specific total energy rate limits.
Definition: tecs.cpp:573
float _throttle_setpoint
normalized throttle demand (0..1)
Definition: tecs.h:207
constexpr _Tp max(_Tp a, _Tp b)
Definition: Limits.hpp:60
float _max_climb_rate
climb rate produced by max allowed throttle (m/sec)
Definition: tecs.h:188
void update_vehicle_state_estimates(float airspeed, const matrix::Dcmf &rotMat, const matrix::Vector3f &accel_body, bool altitude_lock, bool in_air, float altitude, bool vz_valid, float vz, float az)
Updates the following vehicle kineamtic state estimates: Vertical position, velocity and acceleration...
Definition: tecs.cpp:57
float dt
Definition: px4io.c:73
float _SKE_rate_setpoint
specific kinetic energy rate demand (m**2/sec**3)
Definition: tecs.h:255
void _update_height_setpoint(float desired, float state)
Update the desired height.
Definition: tecs.cpp:222
float _TAS_setpoint_adj
true airspeed demand tracked by the TECS algorithm (m/sec)
Definition: tecs.h:231
void _update_speed_setpoint()
Update the desired airspeed.
Definition: tecs.cpp:199
float _hgt_estimate_freq
cross-over frequency of the height rate complementary filter (rad/sec)
Definition: tecs.h:186
float _throttle_time_constant
control time constant used by the throttle demand calculation (sec)
Definition: tecs.h:192
void _update_energy_estimates()
Update specific energy.
Definition: tecs.cpp:285
float _tas_estimate_freq
cross-over frequency of the true airspeed complementary filter (rad/sec)
Definition: tecs.h:187
float _speed_error_gain
gain from speed error to demanded speed rate (1/sec)
Definition: tecs.h:201
uint64_t _speed_update_timestamp
last timestamp of the speed function call
Definition: tecs.h:182
float _vert_pos_state
complimentary filter state - height (m)
Definition: tecs.h:213
static constexpr float DT_DEFAULT
default value for _dt (sec)
Definition: tecs.h:269
#define ISFINITE(x)
Definition: ecl.h:100
float _indicated_airspeed_max
equivalent airspeed demand upper limit (m/sec)
Definition: tecs.h:203