Micro XRCE-DDS 中间件整理以及通信
eProsima Micro XRCE-DDS实现了DDS-XRCE协议,为资源受限设备(如微控制器)提供了与DDS网络通信的能力。该系统采用客户端/服务器架构,包含轻量级客户端和代理服务器组件。PX4已集成uXRCE-DDS中间件,通过串行或UDP链路实现PX4与ROS2的无缝通信。安装方法包括独立安装代理(通过源码或Snap包)、客户端以及代码生成工具Micro XRCE-DDS-Gen,支持
0. 简介
eProsima Micro XRCE-DDS是一个实现由OMG定义和维护的DDS-XRCE协议的库,其目的是允许资源受限的设备(如微控制器)像任何其他DDS参与者一样与DDS世界进行通信。 它遵循客户端/服务器范例,由两个库组成,Micro XRCE-DDS 客户端和Micro XRCE-DDS Agent。Micro XRCE-DDS 客户端是轻量级实体,旨在在 eXtremely Resource C上编译,而 Micro XRCE-DDS 代理是将客户端与 DDS 世界连接起来的代理
PX4 已经使用 uXRCE-DDS 中间件,允许在配套计算机上发布和订阅uORB 消息,就像它们是ROS 2主题一样。这提供了 PX4 和 ROS 2 之间快速可靠的集成,并使 ROS 2 应用程序更容易获取车辆信息和发送命令。PX4 使用利用eProsima Micro XRCE-DDS 的XRCE-DDS 实现。我们可以来看看这个中间件以及具体使用

uXRCE-DDS 中间件由运行在 PX4 上的客户端和运行在配套计算机上的代理组成,它们之间通过串行或 UDP 链路进行双向数据交换。代理充当客户端的代理,使其能够发布和订阅全局 DDS 数据空间中的主题。为了使 PX4 uORB 主题在 DDS 网络上共享,您需要在 PX4 上运行uXRCE-DDS 客户端,并连接到在配套设备上运行的微型 XRCE-DDS 代理。
PX4 uxrce_dds_client将内容发布到/从一组定义的 uORB 主题到全局 DDS 数据空间。
micro XRCE-DDS-Agent在配套计算机上运行,并充当 DDS/ROS 2 网络中客户端的代理。
ros2xrcedds 这是一个用于与 ros2和 XRCEDDS 通信的库。它被用在 ros2duino 中,是一个中间库,可以很容易地适应其他裸平台。
Micro-XRCE-DDS-Client客户端独立版,代理不依赖于客户端代码。它可以独立构建,也可以在 ROS2工作区中构建,或者在 Ubuntu 上以快照包的形式安装。
micro-ROS Agent此存储库包含 Micro-ROS Agent 包。Micro-ROS 代理是包装 Micro XRCE-DDS 代理的 ROS2节点。该节点充当 DDS 网络和单片机内部的 Micro-ROS 节点之间的服务器。它接收和发送来自 Micro-ROS 节点的消息,并跟踪暴露给 ROS2网络的 Micro-ROS 节点。
Micro XRCE-DDS-GenMicroXRCE-DDS Gen 提供了一个工具,可以使用 MicroCDR 序列化库从 idl 文件生成序列化主题代码。虽然这个工具打算与 Micro XRCE-DDS Client 库一起使用,但是生成的代码不依赖于它。
1. XRCE-DDS基础和安装

