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

[rclc] Executor: rcl_wait() returns immediately when there is new data but trigger condition is not satisfied #388

Open
vtran5 opened this issue Aug 7, 2023 · 1 comment
Assignees

Comments

@vtran5
Copy link

vtran5 commented Aug 7, 2023

Issue template

  • RTOS: Ubuntu
  • Installation type: rclc installed as ROS2 package
  • Version or commit hash: humble

Steps to reproduce the issue

Set executor trigger condition to be NOT rclc_executor_trigger_any. Call rclc_executor_spin() with non-zero timeout.

Expected behavior

The executor blocks until there is a handle that has new data. It then checks the trigger condition, if the condition is not satisfied, it will block again until there is a handle has another new data.

Actual behavior

Once there is new data and trigger condition is not satisfied, rcl_wait() returns immediately as the new data is not taken. This leads to the problem that the executor will consume resource until the trigger condition is satisfied.

Additional information

My proposed solution is to take new data before checking the trigger condition. If one callback has mutiple data coming in before the trigger condition, the new data can be overwritten or dropped depends on the callback's entity qos setting.

@JanStaschulat
Copy link
Contributor

JanStaschulat commented Aug 8, 2023

@vtran5. Yes, indeed.

Suppose the following setup:

  • at configuration:
    • rclc_executor with two subscriptions A and B
    • trigger condition waits only for subscription A: rclc_executor_trigger_one(A)
  • at runtime:
    • A is received with low frequency
    • B is received with high frequency

The trigger waits only for message A, but frequently receives message B. In this case, the rclc executor will be in a busy loop because rcl_wait() will return immediately every invocation (because of availability of B and not taking it).

Your idea would be solution. However, it would also change the expected semantics of the trigger condition. That is: if the trigger condition is satisfied, then take all new messages at that timepoint from the DDS queue. Taking the data in-between could also work, but as the QoS parameter are considered well at DDS level, one would have to implement all QoS settings again in the rclc executor (also the ones regarding timing, e.g. keep data only for x ms ...)

I have another idea: if a new message creates a busy loop, then take it out of the rcl_wait set and "save it for later". Then, if the trigger-condition is satisfied, then create one additional invocation of the rcl_wait with all messages. It is also a more complex solution, but it

  • avoids busy_loops of rcl_wait calls
  • does not buffer messages and would not shadow QoS settings in DDS
  • avoids a re-implementation of QoS settings in rclc layer

By the way, the same problem occurs in ROS 2 when using WaitSets. The example code wait_set_topics_with_different_rates.cpp, will create a busy loop if sub3 receives new data, but sub2 does not. So it would be good to come up with a well-designed general solution for this problem.

@JanStaschulat JanStaschulat self-assigned this Aug 8, 2023
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

No branches or pull requests

2 participants