ROS编译PyKDL python3
前言
- 前言
- 编译流程
- 下载源码
- 替换文件
- 编译
- anaconda环境使用PyKDL
本篇记录编译PyKDL的python3版本。由于PyKDL是通过pybind11包装C++库,因此使用python3.6编译的.so库不能用于python3.7等不同版本的python。
编译流程 下载源码git clone https://github.com/orocos/orocos_kinematics_dynamics/
git submodule update --init
替换文件
由于KDL库默认优先使用catkin python编译,需要修改CMakeLists.txt
文件使用python3.6编译:
cd orocos_kinematics_dynamics
cd orocos_kdl
将CMakeLists.txt
文件完整替换为:
#
# Test CMake version
#
CMAKE_MINIMUM_REQUIRED(VERSION 3.0.2)
###################################################
# #
# Start project customization section #
# #
###################################################
PROJECT(orocos_kdl)
SET( KDL_VERSION 1.5.1)
STRING( REGEX MATCHALL "[0-9]+" KDL_VERSIONS ${KDL_VERSION} )
LIST( GET KDL_VERSIONS 0 KDL_VERSION_MAJOR)
LIST( GET KDL_VERSIONS 1 KDL_VERSION_MINOR)
LIST( GET KDL_VERSIONS 2 KDL_VERSION_PATCH)
MESSAGE( STATUS "Orocos KDL version ${VERSION} (${KDL_VERSION_MAJOR}.${KDL_VERSION_MINOR}.${KDL_VERSION_PATCH})" )
SET( PROJ_SOURCE_DIR ${orocos_kdl_SOURCE_DIR} )
SET( PROJ_BINARY_DIR ${orocos_kdl_BINARY_DIR} )
# catkin-specific configuration (optional)
#find_package(catkin QUIET)
#if(catkin_FOUND)
# catkin_package(
# SKIP_CMAKE_CONFIG_GENERATION
# SKIP_PKG_CONFIG_GENERATION
# )
#endif()
IF(NOT CMAKE_INSTALL_PREFIX)
SET( CMAKE_INSTALL_PREFIX /usr/local/ CACHE PATH "Installation directory" FORCE)
MESSAGE( STATUS "Setting installation directory to ${CMAKE_INSTALL_PREFIX}" )
ENDIF(NOT CMAKE_INSTALL_PREFIX)
SET(CMAKE_VERSION "${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}.${CMAKE_PATCH_VERSION}")
IF ( NOT CMAKE_BUILD_TYPE )
SET(CMAKE_BUILD_TYPE Release CACHE STRING "Choose the type of build, options are: None(CMAKE_CXX_FLAGS or CMAKE_C_FLAGS used) Debug Release RelWithDebInfo MinSizeRel." FORCE)
MESSAGE( STATUS "Setting build type to '${CMAKE_BUILD_TYPE}'" )
ELSE ( NOT CMAKE_BUILD_TYPE )
MESSAGE( STATUS "Build type set to '${CMAKE_BUILD_TYPE}' by user." )
ENDIF ( NOT CMAKE_BUILD_TYPE )
SET( KDL_CFLAGS "")
find_package(Eigen3 QUIET)
if(NOT EIGEN3_FOUND)
include(${PROJ_SOURCE_DIR}/cmake/FindEigen3.cmake)
endif()
include_directories(${EIGEN3_INCLUDE_DIR})
SET(KDL_CFLAGS "${KDL_CFLAGS} -I${EIGEN3_INCLUDE_DIR}")
# Check the platform STL containers capabilities
include(cmake/CheckSTLContainers.cmake)
CHECK_STL_CONTAINERS()
# Set the default option appropriately
if(HAVE_STL_CONTAINER_INCOMPLETE_TYPES)
set(KDL_USE_NEW_TREE_INTERFACE_DEFAULT OFF)
else(HAVE_STL_CONTAINER_INCOMPLETE_TYPES)
set(KDL_USE_NEW_TREE_INTERFACE_DEFAULT ON)
endif(HAVE_STL_CONTAINER_INCOMPLETE_TYPES)
# Allow the user to select the Tree API version to use
set(KDL_USE_NEW_TREE_INTERFACE ${KDL_USE_NEW_TREE_INTERFACE_DEFAULT} CACHE BOOL "Use the new KDL Tree interface")
#Sanity check, inform the user
if(NOT HAVE_STL_CONTAINER_INCOMPLETE_TYPES AND NOT KDL_USE_NEW_TREE_INTERFACE)
message(WARNING "You have chosen to use the current Tree Interface, but your platform doesn't support containers of "
"incomplete types, this configuration is likely invalid")
endif()
# The new interface requires the use of shared pointers
if(KDL_USE_NEW_TREE_INTERFACE)
# We need shared_ptr from boost since not all compilers are c++11 capable
find_package(Boost REQUIRED)
include_directories(${Boost_INCLUDE_DIRS})
endif(KDL_USE_NEW_TREE_INTERFACE)
OPTION(ENABLE_TESTS OFF "Enable building of tests")
IF( ENABLE_TESTS )
# If not in standard paths, set CMAKE_xxx_PATH's in environment, eg.
# export CMAKE_INCLUDE_PATH=/opt/local/include
# export CMAKE_LIBRARY_PATH=/opt/local/lib
FIND_LIBRARY(CPPUNIT cppunit)
SET(CPPUNIT ${CPPUNIT} "dl")
FIND_PATH(CPPUNIT_HEADERS cppunit/TestRunner.h)
IF ( CPPUNIT AND CPPUNIT_HEADERS)
MESSAGE( STATUS "-- Looking for Cppunit - found")
ELSE ( CPPUNIT AND CPPUNIT_HEADERS )
MESSAGE( FATAL_ERROR "-- Looking for Cppunit - not found")
ENDIF ( CPPUNIT AND CPPUNIT_HEADERS )
ENDIF(ENABLE_TESTS )
OPTION(ENABLE_EXAMPLES OFF "Enable building of examples")
ADD_SUBDIRECTORY( doc )
ADD_SUBDIRECTORY( src )
ADD_SUBDIRECTORY( tests )
ADD_SUBDIRECTORY( models )
ADD_SUBDIRECTORY( examples )
export(TARGETS orocos-kdl
FILE "${PROJECT_BINARY_DIR}/OrocosKDLTargets.cmake")
export(PACKAGE orocos_kdl)
# Generate CMake package configuration
CONFIGURE_FILE(orocos_kdl-config.cmake.in
${PROJECT_BINARY_DIR}/orocos_kdl-config.cmake @ONLY)
CONFIGURE_FILE(orocos_kdl-config-version.cmake.in
${PROJECT_BINARY_DIR}/orocos_kdl-config-version.cmake @ONLY)
INSTALL(FILES cmake/FindEigen3.cmake DESTINATION share/orocos_kdl/cmake)
INSTALL(FILES ${PROJECT_BINARY_DIR}/orocos_kdl-config.cmake DESTINATION share/orocos_kdl/cmake)
INSTALL(FILES ${PROJECT_BINARY_DIR}/orocos_kdl-config-version.cmake DESTINATION share/orocos_kdl/cmake)
INSTALL(EXPORT OrocosKDLTargets DESTINATION share/orocos_kdl/cmake)
# Generate pkg-config package configuration
CONFIGURE_FILE(orocos_kdl.pc.in ${CMAKE_CURRENT_BINARY_DIR}/orocos-kdl.pc @ONLY)
CONFIGURE_FILE(orocos_kdl.pc.in ${CMAKE_CURRENT_BINARY_DIR}/orocos_kdl.pc @ONLY)
INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/orocos-kdl.pc DESTINATION lib${LIB_SUFFIX}/pkgconfig)
INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/orocos_kdl.pc DESTINATION lib${LIB_SUFFIX}/pkgconfig)
然后:
cd ../python_orocos_kdl
将CMakeLists.txt
完整替换为:
cmake_minimum_required(VERSION 3.0.2)
if(POLICY CMP0048)
cmake_policy(SET CMP0048 NEW)
endif()
# Avoid warning from pybind11 on Windows
if(POLICY CMP0054)
cmake_policy(SET CMP0054 NEW)
endif()
if(POLICY CMP0057)
cmake_policy(SET CMP0057 NEW) # support IN_LISTS which is required for PyBind11 2.6 and newer
endif()
project(python_orocos_kdl VERSION 1.5.1)
# find a matching version of orocos_kdl
find_package(orocos_kdl ${PROJECT_VERSION} EXACT REQUIRED)
include_directories(${orocos_kdl_INCLUDE_DIRS})
link_directories(${orocos_kdl_LIBRARY_DIRS})
#if(DEFINED ENV{ROS_PYTHON_VERSION})
# SET(PYTHON_VERSION $ENV{ROS_PYTHON_VERSION} CACHE STRING "Python Version")
#else()
SET(PYTHON_VERSION 3 CACHE STRING "Python Version")
#endif()
set(PYBIND11_PYTHON_VERSION ${PYTHON_VERSION} CACHE STRING "Python version used by PyBind11")
find_package(PythonInterp ${PYTHON_VERSION} REQUIRED)
find_package(PythonLibs ${PYTHON_VERSION_MAJOR}.${PYTHON_VERSION_MINOR} REQUIRED)
# get_python_lib in python3 produces path which isn't in sys.path: https://bugs.launchpad.net/ubuntu/+source/python3-stdlib-extensions/+bug/1832215
# execute_process(COMMAND ${PYTHON_EXECUTABLE} -c "from distutils.sysconfig import get_python_lib; print(get_python_lib(plat_specific=True, prefix=''))" OUTPUT_VARIABLE PYTHON_SITE_PACKAGES OUTPUT_STRIP_TRAILING_WHITESPACE)
set(PYTHON_SITE_PACKAGES_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/lib/python${PYTHON_VERSION_MAJOR}.${PYTHON_VERSION_MINOR}/dist-packages") # This might be overridden below if built with catkin.
set(LIBRARY_NAME "PyKDL")
# catkin-specific configuration (optional)
#find_package(catkin QUIET)
#if(catkin_FOUND)
# catkin_package(
# SKIP_CMAKE_CONFIG_GENERATION
# SKIP_PKG_CONFIG_GENERATION
# )
# set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CATKIN_DEVEL_PREFIX}/${PYTHON_INSTALL_DIR})
# set(PYTHON_SITE_PACKAGES_INSTALL_DIR "${PYTHON_INSTALL_DIR}")
#endif()
# Build the module
if(WIN32)
set(PYTHON_MODULE_EXTENSION ".pyd")
else()
set(PYTHON_MODULE_EXTENSION ".so")
endif()
find_package(pybind11 QUIET)
if(NOT ${pybind11_FOUND})
message(STATUS "pybind11 not found, building from source")
add_subdirectory(pybind11)
else()
message(STATUS "pybind11 found, building against installed version")
endif()
pybind11_add_module(${LIBRARY_NAME}
PyKDL/PyKDL.h
PyKDL/PyKDL.cpp
PyKDL/frames.cpp
PyKDL/kinfam.cpp
PyKDL/framevel.cpp
PyKDL/dynamics.cpp)
target_link_libraries(${LIBRARY_NAME} PRIVATE ${orocos_kdl_LIBRARIES})
install(TARGETS ${LIBRARY_NAME} DESTINATION "${PYTHON_SITE_PACKAGES_INSTALL_DIR}")
编译
首先编译C++库:
cd orocos_kdl
mkdir build
cd build
cmake ..
make -j4
sudo make install
然后再编译python3版:
cd ../python_orocos_kdl
mkdir build
cd build
cmake .. -DPYTHON_EXECUTABLE=/usr/bin/python3.6 -DPYTHON_VERSION=3
make -j4
sudo make install
anaconda环境使用PyKDL
开头写了,python3.6编译的PyKDL不能给python3.7、python3.8…使用,因此编译时要指定python版本:
cmake .. -DPYTHON_EXECUTABLE=/anaconda_path_to_python -DPYTHON_VERSION=3
make -j4
生成PyKDL.so后,将其复制到anaconda/envs/env_name/lib/python3.x/site-packages
下,就可以在虚拟环境下使用了。