当前位置: 首页 > news >正文

ros通信机制学习——latched持久化机制

点云的地图的发送逻辑中,我发现每次使用rostopic echo 时只会打印一次,然后就不会再打印了。并且rviz中也是始终都会显示的,这里面其实就是用到了latched持久话机制,可以接受这最后一次发布的消息。
我们通过一个具体的项目来学习和认识这个过程

latched话题:

你创建的发布者使用了 latching(持久化)机制 (advertise<sensor_msgs::PointCloud2>(map_topic, 10, true) 中的 true 参数)。Latching 意味着最后一次发布的信息会被保存下来,新的订阅者连接时会立即接收到这条消息。因此,每当一个新的订阅者(如 rostopic echo)连接到这个话题时,它都会立即接收到那条被 latched 的消息。
源码信息:
头文件

#ifndef _MAP_LOADER_HPP_
#define _MAP_LOADER_HPP_

#include <pcl/point_cloud.h>
#include <pcl/point_types.h>
#include <pcl/filters/voxel_grid.h>
#include <pcl_conversions/pcl_conversions.h>
#include <ros/ros.h>
#include <sensor_msgs/Imu.h>
#include <sensor_msgs/PointCloud2.h>
#include <vector>
#include <pcl_ros/transforms.h>

using namespace std;

class MapLoader {
public:
    ros::Publisher pc_map_pub_;
    vector<string> file_list_;

    MapLoader(ros::NodeHandle &nh);

private:
    sensor_msgs::PointCloud2 CreatePcd();
};

#endif

map_load.cpp

#include <map_load/map_load.h>

using namespace std;

MapLoader::MapLoader(ros::NodeHandle &nh){
    std::string pcd_file, map_topic;
    nh.param<string>("pcd_path", pcd_file_path, "");
    nh.param<string>("map_topic", map_topic, "point_map");

    pc_map_pub = nh.advertise<sensor_msgs::PointCloud2>(map_topic, 10, true);
	//latched话题:创建的发布者使用了 latching(持久化)机制 
    // (advertise<sensor_msgs::PointCloud2>(map_topic, 10, true) 中的 true 参数)
    // Latching 意味着最后一次发布的信息会被保存下来,新的订阅者连接时会立即接收到这条消息。
    // 每当一个新的订阅者(如 rostopic echo)连接到这个话题时,它都会立即接收到那条被 latched 的消息

    file_list_.push_back(pcd_file_path);

    auto pc_msg = CreatePcd();
    cout << "pc_msg.width" << "\n" << pc_msg.width << endl;

    if (pc_msg.width != 0) {
        pc_msg.header.frame_id = "map";
        pc_map_pub_.publish(pc_msg);
    }

}

sensor_msgs::PointCloud2 MapLoader::CreatePcd() {
    sensor_msgs::PointCloud2 pc_msg;
    pcl::PointCloud<pcl::PointXYZ> pcd, part;
    int pcd_width = 0;
    for (const string& path : file_list_) {
        if (pcd_width == 0) {
            if (pcl::io::loadPCDFile(path.c_str(), pcd) == -1) {
                cerr << "load failed " << path << endl;
            }
        }
        else {
            if (pcl::io::loadPCDFile(path.c_str(), part) == -1) {
                cerr << "load failed " << path << endl;
            }
            pcd.width += part.width;
            pcd.row_step += part.row_step;
            pcd.data.insert(pcd.data.end(), part.data.begin(), part.data.end());
        }
        cerr << " load " << path << endl;
        if (!ros::ok()) break;
    }

    return pcd;
}

int main(int argc, char** argv) {
    ros::init(argc, argv, "map_loader");
    ROS_INFO("\033[32m ---> \033[0m Map Loader Started.");
    ros::NodeHandle nh;

    ros::spin();
    return 0;
}

然后我们看launch文件中的传参

<launch>
    
    <!--- Sim Time -->
    <param name="/use_sim_time" value="false" />

    <!--- Run Rviz-->
    <!-- <node pkg="rviz" type="rviz" name="rviz" args="-d $(find map_load)/rviz/map_show.rviz" /> -->

    <!--- MapLoader -->    
    <arg name="pcd_path"  default="$(find map_load)/map/map_Statistical_filter.pcd"/>
    <arg name="map_topic" default="point_map"/>

    <node pkg="map_load" type="mapload"    name="mapLoader"    output="screen">
        <param name="pcd_path" value="$(arg pcd_path)"/>
        <param name="map_topic" value="$(arg map_topic)"/>
    </node>

</launch>

主要就是两个参数,一个是pcd的路径,一个是map发布的话题运行后:
在这里插入图片描述
此时可以查看一下话题的发布情况,可以看到

rostopic list
rostopic hz /mapLoader/point_map

在这里插入图片描述
所以就是没有数据在这里发布,也就不会占用带宽.我们卻是可以打印出来的:
在这里插入图片描述
在这里插入图片描述
rviz中也是可以显示出对应的点云地图的,这个方式非常适合那些不会变化的数据的内容.
我们从原理上深入分析一下:

ROS Publisher Latch 机制详解

