LCM库的简单使用

windows 10 系统LCM通信库的编译 LCM是Lightweight Communications and Marshalling 的简称,是一个轻量级的通信与编组库。LCM内部封装了UDP,可以满足实时系统通信中高带宽,低延迟的要求。一般情况下,LCM在Ubuntu等Linux系统中使用的比较多,但是由于一些 众所不知的原因,我决定在Windows 10 64bit系统下搞一搞这个东西。 1. 资源准备 1.1 LCM下载 我下载的... 阅读详情

机器人软件系统中使用的通讯框架多种多样。比如,百度Apollo使用的Cyber RT,ROS1中的TCPROS/UDPROS通信机制,ROS2中使用的DDS等等。

下面介绍一种轻量,易用的通讯框架LCM(Lightweight Communications and Marshalling)。

LCM是一套用于消息传递和数据编码的库和工具,目标是构建高带宽和低延的实时通讯系统。它提供了一个发布/订阅消息传递模型和自动编码/解码代码的生成器。

LCM为多种编程语言(C/C++,C#,Java,Lua,MATLAB,Python)的应用提供接口。

LCM具有如下特性:

  • 低延迟的进程间通信
  • 使用UDP组播的高效广播机制
  • 类型安全的消息编排
  • 用户友好的记录和回放工具
  • 没有集中的 "数据库 "或 “枢纽”–节点间直接通讯
  • 没有守护进程
  • 极少的依赖

参考:

https://lcm-proj.github.io/

安装LCM

安装编译依赖

sudo apt-get install build-essential autoconf automake autopoint libglib2.0-dev libtool openjdk-8-jdk python-dev

编译安装

mkdir build
cd build
cmake ..
make
sudo make install

增加动态库链接地址

export LCM_INSTALL_DIR=/usr/local/lib
echo $LCM_INSTALL_DIR > /etc/ld.so.conf.d/lcm.conf
sudo ldconfig

定义通讯数据结构

LCM库通过编写lcm文件来定义通讯数据结构。下面是一个针对C++的示例。

新建example_t.lcm 文件,并拷贝下面的内容到文件中。

package exlcm;
struct example_t
{
    int64_t  timestamp;
    double   position[3];
    double   orientation[4]; 
    int32_t  num_ranges;
    int16_t  ranges[num_ranges];
    string   name;
    boolean  enabled;
}

执行下面的命令生成头文件

lcm-gen -x example_t.lcm

同一个lcm文件里可以写多个数据结构。如下所示:

package exlcm;
struct example_t
{
    int64_t  timestamp;
    double   position[3];
    double   orientation[4]; 
    int32_t  num_ranges;
    int16_t  ranges[num_ranges];
    string   name;
    boolean  enabled;
}

struct nihao_t
{
    int64_t  timest2amp;
    string   name1;
    boolean  enabl1ed;
}

执行lcm-gen后会为每一个结构体生成一个头文件。

示例来源于:

https://lcm-proj.github.io/tut_lcmgen.html

简单的使用示例

发送代码示例

// file: send_message.cpp
//
// LCM example program.
//
// compile with:
//  $ g++ -o send_message send_message.cpp -llcm
//
// On a system with pkg-config, you can also use:
//  $ g++ -o send_message send_message.cpp `pkg-config --cflags --libs lcm`

#include <lcm/lcm-cpp.hpp>

#include "exlcm/example_t.hpp"

int main(int argc, char **argv)
{
    lcm::LCM lcm;
    if (!lcm.good())
        return 1;

    exlcm::example_t my_data;
    my_data.timestamp = 0;

    my_data.position[0] = 1;
    my_data.position[1] = 2;
    my_data.position[2] = 3;

    my_data.orientation[0] = 1;
    my_data.orientation[1] = 0;
    my_data.orientation[2] = 0;
    my_data.orientation[3] = 0;

    my_data.num_ranges = 15;
    my_data.ranges.resize(my_data.num_ranges);
    for (int i = 0; i < my_data.num_ranges; i++)
        my_data.ranges[i] = i;

    my_data.name = "example string";
    my_data.enabled = true;

    lcm.publish("EXAMPLE", &my_data);

    return 0;
}

接受代码示例

// file: listener.cpp
//
// LCM example program.
//
// compile with:
//  $ gcc -o listener listener.cpp -llcm
//
// On a system with pkg-config, you can also use:
//  $ gcc -o listener listener.cpp `pkg-config --cflags --libs lcm`

#include <stdio.h>

#include <lcm/lcm-cpp.hpp>
#include "exlcm/example_t.hpp"

class Handler {
  public:
    ~Handler() {}
    void handleMessage(const lcm::ReceiveBuffer *rbuf, const std::string &chan,
                       const exlcm::example_t *msg)
    {
        int i;
        printf("Received message on channel \\"%s\\":\\n", chan.c_str());
        printf("  timestamp   = %lld\\n", (long long) msg->timestamp);
        printf("  position    = (%f, %f, %f)\\n", msg->position[0], msg->position[1],
               msg->position[2]);
        printf("  orientation = (%f, %f, %f, %f)\\n", msg->orientation[0], msg->orientation[1],
               msg->orientation[2], msg->orientation[3]);
        printf("  ranges:");
        for (i = 0; i < msg->num_ranges; i++)
            printf(" %d", msg->ranges[i]);
        printf("\\n");
        printf("  name        = '%s'\\n", msg->name.c_str());
        printf("  enabled     = %d\\n", msg->enabled);
    }
};

int main(int argc, char **argv)
{
    lcm::LCM lcm;

    if (!lcm.good())
        return 1;

    Handler handlerObject;
    lcm.subscribe("EXAMPLE", &Handler::handleMessage, &handlerObject);

    while (0 == lcm.handle()) {
        // Do nothing
    }

    return 0;
}

CMakeList.txt 的写法

下面的写法是通用的,也适用于ROS1

find_package(lcm REQUIRED)
include(${LCM_USE_FILE})
target_link_libraries(${PROJECT_NAME}
  lcm
)

下面的写法适用于ROS2

set(dependencies
  "geometry_msgs"
  "nav_msgs"
  "rclcpp"
  "sensor_msgs"
  "tf2"
  "tf2_msgs"
  "OpenCV"
  "PCL"
  # "lcm"   #不要在ament_target_dependencies中加入lcm,不起作用的
  "cv_bridge"
  "image_transport"
)

ament_target_dependencies(${EXEC_NAME} ${dependencies} )  

# 不加的话会报undefined reference to `lcm_destroy' 
target_link_libraries(${EXEC_NAME} lcm)     # 使用target_link_libraries添加lcm依赖

处理回调

lcm用handle()函数来处理消息回调(接受到消息后就执行回调函数)。

lcm.handle() 是阻塞的。只能放到单独的线程里执行。

lcm.handleTimeout(10) 可以超时后返回,然后执行后面的代码。设置的时间的单位是毫秒。

进程间通讯

当需要通信的进程分别在两台机器里时,需要设置如下环境变量(两台电脑命令行窗口都运行这条)。

export LCM_DEFAULT_URL=udpm://239.255.76.67:7667?ttl=1

如果需要通信的两个进程在同一台主机上则不需要运行上面的命令。

如果需要在两个docker间实现通信,需要在同一网络下启动这两个容器。

#以相同的网络启动容器
docker run -it --name test_docker0 --network nat shoufei/kinetic:latest /bin/bash

docker run -it --name test_docker1 --network nat shoufei/kinetic:latest /bin/bash

注意上面的两个docker启动命令均添加了--network nat参数。其中nat是用下面的命令建立的网络接口。

docker network create nat

注意,docker中也需要执行上面设置环境变量的命令。

注意事项

  1. 当数据结构定义的是数组时,生成的头文件中会用vector来定义这个数据。进行赋值时需要先 resize vector 的长度。不然会填充数据时会报错。
void TestNode::test_tof_callback(
  const sensor_msgs::msg::PointCloud2::SharedPtr msg)
{
  testlcm::tof_points_t data;
  
  size_t size = msg->height * msg->width;

  pcl::PCLPointCloud2 pcl_pc2;
  pcl_conversions::toPCL(*msg,pcl_pc2);
  pcl::PointCloud<pcl::PointXYZ>::Ptr temp_cloud(new pcl::PointCloud<pcl::PointXYZ>);
  pcl::fromPCLPointCloud2(pcl_pc2,*temp_cloud);

  data.timestamp = msg->header.stamp.nanosec * 0.001;
  data.num_points = size;
  data.xs.resize(data.num_points);//当数据结构定义的是数组时,生成的头文件中会用vector来定义这个数据。进行赋值时需要先resize vector的长度。不然会填充数据时会报错。
  data.ys.resize(data.num_points);
  data.zs.resize(data.num_points);
  for(uint32_t i = 0; i < size; ++i)
  {
      data.xs[i] = temp_cloud->points[i].x;
      data.ys[i] = temp_cloud->points[i].y;
      data.zs[i] = temp_cloud->points[i].z;
  }
  RCLCPP_INFO(this->get_logger(), "got test tof points");
  lcm.publish(REAR_TOF_POINTS_MSG, &data);
}

参考:

https://lcm-proj.github.io/index.html

http://lcm-proj.github.io/multicast_setup.html


觉得有用就点赞吧!

我是首飞,一个帮大家填坑的机器人开发攻城狮。

另外在公众号《首飞》内回复“机器人”获取精心推荐的C/C++,Python,Docker,Qt,ROS1/2等机器人行业常用技术资料。

一次成功流水账-安装LCM 多机通信 lcm-spy数据实时可视化 主要步骤:1. 安装LCM2. 使用CMake组织工程并编译1. 安装依赖,使用的是Ubuntu16.04的环境 2. 下载、编译并安装 2. 使用CMake组织工程并跑通通信示例生成头文件:创建 lcm_test 文件夹,新建example_t.lcm文件,内容如下: 打开 lcm_test 文件夹,运行 命令生成消息类型,成功运行后会生成 exlcm 文件夹,文件夹中有example_t.hpp的头文件。若没有识别命令,则需要检查是否成功安装 lcm,或是否将 lcm 编译结果添加进环境 阅读详情

相关推荐

LCM库——LCM Type Language分析(一)

/它由emit_encode生成,首先生成一个计算int64_t的哈希值的代码,然后通过emit_encode_nohash递归生成代码去调用每个成员变量的encode函数。当成员变量是普通成员变量时,将其视为长度为1的定长数组。如果是primitive类型,直接调用lcm_coretypes中的encode函数。当它是数组时,将会通过N层循环encode每一个数组元素。

曾经也曾立志 1133

初试LCM

LCM is a set of libraries and tools for message passing and data marshalling,被广泛使用与无人车通信。其官方文档地址为:http://lcm-proj.github.io/这里我们不讲安装,我们只讲使用。(安装在文档中都写有)http://lcm-proj.github.io/build_instructions.html初

RegretPain的博客 1万+

自动驾驶消息传输机制LCM的安装与使用

自动驾驶消息传输机制LCM的安装与使用背景安装使用教程(C++)lcm数据类型定义发送消息接收消息发送-接收消息lcm-log数据解析 背景 自动驾驶领域有很多进程间通信的方式,如ROS、Apollo的Cyber RT… 以及一些自动驾驶初创公司对ROS进行改进的通信协议,今天介绍一种适用于高速自动驾驶场景的LCM通信协议,其特点是轻量化、传输速度快,易封装。 LCM(Lightweight C...

snail_zcx的博客 5291

LCM通信库的安装及使用

一. 安装 1. Ubuntu # 安装依赖 # 必选 sudo apt install build-essential libglib2.0-dev cmake # 可选,可根据使用的语言选择安装 sudo apt install default-jdk python-all-dev liblua5.1-dev golang doxygen # 拷贝源码 git clone https://github.com/lcm-proj/lcm.git cd lcm # 编译并安装 mkdir build &am

Qrpucp的博客 1万+

LCM中C++的API介绍

LCM支持多种语言,也有很多版本,这里只介绍C++的几个类以及方法。类型简介C++的API,LC提供了三个类以及两个结构体来封装LCM,他们分别是: class lcm::LCM struct lcm::ReceiveBuffer class lcm::Subscription struct lcm::LogEvent class lcm::Lo

RegretPain的博客 6553

【腾讯云HAI域探秘】使用LCM-LORA助力炼丹师极速出丹

高性能应用服务(Hyper Application Inventor,HAI)是一款面向 AI 和科学计算的 GPU/NPU 应用服务产品,提供即插即用的强大算力和常见环境。

Lisas_ss的博客 5341

ROS2客户端库与LCM替代方案

完全可以。

2301_79880600的博客 614

lcm教程与实例(C++ API)

背景 Ubuntu 16.04 C++ API lcm 1.30 1. 安装 版本: lcm-1.3.0-saic.tar.gz, 下载 安装 autoconf : $ sudo apt-get install autoconf 解压, 编译, 在LCM目录下执行: $ autoreconf -i $ ./configure $ make -j8 -l8 $ sudo make install ...

QFJIZHI的博客 5913

LCM类型定义语言

LCM类型定义语言的使用和特性。上面一段话的中文翻译除了提供通信原语集合,LCM还包括产生平台无关的数据类型的编组和解组函数的工具。它类似于XDR,但是它的目标是更大的类型安全性,以及对C、Java和Python等多种语言的一流支持。本文档描述了数据编组功能;通信功能在其他地方有描述。注意,可以独立于LCM的通信功能使用LCM的数据编组功能。类型定义包含在以".lcm"为后缀的文件中。

withstand的博客 618

【C++】开源:LCM通讯中间件配置使用

lcm通讯库学习

DevFrank的博客 2749

计算机组成原理课程设计_微程序控制的简单模型机设计

微程序控制的简单模型机设计 要求 基本要求 完成一个简单主机的设计,模型机应具备如下能力:在自行设计的指令集基础上,运行自行编写的简单用户程序,实现特定运算功能。 弹性要求 在此基础上,完成必要的扩展,实现模型机的功能扩展设计,包括:实现多种运算功能(指令集的扩充)、支持更为丰富的寻址方式、有更为完善的微程序设计等。 实验软件和硬件环境 QuartusII, FPGA计算机组...

sailist的记录站 3万+

四足机器人控制算法——建模、控制与实践(unitree_guide配置、自主导航ROS仿真)

宇树科技 unitree_guide 配置

Teriri_的博客 1万+

别再瞎试了!手把手教你用DC NXT的compile_ultra命令搞定物理综合(附完整脚本)

本文详细介绍了如何使用DC NXT的compile_ultra命令进行物理综合,包括环境配置、设计库创建、RTL加载、物理约束加载等关键步骤。通过实战示例和完整脚本,帮助工程师快速掌握TOPO模式下的物理综合流程,提升设计效率。

weixin_30413765的博客 294

利用stl求最大公约数和最小公倍数

#include <iostream> #include <algorithm> //引入头文件 using namespace std; int main() { int i,j; int GCD=__gcd(i,j); //求i,j的最大公约数 int LCM=(i*j)/__gcd(i,j); //求i,j的最小公倍数 return 0; } ...

_C9的博客 1003

【液晶专题】从外挂到In-Cell/ On-Cell/ OGS再也不会傻傻分不清楚了

触控技术经历了从外挂式到内嵌式的革新,主要方案包括外挂式(Out-Cell)、OGS、On-Cell和In-Cell。

一点硬件 1252

视觉Transformer实战 | Data-efficient image Transformer(DeiT)详解与实现

在计算机视觉领域,Vision Transformer (ViT) 已经证明了纯 Transformer 架构在图像分类任务上的强大能力。然而,ViT 通常需要在大规模数据集上预训练才能达到最佳性能,DeiT (Data-efficient image Transformer) 通过引入一系列训练策略和优化,使得 Transformer 模型能够在相对较小的数据集上取得优异表现。本节将详细介绍 DeiT 的技术原理,并使用 PyTorch 从零开始实现 DeiT 模型。

盼小辉丶的博客 1341

LCM库

模块简介 LCM(Lightweight Communications and Marshalling)是一套用于消息传递和数据编组的库和工具的集合,旨在为实时系统提供高带宽和低延迟的消息传递的能力。它提供了一个发布/订阅消息传递模型以及为各种编程语言的应用程序自动生成编/解组代码。 LCM官方地址 使用LCM进行信息交换需要完成以下三个主要步骤: 初始化LCM 发布消息 订阅接受消息 初始化...

weixin_42472382的博客 2070

Python爬虫经典案例第67篇:社交媒体平台爬取:Twitter数据采集实战

Twitter(现更名为X)是全球最具影响力的社交媒体平台之一,拥有超过3.3亿月度活跃用户。作为一个实时信息传播平台,Twitter上的数据涵盖了新闻、政治、娱乐、科技等各个领域,具有极高的研究价值:本文将深入探讨Twitter数据采集的技术方案,包括官方API调用、网页爬取和浏览器自动化三种方式。Twitter采用现代化的微服务架构,主要特点包括:Twitter作为全球最大的社交媒体平台,拥有完善的反爬机制:在开始爬取前,需要明确合法的数据采集方式:重要提示:未经授权爬取Twitter数据可能违反服务条

2201_76125261的博客 659

LCM通讯的使用

本文主要介绍LCM通讯的基本使用,内容主要整理自官网

qq_48922607的博客 2448

华为OD机试双机位C卷-魔法收积木 (C/C++/Py/Java/Js/Go)

华为OD机试(机考)双机位C卷 【魔法收积木】,提供C语言、Java、C++、Python、Go、JavaScript源码实现,并提供完整思路讲解,以及在线OJ模拟做题。华为od - 魔法收积木。

qq_45776114的博客 1940

蓝牙攻防实战指南:低功耗蓝牙

Bluetooth Low Energy(也称Bluetooth Smart)是经典蓝牙(Bluetooth Classic)的演进版本,设计目标是实现极低功耗,适用于无需频繁更换电池的设备,如智能手环、健康监测器、蓝牙标签等。Bluetooth Low Energy 是一项极具前景的无线通信技术,它以极低的功耗实现了短距离高效通信,广泛应用于智能设备和物联网领域。然而,其简化的协议结构和配对机制也带来了不小的安全挑战。

idlecloud0105的博客 682

LCM使用

一、概述 LCM是进行信息收发的工具。 “LCM is a set of libraries and tools for message passing and data marshalling, targeted at real-time systems where high-bandwidth and low latency are critical. It provides a publ...

yly的博客 6043

ParaView: GUI 轴网格

ParaView: GUI 轴网格

希望我的博客,能帮上你解决学习中工作中所遇到的问题 1923

lcm使用方法

// file : userlcm.cpp #include <stdarg.h> #include "userlcm_manage.h" #define USER_LCM_LOG_ON 0 #if USER_LCM_LOG_ON #define USERLCM_LOG(format,arg...) printf("[%s:%s][%u]: " format,__FILE__,__...

ding283595861的博客 2807

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

Qt系列——Win10下LCM通讯库在Qt中的使用及问题解决

Qt系列——Win10下LCM通讯库在Qt中的使用及问题解决

曾经也曾立志 1万+

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

上一篇: 函数绘图工具
下一篇: 使用G2O解决优化问题的简单例子
首飞爱玩机器人
博客等级 码龄14年 6989粉丝 120原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

首飞爱玩机器人

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值