Smach 是一个相当好用的 ros 上的基于状态机的任务级调度框架,但是在 ubuntu20.04 上能够运行 smach 核心程序但是却无法运行 smach_viewer 去调试状态机,解决方法之一是可以通过 ros 分布式通信机制和另一台 ubuntu18.04 的 melodic 机器建立分布式通讯,在 ubuntu18.04 上运行 smach_viewer 去调试状态机。或者也可以通过虚拟机代替 ubuntu18.04 的实体机。还有一种解决方案就是将上述虚拟机更换为更轻量级的 docker 容器。

smach 的作者在 github 的一篇 issue 上回答如下,

For reference: I’m using ROS Noetic and SMACH visualization is something I wanted to have to display the current state of my FSM for easy introspection and bling.

I could not update it to work in Noetic for the same reasons @cosmicog mentionned, however I was able to get it working by using ROS Melodic Docker container, even though the rest of the ROS framework was run in Noetic. I don’t foresee anybody updating this repo anytime soon, at least this gives a way to use the visualization in the last iteration of ROS1 without too much effort.

Some modifications were needed, this was run in a Ubuntu 20.04 machine:

1
2
3
4
5

docker run -it --rm --network host -e DISPLAY=$DISPLAY -v /tmp/.X11-unix:/tmp/.X11-unix:rw ros:melodic bash
apt-get update
apt-get install -y python-pyqt5 ros-melodic-executive-smach-visualization

Edit file /opt/ros/melodic/lib/python2.7/dist-packages/smach_viewer/xdot/xdot_qt.py line 44:

1
from python_qt_binding.QtWidgets import QWidget, QMainWindow

Change to

1
from PyQt5.QtWidgets import QWidget, QMainWindow

Comment out line 185 in /opt/ros/melodic/lib/smach_viewer/smach_viewer.py:

1
# self._local_data._data = pickle.loads(msg.local_data)

Or the terminal will be full of errors and the viewer will not update the current state (but will display it).

参考链接

列出本机安装的所有 docker 镜像

1
docker images

通过镜像运行容器(以 ubuntu:15.10 为例)

1
docker run -t -i ubuntu:15.10 /bin/bash

获取新镜像

1
docker pull ubuntu:13.10

查看所有容器

1
docker ps -a

启动|停止|重启容器

1
docker start|stop|restart <容器ID>

进入容器

1
2
3
4
5
# 使用该命令进入的容器,当退出时,容器会停止
docker attach <容器ID>

# 使用该命令进入的容器,当退出时,容器不会停止,将扔挂在后台运行
docker exec -it <容器ID> /bin/bash

导出容器为 docker 镜像

1
docker export <容器ID> > xxx.tar

从 docker 镜像导入容器

1
cat xxx.tar | docker import - <镜像名>

删除容器

1
docker rm -f <容器ID>

删除镜像

1
docker rm -r <镜像名>

端口映射

1
2
3
4

docker ps
docker port

查看日志

1
docker logs <容器ID>