環(huán)境完整指南)
先說(shuō)個(gè)背景。我這臺(tái)deepin本來(lái)是用來(lái)日常辦公的后來(lái)想折騰機(jī)器人開發(fā)就動(dòng)了裝ROS2的心思。一開始我很天真直接在系統(tǒng)里照著Ubuntu的教程用apt裝ros-humble-desktop結(jié)果裝到一半提示要升級(jí)一堆系統(tǒng)基礎(chǔ)庫(kù)我沒(méi)多想就回車然后重啟之后桌面直接進(jìn)不去了。那次之后我徹底明白了一個(gè)道理在deepin上折騰ROS2最好別碰系統(tǒng)原生的依賴樹老老實(shí)實(shí)走docker才是正路。現(xiàn)在這套方案我已經(jīng)用了挺長(zhǎng)時(shí)間了deepin系統(tǒng)本身干干凈凈ROS2環(huán)境全在容器里搞壞了就重來(lái)再也不怕把系統(tǒng)搞崩。這篇文章就把完整的流程記錄下來(lái)deepin上怎么裝docker、怎么選ROS2鏡像、容器里怎么把rviz2和gazebo的畫面調(diào)出來(lái)以及我踩過(guò)的那些坑。如果你也是deepin用戶又想玩ROS2這篇文章可以直接照著抄。1. 為什么非得繞Docker這一圈ROS2版本與系統(tǒng)版的硬綁關(guān)系1.1 ROS2不是裝個(gè)包就行版本和Ubuntu是一一綁定的先看一組ROS2官方版本支持表。ROS2每個(gè)發(fā)行版都綁定一個(gè)Ubuntu LTS版本這個(gè)綁定關(guān)系是寫死在構(gòu)建腳本里的ROS2版本對(duì)應(yīng)Ubuntu版本發(fā)布時(shí)間維護(hù)狀態(tài)Foxy FitzroyUbuntu 20.04 (Focal)2020年6月已EOLHumble HawksbillUbuntu 22.04 (Jammy)2022年5月當(dāng)前LTSIron IrwiniUbuntu 22.04 (Jammy)2023年5月已EOLJazzy JaliscoUbuntu 24.04 (Noble)2024年5月當(dāng)前LTS為什么會(huì)有這種硬綁定因?yàn)镽OS2的二進(jìn)制包依賴某個(gè)特定版本的Boost、Python、OpenSSL、OpenCV等庫(kù)而這些庫(kù)在Ubuntu版本間差異很大。官方只對(duì)指定Ubuntu版本做完整測(cè)試所以預(yù)編譯包只發(fā)對(duì)應(yīng)版本。如果你用不匹配的系統(tǒng)版本強(qiáng)行裝apt會(huì)告訴你依賴沖突你只能看到一串又一串需要但無(wú)法安裝的報(bào)錯(cuò)。deepin本質(zhì)上基于Debian系和Ubuntu同源但庫(kù)版本又不一樣。ROS2官方并沒(méi)有發(fā)布deepin版本所以要裝只能引入U(xiǎn)buntu源而這一引入就把整個(gè)系統(tǒng)的APT依賴樹攪渾了。這就是我在開頭說(shuō)的桌面崩掉事故的根本原因。1.2 在deepin上硬裝的真實(shí)下場(chǎng)可能有人會(huì)說(shuō)我手動(dòng)從源碼編譯ROS2不行嗎 可以但代價(jià)非常大。源碼編譯一個(gè)humble-desktop全量版本光是依賴就能折騰一整天而且編譯過(guò)程中可能因?yàn)閐eepin的編譯器版本、CMake版本和Ubuntu鏡像不一致出現(xiàn)各種奇奇怪怪的編譯錯(cuò)誤。更別提編譯到一半發(fā)現(xiàn)某個(gè)ROS2包依賴的系統(tǒng)庫(kù)版本不對(duì)又得手動(dòng)去搞。網(wǎng)上還有那種一鍵安裝腳本在Ubuntu上確實(shí)方便但拿到deepin上跑腳本會(huì)識(shí)別系統(tǒng)信息發(fā)現(xiàn)不是Ubuntu就拒絕執(zhí)行或者干脆硬著頭皮去改系統(tǒng)的Python和pip版本最后把系統(tǒng)搞得更亂。我見過(guò)不止一次有人把系統(tǒng)Python換成3.10之后整個(gè)deepin的應(yīng)用商店和桌面組件全部罷工。所以我最終放棄直接在deepin上裝ROS2轉(zhuǎn)向docker。這是目前最穩(wěn)的路不碰宿主系統(tǒng)的依賴樹ROS2需要什么庫(kù)就裝在容器里容器用的鏡像基于Ubuntu 22.04和ROS2 humble的官方發(fā)布版本完全一致。1.3 Docker解決的不只是安裝還有可復(fù)現(xiàn)除了避免系統(tǒng)崩潰docker這套方案還有個(gè)很大的好處可復(fù)現(xiàn)。我可以把整個(gè)ROS2環(huán)境包括裝好的turtlesim、rviz2插件、自己編譯的功能包打包成一個(gè)鏡像拷到另一臺(tái)電腦上直接跑完全不需要重新配置。對(duì)于做機(jī)器人開發(fā)的人來(lái)說(shuō)這個(gè)特性太重要了——你換電腦、換系統(tǒng)、帶學(xué)生做實(shí)訓(xùn)一套鏡像全搞定。另外docker容器的隔離性也給了你隨便折騰的底氣。容器里裝壞了刪掉容器重新create一份幾十秒又是一條好漢。這種試錯(cuò)成本是直接在deepin系統(tǒng)上操作沒(méi)法比的。2. deepin上裝Docker Engine源、驅(qū)動(dòng)與用戶組三件套2.1 為什么不用Docker Desktop先解開那個(gè)virtualization報(bào)錯(cuò)很多從Windows轉(zhuǎn)過(guò)來(lái)的朋友第一反應(yīng)是裝Docker Desktop然后大概率會(huì)撞上這個(gè)報(bào)錯(cuò)virtualization support not detected。這個(gè)報(bào)錯(cuò)的意思是Docker Desktop需要在你的機(jī)器上啟用CPU虛擬化擴(kuò)展VT-x或AMD-V它本質(zhì)上是一個(gè)跑在輕量虛擬機(jī)里的方案對(duì)宿主要求高而且deepin對(duì)Docker Desktop的兼容性并不好。但做ROS2開發(fā)我們根本不需要Docker Desktop。我們用Docker Engine就夠了就是純命令行工具不依賴任何虛擬機(jī)技術(shù)在deepin上非常穩(wěn)。我自己一直用的是CLI方式日常開發(fā)完全夠用甚至比Desktop更清爽、更省資源。2.2 添加Docker源時(shí)最容易卡住的一步deepin上裝Docker Engine最麻煩的不是執(zhí)行apt install而是添加docker官方軟件源。docker官方源是按Debian版本提供apt倉(cāng)庫(kù)的它需要你明確告訴它我是Debian哪個(gè)版本。deepin的/etc/os-release里寫的版本代號(hào)是deepin自己的名字比如amber或beigedocker源不認(rèn)這個(gè)如果你直接照抄官方文檔的命令apt update會(huì)報(bào)錯(cuò)說(shuō)找不到Release文件。正確做法是去看/etc/debian_version這個(gè)文件里寫的是deepin底層對(duì)應(yīng)的Debian版本號(hào)。我的機(jī)器上對(duì)應(yīng)的是bullseye所以docker源要按Debian 11來(lái)配。如果你的deepin版本不同以你機(jī)器上/etc/debian_version的值為準(zhǔn)。操作步驟比較簡(jiǎn)單# 安裝依賴工具 sudo apt update sudo apt install -y apt-transport-https ca-certificates curl gnupg lsb-release # 添加docker官方GPG密鑰 curl -fsSL https://mirrors.aliyun.com/docker-ce/linux/debian/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg # 添加docker倉(cāng)庫(kù)注意bullseye換成你的debian版本代號(hào) echo deb [archamd64 signed-by/usr/share/keyrings/docker-archive-keyring.gpg] https://mirrors.aliyun.com/docker-ce/linux/debian bullseye stable | sudo tee /etc/apt/sources.list.d/docker.list # 刷新索引 sudo apt update這里我刻意用了阿里云的鏡像地址而不是docker官方地址因?yàn)樵趪?guó)內(nèi)直接訪問(wèn)docker官方倉(cāng)庫(kù)經(jīng)常超時(shí)換成鏡像源能省掉很多等待時(shí)間。2.3 安裝、啟動(dòng)、免sudo三步走源配好之后安裝就很直接了sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin sudo systemctl enable --now docker docker versiondocker version能看到客戶端和服務(wù)端版本號(hào)說(shuō)明服務(wù)已經(jīng)正常運(yùn)行。如果是第一次裝可以先跑一下sudo docker run hello-world驗(yàn)證整個(gè)鏈路能通。最后一步是免sudo。docker CLI默認(rèn)需要root權(quán)限每次敲sudo docker很煩而且后面掛載目錄、跑容器時(shí)權(quán)限問(wèn)題會(huì)很多。把當(dāng)前用戶加進(jìn)docker組就能解決sudo usermod -aG docker $USER newgrp docker docker run hello-worldnewgrp docker讓當(dāng)前終端立即生效不用重新登錄。如果重啟終端之后docker還是報(bào)權(quán)限拒絕那就是用戶組沒(méi)刷新成功重新登錄一次就好。2.4 配一個(gè)國(guó)內(nèi)鏡像加速器否則拉鏡像會(huì)懷疑人生docker裝好后第一件要做的事是配鏡像加速器。不配的話直接拉ros鏡像可能卡在下載層動(dòng)彈不得。在/etc/docker/daemon.json里配置鏡像源{ registry-mirrors: [ https://docker.m.daocloud.io, https://dockerproxy.com, https://docker.nju.edu.cn ] }配好之后重啟dockersudo systemctl restart docker加速器的作用相當(dāng)于給Docker Hub加了一層國(guó)內(nèi)緩存拉同名的鏡像時(shí)直接從鏡像站取速度快很多。注意鏡像站有時(shí)候會(huì)調(diào)整域名配多個(gè)備選可以減少拉取失敗的次數(shù)。3. 拿官方鏡像先跑一個(gè)最小ROS2環(huán)境3.1 鏡像版本怎么選從Humble到Jazzydocker官方倉(cāng)庫(kù)里有ROS2鏡像最常見的鏡像名是ros和osrf/ros。選鏡像版本的時(shí)候跟著你實(shí)際需要的ROS2版本走即可。做機(jī)器人開發(fā)目前我還是推薦Humble原因很簡(jiǎn)單生態(tài)最成熟資料最多絕大多數(shù)教學(xué)和開源項(xiàng)目都用humble。如果你的項(xiàng)目明確要求Jazzy或者更新的版本再根據(jù)下表選擇鏡像標(biāo)簽對(duì)應(yīng)ROS2版本對(duì)應(yīng)Ubuntu適用場(chǎng)景ros:humble-ros-core-jammyHumble22.04最小核心適合網(wǎng)關(guān)類設(shè)備ros:humble-ros-base-jammyHumble22.04基礎(chǔ)通信常用工具建議日常開發(fā)用這個(gè)ros:humble-desktopHumble22.04帶圖形工具rviz2等體積大ros:jazzy-ros-base-nobleJazzy24.04新項(xiàng)目、新硬件平臺(tái)ros:jazzy-desktopJazzy24.04新平臺(tái)帶桌面工具我實(shí)際用的是ros:humble-ros-base因?yàn)閐esktop版本體積太大而rviz2這些圖形工具自己可以按需安裝用到什么裝什么反而更清爽。3.2 docker run參數(shù)逐個(gè)拆解啟動(dòng)一個(gè)ROS2容器我會(huì)用這樣一串參數(shù)docker run -it --name ros2_humble \ --network host \ -e DISPLAY$DISPLAY \ -e LIBGL_ALWAYS_SOFTWARE1 \ -e TZAsia/Shanghai \ -v /tmp/.X11-unix:/tmp/.X11-unix \ -v $HOME/ros2_ws:/ros2_ws \ ros:humble-ros-base逐個(gè)說(shuō)說(shuō)為什么這么配--network hostROS2的通信依賴DDSDDS默認(rèn)用UDP多播做節(jié)點(diǎn)發(fā)現(xiàn)。用host網(wǎng)絡(luò)模式容器直接共享deepin主機(jī)的網(wǎng)絡(luò)棧多播包暢通無(wú)阻節(jié)點(diǎn)互相發(fā)現(xiàn)零障礙。這步是ROS2容器能否正常通信的關(guān)鍵。-e DISPLAY$DISPLAY把宿主的圖形顯示環(huán)境變量傳進(jìn)容器讓rviz2知道往哪里畫窗口。-e LIBGL_ALWAYS_SOFTWARE1強(qiáng)制OpenGL走軟件渲染。deepin上如果顯卡驅(qū)動(dòng)沒(méi)處理好rviz2很可能黑屏崩潰先從軟渲染跑通后面再優(yōu)化硬件加速。-e TZAsia/Shanghai容器默認(rèn)UTC時(shí)區(qū)不設(shè)的話日志時(shí)間差8小時(shí)后面排錯(cuò)時(shí)容易混淆。-v /tmp/.X11-unix:/tmp/.X11-unix掛載X11的socket文件這是圖形程序從容器連回宿主桌面的通道。-v $HOME/ros2_ws:/ros2_ws共享工作目錄宿主機(jī)上寫代碼容器里編譯運(yùn)行。注意我加了--name但沒(méi)加--rm因?yàn)槲蚁氡A暨@個(gè)容器容器里安裝的額外包不會(huì)丟。如果只想臨時(shí)用用加--rm更干凈。3.3 容器里的第一行命令source啟動(dòng)容器后你會(huì)直接進(jìn)入一個(gè)root shell。第一件事是加載ROS2環(huán)境變量source /opt/ros/humble/setup.bash ros2 --help如果沒(méi)有這步source直接敲ros2百分百是command not found。為了方便把source寫進(jìn)容器的bashrcecho source /opt/ros/humble/setup.bash ~/.bashrc source ~/.bashrc之后再進(jìn)容器就不用每次手動(dòng)source了。這也是新手最容易忽略的細(xì)節(jié)——網(wǎng)上很多教程直接讓你敲ros2命令卻沒(méi)人告訴你前提是source環(huán)境。3.4 把啟動(dòng)命令固化成腳本手動(dòng)敲docker run那一長(zhǎng)串參數(shù)終究不是長(zhǎng)久之計(jì)。我在deepin主機(jī)的~/bin/下放了一個(gè)啟動(dòng)腳本#!/bin/bash # 啟動(dòng)ROS2 humble容器 xhost local:root docker start ros2_humble 2/dev/null || docker run -it --name ros2_humble \ --network host \ -e DISPLAY$DISPLAY \ -e LIBGL_ALWAYS_SOFTWARE1 \ -e TZAsia/Shanghai \ -v /tmp/.X11-unix:/tmp/.X11-unix \ -v $HOME/ros2_ws:/ros2_ws \ ros:humble-ros-base腳本做了一個(gè)判斷如果容器已經(jīng)存在直接docker start啟動(dòng)不存在才docker run創(chuàng)建。xhost local:root這句放在腳本里省得每次都手動(dòng)授權(quán)X11。4. 畫面要出來(lái)讓rviz2在容器里看見deepin桌面4.1 X11授權(quán)三連DISPLAY、xhost、/tmp/.X11-unix容器里跑圖形程序本質(zhì)是讓容器內(nèi)的進(jìn)程把畫面畫到deepin桌面上。Linux的X11顯示協(xié)議走的是socket通信進(jìn)程要連上X server必須同時(shí)滿足三個(gè)條件知道X server的地址、有訪問(wèn)socket的權(quán)限、能通過(guò)X server的授權(quán)校驗(yàn)。對(duì)應(yīng)的三個(gè)操作我已經(jīng)在前面布置好了-e DISPLAY$DISPLAY把顯示地址傳進(jìn)去。deepin默認(rèn)是:0代表本機(jī)的第一個(gè)顯示設(shè)備。-v /tmp/.X11-unix:/tmp/.X11-unix把X11的socket目錄掛進(jìn)容器。在deepin主機(jī)上執(zhí)行xhost local:root允許本地的root用戶連接X server。xhost local:root這條命令每次重啟機(jī)器后都需要重新執(zhí)行所以我把它直接寫進(jìn)了啟動(dòng)腳本里。如果你發(fā)現(xiàn)容器里啟動(dòng)rviz2時(shí)報(bào)cannot open display優(yōu)先檢查這三項(xiàng)是否都到位了。4.2 顯卡渲染的兩條路軟渲染與掛載/dev/dri圖形界面能打開不代表渲染正常。deepin的機(jī)器配置差異很大有的用N卡閉源驅(qū)動(dòng)有的用Intel核顯。N卡驅(qū)動(dòng)在容器里很容易出問(wèn)題因?yàn)槿萜鲀?nèi)沒(méi)有宿主的X驅(qū)動(dòng)和CUDA庫(kù)直接調(diào)用GPU渲染會(huì)黑屏或者花屏。我的建議是先走軟渲染LIBGL_ALWAYS_SOFTWARE1這個(gè)環(huán)境變量會(huì)讓OpenGL全部走CPU渲染。缺點(diǎn)是幀率低但rviz2這種界面程序不是游戲CPU渲染足夠了。如果你做仿真比如gazebo帶模型加載CPU渲染可能卡那就把宿主機(jī)的GPU設(shè)備掛進(jìn)容器docker run ... --device/dev/dri .../dev/dri是Linux的DRM設(shè)備節(jié)點(diǎn)掛進(jìn)去之后容器里的用戶態(tài)驅(qū)動(dòng)就可以直接訪問(wèn)GPU了。這個(gè)方法對(duì)Intel核顯和AMD卡效果很好N卡反而沒(méi)有在X11下直接掛CUDA走OpenGL的通用做法還是軟渲染更省心。4.3 實(shí)測(cè)在容器里跑turtlesim和rviz2驗(yàn)證圖形鏈路是否通了最輕量的方法是跑turtlesim。在容器里執(zhí)行apt update apt install -y ros-humble-turtlesim ros2 run turtlesim turtlesim_node如果一切正常deepin桌面上會(huì)彈出一個(gè)小海龜?shù)拇翱谀闵踔量梢栽匍_一個(gè)終端用鍵盤控制它。這個(gè)看似簡(jiǎn)單的窗口能彈出來(lái)說(shuō)明DISPLAY、X11授權(quán)、渲染環(huán)境三個(gè)環(huán)節(jié)全部打通后面跑rviz2換湯不換藥。接著驗(yàn)證rviz2apt install -y ros-humble-rviz2 rviz2rviz2的界面比turtlesim復(fù)雜得多如果能正常顯示3D場(chǎng)景且拖動(dòng)不崩潰那這套容器圖形方案就完全成立了。5. 讓容器和deepin主機(jī)真正協(xié)同工作網(wǎng)絡(luò)、共享目錄與用戶映射5.1 host網(wǎng)絡(luò)模式為什么是ROS2的默認(rèn)首選ROS2的通信機(jī)制和ROS1不同它底層用DDSDDS的節(jié)點(diǎn)發(fā)現(xiàn)靠UDP多播。默認(rèn)情況下同一個(gè)局域網(wǎng)內(nèi)的ROS2節(jié)點(diǎn)會(huì)通過(guò)多播地址互相宣告存在。這個(gè)特性在家用路由器環(huán)境里很方便但到了容器就要注意docker默認(rèn)的bridge網(wǎng)絡(luò)模式會(huì)隔離多播包兩個(gè)容器用默認(rèn)網(wǎng)絡(luò)跑ROS2節(jié)點(diǎn)經(jīng)?;ハ嗫床灰姟S?-network host就一勞永逸了容器和deepin主機(jī)共享同一個(gè)網(wǎng)絡(luò)棧多播包直接走宿主物理網(wǎng)卡節(jié)點(diǎn)發(fā)現(xiàn)和通信跟直接在宿主機(jī)上跑沒(méi)區(qū)別。這也是為什么我強(qiáng)烈建議開發(fā)階段用host網(wǎng)絡(luò)模式。代價(jià)是端口隔離失效。比如容器里起了一個(gè)監(jiān)聽固定端口8080的服務(wù)它就占用了宿主機(jī)的8080。ROS2用的端口是動(dòng)態(tài)分配的沖突概率很低但如果你在容器里跑其他Web服務(wù)心里得有個(gè)數(shù)。5.2 用共享目錄做開發(fā)工作流容器里寫代碼最大的痛點(diǎn)是文件隔離。我通常在deepin主機(jī)上用VS Code打開~/ros2_ws寫代碼容器里編譯運(yùn)行兩者通過(guò)掛載共享同一份文件。這樣文件操作在宿主側(cè)權(quán)限管理直觀還能用宿主上熟悉的編輯器。共享目錄的工作流需要一套固定的操作# 在deepin主機(jī)創(chuàng)建并進(jìn)入工作目錄 mkdir -p ~/ros2_ws/src cd ~/ros2_ws # 在容器內(nèi)進(jìn)入同樣的路徑因?yàn)閽燧d兩邊看到的是同一份文件 cd /ros2_ws colcon build --symlink-install source install/setup.bash我在容器里還裝了個(gè)ros-humble-demo-nodes-cpp之類的示例包確認(rèn)編譯后的install目錄能被source。--symlink-install這個(gè)參數(shù)很實(shí)用它用符號(hào)鏈接替代文件拷貝改完源碼不用重新編譯對(duì)頻繁調(diào)試特別友好。5.3 容器內(nèi)用戶的坑與解決默認(rèn)容器里是root用戶root在共享目錄里創(chuàng)建的文件宿主側(cè)屬主也是root。這會(huì)導(dǎo)致一個(gè)很尷尬的情況你在deepin主機(jī)上想改容器里生成的文件沒(méi)有sudo權(quán)限就得干瞪眼。我的解決辦法是讓容器內(nèi)用戶和宿主用戶保持一致的UID。deepin主機(jī)上先看自己的UIDid -u然后用-u參數(shù)指定容器內(nèi)以哪個(gè)UID運(yùn)行docker run -it \ --network host \ -u $(id -u):$(id -g) \ -v $HOME/ros2_ws:/ros2_ws \ ros:humble-ros-base這樣容器內(nèi)創(chuàng)建的文件UID和宿主用戶一致宿主側(cè)隨手就能改。但要注意容器內(nèi)很多系統(tǒng)操作需要root權(quán)限用普通UID運(yùn)行時(shí)會(huì)受限。我的折中方案是日常編譯和運(yùn)行節(jié)點(diǎn)用-u指定普通用戶需要裝包時(shí)才進(jìn)root容器。實(shí)際操作里我會(huì)準(zhǔn)備兩個(gè)啟動(dòng)腳本一個(gè)是root版用來(lái)apt install一個(gè)是普通用戶版用來(lái)日常開發(fā)簡(jiǎn)單粗暴但很好用。6. 實(shí)戰(zhàn)驗(yàn)證與常見翻車點(diǎn)排查6.1 跑通talker/listener驗(yàn)證核心鏈路圖形環(huán)境驗(yàn)證過(guò)了再驗(yàn)證通信鏈路。開兩個(gè)終端進(jìn)入同一個(gè)容器或者分別進(jìn)兩個(gè)容器host網(wǎng)絡(luò)下都一樣一邊跑發(fā)布者一邊跑訂閱者# 終端A ros2 run demo_nodes_cpp talker # 終端B ros2 run demo_nodes_cpp listenerlistener能持續(xù)打印I heard: Hello World說(shuō)明DDS通信鏈路正常。接著可以看話題列表ros2 topic list ros2 topic echo /chatter如果topic能看到但訂閱沒(méi)數(shù)據(jù)大概率是DDS發(fā)現(xiàn)協(xié)議出了問(wèn)題按下面的排查表處理。6.2 全身排查七類典型故障及修復(fù)我把實(shí)操中容易踩的坑整理成一張表按現(xiàn)象排錯(cuò)就行現(xiàn)象根因修復(fù)方案docker: permission denied用戶不在docker組或組未生效newgrp docker或重新登錄拉鏡像超時(shí)未配鏡像加速器修改/etc/docker/daemon.json后重啟ros2: command not found未source環(huán)境source /opt/ros/humble/setup.bash兩個(gè)容器互相看不到節(jié)點(diǎn)DDS多播被bridge網(wǎng)絡(luò)隔離改用--network hostrviz2報(bào)cannot open displayX11授權(quán)或DISPLAY未傳遞檢查xhost local:root和-e DISPLAYrviz2黑屏或崩潰GPU渲染問(wèn)題設(shè)LIBGL_ALWAYS_SOFTWARE1軟渲染容器時(shí)間差8小時(shí)未設(shè)時(shí)區(qū)-e TZAsia/Shanghai重新運(yùn)行這里面最隱蔽的是DDS多播問(wèn)題因?yàn)閳?bào)錯(cuò)不直觀。多個(gè)容器跑起來(lái)后ros2 node list只能看到自己別人一概報(bào)NODE NOT FOUND。新手很難想到是網(wǎng)絡(luò)模式的問(wèn)題我還見過(guò)有人懷疑是防火墻在deepin上折騰半天最后發(fā)現(xiàn)只是docker bridge網(wǎng)絡(luò)把多播包擋住了。換成host網(wǎng)絡(luò)模式立刻解決。6.3 把容器固化下來(lái)docker commit與Compose開發(fā)過(guò)程中你會(huì)裝一堆額外的包比如turtlesim、rviz2、gazebo插件、自己的功能包。如果容器刪了這些全得重裝所以務(wù)必在環(huán)境搭好后固化鏡像docker commit ros2_humble ros2_humble:dev-v1docker commit會(huì)把當(dāng)前容器狀態(tài)打包成新鏡像下次直接用這個(gè)鏡像創(chuàng)建容器所有已裝包都在。我習(xí)慣每穩(wěn)定一個(gè)階段就commit一次版本號(hào)遞增出問(wèn)題可以回滾。更現(xiàn)代的做法是寫docker-compose.yml把啟動(dòng)參數(shù)文件化services: ros2: image: ros:humble-ros-base network_mode: host environment: - DISPLAY${DISPLAY} - LIBGL_ALWAYS_SOFTWARE1 - TZAsia/Shanghai volumes: - /tmp/.X11-unix:/tmp/.X11-unix - $HOME/ros2_ws:/ros2_ws stdin_open: true tty: true command: bash用docker compose up -d一條命令啟動(dòng)參數(shù)全在文件里換機(jī)器也方便。我個(gè)人覺得docker compose雖然比純命令多一步學(xué)習(xí)成本但長(zhǎng)期收益非常大尤其是項(xiàng)目環(huán)境要給別人復(fù)現(xiàn)的時(shí)候。最后再分享一個(gè)實(shí)際工作中的體會(huì)deepin下這套dockerROS2方案真正舒服的地方在于deepin桌面本身對(duì)開發(fā)環(huán)境干預(yù)少、系統(tǒng)干凈容器跑起來(lái)幾乎感覺不到性能損耗。我用了半年多系統(tǒng)一直穩(wěn)定再也沒(méi)出現(xiàn)依賴風(fēng)暴把桌面搞崩的情況。如果你是deepin用戶又想在機(jī)器人開發(fā)這條路上走遠(yuǎn)一點(diǎn)強(qiáng)烈建議花一晚上把docker環(huán)境搭好后面你會(huì)感謝這個(gè)決定的。