【ROS2】IDL(Interface Definition Language)语法解析和使用

概述

当我们的系统变得复杂,且需要多种不同类型的数据结构在不同的节点通信时,最佳实践是将IDL文件按功能模块进行拆分和组织,而不是仅仅将所有定义都放在一个巨大的文件中。

这类似于在C++中将类的声明分散到不同的头文件中,而不是把所有的东西都写在里main.cpp

核心思想:一个功能模块,一个IDL文件

示例

idl 复制代码
// robot_types.idl
module robot {
  struct Header {
    uint64 sec;
    uint32 nsec;
    uint32 seq;
  };

  struct ImuRaw {
    Header header;
    float ax; float ay; float az;
    float gx; float gy; float gz;
  };

  struct MotorPwm {
    Header header;
    float left;
    float right;
  };
};

1. IDL 语法详解 (以 robot_types.idl 为例)

IDL 全称是接口定义语言 (Interface Definition Language)。它是一种与特定编程语言无关的规范语言,用于定义数据类型和接口。DDS 使用它来确保不同的应用程序(即使是用不同语言编写的)能够理解和交换数据。

idl 复制代码
module robot {
  // 具体定义结构体
};
  • module : 这相当于 C++ 中的 namespace 或 Java 中的 package。它用于组织系统的数据类型,避免命名冲突。上面的示例中,定义的所有结构体都将属于 robot 这个模块。在生成的代码中,这通常会体现为名称前缀,例如 robot_Header

idl 复制代码
  struct Header {
    uint64 sec;
    uint32 nsec;
    uint32 seq;
  };
  • struct : 定义一个数据结构,类似于 C/C++ 中的 struct。它将多个数据成员(字段)组合成一个单一的类型。
  • uint64, uint32, float : 这些是 IDL 中的基本数据类型。它们与 C++ 中的类型有直接的对应关系:
    • short, long, long long: 对应 C++ 的 int16_t, int32_t, int64_t
    • unsigned short, unsigned long, unsigned long long: 对应 C++ 的 uint16_t, uint32_t, uint64_t (注意:在 IDL 中 long 是32位,long long 是64位)
    • float, double: 对应 C++ 的 float, double
    • char, wchar: 字符类型
    • boolean: 布尔类型
    • octet: 8位字节,对应 C++ 的 uint8_t

idl 复制代码
  struct ImuRaw {
    Header header; // 
    float ax; float ay; float az;
    float gx; float gy; float gz;
  }; // 

  struct MotorPwm {
    Header header;
    float left;
    float right;
  };
  • 嵌套结构体 : 可以在一个 struct 中包含另一个已经定义的 struct。这里 ImuRawMotorPwm 都包含了 Header 结构体,实现了代码复用。
其它常用 IDL 语法元素:
  • string : 定义一个字符串。string<10> 表示最大长度为10的字符串。

  • sequence : 定义一个动态数组(序列)。sequence<float> 表示一个 float 类型的数组。sequence<float, 5> 表示一个最多包含5个 float 元素的数组。

  • enum : 定义枚举类型。

    idl 复制代码
    enum Color { RED, GREEN, BLUE };
  • const : 定义常量。

    idl 复制代码
    const long MAX_SPEED = 100;

2. 生成类型支持代码

为了让 CycloneDDS 能够理解在 IDL 中定义的结构体,我们需要使用 IDL 编译器将 .idl 文件转换成特定语言(C/C++)的代码。CycloneDDS 提供的这个工具叫做 idlc

idlc 工具会读取 .idl 文件,并生成两部分内容:

  1. C/C++ 头文件 (.h): 包含在 IDL 中定义的结构体的 C/C++ 版本。
  2. C/C++ 源文件 (.c): 包含 DDS 类型描述符(Type Descriptor)。这个描述符包含了关于数据结构的元信息(如字段名、类型、偏移量等),DDS 中间件在序列化和反序列化数据时需要用到它。
如何使用 idlc

idlc 是一个命令行工具,在成功编译和安装 CycloneDDS 后,应该就可以用了

最基本的使用方法是:(不推荐)

bash 复制代码
# -l c 表示生成 C 语言代码 (兼容 C++)
idlc -l c your_idl_file.idl

对于上面的示例程序,命令应该是:

bash 复制代码
idlc -l c idl/robot_types.idl

执行后,会在当前目录下生成 robot_types.hrobot_types.c 两个文件。

3. 集成到 CMake 项目中(推荐)

手动运行 idlc 很繁琐且容易出错。最佳实践是将其集成到 CMakeLists.txt 构建流程中,让它自动完成。

我们可以创建一个自定义命令 (add_custom_command) 和一个自定义目标 (add_custom_target) 来实现这一点。

CMakeLists.txt 的具体实现可以看我的另一篇文章

总结步骤

  1. 定义数据 : 使用 IDL 语法在 .idl 文件中清晰地定义跨平台、跨语言的数据结构。
  2. 编译 IDL(可选) : 使用 idlc -l c <your_file.idl> 命令生成 C 语言兼容的头文件 (.h) 和源文件 (.c)。
  3. 集成构建 : 将 idlc 命令集成到 CMake 或其他构建系统中,实现自动化代码生成。
  4. 使用代码 : 在自己的程序中 #include 生成的 .h 文件,并在调用 dds_create_topic 等函数时,使用 idlc 生成的类型描述符(如 &robot_ImuRaw_desc)。

关于警告

No default extensibility provided. For one or more of the aggregated types in the IDL the extensibility is not explicitly set. Currently the default extensibility for these types is 'final', but this may change to 'appendable' in a future release because that is the default in the DDS XTypes specification.

该警告产生于构建完成后的编译过程中,这是因为在idl文件中没有标注该数据结构是否可扩展(非最终版),我们只需要将标注补充一下就行了,比如:

idl 复制代码
// robot_types.idl
@appendable
module robot {
  struct Header {
    uint64 sec;
    uint32 nsec;
    uint32 seq;
  };
@appendable
  struct ImuRaw {
    Header header;
    float ax; float ay; float az;
    float gx; float gy; float gz;
  };
@final
  struct MotorPwm {
    Header header;
    float left;
    float right;
  };
};
相关推荐
某林21216 小时前
跨越底层与AI的鸿沟:ROS2+多模态大模型(Qwen-VL)机器人全链路排障实录
人工智能·stm32·机器人·人机交互·ros2·技术复盘
MIXLLRED18 小时前
Ubuntu 22.04 + ROS2 Humble 上部署 ScaRF‑SLAM指南
ubuntu·slam·ros2·离线建图
某林2122 天前
ROS 2 与大模型融合实战:从进程连环崩溃到类型安全防御的深度排障复盘
c++·python·安全·机器人·人机交互·ros2
济6172 天前
ROS开发专栏---ROS2 机械臂应用入门(1)---JointState 消息解析与机械臂往复运动控制实验---适配Ubuntu 22.04
嵌入式硬件·嵌入式·ros2·机器人开发·机器人方向
济6172 天前
ROS开发专栏---ROS2 三维视觉应用(2)---使用 PCL 进行桌面物品检测实验---适配Ubuntu 22.04
嵌入式硬件·嵌入式·ros2·机器人开发·机器人方向
竹叶青lvye3 天前
ROS2话题、服务、动作通讯
ros2·服务·动作·话题
kyle~3 天前
ROS2---零拷贝
linux·c++·机器人·ros2
济6173 天前
ROS2 Humble 开发专栏---ROS2 三维视觉应用(1)---RGB-D 相机三维点云数据获取实验---适配Ubuntu 22.04
ubuntu·嵌入式·ros2·机器人开发·机器人方向
BestOrNothing_20153 天前
ROS2 话题通信实战:消息对象、Publisher 发布器与 Subscriber 订阅器保姆级教程
c++·ros2·subscriber·publisher·话题通信
曾小蛙5 天前
【ROS2+深度相机】Orbbec相机时图像传输延迟显著 (DDS数据分发服务配置)
ros2·dds·奥比中光·orbbec