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

LCM中间件入门(1):工作原理核心概念及Ubuntu环境下的C++实践

文章目录

        • 一、LCM中间件简介
        • 二、基本工作原理与核心概念
        • 三、Ubuntu下安装LCM
        • 四、C++使用示例
          • 1. 定义消息类型(`.lcm`文件)
          • 2. 生成C++代码
          • 3. 发布者代码(publisher.cpp)
          • 4. 订阅者代码(subscriber.cpp)
          • 5. 编译与运行
        • 五、总结

一、LCM中间件简介

LCM(Lightweight Communications and Marshalling)是一款轻量级通信与编组中间件,专为实时系统设计,尤其适用于机器人、自动驾驶、航空航天等对低延迟、高可靠性有要求的领域。其核心优势在于轻量化设计(无集中式服务器)、高效数据传输(基于UDP组播)和跨语言支持(C/C++、Python、Java等),能轻松实现多进程/多设备间的实时数据交互。

二、基本工作原理与核心概念
  1. 通信模型
    LCM采用发布-订阅(Publish-Subscribe)模式

    • 发布者(Publisher):向指定“通道(Channel)”发送消息。
    • 订阅者(Subscriber):监听感兴趣的“通道”,接收并处理消息。
    • 通道(Channel):字符串标识的消息传输路径(类似“话题”),用于区分不同类型的消息。
  2. 数据编组(Marshalling)
    LCM通过自定义消息类型实现跨平台数据传输。用户需定义.lcm格式的消息结构,工具会自动生成对应语言的编解码代码,解决不同设备/语言间的数据格式差异(如大小端、数据类型长度)。

  3. 传输机制
    基于UDP组播实现消息广播,支持同一网络内的多节点通信,无需中心节点转发,减少延迟。同时支持单播模式,适用于点对点通信。

三、Ubuntu下安装LCM
  1. 通过包管理器安装(推荐)
    适用于Ubuntu 18.04及以上版本:

    sudo apt update
    sudo apt install liblcm-dev
    
  2. 源码编译安装
    若需最新版本,可从源码编译:

    # 安装依赖
    sudo apt install build-essential cmake libglib2.0-dev# 克隆源码
    git clone https://github.com/lcm-proj/lcm.git
    cd lcm# 编译安装
    mkdir build && cd build
    cmake ..
    make -j4
    sudo make install
    
  3. 验证安装
    执行以下命令,若输出版本信息则安装成功:

    lcm-gen --version
    
四、C++使用示例

以下通过“温度传感器数据传输”案例,展示LCM的完整使用流程。

1. 定义消息类型(.lcm文件)

创建temperature.lcm,定义温度消息结构:

package example;  // 消息包名struct Temperature {int64_t timestamp;  // 时间戳(毫秒)float value;        // 温度值(摄氏度)string sensor_id;   // 传感器ID
}
2. 生成C++代码

使用lcm-gen工具将.lcm文件转换为C++代码:

lcm-gen -x temperature.lcm  # -x 表示生成C++代码

执行后会生成example/Temperature.hpp文件,包含消息的结构体定义和编解码逻辑。

3. 发布者代码(publisher.cpp)
#include <lcm/lcm-cpp.hpp>
#include "example/Temperature.hpp"
#include <chrono>
#include <thread>int main() {// 创建LCM实例(自动绑定网络)lcm::LCM lcm;if (!lcm.good()) {std::cerr << "LCM初始化失败!" << std::endl;return 1;}// 构造消息example::Temperature msg;msg.timestamp = 0;msg.sensor_id = "sensor_001";// 循环发布消息(模拟传感器数据)while (true) {msg.timestamp = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count();msg.value = 25.0 + (rand() % 100) / 10.0;  // 随机温度值(25.0~35.0℃)// 向通道"THERMOMETER"发布消息lcm.publish("THERMOMETER", &msg);std::cout << "发布温度: " << msg.value << "℃(时间戳: " << msg.timestamp << ")" << std::endl;std::this_thread::sleep_for(std::chrono::seconds(1));  // 每秒发布一次}return 0;
}
4. 订阅者代码(subscriber.cpp)
#include <lcm/lcm-cpp.hpp>
#include "example/Temperature.hpp"
#include <iostream>// 消息处理类(继承自消息对应的Listener)
class TemperatureHandler {
public:// 回调函数:接收消息时自动调用void handleMessage(const lcm::ReceiveBuffer* rbuf,const std::string& channel,const example::Temperature* msg) {std::cout << "\n收到通道 [" << channel << "] 的消息:" << std::endl;std::cout << "传感器ID: " << msg->sensor_id << std::endl;std::cout << "温度值: " << msg->value << "℃" << std::endl;std::cout << "时间戳: " << msg->timestamp << "ms" << std::endl;}
};int main() {lcm::LCM lcm;if (!lcm.good()) {std::cerr << "LCM初始化失败!" << std::endl;return 1;}// 创建消息处理器并订阅通道"THERMOMETER"TemperatureHandler handler;lcm.subscribe("THERMOMETER", &TemperatureHandler::handleMessage, &handler);std::cout << "等待接收温度数据..." << std::endl;while (true) {lcm.handle();  // 阻塞等待消息,收到后调用回调函数}return 0;
}
5. 编译与运行

创建CMakeLists.txt

cmake_minimum_required(VERSION 3.10)
project(lcm_example)# -------------------------- 手动指定 LCM 路径 --------------------------
# 替换为你的 LCM 头文件实际路径(根据上面的查询结果修改)
set(LCM_INCLUDE_DIR "/usr/include/lcm")  # 包管理器安装
# set(LCM_INCLUDE_DIR "/usr/local/include/lcm")  # 源码安装# 替换为你的 LCM 库文件实际路径(根据上面的查询结果修改)
set(LCM_LIB_DIR "/usr/lib/x86_64-linux-gnu")  # 包管理器安装
# set(LCM_LIB_DIR "/usr/local/lib")  # 源码安装# 指定 LCM 库文件名(通常是 liblcm.so,去掉前缀 "lib" 和后缀 ".so" 即为库名)
set(LCM_LIB "lcm")
# ----------------------------------------------------------------------# 引入 LCM 头文件
include_directories(${LCM_INCLUDE_DIR} ${CMAKE_CURRENT_BINARY_DIR})# 引入 LCM 库文件路径
link_directories(${LCM_LIB_DIR})# 编译发布者和订阅者,并链接 LCM 库
add_executable(publisher publisher.cpp example/Temperature.hpp)
target_link_libraries(publisher ${LCM_LIB})add_executable(subscriber subscriber.cpp example/Temperature.hpp)
target_link_libraries(subscriber ${LCM_LIB})

编译并运行:

# 编译
mkdir build && cd build
cmake ..
make# 打开两个终端,分别运行
./subscriber  # 订阅者
./publisher   # 发布者

运行后,订阅者会实时接收并打印发布者发送的温度数据。

五、总结

LCM凭借轻量化、低延迟的特性,在实时系统通信中占据重要地位。其核心是通过发布-订阅模式和自定义消息类型,实现跨进程/跨设备的高效数据交互。在Ubuntu环境下,通过简单的安装和代码生成流程,即可快速集成到C++项目中,特别适合机器人、无人机等领域的实时数据传输需求。

http://www.lryc.cn/news/605504.html

相关文章:

  • 【Debian】4-‌2 Gitea搭建
  • Git踩坑
  • windows服务器 maven 配置环境变量,验证maven环境变量是否配置成功
  • es的histogram直方图聚合和terms分组聚合
  • Ubuntu/Debian 搭建 Nginx RTMP 服务器全攻略
  • [Broken IOS] 配置CLI | 终端用户界面TUI
  • 分布式ID方案(标记)
  • 【Linux】linux基础开发工具(二) 编译器gcc/g++、动静态库感性认识、自动化构建-make/Makefile
  • BasicAuthenticationFilter处理 HTTP 基本认证(Basic Authentication)的核心过滤器详解
  • 打破数据质量瓶颈:用n8n实现30秒专业数据质量报告自动化
  • 50天50个小项目 (Vue3 + Tailwindcss V4) ✨ | LiveUserFilter(实时用户过滤组件)
  • ensp安全策略实验
  • 【工具】NVM完全指南:Node.js版本管理工具的安装与使用详解
  • 嵌入式仿真教学的革新力量:深圳航天科技创新研究院引领高效学习新时代
  • 【n8n】如何跟着AI学习n8n【03】:HTTPRequest节点、Webhook节点、SMTP节点、mysql节点
  • 从“碎片化”到“完美重组”:IP报文的分片艺术
  • mysql笔记02:DML插入、更新、删除数据
  • 【读书笔记】Design Patterns (1994)✅
  • 微软发布Microsoft Sentinel数据湖国际版
  • JVM之【Java虚拟机概述】
  • Python实现调整矩阵维度: view
  • 【13】大恒相机SDK C#开发 —— Fom1中实时处理的8个图像 实时显示在Form2界面的 pictureBox中
  • 磁盘坏道检测工具在美国服务器硬件维护中的使用规范
  • MVS相机+YOLO检测方法
  • 【03】大恒相机SDK C#开发 —— 回调采集图像,关闭相机
  • Java WEB技术-序列化和反序列化认识(SpringBoot的Jackson序列化行为?如何打破序列化过程的驼峰规则?如何解决学序列化循环引用问题?)
  • 学习笔记《区块链技术与应用》第三天 网络 难度
  • 详解分布式数据库缓存技术:高性能数据访问的基石
  • 如何在 macOS 上使用 dnsmasq 搭建本地 DNS 缓存/转发
  • 深度解析:基于Python构建的闲鱼自动化营销与信息发送机器人