Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Ardupilot
GitHub Repository: Ardupilot/ardupilot
Path: blob/master/libraries/AP_Baro/AP_Baro_Backend.cpp
9451 views
1
#include "AP_Baro_Backend.h"
2
3
#include <stdio.h>
4
#include <AP_Math/AP_Math.h>
5
#include <AP_Vehicle/AP_Vehicle_Type.h>
6
7
extern const AP_HAL::HAL& hal;
8
9
#ifndef AP_BARO_DATA_CHANGE_TIMEOUT_MS
10
#if APM_BUILD_TYPE(APM_BUILD_ArduSub)
11
#define AP_BARO_DATA_CHANGE_TIMEOUT_MS 20000 // timeout in ms since last successful read that involved temperature of pressure changing
12
#else
13
#define AP_BARO_DATA_CHANGE_TIMEOUT_MS 2000 // timeout in ms since last successful read that involved temperature of pressure changing
14
#endif // APM_BUILD_ArduSub
15
#endif // ifndef(AP_BARO_DATA_CHANGE_TIMEOUT_MS)
16
17
// constructor
18
AP_Baro_Backend::AP_Baro_Backend(AP_Baro &baro) :
19
_frontend(baro)
20
{
21
}
22
23
void AP_Baro_Backend::set_bus_id(uint8_t instance, uint32_t id)
24
{
25
_frontend.sensors[instance].bus_id.set(int32_t(id));
26
}
27
28
void AP_Baro_Backend::update_healthy_flag(uint8_t instance)
29
{
30
if (instance >= _frontend._num_sensors) {
31
return;
32
}
33
WITH_SEMAPHORE(_sem);
34
35
// consider a sensor as healthy if it has had an update in the
36
// last 0.5 seconds and values are non-zero and have changed within the last 2 seconds
37
const uint32_t now = AP_HAL::millis();
38
_frontend.sensors[instance].healthy =
39
(now - _frontend.sensors[instance].last_update_ms < BARO_TIMEOUT_MS) &&
40
(now - _frontend.sensors[instance].last_change_ms < AP_BARO_DATA_CHANGE_TIMEOUT_MS) &&
41
!is_zero(_frontend.sensors[instance].pressure);
42
43
if (_frontend.sensors[instance].temperature < -200 ||
44
_frontend.sensors[instance].temperature > 200) {
45
// if temperature is way out of range then we likely have bad
46
// data from the sensor, treat is as unhealthy. This is done
47
// so SPI sensors which have no data validity checking can
48
// mark a sensor unhealthy
49
_frontend.sensors[instance].healthy = false;
50
}
51
}
52
53
void AP_Baro_Backend::backend_update(uint8_t instance)
54
{
55
update();
56
update_healthy_flag(instance);
57
}
58
59
60
/*
61
copy latest data to the frontend from a backend
62
*/
63
void AP_Baro_Backend::_copy_to_frontend(uint8_t instance, float pressure, float temperature)
64
{
65
if (instance >= _frontend._num_sensors) {
66
return;
67
}
68
uint32_t now = AP_HAL::millis();
69
70
// check for changes in data values
71
if (!is_equal(_frontend.sensors[instance].pressure, pressure) || !is_equal(_frontend.sensors[instance].temperature, temperature)) {
72
_frontend.sensors[instance].last_change_ms = now;
73
}
74
75
// update readings
76
_frontend.sensors[instance].pressure = pressure;
77
_frontend.sensors[instance].temperature = temperature;
78
_frontend.sensors[instance].last_update_ms = now;
79
}
80
81
static constexpr float FILTER_KOEF = 0.1f;
82
83
/* Check that the baro value is valid by using a mean filter. If the
84
* value is further than filter_range from mean value, it is
85
* rejected.
86
*/
87
bool AP_Baro_Backend::pressure_ok(float press)
88
{
89
90
if (isinf(press) || isnan(press)) {
91
return false;
92
}
93
94
const float range = (float)_frontend.get_filter_range();
95
if (range <= 0) {
96
return true;
97
}
98
99
bool ret = true;
100
if (is_zero(_mean_pressure)) {
101
_mean_pressure = press;
102
} else {
103
const float d = fabsf(_mean_pressure - press) / (_mean_pressure + press); // diff divide by mean value in percent ( with the * 200.0f on later line)
104
float koeff = FILTER_KOEF;
105
106
if (d * 200.0f > range) { // check the difference from mean value outside allowed range
107
// printf("\nBaro pressure error: mean %f got %f\n", (double)_mean_pressure, (double)press );
108
ret = false;
109
koeff /= (d * 10.0f); // 2.5 and more, so one bad sample never change mean more than 4%
110
_error_count++;
111
}
112
_mean_pressure = _mean_pressure * (1 - koeff) + press * koeff; // complimentary filter 1/k
113
}
114
return ret;
115
}
116
117