2020-5-17更新

如果你是在使用Kitti2bag时出错就创建一个python2的环境吧,在环境中安装opencv、kitti2bag、以及安装一些必要的包(根据实际情况)

pip install catkin_pkg pyyaml empy rospkg numpy

然后在对应的目录下执行kitti2bag脚本就可以了。

ros使用python3编译cv_bridge、tf等packages_解决方案


原文

​https://stackoverflow.com/questions/49221565/unable-to-use-cv-bridge-with-ros-kinetic-and-python3​

​https://community.bwbot.org/topic/499/%E5%9C%A8ros%E4%B8%AD%E4%BD%BF%E7%94%A8python3/2​


理解不到位的地方还请多多指正


在使用kitti2bag时候,会出现各种问题,下面简单列举

先看一下kitti2bag的文件内容

#!/home/s/anaconda3/envs/py3.7/bin/python3.7
# -*- coding: utf-8 -*-

import sys

try:
import pykitti
print('-----')
except ImportError as e:
print('Could not load module \'pykitti\'. Please run `pip install pykitti`')
sys.exit(1)

# clear py2.7
# sys.path.remove('/opt/ros/kinetic/lib/python2.7/dist-packages')
# print(sys.path)

# sys.path.append('/home/s/anaconda3/envs/py3.7/lib/python3.7/site-packages')
# sys.path.remove('/home/s/ros_study/devel/lib/python2.7/dist-packages')
# print(sys.path)
# sys.path.append('/opt/ros/kinetic/lib/python2.7/dist-packages')
# print(sys.path)
import tf
import os
import cv2
import rospy
import rosbag
import progressbar
from tf2_msgs.msg import TFMessage
from datetime import datetime
from std_msgs.msg import Header
from sensor_msgs.msg import CameraInfo, Imu, PointField, NavSatFix
import sensor_msgs.point_cloud2 as pcl2
from geometry_msgs.msg import TransformStamped, TwistStamped, Transform
print(tf.__file__)
sys.path.append('/opt/ros/kinetic/lib/python2.7/dist-packages')
import cv_bridge
from cv_bridge import CvBridge
print(cv_bridge.__file__)
import numpy as np
import argparse

可以看到,其中需要tf、cv2、rospy、pykitti等packages。
这里面既有Python2的,也有python3的。

问题1

在开始运行命令

(py3.7) ➜  ~ kitti2bag -t 2011_09_26 -r 0001 raw_synced

时,会出现说pykitti找不到这个问题。
对于这个问题,可以开一个Ipython然后Import pykitti
这时可能会找到原因,我的原因是cv2的原因,然后我的解决方案是将环境中的python2的cv2改个名,

sudo mv cv2.so cv2_ros.so

然后在找cv2就找的是当前环境中的cv2了。


问题2

tf的问题,这个问题经查找是由于在python3中无法使用tf

File "/home/s/test/src/py3_cv_bridge/scripts/bev_image.py", line 13, in <module>
import tf
File "/opt/ros/kinetic/lib/python2.7/dist-packages/tf/__init__.py", line 28, in <module>
from tf2_ros import TransformException as Exception, ConnectivityException, LookupException, ExtrapolationException
File "/opt/ros/kinetic/lib/python2.7/dist-packages/tf2_ros/__init__.py", line 38, in <module>
from tf2_py import *
File "/opt/ros/kinetic/lib/python2.7/dist-packages/tf2_py/__init__.py", line 38, in <module>
from ._tf2 import *
ImportError: dynamic module does not define module export function (PyInit__tf2)

这个问题的原因比较复杂,主要是由于路径引起的。
在python中使用tf的tf只能是python3编译的,所以为了解决这个问题我们需要使用python3编译tf
参考:​在ROS中使用Python3​编译完成后,需要将该目录source在.zsh中。
在我们想要使用tf的py文件中,在sys.path需要将python3编译的tf的功能包放在ros自带的packages前面,如下所示,
新建一个ipython

