目录
二、如何将一个python工程封装为一个ROS包并rosrun执行
前言:
我的python代码一般都在pycharm上直接右键运行的,因为pycharm可以集成我的conda虚拟环境。但前段时间需要将我写的python工程“打包”为一个ROS包,并丢到工作空间中和其他部分的代码进行通讯。好假如现在我把整个python工程放到我新创建的一个ros包里,然后我去rosrun这个python工程的入口.py文件(就是平时在pycharm当中右键运行所处在的那份.py文件),就会发现一个大问题:pycharm上能运行是因为它已经帮你集成了你想要的conda虚拟环境,那ROS它在rosrun你的函数时,怎么能知道你的conda虚拟环境呢?这说明我们必须通过某种方式告诉ROS我所期望的编译器在哪里。
也是看网上资料较多较杂,故做个总结。
一、如何在ROS中调用anaconda虚拟环境
1、先上结论:
比如说我指定的conda虚拟环境叫做test_condaros,并且我要运行的文件为:
rosrun test_condaros_pkg main.py
那么我就在这个main.py的第一行加上
#!<path-to-your-conda-env>/bin/python3
这是shebang行,专门用来告诉ROS,当它读到这行注释时,那么接下来的代码都要用shebang行指定的python编译器来运行。其中,
#!
这是必须要有的,后面接不接空格都没关系。然后,
<path-to-your-conda-env>/bin/python3
表示你要指定的python编译器的绝对路径。比如说我创建了一个conda虚拟环境,叫做test_condaros,那么它的python编译器在我的Ubuntu系统里的绝对路径为:
/home/czl/anaconda3/envs/test_condaros/bin/python3,其中czl是我的用户名,至于是python还是python3就要视自己情况而定了。
完整的shebang行长这样:
#! /home/czl/anaconda3/envs/test_condaros/bin/python3
注意事项:
如果希望自己写的shebang行能够正常生效,那么Cmakelistts中的catkin_install_python要保持注释
## Mark executable scripts (Python etc.) for installation
## in contrast to setup.py, you can choose the destination
# catkin_install_python(PROGRAMS
# scripts/my_python_script
# DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
# )
若按照ROS官方的教程“如何写一个发布订阅者节点(python)”cn/ROS/Tutorials/WritingPublisherSubscriber(python) - ROS Wiki
里面会有一步:

如果你在shebang行指定了编译器的同时,还将这个catkin_install_python取消注释,那么catkin_build后这一行catkin_install_python指令便会将你写的shebang行覆盖掉,并调用ROS默认的python编译器。
详细问题可以参考shebang is ignored by rosrun - Robotics Stack Exchange
在这篇博客里,楼主问了“shebang行被rosrun无视了”这个问题,下面有人解答了:

就是说这个catkin_install_python指令会重写你的shebang行。
2、举例验证
下面创建一个简单的ros包来验证上面的结论。
catkin_create_pkg test_condaros_pkg rospy std_msgs
在scripts文件下创建main.py,并添加:
import sys
print(sys.executable) # 来验证能否正确调用test_condaros虚拟环境
用来打印出执行这个文件用的编译器是哪个。
然后我创建一个新的conda虚拟环境:
conda create -n test_condaros python=3.8
并在main.py开头添加shibang行:
#! /home/czl/anaconda3/envs/test_condaros/bin/python3
好测试程序完成,长这样:
#! /home/czl/anaconda3/envs/test_condaros/bin/python3
import sys
print(sys.executable) # 来验证能否正确调用test_condaros虚拟环境
下面开始rosrun来看看使用的编译器是是什么(rosrun前记得给python文件赋予可执行权限)。
①:若按照ROS官方教程来取消注释catkin_install_python指令,rosrun的结果为:
![]()
可明显我的shebang行被覆盖掉了。
②:注释catkin_install_python指令,再rosrun(需要在工作空间先catkin clean后,再执行
catkin build,再rosrun):
![]()
成功!
PS:我还遇到了一个很神奇的bug,如果是自己在Ubuntu上新建工程写shebang行是没有任何问题的,但是这个移植过来的工程就会说我的shebang行有问题,解决办法如下:
若出现报错:
home/czl/anaconda3/envs/trace_detect/bin/python^M:解释器错误: 没有那个文件或目录
则需要在终端出运行如下代码:
sed -i 's/\r$//' /home/czl/catkin_ws/src/test_trace_detect_pkg/scripts/trace_detect_node.py
原因:错误信息中的 ^M 表示在文件中检测到了 Windows 风格的换行符(Carriage Return, CR),这可能是因为文件在 Windows 系统上被编辑过,然后被复制到了 Linux 系统上。Linux 系统期望的是 Unix 风格的换行符,所以需要自己手动去修改
二、如何将一个python工程封装为一个ROS包并rosrun执行
举例演示
我原先有一个python工程,里面主要是一个faster-rcnn的深度学习模型,以及一些open3d之类的其他图像处理代码,大致结构长这样:

总之就是,所有代码都在faster_rcnn文件夹里面了,并且,入口文件main_2D3D.py在faster_rcnn目录下面。
现在我创建一个ros包:trace_detect_pkg,并在其中的scripts文件中,将faster_rcnn里的所有文件全部复制到里面(方便起见,确保入口文件在scripts目录下就行)。
同时,这个main_2D3D.py将不再作为我的入口文件了,我新建了一个trace_detect_node.py作为我的这个trace_detect_pkg的入口文件(作为一个用于通讯的节点python文件,并在里面调用main_2D3D.py),方便管理,也保证用于ROS通讯部分的代码不会污染原先的代码。
好,现在已经将整个python工程搬到ros包里了,接下来就是要做4件事:
1、告诉ROS,当执行
rosrun trace_detect_pkg trace_detect_node.py
时,要用哪个编译器。这个简单,只需要在入口文件trace_detect_node.py的第一行加上sheshang行:
#! /home/czl/anaconda3/envs/trace_detect/bin/python
2、确保ROS能够根据程序里写的各种 相对路径 来查找文件。
同样,也是在入口文件trace_detect_node.py里加上:
import os
script_dir = os.path.dirname(os.path.realpath(__file__))
os.chdir(script_dir)
这段代码的作用是将Python脚本的当前工作目录切换到该脚本文件所在的目录。
例子:假如我现在要运行这个main_2D3D.py(里面包含了许多相对于这个main_2D3D.py而言的路径,比如 ../tmpl.ply)我是在终端直接跑czl@czl-virtual-machine:~$ rosrun test_trace_detect_pkg trace_detect_node.py 这个节点的,那么此时运行的路径就在你的主目录/home/czl下,那么遇到这些相对路径../tmpl.ply,肯定是找不到的。
3、赋予入口文件执行权限
chmod +x trace_detect_node.py
4、至于Cmakelists与package.xml,如果你只是想rosrun这个python工程而不进行任何ros通讯的话,那么只需要一个rospy就搞定了,不需要c++那么复杂。
## Find catkin macros and libraries
## if COMPONENTS list like find_package(catkin REQUIRED COMPONENTS xyz)
## is used, also find other catkin packages
find_package(catkin REQUIRED COMPONENTS
rospy
)
好,此时catkin_build一下,没问题就可以rosrun了。
1万+





