mirror of https://github.com/ArduPilot/ardupilot
Replay: automatically find message types, and improve rate detection
This commit is contained in:
parent
21c895f6f3
commit
93800fb3a1
|
@ -34,7 +34,7 @@ def run_replay(logfile):
|
||||||
opts.tolerance_euler,
|
opts.tolerance_euler,
|
||||||
opts.tolerance_pos,
|
opts.tolerance_pos,
|
||||||
opts.tolerance_vel)
|
opts.tolerance_vel)
|
||||||
run_cmd(cmd, checkfail=True)
|
run_cmd(cmd, checkfail=False)
|
||||||
|
|
||||||
def get_log_list():
|
def get_log_list():
|
||||||
'''get a list of log files to process'''
|
'''get a list of log files to process'''
|
||||||
|
@ -158,12 +158,18 @@ def check_logs():
|
||||||
def create_checked_logs():
|
def create_checked_logs():
|
||||||
'''create a set of CHEK logs'''
|
'''create a set of CHEK logs'''
|
||||||
import glob, os, sys
|
import glob, os, sys
|
||||||
pattern = os.path.join(opts.logdir, "*.bin")
|
if os.path.isfile(opts.logdir):
|
||||||
full_file_list = glob.glob(pattern)
|
full_file_list = [opts.logdir]
|
||||||
|
else:
|
||||||
|
pattern = os.path.join(opts.logdir, "*.bin")
|
||||||
|
full_file_list = glob.glob(pattern)
|
||||||
file_list = []
|
file_list = []
|
||||||
for f in full_file_list:
|
for f in full_file_list:
|
||||||
if not f.endswith("-checked.bin"):
|
if not f.endswith("-checked.bin"):
|
||||||
file_list.append(f)
|
file_list.append(f)
|
||||||
|
if len(file_list) == 0:
|
||||||
|
print("No files to process")
|
||||||
|
sys.exit(1)
|
||||||
for f in file_list:
|
for f in file_list:
|
||||||
print("Processing %s" % f)
|
print("Processing %s" % f)
|
||||||
log_list_current = set(glob.glob("logs/*.BIN"))
|
log_list_current = set(glob.glob("logs/*.BIN"))
|
||||||
|
|
|
@ -24,7 +24,7 @@ void LR_MsgHandler::wait_timestamp(uint32_t timestamp)
|
||||||
void LR_MsgHandler::wait_timestamp_from_msg(uint8_t *msg)
|
void LR_MsgHandler::wait_timestamp_from_msg(uint8_t *msg)
|
||||||
{
|
{
|
||||||
uint64_t time_us;
|
uint64_t time_us;
|
||||||
uint64_t time_ms;
|
uint32_t time_ms;
|
||||||
|
|
||||||
if (field_value(msg, "TimeUS", time_us)) {
|
if (field_value(msg, "TimeUS", time_us)) {
|
||||||
// 64-bit timestamp present - great!
|
// 64-bit timestamp present - great!
|
||||||
|
|
|
@ -119,7 +119,8 @@ uint8_t LogReader::map_fmt_type(const char *name, uint8_t intype)
|
||||||
return mapped_msgid[intype];
|
return mapped_msgid[intype];
|
||||||
}
|
}
|
||||||
|
|
||||||
bool LogReader::handle_log_format_msg(const struct log_Format &f) {
|
bool LogReader::handle_log_format_msg(const struct log_Format &f)
|
||||||
|
{
|
||||||
char name[5];
|
char name[5];
|
||||||
memset(name, '\0', 5);
|
memset(name, '\0', 5);
|
||||||
memcpy(name, f.name, 4);
|
memcpy(name, f.name, 4);
|
||||||
|
@ -137,6 +138,10 @@ bool LogReader::handle_log_format_msg(const struct log_Format &f) {
|
||||||
dataflash.WriteBlock(&f_mapped, sizeof(f_mapped));
|
dataflash.WriteBlock(&f_mapped, sizeof(f_mapped));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (msgparser[f.type] != NULL) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
// map from format name to a parser subclass:
|
// map from format name to a parser subclass:
|
||||||
if (streq(name, "PARM")) {
|
if (streq(name, "PARM")) {
|
||||||
parameter_handler = new LR_MsgHandler_PARM(formats[f.type], dataflash,
|
parameter_handler = new LR_MsgHandler_PARM(formats[f.type], dataflash,
|
||||||
|
|
|
@ -45,7 +45,7 @@ private:
|
||||||
|
|
||||||
uint32_t ground_alt_cm;
|
uint32_t ground_alt_cm;
|
||||||
|
|
||||||
class LR_MsgHandler *msgparser[LOGREADER_MAX_FORMATS];
|
class LR_MsgHandler *msgparser[LOGREADER_MAX_FORMATS] {};
|
||||||
|
|
||||||
Vector3f attitude;
|
Vector3f attitude;
|
||||||
Vector3f ahr2_attitude;
|
Vector3f ahr2_attitude;
|
||||||
|
|
|
@ -206,6 +206,14 @@ public:
|
||||||
bool check_solution = false;
|
bool check_solution = false;
|
||||||
const char *log_filename = NULL;
|
const char *log_filename = NULL;
|
||||||
|
|
||||||
|
/*
|
||||||
|
information about a log from find_log_info
|
||||||
|
*/
|
||||||
|
struct log_information {
|
||||||
|
uint16_t update_rate;
|
||||||
|
bool have_imu2;
|
||||||
|
} log_info {};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const char *filename;
|
const char *filename;
|
||||||
ReplayVehicle &_vehicle;
|
ReplayVehicle &_vehicle;
|
||||||
|
@ -226,10 +234,8 @@ private:
|
||||||
bool done_parameters;
|
bool done_parameters;
|
||||||
bool done_baro_init;
|
bool done_baro_init;
|
||||||
bool done_home_init;
|
bool done_home_init;
|
||||||
uint16_t update_rate = 0;
|
|
||||||
int32_t arm_time_ms = -1;
|
int32_t arm_time_ms = -1;
|
||||||
bool ahrs_healthy;
|
bool ahrs_healthy;
|
||||||
bool have_imu2 = false;
|
|
||||||
bool have_imt = false;
|
bool have_imt = false;
|
||||||
bool have_imt2 = false;
|
bool have_imt2 = false;
|
||||||
bool have_fram = false;
|
bool have_fram = false;
|
||||||
|
@ -263,7 +269,9 @@ private:
|
||||||
void read_sensors(const char *type);
|
void read_sensors(const char *type);
|
||||||
void log_check_generate();
|
void log_check_generate();
|
||||||
void log_check_solution();
|
void log_check_solution();
|
||||||
|
bool show_error(const char *text, float max_error, float tolerance);
|
||||||
void report_checks();
|
void report_checks();
|
||||||
|
bool find_log_info(struct log_information &info);
|
||||||
};
|
};
|
||||||
|
|
||||||
Replay replay(replayvehicle);
|
Replay replay(replayvehicle);
|
||||||
|
@ -271,7 +279,6 @@ Replay replay(replayvehicle);
|
||||||
void Replay::usage(void)
|
void Replay::usage(void)
|
||||||
{
|
{
|
||||||
::printf("Options:\n");
|
::printf("Options:\n");
|
||||||
::printf("\t--rate RATE set IMU rate in Hz\n");
|
|
||||||
::printf("\t--parm NAME=VALUE set parameter NAME to VALUE\n");
|
::printf("\t--parm NAME=VALUE set parameter NAME to VALUE\n");
|
||||||
::printf("\t--accel-mask MASK set accel mask (1=accel1 only, 2=accel2 only, 3=both)\n");
|
::printf("\t--accel-mask MASK set accel mask (1=accel1 only, 2=accel2 only, 3=both)\n");
|
||||||
::printf("\t--gyro-mask MASK set gyro mask (1=gyro1 only, 2=gyro2 only, 3=both)\n");
|
::printf("\t--gyro-mask MASK set gyro mask (1=gyro1 only, 2=gyro2 only, 3=both)\n");
|
||||||
|
@ -300,7 +307,6 @@ void Replay::flush_dataflash(void) {
|
||||||
void Replay::_parse_command_line(uint8_t argc, char * const argv[])
|
void Replay::_parse_command_line(uint8_t argc, char * const argv[])
|
||||||
{
|
{
|
||||||
const struct GetOptLong::option options[] = {
|
const struct GetOptLong::option options[] = {
|
||||||
{"rate", true, 0, 'r'},
|
|
||||||
{"parm", true, 0, 'p'},
|
{"parm", true, 0, 'p'},
|
||||||
{"param", true, 0, 'p'},
|
{"param", true, 0, 'p'},
|
||||||
{"help", false, 0, 'h'},
|
{"help", false, 0, 'h'},
|
||||||
|
@ -321,10 +327,6 @@ void Replay::_parse_command_line(uint8_t argc, char * const argv[])
|
||||||
int opt;
|
int opt;
|
||||||
while ((opt = gopt.getoption()) != -1) {
|
while ((opt = gopt.getoption()) != -1) {
|
||||||
switch (opt) {
|
switch (opt) {
|
||||||
case 'r':
|
|
||||||
update_rate = strtol(gopt.optarg, NULL, 0);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'g':
|
case 'g':
|
||||||
logreader.set_gyro_mask(strtol(gopt.optarg, NULL, 0));
|
logreader.set_gyro_mask(strtol(gopt.optarg, NULL, 0));
|
||||||
break;
|
break;
|
||||||
|
@ -394,86 +396,87 @@ void Replay::_parse_command_line(uint8_t argc, char * const argv[])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class IMU2Counter : public DataFlashFileReader {
|
class IMUCounter : public DataFlashFileReader {
|
||||||
public:
|
public:
|
||||||
IMU2Counter() {}
|
IMUCounter() {}
|
||||||
bool handle_log_format_msg(const struct log_Format &f);
|
bool handle_log_format_msg(const struct log_Format &f);
|
||||||
bool handle_msg(const struct log_Format &f, uint8_t *msg);
|
bool handle_msg(const struct log_Format &f, uint8_t *msg);
|
||||||
|
|
||||||
uint64_t last_imu2_timestamp;
|
uint64_t last_imu_timestamp;
|
||||||
private:
|
private:
|
||||||
MsgHandler *handler;
|
MsgHandler *handler;
|
||||||
};
|
};
|
||||||
bool IMU2Counter::handle_log_format_msg(const struct log_Format &f) {
|
|
||||||
if (!strncmp(f.name,"IMU2",4)) {
|
bool IMUCounter::handle_log_format_msg(const struct log_Format &f) {
|
||||||
// an IMU2 message
|
if (!strncmp(f.name,"IMU",4)) {
|
||||||
|
// an IMU message
|
||||||
handler = new MsgHandler(f);
|
handler = new MsgHandler(f);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
bool IMU2Counter::handle_msg(const struct log_Format &f, uint8_t *msg) {
|
|
||||||
if (strncmp(f.name,"IMU2",4)) {
|
bool IMUCounter::handle_msg(const struct log_Format &f, uint8_t *msg) {
|
||||||
// not an IMU2 message
|
if (strncmp(f.name,"IMU",4)) {
|
||||||
|
// not an IMU message
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (handler->field_value(msg, "TimeUS", last_imu2_timestamp)) {
|
if (handler->field_value(msg, "TimeUS", last_imu_timestamp)) {
|
||||||
// ::printf("Found timestamp %ld\n", last_imu2_timestamp);
|
} else if (handler->field_value(msg, "TimeMS", last_imu_timestamp)) {
|
||||||
} else if (handler->field_value(msg, "TimeMS", last_imu2_timestamp)) {
|
last_imu_timestamp *= 1000;
|
||||||
// ::printf("Found millisecond timestamp %ld\n", last_imu2_timestamp);
|
|
||||||
last_imu2_timestamp *= 1000;
|
|
||||||
} else {
|
} else {
|
||||||
::printf("Unable to find timestamp in IMU2 message");
|
::printf("Unable to find timestamp in IMU message");
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
int find_update_rate(const char *filename) {
|
/*
|
||||||
IMU2Counter reader;
|
find information about the log
|
||||||
|
*/
|
||||||
|
bool Replay::find_log_info(struct log_information &info)
|
||||||
|
{
|
||||||
|
IMUCounter reader;
|
||||||
if (!reader.open_log(filename)) {
|
if (!reader.open_log(filename)) {
|
||||||
perror(filename);
|
perror(filename);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
int samplecount = 0;
|
int samplecount = 0;
|
||||||
uint64_t prev = 0;
|
uint64_t prev = 0;
|
||||||
uint64_t samplesum = 0;
|
uint64_t smallest_delta = 0;
|
||||||
prev = 0;
|
prev = 0;
|
||||||
while (samplecount < 10) {
|
while (samplecount < 1000) {
|
||||||
char type[5];
|
char type[5];
|
||||||
if (!reader.update(type)) {
|
if (!reader.update(type)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (streq(type, "IMU2")) {
|
if (streq(type, "IMU")) {
|
||||||
if (prev == 0) {
|
if (prev == 0) {
|
||||||
prev = reader.last_imu2_timestamp;
|
prev = reader.last_imu_timestamp;
|
||||||
} else {
|
} else {
|
||||||
|
uint64_t delta = reader.last_imu_timestamp - prev;
|
||||||
|
if (smallest_delta == 0 || delta < smallest_delta) {
|
||||||
|
smallest_delta = delta;
|
||||||
|
}
|
||||||
samplecount++;
|
samplecount++;
|
||||||
samplesum += reader.last_imu2_timestamp - prev;
|
|
||||||
prev = reader.last_imu2_timestamp;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (streq(type, "IMU2") && !info.have_imu2) {
|
||||||
|
info.have_imu2 = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (samplecount < 10) {
|
if (smallest_delta == 0) {
|
||||||
::printf("Unable to determine log rate - insufficient IMU2 messages?!");
|
::printf("Unable to determine log rate - insufficient IMU messages?!");
|
||||||
exit(1);
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
float rate = 1000000/int(samplesum/samplecount);
|
float rate = 1.0e6f/smallest_delta;
|
||||||
if (abs(rate - 50) < 5) {
|
if (rate < 100) {
|
||||||
return 50;
|
info.update_rate = 50;
|
||||||
|
} else {
|
||||||
|
info.update_rate = 400;
|
||||||
}
|
}
|
||||||
if (abs(rate - 100) < 10) {
|
return true;
|
||||||
return 100;
|
|
||||||
}
|
|
||||||
if (abs(rate - 200) < 10) {
|
|
||||||
return 200;
|
|
||||||
}
|
|
||||||
if (abs(rate - 400) < 20) { // I have a log which is 10 off...
|
|
||||||
return 400;
|
|
||||||
}
|
|
||||||
::printf("Unable to determine log rate - %f matches no rate\n", rate);
|
|
||||||
exit(1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// catch floating point exceptions
|
// catch floating point exceptions
|
||||||
|
@ -510,11 +513,12 @@ void Replay::setup()
|
||||||
// remember filename for reporting
|
// remember filename for reporting
|
||||||
log_filename = filename;
|
log_filename = filename;
|
||||||
|
|
||||||
if (update_rate == 0) {
|
if (!find_log_info(log_info)) {
|
||||||
update_rate = find_update_rate(filename);
|
printf("Update to get log information\n");
|
||||||
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
hal.console->printf("Using an update rate of %u Hz\n", update_rate);
|
hal.console->printf("Using an update rate of %u Hz\n", log_info.update_rate);
|
||||||
|
|
||||||
if (!logreader.open_log(filename)) {
|
if (!logreader.open_log(filename)) {
|
||||||
perror(filename);
|
perror(filename);
|
||||||
|
@ -522,12 +526,7 @@ void Replay::setup()
|
||||||
}
|
}
|
||||||
|
|
||||||
_vehicle.setup();
|
_vehicle.setup();
|
||||||
set_ins_update_rate(update_rate);
|
set_ins_update_rate(log_info.update_rate);
|
||||||
|
|
||||||
logreader.wait_type("GPS");
|
|
||||||
logreader.wait_type("IMU");
|
|
||||||
logreader.wait_type("GPS");
|
|
||||||
logreader.wait_type("IMU");
|
|
||||||
|
|
||||||
feenableexcept(FE_INVALID | FE_OVERFLOW);
|
feenableexcept(FE_INVALID | FE_OVERFLOW);
|
||||||
|
|
||||||
|
@ -545,32 +544,10 @@ void Replay::setup()
|
||||||
fprintf(ekf2f, "timestamp TimeMS AX AY AZ VWN VWE MN ME MD MX MY MZ\n");
|
fprintf(ekf2f, "timestamp TimeMS AX AY AZ VWN VWE MN ME MD MX MY MZ\n");
|
||||||
fprintf(ekf3f, "timestamp TimeMS IVN IVE IVD IPN IPE IPD IMX IMY IMZ IVT\n");
|
fprintf(ekf3f, "timestamp TimeMS IVN IVE IVD IPN IPE IPD IMX IMY IMZ IVT\n");
|
||||||
fprintf(ekf4f, "timestamp TimeMS SV SP SH SMX SMY SMZ SVT OFN EFE FS DS\n");
|
fprintf(ekf4f, "timestamp TimeMS SV SP SH SMX SMY SMZ SVT OFN EFE FS DS\n");
|
||||||
|
|
||||||
::printf("Waiting for GPS\n");
|
|
||||||
while (!done_home_init) {
|
|
||||||
char type[5];
|
|
||||||
if (!logreader.update(type)) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
read_sensors(type);
|
|
||||||
if (streq(type, "GPS") &&
|
|
||||||
(_vehicle.gps.status() >= AP_GPS::GPS_OK_FIX_3D) &&
|
|
||||||
done_baro_init && !done_home_init) {
|
|
||||||
const Location &loc = _vehicle.gps.location();
|
|
||||||
::printf("GPS Lock at %.7f %.7f %.2fm time=%.1f seconds\n",
|
|
||||||
loc.lat * 1.0e-7f,
|
|
||||||
loc.lng * 1.0e-7f,
|
|
||||||
loc.alt * 0.01f,
|
|
||||||
hal.scheduler->millis()*0.001f);
|
|
||||||
_vehicle.ahrs.set_home(loc);
|
|
||||||
_vehicle.compass.set_initial_location(loc.lat, loc.lng);
|
|
||||||
done_home_init = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Replay::set_ins_update_rate(uint16_t _update_rate) {
|
void Replay::set_ins_update_rate(uint16_t _update_rate) {
|
||||||
switch (update_rate) {
|
switch (_update_rate) {
|
||||||
case 50:
|
case 50:
|
||||||
_vehicle.ins.init(AP_InertialSensor::WARM_START, AP_InertialSensor::RATE_50HZ);
|
_vehicle.ins.init(AP_InertialSensor::WARM_START, AP_InertialSensor::RATE_50HZ);
|
||||||
break;
|
break;
|
||||||
|
@ -609,9 +586,6 @@ void Replay::read_sensors(const char *type)
|
||||||
done_parameters = true;
|
done_parameters = true;
|
||||||
set_user_parameters();
|
set_user_parameters();
|
||||||
}
|
}
|
||||||
if (streq(type,"IMU2")) {
|
|
||||||
have_imu2 = true;
|
|
||||||
}
|
|
||||||
if (use_imt && streq(type,"IMT")) {
|
if (use_imt && streq(type,"IMT")) {
|
||||||
have_imt = true;
|
have_imt = true;
|
||||||
}
|
}
|
||||||
|
@ -619,6 +593,21 @@ void Replay::read_sensors(const char *type)
|
||||||
have_imt2 = true;
|
have_imt2 = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!done_home_init) {
|
||||||
|
if (streq(type, "GPS") &&
|
||||||
|
(_vehicle.gps.status() >= AP_GPS::GPS_OK_FIX_3D) && done_baro_init) {
|
||||||
|
const Location &loc = _vehicle.gps.location();
|
||||||
|
::printf("GPS Lock at %.7f %.7f %.2fm time=%.1f seconds\n",
|
||||||
|
loc.lat * 1.0e-7f,
|
||||||
|
loc.lng * 1.0e-7f,
|
||||||
|
loc.alt * 0.01f,
|
||||||
|
hal.scheduler->millis()*0.001f);
|
||||||
|
_vehicle.ahrs.set_home(loc);
|
||||||
|
_vehicle.compass.set_initial_location(loc.lat, loc.lng);
|
||||||
|
done_home_init = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (streq(type,"GPS")) {
|
if (streq(type,"GPS")) {
|
||||||
_vehicle.gps.update();
|
_vehicle.gps.update();
|
||||||
if (_vehicle.gps.status() >= AP_GPS::GPS_OK_FIX_3D) {
|
if (_vehicle.gps.status() >= AP_GPS::GPS_OK_FIX_3D) {
|
||||||
|
@ -656,7 +645,7 @@ void Replay::read_sensors(const char *type)
|
||||||
// special handling of IMU messages as these trigger an ahrs.update()
|
// special handling of IMU messages as these trigger an ahrs.update()
|
||||||
if (!have_fram &&
|
if (!have_fram &&
|
||||||
!have_imt &&
|
!have_imt &&
|
||||||
((streq(type,"IMU") && !have_imu2) || (streq(type, "IMU2") && have_imu2))) {
|
((streq(type,"IMU") && !log_info.have_imu2) || (streq(type, "IMU2") && log_info.have_imu2))) {
|
||||||
run_ahrs = true;
|
run_ahrs = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -980,12 +969,26 @@ void Replay::loop()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
flush_dataflash();
|
||||||
|
|
||||||
if (check_solution) {
|
if (check_solution) {
|
||||||
report_checks();
|
report_checks();
|
||||||
}
|
}
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Replay::show_error(const char *text, float max_error, float tolerance)
|
||||||
|
{
|
||||||
|
bool failed = max_error > tolerance;
|
||||||
|
printf("%s:\t%.2f %c %.2f\n",
|
||||||
|
text,
|
||||||
|
max_error,
|
||||||
|
failed?'>':'<',
|
||||||
|
tolerance);
|
||||||
|
return failed;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
report results of --check
|
report results of --check
|
||||||
*/
|
*/
|
||||||
|
@ -1006,26 +1009,11 @@ void Replay::report_checks(void)
|
||||||
check_result.max_vel_error);
|
check_result.max_vel_error);
|
||||||
fclose(f);
|
fclose(f);
|
||||||
}
|
}
|
||||||
if (check_result.max_roll_error > tolerance_euler) {
|
failed |= show_error("Roll error", check_result.max_roll_error, tolerance_euler);
|
||||||
printf("Roll error %.2f > %.2f\n", check_result.max_roll_error, tolerance_euler);
|
failed |= show_error("Pitch error", check_result.max_pitch_error, tolerance_euler);
|
||||||
failed = true;
|
failed |= show_error("Yaw error", check_result.max_yaw_error, tolerance_euler);
|
||||||
}
|
failed |= show_error("Position error", check_result.max_pos_error, tolerance_pos);
|
||||||
if (check_result.max_pitch_error > tolerance_euler) {
|
failed |= show_error("Velocity error", check_result.max_vel_error, tolerance_vel);
|
||||||
printf("Pitch error %.2f > %.2f\n", check_result.max_pitch_error, tolerance_euler);
|
|
||||||
failed = true;
|
|
||||||
}
|
|
||||||
if (check_result.max_yaw_error > tolerance_euler) {
|
|
||||||
printf("Yaw error %.2f > %.2f\n", check_result.max_yaw_error, tolerance_euler);
|
|
||||||
failed = true;
|
|
||||||
}
|
|
||||||
if (check_result.max_pos_error > tolerance_pos) {
|
|
||||||
printf("Position error %.2f > %.2f\n", check_result.max_pos_error, tolerance_pos);
|
|
||||||
failed = true;
|
|
||||||
}
|
|
||||||
if (check_result.max_vel_error > tolerance_vel) {
|
|
||||||
printf("Velocity error %.2f > %.2f\n", check_result.max_vel_error, tolerance_vel);
|
|
||||||
failed = true;
|
|
||||||
}
|
|
||||||
if (failed) {
|
if (failed) {
|
||||||
printf("Checks failed\n");
|
printf("Checks failed\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
|
|
Loading…
Reference in New Issue