【ROS实战】解决Python版本冲突问题并揭秘ROS基本开发流程
前言
初学ROS,开始使用后遇到了两个问题:1. ros.init_node()
陷入死循环;2. rosrun [pkg] [filename.py]
时陷入死循环。网上针对这两个问题的解答较少,且目前没有找到很好的解答,特此记录解决方式。本文记录的问题和解答包括:
- ROS运行过程中找不到系统中的或是虚拟环境中的python
- 指定anaconda虚拟环境运行ROS
- 配置conda环境时安装相应的包依赖
- ROS工作目录构建和基本开发流程
本文环境配置:Ubuntu 20.04,ros版本为noetic,anaconda虚拟环境中python版本3.8.20,系统自带python版本为3.8.12,路径/usr/bin/python3
文章目录
问题分析与解决
rosrun或是ros.init_node()死循环
首先给出出现问题的原因:运行当前功能包中的代码使用的python版本错误。本文出现这个问题的原因,是编译和运行默认用了anaconda中的base环境(python版本3.12,或者是系统中的python2),即使控制台中已经切换到了一个python3.8的虚拟环境,以及文件开头书写#!/usr/bin/env python3
。锁定问题原因,主要是通过切换不同的虚拟环境来看报错的情况,根据切换环境后的一些表现,推断出ROS编译和运行使用的python可能与终端的显示有所不同。例如用python3.8的虚拟环境测试时,如果直接cd
到scripts
文件夹下利用python filename.py
运行文件,运行成功,但是如果rosrun [pkg] [filename.py]
则会在ros.init_node()
陷入死循环。
catkin_make
的编译过程中可以帮助我们锁定当前系统找到的python,例如下图:
这可能也是
rosrun
等命令运行时调用的python路径,所以思考怎么让catkin_make
这一步找到正确的python路径。
在vscode下可以较为方便的指定编译时使用的python
路径,具体步骤如下:
- 新建的ROS工程目录下使用快捷键
Ctrl+shift+b
(具体的命令是Task build
,如果要找自己对应的快捷键,可以进入到"键盘快捷方式"中,搜索"build",如下图)。
图:检查系统快捷键
- 之后选择
catkin_make: build
选项后的设置按钮,在初次编译前,在.vscode
文件夹下生成tasks.json
文件。图:配置catkin_make: build命令
- 在
tasks.json
中,我们指定编译使用的python
版本。编译时catkin_make
可能只是检测(而不是真的使用)这个python,但是实际测试表明这样的修改使得rosrun
等命令也找到了正确版本的python。我们在taks.json
中添加一行-DPYTHON_EXECUTABLE=...
,其中...
就是我们希望使用的python的绝对路径。本文的书写如下(略去一些系统自动生成的内容):
{
"version": "2.0.0",
"tasks": [
{
"type": "catkin_make",
"args": [
"--directory",
"/home/mr-wonderfool/...",
"-DCMAKE_BUILD_TYPE=RelWithDebInfo",
"-DPYTHON_EXECUTABLE=/home/mr-wonderfool/anaconda3/envs/ROS/bin/python"
],
"problemMatcher": [
"$catkin-gcc"
],
"group": "build",
"label": "catkin_make: build"
}
]
}
其中python绝对路径的获取,可以在控制台中激活希望使用的虚拟环境,然后which python
得到路径。
4. 至此,在vscode中Ctrl+Shift+b
编译时,将使用我们指定的python。同时rosrun
等命令也是同步找到了这个python,再使用rosrun
不会陷入死循环。
配置运行ROS的anaconda虚拟环境
安装ros-noetic
时,系统安装了相应的包依赖,存在/usr/local/lib/python3/dist-packages
中,但是我们虚拟环境里面并没有这些包,需要相应安装,步骤如下:
- 对于大部分包,根据运行文件的报错直接
pip install ...
即可(例如empy) - 本文在试验时,遇到不好处理的包是
PyKDL
,是tf2_ros
导入时的依赖,无法直接通过pip
安装,需要自己编译之后获取PyKDL.so
,具体方法可以参考这篇文章,亲测有效。 - 利用虚拟环境运行时,系统有时会报
import: command not found
这样的错误,这是由于系统不知道这个文件需要用python进行编译,所以需要在文件开始处注明#!/usr/bin/env python3
。注意这句话主要为了提示系统该文件是python文件,具体env
找到的python,仍是我们刚才指明的python。
ROS工作目录构建和基本开发流程
本节总结ROS构建项目和书写文件的基本流程,将上述的两个部分也包括在其中,我们工作区的名称是example_ws
,一个功能包的名称是test_pkg
:
- 创建文件夹
example_ws
,其中创建src
,然后catkin_make
,命令如下:
mkdir example_ws
cd example_ws && mkdir src && cd ..
catkin_make
通过code .
打开example_ws
,利用前文所述方式添加tasks.json
文件。
cd src/
后创建功能包:
cd src
catkin_create_pkg test_pkg [depend1] [depend2] [...]
具体工作目录的样式这里不再赘述,需要注意的是,创建新功能包后,每次新开终端,都要source devel/setup.bash
。如果会在这个工作区长时间开发,可以将其写到~/.bashrc
中,通过:
echo "source [absolute path]/devel/setup.bash" >> ~/.bashrc
也可以书写一个脚本文件,配合roslaunch
等命令一起使用,先source devel/setup.bash
再利用roslaunch
,这里不展开论述。
- 进入功能包中,创建
scripts
文件夹存放所有的python
文件。功能包创建伊始会生成src/
文件夹,不要在其中书写python文件。开发过程中,在工作区example_ws/
和代码文件目录scripts/
下分别开一个控制台。 - 在
scripts
文件夹下创建.py
文件时,尽量不要通过vscode,因为不会自动给文件可执行权限,又会导致rosrun
报错,这里推荐命令行的方式(利用开在scripts/
下的终端):
cd scripts/
touch test.py
chmod +x test.py
对于新建立的文件,第一行固定写上#!/usr/bin/env python3
。
- 重点:每次在
scripts
下添加新文件,都要修改src/
中的CMakeLists.txt
,在其中catkin_install_python
添加scripts/[new file].py
:
catkin_install_python(PROGRAMS
scripts/test.py
DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
)
这个主要用于rosrun时补充文件的绝对路径。
进一步,每次修改CMakeLists.txt
,都要在工作区目录下(利用开在example_ws
下的控制台)重新执行catkin_make
- 补充:
CMakeLists.txt
中几个部分的先后顺序:
find_package()
catkin_package()
include_directories()
catkin_install_python()
- 利用
rosrun
或者roslaunch
运行功能包下的文件即可。
作者:Mr.Wonderfool