What kind of message does your server node expect?
Seeing in the screenshots you provided you created a custom message: custom_interfaces/srv/Findwall
Maybe you also programmed to expect this message? If so then you should call it:
user:~$ ros2 service call /find_wall custom_interfaces/srv/FindWall ‘{}’
Hi. Thanks for your message. No I haven’t added a message like that. I just expect the robot to find the wall with this service call. The problem is that the service seems working when I list it on terminal. But when I call it with " ros2 service call /find_wall std_srvs/srv/Empty ‘{}’ ", it says “waiting for service to become available…” and nothing happens.
from custom_interfaces.srv import FindWall
from std_srvs.srv import Empty
from geometry_msgs.msg import Twist
from sensor_msgs.msg import LaserScan
from rclpy.qos import ReliabilityPolicy, QoSProfile
import rclpy
from rclpy.node import Node
import time
class Wall_finder(Node):
def __init__(self):
# Here you have the class constructor
# call the class constructor to initialize the node as service_moving
super().__init__('wall_finder')
# create the Service Server object
# defines the type, name, and callback function
self.srv = self.create_service(FindWall, 'find_wall', self.empty_callback)
# create the Publisher object
# in this case, the Publisher will publish on /cmd_vel topic with a queue size of 10 messages.
# use the Twist module
self.subscriber = self.create_subscription(LaserScan, '/scan', self.laser_callback, QoSProfile(depth=10, reliability=ReliabilityPolicy.RELIABLE))
self.angular_velocity = 0.5
self.linear_velocity = 0.2
self.min_distance = 0.3
self.target_angle = 270
self.latest_laser_data = None
self.publisher_ = self.create_publisher(Twist, 'cmd_vel', 10)
def laser_callback(self, laser_data):
self.latest_laser_data = laser_data
def empty_callback(self, request, response):
if self.latest_laser_data is None:
self.get_logger().info('No data received yet!')
return response
else:
shortest_ray_index = self.latest_laser_data.ranges.index(min(self.latest_laser_data.ranges))
while shortest_ray_index!=0:
self.rotate(self.angular_velocity)
self.stop_movement()
while self.latest_laser_data.ranges[0] > self.min_distance:
self.move_forward(self.linear_velocity)
self.stop_movement()
while shortest_ray_index != self.target_angle:
self.rotate(self.angular_velocity)
self.stop_movement()
# return the response parameter
return response
def rotate(self, angular_velocity):
twist = Twist()
twist.angular.z = angular_velocity
self.publisher_.publish(twist)
self.get_logger().info('Rotating!')
time.sleep(0.1)
def move_forward(self, linear_velocity):
twist = Twist()
twist.linear.x = linear_velocity
self.publisher_.publish(twist)
self.get_logger().info('Moving forward!')
time.sleep(0.1)
def stop_movement(self):
twist = Twist()
self.publisher_.publish(twist)
self.get_logger().info('Stop!')
def main(args=None):
# initialize the ROS communication
rclpy.init(args=args)
# declare the node constructor
moving_service = Wall_finder()
# pause the program execution, waits for a request to kill the node (ctrl+c)
rclpy.spin(moving_service)
# shutdown the ROS communication
rclpy.shutdown()
Well we can see here you importing the custom message for the service.
# import the Empty module from std_servs Service interface
from custom_interfaces.srv import FindWall
And here you are using it for the service server, so your server will want to receive a FindWall message
# create the Service Server object
# defines the type, name, and callback function
self.srv = self.create_service(FindWall, 'find_wall', self.empty_callback)
So when you run on terminal ros2 service call /find_wall std_srvs/srv/Empty '{}' it will not work. If your service message file is setup correctly then you should call like so: ros2 service call /find_wall custom_interfaces/srv/FindWall ‘{}’