之前的文章:Ubuntu20安装ROS2-FoxyFitzroy与C++基础测试,介绍了ROS2的安装和ROS2的C++基础编程示例,本篇来继续介绍ROS2的话题发布功能,并测试发布自定义的数据。
1 创建自定义消息的包
1.1 创建test_msg包
cd ~/dev_ws/src
ros2 pkg create --build-type ament_cmake test_msg
1.2 自定义msg
cd test_msg
mkdir msg
新建文件 msg/PersonInfo.msg,写入内容
# 自定义结构体一样的消息
string name
int32 age
float32 height
bool is_student
等价于 C++ 结构体
struct PersonInfo{
std::string name;
int32_t age;
float height;
bool is_student;
};
1.3 修改package.xml
修改 package.xml的消息生成依赖,增加这3行
<buildtool_depend>rosidl_default_generators</buildtool_depend>
<exec_depend>rosidl_default_runtime</exec_depend>
<member_of_group>rosidl_interface_packages</member_of_group>
1.4 修改 CMakeLists.txt
在文件末尾,`ament_package()之前添加消息生成代码
find_package(rosidl_default_generators REQUIRED)
rosidl_generate_interfaces(${PROJECT_NAME}
"msg/PersonInfo.msg"
)
ament_export_dependencies(rosidl_default_runtime)
2 创建发布节点的包
2.1 创建test_02_publish
该包依赖rclcpp和自定义的test_msg
cd ~/dev_ws/src
ros2 pkg create --build-type ament_cmake test_02_publish --dependencies rclcpp test_msg
cd test_02_publish
2.2 编写代码
src中创建person_publisher.cpp
测试代码如下:
#include "rclcpp/rclcpp.hpp"
#include "test_msg/msg/person_info.hpp"
using namespace std::chrono_literals;
class PersonInfoPublisher : public rclcpp::Node
{
public:
PersonInfoPublisher() : Node("person_publisher_node")
{
// 创建发布器,话题名 /person_info,消息类型 test_msg::msg::PersonInfo,队列10
publisher_ = this->create_publisher<test_msg::msg::PersonInfo>("/person_info", 10);
// 定时器 500ms 发布一次
timer_ = this->create_wall_timer(500ms, std::bind(&PersonInfoPublisher::timer_callback, this));
RCLCPP_INFO(this->get_logger(), "自定义消息发布节点启动");
}
private:
void timer_callback()
{
auto msg = test_msg::msg::PersonInfo();
msg.name = "zhangsan";
msg.age = 22;
msg.height = 1.75f;
RCLCPP_INFO(this->get_logger(), "发布: name=%s, age=%d, height=%.2f",
msg.name.c_str(), msg.age, msg.height);
publisher_->publish(msg);
}
rclcpp::Publisher<test_msg::msg::PersonInfo>::SharedPtr publisher_;
rclcpp::TimerBase::SharedPtr timer_;
};
int main(int argc, char * argv[])
{
rclcpp::init(argc, argv);
rclcpp::spin(std::make_shared<PersonInfoPublisher>());
rclcpp::shutdown();
return 0;
}
2.2.1 代码说明
-
- PersonInfoPublisher构造函数中,会创建发布器
publisher_
-
- 和定时器
timer_
-
-
- 发布器的话题名是
-
/person_info
-
-
- ,消息类型
-
test_msg::msg::PersonInfo
-
-
- ,队列10定时器周期500ms,注册回调函数
-
timer_callback
回调函数中,发布器publisher_发布自定义的PersonInfo数据
2.2.2 发布器的写法
// 发布器声明
rclcpp::Publisher<test_msg::msg::PersonInfo>::SharedPtr publisher_;
// 创建发布器,话题名 /person_info,消息类型 test_msg::msg::PersonInfo,队列10
publisher_ = this->create_publisher<test_msg::msg::PersonInfo>("/person_info", 10);
// 发布数据
auto msg = test_msg::msg::PersonInfo();
msg.name = "zhangsan";
msg.age = 22;
msg.height = 1.75f;
RCLCPP_INFO(this->get_logger(), "发布: name=%s, age=%d, height=%.2f",msg.name.c_str(), msg.age, msg.height);
publisher_->publish(msg);
2.3 修改package.xml
ros2 pkg create 已经自动添加 rclcpp、test_msg 依赖,确认存在即可
<buildtool_depend>ament_cmake</buildtool_depend>
<depend>rclcpp</depend>
<depend>test_msg</depend>
2.4 修改 CMakeLists.txt
test_02_publish/CMakeLists 增加下面这些内容
# 编译可执行文件
add_executable(person_publisher src/person_publisher.cpp)
ament_target_dependencies(person_publisher rclcpp test_msg)
# 安装
install(TARGETS
person_publisher
DESTINATION lib/${PROJECT_NAME}
)
3 编译
3.1 代码目录结构
可以先看到代码的目录结构
3.2 编译
cd ~/dev_ws
colcon build --packages-select test_msg test_02_publish
4 运行
4.1 运行数据发布程序
在终端 1中运行发布节点
source install/setup.bash
ros2 run test_02_publish person_publisher
4.2 ros2指令监听话题
新开终端 2,监听话题验证
source ~/dev_ws/install/setup.bash
ros2 topic echo /person_info
5 关于自定义消息的头文件的生成
ROS2 的 rosidl 生成器,对于驼峰命名 PersonInfo.msg,生成的头文件是 person_info.hpp
转换逻辑是:
输入格式:.msg 源文件必须位于包的 msg/ 目录下,文件名通常采用大驼峰命名法(PascalCase),如 MyMessage.msg。
大小写处理:生成器自动将文件名中的大写字母转换为全小写。
分隔符处理:原文件名中的大写字母边界处插入下划线_(即驼峰转蛇形),若原文件名已含下划线则保留。
后缀替换:将 .msg 后缀替换为 **.hpp**。
最终路径:头文件安装在 <package_name>/msg/<converted_name>.hpp
去对应目录看,可以看到 person_info.hpp的内容,它实际又是引用的 person_info__struct.hpp
再继续看,实际是定义的PersonInfo_类
然后通过using PersonInfo = test_msg::msg::PersonInfo_<std::allocator<void>>;对外展示为PersonInfo
6 总结
本篇介绍了ROS2中发布器的简单使用,使用C++编程,创建自定义话题的数据结构,在定时器回调函数中,发布器发布自定义的数据,再通过ros2指令监听话题来验证发布的数据
117