-
Notifications
You must be signed in to change notification settings - Fork 15
Async/await and events executor in animation server #704
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
base: main
Are you sure you want to change the base?
Changes from all commits
dbc229a
da1de8c
5613b55
eedd8a5
55e591d
334826d
66b9939
b8cbb34
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,6 @@ | ||
import os | ||
from typing import Any | ||
from threading import Thread | ||
from typing import Any, Callable | ||
|
||
import rclpy | ||
import yaml | ||
|
@@ -11,6 +12,7 @@ | |
from rcl_interfaces.srv import GetParameters, SetParameters | ||
from rclpy.node import Node | ||
from rclpy.parameter import PARAMETER_SEPARATOR_STRING, Parameter, parameter_value_to_python | ||
from rclpy.task import Future | ||
|
||
# Create a new @nobeartype decorator disabling type-checking. | ||
nobeartype = beartype(conf=BeartypeConf(strategy=BeartypeStrategy.O0)) | ||
|
@@ -194,3 +196,43 @@ def parse_parameter_dict(*, namespace: str, parameter_dict: dict) -> list[Parame | |
parameter = Parameter(name=full_param_name, value=param_value) | ||
parameters.append(parameter.to_parameter_msg()) | ||
return parameters | ||
|
||
|
||
async def async_wait_for(node: Node, rel_time: float): | ||
""" | ||
ROS 2 does not provide an async sleep function, so we implement our own using a timer. | ||
This function will wait for the specified relative time in seconds. | ||
|
||
:param node: The ROS2 node to create the timer on. | ||
:param rel_time: The relative time in seconds to wait. | ||
:return: None | ||
""" | ||
future = Future() | ||
rel_time = max(rel_time, 0.0) | ||
|
||
def done_waiting(): | ||
future.set_result(None) | ||
|
||
timer = node.create_timer(rel_time, done_waiting, clock=node.get_clock()) | ||
await future | ||
timer.cancel() | ||
node.destroy_timer(timer) | ||
|
||
|
||
async def async_run_thread(func: Callable[[], Any]) -> None: | ||
""" | ||
Allows the usage of blocking functions in an async context. | ||
|
||
Spawns a thread to run the function and returns a Future that will be set when the function is done. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This does not seem to return anything, so the comment is wrong. Otherwise, the type annotation is wrong and I have not yet understood async-await in Python... There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah it doesn't return. But we should return, I will fix it. |
||
""" | ||
future = Future() | ||
|
||
def thread_func(): | ||
try: | ||
future.set_result(func()) | ||
except Exception as e: | ||
future.set_exception(e) | ||
|
||
thread = Thread(target=thread_func) | ||
thread.start() | ||
await future |
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 signature
async_wait_for(mynode, 10)
can easily be misunderstood as waiting formynode
to become available, or similar. Therefore, I suggest the following solutions:async_wait
async_wait_for_seconds
async_wait_for(rel_time: float, node: Node)
async_wait_for(seconds: float, node: Node)
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.
Maybe sleep_until?
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 method
sleep_until
sounds like it expects a end-time, not a duration...What do you think about using
Duration
instead ofseconds: float
? This might be cleaner and more ROSy, but is not really necessary and a bit overhead.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 had it as a duration at one point, but I didn't like the verbosity. But I agree that it would be more like the rclpy API.
What do you think of
sleep_for
?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.
YES! Does that need
async
as well in the name or is that clear through other 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.
I would add async, but it should show as a coroutine in the signature as well