-
Notifications
You must be signed in to change notification settings - Fork 13.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
High Latency Telemetry Support #8582
Conversation
@acfloria this seems very interesting. Question: based on the latest iteration that's ongoing on Mavlink form HIGH_LATENCY msg, would this be ready to actually establish a two-way communication instead of just having the FCU sending the data? |
Generally looks good. I'll review in detail and test on my side. What testing have you done with real hardware so far? @TSC21 if you have everything it would be great to test this as well. |
src/modules/commander/commander.cpp
Outdated
mavlink_log_critical(&mavlink_log_pub, "ALL LOW LATENCY DATA LINKS LOST, ACTIVATING HIGH LATENCY LINK"); | ||
vehicle_command_s vehicle_cmd; | ||
vehicle_cmd.command = vehicle_command_s::VEHICLE_CMD_MAVLINK_ENABLE_SENDING; | ||
vehicle_cmd.param1 = 6; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
magic numbers
src/modules/mavlink/mavlink_main.cpp
Outdated
if (vehicle_cmd.command == vehicle_command_s::VEHICLE_CMD_MAVLINK_ENABLE_SENDING) { | ||
if (_mode == (int)round(vehicle_cmd.param1)) { | ||
if (_transmitting_enabled != (int)vehicle_cmd.param2) { | ||
if ((int)vehicle_cmd.param2) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
braces
src/modules/mavlink/mavlink_main.cpp
Outdated
if ((int)vehicle_cmd.param2) | ||
PX4_INFO("Enable transmitting with mavlink instance of type %s on device %s", mavlink_mode_str(_mode), _device_name); | ||
else | ||
PX4_INFO("Disable transmitting with mavlink instance of type %s on device %s", mavlink_mode_str(_mode), _device_name); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
braces
I'm wondering if we need to generalize the link loss handling for all link types, and possibly push more of it into the mavlink module. |
I tested the switching logic and testing the signal strength with the real hardware. I haven't sent any message over the link as I do not have a line rented yet. I will test transmitting data when the overall system is ready for it (Mavlink and QGC) |
71f290a
to
a15a1fa
Compare
a15a1fa
to
72b184e
Compare
@acfloria can you please rebase? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It looks good to me. I can test this when I have my line rental activated. This should be synced also with the update on the HIGH_LATENCY
Mavlink msg.
msg/vehicle_status.msg
Outdated
@@ -62,6 +62,7 @@ bool rc_signal_lost # true if RC reception lost | |||
uint8 rc_input_mode # set to 1 to disable the RC input, 2 to enable manual control to RC in mapping. | |||
|
|||
bool data_link_lost # datalink to GCS lost | |||
bool high_latency_data_link_active # all low latency datalinks to GCS lost |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
indentation
src/drivers/iridiumsbd/IridiumSBD.h
Outdated
@@ -85,54 +85,14 @@ const char *satcom_state_string[4] = {"STANDBY", "SIGNAL CHECK", "SBD SESSION", | |||
|
|||
extern "C" __EXPORT int iridiumsbd_main(int argc, char *argv[]); | |||
|
|||
#define SATCOM_TX_BUF_LEN 50 // TX buffer size - maximum for a SBD MO message is 340, but billed per 50 | |||
#define SATCOM_RX_MSG_BUF_LEN 300 // RX buffer size for MT messages | |||
#define SATCOM_TX_BUF_LEN 340 // TX buffer size - maximum for a SBD MO message is 340, but billed per 50 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
indentation
* @max 300 | ||
* @group Iridium SBD | ||
*/ | ||
PARAM_DEFINE_INT32(ISBD_SBD_TIMEOUT, 60); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this the time for "datalink" timeout on the high latency link?
* @min 60 | ||
* @max 3600 | ||
*/ | ||
PARAM_DEFINE_INT32(COM_HLDL_LOSS_T, 120); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I got my answer here.
src/modules/mavlink/mavlink_main.h
Outdated
@@ -476,6 +476,7 @@ class Mavlink | |||
|
|||
private: | |||
int _instance_id; | |||
bool _transmitting_enabled; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
indentation
@acfloria what's the deal with QRT that lead you to add the conditions? |
I will also do some tests and rent a line once the HIGH_LATENCY message is merged on mavlink.
It is necessary, as for one build version mavlink is not used. I do not recall by heart which version. |
@acfloria were you able to test this in the mean time with the new msg? |
72b184e
to
aabfbd7
Compare
@TSC21 I just added the support for it and tested it in SITL. |
e0745ed
to
d8b7427
Compare
I should be able to test this on my end with real HW this week. |
a2c321b
to
f7f4276
Compare
f7f4276
to
383e924
Compare
06697af
to
7d8e591
Compare
I tested this on a Pixhawk 3 Pro with a RockBlock Mk2 on a bench. The telemetry switching works as outlined in the switching logic. |
@dagar this PR has been extensively tested with real hardware. Can you review the code? |
086b691
to
c1cbaee
Compare
…time sending nothing
- Check if changing to a non standby state if the current state is the standy state and no change is already scheduled. - Add prefix _ to all class variables
Due to the old heartbeat of the high latency telemetry when activating it after flying sufficiently long in normal telemetry it is first detected as lost until the first message is sent. By updating the heartbeat to the current time on switching this issue is avoided. Also includes a small style fix for the HIGH_LATENCY2 stream
02b248d
to
d4fd44d
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've had a look over the first part of the PR and remarked what caught my eye. Generally looks good.
I'll review the mavlink changes in a second pass.
if (*buffer == MAVLINK_PACKAGE_START) { | ||
if (SATCOM_TX_BUF_LEN - _tx_buf_write_idx - (*(buffer + 1) + 8) < 0) { | ||
_tx_buf_write_idx = 0; | ||
mavlink_log_critical(&_mavlink_log_pub, "Deleting full TX buffer before writing new message"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this intended to be user-facing or just to debug?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is just to debug as in high latency telemetry the status texts are not transmitted.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, but it should not go into a release, as a user has no idea what this means.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed. I am filling the tx_buf field of the telemetry_status correctly so it can be observed by that variable if a reset happens. However, I think for debugging it might be useful to have a status message of the driver where the status can be logged in more details. I will add that as a future PR after this one here is merged.
|
||
// check if there is enough space for the incoming mavlink message | ||
if (buflen == 6) { | ||
if (*buffer == MAVLINK_PACKAGE_START) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is fragile: it assumes mavlink 1 and a certain write pattern from mavlink (the buflen == 6
check)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree, that is why I added the check just after that one to catch anything which does not fit into that scheme.
However, in high latency mavlink 1 should be used because it assures that the HIGH_LATENCY2 message is 50 bytes. This is desired as for example rockblock bills in 50 byte increments.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd still rather have it done properly. You can look at how protocol_splitter does it for example: https://github.com/PX4/Firmware/blob/master/src/drivers/protocol_splitter/protocol_splitter.cpp#L358.
At the very least it should be documented that this is a hacky solution and nothing important must depend on this.
Does a user know that he/she should be using mavkink 1 with this device? Is it enforced somewhere?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I adopted it to the way the protocol_splitter is doing it.
Mavlink 1 is not enforced but encouraged as the design of the HIGH_LATENCY2 stream was to create a 50 byte status message. Using Mavlink 2 this goal cannot be met due to the larger header. I added a note in the header file. Once the full high latency telemetry together with QGC is working there should be a documentation about it for example in the dev guide where this information should also be written.
src/modules/commander/Commander.hpp
Outdated
int32_t datalink_loss_timeout, int32_t datalink_regain_timeout, bool *status_changed); | ||
|
||
// telemetry variables | ||
int _telemetry_subs[ORB_MULTI_MAX_INSTANCES] = {}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can you create a separate struct for these? Then you need only one array and can use a constructor or member initializer to initialize the fields
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point. I added that struct.
src/modules/mavlink/mavlink_main.cpp
Outdated
@@ -988,6 +990,7 @@ Mavlink::send_bytes(const uint8_t *buf, unsigned packet_len) | |||
return; | |||
} | |||
|
|||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can you please avoid adding unnecessary newlines?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure, removed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I realize I have plenty of remarks, but the overall structure looks good.
src/modules/mavlink/mavlink_main.cpp
Outdated
|
||
if (cmd_sub->update(&cmd_time, &vehicle_cmd)) { | ||
if ((vehicle_cmd.command == vehicle_command_s::VEHICLE_CMD_CONTROL_HIGH_LATENCY) && (_mode == MAVLINK_MODE_IRIDIUM)) { | ||
if ((vehicle_cmd.param1 > 0.5f)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
unnecessary brackets (more below)
src/modules/mavlink/mavlink_main.cpp
Outdated
_transmitting_enabled = true; | ||
_transmitting_enabled_commanded = true; | ||
|
||
} else if ((vehicle_cmd.param1 <= 0.5f)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just } else {
is enough
src/modules/mavlink/mavlink_main.cpp
Outdated
struct vehicle_command_s vehicle_cmd; | ||
|
||
if (cmd_sub->update(&cmd_time, &vehicle_cmd)) { | ||
if ((vehicle_cmd.command == vehicle_command_s::VEHICLE_CMD_CONTROL_HIGH_LATENCY) && (_mode == MAVLINK_MODE_IRIDIUM)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if this comes from external, someone needs to send an ack. It can be done from commander.
@@ -2201,7 +2236,11 @@ Mavlink::task_main(int argc, char *argv[]) | |||
msg.target_component = command_ack.target_component; | |||
current_command_ack = command_ack.command; | |||
|
|||
// TODO: always transmit the acknowledge once it is only sent over the instance the command is received |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you fix this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have an idea how to fix it, but as it potentially can break things and is not an trivial change I would prefer to do it in a separate PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok that's fine.
if (*buffer == MAVLINK_PACKAGE_START) { | ||
if (SATCOM_TX_BUF_LEN - _tx_buf_write_idx - (*(buffer + 1) + 8) < 0) { | ||
_tx_buf_write_idx = 0; | ||
mavlink_log_critical(&_mavlink_log_pub, "Deleting full TX buffer before writing new message"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, but it should not go into a release, as a user has no idea what this means.
|
||
update_tecs_status(_update_rate_filtered); | ||
|
||
update_battery_status(_update_rate_filtered); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since you're passing a class member _update_rate_filtered
, you can avoid adding an argument and use _update_rate_filtered
directly in update_battery_status
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
src/modules/mavlink/mavlink_stream.h
Outdated
@@ -103,6 +103,11 @@ class MavlinkStream | |||
virtual bool send(const hrt_abstime t) = 0; | |||
#endif | |||
|
|||
/** | |||
* Function to collect/update data for the streams when update() is called. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you document this a bit more? Like saying that it's called at a high rate, independent from the configured stream rate.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
@@ -3929,22 +3941,22 @@ class MavlinkStreamMountOrientation : public MavlinkStream | |||
} | |||
}; | |||
|
|||
class MavlinkStreamHighLatency : public MavlinkStream | |||
class MavlinkStreamHighLatency2 : public MavlinkStream |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
since this is so large, it's almost worth splitting it into a separate file.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure, I moved it to a separate file
if (sent) { | ||
_last_sent = (interval > 0) ? _last_sent + interval : t; | ||
_last_sent = ((interval > 0) && ((int64_t)(1.5 * interval) > dt)) ? _last_sent + interval : t; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you use 1.5f
to avoid converting to double?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changed.
// If the interval is non-zero and dt is smaller than 1.5 times the interval | ||
// do not use the actual time but increment at a fixed rate, so that processing delays do not | ||
// distort the average rate. The check of the maximum interval is done to ensure that after a long time | ||
// not sending anything multiple messages in a short time are sent. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The check of the maximum interval is done to ensure that after a long time not sending anything multiple messages in a short time are sent.
Should this not be more like: The check of the maximum interval is done to ensure that after a long time not sending anything, sending multiple messages in a short time is avoided.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure, you are right. Changed it to your version
@bkueng I implemented the changes you requested. Can you review the fixes again? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the update.
Yes, but this is also currently the default behavior. Any acknowledge will be sent over every instance.
I meant that multiple uorb acks are published. But since you moved this to commander, it's correct now.
Unfortunately not, as this function is used with fields of a packed struct and therefore won't compile using a reference.
Uh, but this is not good, and the compiler complains for good reasons. Passing the member of a packed struct as a pointer can lead to memory access alignment problems (and crashes).
char _test_command[32]; | ||
hrt_abstime _test_timer = 0; | ||
|
||
uint8_t _rx_command_buf[SATCOM_RX_COMMAND_BUF_LEN] = {0}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I suggest you change it to = {}
. {0}
is confusing, as for example using {1}
would lead to only the first element being 1 and all others 0.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changed
#include "mavlink_simple_analyzer.h" | ||
#include "mavlink_stream.h" | ||
|
||
#ifndef MAVLINK_HIGH_LATENCY2_H_ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I suggest you use #pragma once
instead
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changed
@@ -2201,7 +2236,11 @@ Mavlink::task_main(int argc, char *argv[]) | |||
msg.target_component = command_ack.target_component; | |||
current_command_ack = command_ack.command; | |||
|
|||
// TODO: always transmit the acknowledge once it is only sent over the instance the command is received |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok that's fine.
…e function - Addional small cleanup of the iridium driver and the include guards of mavlink module header files
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good to go now!
@dagar circleci seems to be broken |
Improvements of the Iridiumsbd Driver and add a fallback to the high latency telemetry.
The changes in more details:
VERBOSE_INFO
macrovehicle_command
uorb message.Switching Logic: