背景介绍
软件平台
The Robot Operating System (ROS) is a set of software libraries and tools that help you build robot applications. From drivers to state-of-the-art algorithms, and with powerful developer tools, ROS has what you need for your next robotics project. And it’s all open source.
Robot操作系统(ROS)是一组软件库和工具,可帮助您构建机器人应用程序。从驱动程序到最先进的算法,再加上强大的开发工具,ROS为您的下一个机器人项目提供了所需的一切。而且这一切都是开源的。
硬件平台
地平线旭日®️X3派是一款面向生态开发者的嵌入式AI开发板,接口兼容树莓派,具有5Tops端侧推理与4核ARM A53处理能力。可同时多路Camera Sensor的输入并支持H.264/H.265编解码。结合地平线的高性能AI工具链与机器人开发平台,助力开发者快速落地解决方案。
ROS 订阅机制
ROS 2将复杂的系统分解为许多模块化节点。 主题是 ROS 图的重要组成部分,充当节点交换消息的总线。
一个节点可以将数据发布到任意数量的主题,同时订阅任意数量的主题。
主题是数据在节点之间移动的主要方式之一,因此也是在系统的不同部分之间移动的主要方式之一。
(不得不说官方文档还是写的很不错的)
自定义订阅者
(这里参考了很多官方文档)
创建包
打开一个新终端并获取 ROS 2 安装,以便命令正常工作。ros2
导航到上一教程中创建的目录。ros2_ws
回想一下,包应该在目录中创建,而不是在工作区的根目录中创建。 因此,导航到 并运行包创建命令:srcros2_ws/src
ros2 pkg create --build-type ament_python py_pubsub
您的终端将返回一条消息,验证您的软件包及其所有必要文件和文件夹的创建。
编写订阅节点
导航到 py_pubsub
回想一下,此目录是一个 Python
包,与它嵌套的 ROS 2 包同名。ros2_ws/src/py_pubsub/py_pubsub
import rclpy
from rclpy.node import Node
from std_msgs.msg import String
class MinimalSubscriber(Node):
def __init__(self):
super().__init__('minimal_subscriber')
self.subscription = self.create_subscription(
String,
'topic',
self.listener_callback,
10)
self.subscription # prevent unused variable warning
def listener_callback(self, msg):
self.get_logger().info('I heard: "%s"' % msg.data)
def main(args=None):
rclpy.init(args=args)
minimal_subscriber = MinimalSubscriber()
rclpy.spin(minimal_subscriber)
# Destroy the node explicitly
# (optional - otherwise it will be done automatically
# when the garbage collector destroys the node object)
minimal_subscriber.destroy_node()
rclpy.shutdown()
if __name__ == '__main__':
main()
添加依赖
将一个级别导航回目录,其中已为您创建了目录和文件。ros2_ws/src/py_pubsub
setup.py
setup.cfg
package.xml
使用文本编辑器打开。package.xml
如上一教程所述,请确保填写<description>
<maintainer>
<license>
标记:
<description>Examples of minimal publisher/subscriber using rclpy<description>
<maintainer email="you@email.com">Your Name</maintainer>
<license>Apache License 2.0</license>
在上述行之后,添加与节点的导入语句对应的以下依赖项:
<exec_depend>rclpy</exec_depend>
<exec_depend>std_msgs</exec_depend>
这声明了包的需求以及何时执行其代码
添加入口点
打开setup.py
文件。 同样,将 、 和 字段与您的 :maintainer maintainer_email description licensepackage.xml
maintainer='YourName',
maintainer_email='you@email.com',
description='Examples of minimal publisher/subscriber using rclpy',
license='Apache License 2.0',
在字段的括号内添加以下行:
entry_points={
'console_scripts': [
'talker = py_pubsub.publisher_member_function:main',
],
},
不要忘记保存。
检查设置.cfg
文件的内容应自动正确填充,如下所示:setup.cfg
[develop]
script-dir=$base/lib/py_pubsub
[install]
install-scripts=$base/lib/py_pubsub
这只是告诉设置工具将您的可执行文件放入 ,因为会在那里寻找它们。
您现在可以构建软件包,获取本地安装文件并运行它,但让我们先创建订阅者节点,以便您可以看到完整的系统在工作。
消息格式
ai_msgs
自定义的ai msg,包括人/物/车等检测框roi,跟踪track id,抓拍,特征,手势识别等结果。用于算法模型推理后,发布推理结果。
message详细说明如下:
PerceptionTargets.msg
感知结果的消息定义,一般每帧图像对应一个感知结果消息。消息包含:
1、std_msgs/Header header
消息头,包含stamp和frame_id,和用于模型推理的图片header一致,用于表示此消息所对应的图片。
2、int16 fps
感知结果的输出帧率,即算法模型推理处理帧率,小于0无效。
当fps小于sensor的图像输出帧率时,说明算法模型推理耗时比较长,需要对推理流程进行优化。
3、Perf[] perfs
性能统计信息,比如记录每个模型推理的耗时。
当有多个模型时,可以通过记录每个模型的性能信息发现模型推理流程的性能瓶颈。同时当发生推理异常导致无ai消息输出时,也能够根据性能统计信息中的模型名,判断是哪个模型没有输出,实现快速缩小排查范围。
4、Target[] targets
感知目标集合。
5、Target[] disappeared_targets
消失目标集合。
CaptureTargets.msg
抓拍结果的消息定义。消息包含:
1、std_msgs/Header header
消息头,包含stamp和frame_id,和用于模型推理的图片header一致,用于表示此消息所对应的图片。
2、Perf.msg
性能统计信息,比如记录每个模型推理的耗时
4、Target[] targets
抓拍目标集合。
Perf.msg
性能统计信息。
1、string type
类型,用于表示处理模块。例如type为模型名时,表示对此模型推理的性能统计。
2、builtin_interfaces/Time stamp_start
开始处理的时间戳。
3、builtin_interfaces/Time stamp_end
处理完成的时间戳。
Target.msg
目标消息。
1、string type
目标类型名称,如:人、车、动物、物体,具体值可以定义为为person/car/object/animal
2、uint64 track_id
目标跟踪ID号。
3、Roi[] rois
目标的检测框。一个目标可能包含多个检测框,如同时具有人体、人头和人脸检测框。
4、Attribute[] attributes
属性。一个目标可能包含多个属性信息,如同时具有年龄、性别和手势结果。
5、Point[] points
关键点。一个目标可能包含多个关键点信息,如同时具有人脸关键点、人体骨骼点、人手关键点
6、Capture[] captures
跟踪目标抓拍图信息,包含抓拍图、特征、特征的底库检索结果信息。
Roi.msg
roi感知消息,如:人体检测框、人头检测框、人脸检测框、人手检测框。
1、string type
roi类型,如body/head/face/hand。
2、sensor_msgs/RegionOfInterest rect
检测框。
3、float32 score
检测结果的置信度。
Attribute.msg
属性感知消息,如:年龄、性别、手势、眼镜、口罩、活体信息、车辆类型、车辆颜色、车辆速度、车辆所在车道等信息。
1、string type
属性类型,如年龄:age,性别:gender, 手势:gesture。
2、float32 value
属性数值。
如age数值定义举例:
val为实际年龄数值
gender数值定义举例:
“1”: “男”, “-1”: “女”
gesture数值定义举例:
0: Background, // 无手势
1: FingerHeart, // 比心
2: ThumbUp, // 大拇指向上
3: Victory, // V手势
4: Mute, // 嘘
10: Palm, // 手掌
11: Okay, // OK手势
12: ThumbRight, // 大拇指向右
13: ThumbLeft, // 大拇指向左
14: Awesome, // 666手势
3、float32 confidence
属性结果的置信度。
Point.msg
关键点感知结果,如:人脸关键点、人体骨骼点、人手关键点。
1、string type
类型,如body_kps/face_kps/hand_kps。
2、geometry_msgs/Point32[] point
关键点数值。
3、float32[] confidence
每个关键点的置信度,维度和关键点数值相同。
Capture.msg
抓拍信息。
1、std_msgs/Header header
抓拍图对应原视频帧的timestamp和frame_id。
2、sensor_msgs/Image img
抓拍图。
3、float32[] features
抓拍图对应的特征数据,数据长度为0时表示无特征。
4、DBResult db_result
特征的底库检索结果。只有当有特征时底库检索结果有效。
DBResult.msg
底库检索结果。
1、string db_type
底库名称。
2、string match_id
匹配目标ID。
3、float32 distance
特征比对距离。
4、float32 similarity
特征比对相似度。
构建和运行
编译
colcon build --packages-select py_pubsub
打开一个新终端,导航到 ,并获取安装文件:
. install/setup.bash
现在运行说话者节点:
ros2 run py_pubsub listener
我的代码修改
其实Python脚本代码可以直接运行,无需编译
import rclpy
from rclpy.node import Node
from ai_msgs.msg import PerceptionTargets
class MinimalSubscriber(Node):
def __init__(self):
super().__init__('minimal_subscriber')
self.subscription = self.create_subscription(
PerceptionTargets,
'hobot_mono2d_body_detection',
self.listener_callback,
10)
self.subscription # prevent unused variable warning
def listener_callback(self, msg):
if len(msg.targets) > 1:
self.get_logger().info('I heard:' + str(msg.targets[0].type) + str(msg.fps))# "%s"' % msg.data
else:
self.get_logger().info('dont')
# https://c-gitlab.horizon.ai/HHP/box/hobot_msgs/-/tree/develop/ai_msgs
def main(args=None):
rclpy.init(args=args)
minimal_subscriber = MinimalSubscriber()
rclpy.spin(minimal_subscriber)
# Destroy the node explicitly
# (optional - otherwise it will be done automatically
# when the garbage collector destroys the node object)
minimal_subscriber.destroy_node()
rclpy.shutdown()
if __name__ == '__main__':
main()
结果展示
[INFO] [1672741631.264257258] [minimal_subscriber]: I heard:person30
[INFO] [1672741631.295972687] [minimal_subscriber]: I heard:person30
[INFO] [1672741631.327739324] [minimal_subscriber]: I heard:person30
[INFO] [1672741631.363461421] [minimal_subscriber]: I heard:person30
[INFO] [1672741631.392870207] [minimal_subscriber]: I heard:person30
[INFO] [1672741631.429643377] [minimal_subscriber]: I heard:person30
[INFO] [1672741631.465771636] [minimal_subscriber]: I heard:person30
[INFO] [1672741631.496358035] [minimal_subscriber]: I heard:person30