ROS2高效学习第三章 -- 梳理 ros 编译工具,开始 ros2 编程,第一个 hello ros2 样例

1 背景和资料

从本文开始,我们学习 ros2 编程,每一个样例我们都会用 c++ 和 python 实现两次,感受两套语言实现的区别。本文我们重点介绍 ros 构建工具的发展历史,从而引入 colcon 和 ament 。然后分别实现 hello_ros2_cpp 和 hello_ros2_py,体验 ros2 的编译方式。至于如何搭建 ros2 环境,请参考本人上一篇文章 ROS2高效学习第二章 – ros2常用命令和相关概念学习,熟练玩起来小乌龟样例 .
本文参考资料如下:
(1)A universal build tool
(2)Colcon-Tutorial
(3)Creating-A-Workspace
(4)Creating-Your-First-ROS2-Package
(5)古月 ros2_21_tutorials
(6)git 简单教程
(7)Conan tutorial
本系列博客汇总:ROS2 高效学习系列

2 正文

2.1 ros 构建工具和构建系统梳理

(1)构建系统引入:学 Linux C/C++ 编程的人都知道,程序写出来,需要编程成二进制文件才能运行。C 语言的编译器就是 gcc ,C++ 的编译器就是 g++。如果你的程序只有一个 hello_world.cpp 文件,最简单的编译指令如下:

g++ -std=c++11 hello_world.cpp -o hello_world

但一个合格的程序员,不能只写 hello world 。稍微大一些的项目,就会有很多个 .cpp 和 .h 文件,他们彼此之间相互依赖。此时,把整个项目编译出一个可执行程序,这个过程就是构建。目前针对 C/C++ 程序,最常用的构建系统就是 cmake,其底层依赖 makefile,而最下层就是 gcc/g++。
(2)构建工具引入:对于 hello world 级别的程序,只需要一行编译指令就能解决构建问题。稍微大一点的项目,就需要构建系统了。如果项目再大一点,比如实现一个自动驾驶系统,就需要把整个系统分为很多个模块或软件包,分别进行开发。这些模块之间会彼此依赖,比如多个终端模块都依赖 log 日志模块。此时就需要引入构建工具,解决复杂系统内多模块的构建问题。
(3)构建工具和构建系统比较:
构建系统:构建系统的作用范围在单个模块或单个 ros 软件包,负责程序构建。
构建工具:构建工具的作用范围是整个大型系统或一组 ros 软件包,其根据依赖关系图,按照拓扑顺序调用每个包的特定构建系统,依次完成整个系统的构建任务。比如必须先编译 log 日志软件包,然后才能编译终端模块软件包。除了构建任务之外,构建工具还需要为程序运行设置环境变量,比如那个经典的 LD_LIBRARY_PATH 。
(4)ros 历代构建系统:ros1 时我们主要使用 cmake ,以及基于 cmake 的 catkin 构建系统。

find_package(catkin REQUIRED COMPONENTS roscpp rospy std_msgs)

到 ros2 时,我们将使用 ament_cmake,其源于 catkin ,也基于 cmake 。针对 python 软件包 ,ros2 还引入了 setuptools ,这是 python 常用的打包工具。按理说 python 属于解释型语言,不需要编译,setuptools 只是打包工具,但我们仍把他作为一种构建系统。
(5)ros 历代构建工具:ros1 时我们主要使用 catkin_make 构建工具,其继承自 rosbuild 。

catkin_make --source src/hello_ros/

