Skip to content

Commit 731ff93

Browse files
committed
analyzers: add an error-flags analyzer
This should only be used if the error flags aren't handled in a better way, like they are for battery.
1 parent 6d92b25 commit 731ff93

File tree

6 files changed

+351
-0
lines changed

6 files changed

+351
-0
lines changed

LA_MsgHandler.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,8 @@ LA_MsgHandler_ERR::LA_MsgHandler_ERR(std::string name, const struct log_Format &
263263
_analyze->add_data_source("BATTERY_FAILSAFE", "ERR.ECode");
264264
_analyze->add_data_source("CRASH", "ERR.Subsys");
265265
_analyze->add_data_source("CRASH", "ERR.ECode");
266+
_analyze->add_data_source("ERRORFLAGS", "ERR.Subsys");
267+
_analyze->add_data_source("ERRORFLAGS", "ERR.ECode");
266268
}
267269

268270
void LA_MsgHandler_ERR::xprocess(const uint8_t *msg) {
@@ -275,6 +277,9 @@ void LA_MsgHandler_ERR::xprocess(const uint8_t *msg) {
275277
case ERROR_SUBSYSTEM_CRASH:
276278
_vehicle->set_crashed(ecode);
277279
break;
280+
default:
281+
_vehicle->set_subsys_error_code(subsys, ecode);
282+
break;
278283
}
279284
}
280285

Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ SRCS_CPP += analyzer/analyzer_autopilot.cpp
5454
SRCS_CPP += analyzer/analyzer_battery.cpp
5555
SRCS_CPP += analyzer/analyzer_compass_offsets.cpp
5656
SRCS_CPP += analyzer/analyzer_compass_vector_length.cpp
57+
SRCS_CPP += analyzer/analyzer_subsys_errors.cpp
5758
SRCS_CPP += analyzer/analyzer_ever_armed.cpp
5859
SRCS_CPP += analyzer/analyzer_ever_flew.cpp
5960
SRCS_CPP += analyzer/analyzer_good_kf.cpp

analyze.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include "analyzer/analyzer_parameters.h"
2323
#include "analyzer/analyzer_position_estimate_divergence.h"
2424
#include "analyzer/analyzer_sensor_health.h"
25+
#include "analyzer/analyzer_subsys_errors.h"
2526
#include "analyzer/analyzer_motorbalance.h"
2627
#include "analyzer/analyzer_vehicle_definition.h"
2728
#include "analyzer/analyzer_velocity_estimate_divergence.h"
@@ -211,6 +212,13 @@ void Analyze::instantiate_analyzers(INIReader *config)
211212
la_log(LOG_INFO, "Failed to create analyzer_sensor_health");
212213
}
213214

