使用 systemd-nspawn 搭建轻量级的 ROS 开发环境
March 23, 2023 · 7 min read
建议 Tips
您正在查看印刷版本的博客, 印刷版本的博客可能会缺少部分交互功能, 部分内容显示不全或过时. 如果您在查看该印刷版博客时遇到了任何问题, 欢迎来此链接查看在线版: https://www.kxxt.dev/blog/systemd-nspawn-container-for-ros/
You are viewing a printed version of this blog. It may lack some interactive features and some content might now be fully displayed or outdated. If you encounter any problems while viewing this printed version of the blog, feel free to view the online version here: https://www.kxxt.dev/blog/systemd-nspawn-container-for-ros/
背景
本学期的嵌入式机器人课的主要内容是 ROS(Robot Operating System). 上课教的是第一代 ROS Melodic (马上在 2023 年 5 月就停止支持了). ROS 官方主要支持 Ubuntu 操作系统, 对我正在使用的 Archlinux 只有实验性的支持.
AUR 上的 ROS Melodic 已经被标记为 orphan 了, 于是我就装了 ROS Noetic, 比 Melodic 高一代.
然后我就开始各种踩坑了, 首先从 AUR 上装 ROS Noetic 的时候就遇到了
ignition-cmake
的 CMake 文件找不到的问题 .
AUR 里的 ignition-cmake
已经是 v3 了, 简单的看了一下, 缺的文件是 v2 提供的,
而且 v2 和 v3 不冲突. 在安装了 v2 之后, AUR 里的 ROS Noetic 就能顺利的构建安装了.
这时, 我以为坑已经踩完了, 结果上课时遇到了一堆 Python2 相关的问题. ROS Noetic 带的一些 Python 脚本是 Python2 的, 遇上系统的 python3 就挂了, 另外实验提供的代码也全是 Python2 的, 我都要手动翻译成 Python3 (不是什么大问题, 就是有点烦).
昨天踩了个大坑, catkin_make
的时候报找不到 vtk
9.1.0 的一些共享库. 很自然的,
看起来是因为滚动升级把 vtk
给升级了, 系统里的 vtk
共享库都是 9.2.6 的.
先用 ripgrep
搜 9\.1\.0
找出需要 rebuild 的包. 然后清掉缓存再 rebuild.
rebuild 的时候踩到坑了, 撞上了一样的问题. 我必须先把系统里的那些要 rebuild 的 ROS 包给强制卸载掉 (pacman -Rdd
)
才能成功构建它们.
另外, 实验里的 OpenCV 人脸检测程序一跑就 hang. 我检查了一下, hang 在 detectMultiScale
里面了. 如果开个
mamba 环境跑的话就不会 hang, 目测是 Archlinux 带的 (python-)opencv
炸了.
于是, 为了减少踩坑, 我决定还是用 ROS Melodic 官方支持的 Ubuntu 18.04 作为开发环境吧. 之前实验课配置过虚拟机, 不过体验很差. 我想过用 docker 架个开发环境, 但是由于时不时需要往里面装新的软件包, 这就需要经常改 Dockerfile, 使用场景不是很 immutable. 最后我就决定试试 systemd-nspawn.
下面是我在配置完成后写的总结过程, 因此可能会漏掉一些东西.
Bootstrap
先安装 debootstrap
, 然后在 /var/lib/machines/bionic
下 bootstrap 一个 Ubuntu.
# 以 Root 身份运行cd /var/lib/machinesdebootstrap --include=dbus,systemd-container --components=main,universe,multiverse bionic bionic https://mirrors.tuna.tsinghua.edu.cn/ubuntu/
等 bootstrap 完了之后进去设个密码, 删掉 /etc/securetty
来避免等会登陆不了.
systemd-nspawn -D bionicpasswdrm /etc/securettylogout
systemd-nspawn 配置
给我们的 bionic 容器写个配置文件: /etc/systemd/nspawn/bionic.nspawn
:
- 直接使用系统的现有 UID. 因为 Ubuntu 18.04 的 systemd 的版本太低, 不支持 systemd-nspawn 的一些高级功能
- 为了简单起见, 把
VirtualEthernet
设置成no
, 让容器直接使用宿主机网络. - 不使用宿主机的
resolv.conf
- 另外, 为了能在容器里访问摄像头, 把
/dev/video*
Bind 进去 - 为了启用硬件加速1, 把
/dev/dri
Bind 进去.- 我没有验证这个配置有没有生效, 反正最后跑
glxinfo
的结果是硬件加速启用了.
- 我没有验证这个配置有没有生效, 反正最后跑
- 跟宿主机共享 X11 和 dbus
- 把需要共享的目录 Bind 进去
然后, 我们还需要编辑一下 systemd-nspawn@bionic.service
:
sudo systemctl edit systemd-nspawn@bionic.service
添加下面的配置允许容器操作位于 /dev/video1
的摄像头设备.
容器系统配置
然后, 利用 machinectl
启动并登陆进容器:
sudo machinectl start bionicsudo machinectl login bionic
不知道出了什么问题, 我在容器内遇到了 DNS 解析问题, 我的处理方法就是上文中提到的在 nspawn
配置文件里把 ResolveConf
的模式从 auto
改成 off
. 另外, 在容器内禁用 systemd-resolved
服务,
sudo systemctl disable --now systemd-resolvedecho 'nameserver 8.8.8.8' > /etc/resolv.conf
容器内的主机名可能也需要配置一下. 我把它配置成了和宿主机一样.
echo 主机名 > /etc/hostname
并在 /etc/hosts
中添加
127.0.0.1 主机名
然后重启容器, 再重新登陆进去
sudo machinectl stop bionicsudo machinectl start bionicsudo machinectl login bionic
创建一个 uid 和宿主机上的用户相同的用户, 授予 sudo 权限.
然后安装 git, tmux, alacritty 等基本软件, 正常安装 ROS.
使用 ROS
在宿主机上允许容器连接 X server, 并查看 DISPLAY
环境变量的值:
$ xhost +local:$ echo $DISPLAY:0
以普通用户的身份登陆 容器, 然后设置好 DISPLAY
环境变量. 建议放 .bashrc
里, 避免每次使用都要设置.
然后就可以使用 ROS 了.
export DISPLAY=:0alacritty
一个 Bug
在使用时, 我遇到了 rosout 吃满内存的 Bug2, 可以通过创建以下文件来解决
References
- https://wiki.archlinux.org/title/systemd-nspawn
- https://clinta.github.io/getting-started-with-systemd-nspawnd/