【多喝热水系列】从零开始的ROS2之旅——Day5 再遇ROS2功能包:Python和C++功能包编写

【多喝热水系列】从零开始的ROS2之旅——Day5 再遇ROS2功能包:Python和C++功能包编写

【多喝热水系列】从零开始的ROS2之旅——Day5

大家好,这里是【多喝热水系列】从零开始的ROS2之旅第五天!经过前几天的铺垫,我们已经对ROS2的核心概念和基础环境有了一定了解,今天的重点是实战操作——分别完成Python和C++功能包的创建与编译,再把这些功能包整合到工作空间中处理依赖关系,最后还会分享一个Ubuntu系统卡登录界面的踩坑解决方案。话不多说,直接上干货!

一、Python功能包创建和编译

ROS2中功能包是代码组织的基本单位,不同编程语言的功能包创建和编译流程略有差异,先从相对简洁的Python功能包开始。

1.1 创建Python功能包

#建立一个Python语言的功能包 ros2 pkg create demo_python_pkg --build-type ament_python --license Apache-2.0 

结果如下图所示:

1.2 简单编写测试节点

为了验证功能包可用,我们在demo_python_pkg/demo_python_pkg目录下创建一个简单的节点文件python_node.py,实现基础的日志输出:

#demo_python_pkg/demo_python_pkg/python_node.py的节点内容import rclpy from rclpy.node import Node defmain(): rclpy.init() node = Node("python_node") node.get_logger().info("Hello from Python node!") rclpy.spin(node) node.destroy_node() rclpy.shutdown()

1.3 给当前packages.xml添加依赖

#packages.xml添加依赖<depend>rclpy</depend>

1.4 配置setup.py

#setup.py添加的内容 entry_points={'console_scripts':['python_node = demo_python_pkg.python_node:main',#当前面的python_node是你运行时的命令,就相当于执行demo_python_pkg目录下python_node文件中的main函数],},

1.5 编译Python功能包

colcon build 

若编译无报错,会在工作空间根目录生成build、install、log三个文件夹,其中install目录下存放编译后的可执行文件。

1.6 验证功能包

source install/setup.bash echo$AMENT_PREFIX_PATH ros2 run demo_python_pkg python_node 

运行结果:

在这里插入图片描述

1.7 出现的问题及解决方案:

在这里插入图片描述

解决方法:
看看你文件是否Ctrl+s保存,如果未保存会出现编译无可执行文件的问题。
建议把Vscode里面自动保存开启。

操作后文件列表如下所示:

在这里插入图片描述

二、C++功能包

C++功能包的构建类型为ament_cmake,相比Python包多了CMakeLists.txt配置步骤,下面详细说明。

2.1 创建C++功能包

#建立一个C++语言的功能包![请添加图片描述](https://i-blog.ZEEKLOGimg.cn/direct/3cace60e198c422a9bf4e2d0d5267b00.png) ros2 pkg create demo_cpp_pkg --build-type ament_cmake --license Apache-2.0 

结果如图所示:

在这里插入图片描述

2.2 编写测试节点

//demo_cpp_pkg/src/cpp_node.cpp的节点内容#include"rclcpp/rclcpp.hpp"#include<iostream>usingnamespace std;intmain(int argc,char**argv){ rclcpp::init(argc, argv);auto node =make_shared<rclcpp::Node>("cpp_node");RCLCPP_INFO(rclcpp::get_logger("cpp_node"),"Hello from C++ node!"); rclcpp::spin(node); rclcpp::shutdown();return0;}

2.3 配置CMakeLists.txt(核心步骤)

#CMakeLists.txt文件添加的内容 find_package(rclcpp REQUIRED)#1.查找可执行文件的头文件和库文件 add_executable(cpp_node src/cpp_node.cpp)#2.添加可执行文件 cpp_node ament_target_dependencies(cpp_node rclcpp)#3.为可执行文件添加依赖项 rclcpp‘ install(TARGETS cpp_node DESTINATION lib/${PROJECT_NAME})#4.将编译好的可执行文件复制到安装目录 lib/demo_cpp_pkg 下

2.4 packages.xml添加依赖

#packages.xml添加依赖<depend>rclcpp</depend>

2.5 编译C++功能包

colcon build 

2.6 验证功能包

source install/setup.bash ros2 run demo_cpp_pkg cpp_node 

运行结果:

在这里插入图片描述

操作后文件列表如下所示:

在这里插入图片描述

三、多功能包的最佳实践Workspace

实际开发中,可能会遇到需要将已创建的功能包移入指定工作空间。

3.1 功能包移入workspace

mkdir-p chapt2_ws/src 
请添加图片描述


编译结果如下:

请添加图片描述


3.2 处理demo_python_pkg对demo_cpp_pkg的依赖
处理功能包之间依赖的情况。这里我们模拟“demo_python_pkg依赖demo_cpp_pkg”的场景,说明完整的处理流程。

