这篇博客是 B 站《古月·ROS2入门21讲》的第六个视频的图文记录,主要介绍了如何创建工作空间、功能包以及编译工作空间,但我在这里补充了一处如何创建 C++、Python 混用的功能包。原始视频链接如下:

【Note】:该系列博客跳过了视频列表中的第五个,因为该视频介绍的是开发环境的配置,例如安装 git 和 vscode 之类,如果你想学习一下可以通过下面的链接查看:


工作空间

工作空间是 ROS 中一个非常重要的概念,在同一个工作空间中可以有多个不同的功能包。

1. 创建工作空间

这里为了和视频保持一致将工作空间命令也为 dev_ws(但我将工空间放在了 Desktop 目录下),在创建工作空间的时候你需要递归创建一个 src 文件夹放在里面:

$ mkdir -p dev_ws/src

然后进入到该工作空间的 src 目录下拉取源码,源码在古月居的 Github 仓库中:

在这里插入图片描述

$ cd dev_ws/src
$ git clone https://github.com/guyuehome/ros2_21_tutorials.git

在这里插入图片描述

如果你是刚开始使用这个环境,那么还需要安装一下 python-pip 工具,使用下面的命令安装:

$ sudo apt-get install python3-pip

在这里插入图片描述

【Note】:如果你按照我的博客顺序安装的 ros (即使用鱼香 ROS 一键安装命令),那么下面两行代码是不用执行的,如果你是按照 ROS 官方提供的命令则需要执行。

$ sudo pip3 install rosdepc
$ sudo rosdepc init & rosdepc update

2. 构建工作空间

2.1 安装依赖库

返回到工作空间根目录 dev_ws 执行下面的命令,该命令会自动查找你的工作空间中的包所需的依赖并自行安装:

$ rosdepc install -i --from-path src --rosdistro humble -y

显示以下内容表示依赖安装成功:

在这里插入图片描述


2.2 编译工作空间

先安装 colcon 工具,如果你之前用过 ROS1 的话会知道工作空间的构建工具是 catkincolcon 是 ROS2 提供的一个优化后的构建工具:

$ sudo apt-get install python3-colcon-ros

在这里插入图片描述

在工作空间 dev_ws 目录下使用下面的命令编译工作空间:

$ colcon build

如果你在运行后出现以下报错:

    File "/opt/ros/humble/local/lib/python3.10/dist-packages/rosidl_adapter/resource/__init__.py", line 19, in <module>
      import em

  ModuleNotFoundError: No module named 'em'

Call Stack (most recent call first):
  /opt/ros/humble/share/rosidl_cmake/cmake/rosidl_generate_interfaces.cmake:130 (rosidl_adapt_interfaces)
  CMakeLists.txt:25 (rosidl_generate_interfaces)

在这里插入图片描述

该报错通常是因为安装 ROS 是在安装 conda 之前,首先 删除 src 目录之前的所有文件删除,然后退出 conda 后重新编译:

(base) $ conda deactivate 
$ colcon build

在这里插入图片描述

成功编译后在工作空间中会自动生成三个新的文件夹 buildinstalllog

在这里插入图片描述


3. 配置环境变量

在工作空间 dev_ws 编译后生成的 install 目录下可以看到以下几个文件:

在这里插入图片描述

在当前终端中 source 其中的 local_setup.sh 即可让当前终端获得该工作空间下的环境变量:

$ source install/local_setup.sh

在这里插入图片描述

如果你想要在随便新开的一个终端中都能用该工作空间的功能包,那么需要将这个文件的 绝对路径 写入到 ~/.bashrc 文件中。但我个人 不推荐 这样做,原因如下:

  1. 该工作空间不能轻易移动:由于写入的绝对路径,如果你将工作空间移动到新的位置导致路径改变,那么新开的终端依旧找不到该工作空间;
  2. 存在重名功能包风险:如果你有多个工作空间,且没做好功能包命名管理,那么可能会存在重名的功能包使得想要运行的节点出现混乱;

功能包

功能包是工作空间的一个组件,一个功能包下面可以有多个节点。

【Note】:由于拉取的源码中已经有了同名功能包,直接执行创建命令后会报错,因此建议新开一个工作空间感受一下创建命令

