ROS 2 Humble is the latest LTS of the Robot Operating System (ROS), the de facto framework for robot application development. Yocto and ROS 2 allow you to build custom Linux-based production-grade operating systems for robots that obtain best performance for your use case. This article provides a walkthrough on how to build a Linux operating system with ROS 2 Humble for the Microchip PolarFire Icicle Kit
board and showcase our contribution to the ROS 2 community bringing ROS 2 Humble support for Yocto Honister
release. Lastly, we show how to get better performance with ROS 2 Humble using ROBOTCORE hardware acceleration framework for ROS.
- Why Yocto/PetaLinux instead of Ubuntu? production-grade robotic systems
- ROS 2 Humble in Microchip PolarFire Icicle Kit with Yocto
- Step 0. Fetch meta-tegra BSP and checkout Honister's branch
- Step 1. Build basic example BSP for Microchip PolarFire Icicle Kit
- Step 2. Add ROS 2 Humble meta layer
- Step 3. Add meta-layers for ROS 2 Humble and configure them in Yocto/PetaLinux
- Step 4. Create a Yocto recipe image including ROS 2 Humble
- Step 5. Build the image
- ROBOTCORE™ to accelerate your robots
- ROBOTCORE™ improves robotics development productivity
Why Yocto/PetaLinux instead of Ubuntu? production-grade robotic systems
Most people these days develop robots in Ubuntu
, so it's only normal that many engineers demand Ubuntu (a developer-known rootfs) for their robotic creations. This however comes with a technical debt that often new roboticists don't consider. There're two aspects of special relevance that are often misunderstood in robotics:
- security: cybersecurity is a process that requires a periodic effort including monitoring, research and updates of your robot's root file system (rootfs). Keeping it (your rootfs) minimal and monitored is key for a security-driven service. Regardless of whether you're cooking your own Linux rootfs or you're paying for it (someone else building it, and you pay either via telemetry data or via direct payment), a first-class security response requires you to take ownership of cybersecurity. You cannot fully externalize cybersecurity to a third party if you want your users to have a first-class security response. Also, cybersecurity needs to be observed from an attacker's perspective. While doing so, one would understand that attackers are mostly driven by financial opportunities. A common rootfs for robots is certainly a very interesting target. Besides the economics behind an attacker's mindset, from a technical perspective, compromising an operating system that's shared and common across multiple robots with common defaults (e.g. Ubuntu) is indeed a much easier target than "your own Linux distro" cooked for your specific use case and with a minimalistic attack surface (that you or someone else should study by threat modeling it). In a nutshell, you might be exposing yourself by picking a "popular" development-oriented rootfs for your robot.
- real-time: robots are inherently deterministic machines. Information is shared across robot networks between sensors and actuators in real-time. Skipping deadlines can lead to catastrophic missbehaviors. Ensuring an OS is real-time requires all its components to execute in a time-bounded manner. General purpose development-oriented OSs like Ubuntu are generally really bad at meeting real-time deadlines for 3 main reasons:
a)
their Linux kernel isn't engineered enough (even when applyingPREEMPT_RT
patches to their kernel forks, they need lots of engineering hours from knowledgeable embedded folks to assess their real-time performance issues),b)
Linux kernels need to also be real-time capable andc)
there're lots of daemons and processes thought for monitoring and sending telemetry back to the OS vendor that simply break completely the real-time assumptions.
Opposed to this, production-grade embedded systems often rely on strong multidisciplinary engineering teams that build custom and minimalistic Linux distributions for a particular use-case by leveraging Yocto
, a project to build embedded Linux. Rationale is that instead of relying on common development-oriented Linux distros (such as Ubuntu
), Yocto allows you to build a customized Linux system for your use case. This allows you an unmatched granularity wherein you can customize from the bootloader, going through the Linux kernel and all the way into userspace libraries, such as those required to enable ROS 2 support.
ROS 2 Humble in Microchip PolarFire Icicle Kit with Yocto
Acceleration Robotics is a firm focused on designing customized brains for robots to hasten their response time. The company creates custom compute architectures for high performance robots through hardware acceleration solutions. In a nutshell, we deliver semiconductor building blocks for robots while remaining accelerator-agnostic (FPGAs or GPUs) and as such, building custom high-performing Linux distributions becomes second nature. Adding ROS to such distributions while using Yocto
or derivatives (such as PetaLinux
) can be done with the meta-ros
layers.
As an active member of the ROS and ROS 2 communities, we're among the early contributors of meta-ros
(back in the old ROS 1 days) and first ported meta-ros to ROS 2 a few years back. To get ROS 2 Humble into custom embedded Linux OSs, our team at Acceleration Robotics contributed a series of Yocto recipes by updating the meta-ros project (see Pull Request). In total our contributions modified 60K LOC across more than 1000 files.
To get ROS 2 Humble into custom embedded Linux OSs, our team at Acceleration Robotics contributed a series of Yocto recipes by updating the meta-ros project (see Pull Request). In total our contributions modified 60K LOC across more than 1000 files.
Here is how to build a custom ROS 2 Humble embedded Linux for Microchip PolarFire Icicle Kit board:
Step 0. Fetch meta-tegra BSP and checkout Honister's branch
mkdir polarfire-yocto-bsp && cd polarfire-yocto-bsp
sudo apt-get install -y repo
repo init -u https://github.com/polarfire-soc/meta-polarfire-soc-yocto-bsp.git -b master -m tools/manifests/riscv-yocto.xml
repo sync
repo rebase
Step 1. Build basic example BSP for Microchip PolarFire Icicle Kit:
. ./meta-polarfire-soc-yocto-bsp/polarfire-soc_yocto_setup.sh
MACHINE=icicle-kit-es bitbake mpfs-dev-cli
Step 2. Add ROS 2 Humble meta layer
git clone https://github.com/vmayoral/meta-ros -b honister-humble
Step 3. Add meta-layers for ROS 2 Humble and configure them in Yocto/PetaLinux:
The meta-ros layer should be configured to be built by editing build/conf/bblayers.conf
and adding the following at the end:
<your-project-path>/meta-ros/meta-ros2 \
<your-project-path>/meta-ros/meta-ros2-humble \
<your-project-path>/meta-ros/meta-ros-common \
In addition, add the following (e.g. at the beginning of the file) as well, which defines some variables to be used by the meta-ros
recipes:
# define the ROS 2 Yocto target release
ROS_OE_RELEASE_SERIES = "honister"
# define ROS 2 distro
ROS_DISTRO = "humble"
Step 4. Create a Yocto recipe image including ROS 2 Humble:
There're various ways to build the meta-ros
recipes. The following creates a new Yocto image recipe with bare minimum packages required to execute pub/sub examples while including ROS 2 Humble with two open source DDS implementations:
demo-image-ros2.bb
cat << 'EOF' > ./meta-polarfire-soc-yocto-bsp/recipes-core/images/demo-image-ros2.bb
require mpfs-dev-cli.bb
SUMMARY = "An image including a bare-minimum installation of ROS 2 and including some basic pub/sub examples. It includes two DDS middleware implementations, FastDDS and Cyclone DDS"
DESCRIPTION = "${SUMMARY}"
inherit ros_distro_${ROS_DISTRO}
inherit ${ROS_DISTRO_TYPE}_image
ROS_SYSROOT_BUILD_DEPENDENCIES = " \
ament-lint-auto \
ament-cmake-auto \
ament-cmake-core \
ament-cmake-cppcheck \
ament-cmake-cpplint \
ament-cmake-export-definitions \
ament-cmake-export-dependencies \
ament-cmake-export-include-directories \
ament-cmake-export-interfaces \
ament-cmake-export-libraries \
ament-cmake-export-link-flags \
ament-cmake-export-targets \
ament-cmake-gmock \
ament-cmake-gtest \
ament-cmake-include-directories \
ament-cmake-libraries \
ament-cmake \
ament-cmake-pytest \
ament-cmake-python \
ament-cmake-ros \
ament-cmake-target-dependencies \
ament-cmake-test \
ament-cmake-version \
ament-cmake-uncrustify \
ament-cmake-flake8 \
ament-cmake-pep257 \
ament-copyright \
ament-cpplint \
ament-flake8 \
ament-index-python \
ament-lint-cmake \
ament-mypy \
ament-package \
ament-pclint \
ament-pep257 \
ament-pycodestyle \
ament-pyflakes \
ament-uncrustify \
ament-xmllint \
cmake \
eigen3-cmake-module \
fastcdr \
fastrtps-cmake-module \
fastrtps \
git \
gmock-vendor \
gtest-vendor \
pkgconfig \
python-cmake-module \
python3-catkin-pkg \
python3-empy \
python3 \
python3-nose \
python3-pytest \
rcutils \
rmw-implementation-cmake \
rosidl-cmake \
rosidl-default-generators \
rosidl-generator-c \
rosidl-generator-cpp \
rosidl-generator-dds-idl \
rosidl-generator-py \
rosidl-parser \
rosidl-runtime-c \
rosidl-runtime-cpp \
rosidl-typesupport-c \
rosidl-typesupport-cpp \
rosidl-typesupport-fastrtps-cpp \
rosidl-typesupport-interface \
rosidl-typesupport-introspection-c \
rosidl-typesupport-introspection-cpp \
foonathan-memory-vendor \
libyaml-vendor \
"
IMAGE_INSTALL:append = " \
ros-base \
examples-rclcpp-minimal-action-client \
examples-rclcpp-minimal-action-server \
examples-rclcpp-minimal-client \
examples-rclcpp-minimal-composition \
examples-rclcpp-minimal-publisher \
examples-rclcpp-minimal-service \
examples-rclcpp-minimal-subscriber \
examples-rclcpp-minimal-timer \
examples-rclcpp-multithreaded-executor \
examples-rclpy-executors \
examples-rclpy-minimal-action-client \
examples-rclpy-minimal-action-server \
examples-rclpy-minimal-client \
examples-rclpy-minimal-publisher \
examples-rclpy-minimal-service \
examples-rclpy-minimal-subscriber \
demo-nodes-cpp \
demo-nodes-cpp-rosnative \
demo-nodes-py \
cyclonedds \
rmw-cyclonedds-cpp \
tmux \
python3-argcomplete \
glibc-utils \
localedef \
rt-tests \
stress \
${ROS_SYSROOT_BUILD_DEPENDENCIES} \
opencv-staticdev \
libstdc++ \
libstdc++-dev \
"
IMAGE_LINGUAS = "en-us"
GLIBC_GENERATE_LOCALES = "en_US.UTF-8"
EOF
Step 5. Build the image
What's left is to build the project and generate the embedded artifacts desired (kernel, bootloader firmware, rootfs, sysroot, etc.):
MACHINE=icicle-kit-es bitbake demo-image-ros2
This will take a while and in time. Once it finalizes, you'll have your rootfs with ROS 2 Humble 🙂.
ROBOTCORE™ to accelerate your robots
So, now that you have a custom ROS 2 Humble embedded Linux, how do you improve ROS 2 Humble beyond its CPU-centric execution? By using hardware acceleration in the PolarFire Icicle Kit FPGA. To improve your robot's performance and speed it up you should rely on hardware acceleration. The Microchip PolarFire Icicle Kit can speed up ROS computations with its FPGA and our work at Acceleration Robotics focuses on getting you everything you need to create robot cores to boost your ROS 2 Humble architectures with Microchip PolarFire Icicle Kit.
ROBOTCORE™ improves robotics development productivity
ROBOTCORE™ implements the ROS 2 Hardware Acceleration Architecture and Conventions REP and supports the most popular hardware acceleration solutions and development kits to build robots with hardware acceleration and ROS. While doing so, ROBOTCORE™ simplifies the ROS 2 development flow for accelerators providing pre-packaged firmware artifacts that allow you to improve your robotics development productivity. With ROBOTCORE™ building accelerators takes just the following:
# 1. Create ROS 2 workspace
mkdir -p ~/ros2_ws/src; cd ~/ros2_ws
wget https://<your-customer-id-url>/humble_repos.ros
vcs import src --recursive < humble_repos.ros
# 2. build your workspace for dev. machine arch
colcon build --merge-install
# 3. source the overlay to enable ROBOTCORE™
source install/setup.bash
# 4. build your workspace for embedded arch
# and build acceleration kernels altogether
colcon build --merge-install --mixin polarfireiciclekit
Get in touch to acquire a ROBOTCORE™ license including documentation, examples and reference designs.