3.2.1 配置demo_python_pkg的package.xml

#demo_python_pkg的packages.xml添加依赖<depend>demo_cpp_pkg</depend>

编译结果如下:

请添加图片描述

运行时遇到的问题: Ubuntu熄屏卡登入界面方法

首先Ctrl+alt+f3进入命令界面,
然后把自己的用户名和密码输入之后,
再Ctrl+alt+f2把密码再输入一遍,
即可解决此问题。

四、总结
今天的ROS2实战之旅收获满满,我们不仅掌握了Python和C++功能包的创建、编译流程,还学会了处理功能包之间的依赖关系,同时解决了Ubuntu卡登录界面的小问题。功能包是ROS2开发的基础,后续的节点通信、服务客户端等功能都需要基于功能包展开,建议大家多动手实操,熟悉每个步骤的细节。

下一期我们将继续深入ROS2,学习节点之间的话题通信,敬请期待!如果今天的内容对你有帮助,别忘了点赞、收藏、关注,我们下期见!

Read more

C++之动态数组vector

C++之动态数组vector

Vector * 一、什么是 `std::vector`? * 二、`std::vector` 的基本特性 * (一)动态扩展 * (二)随机访问 * (三)内存管理 * 三、`std::vector` 的基本操作 * (一)定义和初始化 * (二)添加和删除元素 * (三)访问元素 * (四)遍历 * (五)大小和容量 * 四、`std::vector` 的应用场景 * (一)动态数组 * (二)随机访问 * (三)内存管理 * 五、注意事项 * (一)性能优化 * (二)内存释放 * (三)异常安全 * 六、总结 在

By Ne0inhk
【C++:C++11收尾】解构C++可调用对象:从入门到精通,掌握function包装器与bind适配器包装器详解

【C++:C++11收尾】解构C++可调用对象:从入门到精通,掌握function包装器与bind适配器包装器详解

🎬 个人主页:艾莉丝努力练剑 ❄专栏传送门:《C语言》《数据结构与算法》《C/C++干货分享&学习过程记录》 《Linux操作系统编程详解》《笔试/面试常见算法:从基础到进阶》《Python干货分享》 ⭐️为天地立心,为生民立命,为往圣继绝学,为万世开太平 🎬 艾莉丝的简介: 🎬 艾莉丝的C++专栏简介: 文章目录 * C++学习阶段的三个参考文档 * 8 ~> 包装器 * 8.1 function * 8.1.1 结构 * 8.1.2 概念 * 8.1.3 function实现 * 8.1.4 重写逆波兰表达式求值 * 8.2 bind

By Ne0inhk
精通 Redis list:使用 redis-plus-plus 的现代 C++ 实践深度解析

精通 Redis list:使用 redis-plus-plus 的现代 C++ 实践深度解析

在构建高性能应用的世界里,Redis 闪电般的内存数据结构与 C++ 的原生性能相结合,无疑是一剂成功的良方。Redis,常被称为“数据结构服务器”,提供了多种功能强大的工具,其中最基础也最核心的之一便是列表(List)。这种有序的字符串集合是实现队列、栈、活动流、消息推送等众多功能的基石。 为了在 C++ 和 Redis 之间架起一座坚实的桥梁,一个健壮的客户端库至关重要。在这方面,redis-plus-plus 以其现代、类型安全和直观的设计脱颖而出。作为一个现代 C++11/14/17 客户端,它将 Redis 命令与开发者熟悉的 C++ 范式(如迭代器、optional 和 chrono 字面量)无缝集成。 本篇深度指南将引导您逐步探索 Redis 列表的核心命令,并通过由 redis-plus-plus 驱动的实用 C+

By Ne0inhk
【C++】【STL】别再混淆!C++容器适配器不是“容器”,这篇讲清它的本质

【C++】【STL】别再混淆!C++容器适配器不是“容器”,这篇讲清它的本质

🔥拾Ծ光:个人主页 👏👏👏欢迎来到我的专栏:《C++》,《C++类和对象》,《数据结构》,《C语言》 📌文档:栈(stack),队列(queue),双端队列(deque),priority_queue 与本文相关博客:《容器进阶:deque的“双端优势” vs list的“链式灵活” vs vector的“连续高效”》 在前面的一篇文章我们讲解了deque容器,其非常适合作为适配器stack和queue的底层数据结构,下面我就来带大家看看这两个适配器是如何与deque结合的! 一、什么是容器适配器? 在 C++ 标准库中,容器适配器(Container Adapters) 是一种基于现有容器实现的特殊容器,它们提供了更特定的接口和功能,隐藏了底层容器的部分特性,仅暴露适配后的操作方式。 ⭐️容器适配器不直接存储数据,而是通过封装底层容器(如

By Ne0inhk