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

uORB::Publication: automatically obtain ORB_QUEUE_LENGTH from the structure #16012

Merged
merged 2 commits into from
Oct 26, 2020

Conversation

shawnfeng0
Copy link
Contributor

@shawnfeng0 shawnfeng0 commented Oct 21, 2020

Use the C++ template technique to get the ORB_QUEUE_LENGTH in the structure, and return the default value if it does not contain ORB_QUEUE_LENGTH.

In this way, there is no need to remember whether a topic has a queue, uORB::Publication will automatically configure the queue size according to the topic in the *.msg file.

@dagar
Copy link
Member

dagar commented Oct 21, 2020

There's a bit of a hack on destruction to be aware of.
https://github.com/PX4/Firmware/blob/b14d0e43265b25a49905c9d543756ed442cbbb2c/src/modules/uORB/Publication.hpp#L67-L71

This is because of standalone uses publishing a vehicle_command by stack allocating uORB::PublicationQueued and we need the vehicle_command to still exist. Maybe we need a slightly different approach for this use case?

@shawnfeng0
Copy link
Contributor Author

shawnfeng0 commented Oct 22, 2020

It may be feasible to put this destructor in Publication and PublicationMulti processing, how about it?
PublicationBase does not perform any functions, but only provides public interfaces and data.

But I think this use case affects the consistency of architecture performance, maybe we should delete this use case later.

I think no matter whether the broadcaster exists or not, the subscribers should be able to continue to get the unobtained data and make the system behave consistently.

@shawnfeng0 shawnfeng0 changed the title uORB::Publication: automatically obtain queue_size from the structure uORB::Publication: automatically obtain ORB_QUEUE_LENGTH from the structure Oct 22, 2020
@dagar
Copy link
Member

dagar commented Oct 22, 2020

I think no matter whether the broadcaster exists or not, the subscribers should be able to continue to get the unobtained data and make the system behave consistently.

I think what could work is leaving it be (skipping unadvertise) if any data was actually published. If the uORB::DeviceNode never published anything and doesn't have any subscribers then it should be deleted on unadvertise.

Later the entire uORB shutdown/cleanup story needs to be reviewed as it's largely been ignored due to most people turning off their drones by pulling power abruptly.

@shawnfeng0
Copy link
Contributor Author

shawnfeng0 commented Oct 22, 2020

Of course, the data should be kept in DeviceNode.

My thoughts are a little different:

Current design:
If the publisher executes unadvertise(), the subscriber will not get the data.
Publishers with queues are not allowed to unadvertise() because the data in the queue is still useful.

Can be modified to:
The publisher executes unadvertise(), which does not affect the subscribers who have subscribed to continue to obtain unobtained data, whether there is only one or there is a queue of data. (Consistent behavior)

This will be another pull request.

@shawnfeng0
Copy link
Contributor Author

shawnfeng0 commented Oct 23, 2020

By the way, in the current design, if a DeviceNode is published by multiple publishers, as long as one of the publishers is destroyed, the DeviceNode will be marked as unadvertised. (Need to record the number of publishers.)

@shawnfeng0 shawnfeng0 force-pushed the uorb_auto_get_queuesize branch from 53d4817 to eea98d4 Compare October 26, 2020 04:44
@shawnfeng0
Copy link
Contributor Author

Can this modification be merged? The unadvertise related issues mentioned above will be a new pull request.

src/modules/uORB/Publication.hpp Outdated Show resolved Hide resolved
src/modules/uORB/Publication.hpp Outdated Show resolved Hide resolved
@shawnfeng0 shawnfeng0 force-pushed the uorb_auto_get_queuesize branch from eea98d4 to c08dc56 Compare October 26, 2020 09:31
Copy link
Member

@bkueng bkueng left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks

@lukegluke
Copy link
Contributor

lukegluke commented Nov 12, 2020

This commits leads to specific factor.

[I'm working with custom board and project based on PX4]
I had LedsSimple driver that works in the same way as rgbled and calls _led_controller.update in Run().

in rcS right after this drivers starts I call led_control cmd three times in a row:

led_control off -p 0                 #turn off all leds
led_control on -l 0 -p 0             #turn on one led with 0 priority
led_control blink -n 3 -s fast -p 2  #blink all leds three times

before (when PublicationQueued was used) after blinking there is on led stay lighting as expected, now it doesn't.
Debugging showed that led_control cmd has time to publish all three orb messages in queue, before driver reaches _led_controller.update call and led controller subscribes to topic - so generation is already 3 for this moment and it reads only last message - blinking.

The workaround that works in my case: call first led_control cmd before starting LedsSimple driver. So than when LedController is created _led_control_sub will be initially subscribed (in its constructor) to already advertised topic.

But as I see the PX4 boards probably don't have such code that would call led_control/tune_control or other related commands in row on boot, right? Anyway just a warning.

@shawnfeng0
Copy link
Contributor Author

shawnfeng0 commented Nov 13, 2020

@lukegluke
That is due to this #15709
After subscribing, current subscribers can only get one old data of before subscription.

unsigned uORB::DeviceNode::get_initial_generation()
{
ATOMIC_ENTER;
// If there any previous publications allow the subscriber to read them
unsigned generation = _generation.load() - (_data_valid ? 1 : 0);
ATOMIC_LEAVE;
return generation;
}

I think the new data should be used when the system starts running, and the queue buffer can be used later.

@lukegluke
Copy link
Contributor

Yes, I saw this. And it is also due to Subscription will not subscribe until topic will be advertise:

if (!device_master->deviceNodeExists(_orb_id, _instance)) {

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants