PX4 Firmware
PX4 Autopilot Software http://px4.io
airspeed.cpp
Go to the documentation of this file.
1 /****************************************************************************
2  *
3  * Copyright (C) 2012-2013 PX4 Development Team. All rights reserved.
4  * Author: Lorenz Meier <lm@inf.ethz.ch>
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
10  * 1. Redistributions of source code must retain the above copyright
11  * notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  * notice, this list of conditions and the following disclaimer in
14  * the documentation and/or other materials provided with the
15  * distribution.
16  * 3. Neither the name PX4 nor the names of its contributors may be
17  * used to endorse or promote products derived from this software
18  * without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
27  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
28  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
30  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31  * POSSIBILITY OF SUCH DAMAGE.
32  *
33  ****************************************************************************/
34 
35 /**
36  * @file airspeed.c
37  * Airspeed estimation
38  *
39  * @author Lorenz Meier <lm@inf.ethz.ch>
40  *
41  */
42 
43 #include "airspeed.h"
44 
45 #include <px4_platform_common/defines.h>
46 #include <lib/ecl/geo/geo.h>
47 
48 /**
49  * Calculate indicated airspeed.
50  *
51  * Note that the indicated airspeed is not the true airspeed because it
52  * lacks the air density compensation. Use the calc_true_airspeed functions to get
53  * the true airspeed.
54  *
55  * @param differential_pressure total_ pressure - static pressure
56  * @return indicated airspeed in m/s
57  */
59  float tube_len, float tube_dia_mm, float differential_pressure, float pressure_ambient, float temperature_celsius)
60 {
61 
62  // air density in kg/m3
63  const float rho_air = get_air_density(pressure_ambient, temperature_celsius);
64 
65  const float dp = fabsf(differential_pressure);
66  float dp_tot = dp;
67 
68  float dv = 0.0f;
69 
70  switch (smodel) {
71 
73  // do nothing
74  }
75  break;
76 
78  // assumes a metal pitot tube with round tip as here: https://drotek.com/shop/2986-large_default/sdp3x-airspeed-sensor-kit-sdp31.jpg
79  // and tubing as provided by px4/drotek (1.5 mm diameter)
80  // The tube_len represents the length of the tubes connecting the pitot to the sensor.
81  switch (pmodel) {
84  const float dp_corr = dp * 96600.0f / pressure_ambient;
85  // flow through sensor
86  float flow_SDP33 = (300.805f - 300.878f / (0.00344205f * powf(dp_corr, 0.68698f) + 1.0f)) * 1.29f / rho_air;
87 
88  // for too small readings the compensation might result in a negative flow which causes numerical issues
89  if (flow_SDP33 < 0.0f) {
90  flow_SDP33 = 0.0f;
91  }
92 
93  float dp_pitot = 0.0f;
94 
95  switch (pmodel) {
97  dp_pitot = (0.0032f * flow_SDP33 * flow_SDP33 + 0.0123f * flow_SDP33 + 1.0f) * 1.29f / rho_air;
98  break;
99 
100  default:
101  // do nothing
102  break;
103  }
104 
105  // pressure drop through tube
106  const float dp_tube = (flow_SDP33 * 0.674f) / 450.0f * tube_len * rho_air / 1.29f;
107 
108  // speed at pitot-tube tip due to flow through sensor
109  dv = 0.125f * flow_SDP33;
110 
111  // sum of all pressure drops
112  dp_tot = dp_corr + dp_tube + dp_pitot;
113  }
114  break;
115 
117  // Pressure loss compensation as defined in https://goo.gl/UHV1Vv.
118  // tube_dia_mm: Diameter in mm of the pitot and tubes, must have the same diameter.
119  // tube_len: Length of the tubes connecting the pitot to the sensor and the static + dynamic port length of the pitot.
120 
121  // check if the tube diameter and dp is nonzero to avoid division by 0
122  if ((tube_dia_mm > 0.0f) && (dp > 0.0f)) {
123  const float d_tubePow4 = powf(tube_dia_mm * 1e-3f, 4);
124  const float denominator = M_PI_F * d_tubePow4 * rho_air * dp;
125 
126  // avoid division by 0
127  float eps = 0.0f;
128 
129  if (fabsf(denominator) > 1e-32f) {
130  const float viscosity = (18.205f + 0.0484f * (temperature_celsius - 20.0f)) * 1e-6f;
131 
132  // 4.79 * 1e-7 -> mass flow through sensor
133  // 59.5 -> dp sensor constant where linear and quadratic contribution to dp vs flow is equal
134  eps = -64.0f * tube_len * viscosity * 4.79f * 1e-7f * (sqrtf(1.0f + 8.0f * dp / 59.3319f) - 1.0f) / denominator;
135  }
136 
137  // range check on eps
138  if (fabsf(eps) >= 1.0f) {
139  eps = 0.0f;
140  }
141 
142  // pressure correction
143  dp_tot = dp / (1.0f + eps);
144  }
145  }
146  break;
147 
148  default: {
149  // do nothing
150  }
151  break;
152  }
153 
154  }
155  break;
156 
157  default: {
158  // do nothing
159  }
160  break;
161  }
162 
163  // if (!PX4_ISFINITE(dp_tube)) {
164  // dp_tube = 0.0f;
165  // }
166 
167  // if (!PX4_ISFINITE(dp_pitot)) {
168  // dp_pitot = 0.0f;
169  // }
170 
171  // if (!PX4_ISFINITE(dv)) {
172  // dv = 0.0f;
173  // }
174 
175  // computed airspeed without correction for inflow-speed at tip of pitot-tube
176  const float airspeed_uncorrected = sqrtf(2.0f * dp_tot / CONSTANTS_AIR_DENSITY_SEA_LEVEL_15C);
177 
178  // corrected airspeed
179  const float airspeed_corrected = airspeed_uncorrected + dv;
180 
181  // return result with correct sign
182  return (differential_pressure > 0.0f) ? airspeed_corrected : -airspeed_corrected;
183 }
184 
185 
186 /**
187  * Calculate indicated airspeed (IAS).
188  *
189  * Note that the indicated airspeed is not the true airspeed because it
190  * lacks the air density and instrument error compensation.
191  *
192  * @param differential_pressure total_ pressure - static pressure
193  * @return IAS in m/s
194  */
195 float calc_IAS(float differential_pressure)
196 {
197 
198 
199  if (differential_pressure > 0.0f) {
200  return sqrtf((2.0f * differential_pressure) / CONSTANTS_AIR_DENSITY_SEA_LEVEL_15C);
201 
202  } else {
203  return -sqrtf((2.0f * fabsf(differential_pressure)) / CONSTANTS_AIR_DENSITY_SEA_LEVEL_15C);
204  }
205 
206 }
207 
208 /**
209  * Calculate true airspeed (TAS) from equivalent airspeed (EAS).
210  *
211  * Note that the true airspeed is NOT the groundspeed, because of the effects of wind
212  *
213  * @param speed_equivalent current equivalent airspeed
214  * @param pressure_ambient pressure at the side of the tube/airplane
215  * @param temperature_celsius air temperature in degrees celcius
216  * @return TAS in m/s
217  */
218 float calc_TAS_from_EAS(float speed_equivalent, float pressure_ambient, float temperature_celsius)
219 {
220  return speed_equivalent * sqrtf(CONSTANTS_AIR_DENSITY_SEA_LEVEL_15C / get_air_density(pressure_ambient,
221  temperature_celsius));
222 }
223 
224 /**
225  * Calculate equivalent airspeed (EAS) from indicated airspeed (IAS).
226  * Note that we neglect the conversion from CAS (calibrated airspeed) to EAS.
227  *
228  * @param speed_indicated current indicated airspeed
229  * @param scale scale from IAS to CAS (accounting for instrument and pitot position erros)
230  * @return EAS in m/s
231  */
232 float calc_EAS_from_IAS(float speed_indicated, float scale)
233 {
234  return speed_indicated * scale;
235 }
236 
237 /**
238  * Directly calculate true airspeed (TAS)
239  *
240  * Here we assume to have no instrument or pitot position error (IAS = CAS),
241  * and neglect the CAS to EAS conversion (CAS = EAS).
242  * Note that the true airspeed is NOT the groundspeed, because of the effects of wind.
243  *
244  * @param total_pressure pressure inside the pitot/prandtl tube
245  * @param static_pressure pressure at the side of the tube/airplane
246  * @param temperature_celsius air temperature in degrees celcius
247  * @return true airspeed in m/s
248  */
249 float calc_TAS(float total_pressure, float static_pressure, float temperature_celsius)
250 {
251  float density = get_air_density(static_pressure, temperature_celsius);
252 
253  if (density < 0.0001f || !PX4_ISFINITE(density)) {
255  }
256 
257  float pressure_difference = total_pressure - static_pressure;
258 
259  if (pressure_difference > 0) {
260  return sqrtf((2.0f * (pressure_difference)) / density);
261 
262  } else {
263  return -sqrtf((2.0f * fabsf(pressure_difference)) / density);
264  }
265 }
266 
267 float get_air_density(float static_pressure, float temperature_celsius)
268 {
269  return static_pressure / (CONSTANTS_AIR_GAS_CONST * (temperature_celsius - CONSTANTS_ABSOLUTE_NULL_CELSIUS));
270 }
271 
272 /**
273  * Calculate equivalent airspeed (EAS) from true airspeed (TAS).
274  * It is the inverse function to calc_TAS_from_EAS()
275  *
276  *
277  * @param speed_true current true airspeed
278  * @param pressure_ambient pressure at the side of the tube/airplane
279  * @param temperature_celsius air temperature in degrees celcius
280  * @return EAS in m/s
281  */
282 float calc_EAS_from_TAS(float speed_true, float pressure_ambient, float temperature_celsius)
283 {
284  return speed_true * sqrtf(get_air_density(pressure_ambient,
285  temperature_celsius) / CONSTANTS_AIR_DENSITY_SEA_LEVEL_15C);
286 }
static constexpr float CONSTANTS_AIR_GAS_CONST
Definition: geo.h:58
static constexpr float CONSTANTS_ABSOLUTE_NULL_CELSIUS
Definition: geo.h:59
float calc_IAS_corrected(enum AIRSPEED_COMPENSATION_MODEL pmodel, enum AIRSPEED_SENSOR_MODEL smodel, float tube_len, float tube_dia_mm, float differential_pressure, float pressure_ambient, float temperature_celsius)
Calculate indicated airspeed.
Definition: airspeed.cpp:58
Definition of geo / math functions to perform geodesic calculations.
float calc_TAS_from_EAS(float speed_equivalent, float pressure_ambient, float temperature_celsius)
Calculate true airspeed (TAS) from equivalent airspeed (EAS).
Definition: airspeed.cpp:218
float calc_EAS_from_TAS(float speed_true, float pressure_ambient, float temperature_celsius)
Calculate equivalent airspeed (EAS) from true airspeed (TAS).
Definition: airspeed.cpp:282
float calc_IAS(float differential_pressure)
Calculate indicated airspeed (IAS).
Definition: airspeed.cpp:195
AIRSPEED_SENSOR_MODEL
Definition: airspeed.h:49
Vector< float, 6 > f(float t, const Matrix< float, 6, 1 > &, const Matrix< float, 3, 1 > &)
Definition: integration.cpp:8
float calc_TAS(float total_pressure, float static_pressure, float temperature_celsius)
Directly calculate true airspeed (TAS)
Definition: airspeed.cpp:249
AIRSPEED_COMPENSATION_MODEL
Definition: airspeed.h:54
static constexpr float CONSTANTS_AIR_DENSITY_SEA_LEVEL_15C
Definition: geo.h:57
float calc_EAS_from_IAS(float speed_indicated, float scale)
Calculate equivalent airspeed (EAS) from indicated airspeed (IAS).
Definition: airspeed.cpp:232
#define M_PI_F
Definition: ashtech.cpp:44
float get_air_density(float static_pressure, float temperature_celsius)
Calculates air density.
Definition: airspeed.cpp:267