1. 核心含义

  • ​功能定义​​:
    latch=true 启用​​持久化消息​​机制,发布者会缓存最后一次发送的消息。
  • ​核心作用​​:
    新订阅者连接到话题时,​​立即收到缓存的最后一条消息​​,无需等待下一次发布。

2. 底层机制

机制说明
消息存储ROS内部维护一个长度为1的队列,仅保留最新消息
触发条件新订阅者通过 ros::Subscriber 连接时触发
生命周期缓存消息保留至新消息发布或节点关闭

3. 适用场景

场景1:静态数据发布(如地图)

// 只需加载一次,新节点需立即获取
pc_map_pub_ = nh.advertise<sensor_msgs::PointCloud2>("map", 10, true);

场景2:低频更新数据(如初始位姿)

// 新的GUI模块启动后需立刻显示当前位置
pose_pub_ = nh.advertise<geometry_msgs::PoseStamped>("initial_pose", 1, true);

场景3:服务类数据(如全局路径)

// 控制模块可能稍后启动,需确保其能获取路径
path_pub_ = nh.advertise<nav_msgs::Path>("global_plan", 1, true);

4. 禁用 Latch 的对比

// 默认行为:latch=false
pc_map_pub_ = nh.advertise<sensor_msgs::PointCloud2>("map", 10); 

新订阅者体验 立即收到最后消息 必须等待下次 publish() 调用
数据连续性 适合单次发布场景 需要持续发布维持数据流

5. 实际效果验证

# 终端1:发布地图(仅一次)
rosrun map_loader map_loader _pcd_path:=/home/user/map.pcd

# 终端2:查看话题
rostopic echo /map  # 立即显示数据
# 禁用 Latch 时的表现
rostopic echo /map  # 无输出,直到再次调用 publish()

6注意事项

  • List item

​​内存管理​​

大消息(如10万+点云)会持续占用内存,需评估消息大小

  • ​​ROS 2 对应机制​​
    通过QoS策略实现:
// ROS 2 等效实现
auto qos = rclcpp::QoS(10).durability(RMW_QOS_POLICY_DURABILITY_TRANSIENT_LOCAL);
pc_map_pub_ = node->create_publisher<sensor_msgs::msg::PointCloud2>("map", qos);
  1. 最佳实践指南

ROS Publisher Latch 参数对比表

​对比维度​latch=true (持久化)latch=false (非持久化,默认)
​新订阅者连接行为​立即收到最后一次发布的消息必须等待下一次 publish() 调用
​消息存储机制​ROS内部维护长度为1的队列,保留最新消息不存储任何历史消息
​适用数据类型​静态数据(地图/参数)、低频更新数据(路径/位姿)高频动态数据(激光/图像/IMU)
​内存占用​存储完整消息副本(需注意大消息内存消耗)无额外占用
​典型场景​初始化配置、服务类结果、需即时同步的全局数据实时数据流、连续状态更新
​调试验证方法​rostopic info /topic 显示 LATCH: truerostopic echo /topic 只在发布后显示新数据
​队列机制​固定队列长度=1(强制保留最新消息)队列长度由 advertise() 的第二个参数定义
​ROS 2 等效实现​DurabilityPolicy::TRANSIENT_LOCALDurabilityPolicy::VOLATILE
​典型代码示例​pub = nh.advertise<MapMsg>("map", 10, true);pub = nh.advertise<LaserScan>("scan", 10);
​数据更新影响​新消息会覆盖缓存,后续订阅者收到最新版本旧订阅者按队列长度接收历史消息,新订阅者只收新消息

相关文章:

  • 【深度学习基础】——机器的神经元:感知机
  • 提示工程指南学习记录(二)
  • 东方博宜OJ ——1335 - 土地分割
  • IDEA的常用设置(更新中......)
  • 云原生(Cloud Native)的详解、开发流程及同类软件对比
  • [ComfyUI] 最新控制模型EasyControl,吉卜力风格一键转绘
  • 08【基础学习】串口通信(三):收发数据包+数据校验
  • 某公司网络OSPF单区域配置
  • 作业帮前端面试题及参考答案 (100道面试题-上)
  • 交易所开发全流程解析:KYC与U盾在安全合规中的战略价值
  • 基于Ubuntu系统搭建51单片机开发环境的详细教程
  • Auto-Encoder --李宏毅机器学习笔记
  • 视觉算法+雾炮联动:开创智能降尘新时代
  • 基于unsloth微调大模型并上传到huggingface
  • zephyr RTOS 中 bt_le_adv_start函数的功能应用
  • 基础知识:离线安装docker、docker compose
  • Docker 代理配置全攻略:从入门到企业级实践
  • iOS设备文件管理实践
  • 【数据分享】1981-2024年全国各城市逐日、逐月、逐年平均气温(Shp格式)
  • 高性能内存kv数据库Redis
  • 国际市场开心果价格上涨35%,背后助力是一条点击过亿的短视频
  • 对话|棋后居文君:创造历史之后,还有继续追梦的心
  • 财政部:一季度证券交易印花税411亿元,同比增长60.6%
  • 吉林省文联党组书记、主席赵明接受纪律审查和监察调查
  • 推动行业健康发展,上海发布医药企业防范商业贿赂案例手册
  • 别把癌症当鼻炎,爱吃这类食物的人,尤其要警惕