Unable to call service using asynchronous service client Rosject task 2.2

I am working on the Rosject and am stuck on task 2.2, which asks us to call the WallFinder service from the wall_follower script using an asynchronous service client. I have used multi-threading and a re-entrant callback group, but my code is not working. Everything builds correctly and the package launches, but the script jusr prints “service not available” into the shell.
My code is below:

import rclpy

import the ROS2 python libraries

from rclpy.node import Node

import the Twist module from geometry_msgs interface

from geometry_msgs.msg import Twist

import the LaserScan module from sensor_msgs interface

from sensor_msgs.msg import LaserScan
from wall_interfaces_custom.srv import FindWall
from rclpy.qos import ReliabilityPolicy, QoSProfile
from rclpy.callback_groups import ReentrantCallbackGroup
from rclpy.executors import MultiThreadedExecutor
import time

class Wall_Following_Node(Node):

def __init__(self):
    # Here you have the class constructor
    # call the class constructor
    super().__init__('wall_following')

    self.group1 = ReentrantCallbackGroup()
    self.group2 = ReentrantCallbackGroup()
    self.group3 = ReentrantCallbackGroup()

    # create the Service Client object
    # defines the name and type of the Service Server you will work with.
    self.find_wall_client = self.create_client(FindWall, 'find_wall',callback_group=self.group1)
    # checks once per second if a Service matching the type and name of the Client is available.
    while not self.find_wall_client.wait_for_service(timeout_sec=1.0):
        # if it is not available, a message is displayed
        self.get_logger().info('service not available, waiting again...')

    self.req = FindWall.Request()
    self.future = FindWall.Response()

    # create the publisher object
    self.publisher_ = self.create_publisher(Twist, 'cmd_vel', 10)
    print(1)
    # create the subscriber object
    self.subscriber = self.create_subscription(LaserScan, '/scan', self.laser_callback, QoSProfile(depth=10, reliability=ReliabilityPolicy.RELIABLE), callback_group=self.group2)
    print(2)
    #self.subscriber = self.create_subscription(LaserScan, '/scan', self.laser_callback, 10)

    # define the timer period for 0.5 seconds
    self.timer_period = 0.5
    # define the variable to save the received info
    self.laser_right = 0
    # define the variable to save the received info
    self.laser_forward = 0
    # create a Twist message
    self.cmd = Twist()
    print(3)
    self.timer = self.create_timer(self.timer_period, self.motion,callback_group=self.group3)
    print(4)
    # create Boolean for synchronous request
    self.request_sent = False

def send_request(self):
    # display message 
    self.get_logger().info('Sending request...')
    # send the request
    self.future = self.client.call_sync(self.req)
    return self.client.call_sync(self.req)

def laser_callback(self,msg):
    # Save the frontal laser scan info at 0°
    self.laser_forward = msg.ranges[359] 
    self.laser_right = msg.ranges[179] 
    
    
def motion(self):

    if self.request_sent is False:
        self.request_sent = True
        self.send_request()

    if self.future.result() is False:
        self.get_logger().info('Service response not received yet')
        time.sleep(1)

    else:

        print(5)
        # Test movement + connection
        """self.cmd.linear.x = 0.1
        self.cmd.angular.z = 0.5
        self.publisher_.publish(self.cmd)"""
        print(6)

        # print the data
        self.get_logger().info('I receive laser right: "%s"' % str(self.laser_right))
        self.get_logger().info('I receive laser forward: "%s"' % str(self.laser_forward))
        # Logic of move
        linear_velocity = 0.1
        angular_velocity_high = 0.5
        angular_velocity_low = 0.1
        if self.laser_forward < 0.5:
            self.cmd.linear.x = linear_velocity
            self.cmd.angular.z = angular_velocity_high
        else:
            if self.laser_right > 0.3:
                self.cmd.linear.x = linear_velocity
                self.cmd.angular.z = angular_velocity_low
                self.get_logger().info("first")
            elif self.laser_right > 0.2 and self.laser_right < 0.3:
                self.cmd.linear.x = linear_velocity
                self.cmd.angular.z = 0.0
                self.get_logger().info("second")         
            else:
                self.cmd.linear.x = linear_velocity
                self.cmd.angular.z = -1*angular_velocity_low
                self.get_logger().info("third")
            
        # Publishing the cmd_vel values to a Topic
        self.publisher_.publish(self.cmd)

def main(args=None):
# initialize the ROS communication
rclpy.init(args=args)

try: 
    # declare the node constructor
    wall_following = Wall_Following_Node()    
    executor = MultiThreadedExecutor(num_threads=4)
    executor.add_node(wall_following)   

    try: 
        executor.spin()
        response = wall_following.send_request()
    finally: 
        executor.shutdown()
        wall_following.destroy_node()
finally:
    rclpy.shutdown()
# pause the program execution, waits for a request to kill the node (ctrl+c)
#rclpy.spin(wall_following)
# Explicity destroy the node
#wall_following.destroy_node()
# shutdown the ROS communication
#rclpy.shutdown()

if name == ‘main’:
main()

Hello @scj ,

If you keep getting this “service not available” message, it probably means that your code is getting stuck here:

while not self.find_wall_client.wait_for_service(timeout_sec=1.0):
        # if it is not available, a message is displayed
        self.get_logger().info('service not available, waiting again...')

This means that it’s not finding the service /find_wall. So, if you run in a different shell the command:
ros2 service list
Can you see the /find_wall service in the list?

The /find_wall service is listed when I run “ros2 service list” in another shell. Any other suggestions why my code might not be working?

ros2_service_list

I asked a colleague who advised me that the problem was that I had not added the service to my launch file. I have now updated my launch file (see below) and the code works. Thanks for your help.

ros2_launch_file

1 Like

This topic was automatically closed 5 days after the last reply. New replies are no longer allowed.