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
相关推荐
程序员榴莲1 天前
Python 中的 @property:像访问属性一样调用方法
开发语言·前端·python
sycmancia1 天前
Qt——拖放事件深度剖析
开发语言·qt
坐吃山猪1 天前
【Nanobot】README09_LEVEL4 添加新聊天渠道
开发语言·网络·python·源码·nanobot
shehuiyuelaiyuehao1 天前
算法27,二维前缀和
开发语言·python·算法
IpdataCloud1 天前
企业安全运营中,如何用IP风险识别工具快速发现异常终端?操作指南
开发语言·php
lingzhilab1 天前
零知派ESP32——BLE Mesh蓝牙组网智能灯控系统(PIR感应+W2812三档调色)
c++·mfc
兩尛1 天前
C++多线程,并发
java·开发语言
计算机安禾1 天前
【c++面向对象编程】第29篇:定位new(placement new):在指定内存上构造对象
开发语言·c++·算法
计算机安禾1 天前
【c++面向对象编程】第27篇:空类的大小为什么是1?——C++对象标识的秘密
开发语言·c++·算法
河阿里1 天前
Python容器:特性、区别和使用场景
开发语言·python