ros自定义消息订阅后如何处理?
时间: 2023-05-30 19:07:18 AIGC 浏览: 309
当订阅了一个自定义 ROS 消息后,需要编写回调函数来处理接收到的消息。回调函数会在接收到消息时被自动调用,其中的参数是接收到的消息。
下面是一个简单的例子,假设自定义消息类型为 MyMsg:
```python
#!/usr/bin/env python
import rospy
from my_package.msg import MyMsg
def callback(data):
rospy.loginfo(rospy.get_caller_id() + "I heard %s", data.data)
def listener():
rospy.init_node('my_listener', anonymous=True)
rospy.Subscriber("my_topic", MyMsg, callback)
rospy.spin()
if __name__ == '__main__':
listener()
```
在这个例子中,我们创建了一个名为 `my_listener` 的节点,并订阅了名为 `my_topic` 的话题,类型为 `MyMsg`。回调函数 `callback` 会在接收到消息时被调用,它会打印消息的内容。
最后,我们调用 `rospy.spin()` 来使程序保持运行状态,以等待接收消息。
相关问题
ros自定义消息
### 创建和使用 ROS 自定义消息
在 ROS 和 ROS2 中,自定义消息是一种用于节点间通信的重要机制。通过创建自定义消息类型,开发者可以根据需求设计特定的数据结构来传递复杂的信息。
#### 1. 判断是否需要创建自定义消息
在开发过程中,如果现有的标准消息类型无法满足应用需求,则需要考虑创建自定义消息[^5]。例如,当需要传输包含多个字段的复合数据时(如人员信息 `Person`),可以通过定义新的 `.msg` 文件实现这一目标。
---
#### 2. 创建自定义消息文件
在 ROS 或 ROS2 的工作空间中,通常会在包内的 `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]。
---
vscode中ROS自定义消息的发布和订阅
在Visual Studio Code (VSCode) 中使用ROS(Robot Operating System)进行自定义消息的发布和订阅通常涉及到几个步骤:
1. 安装插件:首先,需要安装`ros-tooling` 插件,它为VSCode提供了一些方便的ROS集成。可以在终端中通过`npm install -g ros-tooling-vscode` 或者直接在VSCode的扩展市场搜索并安装。
2. 创建节点:创建一个新的ROS节点,可以使用ROS包中的`package.xml`文件来声明新消息类型。例如,如果名为`my_message`的新消息包含字段`int data`,则需在`msg`目录下编写`.msg`文件。
```xml
<?xml version="1.0"?>
<message name="MyMessage">
<field type="int" name="data"/>
</message>
```
3. 编写代码:在C++、Python或其他支持的语言中,使用ROS的API创建发布者(`Publisher`)和订阅者(`Subscriber`)。比如在Python中:
```python
import rclpy
from my_package.srv import MyMessage
class CustomNode(rclpy.Node):
def __init__(self):
super().__init__('custom_node')
self.publisher_ = self.create_publisher(MyMessage, 'my_topic', 10)
self.subscription = self.create_subscription(
MyMessage,
'my_topic',
self.message_callback,
10)
def message_callback(self, msg):
# 处理接收到的消息
```
4. 发布与订阅:在`CustomNode`类实例化后,可以开始发布消息到指定的主题(`my_topic`),并在回调函数`message_callback`中处理订阅来的消息。
5. 运行工作空间:最后,在VSCode的终端中运行`src`目录下的launch文件启动工作空间,并查看日志确认消息是否成功交换。
阅读全文
相关推荐

















