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

New asyncio executor #1399

Draft
wants to merge 10 commits into
base: rolling
Choose a base branch
from

Conversation

nadavelkabets
Copy link
Contributor

@nadavelkabets nadavelkabets commented Jan 15, 2025

Motivation

While rclpy is task-based and built with asynchronous support, its custom implementation imposes significant limitations and lacks integration with Python's asyncio ecosystem. Integrating rclpy nodes with modern asyncio based Python libraries like FastAPI and pyserial-asyncio is difficult and often forces developers into complex multi-threaded solutions.

Inspired by @sloretz's PR #971, this PR introduces an asyncio-based executor that runs nodes entirely on the asyncio event loop, that has become the de facto standard for IO programming in the Python community.

Current Status

This is a POC implementation demonstrating the feasibility of an asyncio executor.
Known limitations include:

  • Basic implementation without comprehensive error handling
  • Not closing the wait_set thread upon KeyboardInterupt
  • No test coverage
  • Integration challenges between ROS futures and asyncio (for example with client.call_async)

Key Architectural Decisions

Before proceeding with a complete implementation, input on several architectural choices is needed:

  1. Executor Compatibility:
    • Should we maintain SingleThreadedExecutor and MultiThreadedExecutor? Both are achievable in the asyncio executor by utilizing asyncio.run_in_executor.
    • If kept, do we modify their behavior to ease the integration of the asyncio executor? The current implementation only extracted code to functions, keeping the original behavior. This led to the partial duplication of _wait_for_ready_callbacks.
  2. Compatibility of Future objects: do we move entirely to the asyncio future, improve the rclpy Future to support asyncio (yield self), or replicate the asyncio approach of executor.create_future()?
  3. Do we keep spin_once functionality in an asyncio context? If we do, how do we implement it?

I believe that this PR has the potential to be a big game changer for rclpy, enabling many new applications and improving the performance of rclpy nodes.
Looking forward to your feedback.

@ryleu
Copy link

ryleu commented Jan 21, 2025

I would love to see this make its way into main. My main frustration with rclpy is that it seems to ignore the "Pythonic" way of doing things in favor of its own way. Asyncio integration would make ROS2 much more pleasant to work with in Python.

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

Successfully merging this pull request may close these issues.

2 participants