ROS tf使用报错:ImportError: dynamic module does not define module export function (PyInit__tf2)
研究小车导航需要用到GPS,小车的系统是ubuntu16.04,python3的默认版本是3.5,ROS是kinetic版本。
随笔
买了一块GPS+惯导模块进行使用,商家提供的教程和例子可以直接通过ROS获取GPS及IMU等数据,但是需要以来tf2包,能看到这篇文章,说明你清楚的知道这是一个好难受的事情,因为这个问题在ubuntu20.04被解决了,甚至ubuntu18.04解决起来也很简单(笔者现在18.04服务器上解决了这个问题:参考知乎一路绿通:解决python3无法使用ROS中tf的问题 - 知乎 (zhihu.com))。
笔者预先有感觉ubuntu16.04会比18.04遇到很多问题,但也觉得就是遇到问题度娘来帮,不行还有ChatPGT打下手,结果发现还是年轻了,不得不重操旧业看起日志一步步解决了,这一篇文章中间会存在一些遗漏的点,因为笔者昨晚上从4点操作到了9点没有解决,早上来了又浪费了2小时才搞定最后一步的小问题,周期比较长所以只能凭剩余的印象来找补找补了。
回归正文:
问题
使用python 导入tf库时遇到如下的问题(基本上都是吧)
>>> import tf
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
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)
解决方法
前期还是按照知乎上那篇来搞得
1、要确保你的系统已经能够使用catkin build
,若能,则跳过这条;若不能,则需要安装
sudo apt-get install python-catkin-tools
2、回到主目录,创建一个新的仓库(同时做好相关的配置):
mkdir ~/secondary_build_ws
cd ~/secondary_build_ws
catkin config -DPYTHON_EXECUTABLE=/usr/bin/python3 -DPYTHON_INCLUDE_DIR=/usr/include/python3.6m -DPYTHON_LIBRARY=/usr/lib/x86_64-linux-gnu/libpython3.6m.so
catkin config --install
这里有一个问题:知乎是ubuntu18.04,默认版本是python3.6,编译的时候没有太多问题,16.04是python3.5,使用默认的编译时会提示版本问题(具体问题好几个没记录,但统一的都是版本问题),所以这里我配置的是conda对应的环境(应该也可以用后文安装的python3.7,不过这个配置是在安装python3.7之前,我懒得全改了)
catkin config -DPYTHON_EXECUTABLE=~/anaconda3/envs/py38/bin/python3 -DPYTHON_INCLUDE_DIR=anaconda3/envs/py38/include/python3.8 -DPYTHON_LIBRARY=~/anaconda3/envs/py38/lib/libpython3.8.so -DSETUPTOOLS_DEB_LAYOUT=OFF && catkin config --install
注:-DSETUPTOOLS_DEB_LAYOUT=OFF 这个是编译好安装时候遇到的问题,加上这个tf_py 可以安装成功,但是test_tf有问题,不过test_tf可以通过移除文件夹处理(一个test 不涉及功能 我就这样处理了, 如果有大神看到后面的问题指点一下,根号了)
3、去clone仓库geometry2:
mkdir src && cd src && git clone -b indigo-devel https://github.com/ros/geometry2
这里也想提一句:indigo-devel分支 看回复说是把kinetic的分支给合到这个分支来了,kinetic都没有自己的独立分支也是够奇怪的(不知道编译时候遇到那么多的问题跟这个有没有关)
4、编译
cd ..
catkin build
4.1编译时候遇到em问题,直接装个就好了
No module named em
pip install empy
pip3 install empy
4.2编译遇到版本提示
我找不到问题log 应该被我删了
安装python3.7(不知道python3.6行不行)
安装过程见:
我按照这篇装的:Ubuntu16.04 LTS自带的Python3.5升级到Python3.7详细记录_ubuntu python3.5升级到python3.7-CSDN博客
装好了之后会出现用命令行打不开终端的问题,按照下面这篇最后描述的那样修改(这也就是为什么安装python3.7不要卸载python3.5的原因)
PS:遇到相关的对应路径文件打开有问题的,都可以这样改:将一开始指定解释器的python3修改为python3.5:类似这样
#! /usr/bin/python3.5
[Python]Python3.5升级3.7_acbbghhgf的技术博客_51CTO博客
4.3编译遇到找不到python.h 解决
fatal error: #include <python.h> 没有那个文件或目录解决方法
fatal error: #include <python.h> no such file or directory
这个问题很奇葩,我找了半天解决办法,以为是python3.7安装的问题,各种修改前缀比如:<python3.5/python.h>或者<python2.7/python.h>都没有解决,最后解决办法:
// 将报错对应代码的第一行
#include <python.h>
// 修改为Python,大小写的问题!!!!!
#include <Python.h>
4.4编译通过,但是安装报错:
error: option --install-layout not recognized
这里网上有解决办法:
参考文章:error: option --install-layout not recognized-CSDN博客
修改成: 方法2中的-DSETUPTOOLS_DEB_LAYOUT=OFF
4.5修改完4.4之后安装test_tf错误
make: *** No rule to make target `install‘. Stop.
我看到是test_tf,就没有关心,直接把test_tf文件都移走了,希望有懂得大神指导一下这个是啥原因, 感谢感谢!!
5.使用tf
5.1 source路径
可以直接放进./bashrc文件中,也可以直接终端source
source ~/Projects/secondary_build_ws/devel/setup.bash
然后就可以愉快的...稍等稍等还没完
5.2 路径顺序问题
还是有问题,需要注意我们编译的 tf 路径要在 ros/kinetic 前面,不然还是会报错。
有两个办法:在.bashrc中 系统环境变量、或者每次终端source一下
source /opt/ros/kinetic/setup.bash
source ~/你的workspace/devel/setup.bash
source ~/secondary_build_ws/devel/setup.bash --extend
export PYTHONPATH=~/secondary_build_ws/devel/lib/python3/dist-packages:$PYTHONPATH
代码里面 :也可以这样处理一下,保证ros/kinetic一定在最外面
import sys
sys.path.remove('/opt/ros/kinetic/lib/python2.7/dist-packages')
sys.path.append('/opt/ros/kinetic/lib/python2.7/dist-packages')
import tf
6.最后最后,还有一个小小的问题
Traceback (most recent call last):
File "Projects/ViNT/test.py", line 4, in <module>
import tf
File "/opt/ros/kinetic/lib/python2.7/dist-packages/tf/__init__.py", line 29, in <module>
from listener import Transformer, TransformListener, TransformerROS
ModuleNotFoundError: No module named 'listener'
很奇葩的问题,明明 listener.py和__init__.py在同一个目录下(通过vscode都可以直接跳转的哦),但是还是报这个错误,没想明白为啥但是解决也很简单,修改 /opt/ros/kinetic/lib/python2.7/dist-packages/tf/__init__.py 文件
from tf2_ros import TransformException as Exception, ConnectivityException, LookupException, ExtrapolationException
from .listener import Transformer, TransformListener, TransformerROS
from .broadcaster import TransformBroadcaster
对,没看错,加个. 就行,感谢chatgpt拯救我于崩溃边缘(这方法我以前用来解决过这个问题,但是这次就是没想起来)附上chatgpt原话