这里在先前的 dev_ws 同级目录下新建一个 exec_ws 工作空间:

$ mkdir -p exec_ws/src
$ cd exec_ws/src

在这里插入图片描述

【Note】:原视频在创建功能包时没有添加依赖包,但通常在创建时会加上参数 --dependencies 表示依赖包,如:

$ ros2 pkg create --build-type ament_cmake demo --dependencies rclcpp rclpy std_msgs

1 创建 python 功能包

如果你在该功能包中只使用 python 则用下面的命令创建:

$ ros2 pkg create --build-type ament_python learning_python

在这里插入图片描述

该功能包中有以下文件,核心是 setup.py 文件,该文件用来指明该包中有哪些脚本将被视作节点:

在这里插入图片描述


2 创建 C++ 功能包

如果你在该功能包中只使用 python 则用下面的命令创建:

$ ros2 pkg create --build-type ament_cmake learning_c

在这里插入图片描述

该功能包中有以下文件,核心是 CMakelists.txt 文件,该文件用来指明哪些 C++ 文件将被编译城节点:

在这里插入图片描述


3 创建 C++ 和 python 的混合功能包

【Note】:这部分内容原始视频中是没有的,只是因为我平时经常用到,所以添加到这里

3.1 创建 C++ 基座功能包

因为 ament_cmake 是更通用的构建系统,它不仅可以编译 C++,还被设计为可以“调用” Python 的 setuptools 来处理包内的 Python 代码。纯 Python 包使用的 ament_python 则无法编译 C++。所以需要先用 ament_cmake 进行功能包构建,然后再添加依赖。

$ ros2 pkg create --build-type ament_cmake learning_mix

在这里插入图片描述

在该功能包下有以下文件:

在这里插入图片描述


3.2 创建 setup.py 文件

在该功能包中创建一个 setup.py 文件,该文件与 CMakeLists.txt 在同一级目录下,然后将以下内容写入,其核心内容与 1.3 中创建的纯 python 功能包中的 setup.py 文件一致,但要注意包名要修改:

from setuptools import find_packages, setup

package_name = 'learning_mix'

setup(
    name=package_name,
    version='0.0.0',
    # 声明 Python 包的查找路径
    packages=[package_name],
    
    # 需要安装的数据文件(例如 package.xml, launch 文件等)
    data_files=[
        ('share/ament_index/resource_index/packages',
            ['resource/' + package_name]),
        ('share/' + package_name, ['package.xml']),
        # 如果有 launch 文件
        # ('share/' + package_name + '/launch', ['launch/my_launch.py']),
    ],
    install_requires=['setuptools'],
    zip_safe=True,
    maintainer='your_name',
    maintainer_email='you@example.com',
    description='TODO: Package description',
    license='TODO: License declaration',
    tests_require=['pytest'],
    
    # ----------------------------------------------------
    # 这是定义 Python 可执行文件的关键
    # ----------------------------------------------------
    entry_points={
        'console_scripts': [
            # 格式:'可执行文件名 = 模块路径:main函数'
            # 'my_py_node = learning_mix.py_node:main',
        ],
    },
)

3.3 创建 init.py 文件

exec_ws/src/learning_mix 目录下创建一个同名文件夹 leanring_mix 并添加一个空的 __init__.py 文件:

.
├── CMakeLists.txt
├── include
│   └── learning_mix
├── learning_mix				<-- Python 模块放这里
│   └── __init__.py
├── package.xml
├── setup.py					<-- 手动创建的 Python 配置文件
└── src							<-- C++ 源代码放这里

4 directories, 4 files

在这里插入图片描述


4. 编译工作空间

此时三个功能包都创建完了,你的文件结构应该如下所示:

在这里插入图片描述

回到工作空间 exec_ws 目录下构建工作空间:

$ colcon build

在这里插入图片描述

如果你只想编译指定的某个包可以用 --packages-select 参数,这样就只会编译 leanring_python 这个包:

$ colcon build --packages-select leanring_python

在这里插入图片描述

Logo

立足具身智能前沿赛道,致力于搭建全球化、开源化、全栈式技术交流与实践共创平台。

更多推荐