(py3.7) ➜  test ipython
Python 3.7.6 | packaged by conda-forge | (default, Mar 23 2020, 23:03:20)
Type 'copyright', 'credits' or 'license' for more information
IPython 7.14.0 -- An enhanced Interactive Python. Type '?' for help.

In [1]: import sys

In [2]: sys.apth
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-2-025fbe3aa165> in <module>
----> 1 sys.apth

AttributeError: module 'sys' has no attribute 'apth'

In [3]: sys.path
Out[3]:
['/home/s/anaconda3/envs/py3.7/bin',
'',
'/opt/ros/kinetic/lib/python2.7/dist-packages',
'/home/s/py3_ws/devel_isolated/tf_conversions/lib/python3/dist-packages',
'/home/s/py3_ws/devel_isolated/tf2_sensor_msgs/lib/python3/dist-packages',
'/home/s/py3_ws/devel_isolated/tf2_kdl/lib/python3/dist-packages',
'/home/s/py3_ws/devel_isolated/tf2_geometry_msgs/lib/python3/dist-packages',
'/home/s/py3_ws/devel_isolated/tf/lib/python3/dist-packages',
'/home/s/py3_ws/devel_isolated/tf2_ros/lib/python3/dist-packages',
'/home/s/py3_ws/devel_isolated/tf2_py/lib/python3/dist-packages',
'/home/s/py3_ws/devel_isolated/tf2_msgs/lib/python3/dist-packages',
'/home/s/py3_ws/devel_isolated/image_geometry/lib/python3/dist-packages',
'/home/s/py3_ws/devel_isolated/cv_bridge/lib/python3/dist-packages',
'/home/s/anaconda3/envs/py3.7/lib/python37.zip',
'/home/s/anaconda3/envs/py3.7/lib/python3.7',
'/home/s/anaconda3/envs/py3.7/lib/python3.7/lib-dynload',
'/home/s/anaconda3/envs/py3.7/lib/python3.7/site-packages',
'/home/s/anaconda3/envs/py3.7/lib/python3.7/site-packages/IPython/extensions',
'/home/s/.ipython']

In [4]: sys.path.remove("/opt/ros/kinetic/lib/python2.7/dist-packages")\
...: sys.path.append("/opt/ros/kinetic/lib/python2.7/dist-packages")\
...: sys.path
File "<ipython-input-4-2783301f9e76>", line 2
sys.path.append("/opt/ros/kinetic/lib/python2.7/dist-packages")\
^
SyntaxError: invalid syntax


In [5]: sys.path
Out[5]:
['/home/s/anaconda3/envs/py3.7/bin',
'',
'/opt/ros/kinetic/lib/python2.7/dist-packages',
'/home/s/py3_ws/devel_isolated/tf_conversions/lib/python3/dist-packages',
'/home/s/py3_ws/devel_isolated/tf2_sensor_msgs/lib/python3/dist-packages',
'/home/s/py3_ws/devel_isolated/tf2_kdl/lib/python3/dist-packages',
'/home/s/py3_ws/devel_isolated/tf2_geometry_msgs/lib/python3/dist-packages',
'/home/s/py3_ws/devel_isolated/tf/lib/python3/dist-packages',
'/home/s/py3_ws/devel_isolated/tf2_ros/lib/python3/dist-packages',
'/home/s/py3_ws/devel_isolated/tf2_py/lib/python3/dist-packages',
'/home/s/py3_ws/devel_isolated/tf2_msgs/lib/python3/dist-packages',
'/home/s/py3_ws/devel_isolated/image_geometry/lib/python3/dist-packages',
'/home/s/py3_ws/devel_isolated/cv_bridge/lib/python3/dist-packages',
'/home/s/anaconda3/envs/py3.7/lib/python37.zip',
'/home/s/anaconda3/envs/py3.7/lib/python3.7',
'/home/s/anaconda3/envs/py3.7/lib/python3.7/lib-dynload',
'/home/s/anaconda3/envs/py3.7/lib/python3.7/site-packages',
'/home/s/anaconda3/envs/py3.7/lib/python3.7/site-packages/IPython/extensions',
'/home/s/.ipython']

In [6]: sys.path.remove('/opt/ros/kinetic/lib/python2.7/dist-packages')

