diff --git a/.gitignore b/.gitignore index 491eaf4280c8a721323b763e5d548507ad8cf9d4..8339c71a25aa5d350133714045b58fe709b39702 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,7 @@ bin/ lib/ build/ +build-rel/ # temp files .*~ diff --git a/CMakeLists.txt b/CMakeLists.txt index 571175132aa2995b6cceecfcf5ea6ee9a0ade444..fd0e02cbcfc8f248a5653356332ca5511b9ef226 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,12 +1,41 @@ cmake_minimum_required(VERSION 2.6) project(spline) +INCLUDE(cmake/base.cmake) +INCLUDE(cmake/python.cmake) +SET(PROJECT_NAME spline) +SET(PROJECT_DESCRIPTION + "template based classes for creating and manipulating spline and bezier curves. Comes with extra options specific to end-effector trajectories in robotics." + ) +SET(PROJECT_URL "") set(CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/build/") set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${PROJECT_SOURCE_DIR}/bin/") +set(LIBRARY_OUTPUT_PATH "${PROJECT_SOURCE_DIR}/lib/") +# Disable -Werror on Unix for now. +SET(CXX_DISABLE_WERROR True) +SET(CMAKE_VERBOSE_MAKEFILE True) find_package(Eigen3 REQUIRED) include_directories(${EIGEN3_INCLUDE_DIR}) +SETUP_PROJECT() + +OPTION (BUILD_PYTHON_INTERFACE "Build the python binding" ON) +IF(BUILD_PYTHON_INTERFACE) +# search for python + FINDPYTHON(2.7 REQUIRED) + find_package( PythonLibs 2.7 REQUIRED ) + include_directories( ${PYTHON_INCLUDE_DIRS} ) + + find_package( Boost COMPONENTS python REQUIRED ) + include_directories( ${Boost_INCLUDE_DIR} ) + + add_subdirectory (python) + +ENDIF(BUILD_PYTHON_INTERFACE) + add_subdirectory (src/tests/spline_test) + +SETUP_PROJECT_FINALIZE() diff --git a/python/CMakeLists.txt b/python/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..51dde9504ca3c4e6b35873cc2523784418eefe29 --- /dev/null +++ b/python/CMakeLists.txt @@ -0,0 +1,24 @@ +cmake_minimum_required( VERSION 2.8 ) + +include_directories("${EIGEN3_INCLUDE_DIR}") + +ADD_REQUIRED_DEPENDENCY("eigenpy") + +include_directories("${PROJECT_SOURCE_DIR}/include") +FILE(GLOB_RECURSE HeaderFiles "${PROJECT_SOURCE_DIR}/include/spline/*.h") + +# Define the wrapper library that wraps our library +add_library( spline SHARED spline_python.cpp ) +#~ target_link_libraries( centroidal_dynamics ${Boost_LIBRARIES} ${PROJECT_NAME} ) +# don't prepend wrapper library name with lib +set_target_properties( spline PROPERTIES PREFIX "" ) + +IF(APPLE) + # We need to change the extension for python bindings + SET_TARGET_PROPERTIES(spline PROPERTIES SUFFIX ".so") +ENDIF(APPLE) +PKG_CONFIG_USE_DEPENDENCY(spline eigenpy) + +INSTALL( + FILES ${LIBRARY_OUTPUT_PATH}spline.so DESTINATION ${PYTHON_SITELIB} +) diff --git a/python/spline_python.cpp b/python/spline_python.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7338e8da9ccdae97493f766bbb160379343dee0c --- /dev/null +++ b/python/spline_python.cpp @@ -0,0 +1,119 @@ +#include "spline/bezier_curve.h" + +#include <vector> + +#include <eigenpy/memory.hpp> +#include <eigenpy/eigenpy.hpp> + +#include <boost/python.hpp> + +/*** TEMPLATE SPECIALIZATION FOR PYTHON ****/ +typedef double real; +typedef Eigen::Vector3d point_t; +typedef Eigen::Matrix<real, Eigen::Dynamic,3> point_list_t; +typedef std::vector<point_t,Eigen::aligned_allocator<point_t> > t_point_t; +typedef std::pair<real, point_t> Waypoint; +typedef std::vector<Waypoint> T_Waypoint; + +typedef spline::bezier_curve <real, real, 3, true, point_t> bezier_t; +/*** TEMPLATE SPECIALIZATION FOR PYTHON ****/ + +EIGENPY_DEFINE_STRUCT_ALLOCATOR_SPECIALIZATION(bezier_t) + +namespace spline +{ +using namespace boost::python; + +t_point_t vectorFromEigenArray(const point_list_t& array) +{ + t_point_t res; + for(int i =0;i<array.rows();++i) + res.push_back(array.row(i)); + return res; +} + +bezier_t* wrapBezierConstructor(const point_list_t& array) +{ + t_point_t asVector = vectorFromEigenArray(array); + return new bezier_t(asVector.begin(), asVector.end()); +} + + +bezier_t* wrapBezierConstructorBounds(const point_list_t& array, const real lb, const real ub) +{ + t_point_t asVector = vectorFromEigenArray(array); + return new bezier_t(asVector.begin(), asVector.end(), lb, ub); +} + +BOOST_PYTHON_MODULE(spline) +{ + /** BEGIN eigenpy init**/ + eigenpy::enableEigenPy(); + + eigenpy::enableEigenPySpecific<point_t,point_t>(); + eigenpy::enableEigenPySpecific<point_list_t,point_list_t>(); + /*eigenpy::exposeAngleAxis(); + eigenpy::exposeQuaternion();*/ + + + class_<bezier_t> + ("bezier", no_init) + .def("__init__", make_constructor(&wrapBezierConstructor)) + .def("__init__", make_constructor(&wrapBezierConstructorBounds)) + .def("min", &bezier_t::min) + .def("max", &bezier_t::max) + .def("__call__", &bezier_t::operator()) + ; + + + /** END eigenpy init**/ + + /** BEGIN enum types **/ + /*#ifdef CLP_FOUND + enum_<SolverLP>("SolverLP") + .value("SOLVER_LP_QPOASES", SOLVER_LP_QPOASES) + .value("SOLVER_LP_CLP", SOLVER_LP_CLP) + .export_values(); + #else + enum_<SolverLP>("SolverLP") + .value("SOLVER_LP_QPOASES", SOLVER_LP_QPOASES) + .export_values(); + #endif + + + enum_<EquilibriumAlgorithm>("EquilibriumAlgorithm") + .value("EQUILIBRIUM_ALGORITHM_LP", EQUILIBRIUM_ALGORITHM_LP) + .value("EQUILIBRIUM_ALGORITHM_LP2", EQUILIBRIUM_ALGORITHM_LP2) + .value("EQUILIBRIUM_ALGORITHM_DLP", EQUILIBRIUM_ALGORITHM_DLP) + .value("EQUILIBRIUM_ALGORITHM_PP", EQUILIBRIUM_ALGORITHM_PP) + .value("EQUILIBRIUM_ALGORITHM_IP", EQUILIBRIUM_ALGORITHM_IP) + .value("EQUILIBRIUM_ALGORITHM_DIP", EQUILIBRIUM_ALGORITHM_DIP) + .export_values(); + + enum_<LP_status>("LP_status") + .value("LP_STATUS_UNKNOWN", LP_STATUS_UNKNOWN) + .value("LP_STATUS_OPTIMAL", LP_STATUS_OPTIMAL) + .value("LP_STATUS_INFEASIBLE", LP_STATUS_INFEASIBLE) + .value("LP_STATUS_UNBOUNDED", LP_STATUS_UNBOUNDED) + .value("LP_STATUS_MAX_ITER_REACHED", LP_STATUS_MAX_ITER_REACHED) + .value("LP_STATUS_ERROR", LP_STATUS_ERROR) + .export_values();*/ + + /** END enum types **/ + + /*bool (Equilibrium::*setNewContacts) + (const MatrixX3ColMajor&, const MatrixX3ColMajor&, const double, const EquilibriumAlgorithm) = &Equilibrium::setNewContacts; + + class_<Equilibrium>("Equilibrium", init<std::string, double, unsigned int, optional <SolverLP, bool, const unsigned int, const bool> >()) + .def("useWarmStart", &Equilibrium::useWarmStart) + .def("setUseWarmStart", &Equilibrium::setUseWarmStart) + .def("getName", &Equilibrium::getName) + .def("getAlgorithm", &Equilibrium::getAlgorithm) + .def("setNewContacts", setNewContacts) + .def("computeEquilibriumRobustness", wrapComputeQuasiEquilibriumRobustness) + .def("computeEquilibriumRobustness", wrapComputeEquilibriumRobustness) + .def("getPolytopeInequalities", wrapGetPolytopeInequalities) + ;*/ +} + +} // namespace spline diff --git a/python/test/test.py b/python/test/test.py new file mode 100644 index 0000000000000000000000000000000000000000..38e3766aac38ca1ff81a8e01ff4d97de0b509fa9 --- /dev/null +++ b/python/test/test.py @@ -0,0 +1,6 @@ +from spline import bezier + +from numpy import matrix + +a = bezier(matrix([[1.,2.,3.],[4.,5.,6.]])) +a = bezier(matrix([[1.,2.,3.],[4.,5.,6.]]), -1., 3.)