小米杯 Docker 容器内 LCM 环境搭建教程

本教程将引导您在基于 Ubuntu 的 Docker 容器中搭建 LCM(Lightweight Communications and Marshalling)环境,解决在配置过程中可能遇到的常见网络和依赖问题。

前置条件:

  • 已安装 Docker 的 Linux 宿主机(本例为 Ubuntu 虚拟机)。
  • 可访问互联网的宿主机网络连接。
  • 已构建名为 cyberdog_sim:v2 的 Docker 镜像。
  • 熟悉 Linux 命令行操作。

教程步骤:

第一部分:宿主机网络环境准备 (关键)

在启动 Docker 容器之前,必须确保宿主机(本例中的 Ubuntu 虚拟机)能够正常访问互联网。之前遇到的 Temporary failure resolving 错误通常是宿主机网络问题导致的。

  1. 检查宿主机网络连接:

    在宿主机终端 (c@c-virtual-machine:~ $ 或 root@c-virtual-machine:/#) 执行:

    Bash

    1
    2
    ping 8.8.8.8
    ping google.com

    • 如果两者都成功(无 100% packet loss网络不可达 ),则宿主机网络正常。
    • 如果失败,请检查虚拟机的网络设置(如 VMware/VirtualBox 的网络适配器模式,推荐 NAT 模式),并尝试重启虚拟机以重新获取 IP 地址。
    • 确保宿主机的网卡(例如 ens33 )已分配 IPv4 地址(如 192.168.130.132 ),可以通过 ip a 命令查看。
  2. (可选但推荐)宿主机 auto_lcm_init.sh 脚本的适应性修改:

    尽管此脚本主要用于容器内部,但如果将来你需要在宿主机直接运行与 LCM 相关的工具,提前修改会避免同样的问题。

    • 打开宿主机上的脚本文件: nano /home/xiangao/motion/scripts/auto_lcm_init.sh

    • 找到获取接口名称的行:

      enxname=$(ifconfig | grep -B 1 -E '192.168.55.100|192.168.44.100' | grep 'flags' | cut -d ':' -f1)

    • 将其中的 IP 地址替换为你的宿主机实际获取到的 IP 地址(例如 192.168.130.132):

      enxname=$(ifconfig | grep -B 1 -E '192.168.130.132' | grep 'flags' | cut -d ':' -f1)

    • 保存并退出。

第二部分:启动 Docker 容器 (必须使用 --network host )

正确启动容器是让容器访问宿主机网络的关键。

  1. 停止并删除所有旧的 Docker 容器实例:

    在宿主机终端执行:

    Bash

    1
    2
    3
    sudo docker ps -a # 找到 cyberdog_sim:v2 容器的 CONTAINER ID 或 NAMES
    sudo docker stop <CONTAINER_ID_或_NAME> # 如果容器正在运行
    sudo docker rm <CONTAINER_ID_或_NAME> # 删除容器

  2. 以宿主机网络模式启动 Docker 容器:

    在宿主机终端执行,确保包含 --network host 标志:

    Bash

    1
    sudo docker run -it --network host --shm-size="1g" --privileged=true -e DISPLAY=$DISPLAY -v /tmp/.X11-unix:/tmp/.X11-unix cyberdog_sim:v2

    这会让你进入容器的 shell 环境 ( root@c-virtual-machine:/# 或类似)。

  3. 在容器内部验证网络接口:

    进入容器后,立即执行 ip a。

    Bash

    1
    ip a

    验证: 你应该能看到宿主机的网络接口,特别是 ens33 ,并且它的 IP 地址与宿主机上的 ens33 IP(如 192.168.130.132 )一致。如果看到 eth0172.17.0.x ,说明 --network host 未生效,需要重新检查启动命令。

第三部分:容器内 LCM 相关依赖和脚本执行

容器成功启动并连接到宿主机网络后,可以在容器内部安装缺失的软件包并执行 LCM 初始化脚本。

  1. 在容器内部更新软件包列表并安装必要的网络工具:

    虽然 net-tools 可能已存在,但 iproute2 是现代 Linux 系统中 ip 命令的提供者,对网络操作至关重要。

    Bash

    1
    2
    apt-get update
    apt-get install -y iproute2 net-tools

    • 排查: 如果 apt-get update 仍出现 Temporary failure resolving ,请返回第一部分,宿主机网络未完全恢复。
  2. 在容器内部编辑 auto_lcm_init.sh 脚本:

    此脚本用于配置 LCM 所需的组播网络接口。它的 IP 匹配规则需要与容器当前识别的 ens33 接口的 IP 地址一致。

    • 进入脚本所在目录: cd /home/xiangao/motion/scripts

    • 打开脚本文件: nano auto_lcm_init.sh

    • 找到获取接口名称的行:

      enxname=$(ifconfig | grep -B 1 -E '192.168.55.100|192.168.44.100' | grep 'flags' | cut -d ':' -f1)

    • 将其中的 IP 地址替换为容器内部 ip a 显示的 ens33 的实际 IP 地址(例如 192.168.130.132):

      enxname=$(ifconfig | grep -B 1 -E '192.168.130.132' | grep 'flags' | cut -d ':' -f1)

    • 保存并退出 nano

  3. 在容器内部执行 auto_lcm_init.sh 脚本:

    Bash

    1
    2
    chmod +x auto_lcm_init.sh
    ./auto_lcm_init.sh

    • 验证: 脚本执行后不应有任何错误输出,或只有成功信息。如果报错 Device not foundSIOCADDRT: No such device ,请重新检查 enxname 变量是否正确获取到接口名称,以及 iproute2net-tools 是否完整安装。

第四部分:解决 Python 模块依赖问题

motion.py 脚本依赖多个 Python 模块(如 lcmrclpypyzbartoml )。它们需要单独安装。

  1. 安装 Python 的 pip 工具:

    Bash

    1
    2
    apt-get update # 再次更新以防万一
    apt-get install -y python3-pip

  2. 安装 lcm 的 Python 绑定:

    Bash

    1
    pip3 install lcm

    • 注意: 如果 pip3 无法找到 lcm ,可能需要尝试 apt-get install -y python3-lcm
  3. Source ROS 2 环境 (解决 ModuleNotFoundError: No module named 'rclpy'):

    rclpy 是 ROS 2 的核心 Python 库。为了让 Python 找到它,需要加载 ROS 2 的环境变量。

    Bash

    1
    source /opt/ros/galactic/setup.bash # 根据你的ROS 2版本调整,如foxy, humble等

    • 验证: python3 -c "import rclpy; print('rclpy imported successfully')"
  4. 安装 pyzbar 库及其依赖 (解决 ModuleNotFoundError: No module named 'pyzbar' 和 Unable to find zbar shared library):

    pyzbar 需要底层的 zbar 共享库。

    Bash

    1
    2
    3
    4
    apt-get update
    apt-get install -y --reinstall libzbar0 zbar-tools # 强制重新安装 zbar 库
    ldconfig # 更新动态链接库缓存
    pip3 install --upgrade --force-reinstall pyzbar # 重新安装 pyzbar Python 绑定

  5. 安装 toml 模块 (解决 ModuleNotFoundError: No module named 'toml' ):

    Bash

    1
    pip3 install toml

第五部分:运行您的应用程序

所有依赖都安装并配置好后,现在可以尝试运行您的主程序了。

  1. 在容器内,回到 motion.py 脚本所在的目录:

    Bash

    1
    cd /home/xiangao/motion

  2. 运行 motion.py

    Bash

    1
    python3 motion.py

    • 预期: 程序应该能成功导入所有模块并开始执行。如果遇到新的 ModuleNotFoundError ,请重复安装对应模块的步骤。如果遇到运行时错误,则需要根据错误信息进行程序逻辑或环境的其他调试。

通过遵循这些步骤,您应该能够成功地在 Docker 容器内的虚拟环境中搭建 LCM 并运行依赖它的 Python 应用程序。整个过程的核心在于理解 Docker 容器的网络模式,以及如何识别并安装所有必要的系统和 Python 依赖。