In [7]: sys.path
Out[7]:
['/home/s/anaconda3/envs/py3.7/bin',
'',
'/home/s/py3_ws/devel_isolated/tf_conversions/lib/python3/dist-packages',
'/home/s/py3_ws/devel_isolated/tf2_sensor_msgs/lib/python3/dist-packages',
'/home/s/py3_ws/devel_isolated/tf2_kdl/lib/python3/dist-packages',
'/home/s/py3_ws/devel_isolated/tf2_geometry_msgs/lib/python3/dist-packages',
'/home/s/py3_ws/devel_isolated/tf/lib/python3/dist-packages',
'/home/s/py3_ws/devel_isolated/tf2_ros/lib/python3/dist-packages',
'/home/s/py3_ws/devel_isolated/tf2_py/lib/python3/dist-packages',
'/home/s/py3_ws/devel_isolated/tf2_msgs/lib/python3/dist-packages',
'/home/s/py3_ws/devel_isolated/image_geometry/lib/python3/dist-packages',
'/home/s/py3_ws/devel_isolated/cv_bridge/lib/python3/dist-packages',
'/home/s/anaconda3/envs/py3.7/lib/python37.zip',
'/home/s/anaconda3/envs/py3.7/lib/python3.7',
'/home/s/anaconda3/envs/py3.7/lib/python3.7/lib-dynload',
'/home/s/anaconda3/envs/py3.7/lib/python3.7/site-packages',
'/home/s/anaconda3/envs/py3.7/lib/python3.7/site-packages/IPython/extensions',
'/home/s/.ipython']

In [8]: sys.path.append('/opt/ros/kinetic/lib/python2.7/dist-packages')

In [9]: sys.path
Out[9]:
['/home/s/anaconda3/envs/py3.7/bin',
'',
'/home/s/py3_ws/devel_isolated/tf_conversions/lib/python3/dist-packages',
'/home/s/py3_ws/devel_isolated/tf2_sensor_msgs/lib/python3/dist-packages',
'/home/s/py3_ws/devel_isolated/tf2_kdl/lib/python3/dist-packages',
'/home/s/py3_ws/devel_isolated/tf2_geometry_msgs/lib/python3/dist-packages',
'/home/s/py3_ws/devel_isolated/tf/lib/python3/dist-packages',
'/home/s/py3_ws/devel_isolated/tf2_ros/lib/python3/dist-packages',
'/home/s/py3_ws/devel_isolated/tf2_py/lib/python3/dist-packages',
'/home/s/py3_ws/devel_isolated/tf2_msgs/lib/python3/dist-packages',
'/home/s/py3_ws/devel_isolated/image_geometry/lib/python3/dist-packages',
'/home/s/py3_ws/devel_isolated/cv_bridge/lib/python3/dist-packages',
'/home/s/anaconda3/envs/py3.7/lib/python37.zip',
'/home/s/anaconda3/envs/py3.7/lib/python3.7',
'/home/s/anaconda3/envs/py3.7/lib/python3.7/lib-dynload',
'/home/s/anaconda3/envs/py3.7/lib/python3.7/site-packages',
'/home/s/anaconda3/envs/py3.7/lib/python3.7/site-packages/IPython/extensions',
'/home/s/.ipython',
'/opt/ros/kinetic/lib/python2.7/dist-packages']

In [10]: import tf

In [11]: tf.__file__
Out[11]: '/home/s/py3_ws/devel_isolated/tf/lib/python3/dist-packages/tf/__init__.py'
问题3
ImportError: dynamic module does not define module export function (PyInit_cv_bridge_boost)

python貌似是可以使用Python2的cv_bridge的,但是如果要想使用python3编译的cv_bridge的话,也是需要python2的packages的。如下所示

#### Python2的cv_bridge
(py3.7) ➜ test ipython
Python 3.7.6 | packaged by conda-forge | (default, Mar 23 2020, 23:03:20)
Type 'copyright', 'credits' or 'license' for more information
IPython 7.14.0 -- An enhanced Interactive Python. Type '?' for help.

