話題接口的定義與使用
話題通信接口的定義也是類似的,繼續(xù)從之前的機(jī)器視覺案例中來衍生,我們想把服務(wù)換成話題,周期發(fā)布目標(biāo)識(shí)別的位置,不管有沒有人需要。
運(yùn)行效果
現(xiàn)在我們會(huì)運(yùn)行三個(gè)節(jié)點(diǎn):
第一個(gè)節(jié)點(diǎn),將驅(qū)動(dòng)相機(jī)并發(fā)布圖像話題,此時(shí)的話題數(shù)據(jù)使用的是ROS中標(biāo)準(zhǔn)定義的Image圖像消息;
第二個(gè)節(jié)點(diǎn),會(huì)運(yùn)行視覺識(shí)別功能,識(shí)別目標(biāo)的位置,這個(gè)位置我們希望封裝成話題消息,發(fā)布出去,誰需要使用誰就來訂閱;
第三個(gè)節(jié)點(diǎn),訂閱位置話題,打印到終端中。
啟動(dòng)三個(gè)終端,分別運(yùn)行以上節(jié)點(diǎn):
$ ros2 run usb_cam usb_cam_node_exe$ ros2 run learning_topic interface_object_pub$ ros2 run learning_topic interface_object_sub
接口定義
在這個(gè)例程中,我們使用ObjectPosition.msg定義了服務(wù)通信的接口:
learning_interface/msg/ObjectPosition.msg
int32 x # 表示目標(biāo)的X坐標(biāo)int32 y # 表示目標(biāo)的Y坐標(biāo)
話題消息的內(nèi)容是一個(gè)位置,我們使用x、y坐標(biāo)值進(jìn)行描述。
完成定義后,還需要在功能包的CMakeLists.txt中配置編譯選項(xiàng),讓編譯器在編譯過程中,根據(jù)接口定義,自動(dòng)生成不同語言的代碼:
...find_package(rosidl_default_generators REQUIRED)rosidl_generate_interfaces(${PROJECT_NAME} "msg/ObjectPosition.msg")...
程序調(diào)用
我們?cè)诖a中再來重點(diǎn)看下接口的使用方法。
發(fā)布者接口調(diào)用
learning_topic/interface_object_pub.py
#!/usr/bin/env python3# -*- coding: utf-8 -*-"""@作者: 古月居@說明: ROS2接口示例-發(fā)布目標(biāo)位置"""import rclpy # ROS2 Python接口庫from rclpy.node import Node # ROS2 節(jié)點(diǎn)類from sensor_msgs.msg import Image # 圖像消息類型from cv_bridge import CvBridge # ROS與OpenCV圖像轉(zhuǎn)換類import cv2 # Opencv圖像處理庫import numpy as np # Python數(shù)值計(jì)算庫from learning_interface.msg import ObjectPosition # 自定義的目標(biāo)位置消息lower_red = np.array([0, 90, 128]) # 紅色的HSV閾值下限upper_red = np.array([180, 255, 255]) # 紅色的HSV閾值上限"""創(chuàng)建一個(gè)訂閱者節(jié)點(diǎn)"""class ImageSubscriber(Node): def __init__(self, name): super().__init__(name) # ROS2節(jié)點(diǎn)父類初始化 self.sub = self.create_subscription( Image, 'image_raw', self.listener_callback, 10) # 創(chuàng)建訂閱者對(duì)象(消息類型、話題名、訂閱者回調(diào)函數(shù)、隊(duì)列長度) self.pub = self.create_publisher( ObjectPosition, "object_position", 10) # 創(chuàng)建發(fā)布者對(duì)象(消息類型、話題名、隊(duì)列長度) self.cv_bridge = CvBridge() # 創(chuàng)建一個(gè)圖像轉(zhuǎn)換對(duì)象,用于OpenCV圖像與ROS的圖像消息的互相轉(zhuǎn)換 self.objectX = 0 self.objectY = 0 def object_detect(self, image): hsv_img = cv2.cvtColor(image, cv2.COLOR_BGR2HSV) # 圖像從BGR顏色模型轉(zhuǎn)換為HSV模型 mask_red = cv2.inRange(hsv_img, lower_red, upper_red) # 圖像二值化 contours, hierarchy = cv2.findContours( mask_red, cv2.RETR_LIST, cv2.CHAIN_APPROX_NONE) # 圖像中輪廓檢測(cè) for cnt in contours: # 去除一些輪廓面積太小的噪聲 if cnt.shape[0] < 150: continue (x, y, w, h) = cv2.boundingRect(cnt) # 得到蘋果所在輪廓的左上角xy像素坐標(biāo)及輪廓范圍的寬和高 cv2.drawContours(image, [cnt], -1, (0, 255, 0), 2) # 將蘋果的輪廓勾勒出來 cv2.circle(image, (int(x+w/2), int(y+h/2)), 5, # 將蘋果的圖像中心點(diǎn)畫出來 (0, 255, 0), -1) self.objectX = int(x+w/2) self.objectY = int(y+h/2) cv2.imshow("object", image) # 使用OpenCV顯示處理后的圖像效果 cv2.waitKey(50) def listener_callback(self, data): self.get_logger().info('Receiving video frame') # 輸出日志信息,提示已進(jìn)入回調(diào)函數(shù) image = self.cv_bridge.imgmsg_to_cv2(data, 'bgr8') # 將ROS的圖像消息轉(zhuǎn)化成OpenCV圖像 position = ObjectPosition() self.object_detect(image) # 蘋果檢測(cè) position.x, position.y = int(self.objectX), int(self.objectY) self.pub.publish(position) # 發(fā)布目標(biāo)位置def main(args=None): # ROS2節(jié)點(diǎn)主入口main函數(shù) rclpy.init(args=args) # ROS2 Python接口初始化 node = ImageSubscriber("topic_webcam_sub") # 創(chuàng)建ROS2節(jié)點(diǎn)對(duì)象并進(jìn)行初始化 rclpy.spin(node) # 循環(huán)等待ROS2退出 node.destroy_node() # 銷毀節(jié)點(diǎn)對(duì)象 rclpy.shutdown() # 關(guān)閉ROS2 Python接口
訂閱者接口調(diào)用
learning_topic/interface_object_sub.py
#!/usr/bin/env python3# -*- coding: utf-8 -*-"""@作者: 古月居@說明: ROS2接口示例-訂閱目標(biāo)位置"""import rclpy # ROS2 Python接口庫from rclpy.node import Node # ROS2 節(jié)點(diǎn)類from std_msgs.msg import String # 字符串消息類型from learning_interface.msg import ObjectPosition # 自定義的目標(biāo)位置消息"""創(chuàng)建一個(gè)訂閱者節(jié)點(diǎn)"""class SubscriberNode(Node): def __init__(self, name): super().__init__(name) # ROS2節(jié)點(diǎn)父類初始化 self.sub = self.create_subscription( ObjectPosition, "/object_position", self.listener_callback, 10) # 創(chuàng)建訂閱者對(duì)象(消息類型、話題名、訂閱者回調(diào)函數(shù)、隊(duì)列長度 def listener_callback(self, msg): # 創(chuàng)建回調(diào)函數(shù),執(zhí)行收到話題消息后對(duì)數(shù)據(jù)的處理 self.get_logger().info('Target Position: "(%d, %d)"' % (msg.x, msg.y))# 輸出日志信息,提示訂閱收到的話題消息def main(args=None): # ROS2節(jié)點(diǎn)主入口main函數(shù) rclpy.init(args=args) # ROS2 Python接口初始化 node = SubscriberNode("interface_position_sub") # 創(chuàng)建ROS2節(jié)點(diǎn)對(duì)象并進(jìn)行初始化 rclpy.spin(node) # 循環(huán)等待ROS2退出 node.destroy_node() # 銷毀節(jié)點(diǎn)對(duì)象 rclpy.shutdown() # 關(guān)閉ROS2 Python接口
接口命令行操作
接口命令的常用操作如下:
$ ros2 interface list # 查看系統(tǒng)接口列表$ ros2 interface sh
-
接口
+關(guān)注
關(guān)注
33文章
9005瀏覽量
153770 -
相機(jī)
+關(guān)注
關(guān)注
4文章
1468瀏覽量
54695 -
通信接口
+關(guān)注
關(guān)注
3文章
251瀏覽量
31478 -
ROS
+關(guān)注
關(guān)注
1文章
288瀏覽量
17756
發(fā)布評(píng)論請(qǐng)先 登錄
MIDI接口定義,MIDI接口游戲桿接口引腳功能定義圖

SCART接口功能定義

接口的定義 通信接口的作用
ROS通信接口機(jī)制介紹

服務(wù)通信接口的定義與使用

SIM卡座的接口定義

評(píng)論