ROS Resources: Documentation | Support | Discussion Forum | Index | Service Status | ros @ Robotics Stack Exchange
Ask Your Question
0

How to spin ROS2 publisher node and non-ROS function asynchronously?

asked 2022-01-05 21:09:59 -0500

iHany gravatar image

Note: Dup of https://github.com/ros2/rclpy/issues/872.

Hi, I'd like to spin a publisher node with non-ros code (in this case, MAVSDK-Python) asynchronously.

So far, I cannot find a way to do so.

Is there any way to achieve it?

code:

import rclpy
from rclpy.node import Node

from std_msgs.msg import String

import asyncio
from mavsdk import System


async def run(node):
    drone = System()
    await drone.connect(system_address="serial:///dev/ttyACM0")
    asyncio.ensure_future(print_battery(drone, node))

async def print_battery(drone, node):
    async for battery in drone.telemetry.battery():
        battery_stat = battery.remaining_percent
        node.battery_percent = battery_stat  # update
        print(f"battery: {node.battery_percent}, i: {node.i}")

class MinimalPublisher(Node):
    def __init__(self):
        super().__init__('minimal_publisher')
        self.publisher_ = self.create_publisher(String, 'topic', 10)
        timer_period = 0.5  # seconds
        self.timer = self.create_timer(timer_period, self.timer_callback)
        self.i = 0
        self.battery_percent = None
    def timer_callback(self):
        msg = String()
        msg.data = 'Hello World: %d' % self.i
        self.publisher_.publish(msg)
        self.get_logger().info('Publishing: "%s"' % msg.data)
        self.i += 1

async def spin_once(minimal_publisher):
    rclpy.spin_once(minimal_publisher)


def main(args=None):
    rclpy.init(args=args)

    minimal_publisher = MinimalPublisher()

    # rclpy.spin_once(minimal_publisher)
    asyncio.ensure_future(spin_once(minimal_publisher))
    asyncio.ensure_future(run(minimal_publisher))

    asyncio.get_event_loop().run_forever()

    # Destroy the node explicitly
    # (optional - otherwise it will be done automatically
    # when the garbage collector destroys the node object)
    minimal_publisher.destroy_node()
    rclpy.shutdown()

if __name__ == '__main__':
    main()

output (what I expected: printing battery condition and Hello World with increasing iteration number):

➜  ~ python3 pub.py
[INFO] [1641399256.034609091] [minimal_publisher]: Publishing: "Hello World: 0"
battery: -0.009999999776482582, i: 1
battery: -0.009999999776482582, i: 1
battery: -0.009999999776482582, i: 1
battery: -0.009999999776482582, i: 1
edit retag flag offensive close merge delete

1 Answer

Sort by » oldest newest most voted
0

answered 2022-01-06 08:16:04 -0500

iHany gravatar image

updated 2022-01-10 08:10:11 -0500

I finally found a way to do it.

It might not be the best way as I'm a newbie to asynchronous programming.

To avoid duplication, I leave a link of a working example (a github comment in MAVSDK-Python) here.

EDIT: still, the asynchronous example in the shared link seems "block" other functions while spinning a node, which makes slow other functions. Is it possible to "spin asynchronously"? EDIT2: I found the solution; see https://github.com/mavlink/MAVSDK-Pyt....

edit flag offensive delete link more

Question Tools

2 followers

Stats

Asked: 2022-01-05 21:09:59 -0500

Seen: 1,562 times

Last updated: Jan 10 '22