In [1]: import cv_bridge

In [2]: cv_bridge.__file__
Out[2]: '/opt/ros/kinetic/lib/python2.7/dist-packages/cv_bridge/__init__.py'

In [3]: import sys

In [4]: sys.path.remove('/opt/ros/kinetic/lib/python2.7/dist-packages')

In [5]: import cv_bridge

In [6]: cv_bridge.__file__
Out[6]: '/opt/ros/kinetic/lib/python2.7/dist-packages/cv_bridge/__init__.py'
#### python3的cv_bridge
(py3.7) ➜ test ipython
Python 3.7.6 | packaged by conda-forge | (default, Mar 23 2020, 23:03:20)
Type 'copyright', 'credits' or 'license' for more information
IPython 7.14.0 -- An enhanced Interactive Python. Type '?' for help.

In [1]: import sys

In [2]: sys.path.remove('/opt/ros/kinetic/lib/python2.7/dist-packages')

In [3]: import cv_bridge
---------------------------------------------------------------------------
ModuleNotFoundError Traceback (most recent call last)
<ipython-input-3-19d934114051> in <module>
----> 1 import cv_bridge

~/py3_ws/devel_isolated/cv_bridge/lib/python3/dist-packages/cv_bridge/__init__.py in <module>
33 for __execfile in __execfiles:
34 with open(__execfile, 'r') as __fh:
---> 35 exec(__fh.read())
36 del __fh
37 del __execfile

~/py3_ws/devel_isolated/cv_bridge/lib/python3/dist-packages/cv_bridge/__init__.py in <module>

~/py3_ws/src/vision_opencv/cv_bridge/python/cv_bridge/core.py in <module>
32 # POSSIBILITY OF SUCH DAMAGE.
33
---> 34 import sensor_msgs.msg
35 import sys
36

ModuleNotFoundError: No module named 'sensor_msgs'

In [4]: sys.path.append('/opt/ros/kinetic/lib/python2.7/dist-packages')

In [5]: import cv_bridge

In [6]: cv_bridge.__file__
Out[6]: '/home/s/py3_ws/src/vision_opencv/cv_bridge/python/cv_bridge/__init__.py'

编译参考:Unable to use cv_bridge with ROS Kinetic and Python3 需要注意的是 编译时的python解析器要选择python3

(venv) ➜  py3_ws catkin_make_isolated -DPYTHON_EXECUTABLE:FILEPATH=/home/s/py3_ws/venv/bin/python3.5

结果

(venv) ➜  py3_ws source devel_isolated/setup.zsh
(venv) ➜ py3_ws echo $ROS_PACKAGE_PATH
/home/s/py3_ws/src/vision_opencv/vision_opencv:/home/s/py3_ws/src/geometry/tf_conversions:/home/s/py3_ws/src/geometry2-noetic-devel/tf2_tools:/home/s/py3_ws/src/geometry2-noetic-devel/tf2_sensor_msgs:/home/s/py3_ws/src/geometry2-noetic-devel/test_tf2:/home/s/py3_ws/src/geometry2-noetic-devel/tf2_kdl:/home/s/py3_ws/src/geometry2-noetic-devel/tf2_geometry_msgs:/home/s/py3_ws/src/geometry/tf:/home/s/py3_ws/src/geometry2-noetic-devel/tf2_ros:/home/s/py3_ws/src/geometry2-noetic-devel/tf2_py:/home/s/py3_ws/src/geometry2-noetic-devel/tf2_eigen:/home/s/py3_ws/src/geometry2-noetic-devel/tf2_bullet:/home/s/py3_ws/src/geometry2-noetic-devel/tf2:/home/s/py3_ws/src/geometry2-noetic-devel/tf2_msgs:/home/s/py3_ws/src/vision_opencv/opencv_tests:/home/s/py3_ws/src/geometry/kdl_conversions:/home/s/py3_ws/src/vision_opencv/image_geometry:/home/s/py3_ws/src/geometry2-noetic-devel/geometry2:/home/s/py3_ws/src/geometry/geometry:/home/s/py3_ws/src/geometry/eigen_conversions:/home/s/py3_ws/src/vision_opencv/cv_bridge:/opt/ros/kinetic/share
(venv) ➜ py3_ws ipython
Python 3.5.2 (default, Apr 16 2020, 17:47:17)
Type 'copyright', 'credits' or 'license' for more information
IPython 7.9.0 -- An enhanced Interactive Python. Type '?' for help.

