mirror of https://github.com/ArduPilot/ardupilot
AP_Baro: Limit ground temperature used for the altitude
Fix an incorrect EAS2TAS that was double counting altitude
This commit is contained in:
parent
495358edbb
commit
c37209a8d5
|
@ -35,6 +35,14 @@
|
||||||
#include "AP_Baro_qflight.h"
|
#include "AP_Baro_qflight.h"
|
||||||
#include "AP_Baro_QURT.h"
|
#include "AP_Baro_QURT.h"
|
||||||
|
|
||||||
|
#define C_TO_KELVIN 273.15f
|
||||||
|
// Gas Constant is from Aerodynamics for Engineering Students, Third Edition, E.L.Houghton and N.B.Carruthers
|
||||||
|
#define ISA_GAS_CONSTANT 287.26f
|
||||||
|
#define ISA_LAPSE_RATE 0.0065f
|
||||||
|
|
||||||
|
#define INTERNAL_TEMPERATURE_CLAMP 35.0f
|
||||||
|
|
||||||
|
|
||||||
extern const AP_HAL::HAL& hal;
|
extern const AP_HAL::HAL& hal;
|
||||||
|
|
||||||
// table of user settable parameters
|
// table of user settable parameters
|
||||||
|
@ -60,7 +68,7 @@ const AP_Param::GroupInfo AP_Baro::var_info[] = {
|
||||||
// @ReadOnly: True
|
// @ReadOnly: True
|
||||||
// @Volatile: True
|
// @Volatile: True
|
||||||
// @User: Advanced
|
// @User: Advanced
|
||||||
AP_GROUPINFO("TEMP", 3, AP_Baro, sensors[0].ground_temperature, 0),
|
AP_GROUPINFO("TEMP", 3, AP_Baro, _user_ground_temperature, 0),
|
||||||
|
|
||||||
// index 4 reserved for old AP_Int8 version in legacy FRAM
|
// index 4 reserved for old AP_Int8 version in legacy FRAM
|
||||||
//AP_GROUPINFO("ALT_OFFSET", 4, AP_Baro, _alt_offset, 0),
|
//AP_GROUPINFO("ALT_OFFSET", 4, AP_Baro, _alt_offset, 0),
|
||||||
|
@ -104,15 +112,7 @@ const AP_Param::GroupInfo AP_Baro::var_info[] = {
|
||||||
// @User: Advanced
|
// @User: Advanced
|
||||||
AP_GROUPINFO("ABS_PRESS2", 9, AP_Baro, sensors[1].ground_pressure, 0),
|
AP_GROUPINFO("ABS_PRESS2", 9, AP_Baro, sensors[1].ground_pressure, 0),
|
||||||
|
|
||||||
// @Param: TEMP2
|
// Slot 10 used to be TEMP2
|
||||||
// @DisplayName: ground temperature
|
|
||||||
// @Description: calibrated ground temperature in degrees Celsius
|
|
||||||
// @Units: degrees celsius
|
|
||||||
// @Increment: 1
|
|
||||||
// @ReadOnly: True
|
|
||||||
// @Volatile: True
|
|
||||||
// @User: Advanced
|
|
||||||
AP_GROUPINFO("TEMP2", 10, AP_Baro, sensors[1].ground_temperature, 0),
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if BARO_MAX_INSTANCES > 2
|
#if BARO_MAX_INSTANCES > 2
|
||||||
|
@ -126,15 +126,7 @@ const AP_Param::GroupInfo AP_Baro::var_info[] = {
|
||||||
// @User: Advanced
|
// @User: Advanced
|
||||||
AP_GROUPINFO("ABS_PRESS3", 11, AP_Baro, sensors[2].ground_pressure, 0),
|
AP_GROUPINFO("ABS_PRESS3", 11, AP_Baro, sensors[2].ground_pressure, 0),
|
||||||
|
|
||||||
// @Param: TEMP3
|
// Slot 12 used to be TEMP3
|
||||||
// @DisplayName: ground temperature
|
|
||||||
// @Description: calibrated ground temperature in degrees Celsius
|
|
||||||
// @Units: degrees celsius
|
|
||||||
// @Increment: 1
|
|
||||||
// @ReadOnly: True
|
|
||||||
// @Volatile: True
|
|
||||||
// @User: Advanced
|
|
||||||
AP_GROUPINFO("TEMP3", 12, AP_Baro, sensors[2].ground_temperature, 0),
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
AP_GROUPEND
|
AP_GROUPEND
|
||||||
|
@ -209,11 +201,12 @@ void AP_Baro::calibrate(bool save)
|
||||||
} else {
|
} else {
|
||||||
if (save) {
|
if (save) {
|
||||||
sensors[i].ground_pressure.set_and_save(sum_pressure[i] / count[i]);
|
sensors[i].ground_pressure.set_and_save(sum_pressure[i] / count[i]);
|
||||||
sensors[i].ground_temperature.set_and_save(sum_temperature[i] / count[i]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_guessed_ground_temperature = get_external_temperature();
|
||||||
|
|
||||||
// panic if all sensors are not calibrated
|
// panic if all sensors are not calibrated
|
||||||
for (uint8_t i=0; i<_num_sensors; i++) {
|
for (uint8_t i=0; i<_num_sensors; i++) {
|
||||||
if (sensors[i].calibrated) {
|
if (sensors[i].calibrated) {
|
||||||
|
@ -234,22 +227,20 @@ void AP_Baro::update_calibration()
|
||||||
if (healthy(i)) {
|
if (healthy(i)) {
|
||||||
sensors[i].ground_pressure.set(get_pressure(i));
|
sensors[i].ground_pressure.set(get_pressure(i));
|
||||||
}
|
}
|
||||||
float last_temperature = sensors[i].ground_temperature;
|
|
||||||
sensors[i].ground_temperature.set(get_calibration_temperature(i));
|
|
||||||
|
|
||||||
// don't notify the GCS too rapidly or we flood the link
|
// don't notify the GCS too rapidly or we flood the link
|
||||||
uint32_t now = AP_HAL::millis();
|
uint32_t now = AP_HAL::millis();
|
||||||
if (now - _last_notify_ms > 10000) {
|
if (now - _last_notify_ms > 10000) {
|
||||||
sensors[i].ground_pressure.notify();
|
sensors[i].ground_pressure.notify();
|
||||||
sensors[i].ground_temperature.notify();
|
|
||||||
_last_notify_ms = now;
|
_last_notify_ms = now;
|
||||||
}
|
}
|
||||||
if (fabsf(last_temperature - sensors[i].ground_temperature) > 3) {
|
|
||||||
// reset _EAS2TAS to force it to recalculate. This happens
|
|
||||||
// when a digital airspeed sensor comes online
|
|
||||||
_EAS2TAS = 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// always update the guessed ground temp
|
||||||
|
_guessed_ground_temperature = get_external_temperature();
|
||||||
|
|
||||||
|
// force EAS2TAS to recalculate
|
||||||
|
_EAS2TAS = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// return altitude difference in meters between current pressure and a
|
// return altitude difference in meters between current pressure and a
|
||||||
|
@ -257,7 +248,7 @@ void AP_Baro::update_calibration()
|
||||||
float AP_Baro::get_altitude_difference(float base_pressure, float pressure) const
|
float AP_Baro::get_altitude_difference(float base_pressure, float pressure) const
|
||||||
{
|
{
|
||||||
float ret;
|
float ret;
|
||||||
float temp = get_ground_temperature() + 273.15f;
|
float temp = get_ground_temperature() + C_TO_KELVIN;
|
||||||
float scaling = pressure / base_pressure;
|
float scaling = pressure / base_pressure;
|
||||||
|
|
||||||
// This is an exact calculation that is within +-2.5m of the standard
|
// This is an exact calculation that is within +-2.5m of the standard
|
||||||
|
@ -274,13 +265,16 @@ float AP_Baro::get_altitude_difference(float base_pressure, float pressure) cons
|
||||||
float AP_Baro::get_EAS2TAS(void)
|
float AP_Baro::get_EAS2TAS(void)
|
||||||
{
|
{
|
||||||
float altitude = get_altitude();
|
float altitude = get_altitude();
|
||||||
if ((fabsf(altitude - _last_altitude_EAS2TAS) < 100.0f) && !is_zero(_EAS2TAS)) {
|
if ((fabsf(altitude - _last_altitude_EAS2TAS) < 25.0f) && !is_zero(_EAS2TAS)) {
|
||||||
// not enough change to require re-calculating
|
// not enough change to require re-calculating
|
||||||
return _EAS2TAS;
|
return _EAS2TAS;
|
||||||
}
|
}
|
||||||
|
|
||||||
float tempK = get_calibration_temperature() + 273.15f - 0.0065f * altitude;
|
// only estimate lapse rate for the difference from the ground location
|
||||||
_EAS2TAS = safe_sqrt(1.225f / ((float)get_pressure() / (287.26f * tempK)));
|
// provides a more consistent reading then trying to estimate a complete
|
||||||
|
// ISA model atmosphere
|
||||||
|
float tempK = get_ground_temperature() + C_TO_KELVIN - ISA_LAPSE_RATE * altitude;
|
||||||
|
_EAS2TAS = safe_sqrt(1.225f / ((float)get_pressure() / (ISA_GAS_CONSTANT * tempK)));
|
||||||
_last_altitude_EAS2TAS = altitude;
|
_last_altitude_EAS2TAS = altitude;
|
||||||
return _EAS2TAS;
|
return _EAS2TAS;
|
||||||
}
|
}
|
||||||
|
@ -288,9 +282,9 @@ float AP_Baro::get_EAS2TAS(void)
|
||||||
// return air density / sea level density - decreases as altitude climbs
|
// return air density / sea level density - decreases as altitude climbs
|
||||||
float AP_Baro::get_air_density_ratio(void)
|
float AP_Baro::get_air_density_ratio(void)
|
||||||
{
|
{
|
||||||
float eas2tas = get_EAS2TAS();
|
const float eas2tas = get_EAS2TAS();
|
||||||
if (eas2tas > 0.0f) {
|
if (eas2tas > 0.0f) {
|
||||||
return 1.0f/(sq(get_EAS2TAS()));
|
return 1.0f/(sq(eas2tas));
|
||||||
} else {
|
} else {
|
||||||
return 1.0f;
|
return 1.0f;
|
||||||
}
|
}
|
||||||
|
@ -309,6 +303,17 @@ float AP_Baro::get_climb_rate(void)
|
||||||
return _climb_rate_filter.slope() * 1.0e3f;
|
return _climb_rate_filter.slope() * 1.0e3f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// returns the ground temperature in degrees C, selecting either a user
|
||||||
|
// provided one, or the internal estimate
|
||||||
|
float AP_Baro::get_ground_temperature(void) const
|
||||||
|
{
|
||||||
|
if (is_zero(_user_ground_temperature)) {
|
||||||
|
return _guessed_ground_temperature;
|
||||||
|
} else {
|
||||||
|
return _user_ground_temperature;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
set external temperature to be used for calibration (degrees C)
|
set external temperature to be used for calibration (degrees C)
|
||||||
|
@ -322,22 +327,21 @@ void AP_Baro::set_external_temperature(float temperature)
|
||||||
/*
|
/*
|
||||||
get the temperature in degrees C to be used for calibration purposes
|
get the temperature in degrees C to be used for calibration purposes
|
||||||
*/
|
*/
|
||||||
float AP_Baro::get_calibration_temperature(uint8_t instance) const
|
float AP_Baro::get_external_temperature(const uint8_t instance) const
|
||||||
{
|
{
|
||||||
// if we have a recent external temperature then use it
|
// if we have a recent external temperature then use it
|
||||||
if (_last_external_temperature_ms != 0 && AP_HAL::millis() - _last_external_temperature_ms < 10000) {
|
if (_last_external_temperature_ms != 0 && AP_HAL::millis() - _last_external_temperature_ms < 10000) {
|
||||||
return _external_temperature;
|
return _external_temperature;
|
||||||
}
|
}
|
||||||
// if we don't have an external temperature then use the minimum
|
// if we don't have an external temperature then use the minimum
|
||||||
// of the barometer temperature and 25 degrees C. The reason for
|
// of the barometer temperature and 35 degrees C. The reason for
|
||||||
// not just using the baro temperature is it tends to read high,
|
// not just using the baro temperature is it tends to read high,
|
||||||
// often 30 degrees above the actual temperature. That means the
|
// often 30 degrees above the actual temperature. That means the
|
||||||
// EAS2TAS tends to be off by quite a large margin
|
// EAS2TAS tends to be off by quite a large margin, as well as
|
||||||
float ret = get_temperature(instance);
|
// the calculation of altitude difference betweeen two pressures
|
||||||
if (ret > 25) {
|
// reporting a high temperature will cause the aircraft to
|
||||||
ret = 25;
|
// estimate itself as flying higher then it actually is.
|
||||||
}
|
return MIN(get_temperature(instance), INTERNAL_TEMPERATURE_CLAMP);
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -370,6 +374,12 @@ bool AP_Baro::_add_backend(AP_Baro_Backend *backend)
|
||||||
*/
|
*/
|
||||||
void AP_Baro::init(void)
|
void AP_Baro::init(void)
|
||||||
{
|
{
|
||||||
|
// ensure that there isn't a previous ground temperature saved
|
||||||
|
if (!is_zero(_user_ground_temperature)) {
|
||||||
|
_user_ground_temperature.set_and_save(0.0f);
|
||||||
|
_user_ground_temperature.notify();
|
||||||
|
}
|
||||||
|
|
||||||
if (_hil_mode) {
|
if (_hil_mode) {
|
||||||
drivers[0] = new AP_Baro_HIL(*this);
|
drivers[0] = new AP_Baro_HIL(*this);
|
||||||
_num_drivers = 1;
|
_num_drivers = 1;
|
||||||
|
|
|
@ -83,8 +83,7 @@ public:
|
||||||
|
|
||||||
// ground temperature in degrees C
|
// ground temperature in degrees C
|
||||||
// the ground values are only valid after calibration
|
// the ground values are only valid after calibration
|
||||||
float get_ground_temperature(void) const { return get_ground_temperature(_primary); }
|
float get_ground_temperature(void) const;
|
||||||
float get_ground_temperature(uint8_t i) const { return sensors[i].ground_temperature.get(); }
|
|
||||||
|
|
||||||
// ground pressure in Pascal
|
// ground pressure in Pascal
|
||||||
// the ground values are only valid after calibration
|
// the ground values are only valid after calibration
|
||||||
|
@ -103,8 +102,8 @@ public:
|
||||||
// settable parameters
|
// settable parameters
|
||||||
static const struct AP_Param::GroupInfo var_info[];
|
static const struct AP_Param::GroupInfo var_info[];
|
||||||
|
|
||||||
float get_calibration_temperature(void) const { return get_calibration_temperature(_primary); }
|
float get_external_temperature(void) const { return get_external_temperature(_primary); };
|
||||||
float get_calibration_temperature(uint8_t instance) const;
|
float get_external_temperature(const uint8_t instance) const;
|
||||||
|
|
||||||
// HIL (and SITL) interface, setting altitude
|
// HIL (and SITL) interface, setting altitude
|
||||||
void setHIL(float altitude_msl);
|
void setHIL(float altitude_msl);
|
||||||
|
@ -170,7 +169,6 @@ private:
|
||||||
float pressure; // pressure in Pascal
|
float pressure; // pressure in Pascal
|
||||||
float temperature; // temperature in degrees C
|
float temperature; // temperature in degrees C
|
||||||
float altitude; // calculated altitude
|
float altitude; // calculated altitude
|
||||||
AP_Float ground_temperature;
|
|
||||||
AP_Float ground_pressure;
|
AP_Float ground_pressure;
|
||||||
} sensors[BARO_MAX_INSTANCES];
|
} sensors[BARO_MAX_INSTANCES];
|
||||||
|
|
||||||
|
@ -184,7 +182,9 @@ private:
|
||||||
uint32_t _last_external_temperature_ms;
|
uint32_t _last_external_temperature_ms;
|
||||||
DerivativeFilterFloat_Size7 _climb_rate_filter;
|
DerivativeFilterFloat_Size7 _climb_rate_filter;
|
||||||
AP_Float _specific_gravity; // the specific gravity of fluid for an ROV 1.00 for freshwater, 1.024 for salt water
|
AP_Float _specific_gravity; // the specific gravity of fluid for an ROV 1.00 for freshwater, 1.024 for salt water
|
||||||
|
AP_Float _user_ground_temperature; // user override of the ground temperature used for EAS2TAS
|
||||||
bool _hil_mode:1;
|
bool _hil_mode:1;
|
||||||
|
float _guessed_ground_temperature; // currently ground temperature estimate using our best abailable source
|
||||||
|
|
||||||
// when did we last notify the GCS of new pressure reference?
|
// when did we last notify the GCS of new pressure reference?
|
||||||
uint32_t _last_notify_ms;
|
uint32_t _last_notify_ms;
|
||||||
|
|
Loading…
Reference in New Issue