215+
Analyzer_Subsys_Errors *analyzer_subsys_errors = new Analyzer_Subsys_Errors(vehicle,_data_sources);
216+
if (analyzer_subsys_errors != NULL) {
217+
configure_analyzer(config, analyzer_subsys_errors);
218+
} else {
219+
la_log(LOG_INFO, "Failed to create analyzer_subsys_errors");
220+
}
221+
214222
Analyzer_Vehicle_Definition *analyzer_vehicle_definition = new Analyzer_Vehicle_Definition(vehicle,_data_sources);
215223
if (analyzer_vehicle_definition != NULL) {
216224
configure_analyzer(config, analyzer_vehicle_definition);

analyzer/analyzer_subsys_errors.cpp

Lines changed: 184 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,184 @@
1+
#include "analyzer_subsys_errors.h"
2+
3+
#include "util.h"
4+
#include "analyzer_util.h"
5+
6+
void Analyzer_Subsys_Errors_Result::to_json(Json::Value &root) const
7+
{
8+
Analyzer_Result_Period::to_json(root);
9+
root["subsystem"] = _subsys;
10+
root["subsystem-string"] = _subsys_string;
11+
root["ecode"] = _ecode;
12+
root["ecode-string"] = _ecode_string;
13+
}
14+
15+
bool Analyzer_Subsys_Errors::configure(INIReader *config) {
16+
if (!Analyzer::configure(config)) {
17+
return false;
18+
}
19+
return true;
20+
}
21+
22+
void Analyzer_Subsys_Errors::end_of_log(uint32_t packet_count UNUSED)
23+
{
24+
auto subsys_errors = _vehicle->subsys_errors();
25+
26+
for (auto it = subsys_errors.begin(); it != subsys_errors.end(); ++it) {
27+
// ::fprintf(stderr, "would evaluate (%s)\n", (*it).first.c_str());
28+
uint32_t subsys = (*it).first;
29+
if (_results[subsys] != NULL) {
30+
close_result(subsys);
31+
}
32+
}
33+
34+
// if (!have) {
35+
// Analyzer_Result_Summary *summary = new Analyzer_Result_Summary();
36+
// summary->set_status(analyzer_status_warn);
37+
// summary->set_reason("Sensor health never updated");
38+
// summary->add_source(_data_sources.get("SENSORS_HEALTH"));
39+
// add_result(summary);
40+
// }
41+
42+
}
43+
44+
void Analyzer_Subsys_Errors::close_result(const uint32_t subsys)
45+
{
46+
Analyzer_Subsys_Errors_Result *result = _results[subsys];
47+
48+
result->set_T_stop(_vehicle->T());
49+
add_result(result);
50+
_results[subsys] = NULL;
51+
}
52+
53+
const std::map<const uint32_t, const std::string> _subsys_name = {
54+
{ ERROR_SUBSYSTEM_MAIN, "MAIN" },
55+
{ ERROR_SUBSYSTEM_RADIO, "RADIO" },
56+
{ ERROR_SUBSYSTEM_COMPASS, "COMPASS" },
57+
{ ERROR_SUBSYSTEM_OPTFLOW, "OPTFLOW" },
58+
{ ERROR_SUBSYSTEM_FAILSAFE_RADIO, "FAILSAFE_RADIO" },
59+
{ ERROR_SUBSYSTEM_FAILSAFE_BATT, "FAILSAFE_BATT" },
60+
{ ERROR_SUBSYSTEM_FAILSAFE_GPS, "FAILSAFE_GPS" }, // not used
61+
{ ERROR_SUBSYSTEM_FAILSAFE_GCS, "FAILSAFE_GCS" },
62+
{ ERROR_SUBSYSTEM_FAILSAFE_FENCE, "FAILSAFE_FENCE" },
63+
{ ERROR_SUBSYSTEM_FLIGHT_MODE, "FLIGHT_MODE" },
64+
{ ERROR_SUBSYSTEM_GPS, "GPS" },
65+
{ ERROR_SUBSYSTEM_CRASH_CHECK, "CRASH_CHECK" },
66+
{ ERROR_SUBSYSTEM_FLIP, "FLIP" },
67+
{ ERROR_SUBSYSTEM_AUTOTUNE, "AUTOTUNE" },
68+
{ ERROR_SUBSYSTEM_PARACHUTE, "PARACHUTE" },
69+
{ ERROR_SUBSYSTEM_EKFCHECK, "EKFCHECK" },
70+
{ ERROR_SUBSYSTEM_FAILSAFE_EKFINAV, "FAILSAFE_EKFINAV" },
71+
{ ERROR_SUBSYSTEM_BARO, "BARO" },
72+
{ ERROR_SUBSYSTEM_CPU, "CPU" },
73+
{ ERROR_SUBSYSTEM_FAILSAFE_ADSB, "FAILSAFE_ADSB" },
74+
{ ERROR_SUBSYSTEM_TERRAIN, "TERRAIN" },
75+
{ ERROR_SUBSYSTEM_NAVIGATION, "NAVIGATION" },
76+
{ ERROR_SUBSYSTEM_FAILSAFE_TERRAIN, "FAILSAFE_TERRAIN" },
77+
{ ERROR_SUBSYSTEM_EKF_PRIMARY, "EKF_PRIMARY" },
78+
};
79+
80+
/// @brief Map from subsystem id to error code values
81+
/// @note Correct only for ArduCopter ATM
82+
/// @note taken from ArduCopter/defines.h
83+
const std::map<const uint32_t, std::map<const uint32_t, const std::string>> _subsys_errors_strings = {
84+
{ ERROR_SUBSYSTEM_RADIO, {
85+
{ ERROR_CODE_RADIO_LATE_FRAME, "Late Frame" },
86+
}
87+
},
88+
{ ERROR_SUBSYSTEM_FAILSAFE_RADIO, {
89+
{ ERROR_CODE_FAILSAFE_OCCURRED, "Occured" },
90+
{ ERROR_CODE_FAILSAFE_RESOLVED, "Resolved" },
91+
}
92+
},
93+
{ ERROR_SUBSYSTEM_FAILSAFE_BATT, {
94+
{ ERROR_CODE_FAILSAFE_OCCURRED, "Occured" },
95+
{ ERROR_CODE_FAILSAFE_RESOLVED, "Resolved" },
96+
}
97+
},
98+
{ ERROR_SUBSYSTEM_FAILSAFE_GPS, {
99+
{ ERROR_CODE_FAILSAFE_OCCURRED, "Occured" },
100+
{ ERROR_CODE_FAILSAFE_RESOLVED, "Resolved" },
101+
}
102+
},
103+
{ ERROR_SUBSYSTEM_FAILSAFE_GCS, {
104+
{ ERROR_CODE_FAILSAFE_OCCURRED, "Occured" },
105+
{ ERROR_CODE_FAILSAFE_RESOLVED, "Resolved" },
106+
}
107+
},
108+
{ ERROR_SUBSYSTEM_FAILSAFE_FENCE, {
109+
{ ERROR_CODE_FAILSAFE_OCCURRED, "Occured" },
110+
{ ERROR_CODE_FAILSAFE_RESOLVED, "Resolved" },
111+
}
112+
},
113+
{ ERROR_SUBSYSTEM_EKFCHECK, {
114+
{ ERROR_CODE_EKFCHECK_BAD_VARIANCE, "Bad Variance" },
115+
}
116+
},
117+
{ ERROR_SUBSYSTEM_BARO, {
118+
{ ERROR_CODE_BARO_GLITCH, "Baro Glitch" },
119+
}
120+
},
121+
{ ERROR_SUBSYSTEM_GPS, {
122+
{ ERROR_CODE_GPS_GLITCH, "GPS Glitch" },
123+
}
124+
},
125+
};
126+
127+
const std::string Analyzer_Subsys_Errors::subsys_string(const uint32_t subsys) const
128+
{
129+
return _subsys_name.at(subsys);
130+
}
131+
132+
const std::string Analyzer_Subsys_Errors::ecode_string(uint32_t subsys,
133+
uint32_t ecode) const
134+
{
135+
try {
136+
std::map<const uint32_t, const std::string> bob = _subsys_errors_strings.at(subsys);
137+
return bob.at(ecode);
138+
} catch (std::out_of_range) {
139+
}
140+
switch(ecode) {
141+
case ERROR_CODE_ERROR_RESOLVED:
142+
return "Resolved";
143+
case ERROR_CODE_FAILED_TO_INITIALISE:
144+
return "Failed to initialise";
145+
case ERROR_CODE_UNHEALTHY:
146+
return "Unhealthy";
147+
default:
148+
return "Unknown";
149+
}
150+
}
151+
152+
void Analyzer_Subsys_Errors::open_result(const uint32_t subsys, const uint32_t ecode)
153+
{
154+
_results[subsys] = new Analyzer_Subsys_Errors_Result(subsys,
155+
subsys_string(subsys),
156+
ecode,
157+
ecode_string(subsys, ecode));
158+
_results[subsys]->set_reason("A subsystem failure has occured");
159+
_results[subsys]->set_T_start(_vehicle->T());
160+
_results[subsys]->set_status(analyzer_status_fail);
161+
_results[subsys]->add_source(_data_sources.get("SUBSYS_ERRORS"));
162+
_results[subsys]->increase_severity_score(10);
163+
}
164+
165+
166+
void Analyzer_Subsys_Errors::evaluate()
167+
{
168+
auto subsys_errors = _vehicle->subsys_errors();
169+
170+
for (auto it = subsys_errors.begin(); it != subsys_errors.end(); ++it) {
171+
uint32_t subsys = (*it).first;
172+
uint32_t new_ecode = (*it).second;
173+
// ::fprintf(stderr, "would evaluate (%s)\n", name.c_str());
174+
if (_results[subsys] != NULL) {
175+
if (_results[subsys]->ecode() != new_ecode) {
176+
close_result(subsys);
177+
}
178+
}
179+
if (_results[subsys] == NULL && new_ecode) {
180+
open_result(subsys, new_ecode);
181+
}
182+
}
183+
}
184+

analyzer/analyzer_subsys_errors.h

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
#ifndef ANALYZER_SUBSYS_ERRORS_H
2+
#define ANALYZER_SUBSYS_ERRORS_H
3+
4+
/*
5+
* analyzer_subsys_errors
6+
*
7+
*/
8+
9+
#include "analyzer.h"
10+
#include "data_sources.h"
11+
12+
13+
class Analyzer_Subsys_Errors_Result : public Analyzer_Result_Period {
14+
public:
15+
Analyzer_Subsys_Errors_Result(uint32_t subsys,
16+
const std::string subsys_string,
17+
uint32_t ecode,
18+
const std::string ecode_string) :
19+
_subsys(subsys),
20+
_subsys_string(subsys_string),
21+
_ecode(ecode),
22+
_ecode_string(ecode_string)
23+
{ }
24+
void to_json(Json::Value &root) const;
25+
uint32_t ecode() const { return _ecode; }
26+
27+
std::string ecode_string() const { return _ecode_string; }
28+
std::string subsys_string() const { return _subsys_string; }
29+
30+
private:
31+
const uint32_t _subsys;
32+
const std::string _subsys_string;
33+
const uint32_t _ecode;
34+
const std::string _ecode_string;
35+
36+
};
37+
38+
class Analyzer_Subsys_Errors : public Analyzer {
39+
40+
public:
41+
Analyzer_Subsys_Errors(AnalyzerVehicle::Base *&vehicle,
42+
Data_Sources &data_sources) :
43+
Analyzer(vehicle, data_sources)
44+
{ }
45+
46+
47+
const std::string name() const override { return "Error Flags"; }
48+
const std::string description() const override {
49+
return "A UAV can have ongoing errors which it is managing. This test will fail if such errors occur";
50+
}
51+
52+
bool configure(INIReader *config) override;
53+
54+
private:
55+
56+
std::map<uint32_t, uint32_t> _subsys_errors = { };
57+
std::map<uint32_t, Analyzer_Subsys_Errors_Result*> _results = { };
58+
59+
void evaluate() override;
60+
61+
void close_result(const uint32_t code);
62+
void open_result(const uint32_t code, const uint32_t ecode);
63+
64+
void end_of_log(uint32_t packet_count) override;
65+
66+
const std::string subsys_string(const uint32_t subsys) const;
67+
const std::string ecode_string(const uint32_t subsys,
68+
const uint32_t ecode) const;
69+
};
70+
71+
#endif
72+
73+

0 commit comments

Comments
 (0)