In [1]: import tf

In [2]: tf.__file__
Out[2]: '/home/s/py3_ws/devel_isolated/tf/lib/python3/dist-packages/tf/__init__.py'

In [3]: import sys

In [4]: sys.path
Out[4]:
['/home/s/py3_ws/src/geometry2-noetic-devel/tf2_py/src',
'/home/s/py3_ws/src/geometry2-noetic-devel/tf2_ros/src',
'/home/s/py3_ws/src/geometry/tf/src',
'/home/s/py3_ws/venv/bin',
'',
'/home/s/py3_ws/devel_isolated/tf_conversions/lib/python3/dist-packages',
'/home/s/py3_ws/devel_isolated/tf2_sensor_msgs/lib/python3/dist-packages',
'/home/s/py3_ws/devel_isolated/tf2_kdl/lib/python3/dist-packages',
'/home/s/py3_ws/devel_isolated/tf2_geometry_msgs/lib/python3/dist-packages',
'/home/s/py3_ws/devel_isolated/tf/lib/python3/dist-packages',
'/home/s/py3_ws/devel_isolated/tf2_ros/lib/python3/dist-packages',
'/home/s/py3_ws/devel_isolated/tf2_py/lib/python3/dist-packages',
'/home/s/py3_ws/devel_isolated/tf2_msgs/lib/python3/dist-packages',
'/home/s/py3_ws/devel_isolated/image_geometry/lib/python3/dist-packages',
'/home/s/py3_ws/devel_isolated/cv_bridge/lib/python3/dist-packages',
'/home/s/py3_ws/devel_isolated/tf_conversions/lib/python2.7/dist-packages',
'/home/s/py3_ws/devel_isolated/tf2_sensor_msgs/lib/python2.7/dist-packages',
'/home/s/py3_ws/devel_isolated/tf2_kdl/lib/python2.7/dist-packages',
'/home/s/py3_ws/devel_isolated/tf2_geometry_msgs/lib/python2.7/dist-packages',
'/home/s/py3_ws/devel_isolated/tf/lib/python2.7/dist-packages',
'/home/s/py3_ws/devel_isolated/tf2_ros/lib/python2.7/dist-packages',
'/home/s/py3_ws/devel_isolated/tf2_py/lib/python2.7/dist-packages',
'/home/s/py3_ws/devel_isolated/tf2_msgs/lib/python2.7/dist-packages',
'/home/s/py3_ws/devel_isolated/image_geometry/lib/python2.7/dist-packages',
'/home/s/py3_ws/devel_isolated/cv_bridge/lib/python2.7/dist-packages',
'/opt/ros/kinetic/lib/python2.7/dist-packages',
'/usr/lib/python35.zip',
'/usr/lib/python3.5',
'/usr/lib/python3.5/plat-x86_64-linux-gnu',
'/usr/lib/python3.5/lib-dynload',
'/home/s/py3_ws/venv/lib/python3.5/site-packages',
'/home/s/py3_ws/venv/lib/python3.5/site-packages/IPython/extensions',
'/home/s/.ipython']

In [5]: import cv_bridge

In [6]: cv_bridge.__file__
Out[6]: '/home/s/py3_ws/devel_isolated/cv_bridge/lib/python3/dist-packages/cv_bridge/__init__.py'

In [7]:
Do you really want to exit ([y]/n)? n

In [7]: from cv_bridge.boost.cv_bridge_boost import getCvType

In [8]:

总结

python3使用的tf必须是python3自己编译的,其余的packages貌似是可以使用Python2的。
在Python3环境中使用packages要时刻注意sys.path中的先后顺序,导入时会自动从前面向后查找。所以,对于python3的tf,要将其路径放在ros自带的路径之前