在 catkin_make 之后,ros1 还发布了 catkin_make_isolated ,catkin_tools 。到 ros2 ,ROS 官方先发布了 ament_tools ,后来又重新开发了 colcon (collective construction,集中构建)构建工具。
(6)为啥重新开发 colcon :ros 经过 ros1 ,ros2 两个大版本的迭代,积累了多款构建工具和构建系统,急需一款统一的构建工具,能同时解决多种版本(ros1,ros2),多种语言(c++ ,python),多种平台(linux,mac,windows)的构建问题。因此重新开发了 colcon。命名方式上也不再坚持构建工具与构建系统的统一,如 catkin和 catkin_make,ament 和 ament_tools,以此强调 colcon 能支持多种构建系统。colcon 也将是 ros 未来唯一的构建工具,更详细的信息可以参考 ros build_tool
(7)构建工具不支持的功能:ros 的构建工具不支持代码拉取功能;不支持安装包依赖项功能,依赖项需要自己在构建之前手动安装好;不支持创建二进制包功能,例如 Debian 包。

2.2 CI/CD 粗讲

(1)CI/CD 概念:Continuous Integration (持续集成),Continuous Deployment (持续部署),这是软件工程中非常重要的概念,也是一种软件开发实践。旨在帮助软件团队快速、可靠地交付他们的产品。
(2)CI/CD 粗讲:在 CI 这步,首先需要一个版本控制系统,当前最好用的就是 git( git 简单教程) 。围绕着 git ,一般会在主线分支上设置静态代码检查,用来检测每一笔提交的质量,比如命名规范等。还会设置自动化单元测试,看守代码功能,并进行代码覆盖率分析。
然后就需要一个工具,很类似 ros 的构建工具,能依次实现代码拉取,代码构建,二进制包管理(如C++ Conan,Conan tutorial)和二进制产物生成。
最后就是 CD,其自动化的把二进制产物部署到测试或生成环境,运行集成测试和冒烟测试。
(3)整个 CI 和 CD 过程几乎涉及软件工程的方方面面,这里推荐一本书:持续交付 发布可靠软件的系统方法,Jez Humble / David Farley

2.3 创建工作空间以及配置 colcon

(1)创建工作空间

mkdir -p ~/colcon_ws/src

(2)配置 colcon_cd :ros1 中有 roscd 命令,可以方便的进行软件包目录切换。到 ros2 ,对应的是 colcon_cd,但需要手动配置一下

echo "source /usr/share/colcon_cd/function/colcon_cd.sh" >> ~/.bashrc
echo "export _colcon_cd_root=/opt/ros/humble/" >> ~/.bashrc

测试命令:

source ~/.bashrc
colcon_cd turtlesim

(3)colcon 有很多命令选项,用户最好设置下他的命令联想功能,方便使用:

echo "source /usr/share/colcon_argcomplete/hook/colcon-argcomplete.bash" >> ~/.bashrc

2.4 hello_ros2_cpp

(1)创建 hello_ros2_cpp 软件包和相关文件

cd ~/colcon_ws/src
ros2 pkg create --build-type ament_cmake  --license Apache-2.0 hello_ros2_cpp
cd hello_ros2_cpp/src
touch hello_ros2.cpp

(2)编写 hello_ros2.cpp

// rcl 是指 ROS Client Library 的缩写,它是 ROS 2 中的一个底层库。
// rcl 抽象了底层的中间件通信功能,为上层的客户端库提供统一的 API 接口。
// 在ros c++ 编程中,我们使用 rclcpp;ros python 编程中,我们使用 rclpy
#include "rclcpp/rclcpp.hpp"
// ros2 更推荐用户使用面向对象编程 OOP,
// 它提供了一种清晰且结构化的方式来组织和管理复杂的软件系统,
// 而机器人软件需要 OOP 的这些优点。
class HelloRos2 : public rclcpp::Node {
public:
    HelloRos2() : Node("hello_ros2") {
        RCLCPP_INFO(this->get_logger(), "start hello ros2 in cpp !!");
    }
    void run() {
        while(rclcpp::ok()) {
            RCLCPP_INFO(this->get_logger(), "hello ros2 in cpp !!");
            sleep(1);
        }
    }
};

int main(int argc, char* argv[]) {
    rclcpp::init(argc, argv);
    auto node = std::make_shared<HelloRos2>();
    node->run();
    rclcpp::shutdown();
    return 0;
}

