-
Notifications
You must be signed in to change notification settings - Fork 227
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
Add support for spin_until_complete #1268
base: rolling
Are you sure you want to change the base?
Add support for spin_until_complete #1268
Conversation
fa1df4d
to
1127177
Compare
1127177
to
35450f4
Compare
35450f4
to
9b94372
Compare
Co-authored-by: Hubert Liberacki <[email protected]> Signed-off-by: Hubert Liberacki <[email protected]> Signed-off-by: Christophe Bedard <[email protected]>
9b94372
to
d0e8130
Compare
I've updated this PR to reflect the decision in ros2/rclcpp#2475 (comment) to not deprecate |
@fujitatomoya could you review this? This reflects the new changes to ros2/rclcpp#2475, which should be final-ish now. |
Well this may be going in yet another direction (ros2/rclcpp#2475 (comment)), so let's wait a bit. |
All good now, this is ready for review. |
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.
Very quick look from me and it looks pretty good, but I do think the function ought to return something like it does in c++. However, another rclpy maintainer can override me if they think this could be added later or that it isn't necessary.
Also, I feel that the tests are kind of shallow and wouldn't catch some of the ways the function could fail.
Execute work until the condition is complete. | ||
|
||
Callbacks and other work will be executed by the provided executor until ``condition()`` | ||
returns ``True`` or the context associated with the executor is shutdown. |
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.
nitpick: no mention of the timeout here
def spin_until_complete( | ||
node: 'Node', | ||
condition: Callable[[], bool], | ||
executor: Optional['Executor'] = None, | ||
timeout_sec: Optional[float] = None, | ||
) -> None: | ||
""" | ||
Execute work until the condition is complete. | ||
|
||
Callbacks and other work will be executed by the provided executor until ``condition()`` | ||
returns ``True`` or the context associated with the executor is shutdown. | ||
|
||
:param node: A node to add to the executor to check for work. | ||
:param condition: The callable condition to wait on. If this condition is not related to what | ||
the executor is waiting on and the timeout is infinite, this could block forever. | ||
:param executor: The executor to use, or the global executor if ``None``. | ||
:param timeout_sec: Seconds to wait. Block until the condition is complete | ||
if ``None`` or negative. Don't wait if 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.
To go along with the discussion in the rclcpp version of this (ros2/rclcpp#2475 (comment)), I think we need to do a much better job of explaining that the executor must be woken up when the condition changes and condition's value must be changed before the signal to wake up is sent, otherwise you might deadlock here (if not using a timeout).
I think we could make an issue to do this as a follow up, as the docs can be improved post API freeze.
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.
Sounds good, will do it as a follow-up issue/PR.
self.assertFalse(condition()) | ||
t = threading.Thread(target=lambda: set_condition()) | ||
t.start() | ||
executor.spin_until_complete(condition, timeout_sec=1.0) | ||
self.assertTrue(condition()) |
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 a fairly weak test in my opinion, as you could comment out line 444 and have it pass most of the time. Also, if spin_until_complete()
was broken (and did not return before the timeout if the condition was true) this would still pass.
def spin_until_complete( | ||
node: 'Node', | ||
condition: Callable[[], bool], | ||
executor: Optional['Executor'] = None, | ||
timeout_sec: Optional[float] = None, | ||
) -> None: |
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.
Should this not return something to indicate if the function returned due to the condition being complete or due to a timeout 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.
Then that would mean that spin_until_future_complete
should also return something similar?
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 so we agree before I do the changes: do we just want a bool
(True
means it returned due to the condition being complete, or False
otherwise), or do we want something like rclcpp::SpinUntilCompleteReturnCode
to indicate SUCCESS
or INTERRUPTED
or TIMEOUT
?
Part of ros2/rclcpp#2475
Replaces #919
Similar to the
rclcpp
changes, this addsspin_until_complete(condition, timeout)
.This also adds
spin_for
.