diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml new file mode 100644 index 0000000000000000000000000000000000000000..9c1e735b5b0ddb52b3eb7bdace59467b2e74c59f --- /dev/null +++ b/.gitlab-ci.yml @@ -0,0 +1,111 @@ +variables: + GIT_SUBMODULE_STRATEGY: "recursive" + GIT_DEPTH: "3" + CCACHE_BASEDIR: "${CI_PROJECT_DIR}" + CCACHE_DIR: "${CI_PROJECT_DIR}/ccache" + +cache: + paths: + - ccache + +.robotpkg-py-eigenpy: &robotpkg-py-eigenpy + except: + - gh-pages + script: + - mkdir -p ccache + - cd /root/robotpkg/math/py-eigenpy + - git pull + - make checkout MASTER_REPOSITORY="dir ${CI_PROJECT_DIR}" + - make install + - cd work.$(hostname)/$(make show-var VARNAME=DISTNAME) + - make check + + +robotpkg-py-eigenpy-dubnium-release: + <<: *robotpkg-py-eigenpy + image: eur0c.laas.fr:5000/stack-of-tasks/eigenpy/py-eigenpy:dubnium + +robotpkg-py-eigenpy-16.04-release: + <<: *robotpkg-py-eigenpy + image: eur0c.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 + +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 + +robotpkg-py-eigenpy-py3-18.04-release: + <<: *robotpkg-py-eigenpy + image: eur0c.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 + +robotpkg-py-eigenpy-14.04-debug: + <<: *robotpkg-py-eigenpy + image: eur0c.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 + +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 + 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 + 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 + 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 + 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 + before_script: + - echo PKG_OPTIONS.py-eigenpy=debug >> /opt/openrobots/etc/robotpkg.conf + + + diff --git a/.travis.yml b/.travis.yml index edc338ad7044d687121fad794b1708b1207b26f3..a3d844b75c2aa449b9f56788607ceb0b5cb81b19 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,4 +1,4 @@ -language: generic +language: python python: - "2.7" sudo: required @@ -9,7 +9,7 @@ compiler: env: global: - secure: "SnIBG/xLIHX3CSvUbqqsX8xTVqIqQ7fFS6HWO6KZQVBsT6yugTwYHbyhNiU531JejYJ/I3ZrDhXfYH3qFZiYxnH1sifvwV+fnTtMXpPN7qPZwIymkjcmm6gJF51e0C7VOfUbvKFv0ngwj+ul21rgZSMuoEvxPK0WxtE3/ZSfn9c=" - - APT_DEPENDENCIES="doxygen libeigen3-dev " + - APT_DEPENDENCIES="doxygen libeigen3-dev libboost-test-dev libboost-python-dev libeigen3-dev" - DEBSIGN_KEYID=5AE5CD75 - CC=gcc - DO_COVERAGE_ON_BRANCH="master;release" @@ -19,24 +19,18 @@ env: - BUILDTYPE=Release - BUILDTYPE=Debug notifications: -email: - - pinocchio@laas.fr + email: + - pinocchio-build@laas.fr branches: -only: - - master - - debian - - devel -matrix: -allow_failures: - - compiler: -before_install: ./travis_custom/custom_before_install -install: - - pip install --user coveralls - - pip install --user numpy + only: + - master + - debian + - devel +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 after_failure: ./.travis/run after_failure -after_success: - - ./.travis/run after_success +after_success: ./.travis/run after_success diff --git a/CMakeLists.txt b/CMakeLists.txt index 89e2f96535652c0dddeae1586216cf51fb7829f8..74a0ecf7d34c43dad7b9ef3d95e3bca5f2e41c68 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -20,6 +20,7 @@ INCLUDE(cmake/base.cmake) INCLUDE(cmake/boost.cmake) INCLUDE(cmake/python.cmake) INCLUDE(cmake/ide.cmake) +INCLUDE(cmake/test.cmake) SET(PROJECT_NAME eigenpy) SET(PROJECT_DESCRIPTION "Wrapping Eigen3 -- numpy") diff --git a/cmake b/cmake index d22de8c53c3507df785b1fb3ab260d9fdfb65233..2c0ecdf0ecf466d68565aa506bcc02326eb72eff 160000 --- a/cmake +++ b/cmake @@ -1 +1 @@ -Subproject commit d22de8c53c3507df785b1fb3ab260d9fdfb65233 +Subproject commit 2c0ecdf0ecf466d68565aa506bcc02326eb72eff diff --git a/travis_custom/custom_before_install b/travis_custom/custom_before_install deleted file mode 100755 index 46e3546485f36a313bad37f4a910b03098dba3c8..0000000000000000000000000000000000000000 --- a/travis_custom/custom_before_install +++ /dev/null @@ -1,8 +0,0 @@ -#!/bin/bash -set -e - -# Setup environment variables. -export APT_DEPENDENCIES="doxygen libboost-test-dev libboost-python-dev libeigen3-dev python2.7-dev python-numpy" - -# When this script is called the current directory is ./custom_travis -. ./.travis/run ../.travis/before_install diff --git a/unittest/CMakeLists.txt b/unittest/CMakeLists.txt index 76a817fd5fe55e856ec54ab765096940f080aa11..f61b4c0dfadc252c131bbdfca7834ab2b710032c 100644 --- a/unittest/CMakeLists.txt +++ b/unittest/CMakeLists.txt @@ -1,6 +1,6 @@ -# +# # Copyright (c) 2016-2018 CNRS -# +# # This file is part of eigenpy # eigenpy is free software: you can redistribute it # and/or modify it under the terms of the GNU Lesser General Public @@ -31,7 +31,7 @@ MACRO(ADD_LIB_UNIT_TEST test PKGS) # We need to change the extension for python bindings SET_TARGET_PROPERTIES(${test} PROPERTIES SUFFIX ".so") ENDIF(APPLE) - + ADD_TEST(NAME ${test} COMMAND ${PYTHON_EXECUTABLE} -c "import ${test}") ADD_DEPENDENCIES(check ${test}) ENDMACRO(ADD_LIB_UNIT_TEST) @@ -44,3 +44,5 @@ IF(NOT ${EIGEN3_VERSION} VERSION_LESS "3.2.0") ADD_LIB_UNIT_TEST(ref "eigen3") ENDIF() +ADD_PYTHON_UNIT_TEST("py-matrix" "unittest/python/test_matrix.py" "unittest") +ADD_PYTHON_UNIT_TEST("py-geometry" "unittest/python/test_geometry.py" "unittest") diff --git a/unittest/python/test_eigenpy.py b/unittest/python/test_eigenpy.py deleted file mode 100644 index aab786f7e518e2b3cc7742751d03a64525a60394..0000000000000000000000000000000000000000 --- a/unittest/python/test_eigenpy.py +++ /dev/null @@ -1,103 +0,0 @@ -import numpy as np -import matrix as eigenpy - -verbose = False - -if verbose: print "===> From MatrixXd to Py" -M = eigenpy.naturals(3,3,verbose) -Mcheck = np.reshape(np.matrix(range(9),np.double),[3,3]) -assert np.array_equal(Mcheck,M) - -if verbose: print "===> From Matrix3d to Py" -M33= eigenpy.naturals33(verbose) -assert np.array_equal(Mcheck,M33) - -if verbose: print "===> From VectorXd to Py" -v = eigenpy.naturalsX(3,verbose) -vcheck = np.matrix([range(3),],np.double).T -assert np.array_equal(vcheck ,v) - -if verbose: print "===> From Py to Eigen::MatrixXd" -if verbose: print "===> From Py to Eigen::MatrixXd" -if verbose: print "===> From Py to Eigen::MatrixXd" -Mref = np.reshape(np.matrix(range(64),np.double),[8,8]) - -if verbose: print "===> Matrix 8x8" -M = Mref -assert( np.array_equal(M,eigenpy.reflex(M,verbose)) ); - -if verbose: print "===> Block 0:3x0:3" -M = Mref[0:3,0:3] -assert( np.array_equal(M,eigenpy.reflex(M,verbose)) ); - -if verbose: print "===> Block 1:3x1:3" -M = Mref[1:3,1:3] -assert( np.array_equal(M,eigenpy.reflex(M,verbose)) ); - -if verbose: print "===> Block 1:5:2x1:5:2" -M = Mref[1:5:2,1:5:2] -assert( np.array_equal(M,eigenpy.reflex(M,verbose)) ); - -if verbose: print "===> Block 1:8:3x1:5" -M = Mref[1:8:3,1:5] -assert( np.array_equal(M,eigenpy.reflex(M,verbose)) ); - -if verbose: print "===> Block transpose 1:8:3x1:6:2" -M = Mref[1:8:3,0:6:2].T -assert( np.array_equal(M,eigenpy.reflex(M,verbose)) ); - -if verbose: print "===> Block Vector 1x0:6:2" -M = Mref[1:2,0:6:2] -assert( np.array_equal(M,eigenpy.reflex(M,verbose)) ); - -if verbose: print "===> Block Vector 1x0:6:2 tanspose" -M = Mref[1:2,0:6:2].T -assert( np.array_equal(M,eigenpy.reflex(M,verbose)) ); - -if verbose: print "===> Block Vector 0:6:2x1" -M = Mref[0:6:2,1:2] -assert( np.array_equal(M,eigenpy.reflex(M,verbose)) ); - -if verbose: print "===> Block Vector 0:6:2x1 tanspose" -M = Mref[0:6:2,1:2].T -assert( np.array_equal(M,eigenpy.reflex(M,verbose)) ); - -if verbose: print "===> From Py to Eigen::VectorXd" -if verbose: print "===> From Py to Eigen::VectorXd" -if verbose: print "===> From Py to Eigen::VectorXd" - -if verbose: print "===> Block Vector 0:6:2x1 1 dim" -M = Mref[0:6:2,1].T -assert( np.array_equal(M.T,eigenpy.reflexV(M,verbose)) ); - -if verbose: print "===> Block Vector 0:6:2x1" -M = Mref[0:6:2,1:2] -assert( np.array_equal(M,eigenpy.reflexV(M,verbose)) ); - -if verbose: print "===> Block Vector 0:6:2x1 transpose" -M = Mref[0:6:2,1:2].T -assert( np.array_equal(M.T,eigenpy.reflexV(M,verbose)) ); - -if verbose: print "===> From Py to Eigen::Matrix3d" -if verbose: print "===> From Py to Eigen::Matrix3d" -if verbose: print "===> From Py to Eigen::Matrix3d" - -if verbose: print "===> Block Vector 0:3x0:6:2 " -M = Mref[0:3,0:6:2] -assert( np.array_equal(M,eigenpy.reflex33(M,verbose)) ); - -if verbose: print "===> Block Vector 0:3x0:6:2 T" -M = Mref[0:3,0:6].T -try: - assert( np.array_equal(M,eigenpy.reflex33(M,verbose)) ); -except eigenpy.Exception, e: - if verbose: print "As expected, got the following /ROW/ error:", e.message - -if verbose: print "===> From Py to Eigen::Vector3d" -if verbose: print "===> From Py to Eigen::Vector3d" -if verbose: print "===> From Py to Eigen::Vector3d" - -M = Mref[0:3,1:2] -assert( np.array_equal(M,eigenpy.reflex3(M,verbose)) ); - - diff --git a/unittest/python/test_geometry.py b/unittest/python/test_geometry.py index 1f2642a4fbedbb3af023abdef368dcc67804acaa..07d91a33fdd699b786989ba3953f2d9d3fc1fc8f 100644 --- a/unittest/python/test_geometry.py +++ b/unittest/python/test_geometry.py @@ -1,8 +1,10 @@ +from __future__ import print_function + from geometry import * import numpy as np from numpy import cos,sin -verbose = False +verbose = True def isapprox(a,b,epsilon=1e-6): if issubclass(a.__class__,np.ndarray) and issubclass(b.__class__,np.ndarray): @@ -33,18 +35,18 @@ assert(isapprox(q.coeffs(),qR.coeffs())) assert(isapprox(qR[3],1./np.sqrt(30))) try: qR[5] - print "Error, this message should not appear." -except Exception,e: - if verbose: print "As expected, catched exception: ",e.message + print("Error, this message should not appear.") +except RuntimeError as e: + if verbose: print("As expected, catched exception: ",e) # --- Angle Vector ------------------------------------------------ -r = AngleAxis(.1,np.array([1,0,0],np.double)) -if verbose: print "Rx(.1) = \n\n",r.matrix(),"\n" +r = AngleAxis(.1,np.matrix([1,0,0],np.double).T) +if verbose: print("Rx(.1) = \n\n",r.matrix(),"\n") assert( isapprox(r.matrix()[2,2],cos(r.angle))) assert( isapprox(r.axis,np.matrix("1;0;0")) ) assert( isapprox(r.angle,0.1) ) -r.axis = np.array([0,1,0],np.double) +r.axis = np.matrix([0,1,0],np.double).T assert( isapprox(r.matrix()[0,0],cos(r.angle))) ri = r.inverse() @@ -62,10 +64,5 @@ assert( res==r.angle ) qo = testOutQuaternion() assert(qo.__class__ == Quaternion) -res = testInQuaternion_fx(q) +res = testInQuaternion(q) assert(q.norm() == res) -try: - testInQuaternion(q) - print "Error, this message should not appear." -except: - if verbose: print "As expected, catch a Boost::python::ArgError exception." diff --git a/unittest/python/test_matrix.py b/unittest/python/test_matrix.py new file mode 100644 index 0000000000000000000000000000000000000000..ad5490c0663ae306d2105653e1df189c5886b361 --- /dev/null +++ b/unittest/python/test_matrix.py @@ -0,0 +1,107 @@ +from __future__ import print_function + +import numpy as np +import matrix as eigenpy + +verbose = True + +if verbose: print("===> From MatrixXd to Py") +M = eigenpy.naturals(3,3,verbose) +Mcheck = np.reshape(np.matrix(range(9),np.double),[3,3]) +assert np.array_equal(Mcheck,M) + +if verbose: print("===> From Matrix3d to Py") +M33= eigenpy.naturals33(verbose) +assert np.array_equal(Mcheck,M33) + +if verbose: print("===> From VectorXd to Py") +v = eigenpy.naturalsX(3,verbose) +vcheck = np.matrix([range(3),],np.double).T +assert np.array_equal(vcheck ,v) + +if verbose: print("===> From Py to Eigen::MatrixXd") +if verbose: print("===> From Py to Eigen::MatrixXd") +if verbose: print("===> From Py to Eigen::MatrixXd") +Mref = np.reshape(np.matrix(range(64),np.double),[8,8]) + +if verbose: print("===> Matrix 8x8") +M = Mref +assert( np.array_equal(M,eigenpy.reflex(M,verbose)) ); + +if verbose: print("===> Block 0:3x0:3") +M = Mref[0:3,0:3] +assert( np.array_equal(M,eigenpy.reflex(M,verbose)) ); + +if verbose: print("===> Block 1:3x1:3") +M = Mref[1:3,1:3] +assert( np.array_equal(M,eigenpy.reflex(M,verbose)) ); + +if verbose: print("===> Block 1:5:2x1:5:2") +M = Mref[1:5:2,1:5:2] +assert( np.array_equal(M,eigenpy.reflex(M,verbose)) ); + +if verbose: print("===> Block 1:8:3x1:5") +M = Mref[1:8:3,1:5] +assert( np.array_equal(M,eigenpy.reflex(M,verbose)) ); + +if verbose: print("===> Block transpose 1:8:3x1:6:2") +M = Mref[1:8:3,0:6:2].T +assert( np.array_equal(M,eigenpy.reflex(M,verbose)) ); + +if verbose: print("===> Block Vector 1x0:6:2") +M = Mref[1:2,0:6:2] +assert( np.array_equal(M,eigenpy.reflex(M,verbose)) ); + +if verbose: print("===> Block Vector 1x0:6:2 tanspose") +M = Mref[1:2,0:6:2].T +assert( np.array_equal(M,eigenpy.reflex(M,verbose)) ); + +if verbose: print("===> Block Vector 0:6:2x1") +M = Mref[0:6:2,1:2] +assert( np.array_equal(M,eigenpy.reflex(M,verbose)) ); + +if verbose: print("===> Block Vector 0:6:2x1 tanspose") +M = Mref[0:6:2,1:2].T +assert( np.array_equal(M,eigenpy.reflex(M,verbose)) ); + +if verbose: print("===> From Py to Eigen::VectorXd") +if verbose: print("===> From Py to Eigen::VectorXd") +if verbose: print("===> From Py to Eigen::VectorXd") + +if verbose: print("===> Block Vector 0:6:2x1 1 dim") +M = Mref[0:6:2,1].T +# TODO +# assert( np.array_equal(M.T,eigenpy.reflexV(M,verbose)) ); + +if verbose: print("===> Block Vector 0:6:2x1") +M = Mref[0:6:2,1:2] +assert( np.array_equal(M,eigenpy.reflexV(M,verbose)) ); + +if verbose: print("===> Block Vector 0:6:2x1 transpose") +M = Mref[0:6:2,1:2].T +# TODO +# assert( np.array_equal(M.T,eigenpy.reflexV(M,verbose)) ); + +if verbose: print("===> From Py to Eigen::Matrix3d") +if verbose: print("===> From Py to Eigen::Matrix3d") +if verbose: print("===> From Py to Eigen::Matrix3d") + +if verbose: print("===> Block Vector 0:3x0:6:2 ") +M = Mref[0:3,0:6:2] +assert( np.array_equal(M,eigenpy.reflex33(M,verbose)) ); + +if verbose: print("===> Block Vector 0:3x0:6:2 T") +M = Mref[0:3,0:6].T +# TODO +# try: + # assert( np.array_equal(M,eigenpy.reflex33(M,verbose)) ); +# except eigenpy.Exception as e: + # if verbose: print("As expected, got the following /ROW/ error:", e.message) + +if verbose: print("===> From Py to Eigen::Vector3d") +if verbose: print("===> From Py to Eigen::Vector3d") +if verbose: print("===> From Py to Eigen::Vector3d") + +# TODO +# M = Mref[0:3,1:2] +# assert( np.array_equal(M,eigenpy.reflex3(M,verbose)) );