Skip to content
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

uXRCE - Allow to set the uORB polling rate per subscription #23473

Open
wants to merge 5 commits into
base: main
Choose a base branch
from

Conversation

AlexisTM
Copy link
Contributor

@AlexisTM AlexisTM commented Jul 31, 2024

Solved Problem

Having a configurable polling rate can have 2 usages:

  • Increase the polling interval for rate limiting of uORB message
  • Decrease the polling interface for reducing the latency of critical topics

The main issue with latency is if we have a 100Hz topic with a 10ms interface, which means we will get a systematic delay between [0-10ms] which is different for each run.

This is especially important to have little/limited delays when using external control modes such as with Auterion/px4-ros2-interface-lib

Solution

  • Add an optional max_rate_hz parameter to the dds_topics.yaml file
  • Moved the optional default_max_rate_hz parameter to the dds_topics.yaml file or set it to 100
  • Use the new max_rate_hz parameter or the default rate

Changelog Entry

For release notes:

Feature/Add the max frequency per subscription for uXRCE
New parameter: `max_rate_hz` in `dds_topics.yaml` to set the uORB subscription maximal data frequency.
New parameter: `default_max_rate_hz` in `dds_topics.yaml` 
Higher frequency (1000Hz) on a lower frequency channel (100Hz) will reduce latencies. 
A max frequency of `0 Hz` means `unlimited`. 

Alternatives

We could make the default interval as a PX4 parameter, but that impacts every topic. Not all topics needs a low polling interval.

Closes: #21716
Closes: #21997

@dagar
Copy link
Member

dagar commented Jul 31, 2024

We really need to introduce some runtime configurability here, by default we probably shouldn't be sending things at high rates.

@dagar
Copy link
Member

dagar commented Aug 1, 2024

For the particular problem you want to solve would it work if we exposed an overall max rate as a PX4 parameter?
I would then default that parameter to something a bit more conservative like 100 Hz, but you could easily lift it as needed.

@AlexisTM
Copy link
Contributor Author

AlexisTM commented Aug 2, 2024

A PX4 Parameter would work too, but doesn't it make sense to have those (rates, topics, default rate) together?
I do not like that file is so deep though. As in, not allowing a custom file per board, especially for custom company products (like ModalAI/Voxl2 and others).

@AlexisTM
Copy link
Contributor Author

AlexisTM commented Aug 2, 2024

For the particular problem you want to solve would it work if we exposed an overall max rate as a PX4 parameter? I would then default that parameter to something a bit more conservative like 100 Hz, but you could easily lift it as needed.

I have just tried this, but I have the problem of having the parameter available when needed.

The yaml data is used to initialize the subscribers structs, at a time we do not have access to the parameters yet.

// Subscribers for messages to send
struct SendTopicsSubs {
SendSubscription send_subscriptions[@(len(publications))] = {
@[ for pub in publications]@
{ ORB_ID(@(pub['topic_simple'])),
uxr_object_id(0, UXR_INVALID_ID),
"@(pub['dds_type'])",
"@(pub['topic'])",
ucdr_topic_size_@(pub['simple_base_type'])(),
&ucdr_serialize_@(pub['simple_base_type']),
@(pub['max_rate_hz']),
},
@[ end for]@
};

Another way would be to initialize the struct in the init function systematically, and still have access to the python generator data. This loop would then be unrolled and the precedent snippet effectively within init();.

void SendTopicsSubs::init() {
for (unsigned idx = 0; idx < sizeof(send_subscriptions)/sizeof(send_subscriptions[0]); ++idx) {
fds[idx].fd = orb_subscribe(send_subscriptions[idx].orb_meta);
fds[idx].events = POLLIN;
orb_set_interval(fds[idx].fd, send_subscriptions[idx].max_rate_hz > 0 ? 1000 / send_subscriptions[idx].max_rate_hz : 10000);
}
}

A last method would be to use a magic number, such as 0 or negative values (aka all invalid values), which are known to be outside of the dataset as we filtered them in Python. Then, we would replace those with the default.

msg_map['publications'] = list(filter(lambda x: x['max_rate_hz'] > 0, msg_map['publications']))

@AlexisTM AlexisTM force-pushed the feature/polling_rate_per_sub branch from 149963d to 9b3d418 Compare August 5, 2024 06:47
@AlexisTM
Copy link
Contributor Author

AlexisTM commented Sep 2, 2024

@dagar could you take a look?

@AlexisTM
Copy link
Contributor Author

Rebased on main

Change max_rate_hz to a float.
Set 0Hz as a disabled topic.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants