2,使用功能包组织C++节点

目录

[2.1 创建 C++ 功能包](#2.1 创建 C++ 功能包)

[2.2 编写 C++ 节点源码](#2.2 编写 C++ 节点源码)

[2.3 修改 CMakeLists.txt](#2.3 修改 CMakeLists.txt)

[2.4 添加依赖声明](#2.4 添加依赖声明)

[2.5 编译与运行(这一步没必要,直接跳2.5,这里只是记录过程)](#2.5 编译与运行(这一步没必要,直接跳2.5,这里只是记录过程))

[2.6 直接使用 colcon 构建](#2.6 直接使用 colcon 构建)

[报错信息:No executable found](#报错信息:No executable found)

问题原因分析

解决步骤

重新执行构建:


2.1 创建 C++ 功能包

在工作空间的 src 目录(或你存放包的目录)下,创建 ament_cmake 类型的 C++ 功能包:

复制代码
ros2 pkg create --build-type ament_cmake --license Apache-2.0 demo_cpp_pkg

执行结果显示包创建成功,自动生成了以下结构:

复制代码
demo_cpp_pkg/
├── CMakeLists.txt
├── include/
│   └── demo_cpp_pkg/
├── package.xml
└── src/

2.2 编写 C++ 节点源码

在 src/ 目录下创建节点源文件 cpp_node.cpp,内容如下:

复制代码
#include "rclcpp/rclcpp.hpp"

int main(int argc, char **argv)
{
    rclcpp::init(argc, argv);
    
    auto node = std::make_shared<rclcpp::Node>("cpp_node");
    
    RCLCPP_INFO(node->get_logger(), "你好 C++ 节点!");
    
    rclcpp::spin(node);
    rclcpp::shutdown();
    
    return 0;
}

2.3 修改 CMakeLists.txt

原始的 CMakeLists.txt 模板 中,find_package(rclcpp REQUIRED) 通常在文件较上方。

我们需要做以下修改:

  1. 确保 find_package(rclcpp REQUIRED) 已存在(通常已自动生成)。
  2. 添加可执行文件声明。
  3. 使用 ament_target_dependencies 链接依赖(推荐方式,比手动 target_include_directories + target_link_libraries 更简洁)。
    其实就是把普通版本的CMakeLists.txt这四行粘贴到这个功能包的CMakeLists.txt:

这里:

target_include_directories(cpp_node PUBLIC ${rclcpp_INCLUDE_DIRS})

#target_link_libraries(cpp_node ${rclcpp_LIBRARIES})

这两行等价于:

ament_target_dependencies(cpp_node rclcpp)
修改后的完整 CMakeLists.txt 如下(关键修改部分已标注):

复制代码
cmake_minimum_required(VERSION 3.8)
project(demo_cpp_pkg)

if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
  add_compile_options(-Wall -Wextra -Wpedantic)
endif()

# find dependencies
find_package(ament_cmake REQUIRED)
find_package(rclcpp REQUIRED)          # ← 查找 rclcpp

add_executable(cpp_node src/cpp_node.cpp)   # ← 修改为你的源文件路径和目标名

# 使用 ament 推荐方式链接依赖(推荐)
ament_target_dependencies(cpp_node rclcpp)

# 以下手动方式也可以,但不推荐混用
# target_include_directories(cpp_node PUBLIC ${rclcpp_INCLUDE_DIRS})
# target_link_libraries(cpp_node ${rclcpp_LIBRARIES})

if(BUILD_TESTING)
  find_package(ament_lint_auto REQUIRED)
  set(ament_cmake_copyright_FOUND TRUE)
  set(ament_cmake_cpplint_FOUND TRUE)
  ament_lint_auto_find_test_dependencies()
endif()

ament_package()

修改要点总结:

  • **add_executable(cpp_node src/cpp_node.cpp):**指定源文件路径和可执行文件名
  • 使用 ament_target_dependencies(cpp_node rclcpp)(推荐)
  • 保留了 find_package(rclcpp REQUIRED)

2.4 添加依赖声明

复制代码
<depend>rclcpp</depend>

2.5 编译与运行(这一步没必要,直接跳2.5,这里只是记录过程)

复制代码
# 1. 进入包目录的 build 文件夹(或直接在工作空间根目录使用 colcon)
cd demo_cpp_pkg
mkdir -p build && cd build

# 2. 配置(cmake)
cmake ..

# 3. 编译
make

# 4. 运行节点
./cpp_node

记得退出base环境,base(miniforge3 / conda)环境中运行 cmake,该环境缺少 ROS 2 所需的 catkin_pkg Python 模块。!!!!!

正确做法:

  1. 退出 conda base 环境(非常重要!)
复制代码
conda deactivate
  1. 确保使用系统自带的 Python(ROS 2 Humble 默认使用 Python 3.10)
  2. 重新执行 cmake .. 和 make

经验教训:

  • ROS 2 开发时,强烈建议不要在 conda/miniconda base 环境中编译,容易出现 Python 包冲突。
  • 最好使用纯系统环境(source /opt/ros/humble/setup.bash 后)进行开发构建。

2.6 直接使用 colcon 构建

在当前目录,依次执行:

复制代码
$ colcon build
$ source install/setup.bash
$ ros2 run demo_cpp_pkg cpp_node

报错信息:No executable found

同时使用 ros2 pkg executables demo_cpp_pkg(或直接 ros2 run)时,系统无法找到可执行文件 cpp_node。

问题原因分析

虽然我们已经在 CMakeLists.txt 中写了:

复制代码
add_executable(cpp_node src/cpp_node.cpp)
ament_target_dependencies(cpp_node rclcpp)

但 没有安装(install)可执行文件 到正确的位置。

ROS 2 的 ros2 run 命令只会从 install/<package_name>/lib/<package_name>/ 目录下查找可执行文件。 如果 CMakeLists.txt 中缺少 install() 指令,colcon build 虽然能成功编译出 cpp_node,但不会将其复制到 install 目录下,导致 ros2 run 找不到可执行程序。

这是 ROS 2 ament_cmake 包开发中最常见的"能编译通过,但 ros2 run 找不到节点"的原因之一。

解决步骤

在 CMakeLists.txt 中添加 install() 指令(推荐写法):

复制代码
# 在 ament_target_dependencies 之后,if(BUILD_TESTING) 之前添加

install(
  TARGETS
    cpp_node
  DESTINATION lib/${PROJECT_NAME}
)

修改后的完整关键部分如下:

复制代码
find_package(ament_cmake REQUIRED)
find_package(rclcpp REQUIRED)

add_executable(cpp_node src/cpp_node.cpp)

ament_target_dependencies(cpp_node rclcpp)

# ==================== 必须添加这一段 ====================
install(
  TARGETS
    cpp_node
  DESTINATION lib/${PROJECT_NAME}
)
# =======================================================

if(BUILD_TESTING)
  ...
endif()

ament_package()

重新执行构建:

复制代码
$ colcon build
$ source install/setup.bash
$ ros2 run demo_cpp_pkg cpp_node
相关推荐
死磕音视频10 小时前
让小模型做选择题:限定候选项并读取 logits 概率的入门实践(附 Python 代码)
开发语言·python·大模型·文本分类·transformers
WL学习笔记12 小时前
C & C++ 内存管理
c++·c++内存管理
顽疲12 小时前
Java vue 养老系统源码详解:月账单 care_month_bill 与 Quartz 扣费 Job 实践
java·开发语言·vue.js·vue养老·springboot养老·java养老
Wang's Blog13 小时前
Java 项目实战: 交友项目 - 安装开发工具与环境准备
java·开发语言·交友
宛 禾14 小时前
Qt 控件入门:QLabel 从拖拽到对象树,一篇讲透
c++·qt·学习
hetao173383714 小时前
联盟场-提高组-R7 & ZYZSC-S-Round 11
c++·算法
程序喵大人15 小时前
【C++入门】编译链接模型 - 07 链接器怎样把符号对上号
开发语言·c++·编译器·编译链接·链接器
微三云 - 廖会灵 (私域系统开发)15 小时前
供应链系统实战:多渠道订单聚合与分布式库存一致性方案总结
开发语言·分布式·php
局部有解15 小时前
Hot100 - 三数之和
数据结构·c++·算法
学逆向的15 小时前
C 数据溢出与精度丢失
c语言·开发语言·网络安全