Client call to service from another ROS2 package hangs

asked 2022-06-15 12:27:47 -0500

brieb gravatar image

I am trying to write a client for a service defined in a separate ROS2 package, but it is hanging waiting for the service to become available.

The other package is a servo package for an AWS DeepRacer car, found here. In my workspace, I git clone this package and build it, then it works just fine. I run this package in one terminal, and then I can run another terminal and call one of the package's services directly:

ros2 service call /servo_pkg/get_led_state deepracer_interfaces_pkg/srv/GetLedCtrlSrv

This call to the service returns as expected.

So now I want to create my own package called gg_led_pkg with a single client to call this get_led_state service based on a timer every 5 seconds. I am using a ReentrantCallbackGroup for the client and the timer, with a MultiThreadedExecutor to spin the node. I set up my setup.py and my package.xml files, dependencies are fine, and everything builds. The client executable runs, but it hangs when trying to call the service.

What am I doing wrong? Is it not possible to call a service from a client defined in a different package but in the same workspace?

Here is the output from my client call

~/environment/deepracer_ws $ ros2 run gg_led_pkg client

[INFO] [1655305042.750526039] [led_minimal_client_async]: Beginning demo, end with CTRL-C

[INFO] [1655305047.741162292] [led_minimal_client_async]: Client sending request

[INFO][1655305052.741094414] [led_minimal_client_async]: Client sending request

And so on and so on...

My client code:

import sys 
from time import sleep 
from threading import Thread

#import the two service interfaces we need to use 
from deepracer_interfaces_pkg.srv import SetLedCtrlSrv, GetLedCtrlSrv

# this imports the ROS2 Client Library for Python 
import rclpy
# the main object for ROS nodes 
from rclpy.node import Node
# import a multi-threaded executor to be used when spinning the node.  
# This allows "parallel" execution of threads
# but the python GIL is still present (so not truly parallel) 
from rclpy.executors import MultiThreadedExecutor
# the re-entrant callback group allows the executor to schedule and execute the group's callbacks
# in any way it sees fit.  This is not necessarily thread safe 
from rclpy.callback_groups import ReentrantCallbackGroup


class LedMinimalClientAsync(Node):

    def __init__(self, client_cb_group, timer_cb_group, manual_call):
        # first initialize 
        super().__init__('led_minimal_client_async')

        self.client_cb_group = client_cb_group
        self.timer_cb_group = timer_cb_group
        self.manual_call = manual_call

        # create a CLI interface for this getter method
        # we set the client to use the GetLedCtrlSrv defined in the deepracer interfaces package
        # we define the name as get_led_ctrl_srv
        # we define a callback group here (going to make it reentrant)
        self.get_led_status = self.create_client(GetLedCtrlSrv, 
                                                'get_led_ctrl_srv', 
                                                callback_group=self.client_cb_group)

        # # wait for the client to become available (this is where it is locking)
        # while not self.get_led_status.wait_for_service(timeout_sec=1.0):
        #     self.get_logger().info('service not available, waiting again...')

        # make a simple request payload, which is empty
        self.req = GetLedCtrlSrv.Request()   


    def start(self):
        '''a method to call the server request outside the __init__()'''
        # if we are not making manual calls to the server
        # then this is false and will use the timer to make ...
(more)
edit retag flag offensive close merge delete