linux程序移植ros,搭建ros交叉编译环境(从x86到nvidiaarm)
⽅法1:
交叉编译环境搭建流程
交叉编译环境搭建的主要思路是利⽤catkin提供的rostoolchain脚本设置相应的交叉编译⼯具、lib库地址等,中间遇到问题再针对性解决。基础环境:
⽬标运⾏环境
arm64 cpu
Ubuntu 16.04
ros kinetic for arm
编译环境
x86_64 cpu
Ubuntu Kylin(16.04)
ros kinetic for amd64
环境设置流程:
1 ARM ubuntu环境上安装arm-indigo版本,后⾯需要将这个arm版本copy到交叉编译环境上
2 x86环境上安装docker(ubuntu)
3 下载docker-ros(ubuntu)镜像, 加载启动docker-ros(ubuntu+ROS)镜像
4 安装 sudo apt-get install g++-arm-linux-gnueabihf
5 将docker环境中中x86版本的indigo替换成arm版本的indigo,
替换之前需要备份x86版本indigo的lib,因为这些库⽂件在运⾏ros时是需要的。
将x86版本indigo的lib保存到localpath⽬录下,设置export LD_LIBRARY_PATH=localpath,
实现运⾏ros命令时使⽤x86的lib库。
6 将arm环境下的库⽂件/头⽂件 copy到docker环境中,⽬录可以⾃⼰设定⽐如:/$ENV{HOME}/cross-compiling/ubuntu-rootfs
7 配置ake⽂件
#ake
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_C_COMPILER /usr/bin/arm-linux-gnueabihf-gcc)
set(CMAKE_CXX_COMPILER /usr/bin/arm-linux-gnueabihf-g++)
set(CMAKE_FIND_ROOT_PATH /opt/ros/indigo $ENV{HOME}/cross-compiling/ubuntu-rootfs)
set(CMAKE_LIBRARY_PATH $ENV{HOME}/cross-compiling/ubuntu-rootfs/usr/lib/arm-linux-gnueabihf
$ENV{HOME}/cross-compiling/ubuntu-rootfs/usr/lib $ENV{HOME}/cross-compiling/ubuntu-rootfs/lib
$ENV{HOME}/cross-compiling/ubuntu-rootfs/usr/local/lib)
set(CMAKE_INCLUDE_PATH $ENV{HOME}/cross-compiling/ubuntu-rootfs/usr/include $ENV{HOME}/cross-
compiling/ubuntu-rootfs/usr/local/include)
set(LD_LIBRARY_PATH $ENV{HOME}/cross-compiling/ubuntu-rootfs/usr/lib/arm-linux-gnueabihf $ENV{HOME}/cross-compiling/ubuntu-rootfs/usr/lib $ENV{HOME}/cross-compiling/ubuntu-rootfs/lib $ENV{HOME}/cross-compiling/ubuntu-rootfs/usr/local/lib)
set(PYTHON_EXECUTABLE /usr/bin/python)
set(PCL_ROOT $ENV{HOME}/cross-compiling/ubuntu-rootfs/usr)
set(CMAKE_CROSSCOMPILING true)
message("${CMAKE_CROSSCOMPILING}")
# Have to set this one to BOTH, to allow CMake to find rospack
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
8 修改/opt/ros/indigo/share/catkin/cmake/ake
该⽂件的第34⾏
if(NOT (APPLE OR WIN32 OR MINGW OR ANDROID))修改为if(NOT (APPLE OR WIN32 OR MING
W OR ANDROID OR UNIX)) 9 个⼈理解cmake交叉编译过程就是修改cmake搜索链接库⽂件位置的过程,正常编译会搜索x86库⽂件做在位置,
交叉编译需要将搜索位置切换到⽬标架构需要的库⽂件存放位置,⽐如/$ENV{HOME}/cross-compiling/ubuntu-rootfs
实现⽅法:
修改catkin_INCLUDE_DIRS catkin_LIBRARY_DIRS,将这两个变量中指向x86系统的位置,修改为指向交叉编译依赖⽂件存放位置
/opt/ros/indigo/share/catkin/ake
这个⽂件末增加如下处理:
list(APPEND catkin_INCLUDE_DIRS ${CMAKE_INCLUDE_PATH})
list(APPEND catkin_LIBRARY_DIRS ${CMAKE_LIBRARY_PATH})
set(catkin_LIBRARIES_tmp ${catkin_LIBRARIES})
set(catkin_LIBRARIES "")
foreach(catkinlib ${catkin_LIBRARIES_tmp})
string(LENGTH ${catkinlib} lengths)
if (${lengths} GREATER 12)
string(SUBSTRING ${catkinlib} "/" 12 result)
string(COMPARE EQUAL ${result} "/usr/lib/lib" compareResult)
if (${compareResult})
string(REPLACE "/usr/lib/lib" "$ENV{HOME}/cross-compiling/ubuntu-rootfs/usr/lib/lib" result_tem ${catkinlib})
list(APPEND catkin_LIBRARIES ${result_tem})
else()
list(APPEND catkin_LIBRARIES ${catkinlib})
endif()
else()
list(APPEND catkin_LIBRARIES ${catkinlib})
endif()
endforeach()
10 编译命令
catkin_make -DCMAKE_TOOLCHAIN_FILE=/$ake
编译
命令
catkin_make -DCMAKE_TOOLCHAIN_FILE=/$ake
验证编译产出
将devel产出拷贝到px2的workspace中,启动roscore之后,进⼊devel/lib/hdmap_interface,运⾏./hdmap_interface_node ⽅法2:
ros开源了⼀套编译库,直接通过python即可得到交叉编译的结果。
这个包安装ros_cross_compile命令后,使⽤以下指令即可实现交叉。命令的第⼀个参数是指向ROS⼯作区的路径。
下⾯是⼀个标准⼯作流的简单调⽤
python -m ros_cross_compile /path/to/my/workspace --arch aarch64 --os ubuntu --rosdistro dashing
关于脚本的其他参数说明,执⾏"python -m ros_cross_compile -h"获得。
tips:python后⾯需要加 -m 来实现模块当作脚本来启动,作者发现⽂章举的例⼦较为详细,因此作为采⽤,来阐述此处为何需要python -m
python xxx.py与python -m xxx。
这是两种加载py⽂件的⽅式:
前者叫做直接运⾏,此时脚本的__name__为'main';
后者把模块当作脚本来启动,相当于import,此时脚本的__name__为'xxx'。这种启动⽅式时最好不要带后缀.py。
不同的加载py⽂件的⽅式,主要是影响sys.path这个属性。sys.path是⼀个list,是当前Python解析器运⾏的环境,Python解析器会在这些⽬录下去寻依赖库。python导⼊⽂件或模块时默认会先在sys.path⾥其的路径。
# 直接启动:python run.py
test_import_project git:(master) ✗ python run.py
['/Users/sx/Documents/note/test_py/test_import_project',
'/usr/local/Cellar/python/2.7.11/Frameworks/Python.framework/Versions/2.7/lib/python27.zip',
...]
# 以模块⽅式启动:python -m run
test_import_project git:(master) ✗ python -m run
['',
'/usr/local/Cellar/python/2.7.11/Frameworks/Python.framework/Versions/2.7/lib/python27.zip',
mysql下载选x86还是arm对⽐⼀下就可以发现,-m运⾏⽐直接运⾏仅是多了⼀个’’,也就是当前所在的⽬录。
直接启动:把run.py⽂件所在的⽬录放到了sys.path属性中。
模块启动:把也就是当前路径放到了sys.path属性中
在实际场景中,对于多个启动⽬录的程序效果明显
# ⽬录结构如下
package/
__init__.py
mod1.py
package2/
__init__.py
run.py
# run.py 内容如下
import sys
from package import mod1
print(sys.path)
现在就尝试以两种不同的⽅法启动run.py⽂件。
# 直接启动(失败)
➜ test_import_project git:(master) ✗ python package2/run.py
Traceback (most recent call last):
File "package2/run.py", line 2, in
from package import mod1
ImportError: No module named package
# 以模块⽅式启动(成功)
➜ test_import_project git:(master) ✗ python -m package2.run
['',
'/usr/local/Cellar/python/2.7.11/Frameworks/Python.framework/Versions/2.7/lib/python27.zip',
...]
接下来分析⼀下原因。
需要注意的是,当需要启动的py⽂件引⽤了⼀个模块,在启动的时候需要考虑sys.path中有没有import的模块的路径。这个时候,到底是使⽤直接启动,还是以模块的启动?⽬的就是把import的那个模块的路径放到sys.path中。
导⼊⼀个模块时,解释器先在当前⽬录中搜索它。如果没有到的话,就会到 sys.path变量中给出的⽬录列表中查。
我们要启动package2⽂件夹下的run.py,所需模块在package⽬录中。因此当我们直接执⾏run.py时,
只是把run.py⽂件所在的⽬录放到了sys.path属性中,sys.path并没有把package⽬录收录。故会报错。
当我们使⽤-m参数时,把当前路径放到了sys.path属性中。当前路径包含了package⽬录与package2⽬录,故均在sys.path中。运⾏成功。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。