...
 
Commits (224)
build*
release/
_build/
_release/
*~
Xcode/
*build*
......@@ -19,92 +19,65 @@ cache:
- make install
- cd work.$(hostname)/$(make show-var VARNAME=DISTNAME)
- make test
robotpkg-py-eigenpy-dubnium-release:
<<: *robotpkg-py-eigenpy
image: eur0c.laas.fr:5000/stack-of-tasks/eigenpy/py-eigenpy:dubnium
- make uninstall
robotpkg-py-eigenpy-16.04-release:
<<: *robotpkg-py-eigenpy
image: eur0c.laas.fr:5000/stack-of-tasks/eigenpy/py-eigenpy:16.04
image: memmos.laas.fr:5000/stack-of-tasks/eigenpy/py-eigenpy:16.04
robotpkg-py-eigenpy-18.04-release:
<<: *robotpkg-py-eigenpy
image: eur0c.laas.fr:5000/stack-of-tasks/eigenpy/py-eigenpy:18.04
robotpkg-py-eigenpy-py3-dubnium-release:
<<: *robotpkg-py-eigenpy
image: eur0c.laas.fr:5000/stack-of-tasks/eigenpy/py-eigenpy-py3:dubnium
allow_failure: true
image: memmos.laas.fr:5000/stack-of-tasks/eigenpy/py-eigenpy:18.04
robotpkg-py-eigenpy-py3-16.04-release:
<<: *robotpkg-py-eigenpy
image: eur0c.laas.fr:5000/stack-of-tasks/eigenpy/py-eigenpy-py3:16.04
allow_failure: true
image: memmos.laas.fr:5000/stack-of-tasks/eigenpy/py-eigenpy-py3:16.04
robotpkg-py-eigenpy-py3-18.04-release:
<<: *robotpkg-py-eigenpy
image: eur0c.laas.fr:5000/stack-of-tasks/eigenpy/py-eigenpy-py3:18.04
image: memmos.laas.fr:5000/stack-of-tasks/eigenpy/py-eigenpy-py3:18.04
robotpkg-py-eigenpy-14.04-release:
<<: *robotpkg-py-eigenpy
image: eur0c.laas.fr:5000/stack-of-tasks/eigenpy/py-eigenpy:14.04
image: memmos.laas.fr:5000/stack-of-tasks/eigenpy/py-eigenpy:14.04
robotpkg-py-eigenpy-14.04-debug:
<<: *robotpkg-py-eigenpy
image: eur0c.laas.fr:5000/stack-of-tasks/eigenpy/py-eigenpy:14.04
image: memmos.laas.fr:5000/stack-of-tasks/eigenpy/py-eigenpy:14.04
before_script:
- echo PKG_OPTIONS.py-eigenpy=debug >> /opt/openrobots/etc/robotpkg.conf
robotpkg-py-eigenpy-py3-14.04-release:
<<: *robotpkg-py-eigenpy
image: eur0c.laas.fr:5000/stack-of-tasks/eigenpy/py-eigenpy-py3:14.04
allow_failure: true
image: memmos.laas.fr:5000/stack-of-tasks/eigenpy/py-eigenpy-py3:14.04
robotpkg-py-eigenpy-py3-14.04-debug:
<<: *robotpkg-py-eigenpy
image: eur0c.laas.fr:5000/stack-of-tasks/eigenpy/py-eigenpy-py3:14.04
before_script:
- echo PKG_OPTIONS.py-eigenpy=debug >> /opt/openrobots/etc/robotpkg.conf
allow_failure: true
robotpkg-py-eigenpy-dubnium-debug:
<<: *robotpkg-py-eigenpy
image: eur0c.laas.fr:5000/stack-of-tasks/eigenpy/py-eigenpy:dubnium
image: memmos.laas.fr:5000/stack-of-tasks/eigenpy/py-eigenpy-py3:14.04
before_script:
- echo PKG_OPTIONS.py-eigenpy=debug >> /opt/openrobots/etc/robotpkg.conf
robotpkg-py-eigenpy-py3-dubnium-debug:
<<: *robotpkg-py-eigenpy
image: eur0c.laas.fr:5000/stack-of-tasks/eigenpy/py-eigenpy-py3:dubnium
before_script:
- echo PKG_OPTIONS.py-eigenpy=debug >> /opt/openrobots/etc/robotpkg.conf
allow_failure: true
robotpkg-py-eigenpy-16.04-debug:
<<: *robotpkg-py-eigenpy
image: eur0c.laas.fr:5000/stack-of-tasks/eigenpy/py-eigenpy:16.04
image: memmos.laas.fr:5000/stack-of-tasks/eigenpy/py-eigenpy:16.04
before_script:
- echo PKG_OPTIONS.py-eigenpy=debug >> /opt/openrobots/etc/robotpkg.conf
robotpkg-py-eigenpy-py3-16.04-debug:
<<: *robotpkg-py-eigenpy
image: eur0c.laas.fr:5000/stack-of-tasks/eigenpy/py-eigenpy-py3:16.04
image: memmos.laas.fr:5000/stack-of-tasks/eigenpy/py-eigenpy-py3:16.04
before_script:
- echo PKG_OPTIONS.py-eigenpy=debug >> /opt/openrobots/etc/robotpkg.conf
allow_failure: true
robotpkg-py-eigenpy-18.04-debug:
<<: *robotpkg-py-eigenpy
image: eur0c.laas.fr:5000/stack-of-tasks/eigenpy/py-eigenpy:18.04
image: memmos.laas.fr:5000/stack-of-tasks/eigenpy/py-eigenpy:18.04
before_script:
- echo PKG_OPTIONS.py-eigenpy=debug >> /opt/openrobots/etc/robotpkg.conf
robotpkg-py-eigenpy-py3-18.04-debug:
<<: *robotpkg-py-eigenpy
image: eur0c.laas.fr:5000/stack-of-tasks/eigenpy/py-eigenpy-py3:18.04
image: memmos.laas.fr:5000/stack-of-tasks/eigenpy/py-eigenpy-py3:18.04
before_script:
- echo PKG_OPTIONS.py-eigenpy=debug >> /opt/openrobots/etc/robotpkg.conf
language: python
python:
- "2.7"
- "3.5"
sudo: required
git:
depth: false
compiler:
- gcc
# - clang
......@@ -22,14 +21,28 @@ jobs:
include:
- dist: bionic
env: BUILDTYPE=Release
python: 2.7
- dist: bionic
env: BUILDTYPE=Release
python: 3.6
- dist: bionic
env: BUILDTYPE=Debug
python: 2.7
- dist: bionic
env: BUILDTYPE=Debug
python: 3.6
- dist: xenial
env: BUILDTYPE=Release
python: 2.7
- dist: xenial
env: BUILDTYPE=Debug
env: BUILDTYPE=Release
python: 3.5
- dist: trusty
env: BUILDTYPE=Debug
env: BUILDTYPE=Release
python: 2.7
- dist: trusty
env: BUILDTYPE=Release
python: 3.4
notifications:
email:
......@@ -43,7 +56,15 @@ before_install: ./.travis/run before_install
install: pip install coveralls numpy
script:
- export CMAKE_ADDITIONAL_OPTIONS="-DCMAKE_BUILD_TYPE=${BUILDTYPE}"
- sudo free -m -t
- ./.travis/run ../travis_custom/custom_build
- cd $TRAVIS_BUILD_DIR/unittest/cmake
- mkdir build
- cd build
- export CMAKE_PREFIX_PATH=/tmp/_ci/install
- cmake ..
- make
- ./extra_lib
- cd /tmp/_ci/build
- make uninstall
after_failure: ./.travis/run after_failure
after_success: ./.travis/run after_success
#
# Copyright (c) 2014-2019 CNRS
# Copyright (c) 2018-2019 INRIA
# Copyright (c) 2018-2020 INRIA
#
CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
SET(PROJECT_NAME eigenpy)
SET(PROJECT_DESCRIPTION "Bindings between Numpy and Eigen using Boost.Python")
SET(PROJECT_URL "http://github.com/stack-of-tasks/eigenpy")
SET(PROJECT_USE_CMAKE_EXPORT TRUE)
SET(PROJECT_USE_KEYWORD_LINK_LIBRARIES TRUE)
SET(PROJECT_CUSTOM_HEADER_EXTENSION "hpp")
# Check if the submodule cmake have been initialized
IF(NOT EXISTS "${PROJECT_SOURCE_DIR}/cmake/base.cmake")
IF(NOT EXISTS "${CMAKE_SOURCE_DIR}/cmake/base.cmake")
MESSAGE(FATAL_ERROR "\nPlease run the following command first:\ngit submodule update --init\n")
ENDIF()
# Disable -Werror on Unix for now.
SET(CXX_DISABLE_WERROR True)
SET(CMAKE_VERBOSE_MAKEFILE True)
INCLUDE(cmake/base.cmake)
COMPUTE_PROJECT_ARGS(PROJECT_ARGS LANGUAGES CXX)
PROJECT(${PROJECT_NAME} ${PROJECT_ARGS})
INCLUDE(cmake/boost.cmake)
INCLUDE(cmake/python.cmake)
INCLUDE(cmake/ide.cmake)
INCLUDE(cmake/apple.cmake)
SET(PROJECT_NAME eigenpy)
SET(PROJECT_DESCRIPTION "Bindings between Numpy and Eigen using Boost.Python")
SET(PROJECT_URL "http://github.com/stack-of-tasks/eigenpy")
# Disable -Werror on Unix for now.
SET(CXX_DISABLE_WERROR True)
SET(CMAKE_VERBOSE_MAKEFILE True)
SETUP_PROJECT()
STRING(REPLACE "-pedantic" "" CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS})
IF(APPLE)
SET(CMAKE_MACOSX_RPATH TRUE)
SET(CMAKE_SKIP_BUILD_RPATH FALSE)
SET(CMAKE_BUILD_WITH_INSTALL_RPATH FALSE)
SET(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
#SET(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib")
LIST(FIND CMAKE_PLATFORM_IMPLICIT_LINK_DIRECTORIES "${CMAKE_INSTALL_PREFIX}/lib" isSystemDir)
IF("${isSystemDir}" STREQUAL "-1")
SET(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib")
ENDIF("${isSystemDir}" STREQUAL "-1")
ENDIF(APPLE)
# If needed, fix CMake policy for APPLE systems
APPLY_DEFAULT_APPLE_CONFIGURATION()
IF(WIN32)
SET(LINK copy_if_different)
......@@ -49,33 +45,37 @@ ENDIF(WIN32)
# --- OPTIONS ---------------------------------------
# ----------------------------------------------------
OPTION(INSTALL_DOCUMENTATION "Generate and install the documentation" FALSE)
OPTION(BUILD_UNIT_TESTS "Build the unitary tests" OFF)
IF(BUILD_UNIT_TESTS)
SET(BUILD_TESTING ON)
ELSE(BUILD_UNIT_TESTS)
SET(BUILD_TESTING OFF)
ENDIF(BUILD_UNIT_TESTS)
IF(DEFINED BUILD_UNIT_TESTS)
MESSAGE(AUTHOR_WARNING "BUILD_UNIT_TESTS is deprecated. Use BUILD_TESTING instead.\
If you are manually building Pinocchio from source in an existing build folder,\
we suggest that you delete your build folder and make a new one.")
SET(BUILD_TESTING ${BUILD_UNIT_TESTS})
ENDIF(DEFINED BUILD_UNIT_TESTS)
FINDPYTHON()
INCLUDE_DIRECTORIES(SYSTEM ${PYTHON_INCLUDE_DIRS})
FIND_NUMPY()
INCLUDE_DIRECTORIES(SYSTEM ${NUMPY_INCLUDE_DIRS})
IF(WIN32)
LINK_DIRECTORIES(${PYTHON_LIBRARY_DIRS})
ENDIF(WIN32)
# ----------------------------------------------------
# --- DEPENDANCIES -----------------------------------
# --- DEPENDENCIES -----------------------------------
# ----------------------------------------------------
ADD_REQUIRED_DEPENDENCY("eigen3 >= 3.0.5")
SET(BOOST_COMPONENTS python)
SEARCH_FOR_BOOST()
# Add Boost path to include directories.
INCLUDE_DIRECTORIES(SYSTEM ${Boost_INCLUDE_DIRS})
# ----------------------------------------------------
# --- INCLUDE ----------------------------------------
# ----------------------------------------------------
SET(${PROJECT_NAME}_UTILS_HEADERS
include/eigenpy/utils/scalar-name.hpp
include/eigenpy/utils/is-approx.hpp
)
SET(${PROJECT_NAME}_SOLVERS_HEADERS
include/eigenpy/solvers/solvers.hpp
include/eigenpy/solvers/preconditioners.hpp
......@@ -87,8 +87,19 @@ SET(${PROJECT_NAME}_SOLVERS_HEADERS
include/eigenpy/solvers/BFGSPreconditioners.hpp
)
SET(${PROJECT_NAME}_DECOMPOSITIONS_HEADERS
include/eigenpy/decompositions/decompositions.hpp
include/eigenpy/decompositions/EigenSolver.hpp
include/eigenpy/decompositions/LDLT.hpp
include/eigenpy/decompositions/LLT.hpp
include/eigenpy/decompositions/SelfAdjointEigenSolver.hpp
)
SET(${PROJECT_NAME}_HEADERS
${${PROJECT_NAME}_UTILS_HEADERS}
${${PROJECT_NAME}_SOLVERS_HEADERS}
${${PROJECT_NAME}_DECOMPOSITIONS_HEADERS}
include/eigenpy/computation-info.hpp
include/eigenpy/eigenpy.hpp
include/eigenpy/exception.hpp
include/eigenpy/expose.hpp
......@@ -98,18 +109,20 @@ SET(${PROJECT_NAME}_HEADERS
include/eigenpy/geometry.hpp
include/eigenpy/geometry-conversion.hpp
include/eigenpy/memory.hpp
include/eigenpy/numpy-type.hpp
include/eigenpy/registration.hpp
include/eigenpy/angle-axis.hpp
include/eigenpy/quaternion.hpp
include/eigenpy/stride.hpp
include/eigenpy/ref.hpp
include/eigenpy/details/rvalue_from_python_data.hpp
include/eigenpy/version.hpp
)
INCLUDE_DIRECTORIES(${${PROJECT_NAME}_BINARY_DIR}/include)
INCLUDE_DIRECTORIES(${${PROJECT_NAME}_SOURCE_DIR}/include)
LINK_DIRECTORIES(${PYTHON_LIBRARY_DIRS})
LIST(APPEND ${PROJECT_NAME}_HEADERS
${${PROJECT_NAME}_BINARY_DIR}/include/${PROJECT_NAME}/config.hpp
${${PROJECT_NAME}_BINARY_DIR}/include/${PROJECT_NAME}/deprecated.hpp
${${PROJECT_NAME}_BINARY_DIR}/include/${PROJECT_NAME}/warning.hpp)
# ----------------------------------------------------
# --- TARGETS ----------------------------------------
......@@ -119,35 +132,63 @@ SET(${PROJECT_NAME}_SOLVERS_SOURCES
src/solvers/solvers.cpp
)
SET(${PROJECT_NAME}_DECOMPOSITIONS_SOURCES
src/decompositions/decompositions.cpp
)
SET(${PROJECT_NAME}_SOURCES
${${PROJECT_NAME}_SOLVERS_SOURCES}
${${PROJECT_NAME}_DECOMPOSITIONS_SOURCES}
src/exception.cpp
src/eigenpy.cpp
src/matrix-float.cpp
src/matrix-complex-float.cpp
src/matrix-complex-double.cpp
src/matrix-double.cpp
src/matrix-long-double.cpp
src/matrix-complex-long-double.cpp
src/matrix-int.cpp
src/matrix-long.cpp
src/angle-axis.cpp
src/quaternion.cpp
src/geometry-conversion.cpp
src/version.cpp
)
ADD_LIBRARY(${PROJECT_NAME} SHARED ${${PROJECT_NAME}_SOURCES} ${${PROJECT_NAME}_HEADERS})
SET_TARGET_PROPERTIES(${PROJECT_NAME} PROPERTIES OUTPUT_NAME "${PROJECT_NAME}${PYTHON_SOABI}")
TARGET_INCLUDE_DIRECTORIES(${PROJECT_NAME}
SYSTEM PUBLIC
${Boost_INCLUDE_DIRS}
${EIGEN3_INCLUDE_DIRS}
${PYTHON_INCLUDE_DIRS}
${NUMPY_INCLUDE_DIRS}
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>)
IF(NOT WIN32)
TARGET_COMPILE_OPTIONS(${PROJECT_NAME} PRIVATE $<$<CXX_COMPILER_ID:MSVC>:-bigobj> "-Wno-conversion")
ELSE()
TARGET_COMPILE_OPTIONS(${PROJECT_NAME} PRIVATE $<$<CXX_COMPILER_ID:MSVC>:-bigobj>)
ENDIF()
TARGET_LINK_BOOST_PYTHON(${PROJECT_NAME})
TARGET_LINK_BOOST_PYTHON(${PROJECT_NAME} PUBLIC)
PKG_CONFIG_USE_DEPENDENCY(${PROJECT_NAME} eigen3)
INSTALL(TARGETS ${PROJECT_NAME}
LIBRARY DESTINATION ${CMAKE_INSTALL_PREFIX}/lib
ARCHIVE DESTINATION ${CMAKE_INSTALL_PREFIX}/lib
RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX}/bin)
EXPORT ${TARGETS_EXPORT_NAME}
PUBLIC_HEADER
INCLUDES DESTINATION ${CMAKE_INSTALL_FULL_INCLUDEDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_FULL_LIBDIR}
ARCHIVE DESTINATION ${CMAKE_INSTALL_FULL_LIBDIR}
RUNTIME DESTINATION ${CMAKE_INSTALL_FULL_BINDIR})
ADD_HEADER_GROUP(${PROJECT_NAME}_HEADERS)
ADD_SOURCE_GROUP(${PROJECT_NAME}_SOURCES)
INCLUDE(GenerateExportHeader)
GENERATE_EXPORT_HEADER(${PROJECT_NAME} EXPORT_FILE_NAME eigenpy/${PROJECT_NAME}_export.h)
TARGET_INCLUDE_DIRECTORIES(${PROJECT_NAME} INTERFACE "$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}>")
SET(PUBLIC_HEADER ${${PROJECT_NAME}_HEADERS})
# Install package for ROS
install(FILES package.xml DESTINATION share/eigenpy)
INSTALL(FILES
${CMAKE_CURRENT_BINARY_DIR}/eigenpy/${PROJECT_NAME}_export.h
DESTINATION include/eigenpy)
# ----------------------------------------------------
# --- PYTHON LIBRARY ---------------------------------
# ----------------------------------------------------
......@@ -162,5 +203,3 @@ PKG_CONFIG_APPEND_LIBS(${PROJECT_NAME})
PKG_CONFIG_APPEND_CFLAGS("-I${PYTHON_INCLUDE_DIRS}")
PKG_CONFIG_APPEND_CFLAGS("-I${NUMPY_INCLUDE_DIRS}")
PKG_CONFIG_APPEND_BOOST_LIBS(${BOOST_COMPONENTS})
SETUP_PROJECT_FINALIZE()
EigenPy
EigenPy — Python bindings between Numpy and Eigen
======
[![License](https://img.shields.io/badge/License-BSD%202--Clause-green.svg)](https://opensource.org/licenses/BSD-2-Clause)
[![Build Status](https://travis-ci.org/stack-of-tasks/eigenpy.svg?branch=devel)](https://travis-ci.org/stack-of-tasks/eigenpy)
[![Conda Downloads](https://img.shields.io/conda/dn/conda-forge/eigenpy.svg)](https://anaconda.org/conda-forge/eigenpy)[![Conda Version](https://img.shields.io/conda/vn/conda-forge/eigenpy.svg)](https://anaconda.org/conda-forge/eigenpy)
[![Conda Downloads](https://img.shields.io/conda/dn/conda-forge/eigenpy.svg)](https://anaconda.org/conda-forge/eigenpy)
[![Conda Version](https://img.shields.io/conda/vn/conda-forge/eigenpy.svg)](https://anaconda.org/conda-forge/eigenpy)
[![Anaconda-Server Badge](https://anaconda.org/conda-forge/eigenpy/badges/installer/conda.svg)](https://conda.anaconda.org/conda-forge)
......
Subproject commit f389aae203c4d92649cd5eb66289fd6a17c03fde
Subproject commit 61344038b1352d5a8de1e20db710c83be805d2eb
......@@ -8,7 +8,6 @@
#include "eigenpy/fwd.hpp"
#include <boost/python.hpp>
#include <Eigen/Core>
#include <Eigen/Geometry>
......@@ -19,18 +18,24 @@ namespace eigenpy
template<typename AngleAxis> class AngleAxisVisitor;
namespace internal
template<typename Scalar>
struct call< Eigen::AngleAxis<Scalar> >
{
template<typename Scalar>
struct call_expose< Eigen::AngleAxis<Scalar> >
typedef Eigen::AngleAxis<Scalar> AngleAxis;
static inline void expose()
{
typedef Eigen::AngleAxis<Scalar> type;
static inline void run()
{
AngleAxisVisitor<type>::expose();
}
};
} // namespace internal
AngleAxisVisitor<AngleAxis>::expose();
}
static inline bool isApprox(const AngleAxis & self, const AngleAxis & other,
const Scalar & prec = Eigen::NumTraits<Scalar>::dummy_precision())
{
return self.isApprox(other,prec);
}
};
BOOST_PYTHON_FUNCTION_OVERLOADS(isApproxAngleAxis_overload,call<Eigen::AngleAxisd>::isApprox,2,3)
template<typename AngleAxis>
class AngleAxisVisitor
......@@ -42,6 +47,7 @@ namespace eigenpy
typedef typename AngleAxis::Matrix3 Matrix3;
typedef typename Eigen::Quaternion<Scalar,0> Quaternion;
typedef Eigen::RotationBase<AngleAxis,3> RotationBase;
public:
......@@ -49,15 +55,15 @@ namespace eigenpy
void visit(PyClass& cl) const
{
cl
.def(bp::init<>("Default constructor"))
.def(bp::init<>(bp::arg("self"),"Default constructor"))
.def(bp::init<Scalar,Vector3>
((bp::arg("angle"),bp::arg("axis")),
((bp::arg("self"),bp::arg("angle"),bp::arg("axis")),
"Initialize from angle and axis."))
.def(bp::init<Matrix3>
((bp::arg("rotationMatrix")),
((bp::arg("self"),bp::arg("rotation matrix")),
"Initialize from a rotation matrix"))
.def(bp::init<Quaternion>(bp::arg("quaternion"),"Initialize from a quaternion."))
.def(bp::init<AngleAxis>(bp::arg("copy"),"Copy constructor."))
.def(bp::init<Quaternion>((bp::arg("self"),bp::arg("quaternion")),"Initialize from a quaternion."))
.def(bp::init<AngleAxis>((bp::arg("self"),bp::arg("copy")),"Copy constructor."))
/* --- Properties --- */
.add_property("axis",
......@@ -69,16 +75,25 @@ namespace eigenpy
&AngleAxisVisitor::setAngle,"The rotation angle.")
/* --- Methods --- */
.def("inverse",&AngleAxis::inverse,"Return the inverse rotation.")
.def("inverse",&AngleAxis::inverse,
bp::arg("self"),
"Return the inverse rotation.")
.def("fromRotationMatrix",&AngleAxis::template fromRotationMatrix<Matrix3>,
bp::arg("Sets *this from a 3x3 rotation matrix."),bp::return_self<>())
.def("toRotationMatrix",&AngleAxis::toRotationMatrix,"Constructs and returns an equivalent 3x3 rotation matrix.")
.def("matrix",&AngleAxis::matrix,"Returns an equivalent rotation matrix.")
.def("isApprox",(bool (AngleAxis::*)(const AngleAxis &))&AngleAxis::isApprox,
"Returns true if *this is approximately equal to other.")
.def("isApprox",(bool (AngleAxis::*)(const AngleAxis &, const Scalar prec))&AngleAxis::isApprox,
bp::args("other","prec"),
"Returns true if *this is approximately equal to other, within the precision determined by prec.")
(bp::arg("self"),bp::arg("rotation matrix")),
"Sets *this from a 3x3 rotation matrix",
bp::return_self<>())
.def("toRotationMatrix",
// bp::arg("self"),
&AngleAxis::toRotationMatrix,
"Constructs and returns an equivalent 3x3 rotation matrix.")
.def("matrix",&AngleAxis::matrix,
bp::arg("self"),
"Returns an equivalent rotation matrix.")
.def("isApprox",
&call<AngleAxis>::isApprox,
isApproxAngleAxis_overload(bp::args("self","other","prec"),
"Returns true if *this is approximately equal to other, within the precision determined by prec."))
/* --- Operators --- */
.def(bp::self * bp::other<Vector3>())
......@@ -101,7 +116,8 @@ namespace eigenpy
{ self.angle() = angle; }
static bool __eq__(const AngleAxis & u, const AngleAxis & v)
{ return u.isApprox(v); }
{ return u.axis() == v.axis() && v.angle() == u.angle(); }
static bool __ne__(const AngleAxis & u, const AngleAxis & v)
{ return !__eq__(u,v); }
......@@ -119,9 +135,12 @@ namespace eigenpy
static void expose()
{
bp::class_<AngleAxis>("AngleAxis",
"AngleAxis representation of rotations.\n\n",
"AngleAxis representation of a rotation.\n\n",
bp::no_init)
.def(AngleAxisVisitor<AngleAxis>());
// Cast to Eigen::RotationBase and vice-versa
bp::implicitly_convertible<AngleAxis,RotationBase>();
}
};
......
/*
* Copyright 2020 INRIA
*/
#ifndef __eigenpy_decompositions_computation_info_hpp__
#define __eigenpy_decompositions_computation_info_hpp__
#include <Eigen/Core>
#include <boost/python.hpp>
#include "eigenpy/config.hpp"
namespace eigenpy
{
inline void EIGENPY_DLLEXPORT exposeComputationInfo()
{
boost::python::enum_<Eigen::ComputationInfo>("ComputationInfo")
.value("Success",Eigen::Success)
.value("NumericalIssue",Eigen::NumericalIssue)
.value("NoConvergence",Eigen::NoConvergence)
.value("InvalidInput",Eigen::InvalidInput)
;
}
} // namespace eigenpy
#endif // define __eigenpy_decompositions_computation_info_hpp__
/*
* Copyright 2020 INRIA
*/
#ifndef __eigenpy_decomposition_eigen_solver_hpp__
#define __eigenpy_decomposition_eigen_solver_hpp__
#include <boost/python.hpp>
#include <Eigen/Core>
#include <Eigen/Eigenvalues>
#include "eigenpy/utils/scalar-name.hpp"
namespace eigenpy
{
template<typename _MatrixType>
struct EigenSolverVisitor
: public boost::python::def_visitor< EigenSolverVisitor<_MatrixType> >
{
typedef _MatrixType MatrixType;
typedef typename MatrixType::Scalar Scalar;
typedef Eigen::EigenSolver<MatrixType> Solver;
template<class PyClass>
void visit(PyClass& cl) const
{
namespace bp = boost::python;
cl
.def(bp::init<>("Default constructor"))
.def(bp::init<Eigen::DenseIndex>(bp::arg("size"),
"Default constructor with memory preallocation"))
.def(bp::init<MatrixType,bp::optional<bool> >(bp::args("matrix","compute_eigen_vectors"),
"Computes eigendecomposition of given matrix"))
.def("eigenvalues",&Solver::eigenvalues,bp::arg("self"),
"Returns the eigenvalues of given matrix.",
bp::return_value_policy<bp::return_by_value>())
.def("eigenvectors",&Solver::eigenvectors,bp::arg("self"),
"Returns the eigenvectors of given matrix.",
bp::return_value_policy<bp::return_by_value>())
.def("compute",&EigenSolverVisitor::compute_proxy<MatrixType>,
bp::args("self","matrix"),
"Computes the eigendecomposition of given matrix.",
bp::return_value_policy<bp::reference_existing_object>())
.def("compute",(Solver & (Solver::*)(const Eigen::EigenBase<MatrixType> & matrix, bool))&Solver::compute,
bp::args("self","matrix","compute_eigen_vectors"),
"Computes the eigendecomposition of given matrix.",
bp::return_value_policy<bp::reference_existing_object>())
.def("getMaxIterations",&Solver::getMaxIterations,bp::arg("self"),
"Returns the maximum number of iterations.")
.def("setMaxIterations",&Solver::setMaxIterations,bp::args("self","max_iter"),
"Sets the maximum number of iterations allowed.",
bp::return_value_policy<bp::reference_existing_object>())
.def("pseudoEigenvalueMatrix",&Solver::pseudoEigenvalueMatrix,bp::arg("self"),
"Returns the block-diagonal matrix in the pseudo-eigendecomposition.")
.def("pseudoEigenvectors",&Solver::pseudoEigenvectors ,bp::arg("self"),
"Returns the pseudo-eigenvectors of given matrix.",
bp::return_value_policy<bp::return_by_value>())
.def("info",&Solver::info,bp::arg("self"),
"NumericalIssue if the input contains INF or NaN values or overflow occured. Returns Success otherwise.")
;
}
static void expose()
{
static const std::string classname = "EigenSolver" + scalar_name<Scalar>::shortname();
expose(classname);
}
static void expose(const std::string & name)
{
namespace bp = boost::python;
bp::class_<Solver>(name.c_str(),
bp::no_init)
.def(EigenSolverVisitor());
}
private:
template<typename MatrixType>
static Solver & compute_proxy(Solver & self, const Eigen::EigenBase<MatrixType> & matrix)
{
return self.compute(matrix);
}
};
} // namespace eigenpy
#endif // ifndef __eigenpy_decomposition_eigen_solver_hpp__
/*
* Copyright 2020 INRIA
*/
#ifndef __eigenpy_decomposition_ldlt_hpp__
#define __eigenpy_decomposition_ldlt_hpp__
#include <boost/python.hpp>
#include <Eigen/Core>
#include <Eigen/Cholesky>
#include "eigenpy/utils/scalar-name.hpp"
namespace eigenpy
{
template<typename _MatrixType>
struct LDLTSolverVisitor
: public boost::python::def_visitor< LDLTSolverVisitor<_MatrixType> >
{
typedef _MatrixType MatrixType;
typedef typename MatrixType::Scalar Scalar;
typedef typename MatrixType::RealScalar RealScalar;
typedef Eigen::Matrix<Scalar,Eigen::Dynamic,1,MatrixType::Options> VectorType;
typedef Eigen::LDLT<MatrixType> Solver;
template<class PyClass>
void visit(PyClass& cl) const
{
namespace bp = boost::python;
cl
.def(bp::init<>("Default constructor"))
.def(bp::init<Eigen::DenseIndex>(bp::arg("size"),
"Default constructor with memory preallocation"))
.def(bp::init<MatrixType>(bp::arg("matrix"),
"Constructs a LDLT factorization from a given matrix."))
.def("isNegative",&Solver::isNegative,bp::arg("self"),
"Returns true if the matrix is negative (semidefinite).")
.def("isPositive",&Solver::isPositive,bp::arg("self"),
"Returns true if the matrix is positive (semidefinite).")
.def("matrixL",&matrixL,bp::arg("self"),
"Returns the lower triangular matrix L.")
.def("matrixU",&matrixU,bp::arg("self"),
"Returns the upper triangular matrix U.")
.def("vectorD",&vectorD,bp::arg("self"),
"Returns the coefficients of the diagonal matrix D.")
.def("transpositionsP",&transpositionsP,bp::arg("self"),
"Returns the permutation matrix P.")
.def("matrixLDLT",&Solver::matrixLDLT,bp::arg("self"),
"Returns the LDLT decomposition matrix.",
bp::return_value_policy<bp::return_by_value>())
.def("rankUpdate",(Solver & (Solver::*)(const Eigen::MatrixBase<VectorType> &, const RealScalar &))&Solver::template rankUpdate<VectorType>,
bp::args("self","vector","sigma"),
bp::return_value_policy<bp::reference_existing_object>() )
#if EIGEN_VERSION_AT_LEAST(3,3,0)
.def("adjoint",&Solver::adjoint,bp::arg("self"),
"Returns the adjoint, that is, a reference to the decomposition itself as if the underlying matrix is self-adjoint.",
bp::return_value_policy<bp::reference_existing_object>())
#endif
.def("compute",(Solver & (Solver::*)(const Eigen::EigenBase<MatrixType> & matrix))&Solver::compute,
bp::args("self","matrix"),
"Computes the LDLT of given matrix.",
bp::return_value_policy<bp::reference_existing_object>())
.def("info",&Solver::info,bp::arg("self"),
"NumericalIssue if the input contains INF or NaN values or overflow occured. Returns Success otherwise.")
#if EIGEN_VERSION_AT_LEAST(3,3,0)
.def("rcond",&Solver::rcond,bp::arg("self"),
"Returns an estimate of the reciprocal condition number of the matrix.")
#endif
.def("reconstructedMatrix",&Solver::reconstructedMatrix,bp::arg("self"),
"Returns the matrix represented by the decomposition, i.e., it returns the product: L L^*. This function is provided for debug purpose.")
.def("solve",&solve<VectorType>,bp::args("self","b"),
"Returns the solution x of A x = b using the current decomposition of A.")
.def("setZero",&Solver::setZero,bp::arg("self"),
"Clear any existing decomposition.")
;
}
static void expose()
{
static const std::string classname = "LDLT" + scalar_name<Scalar>::shortname();
expose(classname);
}
static void expose(const std::string & name)
{
namespace bp = boost::python;
bp::class_<Solver>(name.c_str(),
"Robust Cholesky decomposition of a matrix with pivoting.\n\n"
"Perform a robust Cholesky decomposition of a positive semidefinite or negative semidefinite matrix $ A $ such that $ A = P^TLDL^*P $, where P is a permutation matrix, L is lower triangular with a unit diagonal and D is a diagonal matrix.\n\n"
"The decomposition uses pivoting to ensure stability, so that L will have zeros in the bottom right rank(A) - n submatrix. Avoiding the square root on D also stabilizes the computation.",
bp::no_init)
.def(LDLTSolverVisitor());
}
private:
static MatrixType matrixL(const Solver & self) { return self.matrixL(); }
static MatrixType matrixU(const Solver & self) { return self.matrixU(); }
static VectorType vectorD(const Solver & self) { return self.vectorD(); }
static MatrixType transpositionsP(const Solver & self)
{
return self.transpositionsP() * MatrixType::Identity(self.matrixL().rows(),
self.matrixL().rows());
}
template<typename VectorType>
static VectorType solve(const Solver & self, const VectorType & vec)
{
return self.solve(vec);
}
};
} // namespace eigenpy
#endif // ifndef __eigenpy_decomposition_ldlt_hpp__
/*
* Copyright 2020 INRIA
*/
#ifndef __eigenpy_decomposition_llt_hpp__
#define __eigenpy_decomposition_llt_hpp__
#include <boost/python.hpp>
#include <Eigen/Core>
#include <Eigen/Cholesky>
#include "eigenpy/utils/scalar-name.hpp"
namespace eigenpy
{
template<typename _MatrixType>
struct LLTSolverVisitor
: public boost::python::def_visitor< LLTSolverVisitor<_MatrixType> >
{
typedef _MatrixType MatrixType;
typedef typename MatrixType::Scalar Scalar;
typedef typename MatrixType::RealScalar RealScalar;
typedef Eigen::Matrix<Scalar,Eigen::Dynamic,1,MatrixType::Options> VectorType;
typedef Eigen::LLT<MatrixType> Solver;
template<class PyClass>
void visit(PyClass& cl) const
{
namespace bp = boost::python;
cl
.def(bp::init<>("Default constructor"))
.def(bp::init<Eigen::DenseIndex>(bp::arg("size"),
"Default constructor with memory preallocation"))
.def(bp::init<MatrixType>(bp::arg("matrix"),
"Constructs a LLT factorization from a given matrix."))
.def("matrixL",&matrixL,bp::arg("self"),
"Returns the lower triangular matrix L.")
.def("matrixU",&matrixU,bp::arg("self"),
"Returns the upper triangular matrix U.")
.def("matrixLLT",&Solver::matrixLLT,bp::arg("self"),
"Returns the LLT decomposition matrix.",
bp::return_value_policy<bp::return_by_value>())
.def("rankUpdate",(Solver (Solver::*)(const VectorType &, const RealScalar &))&Solver::template rankUpdate<VectorType>,
bp::args("self","vector","sigma"))
#if EIGEN_VERSION_AT_LEAST(3,3,0)
.def("adjoint",&Solver::adjoint,bp::arg("self"),
"Returns the adjoint, that is, a reference to the decomposition itself as if the underlying matrix is self-adjoint.",
bp::return_value_policy<bp::reference_existing_object>())
#endif
.def("compute",(Solver & (Solver::*)(const Eigen::EigenBase<MatrixType> & matrix))&Solver::compute,
bp::args("self","matrix"),
"Computes the LLT of given matrix.",
bp::return_value_policy<bp::reference_existing_object>())
.def("info",&Solver::info,bp::arg("self"),
"NumericalIssue if the input contains INF or NaN values or overflow occured. Returns Success otherwise.")
#if EIGEN_VERSION_AT_LEAST(3,3,0)
.def("rcond",&Solver::rcond,bp::arg("self"),
"Returns an estimate of the reciprocal condition number of the matrix.")
#endif
.def("reconstructedMatrix",&Solver::reconstructedMatrix,bp::arg("self"),
"Returns the matrix represented by the decomposition, i.e., it returns the product: L L^*. This function is provided for debug purpose.")
.def("solve",&solve<VectorType>,bp::args("self","b"),
"Returns the solution x of A x = b using the current decomposition of A.")
;
}
static void expose()
{
static const std::string classname = "LLT" + scalar_name<Scalar>::shortname();
expose(classname);
}
static void expose(const std::string & name)
{
namespace bp = boost::python;
bp::class_<Solver>(name.c_str(),
"Standard Cholesky decomposition (LL^T) of a matrix and associated features.\n\n"
"This class performs a LL^T Cholesky decomposition of a symmetric, positive definite matrix A such that A = LL^* = U^*U, where L is lower triangular.\n\n"
"While the Cholesky decomposition is particularly useful to solve selfadjoint problems like D^*D x = b, for that purpose, we recommend the Cholesky decomposition without square root which is more stable and even faster. Nevertheless, this standard Cholesky decomposition remains useful in many other situations like generalised eigen problems with hermitian matrices.",
bp::no_init)
.def(LLTSolverVisitor());
}
private:
static MatrixType matrixL(const Solver & self) { return self.matrixL(); }
static MatrixType matrixU(const Solver & self) { return self.matrixU(); }
template<typename VectorType>
static VectorType solve(const Solver & self, const VectorType & vec)
{
return self.solve(vec);
}
};
} // namespace eigenpy
#endif // ifndef __eigenpy_decomposition_llt_hpp__
/*
* Copyright 2020 INRIA
*/
#ifndef __eigenpy_decomposition_self_adjoint_eigen_solver_hpp__
#define __eigenpy_decomposition_self_adjoint_eigen_solver_hpp__
#include <boost/python.hpp>
#include <Eigen/Core>
#include <Eigen/Eigenvalues>
#include "eigenpy/utils/scalar-name.hpp"
namespace eigenpy
{
template<typename _MatrixType>
struct SelfAdjointEigenSolverVisitor
: public boost::python::def_visitor< SelfAdjointEigenSolverVisitor<_MatrixType> >
{
typedef _MatrixType MatrixType;
typedef typename MatrixType::Scalar Scalar;
typedef Eigen::SelfAdjointEigenSolver<MatrixType> Solver;
template<class PyClass>
void visit(PyClass& cl) const
{
namespace bp = boost::python;
cl
.def(bp::init<>("Default constructor"))
.def(bp::init<Eigen::DenseIndex>(bp::arg("size"),
"Default constructor with memory preallocation"))
.def(bp::init<MatrixType,bp::optional<int> >(bp::args("matrix","options"),
"Computes eigendecomposition of given matrix"))
.def("eigenvalues",&Solver::eigenvalues,bp::arg("self"),
"Returns the eigenvalues of given matrix.",
bp::return_value_policy<bp::return_by_value>())
.def("eigenvectors",&Solver::eigenvectors,bp::arg("self"),
"Returns the eigenvectors of given matrix.",
bp::return_value_policy<bp::return_by_value>())
.def("compute",&SelfAdjointEigenSolverVisitor::compute_proxy<MatrixType>,
bp::args("self","matrix"),
"Computes the eigendecomposition of given matrix.",
bp::return_value_policy<bp::reference_existing_object>())
.def("compute",(Solver & (Solver::*)(const Eigen::EigenBase<MatrixType> & matrix, int options))&Solver::compute,
bp::args("self","matrix","options"),
"Computes the eigendecomposition of given matrix.",
bp::return_value_policy<bp::reference_existing_object>())
.def("computeDirect",&SelfAdjointEigenSolverVisitor::computeDirect_proxy,
bp::args("self","matrix"),
"Computes eigendecomposition of given matrix using a closed-form algorithm.",
bp::return_value_policy<bp::reference_existing_object>())
.def("computeDirect",(Solver & (Solver::*)(const MatrixType & matrix, int options))&Solver::computeDirect,
bp::args("self","matrix","options"),
"Computes eigendecomposition of given matrix using a closed-form algorithm.",
bp::return_value_policy<bp::reference_existing_object>())
.def("operatorInverseSqrt",&Solver::operatorInverseSqrt,bp::arg("self"),
"Computes the inverse square root of the matrix.",
bp::return_value_policy<bp::return_by_value>())
.def("operatorSqrt",&Solver::operatorSqrt,bp::arg("self"),
"Computes the inverse square root of the matrix.",
bp::return_value_policy<bp::return_by_value>())
.def("info",&Solver::info,bp::arg("self"),
"NumericalIssue if the input contains INF or NaN values or overflow occured. Returns Success otherwise.")
;
}
static void expose()
{
static const std::string classname = "SelfAdjointEigenSolver" + scalar_name<Scalar>::shortname();
expose(classname);
}
static void expose(const std::string & name)
{
namespace bp = boost::python;
bp::class_<Solver>(name.c_str(),
bp::no_init)
.def(SelfAdjointEigenSolverVisitor());
}
private:
template<typename MatrixType>
static Solver & compute_proxy(Solver & self, const Eigen::EigenBase<MatrixType> & matrix)
{
return self.compute(matrix);
}
static Solver & computeDirect_proxy(Solver & self, const MatrixType & matrix)
{
return self.computeDirect(matrix);
}
};
} // namespace eigenpy
#endif // ifndef __eigenpy_decomposition_self_adjoint_eigen_solver_hpp__
/*
* Copyright 2020 INRIA
*/
#ifndef __eigenpy_decompositions_decompositions_hpp__
#define __eigenpy_decompositions_decompositions_hpp__
#include "eigenpy/config.hpp"
namespace eigenpy
{
void EIGENPY_DLLEXPORT exposeDecompositions();
} // namespace eigenpy
#endif // define __eigenpy_decompositions_decompositions_hpp__
This diff is collapsed.
/*
* Copyright 2014-2019, CNRS
* Copyright 2018-2019, INRIA
* Copyright 2018-2020, INRIA
*/
#ifndef __eigenpy_eigenpy_hpp__
#define __eigenpy_eigenpy_hpp__
#include "eigenpy/fwd.hpp"
#include "eigenpy/deprecated.hh"
#include "eigenpy/eigenpy_export.h"
#include "eigenpy/deprecated.hpp"
#include "eigenpy/config.hpp"
#if EIGEN_VERSION_AT_LEAST(3,2,0)
#include "eigenpy/ref.hpp"
......@@ -24,11 +24,38 @@
#endif // if EIGEN_VERSION_AT_LEAST(3,2,0)
#define EIGENPY_MAKE_TYPEDEFS(Type, TypeSuffix, Size, SizeSuffix) \
/** \ingroup matrixtypedefs */ \
typedef Eigen::Matrix<Type, Size, Size> Matrix##SizeSuffix##TypeSuffix; \
/** \ingroup matrixtypedefs */ \
typedef Eigen::Matrix<Type, Size, 1> Vector##SizeSuffix##TypeSuffix; \
/** \ingroup matrixtypedefs */ \
typedef Eigen::Matrix<Type, 1, Size> RowVector##SizeSuffix##TypeSuffix;
#define EIGENPY_MAKE_FIXED_TYPEDEFS(Type, TypeSuffix, Size) \
/** \ingroup matrixtypedefs */ \
typedef Eigen::Matrix<Type, Size, Eigen::Dynamic> Matrix##Size##X##TypeSuffix; \
/** \ingroup matrixtypedefs */ \
typedef Eigen::Matrix<Type, Eigen::Dynamic, Size> Matrix##X##Size##TypeSuffix;
#define EIGENPY_MAKE_TYPEDEFS_ALL_SIZES(Type, TypeSuffix) \
EIGENPY_MAKE_TYPEDEFS(Type, TypeSuffix, 2, 2) \
EIGENPY_MAKE_TYPEDEFS(Type, TypeSuffix, 3, 3) \
EIGENPY_MAKE_TYPEDEFS(Type, TypeSuffix, 4, 4) \
EIGENPY_MAKE_TYPEDEFS(Type, TypeSuffix, Eigen::Dynamic, X) \
EIGENPY_MAKE_FIXED_TYPEDEFS(Type, TypeSuffix, 2) \
EIGENPY_MAKE_FIXED_TYPEDEFS(Type, TypeSuffix, 3) \
EIGENPY_MAKE_FIXED_TYPEDEFS(Type, TypeSuffix, 4)
namespace eigenpy
{
/* Enable Eigen-Numpy serialization for a set of standard MatrixBase instance. */
void EIGENPY_EXPORT enableEigenPy();
void EIGENPY_DLLEXPORT enableEigenPy();
/* Enable the Eigen--Numpy serialization for the templated MatrixBase class.
* The second template argument is used for inheritance of Eigen classes. If
* using a native Eigen::MatrixBase, simply repeat the same arg twice. */
template<typename MatType>
void enableEigenPySpecific();
......@@ -38,10 +65,36 @@ namespace eigenpy
template<typename MatType,typename EigenEquivalentType>
EIGENPY_DEPRECATED void enableEigenPySpecific();
template<typename Scalar>
EIGEN_DONT_INLINE void exposeType()
{
EIGENPY_MAKE_TYPEDEFS_ALL_SIZES(Scalar,s);
ENABLE_SPECIFIC_MATRIX_TYPE(Vector2s);
ENABLE_SPECIFIC_MATRIX_TYPE(RowVector2s);
ENABLE_SPECIFIC_MATRIX_TYPE(Matrix2s);
ENABLE_SPECIFIC_MATRIX_TYPE(Matrix2Xs);
ENABLE_SPECIFIC_MATRIX_TYPE(MatrixX2s);
ENABLE_SPECIFIC_MATRIX_TYPE(Vector3s);
ENABLE_SPECIFIC_MATRIX_TYPE(RowVector3s);
ENABLE_SPECIFIC_MATRIX_TYPE(Matrix3s);
ENABLE_SPECIFIC_MATRIX_TYPE(Matrix3Xs);
ENABLE_SPECIFIC_MATRIX_TYPE(MatrixX3s);
ENABLE_SPECIFIC_MATRIX_TYPE(Vector4s);
ENABLE_SPECIFIC_MATRIX_TYPE(RowVector4s);
ENABLE_SPECIFIC_MATRIX_TYPE(Matrix4s);
ENABLE_SPECIFIC_MATRIX_TYPE(Matrix4Xs);
ENABLE_SPECIFIC_MATRIX_TYPE(MatrixX4s);
ENABLE_SPECIFIC_MATRIX_TYPE(VectorXs);
ENABLE_SPECIFIC_MATRIX_TYPE(RowVectorXs);
ENABLE_SPECIFIC_MATRIX_TYPE(MatrixXs);
}
} // namespace eigenpy
#include "eigenpy/details.hpp"
#endif // ifndef __eigenpy_eigenpy_hpp__
/*
* Copyright 2019, INRIA
* Copyright 2019 INRIA
*/
#ifndef __eigenpy_expose_hpp__
......@@ -9,18 +9,15 @@
namespace eigenpy
{
namespace internal
///
/// \brief Allows a template specialization.
///
template<typename T>
struct call
{
///
/// \brief Allows a template specialization.
///
template<typename T>
struct call_expose
{
static inline void run() { T::expose(); }
};
} // namespace internal
static inline void expose() { T::expose(); }
};
///
/// \brief Call the expose function of a given type T.
///
......@@ -28,7 +25,7 @@ namespace eigenpy
inline void expose()
{
if(!register_symbolic_link_to_registered_type<T>())
internal::call_expose<T>::run();
call<T>::expose();
}
}
......
......@@ -6,6 +6,8 @@
#ifndef __eigenpy_fwd_hpp__
#define __eigenpy_fwd_hpp__
#include "eigenpy/config.hpp"
#include <boost/python.hpp>
#include <Eigen/Core>
......
/*
* Copyright 2014-2019, CNRS
* Copyright 2018-2019, INRIA
* Copyright 2018-2020, INRIA
*/
#ifndef __eigenpy_geometry_hpp__
#define __eigenpy_geometry_hpp__
#include "eigenpy/eigenpy_export.h"
#include "eigenpy/config.hpp"
namespace eigenpy
{
void EIGENPY_EXPORT exposeQuaternion();
void EIGENPY_EXPORT exposeAngleAxis();
void EIGENPY_DLLEXPORT exposeQuaternion();
void EIGENPY_DLLEXPORT exposeAngleAxis();
void EIGENPY_EXPORT exposeGeometryConversion();
void EIGENPY_DLLEXPORT exposeGeometryConversion();
} // namespace eigenpy
......
/*
* Copyright 2014-2019, CNRS
* Copyright 2018-2019, INRIA
* Copyright 2018-2020, INRIA
*/
#ifndef __eigenpy_map_hpp__
#define __eigenpy_map_hpp__
#include "eigenpy/fwd.hpp"
#include <numpy/arrayobject.h>
#include "eigenpy/exception.hpp"
......@@ -10,7 +13,7 @@
namespace eigenpy
{
template<typename MatType, typename InputScalar, int IsVector>
template<typename MatType, typename InputScalar, bool IsVector>
struct MapNumpyTraits {};
/* Wrap a numpy::array with an Eigen::Map. No memory copy. */
......@@ -33,7 +36,7 @@ namespace eigenpy
namespace eigenpy
{
template<typename MatType, typename InputScalar>
struct MapNumpyTraits<MatType,InputScalar,0>
struct MapNumpyTraits<MatType,InputScalar,false>
{
typedef typename StrideType<MatType>::type Stride;
typedef Eigen::Matrix<InputScalar,MatType::RowsAtCompileTime,MatType::ColsAtCompileTime> EquivalentInputMatrixType;
......@@ -41,35 +44,52 @@ namespace eigenpy
static EigenMap mapImpl( PyArrayObject* pyArray )
{
assert( PyArray_NDIM(pyArray) == 2 );
assert( (PyArray_DIMS(pyArray)[0]<INT_MAX)
&& (PyArray_DIMS(pyArray)[1]<INT_MAX)
&& (PyArray_STRIDE(pyArray, 0)<INT_MAX)
&& (PyArray_STRIDE(pyArray, 1)<INT_MAX) );
const int R = (int)PyArray_DIMS(pyArray)[0];
const int C = (int)PyArray_DIMS(pyArray)[1];
assert(PyArray_NDIM(pyArray) == 2 || PyArray_NDIM(pyArray) == 1);
const long int itemsize = PyArray_ITEMSIZE(pyArray);
const int stride1 = (int)PyArray_STRIDE(pyArray, 0) / (int)itemsize;
const int stride2 = (int)PyArray_STRIDE(pyArray, 1) / (int)itemsize;
int stride1 = -1, stride2 = -1;
int rows = -1, cols = -1;
if(PyArray_NDIM(pyArray) == 2)
{
assert( (PyArray_DIMS(pyArray)[0] < INT_MAX)
&& (PyArray_DIMS(pyArray)[1] < INT_MAX)
&& (PyArray_STRIDE(pyArray,0) < INT_MAX)
&& (PyArray_STRIDE(pyArray,1) < INT_MAX) );
rows = (int)PyArray_DIMS(pyArray)[0];
cols = (int)PyArray_DIMS(pyArray)[1];
stride1 = (int)PyArray_STRIDE(pyArray, 0) / (int)itemsize;
stride2 = (int)PyArray_STRIDE(pyArray, 1) / (int)itemsize;
}
else if(PyArray_NDIM(pyArray) == 1)
{
assert( (PyArray_DIMS(pyArray)[0] < INT_MAX)
&& (PyArray_STRIDE(pyArray,0) < INT_MAX));
rows = (int)PyArray_DIMS(pyArray)[0];
cols = 1;
stride1 = (int)PyArray_STRIDE(pyArray, 0) / (int)itemsize;
stride2 = 0;
}
Stride stride(stride2,stride1);
if( (MatType::RowsAtCompileTime!=R)
if( (MatType::RowsAtCompileTime!=rows)
&& (MatType::RowsAtCompileTime!=Eigen::Dynamic) )
{ throw eigenpy::Exception("The number of rows does not fit with the matrix type."); }
if( (MatType::ColsAtCompileTime!=C)
if( (MatType::ColsAtCompileTime!=cols)
&& (MatType::ColsAtCompileTime!=Eigen::Dynamic) )
{ throw eigenpy::Exception("The number of columns does not fit with the matrix type."); }
InputScalar* pyData = reinterpret_cast<InputScalar*>(PyArray_DATA(pyArray));
return EigenMap( pyData, R,C, stride );
return EigenMap( pyData, rows, cols, stride );
}
};
template<typename MatType, typename InputScalar>
struct MapNumpyTraits<MatType,InputScalar,1>
struct MapNumpyTraits<MatType,InputScalar,true>
{
typedef typename StrideType<MatType>::type Stride;
typedef Eigen::Matrix<InputScalar,MatType::RowsAtCompileTime,MatType::ColsAtCompileTime> EquivalentInputMatrixType;
......@@ -102,9 +122,12 @@ namespace eigenpy
};
template<typename MatType, typename InputScalar>
typename MapNumpy<MatType,InputScalar>::EigenMap MapNumpy<MatType,InputScalar>::map( PyArrayObject* pyArray )
typename MapNumpy<MatType,InputScalar>::EigenMap
MapNumpy<MatType,InputScalar>::map(PyArrayObject * pyArray)
{
return Impl::mapImpl(pyArray);
}
} // namespace eigenpy
#endif // define __eigenpy_map_hpp__
/*
* Copyright 2018-2020, INRIA
*/
#ifndef __eigenpy_numpy_type_hpp__
#define __eigenpy_numpy_type_hpp__
#include "eigenpy/fwd.hpp"
#include <iostream>
#include <patchlevel.h> // For PY_MAJOR_VERSION
namespace eigenpy
{
namespace bp = boost::python;
enum NP_TYPE
{
MATRIX_TYPE,
ARRAY_TYPE
};
struct NumpyType
{
static NumpyType & getInstance()
{
static NumpyType instance;
return instance;
}
operator bp::object () { return getInstance().CurrentNumpyType; }
static bp::object make(PyArrayObject* pyArray, bool copy = false)
{ return make((PyObject*)pyArray,copy); }
static bp::object make(PyObject* pyObj, bool copy = false)
{
bp::object m;
if(isMatrix())
m = getInstance().NumpyMatrixObject(bp::object(bp::handle<>(pyObj)), bp::object(), copy);
// m = NumpyAsMatrixObject(bp::object(bp::handle<>(pyObj)));
else if(isArray())
m = bp::object(bp::handle<>(pyObj)); // nothing to do here
Py_INCREF(m.ptr());
return m;
}
static void setNumpyType(bp::object & obj)
{
PyTypeObject * obj_type = PyType_Check(obj.ptr()) ? reinterpret_cast<PyTypeObject*>(obj.ptr()) : obj.ptr()->ob_type;
if(PyType_IsSubtype(obj_type,getInstance().NumpyMatrixType))
switchToNumpyMatrix();
else if(PyType_IsSubtype(obj_type,getInstance().NumpyArrayType))
switchToNumpyArray();
}
static void switchToNumpyArray()
{
getInstance().CurrentNumpyType = getInstance().NumpyArrayObject;
getInstance().getType() = ARRAY_TYPE;
}
static void switchToNumpyMatrix()
{
getInstance().CurrentNumpyType = getInstance().NumpyMatrixObject;
getInstance().getType() = MATRIX_TYPE;
}
static NP_TYPE & getType()
{
return getInstance().np_type;
}
static bp::object getNumpyType()
{
return getInstance().CurrentNumpyType;
}
static const PyTypeObject * getNumpyMatrixType()
{
return getInstance().NumpyMatrixType;
}
static const PyTypeObject * getNumpyArrayType()
{
return getInstance().NumpyArrayType;
}
static bool isMatrix()
{
return PyType_IsSubtype(reinterpret_cast<PyTypeObject*>(getInstance().CurrentNumpyType.ptr()),
getInstance().NumpyMatrixType);
}
static bool isArray()
{
if(getInstance().isMatrix()) return false;
return PyType_IsSubtype(reinterpret_cast<PyTypeObject*>(getInstance().CurrentNumpyType.ptr()),
getInstance().NumpyArrayType);
}
protected:
NumpyType()
{
pyModule = bp::import("numpy");
#if PY_MAJOR_VERSION >= 3
// TODO I don't know why this Py_INCREF is necessary.
// Without it, the destructor of NumpyType SEGV sometimes.
Py_INCREF(pyModule.ptr());
#endif
NumpyMatrixObject = pyModule.attr("matrix");
NumpyMatrixType = reinterpret_cast<PyTypeObject*>(NumpyMatrixObject.ptr());
NumpyArrayObject = pyModule.attr("ndarray");
NumpyArrayType = reinterpret_cast<PyTypeObject*>(NumpyArrayObject.ptr());
//NumpyAsMatrixObject = pyModule.attr("asmatrix");
//NumpyAsMatrixType = reinterpret_cast<PyTypeObject*>(NumpyAsMatrixObject.ptr());
CurrentNumpyType = NumpyArrayObject; // default conversion
np_type = ARRAY_TYPE;
}
bp::object CurrentNumpyType;
bp::object pyModule;