2.1.2 ROS2 C++ 示例

2.1.2 C++ 示例

ROS 2 在不同语言之间的接口几乎时相同的

在写 C++ 版本的 ROS 程序时,要在 main 函数中加入 argcargv,这其实就是一个入口参数,用于获取用户输入的命令,并且将命令进行分割。

下面我们先打印一下 argcargv

cpp 复制代码
#include "iostream"

int main(int argc, char** argv)
{
    std::cout << "参数数量 = " << argc << std::endl;
    std::cout << "程序名称 = " << argv[0] << std::endl;
    return 0;
}
bash 复制代码
$ g++ ros2_cpp_node.cpp 
$ ./a.out 
参数数量 = 1
程序名称 = ./a.out
$ ./a.out --help
参数数量 = 2
程序名称 = ./a.out
$ ./a.out --help 1 2 3
参数数量 = 5
程序名称 = ./a.out

如果我们想要让 --help 有输出,应该怎么做呢?

cpp 复制代码
#include "iostream"

int main(int argc, char** argv)
{
    std::cout << "参数数量 = " << argc << std::endl;
    std::cout << "程序名称 = " << argv[0] << std::endl;

    std::string arg1 = argv[1];
    if(arg1 == "--help")
    {
        std::cout << "其实这个函数什么用都没有" << std::endl;
    }
    return 0;
}

下面我们来写 C++ 节点

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

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

但是现在直接编译的话会报错

bash 复制代码
$ g++ ros2_cpp_node.cpp 
ros2_cpp_node.cpp:1:10: fatal error: rclcpp/rclcpp.hpp: No such file or directory
    1 | #include "rclcpp/rclcpp.hpp"
      |          ^~~~~~~~~~~~~~~~~~~
compilation terminated.

原因时之前的 include 在系统库里面,但是 rclcpp 是不在系统库里面的。因为使用 g++ 去导库非常麻烦,所以我们使用 CMake 导库

txt 复制代码
cmake_minimum_required(VERSION 3.8)
project(ros2_cpp)
add_executable(ros2_cpp_node ros2_cpp_node.cpp)

其中 add_executable(ros2_cpp_node ros2_cpp_node.cpp) 的第一个 ros2_cpp_node 表示可执行文件的名字,第二个 ros2_cpp_node.cpp 是文件名字。

现在我们还没有添加依赖,先使用 cmake

bash 复制代码
$ cmake .
-- The C compiler identification is GNU 11.4.0
-- The CXX compiler identification is GNU 11.4.0
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /usr/bin/cc - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: /home/hw/Development/shx-notebooks/ros_study/chapt02

如果直接使用 make 编译,会出现和 g++ 一样的错误

bash 复制代码
$ make
[ 50%] Building CXX object CMakeFiles/ros2_cpp_node.dir/ros2_cpp_node.cpp.o
/home/hw/Development/shx-notebooks/ros_study/chapt02/ros2_cpp_node.cpp:1:10: fatal error: rclcpp/rclcpp.hpp: No such file or directory
    1 | #include "rclcpp/rclcpp.hpp"
      |          ^~~~~~~~~~~~~~~~~~~
compilation terminated.
make[2]: *** [CMakeFiles/ros2_cpp_node.dir/build.make:76: CMakeFiles/ros2_cpp_node.dir/ros2_cpp_node.cpp.o] Error 1
make[1]: *** [CMakeFiles/Makefile2:83: CMakeFiles/ros2_cpp_node.dir/all] Error 2
make: *** [Makefile:91: all] Error 2

因为 make 这个命令也是根据 Makefile 这个文件去调用 g++ 编译,本质还是 g++。下面我们使用 CMakeLists 里的 find_package 去找到 rclcpp,其中 REQUIRED 是表示这个包是必需的

txt 复制代码
cmake_minimum_required(VERSION 3.8)
project(ros2_cpp)
add_executable(ros2_cpp_node ros2_cpp_node.cpp)

find_package(rclcpp REQUIRED)

重新运行 cmake

bash 复制代码
$ cmake .
-- Found rclcpp: 16.0.15 (/opt/ros/humble/share/rclcpp/cmake)
-- Found Python3: /usr/bin/python3 (found version "3.10.12") found components: Interpreter 
-- Found rosidl_generator_c: 3.1.7 (/opt/ros/humble/share/rosidl_generator_c/cmake)
-- Found rosidl_adapter: 3.1.7 (/opt/ros/humble/share/rosidl_adapter/cmake)
-- Found rosidl_generator_cpp: 3.1.7 (/opt/ros/humble/share/rosidl_generator_cpp/cmake)
-- Using all available rosidl_typesupport_c: rosidl_typesupport_fastrtps_c;rosidl_typesupport_introspection_c
-- Using all available rosidl_typesupport_cpp: rosidl_typesupport_fastrtps_cpp;rosidl_typesupport_introspection_cpp
-- Found rmw_implementation_cmake: 6.1.2 (/opt/ros/humble/share/rmw_implementation_cmake/cmake)
-- Found rmw_fastrtps_cpp: 6.2.9 (/opt/ros/humble/share/rmw_fastrtps_cpp/cmake)
-- Found OpenSSL: /usr/lib/x86_64-linux-gnu/libcrypto.so (found version "3.0.2")  
-- Found FastRTPS: /opt/ros/humble/include  
-- Using RMW implementation 'rmw_fastrtps_cpp' as default
-- Looking for pthread.h
-- Looking for pthread.h - found
-- Performing Test CMAKE_HAVE_LIBC_PTHREAD
-- Performing Test CMAKE_HAVE_LIBC_PTHREAD - Success
-- Found Threads: TRUE  
-- Configuring done
-- Generating done
-- Build files have been written to: /home/hw/Development/shx-notebooks/ros_study/chapt02

