mirror of
https://github.com/PX4/PX4-Autopilot.git
synced 2026-05-28 02:36:37 +08:00
ekf2-replay: best effort replay when no ekf2_timestamps
Run at sensor_combined speed and publish all other sensors occuring between 2 sonsor_combined samples. This allows a crude replay in case ekf2 replay was not enabled during the flight.
This commit is contained in:
committed by
Mathieu Bresciani
parent
f583406558
commit
cae4f94476
@@ -730,6 +730,7 @@ Replay::nextDataMessage(std::ifstream &file, Subscription &subscription, int msg
|
|||||||
subscription.next_read_pos = cur_pos;
|
subscription.next_read_pos = cur_pos;
|
||||||
file.seekg(subscription.timestamp_offset, ios::cur);
|
file.seekg(subscription.timestamp_offset, ios::cur);
|
||||||
file.read((char *)&subscription.next_timestamp, sizeof(subscription.next_timestamp));
|
file.read((char *)&subscription.next_timestamp, sizeof(subscription.next_timestamp));
|
||||||
|
subscription.published = false;
|
||||||
done = true;
|
done = true;
|
||||||
|
|
||||||
} else { //sanity check failed!
|
} else { //sanity check failed!
|
||||||
@@ -1125,6 +1126,7 @@ Replay::publishTopic(Subscription &sub, void *data)
|
|||||||
|
|
||||||
if (published) {
|
if (published) {
|
||||||
++sub.publication_counter;
|
++sub.publication_counter;
|
||||||
|
sub.published = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return published;
|
return published;
|
||||||
|
|||||||
@@ -44,7 +44,6 @@
|
|||||||
|
|
||||||
#include <px4_platform_common/module.h>
|
#include <px4_platform_common/module.h>
|
||||||
#include <uORB/topics/uORBTopics.hpp>
|
#include <uORB/topics/uORBTopics.hpp>
|
||||||
#include <uORB/topics/ekf2_timestamps.h>
|
|
||||||
|
|
||||||
namespace px4
|
namespace px4
|
||||||
{
|
{
|
||||||
@@ -141,8 +140,10 @@ protected:
|
|||||||
CompatBase *compat = nullptr;
|
CompatBase *compat = nullptr;
|
||||||
|
|
||||||
// statistics
|
// statistics
|
||||||
int error_counter = 0;
|
int approx_timestamp_counter = 0;
|
||||||
int publication_counter = 0;
|
int publication_counter = 0;
|
||||||
|
|
||||||
|
bool published = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -75,6 +75,20 @@ ReplayEkf2::handleTopicUpdate(Subscription &sub, void *data, std::ifstream &repl
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
} else if (sub.orb_meta == ORB_ID(sensor_combined) && !_ekf2_timestamps_exists) {
|
||||||
|
// No ekf2_timestamps topic, publish with approximate timestamps
|
||||||
|
sensor_combined_s sensor_combined;
|
||||||
|
memcpy(&sensor_combined, data, sub.orb_meta->o_size);
|
||||||
|
|
||||||
|
if (!publishEkf2Topics(sensor_combined, replay_file)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wait for modules to process the data
|
||||||
|
px4_lockstep_wait_for_components();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
|
||||||
} else if (sub.orb_meta == ORB_ID(vehicle_status) || sub.orb_meta == ORB_ID(vehicle_land_detected)
|
} else if (sub.orb_meta == ORB_ID(vehicle_status) || sub.orb_meta == ORB_ID(vehicle_land_detected)
|
||||||
|| sub.orb_meta == ORB_ID(vehicle_gps_position)) {
|
|| sub.orb_meta == ORB_ID(vehicle_gps_position)) {
|
||||||
return publishTopic(sub, data);
|
return publishTopic(sub, data);
|
||||||
@@ -121,13 +135,34 @@ ReplayEkf2::onSubscriptionAdded(Subscription &sub, uint16_t msg_id)
|
|||||||
|
|
||||||
} else if (sub.orb_meta == ORB_ID(vehicle_global_position_groundtruth)) {
|
} else if (sub.orb_meta == ORB_ID(vehicle_global_position_groundtruth)) {
|
||||||
_vehicle_global_position_groundtruth_msg_id = msg_id;
|
_vehicle_global_position_groundtruth_msg_id = msg_id;
|
||||||
|
|
||||||
|
} else if (sub.orb_meta == ORB_ID(ekf2_timestamps)) {
|
||||||
|
_ekf2_timestamps_exists = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// the main loop should only handle publication of the following topics, the sensor topics are
|
// the main loop should only handle publication of the following topics, the sensor topics are
|
||||||
// handled separately in publishEkf2Topics()
|
// handled separately in publishEkf2Topics()
|
||||||
// Note: the GPS is not treated here since not missing data is more important than the accuracy of the timestamp
|
// Note: the GPS is not treated here since not missing data is more important than the accuracy of the timestamp
|
||||||
sub.ignored = sub.orb_meta != ORB_ID(ekf2_timestamps) && sub.orb_meta != ORB_ID(vehicle_status)
|
sub.ignored = sub.orb_meta != ORB_ID(ekf2_timestamps) && sub.orb_meta != ORB_ID(vehicle_status)
|
||||||
&& sub.orb_meta != ORB_ID(vehicle_land_detected) && sub.orb_meta != ORB_ID(vehicle_gps_position);
|
&& sub.orb_meta != ORB_ID(vehicle_land_detected) && sub.orb_meta != ORB_ID(vehicle_gps_position)
|
||||||
|
&& sub.orb_meta != ORB_ID(sensor_combined);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
ReplayEkf2::publishEkf2Topics(sensor_combined_s &sensor_combined, std::ifstream &replay_file)
|
||||||
|
{
|
||||||
|
findTimestampAndPublish(sensor_combined.timestamp / 100, _airspeed_msg_id, replay_file);
|
||||||
|
findTimestampAndPublish(sensor_combined.timestamp / 100, _distance_sensor_msg_id, replay_file);
|
||||||
|
findTimestampAndPublish(sensor_combined.timestamp / 100, _optical_flow_msg_id, replay_file);
|
||||||
|
findTimestampAndPublish(sensor_combined.timestamp / 100, _vehicle_air_data_msg_id, replay_file);
|
||||||
|
findTimestampAndPublish(sensor_combined.timestamp / 100, _vehicle_magnetometer_msg_id, replay_file);
|
||||||
|
findTimestampAndPublish(sensor_combined.timestamp / 100, _vehicle_visual_odometry_msg_id, replay_file);
|
||||||
|
findTimestampAndPublish(sensor_combined.timestamp / 100, _aux_global_position_msg_id, replay_file);
|
||||||
|
|
||||||
|
// sensor_combined: publish last because ekf2 is polling on this
|
||||||
|
publishTopic(*_subscriptions[_sensor_combined_msg_id], &sensor_combined);
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
@@ -182,25 +217,26 @@ ReplayEkf2::findTimestampAndPublish(uint64_t timestamp, uint16_t msg_id, std::if
|
|||||||
|
|
||||||
Subscription &sub = *_subscriptions[msg_id];
|
Subscription &sub = *_subscriptions[msg_id];
|
||||||
|
|
||||||
while (sub.next_timestamp / 100 < timestamp && sub.orb_meta) {
|
bool topic_published = false;
|
||||||
|
|
||||||
|
while (sub.next_timestamp / 100 <= timestamp && sub.orb_meta) {
|
||||||
|
if (!sub.published) {
|
||||||
|
if (sub.next_timestamp / 100 != timestamp) {
|
||||||
|
// Not the exact sample, publish but notify error
|
||||||
|
PX4_DEBUG("No timestamp match found for topic %s (%" PRIu64 ", %" PRIu64 ")\n", sub.orb_meta->o_name, sub.next_timestamp / 100,
|
||||||
|
timestamp);
|
||||||
|
++sub.approx_timestamp_counter;
|
||||||
|
}
|
||||||
|
|
||||||
|
readTopicDataToBuffer(sub, replay_file);
|
||||||
|
publishTopic(sub, _read_buffer.data());
|
||||||
|
topic_published = true;
|
||||||
|
}
|
||||||
|
|
||||||
nextDataMessage(replay_file, sub, msg_id);
|
nextDataMessage(replay_file, sub, msg_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!sub.orb_meta) { // no messages anymore
|
return topic_published;
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sub.next_timestamp / 100 != timestamp) {
|
|
||||||
// this can happen in beginning of the log or on a dropout
|
|
||||||
PX4_DEBUG("No timestamp match found for topic %s (%i, %i)", sub.orb_meta->o_name, (int)sub.next_timestamp / 100,
|
|
||||||
timestamp);
|
|
||||||
++sub.error_counter;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
readTopicDataToBuffer(sub, replay_file);
|
|
||||||
publishTopic(sub, _read_buffer.data());
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -220,14 +256,19 @@ ReplayEkf2::onExitMainLoop()
|
|||||||
if (msg_id != msg_id_invalid) {
|
if (msg_id != msg_id_invalid) {
|
||||||
Subscription &sub = *_subscriptions[msg_id];
|
Subscription &sub = *_subscriptions[msg_id];
|
||||||
|
|
||||||
if (sub.publication_counter > 0 || sub.error_counter > 0) {
|
if (sub.publication_counter > 0 || sub.approx_timestamp_counter > 0) {
|
||||||
PX4_INFO("%s: %i, %i", name, sub.publication_counter, sub.error_counter);
|
PX4_INFO("%s: %i (%i)", name, sub.publication_counter, sub.approx_timestamp_counter);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
PX4_INFO("");
|
PX4_INFO("");
|
||||||
PX4_INFO("Topic, Num Published, Num Error (no timestamp match found):");
|
|
||||||
|
if (!_ekf2_timestamps_exists) {
|
||||||
|
PX4_INFO("/!\\ Approximate replay (ekf2_timestamps not found)\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
PX4_INFO("Topic, Num Published (Num approximate timestamp found):");
|
||||||
|
|
||||||
print_sensor_statistics(_airspeed_msg_id, "airspeed");
|
print_sensor_statistics(_airspeed_msg_id, "airspeed");
|
||||||
print_sensor_statistics(_airspeed_validated_msg_id, "airspeed_validated");
|
print_sensor_statistics(_airspeed_validated_msg_id, "airspeed_validated");
|
||||||
|
|||||||
@@ -35,6 +35,9 @@
|
|||||||
|
|
||||||
#include "Replay.hpp"
|
#include "Replay.hpp"
|
||||||
|
|
||||||
|
#include <uORB/topics/ekf2_timestamps.h>
|
||||||
|
#include <uORB/topics/sensor_combined.h>
|
||||||
|
|
||||||
namespace px4
|
namespace px4
|
||||||
{
|
{
|
||||||
|
|
||||||
@@ -70,6 +73,8 @@ private:
|
|||||||
|
|
||||||
bool publishEkf2Topics(const ekf2_timestamps_s &ekf2_timestamps, std::ifstream &replay_file);
|
bool publishEkf2Topics(const ekf2_timestamps_s &ekf2_timestamps, std::ifstream &replay_file);
|
||||||
|
|
||||||
|
bool publishEkf2Topics(sensor_combined_s &sensors_combined, std::ifstream &replay_file);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* find the next message for a subscription that matches a given timestamp and publish it
|
* find the next message for a subscription that matches a given timestamp and publish it
|
||||||
* @param timestamp in 0.1 ms
|
* @param timestamp in 0.1 ms
|
||||||
@@ -93,6 +98,8 @@ private:
|
|||||||
uint16_t _vehicle_local_position_groundtruth_msg_id = msg_id_invalid;
|
uint16_t _vehicle_local_position_groundtruth_msg_id = msg_id_invalid;
|
||||||
uint16_t _vehicle_global_position_groundtruth_msg_id = msg_id_invalid;
|
uint16_t _vehicle_global_position_groundtruth_msg_id = msg_id_invalid;
|
||||||
uint16_t _vehicle_attitude_groundtruth_msg_id = msg_id_invalid;
|
uint16_t _vehicle_attitude_groundtruth_msg_id = msg_id_invalid;
|
||||||
|
|
||||||
|
bool _ekf2_timestamps_exists{false};
|
||||||
};
|
};
|
||||||
|
|
||||||
} //namespace px4
|
} //namespace px4
|
||||||
|
|||||||
Reference in New Issue
Block a user