文章同步发表于 知乎
本文记录我使用 Python3
配合 ROS1
和 tensorflow
实现机器人上的深度学习遇到的一些坑。
因为作业的要求,我们需要在 Ubuntu 上运行一个 tensorflow1 的项目,老师给的安装方法是针对 Ubuntu18 + ROS-melodic 的,而我的电脑只能安装 Ubuntu20 + ROS-noetic(Ubuntu 18 安装的时候连硬盘都找不到,驱动太旧了)。本文将在 Ubuntu20 下,使用 python3
+ ros-noetic
+ tensorflow2
运行一个远古仓库——Tensorflow object detector ,记录其安装方法和遇到的一些坑。
安装
conda 环境配置
首先,配置一个 tensorflow 环境。
若还没有换过源,下载速度可能很慢,使用
conda config --show channels
检查当前的源,使用以下命令添加清华源,并在安装时显示来源:
conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/free/
conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/main/
conda config --set show_channel_urls yes
为了使用 python3,这里我选择了 tensorflow2 的第一个版本。首先,运行如下命令搜索指定的包:
conda search tensorflow
从列表中可以看到 tensorflow 2.0.0 只有 py36
和 py37
两个版本,我们接下来选择 py37
,也即 tensorflow 2.0.0 gpu_py37h768510d_0
这个版本来安装。
建立新仓库 rostf
,安装 python、tensorflow、opencv、PIL 四个包,命令如下:
conda create -n rostf python=3.7 tensorflow=2.0.0=gpu_py37h768510d_0 opencv pillow
等待安装完成后,激活该环境:
conda activate rostf
catkin 工作空间配置
在 ~
目录下新建一个文件夹,命名为 rostf_ws
(也可以自己起别的名字),然后再新建 src
文件夹,在 ~/rostf_ws/src
内打开终端,输入命令:
catkin_init_workspace
在 src
文件夹中克隆对应仓库:
git clone https://github.com/Kukanani/vision_msgs.git
git clone https://github.com/osrf/tensorflow_object_detector.git
然后,终端退回到 ~/rostf_ws
目录,指定解释器,进行第一次 catkin_make
:
catkin_make -DPYTHON_EXECUTABLE=<Anaconda Python 解释器路径>
catkin
包在创建时,允许我们指定 Python 编译器的环境。这里,可以使用如下命令,在第一次 catkin_make
时,指定 Python 解释器为 Anaconda 解释器。之后再次编译(运行 catkin_make
)的时候,catkin
就会沿用上述解释器路径。
默认情况下,新建的 rostf
包储存在 ~/anaconda3/envs
中,我的电脑上用户名为 sunlight
,所以路径如下:
catkin_make -DPYTHON_EXECUTABLE=/home/sunlight/anaconda3/envs/rostf/bin/python3
此时直接 catkin_make
会报错,原因是 anaconda
的 python 解释器缺少必要的 ROS 和 catkin 库,运行如下命令安装必要的库:
pip install empy catkin-tools rospkg
安装完成后再次 catkin_make
,建立虚拟环境。
更改 Python 代码
仓库中的 scripts/ros_detector.py
文件使用系统自带的 Python 实现,因此需要修改部分代码。
第一行指定的解释器应该改为 conda 环境的解释器,因此第一行修改如下:
#!/home/sunlight/anaconda3/envs/rostf/bin/python3
另外,该代码 70~75 行,Detector
类的 __init__
函数存在问题:
def __init__(self):
self.image_pub = rospy.Publisher("debug_image",Image, queue_size=1)
self.object_pub = rospy.Publisher("objects", Detection2DArray, queue_size=1)
self.bridge = CvBridge()
self.image_sub = rospy.Subscriber("image", Image, self.image_cb, queue_size=1, buff_size=2**24)
self.sess = tf.compat.v1.Session(graph=detection_graph,config=config)
这段代码先启动了 ROS 节点,再启动 tensorflow 的会话,可能造成属性 sess
还未赋值,ROS 话题就已经开始发布的情况,从而程序报错。需要将 self.sess
的赋值改到 ROS 话题的指定之前:
def __init__(self):
self.sess = tf.compat.v1.Session(graph=detection_graph,config=config)
self.image_pub = rospy.Publisher("debug_image",Image, queue_size=1)
self.object_pub = rospy.Publisher("objects", Detection2DArray, queue_size=1)
self.bridge = CvBridge()
self.image_sub = rospy.Subscriber("image", Image, self.image_cb, queue_size=1, buff_size=2**24)
运行
在 ~/rosrf
中,输入
source devel/setup.bash
激活当前工作空间。
第一次运行时遇到链接库 libtiff
库异常的报错,解决方法是在终端输入
export LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libtiff.so.5
指定加载系统默认的链接库,而不是 conda 环境中的。如果不想每次都输入,可以将这句写在 setup.bash
,~/.bashrc
或 .launch
文件里面,避免每次启动都输入这句话。
经过检验,发现当前的环境下使用 GPU 来运行该仓库会报错,或者运行后显示异常(我的电脑显卡是 RTX 3050 Ti Laptop,出错原因未知),但是屏蔽 GPU、使用 CPU 就能正常运行。于是使用环境变量直接屏蔽 GPU:
export CUDA_VISIBLE_DEVICES=
环境变量 CUDA_VISIBLE_DEVICES
可以规定此时的环境可以看到哪些 cuda 显卡,令该变量为空字符串之后,所有显卡都不可见,tensorflow 只能调用 CPU 运行。
最后,使用如下命令就可以启动摄像头,顺利运行该仓库:
roslaunch tensorflow_object_detector usb_cam_detector.launch