Yocto环境下编译ROS2、自定义layer添加ros代码以及ament_cmake和No module name 'ament_package'问题解决

0. 最近想在A核上搭建一套ros环境,然后再配合MCU实现一些小功能

1. Yocto编译ROS2

a. 添加meta层

将需要的依赖layer添加到build/conf/bblayers.conf中

meta-oe meta-python meta-ros-common meta-ros2 meta-ros2-humble

b. 添加本地配置文件

c. 进行编译

d. 编译完成,至此带有ros2的yocto镜像编译完成。

2. 自定义layer添加ros代码

a. 创建自定义layer层

1
$ bitbake-layers create-layer ../../meta-ros-publisher

b. 在layer中创建ros代码目录

使能ros环境

1
$ source /opt/ros/jazzy/setup.bash
1
$ ros2 pkg create --build-type ament_cmake --license Apache-2.0 files

以下是创建的meta-ros-publisher的项目目录

c. 添加在~/Free/yocto/meta-ros-publisher/recipes-ros-publisher/ros-publisher/files/src目录下添加我们的ros代码,创建一个简单的talker通过topic来发布信息

1
$ vim ros_publisher_function.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#include <chrono>
#include <memory>
#include <string>

#include "rclcpp/rclcpp.hpp"
#include "std_msgs/msg/string.hpp"

using namespace std::chrono_literals;

class MinimalPublisher : public rclcpp::Node
{
public:
MinimalPublisher()
: Node("minimal_publisher"), count_(0)
{
publisher_ = this->create_publisher<std_msgs::msg::String>("topic", 10);
auto timer_callback =
[this]() -> void {
auto message = std_msgs::msg::String();
message.data = "Hello, world!" + std::to_string(this->count_++);
RCLCPP_INFO(this->get_logger(), "Publishing: '%s'", message.data.c_str());
this->publisher_->publish(message);
};
timer_ = this->create_wall_timer(500ms, timer_callback);
}

private:
rclcpp::TimerBase::SharedPtr timer_;
rclcpp::Publisher<std_msgs::msg::String>::SharedPtr publisher_;
size_t count_;
};

int main(int argc, char **argv)
{
rclcpp::init(argc, argv);
rclcpp::spin(std::make_shared<MinimalPublisher>());
rclcpp::shutdown();

return 0;
}

d. 编写bb文件

在 Yocto 项目中,meta-xxx/recipes-xxx/*.bb 文件(.bb 文件)就是 BitBake recipe,也就是构建某个软件包「食谱」,它的作用包括:

  • 描述包信息:如包名、版本、摘要、许可证等。

  • 定义构建源码获取方式:通过 SRC_URI 指定源码或二进制的位置。

  • 声明依赖关系:告诉 BitBake 构建这个包需要哪些其他包(DEPENDS、RDEPENDS)。

  • 指定构建流程:通过变量或默认任务(do_fetch、do_unpack、do_configure、do_compile、do_install 等)告诉系统如何编译、安装和打包这个软件。

简单来说,每个 .bb 文件定义了你想在目标镜像或包中包含的一个组件,告诉 Yocto 如何抓源、打补丁、编译、安装、生成最终镜像。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
SUMMARY = "Example ROS2 Publisher Node"
LICENSE = "GPL-2.0-only"
LIC_FILES_CHKSUM = "file://package.xml;beginline=8;endline=8;md5=82f0323c08605e5b6f343b05213cf7cc"

ROS_BUILD_TYPE = "ament_cmake"

inherit ros_${ROS_BUILD_TYPE}
inherit ros_distro_jazzy

ROS_BUILD_DEPENDS = " \
rclcpp \
std-msgs \
"

ROS_BUILDTOOL_DEPENDS = " \
ament-cmake-native \
ament-package-native \
ament-cmake-core-native \
cmake-native \
python3-catkin-pkg-native \
"

ROS_EXPORT_DEPENDS = " \
rclcpp \
std-msgs \
"

ROS_BUILDTOOL_EXPORT_DEPENDS = " \
ament-cmake-native \
ament-package-native \
ament-cmake-core-native \
cmake-native \
python3-catkin-pkg-native \
"

ROS_EXEC_DEPENDS = ""

SRC_URI = "file://CMakeLists.txt \
file://package.xml \
file://src/ \
file://include/ \
"

DEPENDS = "${ROS_BUILD_DEPENDS} ${ROS_BUILDTOOL_DEPENDS}"
# Bitbake doesn't support the "export" concept, so build them as if we needed them to build this package (even though we actually
# don't) so that they're guaranteed to have been staged should this package appear in another's DEPENDS.
DEPENDS += "${ROS_EXPORT_DEPENDS} ${ROS_BUILDTOOL_EXPORT_DEPENDS}"

RDEPENDS:${PN} += "${ROS_EXEC_DEPENDS}"

S = "${WORKDIR}"
UNPACKDIR = "${S}"

e. 将meta-ros-publisher添加到build/conf/bblayers.conf

1
$ bitbake-layers add-layer ../../meta-ros-publisher

f. 将ros-publisher添加到本地配置文件

g. 编译ros-publisher

1
$ bitbake ros-publisher

h. 编译yocto镜像

1
$ bitbake core-image-base

i. 问题

在编译时遇到了两个问题,一个是报错找不到ament_cmake,另一个是编译的python环境No module name ‘ament_package’.
我们在编译时使用的是yocto的环境,而不是宿主机的环境编译,说明yocto的编译环境没有配置好,后面我修改了.bb文件,形成了如今上面的.bb文件后,再次编译yocto镜像,编译通过,没有再报错。