Micro XRCE-DDS Gen工具,将*.idl文件配置信息生成对应目标代码;传输层可以使用TCP、UDP、Serial、Custom中的一种;在Client侧,使用MicroCDR库对数据进行序列化/反序列化操作;而在Agent侧,需要用FastCDR对数据进行序列化/反序列化操作。
1.1 安装 eProsima Micro XRCE-DDS 组件
您可以从 这里 下载包含预安装客户端和代理的 Micro XRCE-DDS 和 Fast-DDS Suite Docker 镜像,以及一些编译示例。有关该 Docker 镜像的更多信息,请访问 此处。
1.2 独立安装代理
从 GitHub 克隆项目:
$ git config --global http.postBuffer 524288000
$ git clone https://github.com/eProsima/Micro-XRCE-DDS-Agent.git
$ cd Micro-XRCE-DDS-Agent
$ mkdir build && cd build
在 Linux 中,在 build 文件夹内执行以下命令:
$ cmake ..
$ make
$ sudo make install
在 Windows 中,首先选择 Visual Studio 版本:
$ cmake -G "Visual Studio 15 2017 Win64" ..
$ cmake --build .
$ cmake --build . --target install
请注意,eProsima Micro XRCE-DDS Agent 可在编译时通过多个 CMake 定义进行配置,具体信息请参考 配置 部分。
完成安装后,务必将 /usr/local/lib 添加到动态加载器链接目录中:
sudo ldconfig /usr/local/lib/
从 Snap 包安装
您也可以将 eProsima Micro XRCE-DDS Agent 作为 Snap 包 安装。只需在控制台执行以下命令:
sudo snap install micro-xrce-dds-agent
要下载对应于 develop 分支的 Snap 镜像,可以在安装命令中添加 --edge 标志。请注意,Snap 包仅适用于 Linux。
1.3 独立安装客户端
从 GitHub 克隆项目:
$ git clone https://github.com/eProsima/Micro-XRCE-DDS-Client.git
$ cd Micro-XRCE-DDS-Client
$ mkdir build && cd build
在 Linux 中,在 build 文件夹内执行以下命令:
$ cmake .. -DUCLIENT_BUILD_EXAMPLES=ON # 编译完成后在example文件夹生成了示例的可执行文件
$ make -j8
$ sudo make install