-- Found rclcpp: 16.0.15 (/opt/ros/humble/share/rclcpp/cmake) 可以得知成功找到了 rclcpp/opt/ros/humble/share/

因此,加上 find_package(rclcpp REQUIRED) 就可以找到 rclcpp 的路径,使用rclcpp_INCLUDE_DIRSrclcpp_LIBRARIES 找到对应的头文件和库文件然后写到 rclcpp_INCLUDE_DIR 目录里面去,我们可以使用 CMakeList 打印消息的方法打印出来

cpp 复制代码
cmake_minimum_required(VERSION 3.8)
project(ros2_cpp)
add_executable(ros2_cpp_node ros2_cpp_node.cpp)

find_package(rclcpp REQUIRED)  # 直接查找对应的头文件和库文件
message(STATUS ${rclcpp_INCLUDE_DIRS})  # 头文件及 rclcpp 依赖的头文件
message(STATUS ${rclcpp_LIBRARIES})  # 库文件及 rclcpp 依赖的库文件

可以使用 cmake . | grep rclcpp 来查看,输出很多,不再展示

输出很多的原因是使用 find_package 查找 rclcpp 时,会将 rclcpp 的依赖也查找并添加进去,就像套娃一样,一层套一层。

找到头文件和库文件之后,必须添加进去才能执行 make ,否则依然会报错

cpp 复制代码
cmake_minimum_required(VERSION 3.8)
project(ros2_cpp)
add_executable(ros2_cpp_node ros2_cpp_node.cpp)

find_package(rclcpp REQUIRED)  # 直接查找对应的头文件和库文件
message(STATUS ${rclcpp_INCLUDE_DIRS})  # 头文件及 rclcpp 依赖的头文件
message(STATUS ${rclcpp_LIBRARIES})  # 库文件及 rclcpp 依赖的库文件

target_include_directories(ros2_cpp_node PUBLIC ${rclcpp_INCLUDE_DIRS})  # 头文件包含
target_link_libraries(ros2_cpp_node ${rclcpp_LIBRARIES})  # 库文件链接
  • target_include_directories(ros2_cpp_node PUBLIC ${rclcpp_INCLUDE_DIRS}) 其中第一个 ros2_cpp_node 是可执行文件的名字,第二个 ${rclcpp_INCLUDE_DIRS} 是头文件
  • target_link_libraries(ros2_cpp_node ${rclcpp_LIBRARIES}) 其中第一个 ros2_cpp_node 是可执行文件的名字,第二个 ${rclcpp_LIBRARIES} 是库文件

下面就再次使用 cmake .make 去编译

bash 复制代码
$ make
[ 50%] Building CXX object CMakeFiles/ros2_cpp_node.dir/ros2_cpp_node.cpp.o
[100%] Linking CXX executable ros2_cpp_node
[100%] Built target ros2_cpp_node

执行可执行文件 ros2_cpp_node

bash 复制代码
$ ./ros2_cpp_node 
[INFO] [1764560464.478290756] [cpp_node]: 你好 C++ 节点

打开一个新终端,使用 ros2 node list 查看当前节点,使用 ros2 node info /cpp_node 查看节点的相关信息

bash 复制代码
hw@LAPTOP-OF07PRPE:~/Development/shx-notebooks$ ros2 node list
/cpp_node
hw@LAPTOP-OF07PRPE:~/Development/shx-notebooks$ ros2 node info /cpp_node 
/cpp_node
  Subscribers:
    /parameter_events: rcl_interfaces/msg/ParameterEvent
  Publishers:
    /parameter_events: rcl_interfaces/msg/ParameterEvent
    /rosout: rcl_interfaces/msg/Log
  Service Servers:
    /cpp_node/describe_parameters: rcl_interfaces/srv/DescribeParameters
    /cpp_node/get_parameter_types: rcl_interfaces/srv/GetParameterTypes
    /cpp_node/get_parameters: rcl_interfaces/srv/GetParameters
    /cpp_node/list_parameters: rcl_interfaces/srv/ListParameters
    /cpp_node/set_parameters: rcl_interfaces/srv/SetParameters
    /cpp_node/set_parameters_atomically: rcl_interfaces/srv/SetParametersAtomically
  Service Clients:

  Action Servers:

  Action Clients:
相关推荐
lightqjx1 小时前
【C++】对set和map的使用
开发语言·数据结构·c++·stl
快乐zbc1 小时前
C++ 中 typedef 指针别名与 const 的坑
开发语言·c++
azoo2 小时前
cv::Mat 取元素引起的报错
c++·opencv·计算机视觉
一个不知名程序员www2 小时前
算法学习入门---list与算法竞赛中的链表题(C++)
c++·算法
Aevget2 小时前
从业务面板到多视图协同:QtitanDocking如何驱动行业级桌面应用升级
c++·qt·ui·ui开发·qt6.3
蕓晨2 小时前
钱币找零问题-贪心算法解析
c++·算法·贪心算法
hetao17338372 小时前
2025-12-04 hetao1733837的刷题记录
c++·算法
mjhcsp2 小时前
C++ 后缀自动机(SAM):原理、实现与应用全解析
java·c++·算法
liu****3 小时前
13.数据在内存中的存储
c语言·开发语言·数据结构·c++·算法