当前位置:网站首页>Ros2 - Service Service (IX)
Ros2 - Service Service (IX)
2022-07-05 06:51:00 【Me and nano】
ROS2 Robot operating system
List of articles
Preface
Topic communication can realize multiple ROS One way transmission of data between nodes , Use this asynchronous communication mechanism , Publishers cannot accurately know whether subscribers receive messages , In this lecture, we will study together ROS Another common communication method —— service , It can achieve the synchronous communication effect similar to what you asked and answered .
One 、 Service details
client / Server model
From the perspective of service implementation mechanism , This form of asking and answering is called client / Server model , Referred to as CS Model , When the client needs some data , For a specific service , Send request information , After the server receives the request , It will process and feed back the response information .
This communication mechanism is also very common in life , For example, we often browse various web pages , At this point, your computer browser is the client , Through the domain name or various operations , Send a request to the web server , After receiving it, the server returns the page data that needs to be displayed . This is the way that client-side rendering used when learning crawlers before .
Synchronous communication
This process generally requires that the faster the better , Suppose the server doesn't respond for half a day , Your browser keeps circling , It may be that the server is down , Or the network is bad , So compared with topic communication , In service communication , The client can receive the response information , Determine the state of the server , We also call it synchronous communication
One to many communication
For example, Gu Yueju website , The server is the only one , There are not many exactly the same Gu Yueju websites , But the client that can visit Gu Yueju website is not unique , Everyone can see the same interface . So in the service communication model , The server side is unique , But the client can not be unique .
Service interface
Similar to topic communication , The core of service communication is still to transmit data , The data becomes two parts , A requested data , For example, the command to request the location of Apple , There is also a feedback data , For example, feedback the data of Apple coordinate position , These data are the same as topic news , stay ROS It is also defined in the standard , Topic use .msg File defines , The service USES .srv File defines
Two 、 Service cases
1. Addition solver
Now everyone is right ROS Service communication should have a basic understanding , Next we are going to start writing code . Or start with a relatively simple routine , It's also ROS An official routine , Realize the function of an addition solver through services .
When we need to calculate the sum of two addends , Through the client node , Encapsulate two addends into request data , For services “add_two_ints” Send out , The server-side node that provides this service , After receiving the requested data , Start adding , And encapsulate the sum result into response data , Feedback to the client , Then the client can get the desired results .
Start two terminals , And run the following nodes , The first node is the server , Wait for the requested data and provide the summation function , The second node is the client , Send the two addends passed in and wait for the sum result .
ros2 run learning_service service_adder_server
ros2 run learning_service service_adder_client 2 3
Server code implementation
import rclpy # ROS2 Python Interface library
from rclpy.node import Node # ROS2 Node class
from learning_interface.srv import AddTwoInts # Customized service interface
class adderServer(Node):
def __init__(self, name):
super().__init__(name) # ROS2 Node parent class initialization
self.srv = self.create_service(AddTwoInts, 'add_two_ints', self.adder_callback) # Create a server object ( Interface type 、 service name 、 Server callback function )
def adder_callback(self, request, response): # Create callback function , Execute the processing of data after receiving the request
response.sum = request.a + request.b # Complete the addition and sum calculation , Put the results into the feedback data
self.get_logger().info('Incoming request\na: %d b: %d' % (request.a, request.b)) # Output log information , Prompt that the addition and summation calculation has been completed
return response # Feedback and response information
def main(args=None): # ROS2 Node main entrance main function
rclpy.init(args=args) # ROS2 Python Interface initialization
node = adderServer("service_adder_server") # establish ROS2 Node object and initialize
rclpy.spin(node) # Loop waiting for ROS2 sign out
node.destroy_node() # Destroy the node object
rclpy.shutdown() # close ROS2 Python Interface
Client code
import sys
import rclpy # ROS2 Python Interface library
from rclpy.node import Node # ROS2 Node class
from learning_interface.srv import AddTwoInts # Customized service interface
class adderClient(Node):
def __init__(self, name):
super().__init__(name) # ROS2 Node parent class initialization
self.client = self.create_client(AddTwoInts, 'add_two_ints') # Create a service client object ( Service interface type , service name )
while not self.client.wait_for_service(timeout_sec=1.0): # Wait for the server to start successfully
self.get_logger().info('service not available, waiting again...')
self.request = AddTwoInts.Request() # Create the data object of the service request
def send_request(self): # Create a function to send service requests
self.request.a = int(sys.argv[1])
self.request.b = int(sys.argv[2])
self.future = self.client.call_async(self.request) # Send service requests asynchronously
def main(args=None):
rclpy.init(args=args) # ROS2 Python Interface initialization
node = adderClient("service_adder_client") # establish ROS2 Node object and initialize
node.send_request() # Send service request
while rclpy.ok(): # ROS2 The system operates normally
rclpy.spin_once(node) # Loop through the nodes once
if node.future.done(): # Whether the data processing is completed
try:
response = node.future.result() # Receive feedback data from the server
except Exception as e:
node.get_logger().info(
'Service call failed %r' % (e,))
else:
node.get_logger().info( # Print out the feedback received
'Result of add_two_ints: for %d + %d = %d' %
(node.request.a, node.request.b, response.sum))
break
node.destroy_node() # Destroy the node object
rclpy.shutdown() # close ROS2 Python Interface
After writing the code, you need to set the compilation options of the function package , Let the system know Python Program entry , To open a feature pack setup.py file , Add the following entry point configuration :
entry_points={
'console_scripts': [
'service_adder_client = learning_service.service_adder_client:main',
],
},
Process summary
Analyze the above procedures , If we want to achieve one A client , The process is as follows :
Programming interface initialization
Create nodes and initialize
Create client objects
Create and send request data
Wait for the server to answer the data
Destroy the node and close the interface
Analyze the above procedures , If we want to achieve one A server , The process is as follows :
Programming interface initialization
Create nodes and initialize
Create server-side objects
Service through callback function
Feed back the response result to the client
Destroy the node and close the interface
2. Machine vision recognition
All right. , The addition solver has been implemented , Think back to the visual recognition process we just mentioned , When we need to know the position of the target object , Through the mechanism of service communication , Isn't it more reasonable
Running effect
Three nodes will appear :
Camera drive node , Publish image data ;
Visual recognition node , Subscribe to image data , And it integrates a server-side object , Be ready to provide the target location ;
Client node , We can think of it as a node for robot target tracking , When you need to move according to the target , Just send a request , Then get a current target location .
Start three terminals , Run the above three nodes respectively :
ros2 run usb_cam usb_cam_node_exe
ros2 run learning_service service_object_server
ros2 run learning_service service_object_client
Client code parsing
import rclpy # ROS2 Python Interface library
from rclpy.node import Node # ROS2 Node class
from learning_interface.srv import GetObjectPosition # Customized service interface
class objectClient(Node):
def __init__(self, name):
super().__init__(name) # ROS2 Node parent class initialization
self.client = self.create_client(GetObjectPosition, 'get_target_position')
while not self.client.wait_for_service(timeout_sec=1.0):
self.get_logger().info('service not available, waiting again...')
self.request = GetObjectPosition.Request()
def send_request(self):
self.request.get = True
self.future = self.client.call_async(self.request)
def main(args=None):
rclpy.init(args=args) # ROS2 Python Interface initialization
node = objectClient("service_object_client") # establish ROS2 Node object and initialize
node.send_request()
while rclpy.ok():
rclpy.spin_once(node)
if node.future.done():
try:
response = node.future.result()
except Exception as e:
node.get_logger().info(
'Service call failed %r' % (e,))
else:
node.get_logger().info(
'Result of object position:\n x: %d y: %d' %
(response.x, response.y))
break
node.destroy_node() # Destroy the node object
rclpy.shutdown() # close ROS2 Python Interface
Server code parsing
import rclpy # ROS2 Python Interface library
from rclpy.node import Node # ROS2 Node class
from sensor_msgs.msg import Image # Image message type
import numpy as np # Python Numerical calculation library
from cv_bridge import CvBridge # ROS And OpenCV Image conversion class
import cv2 # Opencv Image processing library
from learning_interface.srv import GetObjectPosition # Customized service interface
lower_red = np.array([0, 90, 128]) # Red HSV Lower threshold
upper_red = np.array([180, 255, 255]) # Red HSV Upper threshold
class ImageSubscriber(Node):
def __init__(self, name):
super().__init__(name) # ROS2 Node parent class initialization
self.sub = self.create_subscription(
Image, 'image_raw', self.listener_callback, 10) # Create subscriber object ( Message type 、 Topic name 、 Subscriber callback function 、 The queue length )
self.cv_bridge = CvBridge() # Create an image conversion object , be used for OpenCV Image and ROS Mutual conversion of image messages of
self.srv = self.create_service(GetObjectPosition, # Create a server object ( Interface type 、 service name 、 Server callback function )
'get_target_position',
self.object_position_callback)
self.objectX = 0
self.objectY = 0
def object_detect(self, image):
hsv_img = cv2.cvtColor(image, cv2.COLOR_BGR2HSV) # Images from BGR The color model is converted to HSV Model
mask_red = cv2.inRange(hsv_img, lower_red, upper_red) # Image binarization
contours, hierarchy = cv2.findContours(
mask_red, cv2.RETR_LIST, cv2.CHAIN_APPROX_NONE) # Contour detection in image
for cnt in contours: # Remove some noise with too small contour area
if cnt.shape[0] < 150:
continue
(x, y, w, h) = cv2.boundingRect(cnt) # Get the upper left corner of the outline of the apple xy Pixel coordinates and the width and height of the contour range
cv2.drawContours(image, [cnt], -1, (0, 255, 0), 2)# Outline the apple
cv2.circle(image, (int(x+w/2), int(y+h/2)), 5,
(0, 255, 0), -1) # Draw the center point of the apple image
self.objectX = int(x+w/2)
self.objectY = int(y+h/2)
cv2.imshow("object", image) # Use OpenCV Display the processed image effect
cv2.waitKey(50)
def listener_callback(self, data):
self.get_logger().info('Receiving video frame') # Output log information , Prompt that the callback function has been entered
image = self.cv_bridge.imgmsg_to_cv2(data, 'bgr8') # take ROS The image message is transformed into OpenCV Images
self.object_detect(image) # Apple detection
def object_position_callback(self, request, response): # Create callback function , Execute the processing of data after receiving the request
if request.get == True:
response.x = self.objectX # Target object XY coordinate
response.y = self.objectY
self.get_logger().info('Object position\nx: %d y: %d' %
(response.x, response.y)) # Output log information , Prompt that feedback has been given
else:
response.x = 0
response.y = 0
self.get_logger().info('Invalid command') # Output log information , Prompt that feedback has been given
return response
def main(args=None): # ROS2 Node main entrance main function
rclpy.init(args=args) # ROS2 Python Interface initialization
node = ImageSubscriber("service_object_server") # establish ROS2 Node object and initialize
rclpy.spin(node) # Loop waiting for ROS2 sign out
node.destroy_node() # Destroy the node object
rclpy.shutdown() # close ROS2 Python Interface
3、 ... and 、 Service command line operation
$ ros2 service list # View the list of services
$ ros2 service type <service_name> # View service data types
$ ros2 service call <service_name> <service_type> <service_data> # Send service request
summary
Topics and services are ROS The two most commonly used data communication methods in , The former is suitable for sensors 、 Control instructions and other periodicity 、 Unidirectional data , The latter is suitable for asking and answering , Data with higher synchronization requirements , For example, get the target location recognized by machine vision .
In the process of robot development , Similar communication applications can be found everywhere ,ROS For most common scenarios , Standard topics and service data types are designed , Like image data 、 Radar data 、 Odometer data, etc , However, the software and hardware of robots are complicated , Many times these standard definitions cannot meet our needs , This is the time , We are going to customize the communication interface .
边栏推荐
- Rehabilitation type force deduction brush question notes D3
- 达梦数据库全部
- The problem of Chinese garbled code in the vscode output box can be solved once for life
- Sum of two numbers, the numbers in the array are converted to decimal, added, and output inversely
- About vscode, "code unreachable" will be displayed when calling sendline series functions with pwntools“
- Skywalking all
- PHY驱动调试之 --- MDIO/MDC接口22号和45号条款(一)
- ROS2——初识ROS2(一)
- ROS2——配置开发环境(五)
- 代码中的英语全部
猜你喜欢
随机推荐
The route of wechat applet jumps again without triggering onload
Dameng database all
Speedtree01 generator properties
Skywalking all
Error: "mountvolume.setup failed for volume PVC fault handling
基于FPGA的一维卷积神经网络CNN的实现(八)激活层实现
Redis-01. First meet redis
Orin 两种刷机方式
全局变量和静态变量的初始化
Lexin interview process
Vscode configures the typera editor for MD
mingling
The “mode“ argument must be integer. Received an instance of Object
Edge calculation data sorting
微信小程序路由再次跳轉不觸發onload
ROS2——node节点(七)
H5 模块悬浮拖动效果
[Chongqing Guangdong education] 1185t administrative leadership reference test of National Open University in autumn 2018
NVM Downloading npm version 6.7.0... Error
TypeScript入门