ROS学习笔记(六)(自定义话题消息)

本文详细介绍如何在ROS中自定义消息类型,包括创建Person.msg文件,定义字段如name、sex、age等,以及如何通过修改package.xml和CMakeLists.txt进行编译,最后验证自定义消息是否生效。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.自定义话题消息自定义,我们先在目录/catkin_ws/src/learning_sun/msg下创建一个名为Person.msg的msg类型文件

2.在文件中输入:

string name
uint8 sex
uint8 age

uint8 unknown = 0
uint8 male = 1
uint8 female = 2

uint32 seq
time stamp
string frame_id

3.文件创建完毕,接下来需要编译文件,退回到src目录下,先修改package.xml文件,添加依赖项,在文件中输入:

  <build_depend>message_generation</build_depend>
  <exec_depend>message_runtime</exec_depend>

4.package.xml文件修改完毕,我们接着在CMakeList文件中修改配置选项,打开CMakeList文件,增加或修改以下选项:

此处注意add_message_files()与generate_messages()一定要在catkin_package()前面才可编译通过

find_package(catkin REQUIRED COMPONENTS
  roscpp
  rospy
  std_msgs

  geometry_msgs
  message_generation
)

add_message_files(
   FILES
   Person.msg
 )

 generate_messages(
   DEPENDENCIES
   std_msgs
 )
catkin_package(
#  INCLUDE_DIRS include
#  LIBRARIES learning_sun
#  CATKIN_DEPENDS roscpp rospy std_msgs
#  DEPENDS system_lib
   CATKIN_DEPENDS geometry_msgs roscpp rospy std_msgs message_runtime
)

5.修改好文件后,退出到catkin_ws目录,执行catkin_make命令编译文件,当进度达到100%时即为编译完成。

6.输入命令 rosmsg show Person查看是否自定义消息生效,如果生效,则会有如下日志:

[learning_sun/Person]:
uint8 unknown=0
uint8 male=1
uint8 female=2
string name
uint8 sex
uint8 age
uint32 seq
time stamp
string frame_id

7.自定义消息实验到此结束

### 创建和使用 ROS 自定义消息ROSROS2 中,自定义消息是一种用于节点间通信的重要机制。通过创建自定义消息类型,开发者可以根据需求设计特定的数据结构来传递复杂的信息。 #### 1. 判断是否需要创建自定义消息 在开发过程中,如果现有的标准消息类型无法满足应用需求,则需要考虑创建自定义消息[^5]。例如,当需要传输包含多个字段的复合数据时(如人员信息 `Person`),可以通过定义新的 `.msg` 文件实现这一目标。 --- #### 2. 创建自定义消息文件 在 ROSROS2 的工作空间中,通常会在包内的 `msg` 目录下创建一个新的 `.msg` 文件。以下是具体操作: - **路径设置** 确保在包目录中有 `msg` 子目录。如果没有,请手动创建。 - **编写 .msg 文件** 在 `msg` 目录下新增一个 `.msg` 文件,例如命名为 `Person.msg`,其内容如下: ```plaintext string name uint8 age bool is_student ``` 这里定义了一个简单的消息类型,其中包含了三个字段:字符串类型的姓名 (`name`)、整数类型的年龄 (`age`) 和布尔型的学生状态 (`is_student`)。 --- #### 3. 配置 package.xml 为了让 ROS 构建系统识别新定义的消息类型,需更新 `package.xml` 文件中的依赖项。对于 ROS1 和 ROS2,分别执行以下配置: - **ROS1** 添加以下两行到 `package.xml` 中: ```xml <build_depend>message_generation</build_depend> <exec_depend>message_runtime</exec_depend> ``` - **ROS2** 同样需要声明对消息生成工具的支持: ```xml <depend>rclcpp</depend> <member_of_group>rosidl_interface_packages</member_of_group> ``` --- #### 4. 更新 CMakeLists.txt 完成上述步骤后,还需修改 `CMakeLists.txt` 来指定构建过程应处理这些消息文件。以下是针对不同版本的具体调整方法: - **ROS1** 将以下代码片段加入 `CMakeLists.txt`: ```cmake find_package(catkin REQUIRED COMPONENTS roscpp std_msgs message_generation ) add_message_files( FILES Person.msg ) generate_messages( DEPENDENCIES std_msgs ) ``` - **ROS2** 对于 ROS2,同样需要告知编译器如何解析消息文件。编辑 `CMakeLists.txt` 如下: ```cmake find_package(ament_cmake REQUIRED) find_package(rmw_implementation_cmake REQUIRED) ament_export_dependencies(message_runtime) rosidl_generate_interfaces(${PROJECT_NAME} "msg/Person.msg" ) ``` --- #### 5. 编写 Publisher 和 Subscriber 节点 一旦完成了消息定义及其相关配置,就可以着手开发实际的应用程序了。下面是一个完整的示例展示如何利用自定义消息进行通信。 ##### (a) 发布者 (Publisher) 实现 ```python import rclpy from rclpy.node import Node from my_custom_msg.msg import Person # 导入自定义消息类型 class PersonPublisher(Node): def __init__(self): super().__init__('person_publisher') self.publisher_ = self.create_publisher(Person, 'person_info', 10) timer_period = 1.0 # 秒 self.timer = self.create_timer(timer_period, self.timer_callback) self.i = 0 def timer_callback(self): msg = Person() msg.name = f'User{self.i}' msg.age = self.i % 100 msg.is_student = True if self.i % 2 == 0 else False self.publisher_.publish(msg) self.get_logger().info(f'Published: {msg}') self.i += 1 def main(args=None): rclpy.init(args=args) person_publisher = PersonPublisher() rclpy.spin(person_publisher) person_publisher.destroy_node() rclpy.shutdown() if __name__ == '__main__': main() ``` ##### (b) 订阅者 (Subscriber) 实现 ```python import rclpy from rclpy.node import Node from my_custom_msg.msg import Person # 导入自定义消息类型 class PersonSubscriber(Node): def __init__(self): super().__init__('person_subscriber') self.subscription = self.create_subscription( Person, 'person_info', self.listener_callback, 10) self.subscription # prevent unused variable warning def listener_callback(self, msg): self.get_logger().info(f'Received: Name={msg.name}, Age={msg.age}, IsStudent={msg.is_student}') def main(args=None): rclpy.init(args=args) person_subscriber = PersonSubscriber() rclpy.spin(person_subscriber) person_subscriber.destroy_node() rclpy.shutdown() if __name__ == '__main__': main() ``` --- #### 6. 测试与验证 启动两个终端窗口并依次运行以下命令测试功能: - 终端 1 (发布者): ```bash ros2 run your_package_name person_publisher ``` - 终端 2 (订阅者): ```bash ros2 run your_package_name person_subscriber ``` 此时可以看到发布者不断发送带有动态变化的人类对象信息,而订阅者则实时打印接收到的内容[^3]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值