mavlink: keep track of seq for any component

Instead of only keeping track of the sequence ID of specific "supported"
components, we now keep track of any sysid/compid of an incoming
message. Before this change, unknown components (such as jMAVSim) would
completely screw up the mavlink message stats and create confusion (at
least in my case).

With this change we currently keep track of up to 8 other components.
Once we reach the limit, we will print a warning.
This commit is contained in:
Julian Oes 2021-04-21 13:37:13 +02:00 committed by Daniel Agar
parent 6ae23e7b7b
commit 71bd35fcaa
3 changed files with 68 additions and 186 deletions

View File

@ -28,7 +28,6 @@ uint32 tx_buffer_overruns # number of TX buffer overruns
float32 rx_rate_avg # transmit rate average (Bytes/s)
uint32 rx_message_count # count of total messages received
uint32 rx_message_count_supported # count of total messages received from supported systems and components (for loss statistics)
uint32 rx_message_lost_count
uint32 rx_buffer_overruns # number of RX buffer overruns
uint32 rx_parse_errors # number of parse errors

View File

@ -1,6 +1,6 @@
/****************************************************************************
*
* Copyright (c) 2012-2019 PX4 Development Team. All rights reserved.
* Copyright (c) 2012-2021 PX4 Development Team. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@ -71,43 +71,6 @@
#define MAVLINK_RECEIVER_NET_ADDED_STACK 0
#endif
const uint8_t MavlinkReceiver::supported_component_map[COMP_ID_MAX] = {
[COMP_ID_ALL] = MAV_COMP_ID_ALL,
[COMP_ID_AUTOPILOT1] = MAV_COMP_ID_AUTOPILOT1,
[COMP_ID_TELEMETRY_RADIO] = MAV_COMP_ID_TELEMETRY_RADIO,
[COMP_ID_CAMERA] = MAV_COMP_ID_CAMERA,
[COMP_ID_CAMERA2] = MAV_COMP_ID_CAMERA2,
[COMP_ID_GIMBAL] = MAV_COMP_ID_GIMBAL,
[COMP_ID_LOG] = MAV_COMP_ID_LOG,
[COMP_ID_ADSB] = MAV_COMP_ID_ADSB,
[COMP_ID_OSD] = MAV_COMP_ID_OSD,
[COMP_ID_PERIPHERAL] = MAV_COMP_ID_PERIPHERAL,
[COMP_ID_FLARM] = MAV_COMP_ID_FLARM,
[COMP_ID_GIMBAL2] = MAV_COMP_ID_GIMBAL2,
[COMP_ID_MISSIONPLANNER] = MAV_COMP_ID_MISSIONPLANNER,
[COMP_ID_ONBOARD_COMPUTER] = MAV_COMP_ID_ONBOARD_COMPUTER,
[COMP_ID_PATHPLANNER] = MAV_COMP_ID_PATHPLANNER,
[COMP_ID_OBSTACLE_AVOIDANCE] = MAV_COMP_ID_OBSTACLE_AVOIDANCE,
[COMP_ID_VISUAL_INERTIAL_ODOMETRY] = MAV_COMP_ID_VISUAL_INERTIAL_ODOMETRY,
[COMP_ID_PAIRING_MANAGER] = MAV_COMP_ID_PAIRING_MANAGER,
[COMP_ID_IMU] = MAV_COMP_ID_IMU,
[COMP_ID_GPS] = MAV_COMP_ID_GPS,
[COMP_ID_GPS2] = MAV_COMP_ID_GPS2,
[COMP_ID_UDP_BRIDGE] = MAV_COMP_ID_UDP_BRIDGE,
[COMP_ID_UART_BRIDGE] = MAV_COMP_ID_UART_BRIDGE,
[COMP_ID_TUNNEL_NODE] = MAV_COMP_ID_TUNNEL_NODE,
};
MavlinkReceiver::~MavlinkReceiver()
{
delete _tune_publisher;
@ -3045,7 +3008,6 @@ MavlinkReceiver::Run()
/* if read failed, this loop won't execute */
for (ssize_t i = 0; i < nread; i++) {
if (mavlink_parse_char(_mavlink->get_channel(), buf[i], &msg, &_status)) {
_total_received_counter++;
/* check if we received version 2 and request a switch. */
if (!(_mavlink->get_status()->flags & MAVLINK_STATUS_FLAG_IN_MAVLINK1)) {
@ -3077,99 +3039,7 @@ MavlinkReceiver::Run()
/* handle packet with parent object */
_mavlink->handle_message(&msg);
// calculate lost messages for this system id
bool px4_sysid_index_found = false;
int px4_sysid_index = 0;
if (msg.sysid != mavlink_system.sysid) {
for (int sys_id = 1; sys_id < MAX_REMOTE_SYSTEM_IDS; sys_id++) {
if (_system_id_map[sys_id] == msg.sysid) {
// slot found
px4_sysid_index_found = true;
px4_sysid_index = sys_id;
break;
}
}
// otherwise record newly seen system id in first available slot
if (!px4_sysid_index_found) {
for (int sys_id = 1; sys_id < MAX_REMOTE_SYSTEM_IDS; sys_id++) {
if (_system_id_map[sys_id] == 0) {
// slot available
px4_sysid_index_found = true;
px4_sysid_index = sys_id;
_system_id_map[sys_id] = msg.sysid;
break;
}
}
}
if (!px4_sysid_index_found) {
PX4_ERR("not enough system id slots (%d)", MAX_REMOTE_SYSTEM_IDS);
}
} else {
px4_sysid_index_found = true;
}
// find PX4 component id
uint8_t px4_comp_id = 0;
bool px4_comp_id_found = false;
for (int id = 0; id < COMP_ID_MAX; id++) {
if (supported_component_map[id] == msg.compid) {
px4_comp_id = id;
px4_comp_id_found = true;
break;
}
}
if (!px4_comp_id_found && !_reported_unsupported_comp_id) {
PX4_WARN("unsupported component id, msgid: %d, sysid: %d compid: %d", msg.msgid, msg.sysid, msg.compid);
_reported_unsupported_comp_id = true;
}
if (px4_comp_id_found && px4_sysid_index_found) {
// Increase receive counter
_total_received_supported_counter++;
uint8_t last_seq = _last_index[px4_sysid_index][px4_comp_id];
uint8_t expected_seq = last_seq + 1;
// Determine what the next expected sequence number is, accounting for
// never having seen a message for this system/component pair.
if (!_sys_comp_present[px4_sysid_index][px4_comp_id]) {
_sys_comp_present[px4_sysid_index][px4_comp_id] = true;
last_seq = msg.seq;
expected_seq = msg.seq;
}
// And if we didn't encounter that sequence number, record the error
if (msg.seq != expected_seq) {
int lost_messages = 0;
// Account for overflow during packet loss
if (msg.seq < expected_seq) {
lost_messages = (msg.seq + 255) - expected_seq;
} else {
lost_messages = msg.seq - expected_seq;
}
// Log how many were lost
_total_lost_counter += lost_messages;
}
// And update the last sequence number for this system/component pair
_last_index[px4_sysid_index][px4_comp_id] = msg.seq;
// Calculate new loss ratio
const float total_sent = _total_received_supported_counter + _total_lost_counter;
float rx_loss_percent = (_total_lost_counter / total_sent) * 100.f;
_running_loss_percent = (rx_loss_percent * 0.5f) + (_running_loss_percent * 0.5f);
}
update_rx_stats(msg);
}
}
@ -3179,9 +3049,8 @@ MavlinkReceiver::Run()
telemetry_status_s &tstatus = _mavlink->telemetry_status();
tstatus.rx_message_count = _total_received_counter;
tstatus.rx_message_count_supported = _total_received_supported_counter;
tstatus.rx_message_lost_count = _total_lost_counter;
tstatus.rx_message_lost_rate = _running_loss_percent;
tstatus.rx_message_lost_rate = static_cast<float>(_total_lost_counter) / static_cast<float>(_total_received_counter);
if (_mavlink_status_last_buffer_overrun != _status.buffer_overrun) {
tstatus.rx_buffer_overruns++;
@ -3232,6 +3101,59 @@ MavlinkReceiver::Run()
}
}
void MavlinkReceiver::update_rx_stats(const mavlink_message_t &message)
{
const bool component_states_has_still_space = [this, &message]() {
for (unsigned i = 0; i < MAX_REMOTE_COMPONENTS; ++i) {
if (_component_states[i].system_id == message.sysid && _component_states[i].component_id == message.compid) {
int lost_messages = 0;
const uint8_t expected_seq = _component_states[i].last_sequence + 1;
// Account for overflow during packet loss
if (message.seq < expected_seq) {
lost_messages = (message.seq + 255) - expected_seq;
} else {
lost_messages = message.seq - expected_seq;
}
_component_states[i].missed_messages += lost_messages;
++_component_states[i].received_messages;
_component_states[i].last_time_received_ms = hrt_absolute_time() / 1000;
_component_states[i].last_sequence = message.seq;
// Also update overall stats
++_total_received_counter;
_total_lost_counter += lost_messages;
return true;
} else if (_component_states[i].system_id == 0 && _component_states[i].component_id == 0) {
_component_states[i].system_id = message.sysid;
_component_states[i].component_id = message.compid;
++_component_states[i].received_messages;
_component_states[i].last_time_received_ms = hrt_absolute_time() / 1000;
_component_states[i].last_sequence = message.seq;
// Also update overall stats
++_total_received_counter;
return true;
}
}
return false;
}();
if (!component_states_has_still_space && !_warned_component_states_full_once) {
PX4_WARN("Max remote components of %u used up", MAX_REMOTE_COMPONENTS);
_warned_component_states_full_once = true;
}
}
void *
MavlinkReceiver::start_helper(void *context)
{

View File

@ -1,6 +1,6 @@
/****************************************************************************
*
* Copyright (c) 2012-2020 PX4 Development Team. All rights reserved.
* Copyright (c) 2012-2021 PX4 Development Team. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@ -225,6 +225,7 @@ private:
void schedule_tune(const char *tune);
void update_rx_stats(const mavlink_message_t &message);
Mavlink *_mavlink;
@ -238,60 +239,20 @@ private:
orb_advert_t _mavlink_log_pub{nullptr};
// subset of MAV_COMPONENTs we support
enum SUPPORTED_COMPONENTS : uint8_t {
COMP_ID_ALL,
COMP_ID_AUTOPILOT1,
COMP_ID_TELEMETRY_RADIO,
COMP_ID_CAMERA,
COMP_ID_CAMERA2,
COMP_ID_GIMBAL,
COMP_ID_LOG,
COMP_ID_ADSB,
COMP_ID_OSD,
COMP_ID_PERIPHERAL,
COMP_ID_FLARM,
COMP_ID_GIMBAL2,
COMP_ID_MISSIONPLANNER,
COMP_ID_ONBOARD_COMPUTER,
COMP_ID_PATHPLANNER,
COMP_ID_OBSTACLE_AVOIDANCE,
COMP_ID_VISUAL_INERTIAL_ODOMETRY,
COMP_ID_PAIRING_MANAGER,
COMP_ID_IMU,
COMP_ID_GPS,
COMP_ID_GPS2,
COMP_ID_UDP_BRIDGE,
COMP_ID_UART_BRIDGE,
COMP_ID_TUNNEL_NODE,
COMP_ID_MAX
static constexpr int MAX_REMOTE_COMPONENTS{8};
struct ComponentState {
uint32_t last_time_received_ms{0};
uint32_t received_messages{0};
uint32_t missed_messages{0};
uint8_t system_id{0};
uint8_t component_id{0};
uint8_t last_sequence{0};
};
ComponentState _component_states[MAX_REMOTE_COMPONENTS] {};
bool _warned_component_states_full_once{false};
// map of supported component IDs to MAV_COMP value
static const uint8_t supported_component_map[COMP_ID_MAX];
bool _reported_unsupported_comp_id{false};
static constexpr int MAX_REMOTE_SYSTEM_IDS{8};
uint8_t _system_id_map[MAX_REMOTE_SYSTEM_IDS] {};
uint8_t _last_index[MAX_REMOTE_SYSTEM_IDS][COMP_ID_MAX] {}; ///< Store the last received sequence ID for each system/componenet pair
uint8_t _sys_comp_present[MAX_REMOTE_SYSTEM_IDS][COMP_ID_MAX] {}; ///< First message flag
uint64_t _total_received_counter{0}; ///< The total number of successfully received messages
uint64_t _total_received_supported_counter{0}; ///< The total number of successfully received messages
uint64_t _total_lost_counter{0}; ///< Total messages lost during transmission.
float _running_loss_percent{0}; ///< Loss rate
uint8_t _mavlink_status_last_buffer_overrun{0};
uint8_t _mavlink_status_last_parse_error{0};