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
相关推荐
知识分享小能手2 小时前
R语言入门学习教程,从入门到精通,R语言网格绘图系统(ggplot2)- 完整知识点与案例代码(3)
开发语言·学习·r语言
ifuleyou16682 小时前
《Inter问题》
android·开发语言·kotlin
WL_Aurora2 小时前
Python基础知识点全解析:从入门到精通
开发语言·python
AI人工智能+电脑小能手2 小时前
【大白话说Java面试题】【Java基础篇】第17题:HashMap的加载因子为什么是0.75而不是1或0.5
java·开发语言·算法·哈希算法·散列表
谭欣辰2 小时前
C++ 哈希表详解
c++·算法·哈希算法·散列表
AKA__Zas2 小时前
初识多线程(初初识)
java·服务器·开发语言·学习方法
zhangrelay2 小时前
三分钟云课实践速通--概率统计--python版
linux·开发语言·笔记·python·学习·ubuntu
blasit2 小时前
Qt C++ http服务器安全登录token生成管理
c++·后端·qt
云栖梦泽2 小时前
Linux内核与驱动:GPIO设备树与SPI设备树的区别
linux·运维·c++·嵌入式硬件