同样,在运行之前,请将 /usr/local/lib 添加到动态加载器链接目录中:
sudo ldconfig /usr/local/lib/
在 Windows 中,首先选择 Visual Studio 版本:
$ cmake -G "Visual Studio 15 2017 Win64" ..
$ cmake --build .
$ cmake --build . --target install
要安装 eProsima Micro XRCE-DDS Client 示例,请在 cmake .. 命令行选项中添加 -DUCLIENT_BUILD_EXAMPLES=ON。
1.4 安装 Micro XRCE-DDS Gen 工具
首先安装依赖项,克隆项目并构建:
$ git clone https://github.com/eProsima/Micro-XRCE-DDS-Gen.git
$ cd Micro-XRCE-DDS-Gen
$ git submodule init
$ git submodule update
$ ./gradlew assemble
安装完成后,Micro XRCE-DDS-Gen 工具将可用:
$ ./scripts/microxrceddsgen -help
ros转xrce-dds可以使用https://github.com/Pansamic/uxrce-ros2-msgs这个项目。
1.5 同时安装代理和客户端
从 GitHub 克隆项目:
$ git clone https://github.com/eProsima/Micro-XRCE-DDS.git
$ cd Micro-XRCE-DDS
$ mkdir build && cd build
在 Linux 中,在 build 文件夹内执行以下命令:
$ cmake ..
$ make
$ sudo make install
在 Windows 中选择 Visual Studio 版本:
$ cmake -G "Visual Studio 15 2017 Win64" ..
$ cmake --build . --target install
现在,eProsima Micro XRCE-DDS Agent 和 eProsima Micro XRCE-DDS Client 都已安装在系统中。要安装 eProsima Micro XRCE-DDS Gen 工具,请在 cmake .. 命令行选项中添加 -DUXRCE_ENABLE_GEN=ON。要安装示例,请添加 -DUXRCE_BUILD_EXAMPLES=ON。
具体和PX4相关的工作已经写的比较明白了,可以参考这篇文章:Ubuntu20.04安装ROS2+ROS2-PX4框架搭建或者 Ubuntu搭建PX4无人机仿真环境(5)
2. 使用 Docker 编译 Micro-XRCE-DDS 代理
为了方便修改 XRCE-DDS 代理,特地编译了一个镜像用于编译代理。以下是详细步骤:
2.1 运行 Docker 镜像
使用以下命令来运行 Docker 镜像:
docker run -itd -p 2019:2019/udp -v agent-build-files:/root/files --name agent-build szc188/micro-xrce-dds-agent-build-env:v2.1.1 /bin/bash
2.2 取消默认的代理
在 VSCode 的终端中执行以下命令,以取消 Git 的默认代理设置:
git config --global --unset http.proxy
git config --global --unset https.proxy
2.3 安装必要的工具
更新包列表并安装 net-tools:
apt update
apt install -y net-tools
2.4 拉取源代码
在终端中执行以下命令以克隆 Micro-XRCE-DDS-Agent 的源代码:
cd /root/files
git clone https://github.com/eProsima/Micro-XRCE-DDS-Agent.git -b v2.1.1
2.5 编译源代码
进入源代码目录并进行编译:
cd Micro-XRCE-DDS-Agent && mkdir build && cd build
cmake ..
make
2.6 运行代理
使用以下命令来运行编译好的代理:
./MicroXRCEAgent udp4 -p 2019
2.7 修改客户端 Topic 名称以兼容 ROS2 防冲突
为了确保局域网内的 Topic 名称不会重复,需要根据本机的序列号定制 Topic 名称。以下是修改步骤:
2.7.1 修改 FastDDSMiddleware.cpp
- 打开文件:
files/Micro-XRCE-DDS-Agent/src/cpp/middleware/fastdds/FastDDSMiddleware.cpp - 搜索
bool FastDDSMiddleware::create_topic_by_xml( - 在找到的
if语句内添加以下代码:
extern std::string chiplink_sn;
std::string str("rt/");
str += chiplink_sn + "/";
str += attrs.topicName;
attrs.topicName = str.c_str();
std::cout << "####### attrs.getTopicName(): " << attrs.getTopicName() << std::endl;
2.7.2 修改 FastDDSEntities.cpp
- 打开文件:
files/Micro-XRCE-DDS-Agent/src/cpp/middleware/fastdds/FastDDSEntities.cpp - 搜索
bool FastDDSDataWriter::create_by_xml(const std::string& xml) - 在
if语句中添加以下代码:
extern std::string custom_sn;
std::string str("rt/");
str += custom_sn + "/";
str += attrs.topic.topicName;
attrs.topic.topicName = str.c_str();
std::cout << "####### FastDDSDataWriter.attrs.topic.topicName: " << attrs.topic.topicName << std::endl;
- 同样修改
bool FastDDSDataReader::create_by_xml(const std::string& xml)中的if语句,添加相同的代码。
2.7.3 修改 microxrce_agent.cpp
- 打开文件:
files/Micro-XRCE-DDS-Agent/microxrce_agent.cpp - 在
int main(int argc, char** argv)上方添加以下代码:
std::string custom_sn = "test_sn";
这样就完成了对客户端 Topic 名称的定制。
3. FreeRTOS + LWIP 工程中移植 Micro-XRCE-DDS
3.1 准备工作
在进行移植之前,准备一个 FreeRTOS + LWIP 工程,并创建两个文件夹:microdds 和 microcdr。然后开始移植工作。
3.2 开始移植
1. 文件拷贝
(1)拷贝 Micro-XRCE-DDS-Client 代码
从第三章下载的 Micro-XRCE-DDS-Client 代码包中,复制以下文件到已有工程的 microdds 文件夹中:
- src 文件夹
- include 文件夹
- examples 文件夹

(2)拷贝 Micro-XRCE-DDS-Agent 代码
从 Micro-XRCE-DDS-Agent 代码包中,复制以下文件到已有工程的 microcdr 文件夹中:
- src 文件夹
- include 文件夹

完成上述步骤后,已有工程的目录结构应如下所示:

2. 调整代码
(1)修改 config.h.in
在 microcdr 中找到 config.h.in 文件,将其重命名为 config.h,并根据需要调整文件中的内容。
修改前:

修改文件名后,调整文件中的内容:

(2)删除多余的头文件
在 microdds/include 文件夹中,删除与 UDP 无关的头文件。

在 microdds/src 文件夹中,删除与 UDP 无关的源文件,仅保留与 UDP 相关的文件。

删除后的文件内容:

(3)处理 config.h.in
在 microdds/include 文件夹中,将 config.h.in 修改为 config.h 文件,并手动调整文件内容。

手动修改文件中的内容:


(4)保留必要的例程
在 microdds/examples 文件夹中,删除其他不必要的例程,仅保留 SubscribeHelloWorld 例程。

3. 例程测试
(1)重命名例程的 main 函数
将 SubscribeHelloWorld 例程中的 main 文件名和 main 函数重命名,以避免与工程中的其他 main 函数冲突。

(2)调整 main 函数内容
根据项目需求,调整 main 函数的内容,以适应 FreeRTOS + LWIP 环境。

(3)调用示例函数
调整完毕后,在工程的函数中调用 example_main() 来启动示例。
提示:
- 确保例程的 IP 地址与 Agent 的 IP 地址在同一网段。
- 确保端口号与 Agent 监听的端口一致。
4. 代码阅读
PublishHelloWorld
#include "HelloWorld.h"
#include <uxr/client/client.h>
#include <ucdr/microcdr.h>
#include <stdio.h> //printf
#include <string.h> //strcmp
#include <stdlib.h> //atoi
#define STREAM_HISTORY 8
#define BUFFER_SIZE UXR_CONFIG_UDP_TRANSPORT_MTU* STREAM_HISTORY
int main(
int args,
char** argv)
{
// CLI配置, 检查参数数量,确保传入IP和端口有效
if (3 > args || 0 == atoi(argv[2]))
{
printf("usage: program [-h | --help] | ip port [<max_topics>]\n");
return 0;
}
char* ip = argv[1]; // 获取命令行输入的IP地址
char* port = argv[2]; // 获取命令行输入的端口号
uint32_t max_topics = (args == 4) ? (uint32_t)atoi(argv[3]) : UINT32_MAX; // 最大主题数,可选参数
// 传输设置,通过UDP初始化传输结构体
uxrUDPTransport transport;
if (!uxr_init_udp_transport(&transport, UXR_IPv4, ip, port))
{
printf("Error at create transport.\n"); // 错误处理:创建传输失败
return 1;
}
// 会话设置,初始化会话并创建
uxrSession session;
uxr_init_session(&session, &transport.comm, 0xAAAABBBB); // 初始化会话ID
if (!uxr_create_session(&session))
{
printf("Error at create session.\n"); // 错误处理:创建会话失败
return 1;
}
// 流配置,用于设置可靠流的发送和接收缓冲区
uint8_t output_reliable_stream_buffer[BUFFER_SIZE];
uxrStreamId reliable_out = uxr_create_output_reliable_stream(&session, output_reliable_stream_buffer, BUFFER_SIZE,
STREAM_HISTORY);
uint8_t input_reliable_stream_buffer[BUFFER_SIZE];
uxr_create_input_reliable_stream(&session, input_reliable_stream_buffer, BUFFER_SIZE, STREAM_HISTORY);
// 创建参与者实体
uxrObjectId participant_id = uxr_object_id(0x01, UXR_PARTICIPANT_ID);
const char* participant_xml = "<dds>"
"<participant>"
"<rtps>"
"<name>default_xrce_participant</name>" // 参与者名称
"</rtps>"
"</participant>"
"</dds>";
uint16_t participant_req = uxr_buffer_create_participant_xml(&session, reliable_out, participant_id, 0,
participant_xml, UXR_REPLACE);
// 创建主题实体
uxrObjectId topic_id = uxr_object_id(0x01, UXR_TOPIC_ID);
const char* topic_xml = "<dds>"
"<topic>"
"<name>HelloWorldTopic</name>" // 主题名称
"<dataType>HelloWorld</dataType>" // 数据类型
"</topic>"
"</dds>";
uint16_t topic_req = uxr_buffer_create_topic_xml(&session, reliable_out, topic_id, participant_id, topic_xml,
UXR_REPLACE);
// 创建发布者实体
uxrObjectId publisher_id = uxr_object_id(0x01, UXR_PUBLISHER_ID);
const char* publisher_xml = ""; // 发布者XML(此处为空)
uint16_t publisher_req = uxr_buffer_create_publisher_xml(&session, reliable_out, publisher_id, participant_id,
publisher_xml, UXR_REPLACE);
// 创建数据写入器(DataWriter)实体
uxrObjectId datawriter_id = uxr_object_id(0x01, UXR_DATAWRITER_ID);
const char* datawriter_xml = "<dds>"
"<data_writer>"
"<topic>"
"<kind>NO_KEY</kind>"
"<name>HelloWorldTopic</name>" // 数据写入器绑定到主题
"<dataType>HelloWorld</dataType>"
"</topic>"
"</data_writer>"
"</dds>";
uint16_t datawriter_req = uxr_buffer_create_datawriter_xml(&session, reliable_out, datawriter_id, publisher_id,
datawriter_xml, UXR_REPLACE);
// 发送创建实体消息并等待状态
uint8_t status[4];
uint16_t requests[4] = { participant_req, topic_req, publisher_req, datawriter_req };
if (!uxr_run_session_until_all_status(&session, 1000, requests, status, 4))
{
// 错误处理:如果未能成功创建所有实体
printf("Error at create entities: participant: %i topic: %i publisher: %i datawriter: %i\n", status[0],
status[1], status[2], status[3]);
return 1;
}
// 写主题循环,将指定数量的话题写入
bool connected = true; // 保持连接状态
uint32_t count = 0; // 计数器
while (connected && count < max_topics)
{
HelloWorld topic = {
++count, "Hello DDS world!" // 增加计数并定义消息内容
};
ucdrBuffer ub; // 定义一个序列化缓冲区
uint32_t topic_size = HelloWorld_size_of_topic(&topic, 0); // 获取消息大小
uxr_prepare_output_stream(&session, reliable_out, datawriter_id, &ub, topic_size); // 准备输出流
HelloWorld_serialize_topic(&ub, &topic); // 序列化主题对象
printf("Send topic: %s, id: %i\n", topic.message, topic.index); // 输出发送的信息
connected = uxr_run_session_time(&session, 1000); // 按时间运行会话
}
// 清理资源
uxr_delete_session(&session); // 删除会话
uxr_close_udp_transport(&transport); // 关闭UDP传输层
return 0; // 程序正常结束
}
…详情请参照古月居
UORB和DDS相关的通信机制,主要包括创建数据读写实体,并按照一定的QoS策略进行配置。同时根据主题名称的生成规则与网络流进行分发,通过检测请求结果来判断各个操作是否成功。
#pragma once
#include <uxr/client/client.h>
#include <ucdr/microcdr.h>
#include <uORB/topics/uORBTopics.hpp>
#define TOPIC_NAME_SIZE 128
// 将给定的 orb_id 和实例转换为 uxrObjectId
uxrObjectId topic_id_from_orb(ORB_ID orb_id, uint8_t instance = 0)
{
if (orb_id != ORB_ID::INVALID) {
uint16_t id = static_cast<uint8_t>(orb_id) + (instance * UINT8_MAX);
uxrObjectId topic_id = uxr_object_id(id, UXR_TOPIC_ID); // 生成并返回用于主题标识的对象ID
return topic_id;
}
return uxrObjectId{}; // 返回一个无效的对象ID
}
// 根据客户端命名空间和方向生成主题名称
static bool generate_topic_name(char *topic, const char *client_namespace, const char *direction, const char *name)
{
if (client_namespace != nullptr) { // 如果客户端命名空间不为空
int ret = snprintf(topic, TOPIC_NAME_SIZE, "rt/%s/fmu/%s/%s", client_namespace, direction, name);
return (ret > 0 && ret < TOPIC_NAME_SIZE); // 检查生成是否成功,且没有超过最大缓冲区大小
}
// 如果没有客户端命名空间则使用默认格式生成主题名称
int ret = snprintf(topic, TOPIC_NAME_SIZE, "rt/fmu/%s/%s", direction, name);
return (ret > 0 && ret < TOPIC_NAME_SIZE);
}
// 创建数据写入者
static bool create_data_writer(uxrSession *session, uxrStreamId reliable_out_stream_id, uxrObjectId participant_id,
ORB_ID orb_id, const char *client_namespace, const char *topic_name_simple, const char *type_name,
uxrObjectId &datawriter_id)
{
char topic_name[TOPIC_NAME_SIZE]; // 存放主题名称
// 生成主题名称
if (!generate_topic_name(topic_name, client_namespace, "out", topic_name_simple)) {
PX4_ERR("topic path too long"); // 输出错误日志:主题路径过长
return false;
}
uxrObjectId topic_id = topic_id_from_orb(orb_id); // 从orb_id获取主题ID
uint16_t topic_req = uxr_buffer_create_topic_bin(session, reliable_out_stream_id, topic_id, participant_id, topic_name,
type_name, UXR_REPLACE); // 在会话中创建主题请求
// 创建发布者
uxrObjectId publisher_id = uxr_object_id(topic_id.id, UXR_PUBLISHER_ID);
uint16_t publisher_req = uxr_buffer_create_publisher_bin(session, reliable_out_stream_id, publisher_id, participant_id,
UXR_REPLACE); // 创建发布者请求
// 数据写入者ID
datawriter_id = uxr_object_id(topic_id.id, UXR_DATAWRITER_ID);
uxrQoS_t qos = { // 设置质量服务(QoS)参数
.durability = UXR_DURABILITY_TRANSIENT_LOCAL, // 确保数据在本地持久
.reliability = UXR_RELIABILITY_BEST_EFFORT, // 优先发送
.history = UXR_HISTORY_KEEP_LAST, // 保留最近的数据历史
.depth = 0, // 深度设为0表示无限制
};
uint16_t datawriter_req = uxr_buffer_create_datawriter_bin(session, reliable_out_stream_id, datawriter_id, publisher_id,
topic_id, qos, UXR_REPLACE); // 创建数据写入者请求
// 发送创建实体消息并等待其状态
uint16_t requests[3] {topic_req, publisher_req, datawriter_req}; // 请求数组
uint8_t status[3]; // 状态反馈数组
if (!uxr_run_session_until_all_status(session, 1000, requests, status, 3)) { // 执行会话并检查所有请求的状态
PX4_ERR("create entities failed: %s, topic: %i publisher: %i datawriter: %i",
topic_name, status[0], status[1], status[2]); // 输出失败信息
return false;
} else {
PX4_INFO("successfully created %s data writer, topic id: %d", topic_name, topic_id.id); // 成功创建提示
}
return true; // 成功返回true
}
// 创建数据读取器
static bool create_data_reader(uxrSession *session, uxrStreamId reliable_out_stream_id, uxrStreamId input_stream_id,
uxrObjectId participant_id, uint16_t index, const char *client_namespace, const char *topic_name_simple,
const char *type_name, uint16_t queue_depth)
{
char topic_name[TOPIC_NAME_SIZE]; // 存放主题名称
// 生成主题名称
if (!generate_topic_name(topic_name, client_namespace, "in", topic_name_simple)) {
PX4_ERR("topic path too long"); // 输出错误日志:主题路径过长
return false;
}
uint16_t id = index + 1000; // 给定索引偏移量id,用于唯一标识
uxrObjectId topic_id = uxr_object_id(id, UXR_TOPIC_ID); // 使用偏移量生成UCPS主题ID
uint16_t topic_req = uxr_buffer_create_topic_bin(session, reliable_out_stream_id, topic_id, participant_id, topic_name,
type_name, UXR_REPLACE); // 创建主题请求
// 创建订阅者
uxrObjectId subscriber_id = uxr_object_id(id, UXR_SUBSCRIBER_ID);
uint16_t subscriber_req = uxr_buffer_create_subscriber_bin(session, reliable_out_stream_id, subscriber_id,
participant_id, UXR_REPLACE); // 创建订阅者请求
// 数据读取器ID
uxrObjectId datareader_id = uxr_object_id(id, UXR_DATAREADER_ID);
uxrQoS_t qos = { // 设置质量服务(QoS)参数
.durability = UXR_DURABILITY_VOLATILE, // 不保证持久性
.reliability = UXR_RELIABILITY_BEST_EFFORT, // 优先发送
.history = UXR_HISTORY_KEEP_LAST, // 保留最近的数据历史
.depth = queue_depth, // 队列深度指定为传入参数
};
uint16_t datareader_req = uxr_buffer_create_datareader_bin(session, reliable_out_stream_id, datareader_id,
subscriber_id, topic_id, qos, UXR_REPLACE); // 创建数据读取器请求
uint16_t requests[3] {topic_req, subscriber_req, datareader_req}; // 请求数组
uint8_t status[3]; // 状态反馈数组
if (!uxr_run_session_until_all_status(session, 1000, requests, status, 3)) { // 执行会话并检查所有请求的状态
PX4_ERR("create entities failed: %s %i %i %i", topic_name,
status[0], status[1], status[2]); // 输出失败信息
return false;
}
uxrDeliveryControl delivery_control{}; // 创建交付控制结构体
delivery_control.max_samples = UXR_MAX_SAMPLES_UNLIMITED; // 最大样本数量设置为无限制
uxr_buffer_request_data(session, reliable_out_stream_id, datareader_id, input_stream_id, &delivery_control); // 请求数据接收
return true; // 成功返回true
}
uORB—> ROS2
ROS 2 需要与 PX4 固件中创建 uXRCE-DDS 客户端模块所使用的消息定义相同,以便正确解析消息。这些定义存储在 ROS 2 接口包 PX4/px4_msgs 中,并由 CI 在主分支和发布分支上自动同步。请注意,PX4 源代码中的所有消息都存在于该存储库中,但只有在PX4-Autopilot/src/modules/uxrce_dds_client/dds_topics.yaml中列出的消息才会作为 ROS 2 主题可用。
如果您正在创建或修改 uORB 消息,您必须手动从您的 PX4 源代码树中更新工作区中的消息。通常,这意味着您需要更新 dds_topics.yaml,克隆接口包,然后通过将 PX4-Autopilot/msg 中的新/修改的消息定义手动同步到其 msg 文件夹中。假设 PX4-Autopilot 位于您的主目录 ~ 中,而 px4_msgs 位于 ~/px4_ros_com/src/ 中,则命令可能是:
rm ~/px4_ros_com/src/px4_msgs/msg/*.msg
cp ~/PX4-Autopilot/mgs/*.msg ~/px4_ros_com/src/px4_msgs/msg/

5. 参考链接
https://docs.px4.io/main/en/middleware/uxrce_dds.html
https://micro-xrce-dds.docs.eprosima.com/en/latest/installation.html
https://blog.csdn.net/gitblog_01184/article/details/141740487
https://blog.csdn.net/weixin_55944949/article/details/140627640
openvela 操作系统专为 AIoT 领域量身定制,以轻量化、标准兼容、安全性和高度可扩展性为核心特点。openvela 以其卓越的技术优势,已成为众多物联网设备和 AI 硬件的技术首选,涵盖了智能手表、运动手环、智能音箱、耳机、智能家居设备以及机器人等多个领域。
更多推荐



所有评论(0)