标签:带宽 框架 订阅 type 其他 连接 模块简介 工具 enabled
1. LCM通信模块简介2. LCM通信模块使用方法
本节旨在介绍基于C编程语言进行LCM通信的使用方法。在此之前,用户需要使用lcm-gen工具将自定义的数据结构编译为LCM能够处理的消息格式。
开发者使用LCM进行消息交换时需要完成以下三个主要步骤:
1)初始化LCM;
2)发布一个消息;
3)订阅及接收消息。
2.1 初始化
LCM的初始化代码如下所示。
#include <stdio.h>
#include <lcm/lcm.h>
int main(int argc, char **argv)
{
lcm_t *lcm = lcm_create(NULL);
if(!lcm) {
return (PX_ERROR);
}
/*
* 用户应用程序代码
*/
lcm_destroy(lcm);
return (ERROR_NONE);
}
函数lcm_create主要完成lcm_t实例的分配与初始化,该实例表示与LCM网络的连接。其入参为NULL表示使用默认设置来初始化LCM。初始化的默认值适合于本地计算机上的其他LCM应用程序进行通信,也可以指定底层网络通信机制的字符串。
完成之后,调用lcm_destroy来清理LCM使用的资源。
2.2 发布消息
假定用户已使用lcm-gen生成了“exlcm_example_t.h”和“exlcm_example_t.c”两个文件,其中用户定义的数据结构被lcm-gen编译并保存在“exlcm_example_t.h”中,假设生成的消息结构如下所示。
typedef struct _exlcm_example_t exlcm_example_t;
struct _exlcm_example_t {
int64_t timestamp;
double position[3];
double orientation[4];
int32_t num_ranges;
int16_t ranges;
char name;
int8_t enabled;
};
接下来我们将按照消息结构实例化一些数据并进行发布,如下所示。
#include <stdio.h>
#include <lcm/lcm.h>
#include "exlcm_example_t.h"
int main(int argc, char **argv)
{
int i;
int16_t ranges[15];
lcm_t *lcm = lcm_create(NULL);
if(!lcm) {
return (PX_ERROR);
}
exlcm_example_t lcmData = {
.timestamp = 0,
.position = { 1, 2, 3 },
.orientation = { 1, 0, 0, 0 },
};
for(i = 0; i < 15; i++) {
ranges[i] = i;
}
lcmData.num_ranges = 15;
lcmData.ranges = ranges;
lcmData.name = "example string";
lcmData.enabled = 1;
exlcm_example_t_publish(lcm, "EXAMPLE", &lcmData);
lcm_destroy(lcm);
return (ERROR_NONE);
}
函数exlcm_example_t_publish将数据串行化为字节流,并使用LCM将数据包发送给接收器,“EXAMPLE”在这里表示通道名,是与数据包一起进行传输的字符串,用于向接收方标识内容。接收这使用该标识符订阅不同的通道,从而可以快速有效的丢弃无关的数据。
2.3 订阅消息
如2.2节所描述,每个LCM消息都以相关联的通道名发送,用户可以根据通道名决定应用程序接收哪些已订阅的消息。发布者与接收者必须就每种消息类型达成使用的通道名的一致性。
消息订阅示例代码如下所示。
#include <stdio.h>
#include <inttypes.h>
#include <sys/select.h>
#include <lcm/lcm.h>
#include "exlcm_example_t.h"
static void my_handler (const lcm_recv_buf_t *rbuf,
const char *channel,
const exlcm_example_t *msg,
void *user)
{
printf("Received message on channel %s:\n", channel);
}
int main(int argc, char ** argv)
{
int status
lcm_t *lcm;
lcm = lcm_create(NULL);
if(!lcm) {
return (PX_ERROR);
}
exlcm_example_t_subscription_t *sub =
exlcm_example_t_subscribe(lcm, "EXAMPLE", &my_handler, NULL);
while(1) {
fd_set fds;
int lcm_fd = lcm_get_fileno(lcm);
FD_ZERO(&fds);
FD_SET(lcm_fd, &fds);
struct timeval timeout = {
1,
0
};
status = select(lcm_fd + 1, &fds, 0, 0, &timeout);
if(ERROR_NONE == status) {
printf("waiting for message\n");
} else if(FD_ISSET(lcm_fd, &fds)) {
lcm_handle(lcm);
}
}
exlcm_example_t_unsubscribe(lcm, sub);
lcm_destroy(lcm);
return (ERROR_NONE);
}
本示例代码首先创建了一个LCM实例,然后向“EXAMPL”通道添加订阅,当该通道接收到消息,将会调用my_handler将该通道打印出来。其中my_handler是在lcm_handle函数内被调用的。如果其他通道上有消息传输,则该示例程序不会接收到,因为该程序只订阅了“EXAMPL”通道。通常一个特定的LCM实例可能具有若干数量的订阅。
3. 最后
SylixOS基于LCM通信模块开发了一套板间通信机制。该机制主要完成了对LCM库的进一步封装。详细内容参见文档《SylixOS板间通信框架开发手册》。
标签:带宽 框架 订阅 type 其他 连接 模块简介 工具 enabled
原文地址:http://blog.51cto.com/12557908/2150593