(3)编写CmakeLists.txt

cmake_minimum_required(VERSION 3.8)
project(hello_ros2_cpp)
find_package(ament_cmake REQUIRED)
// 下面四句是手动添加的,不可少
find_package(rclcpp REQUIRED)
add_executable(${PROJECT_NAME} src/hello_ros2.cpp)
ament_target_dependencies(${PROJECT_NAME} rclcpp)
install(TARGETS
  ${PROJECT_NAME}
  DESTINATION lib/${PROJECT_NAME})
ament_package()

(4)编译并运行

~/colcon_ws
colcon build --packages-select hello_ros2_cpp
source install/local_setup.bash
ros2 run hello_ros2_cpp hello_ros2_cpp

在这里插入图片描述

2.5 hello_ros2_py

(1)创建 hello_ros2_py 软件包和相关文件

cd ~/colcon_ws/src
ros2 pkg create --build-type ament_python --license Apache-2.0 hello_ros2_py
cd hello_ros2_py/hello_ros2_py
touch hello_ros2.py

(2)编写 hello_ros2.py

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

# ros python 编程使用rclpy,也推荐面向对象
import rclpy
from rclpy.node import Node
import time
class HelloRos2(Node):
    def __init__(self, name):
        super().__init__(name)
        self.get_logger().info("start hello_ros2_py node !!")
        
    def run(self):
        try:
            while rclpy.ok():
                self.get_logger().info("hello ros2 in python !!")
                time.sleep(1)
        except KeyboardInterrupt:
            self.get_logger().info("Node was interrupted, shutting down...")

def main(args=None):
    rclpy.init(args=args)
    node = HelloRos2("hello_ros2_py")
    try:
        node.run()
    except KeyboardInterrupt:
        node.destroy_node()
        rclpy.shutdown()

if __name__ == '__main__':
    main()

(3)编写 setup.py

from setuptools import find_packages, setup
package_name = 'hello_ros2_py'
setup(
    name=package_name,
    version='0.0.0',
    packages=find_packages(exclude=['test']),
    data_files=[
        ('share/ament_index/resource_index/packages',
            ['resource/' + package_name]),
        ('share/' + package_name, ['package.xml']),
    ],
    install_requires=['setuptools'],
    zip_safe=True,
    maintainer='ycao',
    maintainer_email='1641395022@qq.com',
    description='TODO: Package description',
    license='Apache-2.0',
    tests_require=['pytest'],
    entry_points={
        'console_scripts': [
        	# 其他都是自动生成的,只有这里需要修改
        	# ros2 引入了 setuptools ,这里的setup.py 用来定义程序的入口
        	# 这里的格式请遵循:'my_node = my_py_pkg.my_node:main'
            'hello_ros2 = hello_ros2_py.hello_ros2:main'
        ],
    },
)

(4)编译并运行

~/colcon_ws
colcon build --packages-select hello_ros2_py
source install/local_setup.bash
ros2 run hello_ros2_py hello_ros2

在这里插入图片描述
(5)踩坑记录
第一,编译 hello_ros2_py 时,总是遇到:

--- stderr: hello_ros2_py
/usr/lib/python3/dist-packages/setuptools/command/install.py:34: SetuptoolsDeprecationWarning: setup.py install is deprecated. Use build and pip and other standards-based tools.
  warnings.warn(
---

解决:setuptools 必须使用 58 版本,参考:setuptools执行问题

pip install setuptools==58

第二,运行 hello_ros2_py 时,总是遇到:

ModuleNotFoundError: No module named 'hello_ros2_py'
[ros2run]: Process exited with failure 1

解决:下面这个文件不能删除,尽管他是空白的。

hello_ros2_py/hello_ros2_py/__init__.py

总结

这篇文章从想写到写完,将近一个月,进度实在令人抱歉。得益于媳妇的支持,最终在春节假期结束前赶出来了,完成后确实有一吐为快的感觉。本文样例托管在本人的 github 上:ros2_code

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值