[First Release] Asyncio For Robotics: Asyncio interface for ROS 2

Hello fellow ROS 2 users,

I wanted to use asyncio with ROS 2 for a while, but didn’t find anything good enough. So I made a library: asyncio_for_robotics: https://github.com/2lian/asyncio-for-robotics

I am looking for feedback from the community, especially as this is my first release :sweat_drops:. What would you like to see? What is missing? What do you find confusing? What should I put forward?

VVV About the project VVV

Why asyncio?

  • Asyncio (native python) syntax is easier, with extensive support and documentation.
  • My lab sees many short term students, enable to grasp the Future/Callback and executor of ROS 2.
    • I am very used to it, but what is it the point if the people I code with never understand it?
  • We work on multi-robots coordination and synchronization.
    • The ROS 2 syntax becomes bloated and unreadable fast.
    • I for example need to wait for a set of robots (or motors) to reach their target, adding a timeout on top of that.
  • Asyncio does not have dependencies, is usable with other communication systems. So I can for example, ask a team to process images using RTSP transport (no ROS code), while I work with ROS transport, and we can merge our work.

Other solutions

I’ve seen several discussions, and people asking for asyncio+ROS 2. Many good solution have been proposed! However, I feel none was polished and reliable enough, usually they increase the barrier of entry instead of lowering it:

How asyncio_for_robotics works? What’s different?

I spin the ROS node in a background thread (similarly to rclpy_async). The user can directly provide a – possibly custom – node to spin in the background, and the user can still interact with the node object – it is just a standard ros node.

This background node sends data onto the main asyncio thread. I provide the user with only a subscription object that exposes several ways to wait for data: wait for data, wait for new data, wait for next data, async for loop to process all data. This object exposes the data stream of ROS objects: Timer, Subscriber, Service Server (Action Server is not implemented yet). On the other hand, Publisher doesn’t need to be implemented, because the user can directly use the node to create one. Service Client has a very small implementation returning an asyncio future of the call.

Finally, it is named asyncio_for_robotics because it can be used with other transport protocol (like zenoh), if you make an interface for it – there’s a quick tutorial on how to do that.

3 Likes

Howdy @2lian! Looks like an interesting development. Would you care to join in our client library working group, because this has been a very hot topic there over the last several meetings. @nadavelkabets has been working on an asyncio executor that should land in the upstream rclpy in time for Lyrical. Would be great to combine efforts there.

Yes I would gladly join!

Actually I have used @nadavelkabets new executor. I installed it from his PR branch, had a little fun with it, interfaced it with my asyncio_for_robotics and ran a (very very) basic benchmark. It seems to improve performances!

Moreover – maybe I did something wrong but – asyncio_for_robotics + AsyncioExecutor scored better on my benchmark than just the AsyncioExecutor. That was very strange.