PX4 Docker容器
提供了适用于完整的PX4开发工具链的Docker容器,其中包括基于NuttX和Linux的硬件、Gazebo Classic仿真环境以及ROS。
本主题将展示如何使用可用的Docker容器,在本地Linux计算机上访问构建环境。
INFO
Dockerfile文件和README文件可在Github上的此处找到。 它们会在Docker Hub上自动构建。
系统必备组件
INFO
目前,PX4容器仅在Linux系统上受支持(如果您没有Linux系统,可以在虚拟机中运行容器)。 请勿将boot2docker
与默认的Linux镜像一起使用,因为它不包含X服务器。
为您的Linux计算机安装Docker,最好使用Docker维护的软件包存储库之一,以获取最新的稳定版本。您可以使用_企业版_或(免费的)社区版。
对于在_Ubuntu_上本地安装非生产环境的设置,安装Docker最快且最简单的方法是使用便捷脚本,如下所示(在同一页面上可以找到其他安装方法):
curl -fsSL get.docker.com -o get-docker.sh
sudo sh get-docker.sh
默认安装要求您以root用户身份调用_Docker_(即使用sudo
)。但是,为了构建PX4固件,我们建议以非root用户身份使用docker。这样,在使用docker之后,您的构建文件夹不会归root所有。
# 创建docker用户组(可能不需要)
sudo groupadd docker
# 将您的用户添加到docker用户组中。
sudo usermod -aG docker $USER
# 在使用docker之前,请重新登录/注销!
本地编辑层次结构
可用的容器可在Github上的此处找到。
使用容器的最简单方法是通过 docker_run.sh 帮助程序脚本。 容器是分层的,因此容器具有其父容器的功能。 例如,下面的部分层次结构显示,带有NuttX构建工具的docker容器(px4-dev-nuttx-focal
)不包含ROS 2,而仿真容器则包含:
- px4io/px4-dev-base-focal
- px4io/px4-dev-nuttx-focal
- px4io/px4-dev-simulation-focal
- px4io/px4-dev-ros-noetic
- px4io/px4-dev-ros2-foxy
- px4io/px4-dev-ros2-rolling
- px4io/px4-dev-base-jammy
- px4io/px4-dev-nuttx-jammy
可以使用latest
标签访问最新版本:px4io/px4-dev-nuttx-focal:latest
(在_hub.docker.com_上为每个容器列出了可用的标签。 例如,px4io/px4-dev-nuttx-focal
的标签可以在此处找到)。
TIP
通常,您应该使用较新的容器,但不一定非要使用latest
(因为它更新过于频繁)。
使用Docker容器
典型命令的语法如下所示。 假设您已将PX4源代码下载到 src/PX4-Autopilot 目录,如下所示:
mkdir src
cd src
git clone https://github.com/PX4/Firmware.git
cd Firmware
助手脚本(docker_run.sh)
使用容器的最简单方法是通过 docker_run.sh 帮助程序脚本。 该脚本将PX4构建命令作为参数(例如make tests
)。它会使用适当容器的最新版本(硬编码)和合理的环境设置来启动docker。
例如,要构建软件在环仿真(SITL),您可以调用(在 /PX4-Autopilot 目录内):
sudo ./Tools/docker_run.sh 'make px4_sitl_default'
或者,要使用NuttX工具链启动一个bash会话:
sudo ./Tools/docker_run.sh 'bash'
TIP
这个脚本很方便,因为您无需过多了解_Docker_,也无需考虑使用哪个容器。 要重新进入此容器(将保留您的更改),只需执行以下操作: 如果脚本存在任何问题,下面部分中讨论的手动方法更加灵活,应在这种情况下使用。
手动调用Docker
典型命令的语法如下所示。 这将运行一个支持X转发的Docker容器(使容器内部的仿真图形用户界面可用)。 它将您计算机上的目录<host_src>
映射到容器内部的<container_src>
,并转发连接 QGroundControl 所需的UDP端口。 使用–privileged
选项,它将自动获得对主机上设备(例如操纵杆和GPU)的访问权限。如果您连接/断开设备,则必须重新启动容器。
# 启用从容器访问xhost
xhost +
# 运行docker
docker run -it --privileged \
--env=LOCAL_USER_ID="$(id -u)" \
-v <host_src>:<container_src>:rw \
-v /tmp/.X11-unix:/tmp/.X11-unix:ro \
-e DISPLAY=:0 \
-p 14570:14570/udp \
--name=<local_container_name> <container>:<tag> <build_command>
其中:
<host_src>
:要映射到容器中<container_src>
的主机计算机目录。通常,这应该是 PX4-Autopilot 目录。<container_src>
:在容器内部时共享(源)目录的位置。<local_container_name>
:正在创建的Docker容器的名称。如果以后我们需要再次引用该容器,可以使用此名称。<container>:<tag>
:要启动的带版本标签的容器,例如:px4io/px4-dev-ros:2017-10-23
。<build_command>
:要在新容器上调用的命令。例如,bash
用于在容器中打开一个bash shell。
下面的具体示例展示了如何打开一个bash shell,并共享主机计算机上的目录 ~/src/PX4-Autopilot。
# 启用从容器访问xhost
xhost +
# 运行docker并打开bash shell
docker run -it --privileged \
--env=LOCAL_USER_ID="$(id -u)" \
-v ~/src/PX4-Autopilot:/src/PX4-Autopilot/:rw \
-v /tmp/.X11-unix:/tmp/.X11-unix:ro \
-e DISPLAY=:0 \
--network host \
--name=px4-ros px4io/px4-dev-ros2-foxy:2022-07-31 bash
INFO
我们使用主机网络模式,以避免在与docker容器相同的系统上使用QGroundControl时,UDP端口访问控制之间发生冲突。
INFO
如果您遇到错误“无法打开显示::0”,可能需要将DISPLAY
设置为不同的值。 在Linux(XWindow)主机上,您可以将-e DISPLAY=:0
更改为-e DISPLAY=$DISPLAY
。 在其他主机上,您可能需要迭代-e DISPLAY=:0
中的0
值,直到“无法打开显示::0”错误消失。
运行模拟实例时,例如在docker容器内的SITL并通过 QGroundControl 从主机控制它,必须手动设置通信链接。 QGroundControl 的自动连接功能在此处不起作用。
cd src/PX4-Autopilot #这是<container_src>
make px4_sitl_default gazebo-classic
重新进入容器
docker run
命令只能用于创建新容器。要重新进入此容器(该容器将保留您的更改),只需执行以下操作:
# 启动容器
sudo docker start container_name
# 在这个容器中打开一个新的bash shell
sudo docker exec -it container_name bash
如果您需要多个连接到该容器的shell,只需打开一个新的shell并再次执行最后一条命令即可。
清理容器
有时您可能需要完全清除一个容器。您可以使用其名称来执行此操作:
docker rm mycontainer
如果您不记得名称,那么可以列出非活动容器的ID,然后删除它们,如下所示:
docker ps -a -q
45eeb98f1dd9
docker rm 45eeb98f1dd9
QGroundControl
当在docker容器内运行模拟实例(例如SITL)并通过主机上的_QGroundControl_对其进行控制时,必须手动设置通信链接。_QGroundControl_的自动连接功能在此处不起作用。
在_QGroundControl_中,导航至设置并选择“通信链接”。创建一个使用UDP协议的新链接。端口取决于所使用的配置,例如,对于SITL配置,端口为14570。IP地址是您的docker容器的IP地址,使用默认网络时通常是172.17.0.1/16。可以使用以下命令找到docker容器的IP地址(假设容器名称为mycontainer
):
$ docker inspect -f '{ {range .NetworkSettings.Networks}}{ {.IPAddress}}{ {end}}' mycontainer
INFO
上面双大括号之间的空格不应存在(它们是为了避免gitbook中出现用户界面渲染问题而需要的)。
故障处理
权限错误
容器会根据需要使用默认用户(通常是“root”)创建文件。这可能会导致权限错误,即主机计算机上的用户无法访问容器创建的文件。
上面的示例使用--env=LOCAL_USER_ID="$(id -u)"
这一行,在容器中创建一个与主机上用户具有相同用户ID(UID)的用户。这可确保容器内创建的所有文件在主机上都可访问。
图形驱动问题
运行Gazebo Classic时,可能会出现类似以下的错误消息:
libGL error: failed to load driver: swrast
在这种情况下,必须安装主机系统的本地图形驱动程序。下载合适的驱动程序,并在容器内部安装它。对于Nvidia驱动程序,应使用以下命令(否则安装程序会检测到主机上已加载的模块并拒绝继续):
./NVIDIA-DRIVER.run -a -N --ui=none --no-kernel-module
有关此内容的更多信息,可以在此处找到。
虚拟机支持
尝试禁用并行构建。
以下配置已通过测试:
- 运行OS X系统,搭配VMWare Fusion和Ubuntu 14.04(在Parallels上具有图形用户界面支持的Docker容器会导致X服务器崩溃)。
内存
为虚拟机至少使用4GB内存。
编译问题
如果编译失败并出现类似以下的错误:
The bug is not reproducible, so it is likely a hardware or OS problem.
c++: internal compiler error: Killed (program cc1plus)
尝试禁用并行构建。
允许从虚拟机主机控制Docker
编辑/etc/defaults/docker
并添加以下行:
DOCKER_OPTS="${DOCKER_OPTS} -H unix:///var/run/docker.sock -H 0.0.0.0:2375"
然后,您可以从主机操作系统控制docker:
export DOCKER_HOST=tcp://<ip of your VM>:2375
# 运行一些docker命令,查看是否有效,例如ps
docker ps