测试版本:
ubuntu22.04
ROS2 humble
新建msg功能包
ros2 pkg create <msg功能包名> --build-type ament_cmake --dependencies <依赖名字>
新建msg文件夹,并在其中新建.msg文件(文件名首字母要大写!!)
里面按“类型 变量名”格式写入话题消息类型
配置CMakeList
增加如下代码(改成自己的msg文件名)(如果只有一个msg就只写一个)
find_package(rosidl_default_generators REQUIRED) # 这行如果没有就加上,有的话就不管
rosidl_generate_interfaces(${PROJECT_NAME}
"msg/MyMessage1.msg"
"msg/MyMessage2.msg"
)
如果和我一样.msg文件还引用了其他包的消息类型,如std_msg的header,还需要加入
find_package(std_msgs REQUIRED)
并在刚才的rosidl_generate_interfaces里面加入:
DEPENDENCIES std_msgs # 声明 std_msgs 依赖
配置package.xml
增加如下代码:
<build_depend>rosidl_default_generators</build_depend>
<exec_depend>rosidl_default_generators</exec_depend>
<member_of_group>rosidl_default_generators</member_of_group>
<member_of_group>rosidl_interface_packages</member_of_group>
如果引用了其他包的消息类型,如std_msg的header,还需要加入:
<build_depend>std_msgs</build_depend>
<exec_depend>std_msgs</exec_depend>
可以用指令看看有没有配好
ros2 pkg list | grep <msg功能包名>
代码中引用
C++:
C++文件还需要配置其功能包中的CMakeList(不是msg功能包的CMakeList),增加下面的代码:
find_package(<msg功能包名> REQUIRED) # 添加消息包依赖
如果还msg中用了其他功能包的消息类型,如std_msgs,还需要加入对应的功能包依赖,例如:
find_package(std_msgs REQUIRED)
并在所有的ament_target_dependencies里面加入自定义的msg功能包名,如下图:
CPP测试代码:
#include <chrono>
#include <functional>
#include <memory>
#include <string>
#include "rclcpp/rclcpp.hpp" // ROS2 C++接口库
#include "std_msgs/msg/string.hpp" // 字符串消息类型
#include "msg_test/msg/test.hpp" // test消息类型
using namespace std::chrono_literals;
class PublisherNode : public rclcpp::Node{
public:
PublisherNode(): Node("topic_helloworld_pub"){
// 创建发布者对象(消息类型、话题名、队列长度)
publisher_ = this->create_publisher<msg_test::msg::Test>("chatter", 10);
// 创建一个定时器,定时执行回调函数
timer_ = this->create_wall_timer(
500ms, std::bind(&PublisherNode::timer_callback, this));
}
private:
void timer_callback(){
auto msg = msg_test::msg::Test(); // 一定要加这个auto!!!!!!!要了命了
msg.a=1;
msg.b=2.3;
msg.c="5.6";
publisher_->publish(msg);// 发布话题消息
RCLCPP_INFO(this->get_logger(), "finished");// 输出日志信息,提示已经完成话题发布
}
rclcpp::TimerBase::SharedPtr timer_; // 定时器指针
rclcpp::Publisher<msg_test::msg::Test>::SharedPtr publisher_; // 发布者指针
};
// ROS2节点主入口main函数
int main(int argc, char * argv[]){
rclcpp::init(argc, argv); // ROS2 C++接口初始化
rclcpp::spin(std::make_shared<PublisherNode>()); // 创建ROS2节点对象并进行初始化
rclcpp::shutdown(); // 关闭ROS2 C++接口
return 0;
}
效果:
python:
开头引用:
from <功能包名>.msg import <msg文件名>
# 这里什么时候加".msg"什么时候不加别记错了
完整测试代码:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import rclpy # ROS2 Python接口库
from rclpy.node import Node # ROS2 节点类
from msg_test.msg import Test
class PublisherNode(Node):
def __init__(self, name):
super().__init__(name) # ROS2节点父类初始化
self.pub = self.create_publisher(Test, "chatter", 10) # 创建发布者对象(消息类型、话题名、队列长度)
self.timer = self.create_timer(0.5, self.timer_callback) # 创建一个定时器(单位为秒的周期,定时执行的回调函数)
def timer_callback(self): # 创建定时器周期执行的回调函数
msg = Test() # 创建一个Test类型的消息对象
msg.a=1
msg.b=2.3
msg.c="5.6"
self.pub.publish(msg) # 发布话题消息
self.get_logger().info("finish") # 输出日志信息,提示已经完成话题发布
def main(args=None): # ROS2节点主入口main函数
rclpy.init(args=args) # ROS2 Python接口初始化
node = PublisherNode("topic_pub") # 创建ROS2节点对象并进行初始化
rclpy.spin(node) # 循环等待ROS2退出
node.destroy_node() # 销毁节点对象
rclpy.shutdown() # 关闭ROS2 Python接口
效果: