moveit2_servo cmakelist 拆解


一、文件整体结构

text

复制代码
cmake_minimum_required(VERSION 3.22)  ← 指定最低 CMake 版本
project(moveit_servo)                  ← 项目名称

【变量定义区】→ 定义所有目标名称
【依赖查找区】→ 查找所有依赖包
【库构建区】  → 构建核心库
【组件节点区】→ 构建 ROS2 组件节点
【可执行文件区】→ 构建独立节点
【安装配置区】→ 安装到工作空间
【测试区】    → 单元测试和集成测试

二、变量定义区(第3-25行)

cmake

复制代码
# 库名称
set(SERVO_LIB_NAME moveit_servo_lib)           # 核心库
set(SERVO_PARAM_LIB_NAME ${SERVO_LIB_NAME}_parameters)  # 参数库
set(POSE_TRACKING pose_tracking)                # 位姿追踪库

# 组件节点(共享库)
set(SERVO_COMPONENT_NODE servo_node)            # 主服务节点
set(SERVO_CONTROLLER_INPUT servo_controller_input) # 手柄输入节点

# 可执行节点
set(SERVO_NODE_MAIN_NAME servo_node_main)       # 主节点入口
set(POSE_TRACKING_DEMO_NAME servo_pose_tracking_demo) # 位姿追踪演示
set(FAKE_SERVO_CMDS_NAME fake_command_publisher) # 模拟命令发布器

设计意图

  • 使用变量集中管理所有目标名称,便于维护

  • 避免在多处硬编码相同的字符串,降低拼写错误风险

  • 当需要重命名时,只需修改变量定义处


三、依赖查找区(第32-53行)

3.1 引入 MoveIt 公共配置

cmake

复制代码
find_package(moveit_common REQUIRED)
moveit_package()
  • moveit_common 是 MoveIt 的公共 CMake 模块

  • moveit_package() 是自定义宏,设置 MoveIt 包的通用编译选项

3.2 定义并查找所有依赖

cmake

复制代码
set(THIS_PACKAGE_INCLUDE_DEPENDS
  control_msgs          # 控制消息
  control_toolbox       # 控制工具
  geometry_msgs         # 几何消息 (Twist, Pose)
  moveit_core           # MoveIt 核心库
  moveit_msgs           # MoveIt 消息
  moveit_ros_planning   # MoveIt 规划相关
  pluginlib             # 插件加载库
  rclcpp                # ROS2 C++客户端库
  rclcpp_components     # 组件节点支持
  sensor_msgs           # 传感器消息
  std_msgs              # 标准消息
  std_srvs              # 标准服务
  tf2_eigen             # TF2与Eigen转换
  trajectory_msgs       # 轨迹消息
)

# 循环查找每个依赖
foreach(Dependency IN ITEMS ${THIS_PACKAGE_INCLUDE_DEPENDS})
  find_package(${Dependency} REQUIRED)
endforeach()

# 额外的依赖
find_package(eigen3_cmake_module REQUIRED)
find_package(Eigen3 REQUIRED)

为什么要分开写?

  • 集中管理依赖列表,方便增删

  • 避免重复的 find_package 调用

  • ament_target_dependencies 在后续会一次性链接所有这些依赖


四、库构建区(第59-87行)

4.1 参数库 (SERVO_PARAM_LIB_NAME)

cmake

复制代码
add_library(${SERVO_PARAM_LIB_NAME} SHARED
  src/servo_parameters.cpp
  src/parameter_descriptor_builder.cpp
)
ament_target_dependencies(${SERVO_PARAM_LIB_NAME} ${THIS_PACKAGE_INCLUDE_DEPENDS})
  • 负责加载和管理 Servo 的配置参数

  • 独立出来以便其他节点也能加载相同的参数

4.2 核心库 (SERVO_LIB_NAME)

cmake

复制代码
add_library(${SERVO_LIB_NAME} SHARED
  src/collision_check.cpp    # 碰撞检测
  src/enforce_limits.cpp     # 限位约束
  src/servo.cpp              # 核心逻辑
  src/servo_calcs.cpp        # 运动学计算
  src/utilities.cpp          # 工具函数
)
target_link_libraries(${SERVO_LIB_NAME} ${SERVO_PARAM_LIB_NAME})  # 链接参数库
  • 核心计算库,不依赖 ROS2 通信

  • 可以独立测试和复用

4.3 位姿追踪库 (POSE_TRACKING)

cmake

复制代码
add_library(${POSE_TRACKING} SHARED src/pose_tracking.cpp)
target_link_libraries(${POSE_TRACKING} ${SERVO_LIB_NAME})
  • 实现位姿追踪功能

  • 链接到核心库,复用计算能力

依赖传递关系

text

复制代码
SERVO_PARAM_LIB_NAME (参数)
        ↓
SERVO_LIB_NAME (核心计算)
        ↓
POSE_TRACKING (位姿追踪)

五、组件节点区(第89-99行)

ROS2 组件节点是可动态加载的共享库,可以在运行时加载到容器进程中。

5.1 主 Servo 节点

cmake

复制代码
add_library(${SERVO_COMPONENT_NODE} SHARED src/servo_node.cpp)
target_link_libraries(${SERVO_COMPONENT_NODE} ${SERVO_LIB_NAME})
rclcpp_components_register_nodes(${SERVO_COMPONENT_NODE} "moveit_servo::ServoNode")
  • rclcpp_components_register_nodes 将节点注册为组件

  • 可以在 launch 文件中用 ComposableNode 加载

5.2 手柄输入节点

cmake

复制代码
add_library(${SERVO_CONTROLLER_INPUT} SHARED src/teleop_demo/joystick_servo_example.cpp)
rclcpp_components_register_nodes(${SERVO_CONTROLLER_INPUT} "moveit_servo::JoyToServoPub")
  • 处理游戏手柄输入

  • 这里就是之前讨论的 joy 包依赖处


六、可执行文件区(第101-119行)

6.1 主节点入口

cmake

复制代码
add_executable(${SERVO_NODE_MAIN_NAME} src/servo_node_main.cpp)
target_link_libraries(${SERVO_NODE_MAIN_NAME} ${SERVO_COMPONENT_NODE})
  • 这是一个独立的可执行文件

  • 直接链接组件库,本质上和加载组件效果相同

6.2 演示程序

cmake

复制代码
add_executable(${POSE_TRACKING_DEMO_NAME} src/cpp_interface_demo/pose_tracking_demo.cpp)
target_link_libraries(${POSE_TRACKING_DEMO_NAME} ${POSE_TRACKING})
  • C++接口演示,不依赖 ROS2 通信

6.3 模拟命令发布器

cmake

复制代码
add_executable(${FAKE_SERVO_CMDS_NAME} test/publish_fake_jog_commands.cpp)
ament_target_dependencies(${FAKE_SERVO_CMDS_NAME}
  rclcpp
  geometry_msgs
  std_srvs
)
  • 仅依赖少量包,用于测试

  • 注意这里没有 列出 THIS_PACKAGE_INCLUDE_DEPENDS,而是单独指定


七、安装配置区(第121-149行)

7.1 安装库文件

cmake

复制代码
install(
  TARGETS
    ${SERVO_LIB_NAME}
    ${SERVO_LIB_NAME}_parameters
    ${POSE_TRACKING}
    ${SERVO_COMPONENT_NODE}
    ${SERVO_CONTROLLER_INPUT}
  EXPORT export_${PROJECT_NAME}  # 导出用于其他包
  LIBRARY DESTINATION lib        # 安装到 lib/
  ARCHIVE DESTINATION lib
  RUNTIME DESTINATION bin
  INCLUDES DESTINATION include
)

7.2 安装可执行文件

cmake

复制代码
install(
  TARGETS
    ${SERVO_NODE_MAIN_NAME}
    ${CPP_DEMO_NAME}        # 注意:这个变量未在开头定义!
    ${POSE_TRACKING_DEMO_NAME}
    ${FAKE_SERVO_CMDS_NAME}
  RUNTIME DESTINATION lib/${PROJECT_NAME}  # 安装到 lib/moveit_servo/
)

⚠️ 注意${CPP_DEMO_NAME} 变量在开头没有定义,这是一个 CMake 警告,可能是开发者忘记删除。

7.3 安装目录

cmake

复制代码
install(DIRECTORY include/ DESTINATION include)
install(DIRECTORY launch DESTINATION share/${PROJECT_NAME})
install(DIRECTORY config DESTINATION share/${PROJECT_NAME})
  • 头文件:include/install/include/moveit_servo/

  • launch 文件:launch/install/share/moveit_servo/launch/

  • config 文件:config/install/share/moveit_servo/config/

7.4 导出配置

cmake

复制代码
ament_export_targets(export_${PROJECT_NAME} HAS_LIBRARY_TARGET)
ament_export_dependencies(${THIS_PACKAGE_INCLUDE_DEPENDS})
  • 其他包可以通过 find_package(moveit_servo) 找到这个包

  • 自动传递依赖关系


八、测试区(第151-194行)

8.1 禁用部分 Lint 测试

cmake

复制代码
set(ament_cmake_copyright_FOUND TRUE)
set(ament_cmake_cpplint_FOUND TRUE)
set(ament_cmake_flake8_FOUND TRUE)
set(ament_cmake_uncrustify_FOUND TRUE)
  • 强制让这些测试通过(即使代码不完美)

  • 常见于大型项目,避免测试阻塞 CI

8.2 三种测试类型

测试名 类型 说明
test_servo_integration 集成测试 测试 Servo 完整功能
test_servo_collision 集成测试 测试碰撞检测
test_servo_pose_tracking 集成测试 测试位姿追踪
servo_calcs_unit_tests 单元测试 测试计算函数

cmake

复制代码
# 集成测试示例
ament_add_gtest_executable(test_servo_integration
    test/test_servo_interface.cpp
    test/servo_launch_test_common.hpp
)
target_link_libraries(test_servo_integration ${SERVO_PARAM_LIB_NAME})
add_ros_test(test/launch/test_servo_integration.test.py TIMEOUT 120 ...)
  • add_ros_test 是 ROS2 扩展,可以启动 ROS 节点进行测试

  • TIMEOUT 120 限制测试最长运行时间


九、设计模式总结

设计模式 体现
分层架构 核心库 → 组件节点 → 可执行文件
组件化 使用 rclcpp_components 支持动态加载
依赖管理 集中定义 THIS_PACKAGE_INCLUDE_DEPENDS
可测试性 核心库与ROS解耦,支持纯单元测试
可复用性 导出 export_${PROJECT_NAME} 供其他包使用

十、潜在问题

  1. ${CPP_DEMO_NAME} 未定义:在 install 中使用了未声明的变量

  2. joy 包未声明 :虽然 joystick_servo_example.cpp 依赖 /joy 话题,但 CMake 中未显式声明(因为话题不强制编译依赖)

改进建议

cmake

复制代码
# 在依赖列表中添加 joy(如果需要编译依赖)
set(THIS_PACKAGE_INCLUDE_DEPENDS
  ...
  joy  # 添加这一行
)
相关推荐
EW Frontier1 小时前
【DOA估计】四根天线、一块SDR,神经网络把测向误差压进2度以内【附python代码】
人工智能·python·神经网络·doa估计·aoa估计
pla888888881 小时前
海光K100_AI单卡ComfyUI+MiniMax-H3环境调优实战:视频生成速度大幅提升
人工智能·音视频
CVHub1 小时前
智能标注工具 X-AnyLabeling v4 全面升级:迈向 AI 时代的数据生产基础设施
人工智能·算法·github
AI导出鸭1 小时前
怎么让腾讯元宝做表格?AI导出鸭苹果版通过解析引擎将元宝表格HTML转为结构化数据,一键导出标准Excel或Word
人工智能·chatgpt·html·excel·ai导出鸭
wujian83112 小时前
豆包导出word手机,就用AI导出鸭:一站式批量导出方案深度解析
人工智能·ai·chatgpt·智能手机·word·ai导出鸭
拿本唠嗑AI研究2 小时前
从电脑到手机:DeepSeek Harness Windows安装与手机互动教程(避坑完全版)
人工智能·windows·智能手机·deepseek·harness
ZJU_统一阿萨姆9 小时前
【算子开发】矩阵乘法(GEMM)入门与共享内存优化
人工智能·线性代数·矩阵·系统架构
AI码农小姐姐9 小时前
AI漫剧用什么软件制作?知漫剧对比即梦/豆包/可灵怎么选?
人工智能
YH552698410 小时前
GPT‑5.6 Sol 原本支持 1M 上下文,Codex 现已放开此前限制,如何看待这次调整?
java·jvm·人工智能·gpt·算法·chatgpt