1. 核心矛盾:Docker 是没有屏幕的
你的电脑(Windows 11)有一块物理显卡和一个物理显示器。 但是,Docker 容器(以及 WSL)本质上是另一台“电脑”。
这台“电脑”是无头模式 (Headless)的。
意思是:它只有主机,没有接显示器,也没有接鼠标键盘。
当你运行rviz2时,Rviz 程序在 Docker 里大喊:“我要画一个窗口!我要画个红色的车!” 但是 Docker 环顾四周,发现自己连个屏幕都没有,它根本没法显示图像。
2. 救星:X11 协议的分离设计
Linux 的图形界面系统(叫 X Window System,简称 X11)有一个天才的设计:计算和显示是分离的。
计算端(Client):负责算这幅画该怎么画(比如:画一个半径 5cm 的圆)。 ->这是你的 Docker/Rviz。
显示端(Server):负责真正点亮屏幕上的像素点。 ->这是你的 Windows。
这两端不需要在同一台电脑上!它们可以通过网络(TCP/IP)说话。
3. 为什么 MobaXterm 是关键?
这里有一个最容易搞混的概念:服务器 (Server) 和 客户端 (Client) 的角色互换。
通常我们认为“服务器”是提供数据的(比如网站),但在 X11 图形世界里:
Rviz (Docker)是Client (客户端):它发出请求(“帮我画个图”)。
MobaXterm / VcXsrv是Server (显示服务器):它提供服务(“好的,我把这块屏幕借给你用,帮你画出来”)。
MobaXterm 不仅仅是一个终端软件,它内置了一个 X Server。当你打开 MobaXterm 时,它其实在你的 Windows 后台悄悄启动了一个“绘图服务”,监听在6000 端口。
4. 整个过程的“通信流”
当你输入ros2 launch ...时,实际上发生了这通“电话”:
发起请求:Docker 里的 Rviz 启动,读取环境变量
DISPLAY=host.docker.internal:0.0。 意思就是:“我的显示器服务器在宿主机(Windows)那里”。网络传输:Rviz 通过虚拟网卡,把“绘图指令”(不是画面,是指令,比如 Create Window, Draw Line)发给了 Windows 的 IP 地址。
MobaXterm 接电话:Windows 上的 MobaXterm(X Server)收到了这些指令。
如果 MobaXterm 没开:电话没人接 -> Rviz 报错
could not connect to display-> 崩溃。如果 MobaXterm 开了但有权限限制(Access Control):电话接通了但被挂断(“你是陌生人,不准画”) -> Rviz 报错。
如果一切正常:MobaXterm 就在你的 Windows 桌面上弹出一个窗口,严格按照 Rviz 的指令把图像画了出来。
5. 总结
为什么 MobaXterm 这么重要?
因为 Docker 只有“大脑”(负责算),Windows 才有“脸”(负责看)。MobaXterm 就是连接“大脑”和“脸”的那根神经。
你如果不打开 MobaXterm,Docker 里的 Rviz 就像是一个被蒙住眼睛的画家,手里拿着画笔,却找不到画布,最后只能气得“Process has died”。