Merge pull request #477 from borglab/temp/copy_python
Mega change: New Wrapper (Python & MATLAB)release/4.3a0
commit
ac35670728
|
@ -47,8 +47,6 @@ case $WRAPPER in
|
|||
;;
|
||||
esac
|
||||
|
||||
git submodule update --init --recursive
|
||||
|
||||
mkdir $GITHUB_WORKSPACE/build
|
||||
cd $GITHUB_WORKSPACE/build
|
||||
|
||||
|
@ -82,9 +80,9 @@ case $WRAPPER in
|
|||
$PYTHON -m unittest discover
|
||||
;;
|
||||
"pybind")
|
||||
cd $GITHUB_WORKSPACE/python
|
||||
cd $GITHUB_WORKSPACE/build/python
|
||||
$PYTHON setup.py install --user --prefix=
|
||||
cd $GITHUB_WORKSPACE/wrap/python/gtsam_py/tests
|
||||
cd $GITHUB_WORKSPACE/python/gtsam/tests
|
||||
$PYTHON -m unittest discover
|
||||
;;
|
||||
*)
|
||||
|
|
|
@ -47,7 +47,6 @@ function configure()
|
|||
BUILD_DIR=$GITHUB_WORKSPACE/build
|
||||
|
||||
#env
|
||||
git submodule update --init --recursive
|
||||
rm -fr $BUILD_DIR || true
|
||||
mkdir $BUILD_DIR && cd $BUILD_DIR
|
||||
|
||||
|
|
|
@ -27,7 +27,7 @@ jobs:
|
|||
|
||||
build_type: [Debug, Release]
|
||||
python_version: [3]
|
||||
wrapper: [cython]
|
||||
wrapper: [pybind]
|
||||
include:
|
||||
- name: ubuntu-18.04-gcc-5
|
||||
os: ubuntu-18.04
|
||||
|
|
268
CMakeLists.txt
268
CMakeLists.txt
|
@ -65,16 +65,19 @@ add_custom_target(uninstall
|
|||
# Configurable Options
|
||||
if(GTSAM_UNSTABLE_AVAILABLE)
|
||||
option(GTSAM_BUILD_UNSTABLE "Enable/Disable libgtsam_unstable" ON)
|
||||
option(GTSAM_UNSTABLE_BUILD_PYTHON "Enable/Disable Python wrapper for libgtsam_unstable" ON)
|
||||
option(GTSAM_UNSTABLE_INSTALL_MATLAB_TOOLBOX "Enable/Disable MATLAB wrapper for libgtsam_unstable" OFF)
|
||||
endif()
|
||||
option(BUILD_SHARED_LIBS "Build shared gtsam library, instead of static" ON)
|
||||
option(GTSAM_USE_QUATERNIONS "Enable/Disable using an internal Quaternion representation for rotations instead of rotation matrices. If enable, Rot3::EXPMAP is enforced by default." OFF)
|
||||
option(GTSAM_POSE3_EXPMAP "Enable/Disable using Pose3::EXPMAP as the default mode. If disabled, Pose3::FIRST_ORDER will be used." ON)
|
||||
option(GTSAM_ROT3_EXPMAP "Ignore if GTSAM_USE_QUATERNIONS is OFF (Rot3::EXPMAP by default). Otherwise, enable Rot3::EXPMAP, or if disabled, use Rot3::CAYLEY." ON)
|
||||
option(GTSAM_POSE3_EXPMAP "Enable/Disable using Pose3::EXPMAP as the default mode. If disabled, Pose3::FIRST_ORDER will be used." ON)
|
||||
option(GTSAM_ROT3_EXPMAP "Ignore if GTSAM_USE_QUATERNIONS is OFF (Rot3::EXPMAP by default). Otherwise, enable Rot3::EXPMAP, or if disabled, use Rot3::CAYLEY." ON)
|
||||
option(GTSAM_ENABLE_CONSISTENCY_CHECKS "Enable/Disable expensive consistency checks" OFF)
|
||||
option(GTSAM_WITH_TBB "Use Intel Threaded Building Blocks (TBB) if available" ON)
|
||||
option(GTSAM_WITH_EIGEN_MKL "Eigen will use Intel MKL if available" OFF)
|
||||
option(GTSAM_WITH_EIGEN_MKL_OPENMP "Eigen, when using Intel MKL, will also use OpenMP for multithreading if available" OFF)
|
||||
option(GTSAM_THROW_CHEIRALITY_EXCEPTION "Throw exception when a triangulated point is behind a camera" ON)
|
||||
option(GTSAM_BUILD_PYTHON "Enable/Disable building & installation of Python module with pybind11" OFF)
|
||||
option(GTSAM_ALLOW_DEPRECATED_SINCE_V41 "Allow use of methods/functions deprecated in GTSAM 4.1" ON)
|
||||
option(GTSAM_TYPEDEF_POINTS_TO_VECTORS "Typedef Point2 and Point3 to Eigen::Vector equivalents" OFF)
|
||||
option(GTSAM_SUPPORT_NESTED_DISSECTION "Support Metis-based nested dissection" ON)
|
||||
|
@ -99,37 +102,44 @@ endif()
|
|||
# Options relating to MATLAB wrapper
|
||||
# TODO: Check for matlab mex binary before handling building of binaries
|
||||
option(GTSAM_INSTALL_MATLAB_TOOLBOX "Enable/Disable installation of matlab toolbox" OFF)
|
||||
option(GTSAM_INSTALL_CYTHON_TOOLBOX "Enable/Disable installation of Cython toolbox" OFF)
|
||||
option(GTSAM_BUILD_WRAP "Enable/Disable building of matlab/cython wrap utility (necessary for matlab/cython interface)" ON)
|
||||
set(GTSAM_PYTHON_VERSION "Default" CACHE STRING "The version of python to build the cython wrapper for (or Default)")
|
||||
set(GTSAM_PYTHON_VERSION "Default" CACHE STRING "The version of Python to build the wrappers against.")
|
||||
|
||||
# Check / set dependent variables for MATLAB wrapper
|
||||
if((GTSAM_INSTALL_MATLAB_TOOLBOX OR GTSAM_INSTALL_CYTHON_TOOLBOX) AND NOT GTSAM_BUILD_WRAP)
|
||||
message(FATAL_ERROR "GTSAM_INSTALL_MATLAB_TOOLBOX or GTSAM_INSTALL_CYTHON_TOOLBOX is enabled, please also enable GTSAM_BUILD_WRAP")
|
||||
endif()
|
||||
if((GTSAM_INSTALL_MATLAB_TOOLBOX OR GTSAM_INSTALL_CYTHON_TOOLBOX) AND GTSAM_BUILD_TYPE_POSTFIXES)
|
||||
set(CURRENT_POSTFIX ${CMAKE_${CMAKE_BUILD_TYPE_UPPER}_POSTFIX})
|
||||
endif()
|
||||
if(GTSAM_INSTALL_WRAP AND NOT GTSAM_BUILD_WRAP)
|
||||
message(FATAL_ERROR "GTSAM_INSTALL_WRAP is enabled, please also enable GTSAM_BUILD_WRAP")
|
||||
if(GTSAM_INSTALL_MATLAB_TOOLBOX AND GTSAM_BUILD_TYPE_POSTFIXES)
|
||||
set(CURRENT_POSTFIX ${CMAKE_${CMAKE_BUILD_TYPE_UPPER}_POSTFIX})
|
||||
endif()
|
||||
|
||||
if(GTSAM_INSTALL_MATLAB_TOOLBOX AND NOT BUILD_SHARED_LIBS)
|
||||
message(FATAL_ERROR "GTSAM_INSTALL_MATLAB_TOOLBOX and BUILD_SHARED_LIBS=OFF. The MATLAB wrapper cannot be compiled with a static GTSAM library because mex modules are themselves shared libraries. If you want a self-contained mex module, enable GTSAM_MEX_BUILD_STATIC_MODULE instead of BUILD_SHARED_LIBS=OFF.")
|
||||
message(FATAL_ERROR "GTSAM_INSTALL_MATLAB_TOOLBOX and BUILD_SHARED_LIBS=OFF. The MATLAB wrapper cannot be compiled with a static GTSAM library because mex modules are themselves shared libraries. If you want a self-contained mex module, enable GTSAM_MEX_BUILD_STATIC_MODULE instead of BUILD_SHARED_LIBS=OFF.")
|
||||
endif()
|
||||
|
||||
if(GTSAM_INSTALL_MATLAB_TOOLBOX AND GTSAM_TYPEDEF_POINTS_TO_VECTORS)
|
||||
message(FATAL_ERROR "GTSAM_INSTALL_MATLAB_TOOLBOX and GTSAM_TYPEDEF_POINTS_TO_VECTORS are both enabled. For now, the MATLAB toolbox cannot deal with this yet. Please turn one of the two options off.")
|
||||
endif()
|
||||
if(GTSAM_BUILD_PYTHON)
|
||||
if (NOT GTSAM_TYPEDEF_POINTS_TO_VECTORS)
|
||||
message(FATAL_ERROR "GTSAM_BUILD_PYTHON requires GTSAM_TYPEDEF_POINTS_TO_VECTORS to be enabled but it is not.")
|
||||
endif()
|
||||
|
||||
if(GTSAM_INSTALL_CYTHON_TOOLBOX AND GTSAM_TYPEDEF_POINTS_TO_VECTORS)
|
||||
message(FATAL_ERROR "GTSAM_INSTALL_CYTHON_TOOLBOX and GTSAM_TYPEDEF_POINTS_TO_VECTORS are both enabled. For now, the CYTHON toolbox cannot deal with this yet. Please turn one of the two options off.")
|
||||
if(GTSAM_UNSTABLE_BUILD_PYTHON)
|
||||
if (NOT GTSAM_BUILD_UNSTABLE)
|
||||
message(WARNING "GTSAM_UNSTABLE_BUILD_PYTHON requires the unstable module to be enabled.")
|
||||
set(GTSAM_UNSTABLE_BUILD_PYTHON OFF)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set(GTSAM_PY_INSTALL_PATH "${CMAKE_INSTALL_PREFIX}/python")
|
||||
endif()
|
||||
|
||||
# Flags for choosing default packaging tools
|
||||
set(CPACK_SOURCE_GENERATOR "TGZ" CACHE STRING "CPack Default Source Generator")
|
||||
set(CPACK_GENERATOR "TGZ" CACHE STRING "CPack Default Binary Generator")
|
||||
|
||||
if (CMAKE_GENERATOR STREQUAL "Ninja" AND
|
||||
((CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.9) OR
|
||||
(CMAKE_CXX_COMPILER_ID STREQUAL "Clang" AND NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 3.5)))
|
||||
# Force colored warnings in Ninja's output, if the compiler has -fdiagnostics-color support.
|
||||
# Rationale in https://github.com/ninja-build/ninja/issues/814
|
||||
add_compile_options(-fdiagnostics-color=always)
|
||||
endif()
|
||||
|
||||
###############################################################################
|
||||
# Find boost
|
||||
|
||||
|
@ -138,18 +148,18 @@ set(CPACK_GENERATOR "TGZ" CACHE STRING "CPack Default Binary Generator")
|
|||
# Boost_NO_SYSTEM_PATHS: set to true to keep the find script from ignoring BOOST_ROOT
|
||||
|
||||
if(MSVC)
|
||||
# By default, boost only builds static libraries on windows
|
||||
set(Boost_USE_STATIC_LIBS ON) # only find static libs
|
||||
# If we ever reset above on windows and, ...
|
||||
# If we use Boost shared libs, disable auto linking.
|
||||
# Some libraries, at least Boost Program Options, rely on this to export DLL symbols.
|
||||
if(NOT Boost_USE_STATIC_LIBS)
|
||||
list_append_cache(GTSAM_COMPILE_DEFINITIONS_PUBLIC BOOST_ALL_NO_LIB BOOST_ALL_DYN_LINK)
|
||||
endif()
|
||||
# Virtual memory range for PCH exceeded on VS2015
|
||||
if(MSVC_VERSION LESS 1910) # older than VS2017
|
||||
list_append_cache(GTSAM_COMPILE_OPTIONS_PRIVATE -Zm295)
|
||||
endif()
|
||||
# By default, boost only builds static libraries on windows
|
||||
set(Boost_USE_STATIC_LIBS ON) # only find static libs
|
||||
# If we ever reset above on windows and, ...
|
||||
# If we use Boost shared libs, disable auto linking.
|
||||
# Some libraries, at least Boost Program Options, rely on this to export DLL symbols.
|
||||
if(NOT Boost_USE_STATIC_LIBS)
|
||||
list_append_cache(GTSAM_COMPILE_DEFINITIONS_PUBLIC BOOST_ALL_NO_LIB BOOST_ALL_DYN_LINK)
|
||||
endif()
|
||||
# Virtual memory range for PCH exceeded on VS2015
|
||||
if(MSVC_VERSION LESS 1910) # older than VS2017
|
||||
list_append_cache(GTSAM_COMPILE_OPTIONS_PRIVATE -Zm295)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# If building DLLs in MSVC, we need to avoid EIGEN_STATIC_ASSERT()
|
||||
|
@ -157,7 +167,7 @@ endif()
|
|||
# See: https://bitbucket.org/gtborg/gtsam/issues/417/fail-to-build-on-msvc-2017
|
||||
#
|
||||
if(MSVC AND BUILD_SHARED_LIBS)
|
||||
list_append_cache(GTSAM_COMPILE_DEFINITIONS_PUBLIC EIGEN_NO_STATIC_ASSERT)
|
||||
list_append_cache(GTSAM_COMPILE_DEFINITIONS_PUBLIC EIGEN_NO_STATIC_ASSERT)
|
||||
endif()
|
||||
|
||||
# Store these in variables so they are automatically replicated in GTSAMConfig.cmake and such.
|
||||
|
@ -227,16 +237,16 @@ find_package(GooglePerfTools)
|
|||
###############################################################################
|
||||
# Support ccache, if installed
|
||||
if(NOT MSVC AND NOT XCODE_VERSION)
|
||||
find_program(CCACHE_FOUND ccache)
|
||||
if(CCACHE_FOUND)
|
||||
if(GTSAM_BUILD_WITH_CCACHE)
|
||||
set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE ccache)
|
||||
set_property(GLOBAL PROPERTY RULE_LAUNCH_LINK ccache)
|
||||
else()
|
||||
set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE "")
|
||||
set_property(GLOBAL PROPERTY RULE_LAUNCH_LINK "")
|
||||
endif()
|
||||
endif(CCACHE_FOUND)
|
||||
find_program(CCACHE_FOUND ccache)
|
||||
if(CCACHE_FOUND)
|
||||
if(GTSAM_BUILD_WITH_CCACHE)
|
||||
set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE ccache)
|
||||
set_property(GLOBAL PROPERTY RULE_LAUNCH_LINK ccache)
|
||||
else()
|
||||
set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE "")
|
||||
set_property(GLOBAL PROPERTY RULE_LAUNCH_LINK "")
|
||||
endif()
|
||||
endif(CCACHE_FOUND)
|
||||
endif()
|
||||
|
||||
###############################################################################
|
||||
|
@ -280,74 +290,74 @@ option(GTSAM_WITH_EIGEN_UNSUPPORTED "Install Eigen's unsupported modules" OFF)
|
|||
|
||||
# Switch for using system Eigen or GTSAM-bundled Eigen
|
||||
if(GTSAM_USE_SYSTEM_EIGEN)
|
||||
find_package(Eigen3 REQUIRED)
|
||||
find_package(Eigen3 REQUIRED)
|
||||
|
||||
# Use generic Eigen include paths e.g. <Eigen/Core>
|
||||
set(GTSAM_EIGEN_INCLUDE_FOR_INSTALL "${EIGEN3_INCLUDE_DIR}")
|
||||
# Use generic Eigen include paths e.g. <Eigen/Core>
|
||||
set(GTSAM_EIGEN_INCLUDE_FOR_INSTALL "${EIGEN3_INCLUDE_DIR}")
|
||||
|
||||
# check if MKL is also enabled - can have one or the other, but not both!
|
||||
# Note: Eigen >= v3.2.5 includes our patches
|
||||
if(EIGEN_USE_MKL_ALL AND (EIGEN3_VERSION VERSION_LESS 3.2.5))
|
||||
message(FATAL_ERROR "MKL requires at least Eigen 3.2.5, and your system appears to have an older version. Disable GTSAM_USE_SYSTEM_EIGEN to use GTSAM's copy of Eigen, or disable GTSAM_WITH_EIGEN_MKL")
|
||||
endif()
|
||||
# check if MKL is also enabled - can have one or the other, but not both!
|
||||
# Note: Eigen >= v3.2.5 includes our patches
|
||||
if(EIGEN_USE_MKL_ALL AND (EIGEN3_VERSION VERSION_LESS 3.2.5))
|
||||
message(FATAL_ERROR "MKL requires at least Eigen 3.2.5, and your system appears to have an older version. Disable GTSAM_USE_SYSTEM_EIGEN to use GTSAM's copy of Eigen, or disable GTSAM_WITH_EIGEN_MKL")
|
||||
endif()
|
||||
|
||||
# Check for Eigen version which doesn't work with MKL
|
||||
# See http://eigen.tuxfamily.org/bz/show_bug.cgi?id=1527 for details.
|
||||
if(EIGEN_USE_MKL_ALL AND (EIGEN3_VERSION VERSION_EQUAL 3.3.4))
|
||||
message(FATAL_ERROR "MKL does not work with Eigen 3.3.4 because of a bug in Eigen. See http://eigen.tuxfamily.org/bz/show_bug.cgi?id=1527. Disable GTSAM_USE_SYSTEM_EIGEN to use GTSAM's copy of Eigen, disable GTSAM_WITH_EIGEN_MKL, or upgrade/patch your installation of Eigen.")
|
||||
endif()
|
||||
# Check for Eigen version which doesn't work with MKL
|
||||
# See http://eigen.tuxfamily.org/bz/show_bug.cgi?id=1527 for details.
|
||||
if(EIGEN_USE_MKL_ALL AND (EIGEN3_VERSION VERSION_EQUAL 3.3.4))
|
||||
message(FATAL_ERROR "MKL does not work with Eigen 3.3.4 because of a bug in Eigen. See http://eigen.tuxfamily.org/bz/show_bug.cgi?id=1527. Disable GTSAM_USE_SYSTEM_EIGEN to use GTSAM's copy of Eigen, disable GTSAM_WITH_EIGEN_MKL, or upgrade/patch your installation of Eigen.")
|
||||
endif()
|
||||
|
||||
# The actual include directory (for BUILD cmake target interface):
|
||||
set(GTSAM_EIGEN_INCLUDE_FOR_BUILD "${EIGEN3_INCLUDE_DIR}")
|
||||
# The actual include directory (for BUILD cmake target interface):
|
||||
set(GTSAM_EIGEN_INCLUDE_FOR_BUILD "${EIGEN3_INCLUDE_DIR}")
|
||||
else()
|
||||
# Use bundled Eigen include path.
|
||||
# Clear any variables set by FindEigen3
|
||||
if(EIGEN3_INCLUDE_DIR)
|
||||
set(EIGEN3_INCLUDE_DIR NOTFOUND CACHE STRING "" FORCE)
|
||||
endif()
|
||||
# Use bundled Eigen include path.
|
||||
# Clear any variables set by FindEigen3
|
||||
if(EIGEN3_INCLUDE_DIR)
|
||||
set(EIGEN3_INCLUDE_DIR NOTFOUND CACHE STRING "" FORCE)
|
||||
endif()
|
||||
|
||||
# set full path to be used by external projects
|
||||
# this will be added to GTSAM_INCLUDE_DIR by gtsam_extra.cmake.in
|
||||
set(GTSAM_EIGEN_INCLUDE_FOR_INSTALL "include/gtsam/3rdparty/Eigen/")
|
||||
# set full path to be used by external projects
|
||||
# this will be added to GTSAM_INCLUDE_DIR by gtsam_extra.cmake.in
|
||||
set(GTSAM_EIGEN_INCLUDE_FOR_INSTALL "include/gtsam/3rdparty/Eigen/")
|
||||
|
||||
# The actual include directory (for BUILD cmake target interface):
|
||||
set(GTSAM_EIGEN_INCLUDE_FOR_BUILD "${CMAKE_SOURCE_DIR}/gtsam/3rdparty/Eigen/")
|
||||
# The actual include directory (for BUILD cmake target interface):
|
||||
set(GTSAM_EIGEN_INCLUDE_FOR_BUILD "${CMAKE_SOURCE_DIR}/gtsam/3rdparty/Eigen/")
|
||||
endif()
|
||||
|
||||
# Detect Eigen version:
|
||||
set(EIGEN_VER_H "${GTSAM_EIGEN_INCLUDE_FOR_BUILD}/Eigen/src/Core/util/Macros.h")
|
||||
if (EXISTS ${EIGEN_VER_H})
|
||||
file(READ "${EIGEN_VER_H}" STR_EIGEN_VERSION)
|
||||
file(READ "${EIGEN_VER_H}" STR_EIGEN_VERSION)
|
||||
|
||||
# Extract the Eigen version from the Macros.h file, lines "#define EIGEN_WORLD_VERSION XX", etc...
|
||||
# Extract the Eigen version from the Macros.h file, lines "#define EIGEN_WORLD_VERSION XX", etc...
|
||||
|
||||
string(REGEX MATCH "EIGEN_WORLD_VERSION[ ]+[0-9]+" GTSAM_EIGEN_VERSION_WORLD "${STR_EIGEN_VERSION}")
|
||||
string(REGEX MATCH "[0-9]+" GTSAM_EIGEN_VERSION_WORLD "${GTSAM_EIGEN_VERSION_WORLD}")
|
||||
string(REGEX MATCH "EIGEN_WORLD_VERSION[ ]+[0-9]+" GTSAM_EIGEN_VERSION_WORLD "${STR_EIGEN_VERSION}")
|
||||
string(REGEX MATCH "[0-9]+" GTSAM_EIGEN_VERSION_WORLD "${GTSAM_EIGEN_VERSION_WORLD}")
|
||||
|
||||
string(REGEX MATCH "EIGEN_MAJOR_VERSION[ ]+[0-9]+" GTSAM_EIGEN_VERSION_MAJOR "${STR_EIGEN_VERSION}")
|
||||
string(REGEX MATCH "[0-9]+" GTSAM_EIGEN_VERSION_MAJOR "${GTSAM_EIGEN_VERSION_MAJOR}")
|
||||
string(REGEX MATCH "EIGEN_MAJOR_VERSION[ ]+[0-9]+" GTSAM_EIGEN_VERSION_MAJOR "${STR_EIGEN_VERSION}")
|
||||
string(REGEX MATCH "[0-9]+" GTSAM_EIGEN_VERSION_MAJOR "${GTSAM_EIGEN_VERSION_MAJOR}")
|
||||
|
||||
string(REGEX MATCH "EIGEN_MINOR_VERSION[ ]+[0-9]+" GTSAM_EIGEN_VERSION_MINOR "${STR_EIGEN_VERSION}")
|
||||
string(REGEX MATCH "[0-9]+" GTSAM_EIGEN_VERSION_MINOR "${GTSAM_EIGEN_VERSION_MINOR}")
|
||||
string(REGEX MATCH "EIGEN_MINOR_VERSION[ ]+[0-9]+" GTSAM_EIGEN_VERSION_MINOR "${STR_EIGEN_VERSION}")
|
||||
string(REGEX MATCH "[0-9]+" GTSAM_EIGEN_VERSION_MINOR "${GTSAM_EIGEN_VERSION_MINOR}")
|
||||
|
||||
set(GTSAM_EIGEN_VERSION "${GTSAM_EIGEN_VERSION_WORLD}.${GTSAM_EIGEN_VERSION_MAJOR}.${GTSAM_EIGEN_VERSION_MINOR}")
|
||||
set(GTSAM_EIGEN_VERSION "${GTSAM_EIGEN_VERSION_WORLD}.${GTSAM_EIGEN_VERSION_MAJOR}.${GTSAM_EIGEN_VERSION_MINOR}")
|
||||
|
||||
message(STATUS "Found Eigen version: ${GTSAM_EIGEN_VERSION}")
|
||||
message(STATUS "Found Eigen version: ${GTSAM_EIGEN_VERSION}")
|
||||
else()
|
||||
message(WARNING "Cannot determine Eigen version, missing file: `${EIGEN_VER_H}`")
|
||||
message(WARNING "Cannot determine Eigen version, missing file: `${EIGEN_VER_H}`")
|
||||
endif ()
|
||||
|
||||
if (MSVC)
|
||||
if (BUILD_SHARED_LIBS)
|
||||
# mute eigen static assert to avoid errors in shared lib
|
||||
list_append_cache(GTSAM_COMPILE_DEFINITIONS_PUBLIC EIGEN_NO_STATIC_ASSERT)
|
||||
endif()
|
||||
list_append_cache(GTSAM_COMPILE_OPTIONS_PRIVATE "/wd4244") # Disable loss of precision which is thrown all over our Eigen
|
||||
if (BUILD_SHARED_LIBS)
|
||||
# mute eigen static assert to avoid errors in shared lib
|
||||
list_append_cache(GTSAM_COMPILE_DEFINITIONS_PUBLIC EIGEN_NO_STATIC_ASSERT)
|
||||
endif()
|
||||
list_append_cache(GTSAM_COMPILE_OPTIONS_PRIVATE "/wd4244") # Disable loss of precision which is thrown all over our Eigen
|
||||
endif()
|
||||
|
||||
if (APPLE AND BUILD_SHARED_LIBS)
|
||||
# Set the default install directory on macOS
|
||||
set(CMAKE_INSTALL_NAME_DIR "${CMAKE_INSTALL_PREFIX}/lib")
|
||||
# Set the default install directory on macOS
|
||||
set(CMAKE_INSTALL_NAME_DIR "${CMAKE_INSTALL_PREFIX}/lib")
|
||||
endif()
|
||||
|
||||
###############################################################################
|
||||
|
@ -356,42 +366,42 @@ endif()
|
|||
# Build list of possible allocators
|
||||
set(possible_allocators "")
|
||||
if(GTSAM_USE_TBB)
|
||||
list(APPEND possible_allocators TBB)
|
||||
set(preferred_allocator TBB)
|
||||
list(APPEND possible_allocators TBB)
|
||||
set(preferred_allocator TBB)
|
||||
else()
|
||||
list(APPEND possible_allocators BoostPool STL)
|
||||
set(preferred_allocator STL)
|
||||
list(APPEND possible_allocators BoostPool STL)
|
||||
set(preferred_allocator STL)
|
||||
endif()
|
||||
if(GOOGLE_PERFTOOLS_FOUND)
|
||||
list(APPEND possible_allocators tcmalloc)
|
||||
list(APPEND possible_allocators tcmalloc)
|
||||
endif()
|
||||
|
||||
# Check if current allocator choice is valid and set cache option
|
||||
list(FIND possible_allocators "${GTSAM_DEFAULT_ALLOCATOR}" allocator_valid)
|
||||
if(allocator_valid EQUAL -1)
|
||||
set(GTSAM_DEFAULT_ALLOCATOR ${preferred_allocator} CACHE STRING "Default allocator" FORCE)
|
||||
set(GTSAM_DEFAULT_ALLOCATOR ${preferred_allocator} CACHE STRING "Default allocator" FORCE)
|
||||
else()
|
||||
set(GTSAM_DEFAULT_ALLOCATOR ${preferred_allocator} CACHE STRING "Default allocator")
|
||||
set(GTSAM_DEFAULT_ALLOCATOR ${preferred_allocator} CACHE STRING "Default allocator")
|
||||
endif()
|
||||
set_property(CACHE GTSAM_DEFAULT_ALLOCATOR PROPERTY STRINGS ${possible_allocators})
|
||||
mark_as_advanced(GTSAM_DEFAULT_ALLOCATOR)
|
||||
|
||||
# Define compile flags depending on allocator
|
||||
if("${GTSAM_DEFAULT_ALLOCATOR}" STREQUAL "BoostPool")
|
||||
set(GTSAM_ALLOCATOR_BOOSTPOOL 1)
|
||||
set(GTSAM_ALLOCATOR_BOOSTPOOL 1)
|
||||
elseif("${GTSAM_DEFAULT_ALLOCATOR}" STREQUAL "STL")
|
||||
set(GTSAM_ALLOCATOR_STL 1)
|
||||
set(GTSAM_ALLOCATOR_STL 1)
|
||||
elseif("${GTSAM_DEFAULT_ALLOCATOR}" STREQUAL "TBB")
|
||||
set(GTSAM_ALLOCATOR_TBB 1)
|
||||
set(GTSAM_ALLOCATOR_TBB 1)
|
||||
elseif("${GTSAM_DEFAULT_ALLOCATOR}" STREQUAL "tcmalloc")
|
||||
set(GTSAM_ALLOCATOR_STL 1) # tcmalloc replaces malloc, so to use it we use the STL allocator
|
||||
list(APPEND GTSAM_ADDITIONAL_LIBRARIES "tcmalloc")
|
||||
set(GTSAM_ALLOCATOR_STL 1) # tcmalloc replaces malloc, so to use it we use the STL allocator
|
||||
list(APPEND GTSAM_ADDITIONAL_LIBRARIES "tcmalloc")
|
||||
endif()
|
||||
|
||||
if(MSVC)
|
||||
list_append_cache(GTSAM_COMPILE_DEFINITIONS_PRIVATE _CRT_SECURE_NO_WARNINGS _SCL_SECURE_NO_WARNINGS)
|
||||
list_append_cache(GTSAM_COMPILE_OPTIONS_PRIVATE /wd4251 /wd4275 /wd4251 /wd4661 /wd4344 /wd4503) # Disable non-DLL-exported base class and other warnings
|
||||
list_append_cache(GTSAM_COMPILE_OPTIONS_PRIVATE /bigobj) # Allow large object files for template-based code
|
||||
list_append_cache(GTSAM_COMPILE_DEFINITIONS_PRIVATE _CRT_SECURE_NO_WARNINGS _SCL_SECURE_NO_WARNINGS)
|
||||
list_append_cache(GTSAM_COMPILE_OPTIONS_PRIVATE /wd4251 /wd4275 /wd4251 /wd4661 /wd4344 /wd4503) # Disable non-DLL-exported base class and other warnings
|
||||
list_append_cache(GTSAM_COMPILE_OPTIONS_PRIVATE /bigobj) # Allow large object files for template-based code
|
||||
endif()
|
||||
|
||||
# GCC 4.8+ complains about local typedefs which we use for shared_ptr etc.
|
||||
|
@ -419,14 +429,11 @@ endif()
|
|||
# Build CppUnitLite
|
||||
add_subdirectory(CppUnitLite)
|
||||
|
||||
# Build wrap
|
||||
if (GTSAM_BUILD_WRAP)
|
||||
add_subdirectory(wrap)
|
||||
# suppress warning of cython line being too long
|
||||
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-misleading-indentation")
|
||||
endif()
|
||||
endif(GTSAM_BUILD_WRAP)
|
||||
# This is the new wrapper
|
||||
if(GTSAM_BUILD_PYTHON)
|
||||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/wrap/cmake")
|
||||
add_subdirectory(python)
|
||||
endif()
|
||||
|
||||
# Build GTSAM library
|
||||
add_subdirectory(gtsam)
|
||||
|
@ -447,23 +454,9 @@ endif()
|
|||
|
||||
# Matlab toolbox
|
||||
if (GTSAM_INSTALL_MATLAB_TOOLBOX)
|
||||
add_subdirectory(matlab)
|
||||
add_subdirectory(matlab)
|
||||
endif()
|
||||
|
||||
# Cython wrap
|
||||
if (GTSAM_INSTALL_CYTHON_TOOLBOX)
|
||||
set(GTSAM_INSTALL_CYTHON_TOOLBOX 1)
|
||||
# Set up cache options
|
||||
# Cython install path appended with Build type (e.g. cython, cythonDebug, etc).
|
||||
# This does not override custom values set from the command line
|
||||
set(GTSAM_CYTHON_INSTALL_PATH "${PROJECT_BINARY_DIR}/cython${GTSAM_BUILD_TAG}" CACHE PATH "Cython toolbox destination, blank defaults to PROJECT_BINARY_DIR/cython<GTSAM_BUILD_TAG>")
|
||||
set(GTSAM_EIGENCY_INSTALL_PATH ${GTSAM_CYTHON_INSTALL_PATH}/gtsam_eigency)
|
||||
add_subdirectory(cython ${GTSAM_CYTHON_INSTALL_PATH})
|
||||
else()
|
||||
set(GTSAM_INSTALL_CYTHON_TOOLBOX 0) # This will go into config.h
|
||||
endif()
|
||||
|
||||
|
||||
# Install config and export files
|
||||
GtsamMakeConfigFile(GTSAM "${CMAKE_CURRENT_SOURCE_DIR}/gtsam_extra.cmake.in")
|
||||
export(TARGETS ${GTSAM_EXPORTED_TARGETS} FILE GTSAM-exports.cmake)
|
||||
|
@ -524,7 +517,9 @@ endif()
|
|||
print_enabled_config(${BUILD_SHARED_LIBS} "Build shared GTSAM libraries")
|
||||
print_enabled_config(${GTSAM_BUILD_TYPE_POSTFIXES} "Put build type in library name")
|
||||
if(GTSAM_UNSTABLE_AVAILABLE)
|
||||
print_enabled_config(${GTSAM_BUILD_UNSTABLE} "Build libgtsam_unstable")
|
||||
print_enabled_config(${GTSAM_BUILD_UNSTABLE} "Build libgtsam_unstable ")
|
||||
print_enabled_config(${GTSAM_UNSTABLE_BUILD_PYTHON} "Build GTSAM unstable Python ")
|
||||
print_enabled_config(${GTSAM_UNSTABLE_INSTALL_MATLAB_TOOLBOX} "Build MATLAB Toolbox for unstable")
|
||||
endif()
|
||||
|
||||
if(NOT MSVC AND NOT XCODE_VERSION)
|
||||
|
@ -572,13 +567,13 @@ else()
|
|||
endif()
|
||||
|
||||
if(NOT MSVC AND NOT XCODE_VERSION)
|
||||
if(CCACHE_FOUND AND GTSAM_BUILD_WITH_CCACHE)
|
||||
if(CCACHE_FOUND AND GTSAM_BUILD_WITH_CCACHE)
|
||||
print_config("Build with ccache" "Yes")
|
||||
elseif(CCACHE_FOUND)
|
||||
elseif(CCACHE_FOUND)
|
||||
print_config("Build with ccache" "ccache found but GTSAM_BUILD_WITH_CCACHE is disabled")
|
||||
else()
|
||||
else()
|
||||
print_config("Build with ccache" "No")
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
message(STATUS "Packaging flags")
|
||||
|
@ -594,7 +589,6 @@ print_enabled_config(${GTSAM_ALLOW_DEPRECATED_SINCE_V41} "Allow features deprec
|
|||
print_enabled_config(${GTSAM_TYPEDEF_POINTS_TO_VECTORS} "Point3 is typedef to Vector3 ")
|
||||
print_enabled_config(${GTSAM_SUPPORT_NESTED_DISSECTION} "Metis-based Nested Dissection ")
|
||||
print_enabled_config(${GTSAM_TANGENT_PREINTEGRATION} "Use tangent-space preintegration")
|
||||
print_enabled_config(${GTSAM_BUILD_WRAP} "Build Wrap ")
|
||||
|
||||
message(STATUS "MATLAB toolbox flags")
|
||||
print_enabled_config(${GTSAM_INSTALL_MATLAB_TOOLBOX} "Install MATLAB toolbox ")
|
||||
|
@ -602,23 +596,23 @@ if (${GTSAM_INSTALL_MATLAB_TOOLBOX})
|
|||
print_config("MATLAB root" "${MATLAB_ROOT}")
|
||||
print_config("MEX binary" "${MEX_COMMAND}")
|
||||
endif()
|
||||
|
||||
message(STATUS "Cython toolbox flags ")
|
||||
print_enabled_config(${GTSAM_INSTALL_CYTHON_TOOLBOX} "Install Cython toolbox ")
|
||||
if(GTSAM_INSTALL_CYTHON_TOOLBOX)
|
||||
print_config("Python version" "${GTSAM_PYTHON_VERSION}")
|
||||
message(STATUS "Python toolbox flags ")
|
||||
print_enabled_config(${GTSAM_BUILD_PYTHON} "Build Python module with pybind ")
|
||||
if(GTSAM_BUILD_PYTHON)
|
||||
print_config("Python version" ${GTSAM_PYTHON_VERSION})
|
||||
endif()
|
||||
|
||||
message(STATUS "===============================================================")
|
||||
|
||||
# Print warnings at the end
|
||||
if(GTSAM_WITH_TBB AND NOT TBB_FOUND)
|
||||
message(WARNING "TBB 4.4 or newer was not found - this is ok, but note that GTSAM parallelization will be disabled. Set GTSAM_WITH_TBB to 'Off' to avoid this warning.")
|
||||
message(WARNING "TBB 4.4 or newer was not found - this is ok, but note that GTSAM parallelization will be disabled. Set GTSAM_WITH_TBB to 'Off' to avoid this warning.")
|
||||
endif()
|
||||
if(GTSAM_WITH_EIGEN_MKL AND NOT MKL_FOUND)
|
||||
message(WARNING "MKL was not found - this is ok, but note that MKL will be disabled. Set GTSAM_WITH_EIGEN_MKL to 'Off' to disable this warning. See INSTALL.md for notes on performance.")
|
||||
message(WARNING "MKL was not found - this is ok, but note that MKL will be disabled. Set GTSAM_WITH_EIGEN_MKL to 'Off' to disable this warning. See INSTALL.md for notes on performance.")
|
||||
endif()
|
||||
if(GTSAM_WITH_EIGEN_MKL_OPENMP AND NOT OPENMP_FOUND AND MKL_FOUND)
|
||||
message(WARNING "Your compiler does not support OpenMP. Set GTSAM_WITH_EIGEN_MKL_OPENMP to 'Off' to avoid this warning. See INSTALL.md for notes on performance.")
|
||||
message(WARNING "Your compiler does not support OpenMP. Set GTSAM_WITH_EIGEN_MKL_OPENMP to 'Off' to avoid this warning. See INSTALL.md for notes on performance.")
|
||||
endif()
|
||||
|
||||
# Include CPack *after* all flags
|
||||
|
|
|
@ -17,8 +17,6 @@ install(FILES
|
|||
GtsamBuildTypes.cmake
|
||||
GtsamMakeConfigFile.cmake
|
||||
GtsamMatlabWrap.cmake
|
||||
GtsamPythonWrap.cmake
|
||||
GtsamCythonWrap.cmake
|
||||
GtsamTesting.cmake
|
||||
GtsamPrinting.cmake
|
||||
FindCython.cmake
|
||||
|
|
|
@ -1,204 +0,0 @@
|
|||
# Check Cython version, need to be >=0.25.2
|
||||
# Unset these cached variables to avoid surprises when the python/cython
|
||||
# in the current environment are different from the cached!
|
||||
unset(PYTHON_EXECUTABLE CACHE)
|
||||
unset(CYTHON_EXECUTABLE CACHE)
|
||||
unset(PYTHON_INCLUDE_DIR CACHE)
|
||||
unset(PYTHON_MAJOR_VERSION CACHE)
|
||||
unset(PYTHON_LIBRARY CACHE)
|
||||
|
||||
# Allow override from command line
|
||||
if(NOT DEFINED GTSAM_USE_CUSTOM_PYTHON_LIBRARY)
|
||||
if(GTSAM_PYTHON_VERSION STREQUAL "Default")
|
||||
find_package(PythonInterp REQUIRED)
|
||||
find_package(PythonLibs REQUIRED)
|
||||
else()
|
||||
find_package(PythonInterp ${GTSAM_PYTHON_VERSION} EXACT REQUIRED)
|
||||
find_package(PythonLibs ${GTSAM_PYTHON_VERSION} EXACT REQUIRED)
|
||||
endif()
|
||||
endif()
|
||||
find_package(Cython 0.25.2 REQUIRED)
|
||||
|
||||
execute_process(COMMAND "${PYTHON_EXECUTABLE}" "-c"
|
||||
"from __future__ import print_function;import sys;print(sys.version[0], end='')"
|
||||
OUTPUT_VARIABLE PYTHON_MAJOR_VERSION
|
||||
)
|
||||
|
||||
# User-friendly Cython wrapping and installing function.
|
||||
# Builds a Cython module from the provided interface_header.
|
||||
# For example, for the interface header gtsam.h,
|
||||
# this will build the wrap module 'gtsam'.
|
||||
#
|
||||
# Arguments:
|
||||
#
|
||||
# interface_header: The relative path to the wrapper interface definition file.
|
||||
# extra_imports: extra header to import in the Cython pxd file.
|
||||
# For example, to use Cython gtsam.pxd in your own module,
|
||||
# use "from gtsam cimport *"
|
||||
# install_path: destination to install the library
|
||||
# libs: libraries to link with
|
||||
# dependencies: Dependencies which need to be built before the wrapper
|
||||
function(wrap_and_install_library_cython interface_header extra_imports install_path libs dependencies)
|
||||
# Paths for generated files
|
||||
get_filename_component(module_name "${interface_header}" NAME_WE)
|
||||
set(generated_files_path "${install_path}")
|
||||
wrap_library_cython("${interface_header}" "${generated_files_path}" "${extra_imports}" "${libs}" "${dependencies}")
|
||||
endfunction()
|
||||
|
||||
function(set_up_required_cython_packages)
|
||||
# Set up building of cython module
|
||||
include_directories(${PYTHON_INCLUDE_DIRS})
|
||||
find_package(NumPy REQUIRED)
|
||||
include_directories(${NUMPY_INCLUDE_DIRS})
|
||||
endfunction()
|
||||
|
||||
|
||||
# Convert pyx to cpp by executing cython
|
||||
# This is the first step to compile cython from the command line
|
||||
# as described at: http://cython.readthedocs.io/en/latest/src/reference/compilation.html
|
||||
#
|
||||
# Arguments:
|
||||
# - target: The specified target for this step
|
||||
# - pyx_file: The input pyx_file in full *absolute* path
|
||||
# - generated_cpp: The output cpp file in full absolute path
|
||||
# - include_dirs: Directories to include when executing cython
|
||||
function(pyx_to_cpp target pyx_file generated_cpp include_dirs)
|
||||
foreach(dir ${include_dirs})
|
||||
set(includes_for_cython ${includes_for_cython} -I ${dir})
|
||||
endforeach()
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT ${generated_cpp}
|
||||
COMMAND
|
||||
${CYTHON_EXECUTABLE} -X boundscheck=False -v --fast-fail --cplus -${PYTHON_MAJOR_VERSION} ${includes_for_cython} ${pyx_file} -o ${generated_cpp}
|
||||
VERBATIM)
|
||||
add_custom_target(${target} ALL DEPENDS ${generated_cpp})
|
||||
endfunction()
|
||||
|
||||
# Build the cpp file generated by converting pyx using cython
|
||||
# This is the second step to compile cython from the command line
|
||||
# as described at: http://cython.readthedocs.io/en/latest/src/reference/compilation.html
|
||||
#
|
||||
# Arguments:
|
||||
# - target: The specified target for this step
|
||||
# - cpp_file: The input cpp_file in full *absolute* path
|
||||
# - output_lib_we: The output lib filename only (without extension)
|
||||
# - output_dir: The output directory
|
||||
function(build_cythonized_cpp target cpp_file output_lib_we output_dir)
|
||||
add_library(${target} MODULE ${cpp_file})
|
||||
|
||||
if(WIN32)
|
||||
# Use .pyd extension instead of .dll on Windows
|
||||
set_target_properties(${target} PROPERTIES SUFFIX ".pyd")
|
||||
|
||||
# Add full path to the Python library
|
||||
target_link_libraries(${target} ${PYTHON_LIBRARIES})
|
||||
endif()
|
||||
|
||||
if(APPLE)
|
||||
set(link_flags "-undefined dynamic_lookup")
|
||||
endif()
|
||||
set_target_properties(${target}
|
||||
PROPERTIES COMPILE_FLAGS "-w"
|
||||
LINK_FLAGS "${link_flags}"
|
||||
OUTPUT_NAME ${output_lib_we}
|
||||
PREFIX ""
|
||||
${CMAKE_BUILD_TYPE_UPPER}_POSTFIX ""
|
||||
LIBRARY_OUTPUT_DIRECTORY ${output_dir})
|
||||
endfunction()
|
||||
|
||||
# Cythonize a pyx from the command line as described at
|
||||
# http://cython.readthedocs.io/en/latest/src/reference/compilation.html
|
||||
# Arguments:
|
||||
# - target: The specified target
|
||||
# - pyx_file: The input pyx_file in full *absolute* path
|
||||
# - output_lib_we: The output lib filename only (without extension)
|
||||
# - output_dir: The output directory
|
||||
# - include_dirs: Directories to include when executing cython
|
||||
# - libs: Libraries to link with
|
||||
# - interface_header: For dependency. Any update in interface header will re-trigger cythonize
|
||||
function(cythonize target pyx_file output_lib_we output_dir include_dirs libs interface_header dependencies)
|
||||
get_filename_component(pyx_path "${pyx_file}" DIRECTORY)
|
||||
get_filename_component(pyx_name "${pyx_file}" NAME_WE)
|
||||
set(generated_cpp "${output_dir}/${pyx_name}.cpp")
|
||||
|
||||
set_up_required_cython_packages()
|
||||
pyx_to_cpp(${target}_pyx2cpp ${pyx_file} ${generated_cpp} "${include_dirs}")
|
||||
|
||||
# Late dependency injection, to make sure this gets called whenever the interface header is updated
|
||||
# See: https://stackoverflow.com/questions/40032593/cmake-does-not-rebuild-dependent-after-prerequisite-changes
|
||||
add_custom_command(OUTPUT ${generated_cpp} DEPENDS ${interface_header} ${pyx_file} APPEND)
|
||||
if (NOT "${dependencies}" STREQUAL "")
|
||||
add_dependencies(${target}_pyx2cpp "${dependencies}")
|
||||
endif()
|
||||
|
||||
build_cythonized_cpp(${target} ${generated_cpp} ${output_lib_we} ${output_dir})
|
||||
if (NOT "${libs}" STREQUAL "")
|
||||
target_link_libraries(${target} "${libs}")
|
||||
endif()
|
||||
add_dependencies(${target} ${target}_pyx2cpp)
|
||||
|
||||
if(TARGET ${python_install_target})
|
||||
add_dependencies(${python_install_target} ${target})
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
# Internal function that wraps a library and compiles the wrapper
|
||||
function(wrap_library_cython interface_header generated_files_path extra_imports libs dependencies)
|
||||
# Wrap codegen interface
|
||||
# Extract module path and name from interface header file name
|
||||
# wrap requires interfacePath to be *absolute*
|
||||
get_filename_component(interface_header "${interface_header}" ABSOLUTE)
|
||||
get_filename_component(module_path "${interface_header}" PATH)
|
||||
get_filename_component(module_name "${interface_header}" NAME_WE)
|
||||
|
||||
# Wrap module to Cython pyx
|
||||
message(STATUS "Cython wrapper generating ${generated_files_path}/${module_name}.pyx")
|
||||
set(generated_pyx "${generated_files_path}/${module_name}.pyx")
|
||||
if(NOT EXISTS ${generated_files_path})
|
||||
file(MAKE_DIRECTORY "${generated_files_path}")
|
||||
endif()
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT ${generated_pyx}
|
||||
DEPENDS ${interface_header} wrap
|
||||
COMMAND
|
||||
wrap --cython ${module_path} ${module_name} ${generated_files_path} "${extra_imports}"
|
||||
VERBATIM
|
||||
WORKING_DIRECTORY ${generated_files_path}/../)
|
||||
add_custom_target(cython_wrap_${module_name}_pyx ALL DEPENDS ${generated_pyx})
|
||||
if(NOT "${dependencies}" STREQUAL "")
|
||||
add_dependencies(cython_wrap_${module_name}_pyx ${dependencies})
|
||||
endif()
|
||||
|
||||
message(STATUS "Cythonize and build ${module_name}.pyx")
|
||||
get_property(include_dirs DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY INCLUDE_DIRECTORIES)
|
||||
cythonize(cythonize_${module_name} ${generated_pyx} ${module_name}
|
||||
${generated_files_path} "${include_dirs}" "${libs}" ${interface_header} cython_wrap_${module_name}_pyx)
|
||||
|
||||
# distclean
|
||||
add_custom_target(wrap_${module_name}_cython_distclean
|
||||
COMMAND cmake -E remove_directory ${generated_files_path})
|
||||
endfunction()
|
||||
|
||||
# Helper function to install Cython scripts and handle multiple build types where the scripts
|
||||
# should be installed to all build type toolboxes
|
||||
#
|
||||
# Arguments:
|
||||
# source_directory: The source directory to be installed. "The last component of each directory
|
||||
# name is appended to the destination directory but a trailing slash may be
|
||||
# used to avoid this because it leaves the last component empty."
|
||||
# (https://cmake.org/cmake/help/v3.3/command/install.html?highlight=install#installing-directories)
|
||||
# dest_directory: The destination directory to install to.
|
||||
# patterns: list of file patterns to install
|
||||
function(install_cython_scripts source_directory dest_directory patterns)
|
||||
set(patterns_args "")
|
||||
set(exclude_patterns "")
|
||||
|
||||
foreach(pattern ${patterns})
|
||||
list(APPEND patterns_args PATTERN "${pattern}")
|
||||
endforeach()
|
||||
|
||||
file(COPY "${source_directory}" DESTINATION "${dest_directory}"
|
||||
FILES_MATCHING ${patterns_args} PATTERN "${exclude_patterns}" EXCLUDE)
|
||||
endfunction()
|
|
@ -23,6 +23,11 @@ else()
|
|||
file(GLOB matlab_bin_directories "/usr/local/MATLAB/*/bin")
|
||||
set(mex_program_name "mex")
|
||||
endif()
|
||||
|
||||
if(GTSAM_CUSTOM_MATLAB_PATH)
|
||||
set(matlab_bin_directories ${GTSAM_CUSTOM_MATLAB_PATH})
|
||||
endif()
|
||||
|
||||
# Run find_program explicitly putting $PATH after our predefined program
|
||||
# directories using 'ENV PATH' and 'NO_SYSTEM_ENVIRONMENT_PATH' - this prevents
|
||||
# finding the LaTeX mex program (totally unrelated to MATLAB Mex) when LaTeX is
|
||||
|
@ -209,15 +214,34 @@ function(wrap_library_internal interfaceHeader linkLibraries extraIncludeDirs ex
|
|||
|
||||
# Set up generation of module source file
|
||||
file(MAKE_DIRECTORY "${generated_files_path}")
|
||||
|
||||
if(GTSAM_PYTHON_VERSION STREQUAL "Default")
|
||||
find_package(PythonInterp REQUIRED)
|
||||
find_package(PythonLibs REQUIRED)
|
||||
else()
|
||||
find_package(PythonInterp
|
||||
${GTSAM_PYTHON_VERSION}
|
||||
EXACT
|
||||
REQUIRED)
|
||||
find_package(PythonLibs
|
||||
${GTSAM_PYTHON_VERSION}
|
||||
EXACT
|
||||
REQUIRED)
|
||||
endif()
|
||||
|
||||
set(_ignore gtsam::Point2
|
||||
gtsam::Point3)
|
||||
add_custom_command(
|
||||
OUTPUT ${generated_cpp_file}
|
||||
DEPENDS ${interfaceHeader} wrap ${module_library_target} ${otherLibraryTargets} ${otherSourcesAndObjects}
|
||||
COMMAND
|
||||
wrap --matlab
|
||||
${modulePath}
|
||||
${moduleName}
|
||||
${generated_files_path}
|
||||
${matlab_h_path}
|
||||
DEPENDS ${interfaceHeader} ${module_library_target} ${otherLibraryTargets} ${otherSourcesAndObjects}
|
||||
COMMAND
|
||||
${PYTHON_EXECUTABLE}
|
||||
${CMAKE_SOURCE_DIR}/wrap/matlab_wrapper.py
|
||||
--src ${interfaceHeader}
|
||||
--module_name ${moduleName}
|
||||
--out ${generated_files_path}
|
||||
--top_module_namespaces ${moduleName}
|
||||
--ignore ${_ignore}
|
||||
VERBATIM
|
||||
WORKING_DIRECTORY ${generated_files_path})
|
||||
|
||||
|
|
|
@ -1,102 +0,0 @@
|
|||
#Setup cache options
|
||||
set(GTSAM_PYTHON_VERSION "Default" CACHE STRING "Target python version for GTSAM python module. Use 'Default' to chose the default version")
|
||||
set(GTSAM_BUILD_PYTHON_FLAGS "" CACHE STRING "Extra flags for running Matlab PYTHON compilation")
|
||||
set(GTSAM_PYTHON_INSTALL_PATH "" CACHE PATH "Python toolbox destination, blank defaults to CMAKE_INSTALL_PREFIX/borg/python")
|
||||
if(NOT GTSAM_PYTHON_INSTALL_PATH)
|
||||
set(GTSAM_PYTHON_INSTALL_PATH "${CMAKE_INSTALL_PREFIX}/borg/python")
|
||||
endif()
|
||||
|
||||
#Author: Paul Furgale Modified by Andrew Melim
|
||||
function(wrap_python TARGET_NAME PYTHON_MODULE_DIRECTORY)
|
||||
# # Boost
|
||||
# find_package(Boost COMPONENTS python filesystem system REQUIRED)
|
||||
# include_directories(${Boost_INCLUDE_DIRS})
|
||||
|
||||
# # Find Python
|
||||
# FIND_PACKAGE(PythonLibs 2.7 REQUIRED)
|
||||
# INCLUDE_DIRECTORIES(${PYTHON_INCLUDE_DIRS})
|
||||
|
||||
IF(APPLE)
|
||||
# The apple framework headers don't include the numpy headers for some reason.
|
||||
GET_FILENAME_COMPONENT(REAL_PYTHON_INCLUDE ${PYTHON_INCLUDE_DIRS} REALPATH)
|
||||
IF( ${REAL_PYTHON_INCLUDE} MATCHES Python.framework)
|
||||
message("Trying to find extra headers for numpy from ${REAL_PYTHON_INCLUDE}.")
|
||||
message("Looking in ${REAL_PYTHON_INCLUDE}/../../Extras/lib/python/numpy/core/include/numpy")
|
||||
FIND_PATH(NUMPY_INCLUDE_DIR arrayobject.h
|
||||
${REAL_PYTHON_INCLUDE}/../../Extras/lib/python/numpy/core/include/numpy
|
||||
${REAL_PYTHON_INCLUDE}/numpy
|
||||
)
|
||||
IF(${NUMPY_INCLUDE_DIR} MATCHES NOTFOUND)
|
||||
message("Unable to find numpy include directories: ${NUMPY_INCLUDE_DIR}")
|
||||
ELSE()
|
||||
message("Found headers at ${NUMPY_INCLUDE_DIR}")
|
||||
INCLUDE_DIRECTORIES(${NUMPY_INCLUDE_DIR})
|
||||
INCLUDE_DIRECTORIES(${NUMPY_INCLUDE_DIR}/..)
|
||||
ENDIF()
|
||||
ENDIF()
|
||||
ENDIF(APPLE)
|
||||
|
||||
if(MSVC)
|
||||
add_library(${moduleName}_python MODULE ${ARGN})
|
||||
set_target_properties(${moduleName}_python PROPERTIES
|
||||
OUTPUT_NAME ${moduleName}_python
|
||||
CLEAN_DIRECT_OUTPUT 1
|
||||
VERSION 1
|
||||
SOVERSION 0
|
||||
SUFFIX ".pyd")
|
||||
target_link_libraries(${moduleName}_python ${Boost_PYTHON_LIBRARY} ${PYTHON_LIBRARY} ${gtsamLib}) #temp
|
||||
|
||||
set(PYLIB_OUTPUT_FILE $<TARGET_FILE:${moduleName}_python>)
|
||||
message(${PYLIB_OUTPUT_FILE})
|
||||
get_filename_component(PYLIB_OUTPUT_NAME ${PYLIB_OUTPUT_FILE} NAME_WE)
|
||||
set(PYLIB_SO_NAME ${PYLIB_OUTPUT_NAME}.pyd)
|
||||
|
||||
ELSE()
|
||||
# Create a shared library
|
||||
add_library(${moduleName}_python SHARED ${generated_cpp_file})
|
||||
|
||||
set_target_properties(${moduleName}_python PROPERTIES
|
||||
OUTPUT_NAME ${moduleName}_python
|
||||
CLEAN_DIRECT_OUTPUT 1)
|
||||
target_link_libraries(${moduleName}_python ${Boost_PYTHON_LIBRARY} ${PYTHON_LIBRARY} ${gtsamLib}) #temp
|
||||
# On OSX and Linux, the python library must end in the extension .so. Build this
|
||||
# filename here.
|
||||
get_property(PYLIB_OUTPUT_FILE TARGET ${moduleName}_python PROPERTY LOCATION)
|
||||
set(PYLIB_OUTPUT_FILE $<TARGET_FILE:${moduleName}_python>)
|
||||
message(${PYLIB_OUTPUT_FILE})
|
||||
get_filename_component(PYLIB_OUTPUT_NAME ${PYLIB_OUTPUT_FILE} NAME_WE)
|
||||
set(PYLIB_SO_NAME lib${moduleName}_python.so)
|
||||
ENDIF(MSVC)
|
||||
|
||||
# Installs the library in the gtsam folder, which is used by setup.py to create the gtsam package
|
||||
set(PYTHON_MODULE_DIRECTORY ${CMAKE_SOURCE_DIR}/python/gtsam)
|
||||
# Cause the library to be output in the correct directory.
|
||||
add_custom_command(TARGET ${moduleName}_python
|
||||
POST_BUILD
|
||||
COMMAND cp -v ${PYLIB_OUTPUT_FILE} ${PYTHON_MODULE_DIRECTORY}/${PYLIB_SO_NAME}
|
||||
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
|
||||
COMMENT "Copying library files to python directory" )
|
||||
|
||||
# Cause the library to be output in the correct directory.
|
||||
add_custom_command(TARGET ${TARGET_NAME}
|
||||
POST_BUILD
|
||||
COMMAND cp -v ${PYLIB_OUTPUT_FILE} ${PYTHON_MODULE_DIRECTORY}/${PYLIB_SO_NAME}
|
||||
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
|
||||
COMMENT "Copying library files to python directory" )
|
||||
|
||||
get_directory_property(AMCF ADDITIONAL_MAKE_CLEAN_FILES)
|
||||
list(APPEND AMCF ${PYTHON_MODULE_DIRECTORY}/${PYLIB_SO_NAME})
|
||||
set_directory_properties(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES "${AMCF}")
|
||||
endfunction(wrap_python)
|
||||
|
||||
# Macro to get list of subdirectories
|
||||
macro(SUBDIRLIST result curdir)
|
||||
file(GLOB children RELATIVE ${curdir} ${curdir}/*)
|
||||
set(dirlist "")
|
||||
foreach(child ${children})
|
||||
if(IS_DIRECTORY ${curdir}/${child})
|
||||
list(APPEND dirlist ${child})
|
||||
endif()
|
||||
endforeach()
|
||||
set(${result} ${dirlist})
|
||||
endmacro()
|
|
@ -47,9 +47,14 @@
|
|||
# endif
|
||||
# endif
|
||||
#else
|
||||
#ifdef __APPLE__
|
||||
# define @library_name@_EXPORT __attribute__((visibility("default")))
|
||||
# define @library_name@_EXTERN_EXPORT extern
|
||||
#else
|
||||
# define @library_name@_EXPORT
|
||||
# define @library_name@_EXTERN_EXPORT extern
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#undef BUILD_SHARED_LIBS
|
||||
|
||||
|
|
|
@ -1,57 +0,0 @@
|
|||
# Install cython components
|
||||
include(GtsamCythonWrap)
|
||||
|
||||
# Create the cython toolbox for the gtsam library
|
||||
if (GTSAM_INSTALL_CYTHON_TOOLBOX)
|
||||
# Add the new make target command
|
||||
set(python_install_target python-install)
|
||||
add_custom_target(${python_install_target}
|
||||
COMMAND ${PYTHON_EXECUTABLE} ${GTSAM_CYTHON_INSTALL_PATH}/setup.py install
|
||||
WORKING_DIRECTORY ${GTSAM_CYTHON_INSTALL_PATH})
|
||||
|
||||
# build and include the eigency version of eigency
|
||||
add_subdirectory(gtsam_eigency)
|
||||
include_directories(${GTSAM_EIGENCY_INSTALL_PATH})
|
||||
|
||||
# Fix for error "C1128: number of sections exceeded object file format limit"
|
||||
if(MSVC)
|
||||
add_compile_options(/bigobj)
|
||||
endif()
|
||||
|
||||
# First set up all the package related files.
|
||||
# This also ensures the below wrap operations work correctly.
|
||||
set(CYTHON_INSTALL_REQUIREMENTS_FILE "${PROJECT_SOURCE_DIR}/cython/requirements.txt")
|
||||
|
||||
# Install the custom-generated __init__.py
|
||||
# This makes the cython (sub-)directories into python packages, so gtsam can be found while wrapping gtsam_unstable
|
||||
configure_file(${PROJECT_SOURCE_DIR}/cython/gtsam/__init__.py ${GTSAM_CYTHON_INSTALL_PATH}/gtsam/__init__.py COPYONLY)
|
||||
configure_file(${PROJECT_SOURCE_DIR}/cython/gtsam_unstable/__init__.py ${GTSAM_CYTHON_INSTALL_PATH}/gtsam_unstable/__init__.py COPYONLY)
|
||||
configure_file(${PROJECT_SOURCE_DIR}/cython/setup.py.in ${GTSAM_CYTHON_INSTALL_PATH}/setup.py)
|
||||
|
||||
# Wrap gtsam
|
||||
add_custom_target(gtsam_header DEPENDS "../gtsam.h")
|
||||
wrap_and_install_library_cython("../gtsam.h" # interface_header
|
||||
"" # extra imports
|
||||
"${GTSAM_CYTHON_INSTALL_PATH}/gtsam" # install path
|
||||
gtsam # library to link with
|
||||
"wrap;cythonize_eigency;gtsam;gtsam_header" # dependencies which need to be built before wrapping
|
||||
)
|
||||
add_dependencies(${python_install_target} gtsam gtsam_header)
|
||||
|
||||
# Wrap gtsam_unstable
|
||||
if(GTSAM_BUILD_UNSTABLE)
|
||||
add_custom_target(gtsam_unstable_header DEPENDS "../gtsam_unstable/gtsam_unstable.h")
|
||||
wrap_and_install_library_cython("../gtsam_unstable/gtsam_unstable.h" # interface_header
|
||||
"from gtsam.gtsam cimport *" # extra imports
|
||||
"${GTSAM_CYTHON_INSTALL_PATH}/gtsam_unstable" # install path
|
||||
gtsam_unstable # library to link with
|
||||
"gtsam_unstable;gtsam_unstable_header;cythonize_gtsam" # dependencies to be built before wrapping
|
||||
)
|
||||
add_dependencies(${python_install_target} gtsam_unstable gtsam_unstable_header)
|
||||
endif()
|
||||
|
||||
# install scripts and tests
|
||||
install_cython_scripts("${PROJECT_SOURCE_DIR}/cython/gtsam" "${GTSAM_CYTHON_INSTALL_PATH}" "*.py")
|
||||
install_cython_scripts("${PROJECT_SOURCE_DIR}/cython/gtsam_unstable" "${GTSAM_CYTHON_INSTALL_PATH}" "*.py")
|
||||
|
||||
endif ()
|
147
cython/README.md
147
cython/README.md
|
@ -1,147 +0,0 @@
|
|||
# Python Wrapper
|
||||
|
||||
This is the Python wrapper around the GTSAM C++ library. We use Cython to generate the bindings to the underlying C++ code.
|
||||
|
||||
## Requirements
|
||||
|
||||
- If you want to build the GTSAM python library for a specific python version (eg 3.6),
|
||||
use the `-DGTSAM_PYTHON_VERSION=3.6` option when running `cmake` otherwise the default interpreter will be used.
|
||||
- If the interpreter is inside an environment (such as an anaconda environment or virtualenv environment),
|
||||
then the environment should be active while building GTSAM.
|
||||
- This wrapper needs `Cython(>=0.25.2)`, `backports_abc(>=0.5)`, and `numpy(>=1.11.0)`. These can be installed as follows:
|
||||
|
||||
```bash
|
||||
pip install -r <gtsam_folder>/cython/requirements.txt
|
||||
```
|
||||
|
||||
- For compatibility with GTSAM's Eigen version, it contains its own cloned version of [Eigency](https://github.com/wouterboomsma/eigency.git),
|
||||
named `gtsam_eigency`, to interface between C++'s Eigen and Python's numpy.
|
||||
|
||||
## Install
|
||||
|
||||
- Run cmake with the `GTSAM_INSTALL_CYTHON_TOOLBOX` cmake flag enabled to configure building the wrapper. The wrapped module will be built and copied to the directory defined by `GTSAM_CYTHON_INSTALL_PATH`, which is by default `<PROJECT_BINARY_DIR>/cython` in Release mode and `<PROJECT_BINARY_DIR>/cython<CMAKE_BUILD_TYPE>` for other modes.
|
||||
|
||||
- Build GTSAM and the wrapper with `make`.
|
||||
|
||||
- To install, simply run `make python-install`.
|
||||
- The same command can be used to install into a virtual environment if it is active.
|
||||
- **NOTE**: if you don't want GTSAM to install to a system directory such as `/usr/local`, pass `-DCMAKE_INSTALL_PREFIX="./install"` to cmake to install GTSAM to a subdirectory of the build directory.
|
||||
|
||||
- You can also directly run `make python-install` without running `make`, and it will compile all the dependencies accordingly.
|
||||
|
||||
## Unit Tests
|
||||
|
||||
The Cython toolbox also has a small set of unit tests located in the
|
||||
test directory. To run them:
|
||||
|
||||
```bash
|
||||
cd <GTSAM_CYTHON_INSTALL_PATH>
|
||||
python -m unittest discover
|
||||
```
|
||||
|
||||
## Utils
|
||||
|
||||
TODO
|
||||
|
||||
## Examples
|
||||
|
||||
TODO
|
||||
|
||||
## Writing Your Own Scripts
|
||||
|
||||
See the tests for examples.
|
||||
|
||||
### Some Important Notes:
|
||||
|
||||
- Vector/Matrix:
|
||||
|
||||
- GTSAM expects double-precision floating point vectors and matrices.
|
||||
Hence, you should pass numpy matrices with `dtype=float`, or `float64`.
|
||||
- Also, GTSAM expects _column-major_ matrices, unlike the default storage
|
||||
scheme in numpy. Hence, you should pass column-major matrices to GTSAM using
|
||||
the flag order='F'. And you always get column-major matrices back.
|
||||
For more details, see [this link](https://github.com/wouterboomsma/eigency#storage-layout---why-arrays-are-sometimes-transposed).
|
||||
- Passing row-major matrices of different dtype, e.g. `int`, will also work
|
||||
as the wrapper converts them to column-major and dtype float for you,
|
||||
using numpy.array.astype(float, order='F', copy=False).
|
||||
However, this will result a copy if your matrix is not in the expected type
|
||||
and storage order.
|
||||
|
||||
- Inner namespace: Classes in inner namespace will be prefixed by <innerNamespace>\_ in Python.
|
||||
|
||||
Examples: `noiseModel_Gaussian`, `noiseModel_mEstimator_Tukey`
|
||||
|
||||
- Casting from a base class to a derive class must be done explicitly.
|
||||
|
||||
Examples:
|
||||
|
||||
```python
|
||||
noiseBase = factor.noiseModel()
|
||||
noiseGaussian = dynamic_cast_noiseModel_Gaussian_noiseModel_Base(noiseBase)
|
||||
```
|
||||
|
||||
## Wrapping Custom GTSAM-based Project
|
||||
|
||||
Please refer to the template project and the corresponding tutorial available [here](https://github.com/borglab/GTSAM-project-python).
|
||||
|
||||
## KNOWN ISSUES
|
||||
|
||||
- Doesn't work with python3 installed from homebrew
|
||||
- size-related issue: can only wrap up to a certain number of classes: up to mEstimator!
|
||||
- Guess: 64 vs 32b? disutils Compiler flags?
|
||||
- Bug with Cython 0.24: instantiated factor classes return FastVector<size_t> for keys(), which can't be casted to FastVector<Key>
|
||||
- Upgrading to 0.25 solves the problem
|
||||
- Need default constructor and default copy constructor for almost every classes... :(
|
||||
- support these constructors by default and declare "delete" for special classes?
|
||||
|
||||
### TODO
|
||||
|
||||
- [ ] allow duplication of parent' functions in child classes. Not allowed for now due to conflicts in Cython.
|
||||
- [ ] a common header for boost shared_ptr? (Or wait until everything is switched to std::shared_ptr in GTSAM?)
|
||||
- [ ] inner namespaces ==> inner packages?
|
||||
- [ ] Wrap fixed-size Matrices/Vectors?
|
||||
|
||||
### Completed/Cancelled:
|
||||
|
||||
- [x] Fix Python tests: don't use " import <package> \* ": Bad style!!! (18-03-17 19:50)
|
||||
- [x] Unit tests for cython wrappers @done (18-03-17 18:45) -- simply compare generated files
|
||||
- [x] Wrap unstable @done (18-03-17 15:30)
|
||||
- [x] Unify cython/GTSAM.h and the original GTSAM.h @done (18-03-17 15:30)
|
||||
- [x] 18-03-17: manage to unify the two versions by removing std container stubs from the matlab version,and keeping KeyList/KeyVector/KeySet as in the matlab version. Probably Cython 0.25 fixes the casting problem.
|
||||
- [x] 06-03-17: manage to remove the requirements for default and copy constructors
|
||||
- [ ] 25-11-16: Try to unify but failed. Main reasons are: Key/size_t, std containers, KeyVector/KeyList/KeySet. Matlab doesn't need to know about Key, but I can't make Cython to ignore Key as it couldn't cast KeyVector, i.e. FastVector<Key>, to FastVector<size_t>.
|
||||
- [ ] Marginal and JointMarginal: revert changes @failed (17-03-17 11:00) -- Cython does need a default constructor! It produces cpp code like this: `GTSAM::JointMarginal __pyx_t_1;` Users don't have to wrap this constructor, however.
|
||||
- [x] Convert input numpy Matrix/Vector to float dtype and storage order 'F' automatically, cannot crash! @done (15-03-17 13:00)
|
||||
- [x] Remove requirements.txt - Frank: don't bother with only 2 packages and a special case for eigency! @done (08-03-17 10:30)
|
||||
- [x] CMake install script @done (25-11-16 02:30)
|
||||
- [ ] [REFACTOR] better name for uninstantiateClass: very vague!! @cancelled (25-11-16 02:30) -- lazy
|
||||
- [ ] forward declaration? @cancelled (23-11-16 13:00) - nothing to do, seem to work?
|
||||
- [x] wrap VariableIndex: why is it in inference? If need to, shouldn't have constructors to specific FactorGraphs @done (23-11-16 13:00)
|
||||
- [x] Global functions @done (22-11-16 21:00)
|
||||
- [x] [REFACTOR] typesEqual --> isSameSignature @done (22-11-16 21:00)
|
||||
- [x] Proper overloads (constructors, static methods, methods) @done (20-11-16 21:00)
|
||||
- [x] Allow overloading methods. The current solution is annoying!!! @done (20-11-16 21:00)
|
||||
- [x] Casting from parent and grandparents @done (16-11-16 17:00)
|
||||
- [x] Allow overloading constructors. The current solution is annoying!!! @done (16-11-16 17:00)
|
||||
- [x] Support "print obj" @done (16-11-16 17:00)
|
||||
- [x] methods for FastVector: at, [], ... @done (16-11-16 17:00)
|
||||
- [x] Cython: Key and size_t: traits<size_t> doesn't exist @done (16-09-12 18:34)
|
||||
- [x] KeyVector, KeyList, KeySet... @done (16-09-13 17:19)
|
||||
- [x] [Nice to have] parse typedef @done (16-09-13 17:19)
|
||||
- [x] ctypedef at correct places @done (16-09-12 18:34)
|
||||
- [x] expand template variable type in constructor/static methods? @done (16-09-12 18:34)
|
||||
- [x] NonlinearOptimizer: copy constructor deleted!!! @done (16-09-13 17:20)
|
||||
- [x] Value: no default constructor @done (16-09-13 17:20)
|
||||
- [x] ctypedef PriorFactor[Vector] PriorFactorVector @done (16-09-19 12:25)
|
||||
- [x] Delete duplicate methods in derived class @done (16-09-12 13:38)
|
||||
- [x] Fix return properly @done (16-09-11 17:14)
|
||||
- [x] handle pair @done (16-09-11 17:14)
|
||||
- [x] Eigency: ambiguous call: A(const T&) A(const Vector& v) and Eigency A(Map[Vector]& v) @done (16-09-11 07:59)
|
||||
- [x] Eigency: Constructor: ambiguous construct from Vector/Matrix @done (16-09-11 07:59)
|
||||
- [x] Eigency: Fix method template of Vector/Matrix: template argument is [Vector] while arugment is Map[Vector] @done (16-09-11 08:22)
|
||||
- [x] Robust noise: copy assignment operator is deleted because of shared_ptr of the abstract Base class @done (16-09-10 09:05)
|
||||
- [ ] Cython: Constructor: generate default constructor? (hack: if it's serializable?) @cancelled (16-09-13 17:20)
|
||||
- [ ] Eigency: Map[] to Block @created(16-09-10 07:59) @cancelled (16-09-11 08:28)
|
||||
|
||||
- inference before symbolic/linear
|
||||
- what's the purpose of "virtual" ??
|
|
@ -1,26 +0,0 @@
|
|||
from .gtsam import *
|
||||
|
||||
try:
|
||||
import gtsam_unstable
|
||||
|
||||
|
||||
def _deprecated_wrapper(item, name):
|
||||
def wrapper(*args, **kwargs):
|
||||
from warnings import warn
|
||||
message = ('importing the unstable item "{}" directly from gtsam is deprecated. '.format(name) +
|
||||
'Please import it from gtsam_unstable.')
|
||||
warn(message)
|
||||
return item(*args, **kwargs)
|
||||
return wrapper
|
||||
|
||||
|
||||
for name in dir(gtsam_unstable):
|
||||
if not name.startswith('__'):
|
||||
item = getattr(gtsam_unstable, name)
|
||||
if callable(item):
|
||||
item = _deprecated_wrapper(item, name)
|
||||
globals()[name] = item
|
||||
|
||||
except ImportError:
|
||||
pass
|
||||
|
|
@ -1,153 +0,0 @@
|
|||
"""
|
||||
GTSAM Copyright 2010-2019, Georgia Tech Research Corporation,
|
||||
Atlanta, Georgia 30332-0415
|
||||
All Rights Reserved
|
||||
|
||||
See LICENSE for the license information
|
||||
|
||||
A script validating and demonstrating the ImuFactor inference.
|
||||
|
||||
Author: Frank Dellaert, Varun Agrawal
|
||||
"""
|
||||
|
||||
from __future__ import print_function
|
||||
|
||||
import math
|
||||
|
||||
import gtsam
|
||||
import matplotlib.pyplot as plt
|
||||
import numpy as np
|
||||
from gtsam import symbol_shorthand_B as B
|
||||
from gtsam import symbol_shorthand_V as V
|
||||
from gtsam import symbol_shorthand_X as X
|
||||
from gtsam.utils.plot import plot_pose3
|
||||
from mpl_toolkits.mplot3d import Axes3D
|
||||
|
||||
from PreintegrationExample import POSES_FIG, PreintegrationExample
|
||||
|
||||
BIAS_KEY = B(0)
|
||||
|
||||
|
||||
np.set_printoptions(precision=3, suppress=True)
|
||||
|
||||
|
||||
class ImuFactorExample(PreintegrationExample):
|
||||
|
||||
def __init__(self):
|
||||
self.velocity = np.array([2, 0, 0])
|
||||
self.priorNoise = gtsam.noiseModel_Isotropic.Sigma(6, 0.1)
|
||||
self.velNoise = gtsam.noiseModel_Isotropic.Sigma(3, 0.1)
|
||||
|
||||
# Choose one of these twists to change scenario:
|
||||
zero_twist = (np.zeros(3), np.zeros(3))
|
||||
forward_twist = (np.zeros(3), self.velocity)
|
||||
loop_twist = (np.array([0, -math.radians(30), 0]), self.velocity)
|
||||
sick_twist = (
|
||||
np.array([math.radians(30), -math.radians(30), 0]), self.velocity)
|
||||
|
||||
accBias = np.array([-0.3, 0.1, 0.2])
|
||||
gyroBias = np.array([0.1, 0.3, -0.1])
|
||||
bias = gtsam.imuBias_ConstantBias(accBias, gyroBias)
|
||||
|
||||
dt = 1e-2
|
||||
super(ImuFactorExample, self).__init__(sick_twist, bias, dt)
|
||||
|
||||
def addPrior(self, i, graph):
|
||||
state = self.scenario.navState(i)
|
||||
graph.push_back(gtsam.PriorFactorPose3(
|
||||
X(i), state.pose(), self.priorNoise))
|
||||
graph.push_back(gtsam.PriorFactorVector(
|
||||
V(i), state.velocity(), self.velNoise))
|
||||
|
||||
def run(self):
|
||||
graph = gtsam.NonlinearFactorGraph()
|
||||
|
||||
# initialize data structure for pre-integrated IMU measurements
|
||||
pim = gtsam.PreintegratedImuMeasurements(self.params, self.actualBias)
|
||||
|
||||
T = 12
|
||||
num_poses = T + 1 # assumes 1 factor per second
|
||||
initial = gtsam.Values()
|
||||
initial.insert(BIAS_KEY, self.actualBias)
|
||||
for i in range(num_poses):
|
||||
state_i = self.scenario.navState(float(i))
|
||||
|
||||
poseNoise = gtsam.Pose3.Expmap(np.random.randn(3)*0.1)
|
||||
pose = state_i.pose().compose(poseNoise)
|
||||
|
||||
velocity = state_i.velocity() + np.random.randn(3)*0.1
|
||||
|
||||
initial.insert(X(i), pose)
|
||||
initial.insert(V(i), velocity)
|
||||
|
||||
# simulate the loop
|
||||
i = 0 # state index
|
||||
actual_state_i = self.scenario.navState(0)
|
||||
for k, t in enumerate(np.arange(0, T, self.dt)):
|
||||
# get measurements and add them to PIM
|
||||
measuredOmega = self.runner.measuredAngularVelocity(t)
|
||||
measuredAcc = self.runner.measuredSpecificForce(t)
|
||||
pim.integrateMeasurement(measuredAcc, measuredOmega, self.dt)
|
||||
|
||||
poseNoise = gtsam.Pose3.Expmap(np.random.randn(3)*0.1)
|
||||
|
||||
actual_state_i = gtsam.NavState(
|
||||
actual_state_i.pose().compose(poseNoise),
|
||||
actual_state_i.velocity() + np.random.randn(3)*0.1)
|
||||
|
||||
# Plot IMU many times
|
||||
if k % 10 == 0:
|
||||
self.plotImu(t, measuredOmega, measuredAcc)
|
||||
|
||||
# Plot every second
|
||||
if k % int(1 / self.dt) == 0:
|
||||
self.plotGroundTruthPose(t)
|
||||
|
||||
# create IMU factor every second
|
||||
if (k + 1) % int(1 / self.dt) == 0:
|
||||
factor = gtsam.ImuFactor(X(i), V(i), X(
|
||||
i + 1), V(i + 1), BIAS_KEY, pim)
|
||||
graph.push_back(factor)
|
||||
if True:
|
||||
print(factor)
|
||||
print(pim.predict(actual_state_i, self.actualBias))
|
||||
pim.resetIntegration()
|
||||
actual_state_i = self.scenario.navState(t + self.dt)
|
||||
i += 1
|
||||
|
||||
# add priors on beginning and end
|
||||
self.addPrior(0, graph)
|
||||
self.addPrior(num_poses - 1, graph)
|
||||
|
||||
# optimize using Levenberg-Marquardt optimization
|
||||
params = gtsam.LevenbergMarquardtParams()
|
||||
params.setVerbosityLM("SUMMARY")
|
||||
optimizer = gtsam.LevenbergMarquardtOptimizer(graph, initial, params)
|
||||
result = optimizer.optimize()
|
||||
|
||||
# Calculate and print marginal covariances
|
||||
marginals = gtsam.Marginals(graph, result)
|
||||
print("Covariance on bias:\n", marginals.marginalCovariance(BIAS_KEY))
|
||||
for i in range(num_poses):
|
||||
print("Covariance on pose {}:\n{}\n".format(
|
||||
i, marginals.marginalCovariance(X(i))))
|
||||
print("Covariance on vel {}:\n{}\n".format(
|
||||
i, marginals.marginalCovariance(V(i))))
|
||||
|
||||
# Plot resulting poses
|
||||
i = 0
|
||||
while result.exists(X(i)):
|
||||
pose_i = result.atPose3(X(i))
|
||||
plot_pose3(POSES_FIG, pose_i, 0.1)
|
||||
i += 1
|
||||
|
||||
gtsam.utils.plot.set_axes_equal(POSES_FIG)
|
||||
|
||||
print(result.atimuBias_ConstantBias(BIAS_KEY))
|
||||
|
||||
plt.ioff()
|
||||
plt.show()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
ImuFactorExample().run()
|
|
@ -1,42 +0,0 @@
|
|||
include(GtsamCythonWrap)
|
||||
|
||||
# Copy eigency's sources to the build folder
|
||||
# so that the cython-generated header "conversions_api.h" can be found when cythonizing eigency's core
|
||||
# and eigency's cython pxd headers can be found when cythonizing gtsam
|
||||
file(COPY "." DESTINATION ".")
|
||||
set(OUTPUT_DIR "${GTSAM_CYTHON_INSTALL_PATH}/gtsam_eigency")
|
||||
set(EIGENCY_INCLUDE_DIR ${OUTPUT_DIR})
|
||||
|
||||
# This is to make the build/cython/gtsam_eigency folder a python package
|
||||
configure_file(__init__.py.in ${OUTPUT_DIR}/__init__.py)
|
||||
|
||||
# include eigency headers
|
||||
include_directories(${EIGENCY_INCLUDE_DIR})
|
||||
|
||||
# Cythonize and build eigency
|
||||
message(STATUS "Cythonize and build eigency")
|
||||
# Important trick: use "../gtsam_eigency/conversions.pyx" to let cython know that the conversions module is
|
||||
# a part of the gtsam_eigency package and generate the function call import_gtsam_eigency__conversions()
|
||||
# in conversions_api.h correctly!
|
||||
cythonize(cythonize_eigency_conversions "../gtsam_eigency/conversions.pyx" "conversions"
|
||||
"${OUTPUT_DIR}" "${EIGENCY_INCLUDE_DIR}" "" "" "")
|
||||
cythonize(cythonize_eigency_core "../gtsam_eigency/core.pyx" "core"
|
||||
${OUTPUT_DIR} "${EIGENCY_INCLUDE_DIR}" "" "" "")
|
||||
|
||||
# Include Eigen headers:
|
||||
target_include_directories(cythonize_eigency_conversions PUBLIC
|
||||
$<BUILD_INTERFACE:${GTSAM_EIGEN_INCLUDE_FOR_BUILD}>
|
||||
$<INSTALL_INTERFACE:${GTSAM_EIGEN_INCLUDE_FOR_INSTALL}>
|
||||
)
|
||||
target_include_directories(cythonize_eigency_core PUBLIC
|
||||
$<BUILD_INTERFACE:${GTSAM_EIGEN_INCLUDE_FOR_BUILD}>
|
||||
$<INSTALL_INTERFACE:${GTSAM_EIGEN_INCLUDE_FOR_INSTALL}>
|
||||
)
|
||||
|
||||
add_dependencies(cythonize_eigency_core cythonize_eigency_conversions)
|
||||
add_custom_target(cythonize_eigency)
|
||||
add_dependencies(cythonize_eigency cythonize_eigency_conversions cythonize_eigency_core)
|
||||
|
||||
if(TARGET ${python_install_target})
|
||||
add_dependencies(${python_install_target} cythonize_eigency)
|
||||
endif()
|
|
@ -1,20 +0,0 @@
|
|||
Copyright (c) 2016 Wouter Boomsma
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
@ -1,13 +0,0 @@
|
|||
import os
|
||||
import numpy as np
|
||||
|
||||
__eigen_dir__ = "${GTSAM_EIGEN_INCLUDE_FOR_INSTALL}"
|
||||
|
||||
def get_includes(include_eigen=True):
|
||||
root = os.path.dirname(__file__)
|
||||
parent = os.path.join(root, "..")
|
||||
path = [root, parent, np.get_include()]
|
||||
if include_eigen:
|
||||
path.append(os.path.join(root, __eigen_dir__))
|
||||
return path
|
||||
|
|
@ -1,62 +0,0 @@
|
|||
cimport numpy as np
|
||||
|
||||
cdef api np.ndarray[double, ndim=2] ndarray_double_C(double *data, long rows, long cols, long outer_stride, long inner_stride)
|
||||
cdef api np.ndarray[double, ndim=2] ndarray_double_F(double *data, long rows, long cols, long outer_stride, long inner_stride)
|
||||
cdef api np.ndarray[double, ndim=2] ndarray_copy_double_C(const double *data, long rows, long cols, long outer_stride, long inner_stride)
|
||||
cdef api np.ndarray[double, ndim=2] ndarray_copy_double_F(const double *data, long rows, long cols, long outer_stride, long inner_stride)
|
||||
|
||||
cdef api np.ndarray[float, ndim=2] ndarray_float_C(float *data, long rows, long cols, long outer_stride, long inner_stride)
|
||||
cdef api np.ndarray[float, ndim=2] ndarray_float_F(float *data, long rows, long cols, long outer_stride, long inner_stride)
|
||||
cdef api np.ndarray[float, ndim=2] ndarray_copy_float_C(const float *data, long rows, long cols, long outer_stride, long inner_stride)
|
||||
cdef api np.ndarray[float, ndim=2] ndarray_copy_float_F(const float *data, long rows, long cols, long outer_stride, long inner_stride)
|
||||
|
||||
cdef api np.ndarray[long, ndim=2] ndarray_long_C(long *data, long rows, long cols, long outer_stride, long inner_stride)
|
||||
cdef api np.ndarray[long, ndim=2] ndarray_long_F(long *data, long rows, long cols, long outer_stride, long inner_stride)
|
||||
cdef api np.ndarray[long, ndim=2] ndarray_copy_long_C(const long *data, long rows, long cols, long outer_stride, long inner_stride)
|
||||
cdef api np.ndarray[long, ndim=2] ndarray_copy_long_F(const long *data, long rows, long cols, long outer_stride, long inner_stride)
|
||||
|
||||
cdef api np.ndarray[unsigned long, ndim=2] ndarray_ulong_C(unsigned long *data, long rows, long cols, long outer_stride, long inner_stride)
|
||||
cdef api np.ndarray[unsigned long, ndim=2] ndarray_ulong_F(unsigned long *data, long rows, long cols, long outer_stride, long inner_stride)
|
||||
cdef api np.ndarray[unsigned long, ndim=2] ndarray_copy_ulong_C(const unsigned long *data, long rows, long cols, long outer_stride, long inner_stride)
|
||||
cdef api np.ndarray[unsigned long, ndim=2] ndarray_copy_ulong_F(const unsigned long *data, long rows, long cols, long outer_stride, long inner_stride)
|
||||
|
||||
cdef api np.ndarray[int, ndim=2] ndarray_int_C(int *data, long rows, long cols, long outer_stride, long inner_stride)
|
||||
cdef api np.ndarray[int, ndim=2] ndarray_int_F(int *data, long rows, long cols, long outer_stride, long inner_stride)
|
||||
cdef api np.ndarray[int, ndim=2] ndarray_copy_int_C(const int *data, long rows, long cols, long outer_stride, long inner_stride)
|
||||
cdef api np.ndarray[int, ndim=2] ndarray_copy_int_F(const int *data, long rows, long cols, long outer_stride, long inner_stride)
|
||||
|
||||
cdef api np.ndarray[unsigned int, ndim=2] ndarray_uint_C(unsigned int *data, long rows, long cols, long outer_stride, long inner_stride)
|
||||
cdef api np.ndarray[unsigned int, ndim=2] ndarray_uint_F(unsigned int *data, long rows, long cols, long outer_stride, long inner_stride)
|
||||
cdef api np.ndarray[unsigned int, ndim=2] ndarray_copy_uint_C(const unsigned int *data, long rows, long cols, long outer_stride, long inner_stride)
|
||||
cdef api np.ndarray[unsigned int, ndim=2] ndarray_copy_uint_F(const unsigned int *data, long rows, long cols, long outer_stride, long inner_stride)
|
||||
|
||||
cdef api np.ndarray[short, ndim=2] ndarray_short_C(short *data, long rows, long cols, long outer_stride, long inner_stride)
|
||||
cdef api np.ndarray[short, ndim=2] ndarray_short_F(short *data, long rows, long cols, long outer_stride, long inner_stride)
|
||||
cdef api np.ndarray[short, ndim=2] ndarray_copy_short_C(const short *data, long rows, long cols, long outer_stride, long inner_stride)
|
||||
cdef api np.ndarray[short, ndim=2] ndarray_copy_short_F(const short *data, long rows, long cols, long outer_stride, long inner_stride)
|
||||
|
||||
cdef api np.ndarray[unsigned short, ndim=2] ndarray_ushort_C(unsigned short *data, long rows, long cols, long outer_stride, long inner_stride)
|
||||
cdef api np.ndarray[unsigned short, ndim=2] ndarray_ushort_F(unsigned short *data, long rows, long cols, long outer_stride, long inner_stride)
|
||||
cdef api np.ndarray[unsigned short, ndim=2] ndarray_copy_ushort_C(const unsigned short *data, long rows, long cols, long outer_stride, long inner_stride)
|
||||
cdef api np.ndarray[unsigned short, ndim=2] ndarray_copy_ushort_F(const unsigned short *data, long rows, long cols, long outer_stride, long inner_stride)
|
||||
|
||||
cdef api np.ndarray[signed char, ndim=2] ndarray_schar_C(signed char *data, long rows, long cols, long outer_stride, long inner_stride)
|
||||
cdef api np.ndarray[signed char, ndim=2] ndarray_schar_F(signed char *data, long rows, long cols, long outer_stride, long inner_stride)
|
||||
cdef api np.ndarray[signed char, ndim=2] ndarray_copy_schar_C(const signed char *data, long rows, long cols, long outer_stride, long inner_stride)
|
||||
cdef api np.ndarray[signed char, ndim=2] ndarray_copy_schar_F(const signed char *data, long rows, long cols, long outer_stride, long inner_stride)
|
||||
|
||||
cdef api np.ndarray[unsigned char, ndim=2] ndarray_uchar_C(unsigned char *data, long rows, long cols, long outer_stride, long inner_stride)
|
||||
cdef api np.ndarray[unsigned char, ndim=2] ndarray_uchar_F(unsigned char *data, long rows, long cols, long outer_stride, long inner_stride)
|
||||
cdef api np.ndarray[unsigned char, ndim=2] ndarray_copy_uchar_C(const unsigned char *data, long rows, long cols, long outer_stride, long inner_stride)
|
||||
cdef api np.ndarray[unsigned char, ndim=2] ndarray_copy_uchar_F(const unsigned char *data, long rows, long cols, long outer_stride, long inner_stride)
|
||||
|
||||
cdef api np.ndarray[np.complex128_t, ndim=2] ndarray_complex_double_C(np.complex128_t *data, long rows, long cols, long outer_stride, long inner_stride)
|
||||
cdef api np.ndarray[np.complex128_t, ndim=2] ndarray_complex_double_F(np.complex128_t *data, long rows, long cols, long outer_stride, long inner_stride)
|
||||
cdef api np.ndarray[np.complex128_t, ndim=2] ndarray_copy_complex_double_C(const np.complex128_t *data, long rows, long cols, long outer_stride, long inner_stride)
|
||||
cdef api np.ndarray[np.complex128_t, ndim=2] ndarray_copy_complex_double_F(const np.complex128_t *data, long rows, long cols, long outer_stride, long inner_stride)
|
||||
|
||||
cdef api np.ndarray[np.complex64_t, ndim=2] ndarray_complex_float_C(np.complex64_t *data, long rows, long cols, long outer_stride, long inner_stride)
|
||||
cdef api np.ndarray[np.complex64_t, ndim=2] ndarray_complex_float_F(np.complex64_t *data, long rows, long cols, long outer_stride, long inner_stride)
|
||||
cdef api np.ndarray[np.complex64_t, ndim=2] ndarray_copy_complex_float_C(const np.complex64_t *data, long rows, long cols, long outer_stride, long inner_stride)
|
||||
cdef api np.ndarray[np.complex64_t, ndim=2] ndarray_copy_complex_float_F(const np.complex64_t *data, long rows, long cols, long outer_stride, long inner_stride)
|
||||
|
|
@ -1,327 +0,0 @@
|
|||
cimport cython
|
||||
import numpy as np
|
||||
from numpy.lib.stride_tricks import as_strided
|
||||
|
||||
@cython.boundscheck(False)
|
||||
cdef np.ndarray[double, ndim=2] ndarray_double_C(double *data, long rows, long cols, long row_stride, long col_stride):
|
||||
cdef double[:,:] mem_view = <double[:rows,:cols]>data
|
||||
dtype = 'double'
|
||||
cdef int itemsize = np.dtype(dtype).itemsize
|
||||
return as_strided(np.asarray(mem_view, dtype=dtype, order="C"), strides=[row_stride*itemsize, col_stride*itemsize])
|
||||
@cython.boundscheck(False)
|
||||
cdef np.ndarray[double, ndim=2] ndarray_double_F(double *data, long rows, long cols, long row_stride, long col_stride):
|
||||
cdef double[::1,:] mem_view = <double[:rows:1,:cols]>data
|
||||
dtype = 'double'
|
||||
cdef int itemsize = np.dtype(dtype).itemsize
|
||||
return as_strided(np.asarray(mem_view, dtype=dtype, order="F"), strides=[row_stride*itemsize, col_stride*itemsize])
|
||||
|
||||
@cython.boundscheck(False)
|
||||
cdef np.ndarray[double, ndim=2] ndarray_copy_double_C(const double *data, long rows, long cols, long row_stride, long col_stride):
|
||||
cdef double[:,:] mem_view = <double[:rows,:cols]>data
|
||||
dtype = 'double'
|
||||
cdef int itemsize = np.dtype(dtype).itemsize
|
||||
return np.copy(as_strided(np.asarray(mem_view, dtype=dtype, order="C"), strides=[row_stride*itemsize, col_stride*itemsize]))
|
||||
@cython.boundscheck(False)
|
||||
cdef np.ndarray[double, ndim=2] ndarray_copy_double_F(const double *data, long rows, long cols, long row_stride, long col_stride):
|
||||
cdef double[::1,:] mem_view = <double[:rows:1,:cols]>data
|
||||
dtype = 'double'
|
||||
cdef int itemsize = np.dtype(dtype).itemsize
|
||||
return np.copy(as_strided(np.asarray(mem_view, dtype=dtype, order="F"), strides=[row_stride*itemsize, col_stride*itemsize]))
|
||||
|
||||
|
||||
@cython.boundscheck(False)
|
||||
cdef np.ndarray[float, ndim=2] ndarray_float_C(float *data, long rows, long cols, long row_stride, long col_stride):
|
||||
cdef float[:,:] mem_view = <float[:rows,:cols]>data
|
||||
dtype = 'float'
|
||||
cdef int itemsize = np.dtype(dtype).itemsize
|
||||
return as_strided(np.asarray(mem_view, dtype=dtype, order="C"), strides=[row_stride*itemsize, col_stride*itemsize])
|
||||
@cython.boundscheck(False)
|
||||
cdef np.ndarray[float, ndim=2] ndarray_float_F(float *data, long rows, long cols, long row_stride, long col_stride):
|
||||
cdef float[::1,:] mem_view = <float[:rows:1,:cols]>data
|
||||
dtype = 'float'
|
||||
cdef int itemsize = np.dtype(dtype).itemsize
|
||||
return as_strided(np.asarray(mem_view, dtype=dtype, order="F"), strides=[row_stride*itemsize, col_stride*itemsize])
|
||||
|
||||
@cython.boundscheck(False)
|
||||
cdef np.ndarray[float, ndim=2] ndarray_copy_float_C(const float *data, long rows, long cols, long row_stride, long col_stride):
|
||||
cdef float[:,:] mem_view = <float[:rows,:cols]>data
|
||||
dtype = 'float'
|
||||
cdef int itemsize = np.dtype(dtype).itemsize
|
||||
return np.copy(as_strided(np.asarray(mem_view, dtype=dtype, order="C"), strides=[row_stride*itemsize, col_stride*itemsize]))
|
||||
@cython.boundscheck(False)
|
||||
cdef np.ndarray[float, ndim=2] ndarray_copy_float_F(const float *data, long rows, long cols, long row_stride, long col_stride):
|
||||
cdef float[::1,:] mem_view = <float[:rows:1,:cols]>data
|
||||
dtype = 'float'
|
||||
cdef int itemsize = np.dtype(dtype).itemsize
|
||||
return np.copy(as_strided(np.asarray(mem_view, dtype=dtype, order="F"), strides=[row_stride*itemsize, col_stride*itemsize]))
|
||||
|
||||
|
||||
@cython.boundscheck(False)
|
||||
cdef np.ndarray[long, ndim=2] ndarray_long_C(long *data, long rows, long cols, long row_stride, long col_stride):
|
||||
cdef long[:,:] mem_view = <long[:rows,:cols]>data
|
||||
dtype = 'int_'
|
||||
cdef int itemsize = np.dtype(dtype).itemsize
|
||||
return as_strided(np.asarray(mem_view, dtype=dtype, order="C"), strides=[row_stride*itemsize, col_stride*itemsize])
|
||||
@cython.boundscheck(False)
|
||||
cdef np.ndarray[long, ndim=2] ndarray_long_F(long *data, long rows, long cols, long row_stride, long col_stride):
|
||||
cdef long[::1,:] mem_view = <long[:rows:1,:cols]>data
|
||||
dtype = 'int_'
|
||||
cdef int itemsize = np.dtype(dtype).itemsize
|
||||
return as_strided(np.asarray(mem_view, dtype=dtype, order="F"), strides=[row_stride*itemsize, col_stride*itemsize])
|
||||
|
||||
@cython.boundscheck(False)
|
||||
cdef np.ndarray[long, ndim=2] ndarray_copy_long_C(const long *data, long rows, long cols, long row_stride, long col_stride):
|
||||
cdef long[:,:] mem_view = <long[:rows,:cols]>data
|
||||
dtype = 'int_'
|
||||
cdef int itemsize = np.dtype(dtype).itemsize
|
||||
return np.copy(as_strided(np.asarray(mem_view, dtype=dtype, order="C"), strides=[row_stride*itemsize, col_stride*itemsize]))
|
||||
@cython.boundscheck(False)
|
||||
cdef np.ndarray[long, ndim=2] ndarray_copy_long_F(const long *data, long rows, long cols, long row_stride, long col_stride):
|
||||
cdef long[::1,:] mem_view = <long[:rows:1,:cols]>data
|
||||
dtype = 'int_'
|
||||
cdef int itemsize = np.dtype(dtype).itemsize
|
||||
return np.copy(as_strided(np.asarray(mem_view, dtype=dtype, order="F"), strides=[row_stride*itemsize, col_stride*itemsize]))
|
||||
|
||||
|
||||
@cython.boundscheck(False)
|
||||
cdef np.ndarray[unsigned long, ndim=2] ndarray_ulong_C(unsigned long *data, long rows, long cols, long row_stride, long col_stride):
|
||||
cdef unsigned long[:,:] mem_view = <unsigned long[:rows,:cols]>data
|
||||
dtype = 'uint'
|
||||
cdef int itemsize = np.dtype(dtype).itemsize
|
||||
return as_strided(np.asarray(mem_view, dtype=dtype, order="C"), strides=[row_stride*itemsize, col_stride*itemsize])
|
||||
@cython.boundscheck(False)
|
||||
cdef np.ndarray[unsigned long, ndim=2] ndarray_ulong_F(unsigned long *data, long rows, long cols, long row_stride, long col_stride):
|
||||
cdef unsigned long[::1,:] mem_view = <unsigned long[:rows:1,:cols]>data
|
||||
dtype = 'uint'
|
||||
cdef int itemsize = np.dtype(dtype).itemsize
|
||||
return as_strided(np.asarray(mem_view, dtype=dtype, order="F"), strides=[row_stride*itemsize, col_stride*itemsize])
|
||||
|
||||
@cython.boundscheck(False)
|
||||
cdef np.ndarray[unsigned long, ndim=2] ndarray_copy_ulong_C(const unsigned long *data, long rows, long cols, long row_stride, long col_stride):
|
||||
cdef unsigned long[:,:] mem_view = <unsigned long[:rows,:cols]>data
|
||||
dtype = 'uint'
|
||||
cdef int itemsize = np.dtype(dtype).itemsize
|
||||
return np.copy(as_strided(np.asarray(mem_view, dtype=dtype, order="C"), strides=[row_stride*itemsize, col_stride*itemsize]))
|
||||
@cython.boundscheck(False)
|
||||
cdef np.ndarray[unsigned long, ndim=2] ndarray_copy_ulong_F(const unsigned long *data, long rows, long cols, long row_stride, long col_stride):
|
||||
cdef unsigned long[::1,:] mem_view = <unsigned long[:rows:1,:cols]>data
|
||||
dtype = 'uint'
|
||||
cdef int itemsize = np.dtype(dtype).itemsize
|
||||
return np.copy(as_strided(np.asarray(mem_view, dtype=dtype, order="F"), strides=[row_stride*itemsize, col_stride*itemsize]))
|
||||
|
||||
|
||||
@cython.boundscheck(False)
|
||||
cdef np.ndarray[int, ndim=2] ndarray_int_C(int *data, long rows, long cols, long row_stride, long col_stride):
|
||||
cdef int[:,:] mem_view = <int[:rows,:cols]>data
|
||||
dtype = 'int'
|
||||
cdef int itemsize = np.dtype(dtype).itemsize
|
||||
return as_strided(np.asarray(mem_view, dtype=dtype, order="C"), strides=[row_stride*itemsize, col_stride*itemsize])
|
||||
@cython.boundscheck(False)
|
||||
cdef np.ndarray[int, ndim=2] ndarray_int_F(int *data, long rows, long cols, long row_stride, long col_stride):
|
||||
cdef int[::1,:] mem_view = <int[:rows:1,:cols]>data
|
||||
dtype = 'int'
|
||||
cdef int itemsize = np.dtype(dtype).itemsize
|
||||
return as_strided(np.asarray(mem_view, dtype=dtype, order="F"), strides=[row_stride*itemsize, col_stride*itemsize])
|
||||
|
||||
@cython.boundscheck(False)
|
||||
cdef np.ndarray[int, ndim=2] ndarray_copy_int_C(const int *data, long rows, long cols, long row_stride, long col_stride):
|
||||
cdef int[:,:] mem_view = <int[:rows,:cols]>data
|
||||
dtype = 'int'
|
||||
cdef int itemsize = np.dtype(dtype).itemsize
|
||||
return np.copy(as_strided(np.asarray(mem_view, dtype=dtype, order="C"), strides=[row_stride*itemsize, col_stride*itemsize]))
|
||||
@cython.boundscheck(False)
|
||||
cdef np.ndarray[int, ndim=2] ndarray_copy_int_F(const int *data, long rows, long cols, long row_stride, long col_stride):
|
||||
cdef int[::1,:] mem_view = <int[:rows:1,:cols]>data
|
||||
dtype = 'int'
|
||||
cdef int itemsize = np.dtype(dtype).itemsize
|
||||
return np.copy(as_strided(np.asarray(mem_view, dtype=dtype, order="F"), strides=[row_stride*itemsize, col_stride*itemsize]))
|
||||
|
||||
|
||||
@cython.boundscheck(False)
|
||||
cdef np.ndarray[unsigned int, ndim=2] ndarray_uint_C(unsigned int *data, long rows, long cols, long row_stride, long col_stride):
|
||||
cdef unsigned int[:,:] mem_view = <unsigned int[:rows,:cols]>data
|
||||
dtype = 'uint'
|
||||
cdef int itemsize = np.dtype(dtype).itemsize
|
||||
return as_strided(np.asarray(mem_view, dtype=dtype, order="C"), strides=[row_stride*itemsize, col_stride*itemsize])
|
||||
@cython.boundscheck(False)
|
||||
cdef np.ndarray[unsigned int, ndim=2] ndarray_uint_F(unsigned int *data, long rows, long cols, long row_stride, long col_stride):
|
||||
cdef unsigned int[::1,:] mem_view = <unsigned int[:rows:1,:cols]>data
|
||||
dtype = 'uint'
|
||||
cdef int itemsize = np.dtype(dtype).itemsize
|
||||
return as_strided(np.asarray(mem_view, dtype=dtype, order="F"), strides=[row_stride*itemsize, col_stride*itemsize])
|
||||
|
||||
@cython.boundscheck(False)
|
||||
cdef np.ndarray[unsigned int, ndim=2] ndarray_copy_uint_C(const unsigned int *data, long rows, long cols, long row_stride, long col_stride):
|
||||
cdef unsigned int[:,:] mem_view = <unsigned int[:rows,:cols]>data
|
||||
dtype = 'uint'
|
||||
cdef int itemsize = np.dtype(dtype).itemsize
|
||||
return np.copy(as_strided(np.asarray(mem_view, dtype=dtype, order="C"), strides=[row_stride*itemsize, col_stride*itemsize]))
|
||||
@cython.boundscheck(False)
|
||||
cdef np.ndarray[unsigned int, ndim=2] ndarray_copy_uint_F(const unsigned int *data, long rows, long cols, long row_stride, long col_stride):
|
||||
cdef unsigned int[::1,:] mem_view = <unsigned int[:rows:1,:cols]>data
|
||||
dtype = 'uint'
|
||||
cdef int itemsize = np.dtype(dtype).itemsize
|
||||
return np.copy(as_strided(np.asarray(mem_view, dtype=dtype, order="F"), strides=[row_stride*itemsize, col_stride*itemsize]))
|
||||
|
||||
|
||||
@cython.boundscheck(False)
|
||||
cdef np.ndarray[short, ndim=2] ndarray_short_C(short *data, long rows, long cols, long row_stride, long col_stride):
|
||||
cdef short[:,:] mem_view = <short[:rows,:cols]>data
|
||||
dtype = 'short'
|
||||
cdef int itemsize = np.dtype(dtype).itemsize
|
||||
return as_strided(np.asarray(mem_view, dtype=dtype, order="C"), strides=[row_stride*itemsize, col_stride*itemsize])
|
||||
@cython.boundscheck(False)
|
||||
cdef np.ndarray[short, ndim=2] ndarray_short_F(short *data, long rows, long cols, long row_stride, long col_stride):
|
||||
cdef short[::1,:] mem_view = <short[:rows:1,:cols]>data
|
||||
dtype = 'short'
|
||||
cdef int itemsize = np.dtype(dtype).itemsize
|
||||
return as_strided(np.asarray(mem_view, dtype=dtype, order="F"), strides=[row_stride*itemsize, col_stride*itemsize])
|
||||
|
||||
@cython.boundscheck(False)
|
||||
cdef np.ndarray[short, ndim=2] ndarray_copy_short_C(const short *data, long rows, long cols, long row_stride, long col_stride):
|
||||
cdef short[:,:] mem_view = <short[:rows,:cols]>data
|
||||
dtype = 'short'
|
||||
cdef int itemsize = np.dtype(dtype).itemsize
|
||||
return np.copy(as_strided(np.asarray(mem_view, dtype=dtype, order="C"), strides=[row_stride*itemsize, col_stride*itemsize]))
|
||||
@cython.boundscheck(False)
|
||||
cdef np.ndarray[short, ndim=2] ndarray_copy_short_F(const short *data, long rows, long cols, long row_stride, long col_stride):
|
||||
cdef short[::1,:] mem_view = <short[:rows:1,:cols]>data
|
||||
dtype = 'short'
|
||||
cdef int itemsize = np.dtype(dtype).itemsize
|
||||
return np.copy(as_strided(np.asarray(mem_view, dtype=dtype, order="F"), strides=[row_stride*itemsize, col_stride*itemsize]))
|
||||
|
||||
|
||||
@cython.boundscheck(False)
|
||||
cdef np.ndarray[unsigned short, ndim=2] ndarray_ushort_C(unsigned short *data, long rows, long cols, long row_stride, long col_stride):
|
||||
cdef unsigned short[:,:] mem_view = <unsigned short[:rows,:cols]>data
|
||||
dtype = 'ushort'
|
||||
cdef int itemsize = np.dtype(dtype).itemsize
|
||||
return as_strided(np.asarray(mem_view, dtype=dtype, order="C"), strides=[row_stride*itemsize, col_stride*itemsize])
|
||||
@cython.boundscheck(False)
|
||||
cdef np.ndarray[unsigned short, ndim=2] ndarray_ushort_F(unsigned short *data, long rows, long cols, long row_stride, long col_stride):
|
||||
cdef unsigned short[::1,:] mem_view = <unsigned short[:rows:1,:cols]>data
|
||||
dtype = 'ushort'
|
||||
cdef int itemsize = np.dtype(dtype).itemsize
|
||||
return as_strided(np.asarray(mem_view, dtype=dtype, order="F"), strides=[row_stride*itemsize, col_stride*itemsize])
|
||||
|
||||
@cython.boundscheck(False)
|
||||
cdef np.ndarray[unsigned short, ndim=2] ndarray_copy_ushort_C(const unsigned short *data, long rows, long cols, long row_stride, long col_stride):
|
||||
cdef unsigned short[:,:] mem_view = <unsigned short[:rows,:cols]>data
|
||||
dtype = 'ushort'
|
||||
cdef int itemsize = np.dtype(dtype).itemsize
|
||||
return np.copy(as_strided(np.asarray(mem_view, dtype=dtype, order="C"), strides=[row_stride*itemsize, col_stride*itemsize]))
|
||||
@cython.boundscheck(False)
|
||||
cdef np.ndarray[unsigned short, ndim=2] ndarray_copy_ushort_F(const unsigned short *data, long rows, long cols, long row_stride, long col_stride):
|
||||
cdef unsigned short[::1,:] mem_view = <unsigned short[:rows:1,:cols]>data
|
||||
dtype = 'ushort'
|
||||
cdef int itemsize = np.dtype(dtype).itemsize
|
||||
return np.copy(as_strided(np.asarray(mem_view, dtype=dtype, order="F"), strides=[row_stride*itemsize, col_stride*itemsize]))
|
||||
|
||||
|
||||
@cython.boundscheck(False)
|
||||
cdef np.ndarray[signed char, ndim=2] ndarray_schar_C(signed char *data, long rows, long cols, long row_stride, long col_stride):
|
||||
cdef signed char[:,:] mem_view = <signed char[:rows,:cols]>data
|
||||
dtype = 'int8'
|
||||
cdef int itemsize = np.dtype(dtype).itemsize
|
||||
return as_strided(np.asarray(mem_view, dtype=dtype, order="C"), strides=[row_stride*itemsize, col_stride*itemsize])
|
||||
@cython.boundscheck(False)
|
||||
cdef np.ndarray[signed char, ndim=2] ndarray_schar_F(signed char *data, long rows, long cols, long row_stride, long col_stride):
|
||||
cdef signed char[::1,:] mem_view = <signed char[:rows:1,:cols]>data
|
||||
dtype = 'int8'
|
||||
cdef int itemsize = np.dtype(dtype).itemsize
|
||||
return as_strided(np.asarray(mem_view, dtype=dtype, order="F"), strides=[row_stride*itemsize, col_stride*itemsize])
|
||||
|
||||
@cython.boundscheck(False)
|
||||
cdef np.ndarray[signed char, ndim=2] ndarray_copy_schar_C(const signed char *data, long rows, long cols, long row_stride, long col_stride):
|
||||
cdef signed char[:,:] mem_view = <signed char[:rows,:cols]>data
|
||||
dtype = 'int8'
|
||||
cdef int itemsize = np.dtype(dtype).itemsize
|
||||
return np.copy(as_strided(np.asarray(mem_view, dtype=dtype, order="C"), strides=[row_stride*itemsize, col_stride*itemsize]))
|
||||
@cython.boundscheck(False)
|
||||
cdef np.ndarray[signed char, ndim=2] ndarray_copy_schar_F(const signed char *data, long rows, long cols, long row_stride, long col_stride):
|
||||
cdef signed char[::1,:] mem_view = <signed char[:rows:1,:cols]>data
|
||||
dtype = 'int8'
|
||||
cdef int itemsize = np.dtype(dtype).itemsize
|
||||
return np.copy(as_strided(np.asarray(mem_view, dtype=dtype, order="F"), strides=[row_stride*itemsize, col_stride*itemsize]))
|
||||
|
||||
|
||||
@cython.boundscheck(False)
|
||||
cdef np.ndarray[unsigned char, ndim=2] ndarray_uchar_C(unsigned char *data, long rows, long cols, long row_stride, long col_stride):
|
||||
cdef unsigned char[:,:] mem_view = <unsigned char[:rows,:cols]>data
|
||||
dtype = 'uint8'
|
||||
cdef int itemsize = np.dtype(dtype).itemsize
|
||||
return as_strided(np.asarray(mem_view, dtype=dtype, order="C"), strides=[row_stride*itemsize, col_stride*itemsize])
|
||||
@cython.boundscheck(False)
|
||||
cdef np.ndarray[unsigned char, ndim=2] ndarray_uchar_F(unsigned char *data, long rows, long cols, long row_stride, long col_stride):
|
||||
cdef unsigned char[::1,:] mem_view = <unsigned char[:rows:1,:cols]>data
|
||||
dtype = 'uint8'
|
||||
cdef int itemsize = np.dtype(dtype).itemsize
|
||||
return as_strided(np.asarray(mem_view, dtype=dtype, order="F"), strides=[row_stride*itemsize, col_stride*itemsize])
|
||||
|
||||
@cython.boundscheck(False)
|
||||
cdef np.ndarray[unsigned char, ndim=2] ndarray_copy_uchar_C(const unsigned char *data, long rows, long cols, long row_stride, long col_stride):
|
||||
cdef unsigned char[:,:] mem_view = <unsigned char[:rows,:cols]>data
|
||||
dtype = 'uint8'
|
||||
cdef int itemsize = np.dtype(dtype).itemsize
|
||||
return np.copy(as_strided(np.asarray(mem_view, dtype=dtype, order="C"), strides=[row_stride*itemsize, col_stride*itemsize]))
|
||||
@cython.boundscheck(False)
|
||||
cdef np.ndarray[unsigned char, ndim=2] ndarray_copy_uchar_F(const unsigned char *data, long rows, long cols, long row_stride, long col_stride):
|
||||
cdef unsigned char[::1,:] mem_view = <unsigned char[:rows:1,:cols]>data
|
||||
dtype = 'uint8'
|
||||
cdef int itemsize = np.dtype(dtype).itemsize
|
||||
return np.copy(as_strided(np.asarray(mem_view, dtype=dtype, order="F"), strides=[row_stride*itemsize, col_stride*itemsize]))
|
||||
|
||||
|
||||
@cython.boundscheck(False)
|
||||
cdef np.ndarray[np.complex128_t, ndim=2] ndarray_complex_double_C(np.complex128_t *data, long rows, long cols, long row_stride, long col_stride):
|
||||
cdef np.complex128_t[:,:] mem_view = <np.complex128_t[:rows,:cols]>data
|
||||
dtype = 'complex128'
|
||||
cdef int itemsize = np.dtype(dtype).itemsize
|
||||
return as_strided(np.asarray(mem_view, dtype=dtype, order="C"), strides=[row_stride*itemsize, col_stride*itemsize])
|
||||
@cython.boundscheck(False)
|
||||
cdef np.ndarray[np.complex128_t, ndim=2] ndarray_complex_double_F(np.complex128_t *data, long rows, long cols, long row_stride, long col_stride):
|
||||
cdef np.complex128_t[::1,:] mem_view = <np.complex128_t[:rows:1,:cols]>data
|
||||
dtype = 'complex128'
|
||||
cdef int itemsize = np.dtype(dtype).itemsize
|
||||
return as_strided(np.asarray(mem_view, dtype=dtype, order="F"), strides=[row_stride*itemsize, col_stride*itemsize])
|
||||
|
||||
@cython.boundscheck(False)
|
||||
cdef np.ndarray[np.complex128_t, ndim=2] ndarray_copy_complex_double_C(const np.complex128_t *data, long rows, long cols, long row_stride, long col_stride):
|
||||
cdef np.complex128_t[:,:] mem_view = <np.complex128_t[:rows,:cols]>data
|
||||
dtype = 'complex128'
|
||||
cdef int itemsize = np.dtype(dtype).itemsize
|
||||
return np.copy(as_strided(np.asarray(mem_view, dtype=dtype, order="C"), strides=[row_stride*itemsize, col_stride*itemsize]))
|
||||
@cython.boundscheck(False)
|
||||
cdef np.ndarray[np.complex128_t, ndim=2] ndarray_copy_complex_double_F(const np.complex128_t *data, long rows, long cols, long row_stride, long col_stride):
|
||||
cdef np.complex128_t[::1,:] mem_view = <np.complex128_t[:rows:1,:cols]>data
|
||||
dtype = 'complex128'
|
||||
cdef int itemsize = np.dtype(dtype).itemsize
|
||||
return np.copy(as_strided(np.asarray(mem_view, dtype=dtype, order="F"), strides=[row_stride*itemsize, col_stride*itemsize]))
|
||||
|
||||
|
||||
@cython.boundscheck(False)
|
||||
cdef np.ndarray[np.complex64_t, ndim=2] ndarray_complex_float_C(np.complex64_t *data, long rows, long cols, long row_stride, long col_stride):
|
||||
cdef np.complex64_t[:,:] mem_view = <np.complex64_t[:rows,:cols]>data
|
||||
dtype = 'complex64'
|
||||
cdef int itemsize = np.dtype(dtype).itemsize
|
||||
return as_strided(np.asarray(mem_view, dtype=dtype, order="C"), strides=[row_stride*itemsize, col_stride*itemsize])
|
||||
@cython.boundscheck(False)
|
||||
cdef np.ndarray[np.complex64_t, ndim=2] ndarray_complex_float_F(np.complex64_t *data, long rows, long cols, long row_stride, long col_stride):
|
||||
cdef np.complex64_t[::1,:] mem_view = <np.complex64_t[:rows:1,:cols]>data
|
||||
dtype = 'complex64'
|
||||
cdef int itemsize = np.dtype(dtype).itemsize
|
||||
return as_strided(np.asarray(mem_view, dtype=dtype, order="F"), strides=[row_stride*itemsize, col_stride*itemsize])
|
||||
|
||||
@cython.boundscheck(False)
|
||||
cdef np.ndarray[np.complex64_t, ndim=2] ndarray_copy_complex_float_C(const np.complex64_t *data, long rows, long cols, long row_stride, long col_stride):
|
||||
cdef np.complex64_t[:,:] mem_view = <np.complex64_t[:rows,:cols]>data
|
||||
dtype = 'complex64'
|
||||
cdef int itemsize = np.dtype(dtype).itemsize
|
||||
return np.copy(as_strided(np.asarray(mem_view, dtype=dtype, order="C"), strides=[row_stride*itemsize, col_stride*itemsize]))
|
||||
@cython.boundscheck(False)
|
||||
cdef np.ndarray[np.complex64_t, ndim=2] ndarray_copy_complex_float_F(const np.complex64_t *data, long rows, long cols, long row_stride, long col_stride):
|
||||
cdef np.complex64_t[::1,:] mem_view = <np.complex64_t[:rows:1,:cols]>data
|
||||
dtype = 'complex64'
|
||||
cdef int itemsize = np.dtype(dtype).itemsize
|
||||
return np.copy(as_strided(np.asarray(mem_view, dtype=dtype, order="F"), strides=[row_stride*itemsize, col_stride*itemsize]))
|
||||
|
|
@ -1,917 +0,0 @@
|
|||
cimport cython
|
||||
cimport numpy as np
|
||||
|
||||
ctypedef signed char schar;
|
||||
ctypedef unsigned char uchar;
|
||||
|
||||
ctypedef fused dtype:
|
||||
uchar
|
||||
schar
|
||||
short
|
||||
int
|
||||
long
|
||||
float
|
||||
double
|
||||
|
||||
ctypedef fused DenseType:
|
||||
Matrix
|
||||
Array
|
||||
|
||||
ctypedef fused Rows:
|
||||
_1
|
||||
_2
|
||||
_3
|
||||
_4
|
||||
_5
|
||||
_6
|
||||
_7
|
||||
_8
|
||||
_9
|
||||
_10
|
||||
_11
|
||||
_12
|
||||
_13
|
||||
_14
|
||||
_15
|
||||
_16
|
||||
_17
|
||||
_18
|
||||
_19
|
||||
_20
|
||||
_21
|
||||
_22
|
||||
_23
|
||||
_24
|
||||
_25
|
||||
_26
|
||||
_27
|
||||
_28
|
||||
_29
|
||||
_30
|
||||
_31
|
||||
_32
|
||||
Dynamic
|
||||
|
||||
ctypedef Rows Cols
|
||||
ctypedef Rows StrideOuter
|
||||
ctypedef Rows StrideInner
|
||||
|
||||
ctypedef fused DenseTypeShort:
|
||||
Vector1i
|
||||
Vector2i
|
||||
Vector3i
|
||||
Vector4i
|
||||
VectorXi
|
||||
RowVector1i
|
||||
RowVector2i
|
||||
RowVector3i
|
||||
RowVector4i
|
||||
RowVectorXi
|
||||
Matrix1i
|
||||
Matrix2i
|
||||
Matrix3i
|
||||
Matrix4i
|
||||
MatrixXi
|
||||
Vector1f
|
||||
Vector2f
|
||||
Vector3f
|
||||
Vector4f
|
||||
VectorXf
|
||||
RowVector1f
|
||||
RowVector2f
|
||||
RowVector3f
|
||||
RowVector4f
|
||||
RowVectorXf
|
||||
Matrix1f
|
||||
Matrix2f
|
||||
Matrix3f
|
||||
Matrix4f
|
||||
MatrixXf
|
||||
Vector1d
|
||||
Vector2d
|
||||
Vector3d
|
||||
Vector4d
|
||||
VectorXd
|
||||
RowVector1d
|
||||
RowVector2d
|
||||
RowVector3d
|
||||
RowVector4d
|
||||
RowVectorXd
|
||||
Matrix1d
|
||||
Matrix2d
|
||||
Matrix3d
|
||||
Matrix4d
|
||||
MatrixXd
|
||||
Vector1cf
|
||||
Vector2cf
|
||||
Vector3cf
|
||||
Vector4cf
|
||||
VectorXcf
|
||||
RowVector1cf
|
||||
RowVector2cf
|
||||
RowVector3cf
|
||||
RowVector4cf
|
||||
RowVectorXcf
|
||||
Matrix1cf
|
||||
Matrix2cf
|
||||
Matrix3cf
|
||||
Matrix4cf
|
||||
MatrixXcf
|
||||
Vector1cd
|
||||
Vector2cd
|
||||
Vector3cd
|
||||
Vector4cd
|
||||
VectorXcd
|
||||
RowVector1cd
|
||||
RowVector2cd
|
||||
RowVector3cd
|
||||
RowVector4cd
|
||||
RowVectorXcd
|
||||
Matrix1cd
|
||||
Matrix2cd
|
||||
Matrix3cd
|
||||
Matrix4cd
|
||||
MatrixXcd
|
||||
Array22i
|
||||
Array23i
|
||||
Array24i
|
||||
Array2Xi
|
||||
Array32i
|
||||
Array33i
|
||||
Array34i
|
||||
Array3Xi
|
||||
Array42i
|
||||
Array43i
|
||||
Array44i
|
||||
Array4Xi
|
||||
ArrayX2i
|
||||
ArrayX3i
|
||||
ArrayX4i
|
||||
ArrayXXi
|
||||
Array2i
|
||||
Array3i
|
||||
Array4i
|
||||
ArrayXi
|
||||
Array22f
|
||||
Array23f
|
||||
Array24f
|
||||
Array2Xf
|
||||
Array32f
|
||||
Array33f
|
||||
Array34f
|
||||
Array3Xf
|
||||
Array42f
|
||||
Array43f
|
||||
Array44f
|
||||
Array4Xf
|
||||
ArrayX2f
|
||||
ArrayX3f
|
||||
ArrayX4f
|
||||
ArrayXXf
|
||||
Array2f
|
||||
Array3f
|
||||
Array4f
|
||||
ArrayXf
|
||||
Array22d
|
||||
Array23d
|
||||
Array24d
|
||||
Array2Xd
|
||||
Array32d
|
||||
Array33d
|
||||
Array34d
|
||||
Array3Xd
|
||||
Array42d
|
||||
Array43d
|
||||
Array44d
|
||||
Array4Xd
|
||||
ArrayX2d
|
||||
ArrayX3d
|
||||
ArrayX4d
|
||||
ArrayXXd
|
||||
Array2d
|
||||
Array3d
|
||||
Array4d
|
||||
ArrayXd
|
||||
Array22cf
|
||||
Array23cf
|
||||
Array24cf
|
||||
Array2Xcf
|
||||
Array32cf
|
||||
Array33cf
|
||||
Array34cf
|
||||
Array3Xcf
|
||||
Array42cf
|
||||
Array43cf
|
||||
Array44cf
|
||||
Array4Xcf
|
||||
ArrayX2cf
|
||||
ArrayX3cf
|
||||
ArrayX4cf
|
||||
ArrayXXcf
|
||||
Array2cf
|
||||
Array3cf
|
||||
Array4cf
|
||||
ArrayXcf
|
||||
Array22cd
|
||||
Array23cd
|
||||
Array24cd
|
||||
Array2Xcd
|
||||
Array32cd
|
||||
Array33cd
|
||||
Array34cd
|
||||
Array3Xcd
|
||||
Array42cd
|
||||
Array43cd
|
||||
Array44cd
|
||||
Array4Xcd
|
||||
ArrayX2cd
|
||||
ArrayX3cd
|
||||
ArrayX4cd
|
||||
ArrayXXcd
|
||||
Array2cd
|
||||
Array3cd
|
||||
Array4cd
|
||||
ArrayXcd
|
||||
|
||||
ctypedef fused StorageOrder:
|
||||
RowMajor
|
||||
ColMajor
|
||||
|
||||
ctypedef fused MapOptions:
|
||||
Aligned
|
||||
Unaligned
|
||||
|
||||
cdef extern from "eigency_cpp.h" namespace "eigency":
|
||||
|
||||
cdef cppclass _1 "1":
|
||||
pass
|
||||
|
||||
cdef cppclass _2 "2":
|
||||
pass
|
||||
|
||||
cdef cppclass _3 "3":
|
||||
pass
|
||||
|
||||
cdef cppclass _4 "4":
|
||||
pass
|
||||
|
||||
cdef cppclass _5 "5":
|
||||
pass
|
||||
|
||||
cdef cppclass _6 "6":
|
||||
pass
|
||||
|
||||
cdef cppclass _7 "7":
|
||||
pass
|
||||
|
||||
cdef cppclass _8 "8":
|
||||
pass
|
||||
|
||||
cdef cppclass _9 "9":
|
||||
pass
|
||||
|
||||
cdef cppclass _10 "10":
|
||||
pass
|
||||
|
||||
cdef cppclass _11 "11":
|
||||
pass
|
||||
|
||||
cdef cppclass _12 "12":
|
||||
pass
|
||||
|
||||
cdef cppclass _13 "13":
|
||||
pass
|
||||
|
||||
cdef cppclass _14 "14":
|
||||
pass
|
||||
|
||||
cdef cppclass _15 "15":
|
||||
pass
|
||||
|
||||
cdef cppclass _16 "16":
|
||||
pass
|
||||
|
||||
cdef cppclass _17 "17":
|
||||
pass
|
||||
|
||||
cdef cppclass _18 "18":
|
||||
pass
|
||||
|
||||
cdef cppclass _19 "19":
|
||||
pass
|
||||
|
||||
cdef cppclass _20 "20":
|
||||
pass
|
||||
|
||||
cdef cppclass _21 "21":
|
||||
pass
|
||||
|
||||
cdef cppclass _22 "22":
|
||||
pass
|
||||
|
||||
cdef cppclass _23 "23":
|
||||
pass
|
||||
|
||||
cdef cppclass _24 "24":
|
||||
pass
|
||||
|
||||
cdef cppclass _25 "25":
|
||||
pass
|
||||
|
||||
cdef cppclass _26 "26":
|
||||
pass
|
||||
|
||||
cdef cppclass _27 "27":
|
||||
pass
|
||||
|
||||
cdef cppclass _28 "28":
|
||||
pass
|
||||
|
||||
cdef cppclass _29 "29":
|
||||
pass
|
||||
|
||||
cdef cppclass _30 "30":
|
||||
pass
|
||||
|
||||
cdef cppclass _31 "31":
|
||||
pass
|
||||
|
||||
cdef cppclass _32 "32":
|
||||
pass
|
||||
|
||||
cdef cppclass PlainObjectBase:
|
||||
pass
|
||||
|
||||
cdef cppclass Map[DenseTypeShort](PlainObjectBase):
|
||||
Map() except +
|
||||
Map(np.ndarray array) except +
|
||||
|
||||
cdef cppclass FlattenedMap[DenseType, dtype, Rows, Cols]:
|
||||
FlattenedMap() except +
|
||||
FlattenedMap(np.ndarray array) except +
|
||||
|
||||
cdef cppclass FlattenedMapWithOrder "eigency::FlattenedMap" [DenseType, dtype, Rows, Cols, StorageOrder]:
|
||||
FlattenedMapWithOrder() except +
|
||||
FlattenedMapWithOrder(np.ndarray array) except +
|
||||
|
||||
cdef cppclass FlattenedMapWithStride "eigency::FlattenedMap" [DenseType, dtype, Rows, Cols, StorageOrder, MapOptions, StrideOuter, StrideInner]:
|
||||
FlattenedMapWithStride() except +
|
||||
FlattenedMapWithStride(np.ndarray array) except +
|
||||
|
||||
cdef np.ndarray ndarray_view(PlainObjectBase &)
|
||||
cdef np.ndarray ndarray_copy(PlainObjectBase &)
|
||||
cdef np.ndarray ndarray(PlainObjectBase &)
|
||||
|
||||
|
||||
cdef extern from "eigency_cpp.h" namespace "Eigen":
|
||||
|
||||
cdef cppclass Dynamic:
|
||||
pass
|
||||
|
||||
cdef cppclass RowMajor:
|
||||
pass
|
||||
|
||||
cdef cppclass ColMajor:
|
||||
pass
|
||||
|
||||
cdef cppclass Aligned:
|
||||
pass
|
||||
|
||||
cdef cppclass Unaligned:
|
||||
pass
|
||||
|
||||
cdef cppclass Matrix(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass Array(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass VectorXd(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass Vector1i(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass Vector2i(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass Vector3i(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass Vector4i(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass VectorXi(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass RowVector1i(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass RowVector2i(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass RowVector3i(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass RowVector4i(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass RowVectorXi(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass Matrix1i(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass Matrix2i(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass Matrix3i(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass Matrix4i(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass MatrixXi(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass Vector1f(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass Vector2f(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass Vector3f(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass Vector4f(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass VectorXf(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass RowVector1f(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass RowVector2f(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass RowVector3f(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass RowVector4f(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass RowVectorXf(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass Matrix1f(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass Matrix2f(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass Matrix3f(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass Matrix4f(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass MatrixXf(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass Vector1d(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass Vector2d(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass Vector3d(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass Vector4d(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass VectorXd(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass RowVector1d(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass RowVector2d(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass RowVector3d(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass RowVector4d(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass RowVectorXd(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass Matrix1d(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass Matrix2d(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass Matrix3d(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass Matrix4d(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass MatrixXd(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass Vector1cf(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass Vector2cf(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass Vector3cf(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass Vector4cf(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass VectorXcf(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass RowVector1cf(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass RowVector2cf(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass RowVector3cf(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass RowVector4cf(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass RowVectorXcf(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass Matrix1cf(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass Matrix2cf(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass Matrix3cf(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass Matrix4cf(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass MatrixXcf(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass Vector1cd(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass Vector2cd(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass Vector3cd(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass Vector4cd(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass VectorXcd(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass RowVector1cd(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass RowVector2cd(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass RowVector3cd(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass RowVector4cd(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass RowVectorXcd(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass Matrix1cd(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass Matrix2cd(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass Matrix3cd(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass Matrix4cd(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass MatrixXcd(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass Array22i(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass Array23i(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass Array24i(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass Array2Xi(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass Array32i(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass Array33i(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass Array34i(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass Array3Xi(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass Array42i(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass Array43i(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass Array44i(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass Array4Xi(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass ArrayX2i(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass ArrayX3i(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass ArrayX4i(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass ArrayXXi(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass Array2i(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass Array3i(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass Array4i(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass ArrayXi(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass Array22f(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass Array23f(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass Array24f(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass Array2Xf(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass Array32f(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass Array33f(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass Array34f(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass Array3Xf(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass Array42f(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass Array43f(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass Array44f(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass Array4Xf(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass ArrayX2f(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass ArrayX3f(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass ArrayX4f(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass ArrayXXf(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass Array2f(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass Array3f(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass Array4f(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass ArrayXf(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass Array22d(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass Array23d(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass Array24d(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass Array2Xd(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass Array32d(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass Array33d(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass Array34d(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass Array3Xd(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass Array42d(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass Array43d(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass Array44d(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass Array4Xd(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass ArrayX2d(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass ArrayX3d(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass ArrayX4d(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass ArrayXXd(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass Array2d(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass Array3d(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass Array4d(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass ArrayXd(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass Array22cf(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass Array23cf(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass Array24cf(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass Array2Xcf(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass Array32cf(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass Array33cf(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass Array34cf(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass Array3Xcf(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass Array42cf(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass Array43cf(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass Array44cf(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass Array4Xcf(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass ArrayX2cf(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass ArrayX3cf(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass ArrayX4cf(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass ArrayXXcf(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass Array2cf(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass Array3cf(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass Array4cf(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass ArrayXcf(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass Array22cd(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass Array23cd(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass Array24cd(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass Array2Xcd(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass Array32cd(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass Array33cd(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass Array34cd(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass Array3Xcd(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass Array42cd(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass Array43cd(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass Array44cd(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass Array4Xcd(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass ArrayX2cd(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass ArrayX3cd(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass ArrayX4cd(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass ArrayXXcd(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass Array2cd(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass Array3cd(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass Array4cd(PlainObjectBase):
|
||||
pass
|
||||
|
||||
cdef cppclass ArrayXcd(PlainObjectBase):
|
||||
pass
|
||||
|
||||
|
|
@ -1 +0,0 @@
|
|||
|
|
@ -1,504 +0,0 @@
|
|||
#include <Eigen/Dense>
|
||||
|
||||
#include <iostream>
|
||||
#include <stdexcept>
|
||||
#include <complex>
|
||||
|
||||
typedef ::std::complex< double > __pyx_t_double_complex;
|
||||
typedef ::std::complex< float > __pyx_t_float_complex;
|
||||
|
||||
#include "conversions_api.h"
|
||||
|
||||
#ifndef EIGENCY_CPP
|
||||
#define EIGENCY_CPP
|
||||
|
||||
namespace eigency {
|
||||
|
||||
template<typename Scalar>
|
||||
inline PyArrayObject *_ndarray_view(Scalar *, long rows, long cols, bool is_row_major, long outer_stride=0, long inner_stride=0);
|
||||
template<typename Scalar>
|
||||
inline PyArrayObject *_ndarray_copy(const Scalar *, long rows, long cols, bool is_row_major, long outer_stride=0, long inner_stride=0);
|
||||
|
||||
// Strides:
|
||||
// Eigen and numpy differ in their way of dealing with strides. Eigen has the concept of outer and
|
||||
// inner strides, which are dependent on whether the array/matrix is row-major of column-major:
|
||||
// Inner stride: denotes the offset between succeeding elements in each row (row-major) or column (column-major).
|
||||
// Outer stride: denotes the offset between succeeding rows (row-major) or succeeding columns (column-major).
|
||||
// In contrast, numpy's stride is simply a measure of how fast each dimension should be incremented.
|
||||
// Consequently, a switch in numpy storage order from row-major to column-major involves a switch
|
||||
// in strides, while it does not affect the stride in Eigen.
|
||||
template<>
|
||||
inline PyArrayObject *_ndarray_view<double>(double *data, long rows, long cols, bool is_row_major, long outer_stride, long inner_stride) {
|
||||
if (is_row_major) {
|
||||
// Eigen row-major mode: row_stride=outer_stride, and col_stride=inner_stride
|
||||
// If no stride is given, the row_stride is set to the number of columns.
|
||||
return ndarray_double_C(data, rows, cols, outer_stride>0?outer_stride:cols, inner_stride>0?inner_stride:1);
|
||||
} else {
|
||||
// Eigen column-major mode: row_stride=outer_stride, and col_stride=inner_stride
|
||||
// If no stride is given, the cow_stride is set to the number of rows.
|
||||
return ndarray_double_F(data, rows, cols, inner_stride>0?inner_stride:1, outer_stride>0?outer_stride:rows);
|
||||
}
|
||||
}
|
||||
template<>
|
||||
inline PyArrayObject *_ndarray_copy<double>(const double *data, long rows, long cols, bool is_row_major, long outer_stride, long inner_stride) {
|
||||
if (is_row_major)
|
||||
return ndarray_copy_double_C(data, rows, cols, outer_stride>0?outer_stride:cols, inner_stride>0?inner_stride:1);
|
||||
else
|
||||
return ndarray_copy_double_F(data, rows, cols, inner_stride>0?inner_stride:1, outer_stride>0?outer_stride:rows);
|
||||
}
|
||||
|
||||
template<>
|
||||
inline PyArrayObject *_ndarray_view<float>(float *data, long rows, long cols, bool is_row_major, long outer_stride, long inner_stride) {
|
||||
if (is_row_major)
|
||||
return ndarray_float_C(data, rows, cols, outer_stride>0?outer_stride:cols, inner_stride>0?inner_stride:1);
|
||||
else
|
||||
return ndarray_float_F(data, rows, cols, inner_stride>0?inner_stride:1, outer_stride>0?outer_stride:rows);
|
||||
}
|
||||
template<>
|
||||
inline PyArrayObject *_ndarray_copy<float>(const float *data, long rows, long cols, bool is_row_major, long outer_stride, long inner_stride) {
|
||||
if (is_row_major)
|
||||
return ndarray_copy_float_C(data, rows, cols, outer_stride>0?outer_stride:cols, inner_stride>0?inner_stride:1);
|
||||
else
|
||||
return ndarray_copy_float_F(data, rows, cols, inner_stride>0?inner_stride:1, outer_stride>0?outer_stride:rows);
|
||||
}
|
||||
|
||||
template<>
|
||||
inline PyArrayObject *_ndarray_view<long>(long *data, long rows, long cols, bool is_row_major, long outer_stride, long inner_stride) {
|
||||
if (is_row_major)
|
||||
return ndarray_long_C(data, rows, cols, outer_stride>0?outer_stride:cols, inner_stride>0?inner_stride:1);
|
||||
else
|
||||
return ndarray_long_F(data, rows, cols, inner_stride>0?inner_stride:1, outer_stride>0?outer_stride:rows);
|
||||
}
|
||||
template<>
|
||||
inline PyArrayObject *_ndarray_copy<long>(const long *data, long rows, long cols, bool is_row_major, long outer_stride, long inner_stride) {
|
||||
if (is_row_major)
|
||||
return ndarray_copy_long_C(data, rows, cols, outer_stride>0?outer_stride:cols, inner_stride>0?inner_stride:1);
|
||||
else
|
||||
return ndarray_copy_long_F(data, rows, cols, inner_stride>0?inner_stride:1, outer_stride>0?outer_stride:rows);
|
||||
}
|
||||
|
||||
template<>
|
||||
inline PyArrayObject *_ndarray_view<unsigned long>(unsigned long *data, long rows, long cols, bool is_row_major, long outer_stride, long inner_stride) {
|
||||
if (is_row_major)
|
||||
return ndarray_ulong_C(data, rows, cols, outer_stride>0?outer_stride:cols, inner_stride>0?inner_stride:1);
|
||||
else
|
||||
return ndarray_ulong_F(data, rows, cols, inner_stride>0?inner_stride:1, outer_stride>0?outer_stride:rows);
|
||||
}
|
||||
template<>
|
||||
inline PyArrayObject *_ndarray_copy<unsigned long>(const unsigned long *data, long rows, long cols, bool is_row_major, long outer_stride, long inner_stride) {
|
||||
if (is_row_major)
|
||||
return ndarray_copy_ulong_C(data, rows, cols, outer_stride>0?outer_stride:cols, inner_stride>0?inner_stride:1);
|
||||
else
|
||||
return ndarray_copy_ulong_F(data, rows, cols, inner_stride>0?inner_stride:1, outer_stride>0?outer_stride:rows);
|
||||
}
|
||||
|
||||
template<>
|
||||
inline PyArrayObject *_ndarray_view<int>(int *data, long rows, long cols, bool is_row_major, long outer_stride, long inner_stride) {
|
||||
if (is_row_major)
|
||||
return ndarray_int_C(data, rows, cols, outer_stride>0?outer_stride:cols, inner_stride>0?inner_stride:1);
|
||||
else
|
||||
return ndarray_int_F(data, rows, cols, inner_stride>0?inner_stride:1, outer_stride>0?outer_stride:rows);
|
||||
}
|
||||
template<>
|
||||
inline PyArrayObject *_ndarray_copy<int>(const int *data, long rows, long cols, bool is_row_major, long outer_stride, long inner_stride) {
|
||||
if (is_row_major)
|
||||
return ndarray_copy_int_C(data, rows, cols, outer_stride>0?outer_stride:cols, inner_stride>0?inner_stride:1);
|
||||
else
|
||||
return ndarray_copy_int_F(data, rows, cols, inner_stride>0?inner_stride:1, outer_stride>0?outer_stride:rows);
|
||||
}
|
||||
|
||||
template<>
|
||||
inline PyArrayObject *_ndarray_view<unsigned int>(unsigned int *data, long rows, long cols, bool is_row_major, long outer_stride, long inner_stride) {
|
||||
if (is_row_major)
|
||||
return ndarray_uint_C(data, rows, cols, outer_stride>0?outer_stride:cols, inner_stride>0?inner_stride:1);
|
||||
else
|
||||
return ndarray_uint_F(data, rows, cols, inner_stride>0?inner_stride:1, outer_stride>0?outer_stride:rows);
|
||||
}
|
||||
template<>
|
||||
inline PyArrayObject *_ndarray_copy<unsigned int>(const unsigned int *data, long rows, long cols, bool is_row_major, long outer_stride, long inner_stride) {
|
||||
if (is_row_major)
|
||||
return ndarray_copy_uint_C(data, rows, cols, outer_stride>0?outer_stride:cols, inner_stride>0?inner_stride:1);
|
||||
else
|
||||
return ndarray_copy_uint_F(data, rows, cols, inner_stride>0?inner_stride:1, outer_stride>0?outer_stride:rows);
|
||||
}
|
||||
|
||||
template<>
|
||||
inline PyArrayObject *_ndarray_view<short>(short *data, long rows, long cols, bool is_row_major, long outer_stride, long inner_stride) {
|
||||
if (is_row_major)
|
||||
return ndarray_short_C(data, rows, cols, outer_stride>0?outer_stride:cols, inner_stride>0?inner_stride:1);
|
||||
else
|
||||
return ndarray_short_F(data, rows, cols, inner_stride>0?inner_stride:1, outer_stride>0?outer_stride:rows);
|
||||
}
|
||||
template<>
|
||||
inline PyArrayObject *_ndarray_copy<short>(const short *data, long rows, long cols, bool is_row_major, long outer_stride, long inner_stride) {
|
||||
if (is_row_major)
|
||||
return ndarray_copy_short_C(data, rows, cols, outer_stride>0?outer_stride:cols, inner_stride>0?inner_stride:1);
|
||||
else
|
||||
return ndarray_copy_short_F(data, rows, cols, inner_stride>0?inner_stride:1, outer_stride>0?outer_stride:rows);
|
||||
}
|
||||
|
||||
template<>
|
||||
inline PyArrayObject *_ndarray_view<unsigned short>(unsigned short *data, long rows, long cols, bool is_row_major, long outer_stride, long inner_stride) {
|
||||
if (is_row_major)
|
||||
return ndarray_ushort_C(data, rows, cols, outer_stride>0?outer_stride:cols, inner_stride>0?inner_stride:1);
|
||||
else
|
||||
return ndarray_ushort_F(data, rows, cols, inner_stride>0?inner_stride:1, outer_stride>0?outer_stride:rows);
|
||||
}
|
||||
template<>
|
||||
inline PyArrayObject *_ndarray_copy<unsigned short>(const unsigned short *data, long rows, long cols, bool is_row_major, long outer_stride, long inner_stride) {
|
||||
if (is_row_major)
|
||||
return ndarray_copy_ushort_C(data, rows, cols, outer_stride>0?outer_stride:cols, inner_stride>0?inner_stride:1);
|
||||
else
|
||||
return ndarray_copy_ushort_F(data, rows, cols, inner_stride>0?inner_stride:1, outer_stride>0?outer_stride:rows);
|
||||
}
|
||||
|
||||
template<>
|
||||
inline PyArrayObject *_ndarray_view<signed char>(signed char *data, long rows, long cols, bool is_row_major, long outer_stride, long inner_stride) {
|
||||
if (is_row_major)
|
||||
return ndarray_schar_C(data, rows, cols, outer_stride>0?outer_stride:cols, inner_stride>0?inner_stride:1);
|
||||
else
|
||||
return ndarray_schar_F(data, rows, cols, inner_stride>0?inner_stride:1, outer_stride>0?outer_stride:rows);
|
||||
}
|
||||
template<>
|
||||
inline PyArrayObject *_ndarray_copy<signed char>(const signed char *data, long rows, long cols, bool is_row_major, long outer_stride, long inner_stride) {
|
||||
if (is_row_major)
|
||||
return ndarray_copy_schar_C(data, rows, cols, outer_stride>0?outer_stride:cols, inner_stride>0?inner_stride:1);
|
||||
else
|
||||
return ndarray_copy_schar_F(data, rows, cols, inner_stride>0?inner_stride:1, outer_stride>0?outer_stride:rows);
|
||||
}
|
||||
|
||||
template<>
|
||||
inline PyArrayObject *_ndarray_view<unsigned char>(unsigned char *data, long rows, long cols, bool is_row_major, long outer_stride, long inner_stride) {
|
||||
if (is_row_major)
|
||||
return ndarray_uchar_C(data, rows, cols, outer_stride>0?outer_stride:cols, inner_stride>0?inner_stride:1);
|
||||
else
|
||||
return ndarray_uchar_F(data, rows, cols, inner_stride>0?inner_stride:1, outer_stride>0?outer_stride:rows);
|
||||
}
|
||||
template<>
|
||||
inline PyArrayObject *_ndarray_copy<unsigned char>(const unsigned char *data, long rows, long cols, bool is_row_major, long outer_stride, long inner_stride) {
|
||||
if (is_row_major)
|
||||
return ndarray_copy_uchar_C(data, rows, cols, outer_stride>0?outer_stride:cols, inner_stride>0?inner_stride:1);
|
||||
else
|
||||
return ndarray_copy_uchar_F(data, rows, cols, inner_stride>0?inner_stride:1, outer_stride>0?outer_stride:rows);
|
||||
}
|
||||
|
||||
template<>
|
||||
inline PyArrayObject *_ndarray_view<std::complex<double> >(std::complex<double> *data, long rows, long cols, bool is_row_major, long outer_stride, long inner_stride) {
|
||||
if (is_row_major)
|
||||
return ndarray_complex_double_C(data, rows, cols, outer_stride>0?outer_stride:cols, inner_stride>0?inner_stride:1);
|
||||
else
|
||||
return ndarray_complex_double_F(data, rows, cols, inner_stride>0?inner_stride:1, outer_stride>0?outer_stride:rows);
|
||||
}
|
||||
template<>
|
||||
inline PyArrayObject *_ndarray_copy<std::complex<double> >(const std::complex<double> *data, long rows, long cols, bool is_row_major, long outer_stride, long inner_stride) {
|
||||
if (is_row_major)
|
||||
return ndarray_copy_complex_double_C(data, rows, cols, outer_stride>0?outer_stride:cols, inner_stride>0?inner_stride:1);
|
||||
else
|
||||
return ndarray_copy_complex_double_F(data, rows, cols, inner_stride>0?inner_stride:1, outer_stride>0?outer_stride:rows);
|
||||
}
|
||||
|
||||
template<>
|
||||
inline PyArrayObject *_ndarray_view<std::complex<float> >(std::complex<float> *data, long rows, long cols, bool is_row_major, long outer_stride, long inner_stride) {
|
||||
if (is_row_major)
|
||||
return ndarray_complex_float_C(data, rows, cols, outer_stride>0?outer_stride:cols, inner_stride>0?inner_stride:1);
|
||||
else
|
||||
return ndarray_complex_float_F(data, rows, cols, inner_stride>0?inner_stride:1, outer_stride>0?outer_stride:rows);
|
||||
}
|
||||
template<>
|
||||
inline PyArrayObject *_ndarray_copy<std::complex<float> >(const std::complex<float> *data, long rows, long cols, bool is_row_major, long outer_stride, long inner_stride) {
|
||||
if (is_row_major)
|
||||
return ndarray_copy_complex_float_C(data, rows, cols, outer_stride>0?outer_stride:cols, inner_stride>0?inner_stride:1);
|
||||
else
|
||||
return ndarray_copy_complex_float_F(data, rows, cols, inner_stride>0?inner_stride:1, outer_stride>0?outer_stride:rows);
|
||||
}
|
||||
|
||||
|
||||
template <typename Derived>
|
||||
inline PyArrayObject *ndarray(Eigen::PlainObjectBase<Derived> &m) {
|
||||
import_gtsam_eigency__conversions();
|
||||
return _ndarray_view(m.data(), m.rows(), m.cols(), m.IsRowMajor);
|
||||
}
|
||||
// If C++11 is available, check if m is an r-value reference, in
|
||||
// which case a copy should always be made
|
||||
#if __cplusplus >= 201103L
|
||||
template <typename Derived>
|
||||
inline PyArrayObject *ndarray(Eigen::PlainObjectBase<Derived> &&m) {
|
||||
import_gtsam_eigency__conversions();
|
||||
return _ndarray_copy(m.data(), m.rows(), m.cols(), m.IsRowMajor);
|
||||
}
|
||||
#endif
|
||||
template <typename Derived>
|
||||
inline PyArrayObject *ndarray(const Eigen::PlainObjectBase<Derived> &m) {
|
||||
import_gtsam_eigency__conversions();
|
||||
return _ndarray_copy(m.data(), m.rows(), m.cols(), m.IsRowMajor);
|
||||
}
|
||||
template <typename Derived>
|
||||
inline PyArrayObject *ndarray_view(Eigen::PlainObjectBase<Derived> &m) {
|
||||
import_gtsam_eigency__conversions();
|
||||
return _ndarray_view(m.data(), m.rows(), m.cols(), m.IsRowMajor);
|
||||
}
|
||||
template <typename Derived>
|
||||
inline PyArrayObject *ndarray_view(const Eigen::PlainObjectBase<Derived> &m) {
|
||||
import_gtsam_eigency__conversions();
|
||||
return _ndarray_view(const_cast<typename Derived::Scalar*>(m.data()), m.rows(), m.cols(), m.IsRowMajor);
|
||||
}
|
||||
template <typename Derived>
|
||||
inline PyArrayObject *ndarray_copy(const Eigen::PlainObjectBase<Derived> &m) {
|
||||
import_gtsam_eigency__conversions();
|
||||
return _ndarray_copy(m.data(), m.rows(), m.cols(), m.IsRowMajor);
|
||||
}
|
||||
|
||||
template <typename Derived, int MapOptions, typename Stride>
|
||||
inline PyArrayObject *ndarray(Eigen::Map<Derived, MapOptions, Stride> &m) {
|
||||
import_gtsam_eigency__conversions();
|
||||
return _ndarray_view(m.data(), m.rows(), m.cols(), m.IsRowMajor, m.outerStride(), m.innerStride());
|
||||
}
|
||||
template <typename Derived, int MapOptions, typename Stride>
|
||||
inline PyArrayObject *ndarray(const Eigen::Map<Derived, MapOptions, Stride> &m) {
|
||||
import_gtsam_eigency__conversions();
|
||||
// Since this is a map, we assume that ownership is correctly taken care
|
||||
// of, and we avoid taking a copy
|
||||
return _ndarray_view(const_cast<typename Derived::Scalar*>(m.data()), m.rows(), m.cols(), m.IsRowMajor, m.outerStride(), m.innerStride());
|
||||
}
|
||||
template <typename Derived, int MapOptions, typename Stride>
|
||||
inline PyArrayObject *ndarray_view(Eigen::Map<Derived, MapOptions, Stride> &m) {
|
||||
import_gtsam_eigency__conversions();
|
||||
return _ndarray_view(m.data(), m.rows(), m.cols(), m.IsRowMajor, m.outerStride(), m.innerStride());
|
||||
}
|
||||
template <typename Derived, int MapOptions, typename Stride>
|
||||
inline PyArrayObject *ndarray_view(const Eigen::Map<Derived, MapOptions, Stride> &m) {
|
||||
import_gtsam_eigency__conversions();
|
||||
return _ndarray_view(const_cast<typename Derived::Scalar*>(m.data()), m.rows(), m.cols(), m.IsRowMajor, m.outerStride(), m.innerStride());
|
||||
}
|
||||
template <typename Derived, int MapOptions, typename Stride>
|
||||
inline PyArrayObject *ndarray_copy(const Eigen::Map<Derived, MapOptions, Stride> &m) {
|
||||
import_gtsam_eigency__conversions();
|
||||
return _ndarray_copy(m.data(), m.rows(), m.cols(), m.IsRowMajor, m.outerStride(), m.innerStride());
|
||||
}
|
||||
|
||||
|
||||
template <typename MatrixType,
|
||||
int _MapOptions = Eigen::Unaligned,
|
||||
typename _StrideType=Eigen::Stride<0,0> >
|
||||
class MapBase: public Eigen::Map<MatrixType, _MapOptions, _StrideType> {
|
||||
public:
|
||||
typedef Eigen::Map<MatrixType, _MapOptions, _StrideType> Base;
|
||||
typedef typename Base::Scalar Scalar;
|
||||
|
||||
MapBase(Scalar* data,
|
||||
long rows,
|
||||
long cols,
|
||||
_StrideType stride=_StrideType())
|
||||
: Base(data,
|
||||
// If both dimensions are dynamic or dimensions match, accept dimensions as they are
|
||||
((Base::RowsAtCompileTime==Eigen::Dynamic && Base::ColsAtCompileTime==Eigen::Dynamic) ||
|
||||
(Base::RowsAtCompileTime==rows && Base::ColsAtCompileTime==cols))
|
||||
? rows
|
||||
// otherwise, test if swapping them makes them fit
|
||||
: ((Base::RowsAtCompileTime==cols || Base::ColsAtCompileTime==rows)
|
||||
? cols
|
||||
: rows),
|
||||
((Base::RowsAtCompileTime==Eigen::Dynamic && Base::ColsAtCompileTime==Eigen::Dynamic) ||
|
||||
(Base::RowsAtCompileTime==rows && Base::ColsAtCompileTime==cols))
|
||||
? cols
|
||||
: ((Base::RowsAtCompileTime==cols || Base::ColsAtCompileTime==rows)
|
||||
? rows
|
||||
: cols),
|
||||
stride
|
||||
) {}
|
||||
|
||||
MapBase &operator=(const MatrixType &other) {
|
||||
Base::operator=(other);
|
||||
return *this;
|
||||
}
|
||||
|
||||
virtual ~MapBase() { }
|
||||
};
|
||||
|
||||
|
||||
template <template<class,int,int,int,int,int> class EigencyDenseBase,
|
||||
typename Scalar,
|
||||
int _Rows, int _Cols,
|
||||
int _Options = Eigen::AutoAlign |
|
||||
#if defined(__GNUC__) && __GNUC__==3 && __GNUC_MINOR__==4
|
||||
// workaround a bug in at least gcc 3.4.6
|
||||
// the innermost ?: ternary operator is misparsed. We write it slightly
|
||||
// differently and this makes gcc 3.4.6 happy, but it's ugly.
|
||||
// The error would only show up with EIGEN_DEFAULT_TO_ROW_MAJOR is defined
|
||||
// (when EIGEN_DEFAULT_MATRIX_STORAGE_ORDER_OPTION is RowMajor)
|
||||
( (_Rows==1 && _Cols!=1) ? Eigen::RowMajor
|
||||
// EIGEN_DEFAULT_MATRIX_STORAGE_ORDER_OPTION contains explicit namespace since Eigen 3.1.19
|
||||
#if EIGEN_VERSION_AT_LEAST(3,2,90)
|
||||
: !(_Cols==1 && _Rows!=1) ? EIGEN_DEFAULT_MATRIX_STORAGE_ORDER_OPTION
|
||||
#else
|
||||
: !(_Cols==1 && _Rows!=1) ? Eigen::EIGEN_DEFAULT_MATRIX_STORAGE_ORDER_OPTION
|
||||
#endif
|
||||
: ColMajor ),
|
||||
#else
|
||||
( (_Rows==1 && _Cols!=1) ? Eigen::RowMajor
|
||||
: (_Cols==1 && _Rows!=1) ? Eigen::ColMajor
|
||||
// EIGEN_DEFAULT_MATRIX_STORAGE_ORDER_OPTION contains explicit namespace since Eigen 3.1.19
|
||||
#if EIGEN_VERSION_AT_LEAST(3,2,90)
|
||||
: EIGEN_DEFAULT_MATRIX_STORAGE_ORDER_OPTION ),
|
||||
#else
|
||||
: Eigen::EIGEN_DEFAULT_MATRIX_STORAGE_ORDER_OPTION ),
|
||||
#endif
|
||||
#endif
|
||||
int _MapOptions = Eigen::Unaligned,
|
||||
int _StrideOuter=0, int _StrideInner=0,
|
||||
int _MaxRows = _Rows,
|
||||
int _MaxCols = _Cols>
|
||||
class FlattenedMap: public MapBase<EigencyDenseBase<Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols>, _MapOptions, Eigen::Stride<_StrideOuter, _StrideInner> > {
|
||||
public:
|
||||
typedef MapBase<EigencyDenseBase<Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols>, _MapOptions, Eigen::Stride<_StrideOuter, _StrideInner> > Base;
|
||||
|
||||
FlattenedMap()
|
||||
: Base(NULL, 0, 0),
|
||||
object_(NULL) {}
|
||||
|
||||
FlattenedMap(Scalar *data, long rows, long cols, long outer_stride=0, long inner_stride=0)
|
||||
: Base(data, rows, cols,
|
||||
Eigen::Stride<_StrideOuter, _StrideInner>(outer_stride, inner_stride)),
|
||||
object_(NULL) {
|
||||
}
|
||||
|
||||
FlattenedMap(PyArrayObject *object)
|
||||
: Base((Scalar *)((PyArrayObject*)object)->data,
|
||||
// : Base(_from_numpy<Scalar>((PyArrayObject*)object),
|
||||
(((PyArrayObject*)object)->nd == 2) ? ((PyArrayObject*)object)->dimensions[0] : 1,
|
||||
(((PyArrayObject*)object)->nd == 2) ? ((PyArrayObject*)object)->dimensions[1] : ((PyArrayObject*)object)->dimensions[0],
|
||||
Eigen::Stride<_StrideOuter, _StrideInner>(_StrideOuter != Eigen::Dynamic ? _StrideOuter : (((PyArrayObject*)object)->nd == 2) ? ((PyArrayObject*)object)->dimensions[0] : 1,
|
||||
_StrideInner != Eigen::Dynamic ? _StrideInner : (((PyArrayObject*)object)->nd == 2) ? ((PyArrayObject*)object)->dimensions[1] : ((PyArrayObject*)object)->dimensions[0])),
|
||||
object_(object) {
|
||||
|
||||
if (((PyObject*)object != Py_None) && !PyArray_ISONESEGMENT(object))
|
||||
throw std::invalid_argument("Numpy array must be a in one contiguous segment to be able to be transferred to a Eigen Map.");
|
||||
|
||||
Py_XINCREF(object_);
|
||||
}
|
||||
FlattenedMap &operator=(const FlattenedMap &other) {
|
||||
if (other.object_) {
|
||||
new (this) FlattenedMap(other.object_);
|
||||
} else {
|
||||
// Replace the memory that we point to (not a memory allocation)
|
||||
new (this) FlattenedMap(const_cast<Scalar*>(other.data()),
|
||||
other.rows(),
|
||||
other.cols(),
|
||||
other.outerStride(),
|
||||
other.innerStride());
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
operator Base() const {
|
||||
return static_cast<Base>(*this);
|
||||
}
|
||||
|
||||
operator Base&() const {
|
||||
return static_cast<Base&>(*this);
|
||||
}
|
||||
|
||||
operator EigencyDenseBase<Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols>() const {
|
||||
return EigencyDenseBase<Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols>(static_cast<Base>(*this));
|
||||
}
|
||||
|
||||
virtual ~FlattenedMap() {
|
||||
Py_XDECREF(object_);
|
||||
}
|
||||
|
||||
private:
|
||||
PyArrayObject * const object_;
|
||||
};
|
||||
|
||||
|
||||
template <typename MatrixType>
|
||||
class Map: public MapBase<MatrixType> {
|
||||
public:
|
||||
typedef MapBase<MatrixType> Base;
|
||||
typedef typename MatrixType::Scalar Scalar;
|
||||
|
||||
enum {
|
||||
RowsAtCompileTime = Base::Base::RowsAtCompileTime,
|
||||
ColsAtCompileTime = Base::Base::ColsAtCompileTime
|
||||
};
|
||||
|
||||
Map()
|
||||
: Base(NULL,
|
||||
(RowsAtCompileTime == Eigen::Dynamic) ? 0 : RowsAtCompileTime,
|
||||
(ColsAtCompileTime == Eigen::Dynamic) ? 0 : ColsAtCompileTime),
|
||||
object_(NULL) {
|
||||
}
|
||||
|
||||
Map(Scalar *data, long rows, long cols)
|
||||
: Base(data, rows, cols),
|
||||
object_(NULL) {}
|
||||
|
||||
Map(PyArrayObject *object)
|
||||
: Base((PyObject*)object == Py_None? NULL: (Scalar *)object->data,
|
||||
// ROW: If array is in row-major order, transpose (see README)
|
||||
(PyObject*)object == Py_None? 0 :
|
||||
(!PyArray_IS_F_CONTIGUOUS(object)
|
||||
? ((object->nd == 1)
|
||||
? 1 // ROW: If 1D row-major numpy array, set to 1 (row vector)
|
||||
: object->dimensions[1])
|
||||
: object->dimensions[0]),
|
||||
// COLUMN: If array is in row-major order: transpose (see README)
|
||||
(PyObject*)object == Py_None? 0 :
|
||||
(!PyArray_IS_F_CONTIGUOUS(object)
|
||||
? object->dimensions[0]
|
||||
: ((object->nd == 1)
|
||||
? 1 // COLUMN: If 1D col-major numpy array, set to length (column vector)
|
||||
: object->dimensions[1]))),
|
||||
object_(object) {
|
||||
|
||||
if (((PyObject*)object != Py_None) && !PyArray_ISONESEGMENT(object))
|
||||
throw std::invalid_argument("Numpy array must be a in one contiguous segment to be able to be transferred to a Eigen Map.");
|
||||
Py_XINCREF(object_);
|
||||
}
|
||||
|
||||
Map &operator=(const Map &other) {
|
||||
if (other.object_) {
|
||||
new (this) Map(other.object_);
|
||||
} else {
|
||||
// Replace the memory that we point to (not a memory allocation)
|
||||
new (this) Map(const_cast<Scalar*>(other.data()),
|
||||
other.rows(),
|
||||
other.cols());
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
Map &operator=(const MatrixType &other) {
|
||||
MapBase<MatrixType>::operator=(other);
|
||||
return *this;
|
||||
}
|
||||
|
||||
operator Base() const {
|
||||
return static_cast<Base>(*this);
|
||||
}
|
||||
|
||||
operator Base&() const {
|
||||
return static_cast<Base&>(*this);
|
||||
}
|
||||
|
||||
operator MatrixType() const {
|
||||
return MatrixType(static_cast<Base>(*this));
|
||||
}
|
||||
|
||||
virtual ~Map() {
|
||||
Py_XDECREF(object_);
|
||||
}
|
||||
|
||||
private:
|
||||
PyArrayObject * const object_;
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
Cython>=0.25.2
|
||||
backports_abc>=0.5
|
||||
numpy>=1.11.0
|
|
@ -287,7 +287,7 @@ int main(int argc, char* argv[]) {
|
|||
new_values.insert(current_pose_key, gps_pose);
|
||||
|
||||
printf("################ POSE INCLUDED AT TIME %lf ################\n", t);
|
||||
gps_pose.translation().print();
|
||||
cout << gps_pose.translation();
|
||||
printf("\n\n");
|
||||
} else {
|
||||
new_values.insert(current_pose_key, current_pose_global);
|
||||
|
|
|
@ -217,5 +217,5 @@ if (GTSAM_INSTALL_MATLAB_TOOLBOX)
|
|||
endif()
|
||||
|
||||
# Wrap
|
||||
wrap_and_install_library(../gtsam.h "${GTSAM_ADDITIONAL_LIBRARIES}" "" "${mexFlags}")
|
||||
wrap_and_install_library(gtsam.i "${GTSAM_ADDITIONAL_LIBRARIES}" "" "${mexFlags}")
|
||||
endif ()
|
||||
|
|
|
@ -618,6 +618,9 @@ class SOn {
|
|||
// Other methods
|
||||
Vector vec() const;
|
||||
Matrix matrix() const;
|
||||
|
||||
// enabling serialization functionality
|
||||
void serialize() const;
|
||||
};
|
||||
|
||||
#include <gtsam/geometry/Rot3.h>
|
||||
|
@ -2171,7 +2174,11 @@ class Values {
|
|||
// void insert(size_t j, const gtsam::Value& value);
|
||||
// void update(size_t j, const gtsam::Value& val);
|
||||
// gtsam::Value at(size_t j) const;
|
||||
|
||||
|
||||
// The order is important: Vector has to precede Point2/Point3 so `atVector`
|
||||
// can work for those fixed-size vectors.
|
||||
void insert(size_t j, Vector vector);
|
||||
void insert(size_t j, Matrix matrix);
|
||||
void insert(size_t j, const gtsam::Point2& point2);
|
||||
void insert(size_t j, const gtsam::Point3& point3);
|
||||
void insert(size_t j, const gtsam::Rot2& rot2);
|
||||
|
@ -2188,8 +2195,6 @@ class Values {
|
|||
void insert(size_t j, const gtsam::PinholeCameraCal3_S2& simple_camera);
|
||||
void insert(size_t j, const gtsam::imuBias::ConstantBias& constant_bias);
|
||||
void insert(size_t j, const gtsam::NavState& nav_state);
|
||||
void insert(size_t j, Vector vector);
|
||||
void insert(size_t j, Matrix matrix);
|
||||
|
||||
void update(size_t j, const gtsam::Point2& point2);
|
||||
void update(size_t j, const gtsam::Point3& point3);
|
||||
|
@ -2797,16 +2802,16 @@ class SfmData {
|
|||
|
||||
string findExampleDataFile(string name);
|
||||
pair<gtsam::NonlinearFactorGraph*, gtsam::Values*> load2D(string filename,
|
||||
gtsam::noiseModel::Diagonal* model, int maxID, bool addNoise, bool smart);
|
||||
gtsam::noiseModel::Diagonal* model, int maxIndex, bool addNoise, bool smart);
|
||||
pair<gtsam::NonlinearFactorGraph*, gtsam::Values*> load2D(string filename,
|
||||
gtsam::noiseModel::Diagonal* model, int maxID, bool addNoise);
|
||||
gtsam::noiseModel::Diagonal* model, int maxIndex, bool addNoise);
|
||||
pair<gtsam::NonlinearFactorGraph*, gtsam::Values*> load2D(string filename,
|
||||
gtsam::noiseModel::Diagonal* model, int maxID);
|
||||
gtsam::noiseModel::Diagonal* model, int maxIndex);
|
||||
pair<gtsam::NonlinearFactorGraph*, gtsam::Values*> load2D(string filename,
|
||||
gtsam::noiseModel::Diagonal* model);
|
||||
pair<gtsam::NonlinearFactorGraph*, gtsam::Values*> load2D(string filename);
|
||||
pair<gtsam::NonlinearFactorGraph*, gtsam::Values*> load2D_robust(string filename,
|
||||
gtsam::noiseModel::Base* model);
|
||||
gtsam::noiseModel::Base* model, int maxIndex);
|
||||
void save2D(const gtsam::NonlinearFactorGraph& graph,
|
||||
const gtsam::Values& config, gtsam::noiseModel::Diagonal* model,
|
||||
string filename);
|
||||
|
@ -2816,8 +2821,8 @@ class BetweenFactorPose3s
|
|||
{
|
||||
BetweenFactorPose3s();
|
||||
size_t size() const;
|
||||
gtsam::BetweenFactorPose3* at(size_t i) const;
|
||||
void push_back(const gtsam::BetweenFactorPose3* factor);
|
||||
gtsam::BetweenFactor<gtsam::Pose3>* at(size_t i) const;
|
||||
void push_back(const gtsam::BetweenFactor<gtsam::Pose3>* factor);
|
||||
};
|
||||
|
||||
#include <gtsam/slam/InitializePose3.h>
|
||||
|
@ -2877,9 +2882,9 @@ virtual class FrobeniusBetweenFactor : gtsam::NoiseModelFactor {
|
|||
#include <gtsam/sfm/ShonanFactor.h>
|
||||
|
||||
virtual class ShonanFactor3 : gtsam::NoiseModelFactor {
|
||||
ShonanFactor(size_t key1, size_t key2, const gtsam::Rot3 &R12,
|
||||
ShonanFactor3(size_t key1, size_t key2, const gtsam::Rot3 &R12,
|
||||
size_t p);
|
||||
ShonanFactor(size_t key1, size_t key2, const gtsam::Rot3 &R12,
|
||||
ShonanFactor3(size_t key1, size_t key2, const gtsam::Rot3 &R12,
|
||||
size_t p, gtsam::noiseModel::Base *model);
|
||||
Vector evaluateError(const gtsam::SOn &Q1, const gtsam::SOn &Q2);
|
||||
};
|
||||
|
@ -2955,6 +2960,7 @@ class ShonanAveraging2 {
|
|||
|
||||
// Advanced API
|
||||
gtsam::NonlinearFactorGraph buildGraphAt(size_t p) const;
|
||||
gtsam::Values initializeRandomlyAt(size_t p) const;
|
||||
double costAt(size_t p, const gtsam::Values& values) const;
|
||||
pair<double, Vector> computeMinEigenVector(const gtsam::Values& values) const;
|
||||
bool checkOptimality(const gtsam::Values& values) const;
|
||||
|
@ -2999,6 +3005,7 @@ class ShonanAveraging3 {
|
|||
|
||||
// Advanced API
|
||||
gtsam::NonlinearFactorGraph buildGraphAt(size_t p) const;
|
||||
gtsam::Values initializeRandomlyAt(size_t p) const;
|
||||
double costAt(size_t p, const gtsam::Values& values) const;
|
||||
pair<double, Vector> computeMinEigenVector(const gtsam::Values& values) const;
|
||||
bool checkOptimality(const gtsam::Values& values) const;
|
|
@ -749,10 +749,23 @@ Values ShonanAveraging<d>::initializeRandomly(std::mt19937 &rng) const {
|
|||
return initial;
|
||||
}
|
||||
|
||||
/* ************************************************************************* */
|
||||
template <size_t d> Values ShonanAveraging<d>::initializeRandomly() const {
|
||||
return initializeRandomly(kRandomNumberGenerator);
|
||||
}
|
||||
|
||||
/* ************************************************************************* */
|
||||
template <size_t d>
|
||||
Values ShonanAveraging<d>::initializeRandomly() const {
|
||||
return ShonanAveraging<d>::initializeRandomly(kRandomNumberGenerator);
|
||||
Values ShonanAveraging<d>::initializeRandomlyAt(size_t p,
|
||||
std::mt19937 &rng) const {
|
||||
const Values randomRotations = initializeRandomly(rng);
|
||||
return LiftTo<Rot3>(p, randomRotations); // lift to p!
|
||||
}
|
||||
|
||||
/* ************************************************************************* */
|
||||
template <size_t d>
|
||||
Values ShonanAveraging<d>::initializeRandomlyAt(size_t p) const {
|
||||
return initializeRandomlyAt(p, kRandomNumberGenerator);
|
||||
}
|
||||
|
||||
/* ************************************************************************* */
|
||||
|
|
|
@ -235,6 +235,15 @@ public:
|
|||
*/
|
||||
NonlinearFactorGraph buildGraphAt(size_t p) const;
|
||||
|
||||
/**
|
||||
* Create initial Values of type SO(p)
|
||||
* @param p the dimensionality of the rotation manifold
|
||||
*/
|
||||
Values initializeRandomlyAt(size_t p, std::mt19937 &rng) const;
|
||||
|
||||
/// Version of initializeRandomlyAt with fixed random seed.
|
||||
Values initializeRandomlyAt(size_t p) const;
|
||||
|
||||
/**
|
||||
* Calculate cost for SO(p)
|
||||
* Values should be of type SO(p)
|
||||
|
|
|
@ -570,7 +570,7 @@ GraphAndValues load2D(pair<string, SharedNoiseModel> dataset, size_t maxIndex,
|
|||
|
||||
/* ************************************************************************* */
|
||||
GraphAndValues load2D_robust(const string &filename,
|
||||
noiseModel::Base::shared_ptr &model,
|
||||
const noiseModel::Base::shared_ptr &model,
|
||||
size_t maxIndex) {
|
||||
return load2D(filename, model, maxIndex);
|
||||
}
|
||||
|
|
|
@ -172,7 +172,7 @@ GTSAM_EXPORT GraphAndValues load2D(const std::string& filename,
|
|||
|
||||
/// @deprecated load2D now allows for arbitrary models and wrapping a robust kernel
|
||||
GTSAM_EXPORT GraphAndValues load2D_robust(const std::string& filename,
|
||||
noiseModel::Base::shared_ptr& model, size_t maxIndex = 0);
|
||||
const noiseModel::Base::shared_ptr& model, size_t maxIndex = 0);
|
||||
|
||||
/** save 2d graph */
|
||||
GTSAM_EXPORT void save2D(const NonlinearFactorGraph& graph,
|
||||
|
|
|
@ -108,7 +108,7 @@ list(APPEND GTSAM_EXPORTED_TARGETS gtsam_unstable)
|
|||
set(GTSAM_EXPORTED_TARGETS "${GTSAM_EXPORTED_TARGETS}" PARENT_SCOPE)
|
||||
|
||||
# Wrap version for gtsam_unstable
|
||||
if (GTSAM_INSTALL_MATLAB_TOOLBOX)
|
||||
if (GTSAM_UNSTABLE_INSTALL_MATLAB_TOOLBOX)
|
||||
# Set up codegen
|
||||
include(GtsamMatlabWrap)
|
||||
|
||||
|
@ -119,8 +119,8 @@ if (GTSAM_INSTALL_MATLAB_TOOLBOX)
|
|||
endif()
|
||||
|
||||
# Wrap
|
||||
wrap_and_install_library(gtsam_unstable.h "gtsam" "" "${mexFlags}")
|
||||
endif(GTSAM_INSTALL_MATLAB_TOOLBOX)
|
||||
wrap_and_install_library(gtsam_unstable.i "gtsam" "" "${mexFlags}")
|
||||
endif(GTSAM_UNSTABLE_INSTALL_MATLAB_TOOLBOX)
|
||||
|
||||
|
||||
# Build examples
|
||||
|
|
|
@ -114,7 +114,7 @@ public:
|
|||
/** implement functions needed to derive from Factor */
|
||||
|
||||
/* ************************************************************************* */
|
||||
virtual double error(const Values& x) const {
|
||||
double error(const Values &x) const override {
|
||||
return whitenedError(x).squaredNorm();
|
||||
}
|
||||
|
||||
|
@ -125,8 +125,7 @@ public:
|
|||
* Hence \f$ b = z - h(x) = - \mathtt{error\_vector}(x) \f$
|
||||
*/
|
||||
/* This version of linearize recalculates the noise model each time */
|
||||
virtual boost::shared_ptr<GaussianFactor> linearize(
|
||||
const Values& x) const {
|
||||
boost::shared_ptr<GaussianFactor> linearize(const Values &x) const override {
|
||||
// Only linearize if the factor is active
|
||||
if (!this->active(x))
|
||||
return boost::shared_ptr<JacobianFactor>();
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
function pt = Point2(varargin)
|
||||
% Point2 shim
|
||||
if nargin == 2 && isa(varargin{1}, 'double')
|
||||
pt = [varargin{1} varargin{2}]';
|
||||
elseif nargin == 1
|
||||
pt = varargin{1};
|
||||
elseif nargin == 0
|
||||
pt = [0 0]';
|
||||
else
|
||||
error('Arguments do not match any overload of Point2 shim');
|
||||
end
|
||||
end
|
|
@ -0,0 +1,12 @@
|
|||
function pt = Point3(varargin)
|
||||
% Point3 shim
|
||||
if nargin == 3 && isa(varargin{1}, 'double')
|
||||
pt = [varargin{1} varargin{2} varargin{3}]';
|
||||
elseif nargin == 1
|
||||
pt = varargin{1};
|
||||
elseif nargin == 0
|
||||
pt = [0 0 0]';
|
||||
else
|
||||
error('Arguments do not match any overload of Point3 shim');
|
||||
end
|
||||
end
|
|
@ -50,9 +50,9 @@ for i = 1:cylinderNum
|
|||
visible = true;
|
||||
for k = 1:cylinderNum
|
||||
|
||||
rayCameraToPoint = pose.translation().between(sampledPoint3).vector();
|
||||
rayCameraToCylinder = pose.translation().between(cylinders{k}.centroid).vector();
|
||||
rayCylinderToPoint = cylinders{k}.centroid.between(sampledPoint3).vector();
|
||||
rayCameraToPoint = pose.translation().between(sampledPoint3);
|
||||
rayCameraToCylinder = pose.translation().between(cylinders{k}.centroid);
|
||||
rayCylinderToPoint = cylinders{k}.centroid.between(sampledPoint3);
|
||||
|
||||
% Condition 1: all points in front of the cylinders'
|
||||
% surfaces are visible
|
||||
|
|
|
@ -25,20 +25,20 @@ for i = 1:cylinderNum
|
|||
% For Cheirality Exception
|
||||
sampledPoint3 = cylinders{i}.Points{j};
|
||||
sampledPoint3local = pose.transformTo(sampledPoint3);
|
||||
if sampledPoint3local.z < 0
|
||||
if sampledPoint3local(3) < 0
|
||||
continue;
|
||||
end
|
||||
|
||||
% measurements
|
||||
Z.du = K.fx() * K.baseline() / sampledPoint3local.z;
|
||||
Z.uL = K.fx() * sampledPoint3local.x / sampledPoint3local.z + K.px();
|
||||
Z.du = K.fx() * K.baseline() / sampledPoint3local(3);
|
||||
Z.uL = K.fx() * sampledPoint3local(1) / sampledPoint3local(3) + K.px();
|
||||
Z.uR = Z.uL + Z.du;
|
||||
Z.v = K.fy() / sampledPoint3local.z + K.py();
|
||||
Z.v = K.fy() / sampledPoint3local(3) + K.py();
|
||||
|
||||
% ignore points not visible in the scene
|
||||
if Z.uL < 0 || Z.uL >= imageSize.x || ...
|
||||
Z.uR < 0 || Z.uR >= imageSize.x || ...
|
||||
Z.v < 0 || Z.v >= imageSize.y
|
||||
if Z.uL < 0 || Z.uL >= imageSize(1) || ...
|
||||
Z.uR < 0 || Z.uR >= imageSize(1) || ...
|
||||
Z.v < 0 || Z.v >= imageSize(2)
|
||||
continue;
|
||||
end
|
||||
|
||||
|
@ -54,9 +54,9 @@ for i = 1:cylinderNum
|
|||
visible = true;
|
||||
for k = 1:cylinderNum
|
||||
|
||||
rayCameraToPoint = pose.translation().between(sampledPoint3).vector();
|
||||
rayCameraToCylinder = pose.translation().between(cylinders{k}.centroid).vector();
|
||||
rayCylinderToPoint = cylinders{k}.centroid.between(sampledPoint3).vector();
|
||||
rayCameraToPoint = sampledPoint3 - pose.translation();
|
||||
rayCameraToCylinder = cylinders{k}.centroid - pose.translation();
|
||||
rayCylinderToPoint = sampledPoint3 - cylinders{k}.centroid;
|
||||
|
||||
% Condition 1: all points in front of the cylinders'
|
||||
% surfaces are visible
|
||||
|
|
|
@ -12,8 +12,8 @@ function [cylinder] = cylinderSampling(baseCentroid, radius, height, density)
|
|||
% sample the points
|
||||
for i = 1:pointsNum
|
||||
theta = 2 * pi * rand;
|
||||
x = radius * cos(theta) + baseCentroid.x;
|
||||
y = radius * sin(theta) + baseCentroid.y;
|
||||
x = radius * cos(theta) + baseCentroid(1);
|
||||
y = radius * sin(theta) + baseCentroid(2);
|
||||
z = height * rand;
|
||||
points3{i,1} = Point3([x,y,z]');
|
||||
end
|
||||
|
@ -22,5 +22,5 @@ function [cylinder] = cylinderSampling(baseCentroid, radius, height, density)
|
|||
cylinder.radius = radius;
|
||||
cylinder.height = height;
|
||||
cylinder.Points = points3;
|
||||
cylinder.centroid = Point3(baseCentroid.x, baseCentroid.y, height/2);
|
||||
cylinder.centroid = Point3(baseCentroid(1), baseCentroid(2), height/2);
|
||||
end
|
|
@ -1,7 +1,7 @@
|
|||
function plotCamera(pose, axisLength)
|
||||
hold on
|
||||
|
||||
C = pose.translation().vector();
|
||||
C = pose.translation();
|
||||
R = pose.rotation().matrix();
|
||||
|
||||
xAxis = C+R(:,1)*axisLength;
|
||||
|
|
|
@ -13,7 +13,7 @@ set(gcf, 'Position', [80,1,1800,1000]);
|
|||
%% plot all the cylinders and sampled points
|
||||
|
||||
axis equal
|
||||
axis([0, options.fieldSize.x, 0, options.fieldSize.y, 0, options.height + 30]);
|
||||
axis([0, options.fieldSize(1), 0, options.fieldSize(2), 0, options.height + 30]);
|
||||
xlabel('X (m)');
|
||||
ylabel('Y (m)');
|
||||
zlabel('Height (m)');
|
||||
|
@ -50,8 +50,8 @@ for i = 1:cylinderNum
|
|||
|
||||
[X,Y,Z] = cylinder(cylinders{i}.radius, sampleDensity * cylinders{i}.radius * cylinders{i}.height);
|
||||
|
||||
X = X + cylinders{i}.centroid.x;
|
||||
Y = Y + cylinders{i}.centroid.y;
|
||||
X = X + cylinders{i}.centroid(1);
|
||||
Y = Y + cylinders{i}.centroid(2);
|
||||
Z = Z * cylinders{i}.height;
|
||||
|
||||
h_cylinder{i} = surf(X,Y,Z);
|
||||
|
@ -76,7 +76,7 @@ for i = 1:posesSize
|
|||
%plotCamera(poses{i}, 3);
|
||||
|
||||
gRp = poses{i}.rotation().matrix(); % rotation from pose to global
|
||||
C = poses{i}.translation().vector();
|
||||
C = poses{i}.translation();
|
||||
axisLength = 3;
|
||||
|
||||
xAxis = C+gRp(:,1)*axisLength;
|
||||
|
@ -111,14 +111,14 @@ for i = 1:posesSize
|
|||
for j = 1:pointSize
|
||||
if ~isempty(pts3d{j}.cov{i})
|
||||
hold on
|
||||
h_point{j} = plot3(pts3d{j}.data.x, pts3d{j}.data.y, pts3d{j}.data.z);
|
||||
h_point_cov{j} = gtsam.covarianceEllipse3D([pts3d{j}.data.x; pts3d{j}.data.y; pts3d{j}.data.z], ...
|
||||
h_point{j} = plot3(pts3d{j}.data(1), pts3d{j}.data(2), pts3d{j}.data(3));
|
||||
h_point_cov{j} = gtsam.covarianceEllipse3D([pts3d{j}.data(1); pts3d{j}.data(2); pts3d{j}.data(3)], ...
|
||||
pts3d{j}.cov{i}, options.plot.covarianceScale);
|
||||
end
|
||||
end
|
||||
|
||||
axis equal
|
||||
axis([0, options.fieldSize.x, 0, options.fieldSize.y, 0, options.height + 30]);
|
||||
axis([0, options.fieldSize(1), 0, options.fieldSize(2), 0, options.height + 30]);
|
||||
|
||||
drawnow
|
||||
|
||||
|
@ -158,7 +158,7 @@ for i = 1 : posesSize
|
|||
hold on
|
||||
|
||||
campos([poses{i}.x, poses{i}.y, poses{i}.z]);
|
||||
camtarget([options.fieldSize.x/2, options.fieldSize.y/2, 0]);
|
||||
camtarget([options.fieldSize(1)/2, options.fieldSize(2)/2, 0]);
|
||||
camlight(hlight, 'headlight');
|
||||
|
||||
if options.writeVideo
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
function plotPoint2(p,color,P)
|
||||
% plotPoint2 shows a Point2, possibly with covariance matrix
|
||||
if size(color,2)==1
|
||||
plot(p.x,p.y,[color '*']);
|
||||
plot(p(1),p(2),[color '*']);
|
||||
else
|
||||
plot(p.x,p.y,color);
|
||||
plot(p(1),p(2),color);
|
||||
end
|
||||
if exist('P', 'var') && (~isempty(P))
|
||||
gtsam.covarianceEllipse([p.x;p.y],P,color(1));
|
||||
gtsam.covarianceEllipse([p(1);p(2)],P,color(1));
|
||||
end
|
|
@ -1,12 +1,12 @@
|
|||
function plotPoint3(p, color, P)
|
||||
%PLOTPOINT3 Plot a Point3 with an optional covariance matrix
|
||||
if size(color,2)==1
|
||||
plot3(p.x,p.y,p.z,[color '*']);
|
||||
plot3(p(1),p(2),p(3),[color '*']);
|
||||
else
|
||||
plot3(p.x,p.y,p.z,color);
|
||||
plot3(p(1),p(2),p(3),color);
|
||||
end
|
||||
if exist('P', 'var')
|
||||
gtsam.covarianceEllipse3D([p.x;p.y;p.z],P);
|
||||
gtsam.covarianceEllipse3D([p(1);p(2);p(3)],P);
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -4,7 +4,7 @@ if nargin<3,axisLength=0.1;end
|
|||
|
||||
% get rotation and translation (center)
|
||||
gRp = pose.rotation().matrix(); % rotation from pose to global
|
||||
C = pose.translation().vector();
|
||||
C = pose.translation();
|
||||
|
||||
if ~isempty(axisLength)
|
||||
% draw the camera axes
|
||||
|
|
|
@ -38,7 +38,7 @@ graph.add(PriorFactorPose3(symbol('x', 1), cameraPoses{1}, posePriorNoise));
|
|||
%% initialize graph and values
|
||||
initialEstimate = Values;
|
||||
for i = 1:pointsNum
|
||||
point_j = points3d{i}.data.retract(0.05*randn(3,1));
|
||||
point_j = points3d{i}.data + (0.05*randn(3,1));
|
||||
initialEstimate.insert(symbol('p', i), point_j);
|
||||
end
|
||||
|
||||
|
|
|
@ -46,7 +46,7 @@ options.camera.horizon = 60;
|
|||
% camera baseline
|
||||
options.camera.baseline = 0.05;
|
||||
% camera focal length
|
||||
options.camera.f = round(options.camera.resolution.x * options.camera.horizon / ...
|
||||
options.camera.f = round(options.camera.resolution(1) * options.camera.horizon / ...
|
||||
options.camera.fov);
|
||||
% camera focal baseline
|
||||
options.camera.fB = options.camera.f * options.camera.baseline;
|
||||
|
@ -54,15 +54,15 @@ options.camera.fB = options.camera.f * options.camera.baseline;
|
|||
options.camera.disparity = options.camera.fB / options.camera.horizon;
|
||||
% Monocular Camera Calibration
|
||||
options.camera.monoK = Cal3_S2(options.camera.f, options.camera.f, 0, ...
|
||||
options.camera.resolution.x/2, options.camera.resolution.y/2);
|
||||
options.camera.resolution(1)/2, options.camera.resolution(2)/2);
|
||||
% Stereo Camera Calibration
|
||||
options.camera.stereoK = Cal3_S2Stereo(options.camera.f, options.camera.f, 0, ...
|
||||
options.camera.resolution.x/2, options.camera.resolution.y/2, options.camera.disparity);
|
||||
options.camera.resolution(1)/2, options.camera.resolution(2)/2, options.camera.disparity);
|
||||
|
||||
% write video output
|
||||
options.writeVideo = true;
|
||||
% the testing field size (unit: meter)
|
||||
options.fieldSize = Point2([100, 100]');
|
||||
options.fieldSize = Point2(100, 100);
|
||||
% camera flying speed (unit: meter / second)
|
||||
options.speed = 20;
|
||||
% camera flying height
|
||||
|
@ -113,14 +113,14 @@ theta = 0;
|
|||
i = 1;
|
||||
while i <= cylinderNum
|
||||
theta = theta + 2*pi/10;
|
||||
x = 40 * rand * cos(theta) + options.fieldSize.x/2;
|
||||
y = 20 * rand * sin(theta) + options.fieldSize.y/2;
|
||||
baseCentroid{i} = Point2([x, y]');
|
||||
x = 40 * rand * cos(theta) + options.fieldSize(1)/2;
|
||||
y = 20 * rand * sin(theta) + options.fieldSize(2)/2;
|
||||
baseCentroid{i} = Point2(x, y);
|
||||
|
||||
% prevent two cylinders interact with each other
|
||||
regenerate = false;
|
||||
for j = 1:i-1
|
||||
if i > 1 && baseCentroid{i}.dist(baseCentroid{j}) < options.cylinder.radius * 2
|
||||
if i > 1 && norm(baseCentroid{i} - baseCentroid{j}) < options.cylinder.radius * 2
|
||||
regenerate = true;
|
||||
break;
|
||||
end
|
||||
|
@ -146,17 +146,17 @@ while 1
|
|||
angle = 0.1*pi*(rand-0.5);
|
||||
inc_t = Point3(distance * cos(angle), ...
|
||||
distance * sin(angle), 0);
|
||||
t = t.compose(inc_t);
|
||||
t = t + inc_t;
|
||||
|
||||
if t.x > options.fieldSize.x - 10 || t.y > options.fieldSize.y - 10;
|
||||
if t(1) > options.fieldSize(1) - 10 || t(2) > options.fieldSize(2) - 10;
|
||||
break;
|
||||
end
|
||||
|
||||
%t = Point3([(i-1)*(options.fieldSize.x - 10)/options.poseNum + 10, ...
|
||||
% 15, 10]');
|
||||
camera = PinholeCameraCal3_S2.Lookat(t, ...
|
||||
Point3(options.fieldSize.x/2, options.fieldSize.y/2, 0), ...
|
||||
Point3([0,0,1]'), options.camera.monoK);
|
||||
Point3(options.fieldSize(1)/2, options.fieldSize(2)/2, 0), ...
|
||||
Point3(0,0,1), options.camera.monoK);
|
||||
cameraPoses{end+1} = camera.pose;
|
||||
end
|
||||
|
||||
|
|
|
@ -15,14 +15,14 @@ import gtsam.*
|
|||
|
||||
%% Create two cameras and corresponding essential matrix E
|
||||
aRb = Rot3.Yaw(pi/2);
|
||||
aTb = Point3 (0.1, 0, 0);
|
||||
aTb = [.1, 0, 0]';
|
||||
identity=Pose3;
|
||||
aPb = Pose3(aRb, aTb);
|
||||
cameraA = CalibratedCamera(identity);
|
||||
cameraB = CalibratedCamera(aPb);
|
||||
|
||||
%% Create 5 points
|
||||
P = { Point3(0, 0, 1), Point3(-0.1, 0, 1), Point3(0.1, 0, 1), Point3(0, 0.5, 0.5), Point3(0, -0.5, 0.5) };
|
||||
P = { [0, 0, 1]', [-0.1, 0, 1]', [0.1, 0, 1]', [0, 0.5, 0.5]', [0, -0.5, 0.5]' };
|
||||
|
||||
%% Project points in both cameras
|
||||
for i=1:5
|
||||
|
|
|
@ -71,9 +71,12 @@ marginals = Marginals(graph, result);
|
|||
plot2DTrajectory(result, [], marginals);
|
||||
plot2DPoints(result, 'b', marginals);
|
||||
|
||||
plot([result.atPose2(i1).x; result.atPoint2(j1).x],[result.atPose2(i1).y; result.atPoint2(j1).y], 'c-');
|
||||
plot([result.atPose2(i2).x; result.atPoint2(j1).x],[result.atPose2(i2).y; result.atPoint2(j1).y], 'c-');
|
||||
plot([result.atPose2(i3).x; result.atPoint2(j2).x],[result.atPose2(i3).y; result.atPoint2(j2).y], 'c-');
|
||||
p_j1 = result.atPoint2(j1);
|
||||
p_j2 = result.atPoint2(j2);
|
||||
|
||||
plot([result.atPose2(i1).x; p_j1(1)],[result.atPose2(i1).y; p_j1(2)], 'c-');
|
||||
plot([result.atPose2(i2).x; p_j1(1)],[result.atPose2(i2).y; p_j1(2)], 'c-');
|
||||
plot([result.atPose2(i3).x; p_j2(1)],[result.atPose2(i3).y; p_j2(2)], 'c-');
|
||||
axis([-0.6 4.8 -1 1])
|
||||
axis equal
|
||||
view(2)
|
||||
|
|
|
@ -60,15 +60,18 @@ for j=1:2
|
|||
S{j}=chol(Q{j}); % for sampling
|
||||
end
|
||||
|
||||
plot([sample.atPose2(i1).x; sample.atPoint2(j1).x],[sample.atPose2(i1).y; sample.atPoint2(j1).y], 'c-');
|
||||
plot([sample.atPose2(i2).x; sample.atPoint2(j1).x],[sample.atPose2(i2).y; sample.atPoint2(j1).y], 'c-');
|
||||
plot([sample.atPose2(i3).x; sample.atPoint2(j2).x],[sample.atPose2(i3).y; sample.atPoint2(j2).y], 'c-');
|
||||
p_j1 = sample.atPoint2(j1);
|
||||
p_j2 = sample.atPoint2(j2);
|
||||
|
||||
plot([sample.atPose2(i1).x; p_j1(1)],[sample.atPose2(i1).y; p_j1(2)], 'c-');
|
||||
plot([sample.atPose2(i2).x; p_j1(1)],[sample.atPose2(i2).y; p_j1(2)], 'c-');
|
||||
plot([sample.atPose2(i3).x; p_j2(1)],[sample.atPose2(i3).y; p_j2(2)], 'c-');
|
||||
view(2); axis auto; axis equal
|
||||
|
||||
%% Do Sampling on point 2
|
||||
N=1000;
|
||||
for s=1:N
|
||||
delta = S{2}*randn(2,1);
|
||||
proposedPoint = Point2(point{2}.x+delta(1),point{2}.y+delta(2));
|
||||
proposedPoint = Point2(point{2} + delta);
|
||||
plotPoint2(proposedPoint,'k.')
|
||||
end
|
|
@ -54,7 +54,7 @@ initialEstimate.print(sprintf('\nInitial estimate:\n'));
|
|||
%% Optimize using Levenberg-Marquardt optimization with SubgraphSolver
|
||||
params = gtsam.LevenbergMarquardtParams;
|
||||
subgraphParams = gtsam.SubgraphSolverParameters;
|
||||
params.setLinearSolverType('CONJUGATE_GRADIENT');
|
||||
params.setLinearSolverType('ITERATIVE');
|
||||
params.setIterativeParams(subgraphParams);
|
||||
optimizer = gtsam.LevenbergMarquardtOptimizer(graph, initialEstimate);
|
||||
result = optimizer.optimize();
|
||||
|
|
|
@ -47,7 +47,7 @@ end
|
|||
%% Add Gaussian priors for a pose and a landmark to constrain the system
|
||||
cameraPriorNoise = noiseModel.Diagonal.Sigmas(cameraNoiseSigmas);
|
||||
firstCamera = PinholeCameraCal3_S2(truth.cameras{1}.pose, truth.K);
|
||||
graph.add(PriorFactorSimpleCamera(symbol('c',1), firstCamera, cameraPriorNoise));
|
||||
graph.add(PriorFactorPinholeCameraCal3_S2(symbol('c',1), firstCamera, cameraPriorNoise));
|
||||
|
||||
pointPriorNoise = noiseModel.Isotropic.Sigma(3,pointNoiseSigma);
|
||||
graph.add(PriorFactorPoint3(symbol('p',1), truth.points{1}, pointPriorNoise));
|
||||
|
@ -64,7 +64,7 @@ for i=1:size(truth.cameras,2)
|
|||
initialEstimate.insert(symbol('c',i), camera_i);
|
||||
end
|
||||
for j=1:size(truth.points,2)
|
||||
point_j = Point3(truth.points{j}.vector() + 0.1*randn(3,1));
|
||||
point_j = Point3(truth.points{j} + 0.1*randn(3,1));
|
||||
initialEstimate.insert(symbol('p',j), point_j);
|
||||
end
|
||||
initialEstimate.print(sprintf('\nInitial estimate:\n '));
|
||||
|
|
|
@ -58,7 +58,7 @@ for i=1:size(truth.cameras,2)
|
|||
initialEstimate.insert(symbol('x',i), pose_i);
|
||||
end
|
||||
for j=1:size(truth.points,2)
|
||||
point_j = Point3(truth.points{j}.vector() + 0.1*randn(3,1));
|
||||
point_j = Point3(truth.points{j} + 0.1*randn(3,1));
|
||||
initialEstimate.insert(symbol('p',j), point_j);
|
||||
end
|
||||
initialEstimate.print(sprintf('\nInitial estimate:\n '));
|
||||
|
|
|
@ -51,10 +51,10 @@ graph.add(GenericStereoFactor3D(StereoPoint2(320, 270, 115), stereo_model, x2, l
|
|||
initialEstimate = Values;
|
||||
initialEstimate.insert(x1, first_pose);
|
||||
% noisy estimate for pose 2
|
||||
initialEstimate.insert(x2, Pose3(Rot3(), Point3(0.1,-.1,1.1)));
|
||||
initialEstimate.insert(l1, Point3( 1, 1, 5));
|
||||
initialEstimate.insert(l2, Point3(-1, 1, 5));
|
||||
initialEstimate.insert(l3, Point3( 0,-.5, 5));
|
||||
initialEstimate.insert(x2, Pose3(Rot3(), [0.1, -.1, 1.1]'));
|
||||
initialEstimate.insert(l1, [ 1, 1, 5]');
|
||||
initialEstimate.insert(l2, [-1, 1, 5]');
|
||||
initialEstimate.insert(l3, [ 0,-.5, 5]');
|
||||
|
||||
%% optimize
|
||||
fprintf(1,'Optimizing\n'); tic
|
||||
|
|
|
@ -48,7 +48,7 @@ function plot_m_estimator(x, model, plot_title, fig_id, filename)
|
|||
rho = zeros(size(x));
|
||||
for i = 1:size(x, 2)
|
||||
w(i) = model.weight(x(i));
|
||||
rho(i) = model.residual(x(i));
|
||||
rho(i) = model.loss(x(i));
|
||||
end
|
||||
|
||||
psi = w .* x;
|
||||
|
|
|
@ -66,4 +66,4 @@ CHECK('pose_1.equals(Pose2,1e-4)',pose_1.equals(Pose2,1e-4));
|
|||
|
||||
point_1 = result.atPoint2(symbol('l',1));
|
||||
marginals.marginalCovariance(symbol('l',1));
|
||||
CHECK('point_1.equals(Point2(2,2),1e-4)',point_1.equals(Point2(2,2),1e-4));
|
||||
CHECK('point_1.equals(Point2(2,2),1e-4)',norm(point_1 - Point2(2,2)) < 1e-4);
|
||||
|
|
|
@ -69,5 +69,5 @@ end
|
|||
|
||||
for j=1:size(truth.points,2)
|
||||
point_j = result.atPoint3(symbol('p',j));
|
||||
CHECK('point_j.equals(truth.points{j},1e-5)',point_j.equals(truth.points{j},1e-5))
|
||||
CHECK('point_j.equals(truth.points{j},1e-5)',norm(point_j - truth.points{j}) < 1e-5)
|
||||
end
|
||||
|
|
|
@ -65,4 +65,4 @@ pose_x1 = result.atPose3(x1);
|
|||
CHECK('pose_x1.equals(first_pose,1e-4)',pose_x1.equals(first_pose,1e-4));
|
||||
|
||||
point_l1 = result.atPoint3(l1);
|
||||
CHECK('point_1.equals(expected_l1,1e-4)',point_l1.equals(expected_l1,1e-4));
|
||||
CHECK('point_1.equals(expected_l1,1e-4)',norm(point_l1 - expected_l1) < 1e-4);
|
|
@ -5,8 +5,8 @@ values = Values;
|
|||
E = EssentialMatrix(Rot3,Unit3);
|
||||
tol = 1e-9;
|
||||
|
||||
values.insert(0, Point2);
|
||||
values.insert(1, Point3);
|
||||
values.insert(0, Point2(0, 0));
|
||||
values.insert(1, Point3(0, 0, 0));
|
||||
values.insert(2, Rot2);
|
||||
values.insert(3, Pose2);
|
||||
values.insert(4, Rot3);
|
||||
|
@ -21,8 +21,8 @@ values.insert(10, imuBias.ConstantBias);
|
|||
values.insert(11, [1;2;3]);
|
||||
values.insert(12, [1 2;3 4]);
|
||||
|
||||
EXPECT('at',values.atPoint2(0).equals(Point2,tol));
|
||||
EXPECT('at',values.atPoint3(1).equals(Point3,tol));
|
||||
EXPECT('at',values.atPoint2(0) == Point2(0, 0));
|
||||
EXPECT('at',values.atPoint3(1) == Point3(0, 0, 0));
|
||||
EXPECT('at',values.atRot2(2).equals(Rot2,tol));
|
||||
EXPECT('at',values.atPose2(3).equals(Pose2,tol));
|
||||
EXPECT('at',values.atRot3(4).equals(Rot3,tol));
|
||||
|
|
|
@ -51,5 +51,5 @@ end
|
|||
|
||||
for j=1:size(truth.points,2)
|
||||
point_j = result.atPoint3(symbol('l',j));
|
||||
CHECK('point_j.equals(truth.points{j},1e-5)',point_j.equals(truth.points{j},1e-5))
|
||||
CHECK('point_j.equals(truth.points{j},1e-5)',norm(point_j - truth.points{j}) < 1e-5)
|
||||
end
|
||||
|
|
|
@ -28,19 +28,19 @@ currentVelocityGlobalIMUbody = currentVelocityGlobal;
|
|||
%% Prepare data structures for actual trajectory and estimates
|
||||
% Actual trajectory
|
||||
positions = zeros(3, length(times)+1);
|
||||
positions(:,1) = currentPoseGlobal.translation.vector;
|
||||
positions(:,1) = currentPoseGlobal.translation;
|
||||
poses(1).p = positions(:,1);
|
||||
poses(1).R = currentPoseGlobal.rotation.matrix;
|
||||
|
||||
% Trajectory estimate (integrated in the navigation frame)
|
||||
positionsIMUnav = zeros(3, length(times)+1);
|
||||
positionsIMUnav(:,1) = currentPoseGlobalIMUbody.translation.vector;
|
||||
positionsIMUnav(:,1) = currentPoseGlobalIMUbody.translation;
|
||||
posesIMUnav(1).p = positionsIMUnav(:,1);
|
||||
posesIMUnav(1).R = poses(1).R;
|
||||
|
||||
% Trajectory estimate (integrated in the body frame)
|
||||
positionsIMUbody = zeros(3, length(times)+1);
|
||||
positionsIMUbody(:,1) = currentPoseGlobalIMUbody.translation.vector;
|
||||
positionsIMUbody(:,1) = currentPoseGlobalIMUbody.translation;
|
||||
posesIMUbody(1).p = positionsIMUbody(:,1);
|
||||
posesIMUbody(1).R = poses(1).R;
|
||||
|
||||
|
@ -120,9 +120,9 @@ for t = times
|
|||
currentPoseGlobalIMUnav, currentVelocityGlobalIMUnav, acc_omega, deltaT);
|
||||
|
||||
%% Store data in some structure for statistics and plots
|
||||
positions(:,i) = currentPoseGlobal.translation.vector;
|
||||
positionsIMUbody(:,i) = currentPoseGlobalIMUbody.translation.vector;
|
||||
positionsIMUnav(:,i) = currentPoseGlobalIMUnav.translation.vector;
|
||||
positions(:,i) = currentPoseGlobal.translation;
|
||||
positionsIMUbody(:,i) = currentPoseGlobalIMUbody.translation;
|
||||
positionsIMUnav(:,i) = currentPoseGlobalIMUnav.translation;
|
||||
% -
|
||||
poses(i).p = positions(:,i);
|
||||
posesIMUbody(i).p = positionsIMUbody(:,i);
|
||||
|
|
|
@ -28,7 +28,7 @@ currentVelocityGlobal = velocity;
|
|||
%% Prepare data structures for actual trajectory and estimates
|
||||
% Actual trajectory
|
||||
positions = zeros(3, length(times)+1);
|
||||
positions(:,1) = currentPoseGlobal.translation.vector;
|
||||
positions(:,1) = currentPoseGlobal.translation;
|
||||
poses(1).p = positions(:,1);
|
||||
poses(1).R = currentPoseGlobal.rotation.matrix;
|
||||
|
||||
|
@ -112,7 +112,7 @@ for t = times
|
|||
end
|
||||
|
||||
%% Store data in some structure for statistics and plots
|
||||
positions(:,i) = currentPoseGlobal.translation.vector;
|
||||
positions(:,i) = currentPoseGlobal.translation;
|
||||
i = i + 1;
|
||||
end
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ measuredOmega = omega1Body;
|
|||
|
||||
% Acceleration measurement (in this simple toy example no other forces
|
||||
% act on the body and the only acceleration is the centripetal Coriolis acceleration)
|
||||
measuredAcc = Point3(cross(omega1Body, velocity1Body)).vector;
|
||||
measuredAcc = Point3(cross(omega1Body, velocity1Body));
|
||||
acc_omega = [ measuredAcc; measuredOmega ];
|
||||
|
||||
end
|
||||
|
|
|
@ -6,16 +6,16 @@ import gtsam.*;
|
|||
|
||||
% Calculate gyro measured rotation rate by transforming body rotation rate
|
||||
% into the IMU frame.
|
||||
measuredOmega = imuFrame.rotation.unrotate(Point3(omega1Body)).vector;
|
||||
measuredOmega = imuFrame.rotation.unrotate(Point3(omega1Body));
|
||||
|
||||
% Transform both velocities into IMU frame, accounting for the velocity
|
||||
% induced by rigid body rotation on a lever arm (Coriolis effect).
|
||||
velocity1inertial = imuFrame.rotation.unrotate( ...
|
||||
Point3(velocity1Body + cross(omega1Body, imuFrame.translation.vector))).vector;
|
||||
Point3(velocity1Body + cross(omega1Body, imuFrame.translation)));
|
||||
|
||||
imu2in1 = Rot3.Expmap(measuredOmega * deltaT);
|
||||
velocity2inertial = imu2in1.rotate(imuFrame.rotation.unrotate( ...
|
||||
Point3(velocity2Body + cross(omega2Body, imuFrame.translation.vector)))).vector;
|
||||
Point3(velocity2Body + cross(omega2Body, imuFrame.translation))));
|
||||
|
||||
% Acceleration in IMU frame
|
||||
measuredAcc = (velocity2inertial - velocity1inertial) / deltaT;
|
||||
|
|
|
@ -190,13 +190,13 @@ for i = 1:length(times)
|
|||
newFactors.add(PriorFactorConstantBias(currentBiasKey, zeroBias, sigma_init_b));
|
||||
|
||||
% Store data
|
||||
positionsInFixedGT(:,1) = currentPoseFixedGT.translation.vector;
|
||||
positionsInFixedGT(:,1) = currentPoseFixedGT.translation;
|
||||
velocityInFixedGT(:,1) = currentVelocityFixedGT;
|
||||
positionsInRotatingGT(:,1) = currentPoseRotatingGT.translation.vector;
|
||||
%velocityInRotatingGT(:,1) = currentPoseRotatingGT.velocity.vector;
|
||||
positionsEstimates(:,i) = currentPoseEstimate.translation.vector;
|
||||
velocitiesEstimates(:,i) = currentVelocityEstimate.vector;
|
||||
currentRotatingFrameForPlot(1).p = currentRotatingFrame.translation.vector;
|
||||
positionsInRotatingGT(:,1) = currentPoseRotatingGT.translation;
|
||||
%velocityInRotatingGT(:,1) = currentPoseRotatingGT.velocity;
|
||||
positionsEstimates(:,i) = currentPoseEstimate.translation;
|
||||
velocitiesEstimates(:,i) = currentVelocityEstimate;
|
||||
currentRotatingFrameForPlot(1).p = currentRotatingFrame.translation;
|
||||
currentRotatingFrameForPlot(1).R = currentRotatingFrame.rotation.matrix;
|
||||
else
|
||||
|
||||
|
@ -204,18 +204,18 @@ for i = 1:length(times)
|
|||
% Update the position and velocity
|
||||
% x_t = x_0 + v_0*dt + 1/2*a_0*dt^2
|
||||
% v_t = v_0 + a_0*dt
|
||||
currentPositionFixedGT = Point3(currentPoseFixedGT.translation.vector ...
|
||||
currentPositionFixedGT = Point3(currentPoseFixedGT.translation ...
|
||||
+ currentVelocityFixedGT * deltaT + 0.5 * accelFixed * deltaT * deltaT);
|
||||
currentVelocityFixedGT = currentVelocityFixedGT + accelFixed * deltaT;
|
||||
|
||||
currentPoseFixedGT = Pose3(Rot3, currentPositionFixedGT); % constant orientation
|
||||
|
||||
% Rotate pose in fixed frame to get pose in rotating frame
|
||||
previousPositionRotatingGT = currentPoseRotatingGT.translation.vector;
|
||||
previousPositionRotatingGT = currentPoseRotatingGT.translation;
|
||||
currentRotatingFrame = currentRotatingFrame.compose(changePoseRotatingFrame);
|
||||
inverseCurrentRotatingFrame = (currentRotatingFrame.inverse);
|
||||
currentPoseRotatingGT = inverseCurrentRotatingFrame.compose(currentPoseFixedGT);
|
||||
currentPositionRotatingGT = currentPoseRotatingGT.translation.vector;
|
||||
currentPositionRotatingGT = currentPoseRotatingGT.translation;
|
||||
|
||||
% Get velocity in rotating frame by treating it like a position and using compose
|
||||
% Maybe Luca knows a better way to do this within GTSAM.
|
||||
|
@ -230,11 +230,11 @@ for i = 1:length(times)
|
|||
% - 0.5 * accelFixed * deltaT * deltaT) / deltaT + accelFixed * deltaT;
|
||||
|
||||
% Store GT (ground truth) poses
|
||||
positionsInFixedGT(:,i) = currentPoseFixedGT.translation.vector;
|
||||
positionsInFixedGT(:,i) = currentPoseFixedGT.translation;
|
||||
velocityInFixedGT(:,i) = currentVelocityFixedGT;
|
||||
positionsInRotatingGT(:,i) = currentPoseRotatingGT.translation.vector;
|
||||
positionsInRotatingGT(:,i) = currentPoseRotatingGT.translation;
|
||||
velocityInRotatingGT(:,i) = currentVelocityRotatingGT;
|
||||
currentRotatingFrameForPlot(i).p = currentRotatingFrame.translation.vector;
|
||||
currentRotatingFrameForPlot(i).p = currentRotatingFrame.translation;
|
||||
currentRotatingFrameForPlot(i).R = currentRotatingFrame.rotation.matrix;
|
||||
|
||||
%% Estimate trajectory in rotating frame using GTSAM (ground truth measurements)
|
||||
|
@ -303,9 +303,9 @@ for i = 1:length(times)
|
|||
currentVelocityEstimate = isam.calculateEstimate(currentVelKey);
|
||||
currentBias = isam.calculateEstimate(currentBiasKey);
|
||||
|
||||
positionsEstimates(:,i) = currentPoseEstimate.translation.vector;
|
||||
velocitiesEstimates(:,i) = currentVelocityEstimate.vector;
|
||||
biasEstimates(:,i) = currentBias.vector;
|
||||
positionsEstimates(:,i) = currentPoseEstimate.translation;
|
||||
velocitiesEstimates(:,i) = currentVelocityEstimate;
|
||||
biasEstimates(:,i) = currentBias;
|
||||
|
||||
% In matrix form: R_error = R_gt'*R_estimate
|
||||
% Perform Logmap on the rotation matrix to get a vector
|
||||
|
|
|
@ -151,14 +151,14 @@ hold on;
|
|||
if options.includeCameraFactors
|
||||
b = [-1000 2000 -2000 2000 -30 30];
|
||||
for i = 1:size(metadata.camera.gtLandmarkPoints,2)
|
||||
p = metadata.camera.gtLandmarkPoints(i).vector;
|
||||
p = metadata.camera.gtLandmarkPoints(i);
|
||||
if(p(1) > b(1) && p(1) < b(2) && p(2) > b(3) && p(2) < b(4) && p(3) > b(5) && p(3) < b(6))
|
||||
plot3(p(1), p(2), p(3), 'k+');
|
||||
end
|
||||
end
|
||||
pointsToPlot = metadata.camera.gtLandmarkPoints(find(projectionFactorSeenBy > 0));
|
||||
for i = 1:length(pointsToPlot)
|
||||
p = pointsToPlot(i).vector;
|
||||
p = pointsToPlot(i);
|
||||
plot3(p(1), p(2), p(3), 'gs', 'MarkerSize', 10);
|
||||
end
|
||||
end
|
||||
|
@ -233,9 +233,9 @@ for k=1:numMonteCarloRuns
|
|||
for i=0:options.trajectoryLength
|
||||
% compute estimation errors
|
||||
currentPoseKey = symbol('x', i);
|
||||
gtPosition = gtValues.at(currentPoseKey).translation.vector;
|
||||
estPosition = estimate.at(currentPoseKey).translation.vector;
|
||||
estR = estimate.at(currentPoseKey).rotation.matrix;
|
||||
gtPosition = gtValues.atPose3(currentPoseKey).translation;
|
||||
estPosition = estimate.atPose3(currentPoseKey).translation;
|
||||
estR = estimate.atPose3(currentPoseKey).rotation.matrix;
|
||||
errPosition = estPosition - gtPosition;
|
||||
|
||||
% compute covariances:
|
||||
|
|
|
@ -14,7 +14,7 @@ graph = NonlinearFactorGraph;
|
|||
for i=0:length(measurements)
|
||||
% Get the current pose
|
||||
currentPoseKey = symbol('x', i);
|
||||
currentPose = values.at(currentPoseKey);
|
||||
currentPose = values.atPose3(currentPoseKey);
|
||||
|
||||
if i==0
|
||||
%% first time step, add priors
|
||||
|
@ -26,11 +26,11 @@ for i=0:length(measurements)
|
|||
% IMU velocity and bias priors
|
||||
if options.includeIMUFactors == 1
|
||||
currentVelKey = symbol('v', 0);
|
||||
currentVel = values.at(currentVelKey).vector;
|
||||
currentVel = values.atPoint3(currentVelKey);
|
||||
graph.add(PriorFactorLieVector(currentVelKey, LieVector(currentVel), noiseModels.noiseVel));
|
||||
|
||||
currentBiasKey = symbol('b', 0);
|
||||
currentBias = values.at(currentBiasKey);
|
||||
currentBias = values.atPoint3(currentBiasKey);
|
||||
graph.add(PriorFactorConstantBias(currentBiasKey, currentBias, noiseModels.noisePriorBias));
|
||||
end
|
||||
|
||||
|
@ -155,7 +155,7 @@ for i=0:length(measurements)
|
|||
if options.includeCameraFactors == 1
|
||||
for j = 1:length(measurements(i).landmarks)
|
||||
cameraMeasurmentNoise = measurementNoise.cameraNoiseVector .* randn(2,1);
|
||||
cameraPixelMeasurement = measurements(i).landmarks(j).vector;
|
||||
cameraPixelMeasurement = measurements(i).landmarks(j);
|
||||
% Only add the measurement if it is in the image frame (based on calibration)
|
||||
if(cameraPixelMeasurement(1) > 0 && cameraPixelMeasurement(2) > 0 ...
|
||||
&& cameraPixelMeasurement(1) < 2*metadata.camera.calibration.px ...
|
||||
|
|
|
@ -40,7 +40,7 @@ if options.useRealData == 1
|
|||
|
||||
%% gt Between measurements
|
||||
if options.includeBetweenFactors == 1 && i > 0
|
||||
prevPose = values.at(currentPoseKey - 1);
|
||||
prevPose = values.atPose3(currentPoseKey - 1);
|
||||
deltaPose = prevPose.between(currentPose);
|
||||
measurements(i).deltaVector = Pose3.Logmap(deltaPose);
|
||||
end
|
||||
|
@ -65,7 +65,7 @@ if options.useRealData == 1
|
|||
IMUdeltaPose = IMUPose1.between(IMUPose2);
|
||||
IMUdeltaPoseVector = Pose3.Logmap(IMUdeltaPose);
|
||||
IMUdeltaRotVector = IMUdeltaPoseVector(1:3);
|
||||
IMUdeltaPositionVector = IMUPose2.translation.vector - IMUPose1.translation.vector; % translation in absolute frame
|
||||
IMUdeltaPositionVector = IMUPose2.translation - IMUPose1.translation; % translation in absolute frame
|
||||
|
||||
measurements(i).imu(j).deltaT = deltaT;
|
||||
|
||||
|
@ -88,7 +88,7 @@ if options.useRealData == 1
|
|||
|
||||
%% gt GPS measurements
|
||||
if options.includeGPSFactors == 1 && i > 0
|
||||
gpsPositionVector = imuSimulator.getPoseFromGtScenario(gtScenario,scenarioInd).translation.vector;
|
||||
gpsPositionVector = imuSimulator.getPoseFromGtScenario(gtScenario,scenarioInd).translation;
|
||||
measurements(i).gpsPositionVector = gpsPositionVector;
|
||||
end
|
||||
|
||||
|
|
|
@ -5,9 +5,9 @@ function [ finalPose, finalVelocityGlobal ] = integrateIMUTrajectory( ...
|
|||
import gtsam.*;
|
||||
|
||||
imu2in1 = Rot3.Expmap(acc_omegaIMU(4:6) * deltaT);
|
||||
accelGlobal = initialPoseGlobal.rotation().rotate(Point3(acc_omegaIMU(1:3))).vector;
|
||||
accelGlobal = initialPoseGlobal.rotation().rotate(Point3(acc_omegaIMU(1:3)));
|
||||
|
||||
finalPosition = Point3(initialPoseGlobal.translation.vector ...
|
||||
finalPosition = Point3(initialPoseGlobal.translation ...
|
||||
+ initialVelocityGlobal * deltaT + 0.5 * accelGlobal * deltaT * deltaT);
|
||||
finalVelocityGlobal = initialVelocityGlobal + accelGlobal * deltaT;
|
||||
finalRotation = initialPoseGlobal.rotation.compose(imu2in1);
|
||||
|
|
|
@ -3,7 +3,7 @@ function [ finalPose, finalVelocityGlobal ] = integrateIMUTrajectory_bodyFrame(
|
|||
|
||||
% Before integrating in the body frame we need to compensate for the Coriolis
|
||||
% effect
|
||||
acc_body = acc_omegaIMU(1:3) - Point3(cross(acc_omegaIMU(4:6), velocity1Body)).vector;
|
||||
acc_body = acc_omegaIMU(1:3) - Point3(cross(acc_omegaIMU(4:6), velocity1Body));
|
||||
% after compensating for coriolis this will be essentially zero
|
||||
% since we are moving at constant body velocity
|
||||
|
||||
|
@ -16,8 +16,8 @@ finalPositionBody = velocity1Body * deltaT + 0.5 * acc_body * deltaT * deltaT;
|
|||
finalVelocityBody = velocity1Body + acc_body * deltaT;
|
||||
|
||||
%% Express the integrated quantities in the global frame
|
||||
finalVelocityGlobal = initialVelocityGlobal + (initialPoseGlobal.rotation().rotate(Point3(finalVelocityBody)).vector() );
|
||||
finalPosition = initialPoseGlobal.translation().vector() + initialPoseGlobal.rotation().rotate( Point3(finalPositionBody)).vector() ;
|
||||
finalVelocityGlobal = initialVelocityGlobal + (initialPoseGlobal.rotation().rotate(Point3(finalVelocityBody)) );
|
||||
finalPosition = initialPoseGlobal.translation() + initialPoseGlobal.rotation().rotate( Point3(finalPositionBody)) ;
|
||||
finalRotation = initialPoseGlobal.rotation.compose(imu2in1);
|
||||
% Include position and rotation in a pose
|
||||
finalPose = Pose3(finalRotation, Point3(finalPosition) );
|
||||
|
|
|
@ -9,8 +9,8 @@ finalRotation = initialPoseGlobal.rotation.compose(imu2in1);
|
|||
|
||||
intermediateRotation = initialPoseGlobal.rotation.compose( Rot3.Expmap(acc_omegaIMU(4:6) * deltaT/2 ));
|
||||
% Integrate positions (equation (1) in Lupton)
|
||||
accelGlobal = intermediateRotation.rotate(Point3(acc_omegaIMU(1:3))).vector;
|
||||
finalPosition = Point3(initialPoseGlobal.translation.vector ...
|
||||
accelGlobal = intermediateRotation.rotate(Point3(acc_omegaIMU(1:3)));
|
||||
finalPosition = Point3(initialPoseGlobal.translation ...
|
||||
+ initialVelocityGlobal * deltaT + 0.5 * accelGlobal * deltaT * deltaT);
|
||||
finalVelocityGlobal = initialVelocityGlobal + accelGlobal * deltaT;
|
||||
|
||||
|
|
|
@ -6,16 +6,16 @@ import gtsam.*;
|
|||
% Rotation: R^1_2
|
||||
body2in1 = Rot3.Expmap(omega1Body * deltaT);
|
||||
% Velocity 2 in frame 1: v^1_2 = R^1_2 v^2_2
|
||||
velocity2inertial = body2in1.rotate(Point3(velocity2Body)).vector;
|
||||
velocity2inertial = body2in1.rotate(Point3(velocity2Body));
|
||||
% Acceleration: a^1 = (v^1_2 - v^1_1)/dt
|
||||
accelBody1 = (velocity2inertial - velocity1Body) / deltaT;
|
||||
|
||||
% Velocity 1 in frame W: v^W_1 = R^W_1 v^1_1
|
||||
initialVelocityGlobal = initialPose.rotation().rotate(Point3(velocity1Body)).vector;
|
||||
initialVelocityGlobal = initialPose.rotation().rotate(Point3(velocity1Body));
|
||||
% Acceleration in frame W: a^W = R^W_1 a^1
|
||||
accelGlobal = initialPose.rotation().rotate(Point3(accelBody1)).vector;
|
||||
accelGlobal = initialPose.rotation().rotate(Point3(accelBody1));
|
||||
|
||||
finalPosition = Point3(initialPose.translation.vector + initialVelocityGlobal * deltaT + 0.5 * accelGlobal * deltaT * deltaT);
|
||||
finalPosition = Point3(initialPose.translation + initialVelocityGlobal * deltaT + 0.5 * accelGlobal * deltaT * deltaT);
|
||||
finalVelocityGlobal = initialVelocityGlobal + accelGlobal * deltaT;
|
||||
finalRotation = initialPose.rotation.compose(body2in1);
|
||||
finalPose = Pose3(finalRotation, finalPosition);
|
||||
|
|
|
@ -10,7 +10,7 @@ omega = [0;0;0.1];
|
|||
velocity = [1;0;0];
|
||||
R = Rot3.Expmap(omega * deltaT);
|
||||
|
||||
velocity2body = R.unrotate(Point3(velocity)).vector;
|
||||
velocity2body = R.unrotate(Point3(velocity));
|
||||
acc_omegaExpected = [-0.01; 0; 0; 0; 0; 0.1];
|
||||
acc_omegaActual = imuSimulator.calculateIMUMeasurement(omega, omega, velocity, velocity2body, deltaT, Pose3(Rot3, Point3([1;0;0])));
|
||||
disp('IMU measurement discrepancy:');
|
||||
|
@ -40,7 +40,7 @@ disp(acc_omegaActual - acc_omegaExpected);
|
|||
initialPose = Pose3;
|
||||
initialVelocity = velocity;
|
||||
finalPoseExpected = Pose3.Expmap([ omega; velocity ] * deltaT);
|
||||
finalVelocityExpected = finalPoseExpected.rotation.rotate(Point3(velocity)).vector;
|
||||
finalVelocityExpected = finalPoseExpected.rotation.rotate(Point3(velocity));
|
||||
[ finalPoseActual, finalVelocityActual ] = imuSimulator.integrateTrajectory(initialPose, omega, velocity, velocity, deltaT);
|
||||
disp('Final pose discrepancy:');
|
||||
disp(finalPoseExpected.between(finalPoseActual).matrix);
|
||||
|
|
|
@ -21,12 +21,12 @@ positions = zeros(3, length(times)+1);
|
|||
|
||||
i = 2;
|
||||
for t = times
|
||||
velocity1body = currentPoseGlobal.rotation.unrotate(Point3(currentVelocityGlobal)).vector;
|
||||
velocity1body = currentPoseGlobal.rotation.unrotate(Point3(currentVelocityGlobal));
|
||||
R = Rot3.Expmap(omega * deltaT);
|
||||
velocity2body = currentPoseGlobal.rotation.compose(R).unrotate(Point3(currentVelocityGlobal)).vector;
|
||||
velocity2body = currentPoseGlobal.rotation.compose(R).unrotate(Point3(currentVelocityGlobal));
|
||||
[ currentPoseGlobal, currentVelocityGlobal ] = imuSimulator.integrateTrajectory(currentPoseGlobal, omega, velocity1body, velocity2body, deltaT);
|
||||
|
||||
positions(:,i) = currentPoseGlobal.translation.vector;
|
||||
positions(:,i) = currentPoseGlobal.translation;
|
||||
i = i + 1;
|
||||
end
|
||||
|
||||
|
|
|
@ -26,27 +26,27 @@ currentPoseGlobal = Pose3;
|
|||
currentVelocityGlobal = velocity;
|
||||
% Initial state (IMU)
|
||||
currentPoseGlobalIMU = Pose3; %currentPoseGlobal.compose(IMUinBody);
|
||||
%currentVelocityGlobalIMU = IMUinBody.rotation.unrotate(Point3(velocity)).vector; % no Coriolis here?
|
||||
%currentVelocityGlobalIMU = IMUinBody.rotation.unrotate(Point3(velocity)); % no Coriolis here?
|
||||
currentVelocityGlobalIMU = IMUinBody.rotation.unrotate( ...
|
||||
Point3(velocity + cross(omega, IMUinBody.translation.vector))).vector;
|
||||
Point3(velocity + cross(omega, IMUinBody.translation)));
|
||||
|
||||
|
||||
% Positions
|
||||
% body trajectory
|
||||
positions = zeros(3, length(times)+1);
|
||||
positions(:,1) = currentPoseGlobal.translation.vector;
|
||||
positions(:,1) = currentPoseGlobal.translation;
|
||||
poses(1).p = positions(:,1);
|
||||
poses(1).R = currentPoseGlobal.rotation.matrix;
|
||||
|
||||
% Expected IMU trajectory (from body trajectory and lever arm)
|
||||
positionsIMUe = zeros(3, length(times)+1);
|
||||
positionsIMUe(:,1) = IMUinBody.compose(currentPoseGlobalIMU).translation.vector;
|
||||
positionsIMUe(:,1) = IMUinBody.compose(currentPoseGlobalIMU).translation;
|
||||
posesIMUe(1).p = positionsIMUe(:,1);
|
||||
posesIMUe(1).R = poses(1).R * IMUinBody.rotation.matrix;
|
||||
|
||||
% Integrated IMU trajectory (from IMU measurements)
|
||||
positionsIMU = zeros(3, length(times)+1);
|
||||
positionsIMU(:,1) = IMUinBody.compose(currentPoseGlobalIMU).translation.vector;
|
||||
positionsIMU(:,1) = IMUinBody.compose(currentPoseGlobalIMU).translation;
|
||||
posesIMU(1).p = positionsIMU(:,1);
|
||||
posesIMU(1).R = IMUinBody.compose(currentPoseGlobalIMU).rotation.matrix;
|
||||
|
||||
|
@ -62,9 +62,9 @@ for t = times
|
|||
currentPoseGlobalIMU, currentVelocityGlobalIMU, acc_omega, deltaT);
|
||||
|
||||
% Store data in some structure for statistics and plots
|
||||
positions(:,i) = currentPoseGlobal.translation.vector;
|
||||
positionsIMUe(:,i) = currentPoseGlobal.translation.vector + currentPoseGlobal.rotation.matrix * IMUinBody.translation.vector;
|
||||
positionsIMU(:,i) = IMUinBody.compose(currentPoseGlobalIMU).translation.vector;
|
||||
positions(:,i) = currentPoseGlobal.translation;
|
||||
positionsIMUe(:,i) = currentPoseGlobal.translation + currentPoseGlobal.rotation.matrix * IMUinBody.translation;
|
||||
positionsIMU(:,i) = IMUinBody.compose(currentPoseGlobalIMU).translation;
|
||||
|
||||
poses(i).p = positions(:,i);
|
||||
posesIMUe(i).p = positionsIMUe(:,i);
|
||||
|
|
|
@ -34,19 +34,19 @@ currentVelocityGlobalIMUbody = currentVelocityGlobal;
|
|||
%% Prepare data structures for actual trajectory and estimates
|
||||
% Actual trajectory
|
||||
positions = zeros(3, length(times)+1);
|
||||
positions(:,1) = currentPoseGlobal.translation.vector;
|
||||
positions(:,1) = currentPoseGlobal.translation;
|
||||
poses(1).p = positions(:,1);
|
||||
poses(1).R = currentPoseGlobal.rotation.matrix;
|
||||
|
||||
% Trajectory estimate (integrated in the navigation frame)
|
||||
positionsIMUnav = zeros(3, length(times)+1);
|
||||
positionsIMUnav(:,1) = currentPoseGlobalIMUbody.translation.vector;
|
||||
positionsIMUnav(:,1) = currentPoseGlobalIMUbody.translation;
|
||||
posesIMUnav(1).p = positionsIMUnav(:,1);
|
||||
posesIMUnav(1).R = poses(1).R;
|
||||
|
||||
% Trajectory estimate (integrated in the body frame)
|
||||
positionsIMUbody = zeros(3, length(times)+1);
|
||||
positionsIMUbody(:,1) = currentPoseGlobalIMUbody.translation.vector;
|
||||
positionsIMUbody(:,1) = currentPoseGlobalIMUbody.translation;
|
||||
posesIMUbody(1).p = positionsIMUbody(:,1);
|
||||
posesIMUbody(1).R = poses(1).R;
|
||||
|
||||
|
@ -72,9 +72,9 @@ for t = times
|
|||
currentPoseGlobalIMUnav, currentVelocityGlobalIMUnav, acc_omega, deltaT);
|
||||
|
||||
%% Store data in some structure for statistics and plots
|
||||
positions(:,i) = currentPoseGlobal.translation.vector;
|
||||
positionsIMUbody(:,i) = currentPoseGlobalIMUbody.translation.vector;
|
||||
positionsIMUnav(:,i) = currentPoseGlobalIMUnav.translation.vector;
|
||||
positions(:,i) = currentPoseGlobal.translation;
|
||||
positionsIMUbody(:,i) = currentPoseGlobalIMUbody.translation;
|
||||
positionsIMUnav(:,i) = currentPoseGlobalIMUnav.translation;
|
||||
% -
|
||||
poses(i).p = positions(:,i);
|
||||
posesIMUbody(i).p = positionsIMUbody(:,i);
|
||||
|
|
|
@ -120,7 +120,7 @@ for i=1:size(trajectory)-1
|
|||
end
|
||||
|
||||
% current ground-truth position indicator
|
||||
h_cursor = plot3(a1, pose_t.x,pose_t.y,pose_t.z,'*');
|
||||
h_cursor = plot3(a1, pose_t(1),pose_t(2),pose_t(3),'*');
|
||||
|
||||
camera_pose = pose.compose(camera_transform);
|
||||
|
||||
|
@ -198,7 +198,7 @@ for i=1:size(trajectory)-1
|
|||
if ~result.exists(lKey)
|
||||
p = landmarks.atPoint3(lKey);
|
||||
n = normrnd(0,landmark_noise,3,1);
|
||||
noisy_landmark = Point3(p.x()+n(1),p.y()+n(2),p.z()+n(3));
|
||||
noisy_landmark = p + n;
|
||||
initial.insert(lKey, noisy_landmark);
|
||||
|
||||
% and add a prior since its position is known
|
||||
|
@ -245,32 +245,33 @@ for i=1:size(trajectory)-1
|
|||
initial = Values;
|
||||
fg = NonlinearFactorGraph;
|
||||
|
||||
currentVelocityGlobal = result.at(currentVelKey);
|
||||
currentBias = result.at(currentBiasKey);
|
||||
currentVelocityGlobal = result.atPoint3(currentVelKey);
|
||||
currentBias = result.atConstantBias(currentBiasKey);
|
||||
|
||||
%% plot current pose result
|
||||
isam_pose = result.at(xKey);
|
||||
isam_pose = result.atPose3(xKey);
|
||||
pose_t = isam_pose.translation();
|
||||
|
||||
if exist('h_result','var')
|
||||
delete(h_result);
|
||||
end
|
||||
|
||||
h_result = plot3(a1, pose_t.x,pose_t.y,pose_t.z,'^b', 'MarkerSize', 10);
|
||||
h_result = plot3(a1, pose_t(1),pose_t(2),pose_t(3),'^b', 'MarkerSize', 10);
|
||||
title(a1, sprintf('Step %d', i));
|
||||
|
||||
if exist('h_text1(1)', 'var')
|
||||
delete(h_text1(1));
|
||||
% delete(h_text2(1));
|
||||
end
|
||||
ty = result.at(transformKey).translation().y();
|
||||
K_estimate = result.at(calibrationKey);
|
||||
t = result.atPose3(transformKey).translation();
|
||||
ty = t(2);
|
||||
K_estimate = result.atCal3_S2(calibrationKey);
|
||||
K_errors = K.localCoordinates(K_estimate);
|
||||
|
||||
camera_transform_estimate = result.at(transformKey);
|
||||
camera_transform_estimate = result.atPose3(transformKey);
|
||||
|
||||
fx = result.at(calibrationKey).fx();
|
||||
fy = result.at(calibrationKey).fy();
|
||||
fx = result.atCal3_S2(calibrationKey).fx();
|
||||
fy = result.atCal3_S2(calibrationKey).fy();
|
||||
% h_text1 = text(-600,0,0,sprintf('Y-Transform(0.0): %0.2f',ty));
|
||||
text(0,1300,0,sprintf('Calibration and IMU-cam transform errors:'));
|
||||
|
||||
|
@ -304,7 +305,7 @@ for i=1:size(trajectory)-1
|
|||
end
|
||||
|
||||
%% print out final camera transform and write video
|
||||
result.at(transformKey);
|
||||
result.atPose3(transformKey);
|
||||
if(write_video)
|
||||
close(videoObj);
|
||||
end
|
|
@ -53,7 +53,7 @@ y_shift = Point3(0,0.5,0);
|
|||
|
||||
% insert shifted points
|
||||
for i=1:nrPoints
|
||||
initial.insert(100+i,landmarks{i}.compose(y_shift));
|
||||
initial.insert(100+i,landmarks{i} + y_shift);
|
||||
end
|
||||
|
||||
figure(1);
|
||||
|
@ -134,7 +134,7 @@ for i=1:steps
|
|||
end
|
||||
if i == 2
|
||||
fg.add(PriorFactorPose3(2, Pose3(Rot3(),Point3(1,0,0)),pose_cov));
|
||||
fg.add(PriorFactorLieVector(currentVelKey, currentVelocityGlobal, sigma_init_v));
|
||||
fg.add(PriorFactorVector(currentVelKey, currentVelocityGlobal, sigma_init_v));
|
||||
fg.add(PriorFactorConstantBias(currentBiasKey, currentBias, sigma_init_b));
|
||||
end
|
||||
if i > 1
|
||||
|
@ -144,7 +144,7 @@ for i=1:steps
|
|||
step = move_circle;
|
||||
end
|
||||
|
||||
initial.insert(i,result.at(i-1).compose(step));
|
||||
initial.insert(i,result.atPose3(i-1).compose(step));
|
||||
fg.add(BetweenFactorPose3(i-1,i, step, covariance));
|
||||
|
||||
deltaT = 1;
|
||||
|
@ -158,10 +158,13 @@ for i=1:steps
|
|||
|
||||
[ currentIMUPoseGlobal, currentVelocityGlobal ] = imuSimulator.integrateTrajectory( ...
|
||||
currentIMUPoseGlobal, omega, velocity, velocity, deltaT);
|
||||
|
||||
currentSummarizedMeasurement = gtsam.ImuFactorPreintegratedMeasurements( ...
|
||||
currentBias, IMU_metadata.AccelerometerSigma.^2 * eye(3), ...
|
||||
IMU_metadata.GyroscopeSigma.^2 * eye(3), IMU_metadata.IntegrationSigma.^2 * eye(3));
|
||||
|
||||
params = gtsam.PreintegrationParams.MakeSharedD(9.81);
|
||||
params.setAccelerometerCovariance(IMU_metadata.AccelerometerSigma.^2 * eye(3));
|
||||
params.setGyroscopeCovariance(IMU_metadata.GyroscopeSigma.^2 * eye(3));
|
||||
params.setIntegrationCovariance(IMU_metadata.IntegrationSigma.^2 * eye(3));
|
||||
currentSummarizedMeasurement = gtsam.PreintegratedImuMeasurements( ...
|
||||
params, currentBias);
|
||||
|
||||
accMeas = acc_omega(1:3)-g;
|
||||
omegaMeas = acc_omega(4:6);
|
||||
|
@ -171,7 +174,7 @@ for i=1:steps
|
|||
fg.add(ImuFactor( ...
|
||||
i-1, currentVelKey-1, ...
|
||||
i, currentVelKey, ...
|
||||
currentBiasKey, currentSummarizedMeasurement, g, w_coriolis));
|
||||
currentBiasKey, currentSummarizedMeasurement));
|
||||
|
||||
% Bias evolution as given in the IMU metadata
|
||||
fg.add(BetweenFactorConstantBias(currentBiasKey-1, currentBiasKey, imuBias.ConstantBias(zeros(3,1), zeros(3,1)), ...
|
||||
|
@ -204,8 +207,8 @@ for i=1:steps
|
|||
initial = Values;
|
||||
fg = NonlinearFactorGraph;
|
||||
|
||||
currentVelocityGlobal = isam.calculateEstimate(currentVelKey);
|
||||
currentBias = isam.calculateEstimate(currentBiasKey);
|
||||
currentVelocityGlobal = isam.calculateEstimate().atVector(currentVelKey);
|
||||
currentBias = isam.calculateEstimate().atConstantBias(currentBiasKey);
|
||||
|
||||
%% Compute some marginals
|
||||
marginal = isam.marginalCovariance(calibrationKey);
|
||||
|
@ -249,10 +252,10 @@ for i=1:steps
|
|||
gtsam.plotPose3(currentIMUPoseGlobal, [], 2);
|
||||
|
||||
%% plot results
|
||||
result_camera_transform = result.at(transformKey);
|
||||
result_camera_transform = result.atPose3(transformKey);
|
||||
for j=1:i
|
||||
gtsam.plotPose3(result.at(j),[],0.5);
|
||||
gtsam.plotPose3(result.at(j).compose(result_camera_transform),[],0.5);
|
||||
gtsam.plotPose3(result.atPose3(j),[],0.5);
|
||||
gtsam.plotPose3(result.atPose3(j).compose(result_camera_transform),[],0.5);
|
||||
end
|
||||
|
||||
xlabel('x (m)');
|
||||
|
@ -265,14 +268,15 @@ for i=1:steps
|
|||
% axis equal
|
||||
|
||||
for l=101:100+nrPoints
|
||||
plotPoint3(result.at(l),'g');
|
||||
plotPoint3(result.atPoint3(l),'g');
|
||||
end
|
||||
|
||||
ty = result.at(transformKey).translation().y();
|
||||
fx = result.at(calibrationKey).fx();
|
||||
fy = result.at(calibrationKey).fy();
|
||||
px = result.at(calibrationKey).px();
|
||||
py = result.at(calibrationKey).py();
|
||||
t = result.atPose3(transformKey).translation();
|
||||
ty = t(2);
|
||||
fx = result.atCal3_S2(calibrationKey).fx();
|
||||
fy = result.atCal3_S2(calibrationKey).fy();
|
||||
px = result.atCal3_S2(calibrationKey).px();
|
||||
py = result.atCal3_S2(calibrationKey).py();
|
||||
text(1,5,5,sprintf('Y-Transform(0.0): %0.2f',ty));
|
||||
text(1,5,3,sprintf('fx(900): %.0f',fx));
|
||||
text(1,5,1,sprintf('fy(900): %.0f',fy));
|
||||
|
@ -342,10 +346,10 @@ end
|
|||
fprintf('Cheirality Exception count: %d\n', cheirality_exception_count);
|
||||
|
||||
disp('Transform after optimization');
|
||||
result.at(transformKey)
|
||||
result.atPose3(transformKey)
|
||||
|
||||
disp('Calibration after optimization');
|
||||
result.at(calibrationKey)
|
||||
result.atCal3_S2(calibrationKey)
|
||||
|
||||
disp('Bias after optimization');
|
||||
currentBias
|
||||
|
|
|
@ -33,7 +33,7 @@ y_shift = Point3(0,1,0);
|
|||
|
||||
% insert shifted points
|
||||
for i=1:nrPoints
|
||||
initial.insert(100+i,landmarks{i}.compose(y_shift));
|
||||
initial.insert(100+i,landmarks{i} + y_shift);
|
||||
end
|
||||
|
||||
figure(1);
|
||||
|
|
|
@ -47,7 +47,7 @@ y_shift = Point3(0,1,0);
|
|||
|
||||
% insert shifted points
|
||||
for i=1:nrPoints
|
||||
initial.insert(100+i,landmarks{i}.compose(y_shift));
|
||||
initial.insert(100+i,landmarks{i} + y_shift);
|
||||
end
|
||||
|
||||
figure(1);
|
||||
|
@ -146,7 +146,8 @@ for i=1:20
|
|||
plotPoint3(result.atPoint3(l),'g');
|
||||
end
|
||||
|
||||
ty = result.atPose3(1000).translation().y();
|
||||
t = result.atPose3(1000).translation();
|
||||
ty = t(2);
|
||||
text(5,5,5,sprintf('Y-Transform: %0.2g',ty));
|
||||
|
||||
if(write_video)
|
||||
|
|
|
@ -25,9 +25,9 @@ for i = 0:measurement_keys.size-1
|
|||
key_index = gtsam.symbolIndex(key);
|
||||
p = landmarks.atPoint3(gtsam.symbol('l',key_index));
|
||||
|
||||
x(i+1) = p.x;
|
||||
y(i+1) = p.y;
|
||||
z(i+1) = p.z;
|
||||
x(i+1) = p(1);
|
||||
y(i+1) = p(2);
|
||||
z(i+1) = p(3);
|
||||
|
||||
end
|
||||
|
||||
|
|
|
@ -11,9 +11,9 @@ function [ measurements ] = project_landmarks( pose, landmarks, K )
|
|||
z = camera.project(landmarks.atPoint3(symbol('l',i)));
|
||||
|
||||
% check bounding box
|
||||
if z.x < 0 || z.x > 1280
|
||||
if z(1) < 0 || z(1) > 1280
|
||||
continue
|
||||
elseif z.y < 0 || z.y > 960
|
||||
elseif z(2) < 0 || z(2) > 960
|
||||
continue
|
||||
end
|
||||
|
||||
|
|
|
@ -50,8 +50,8 @@ result = optimizer.optimize();
|
|||
% Check result
|
||||
CHECK('error',result.atPose2(100).equals(b1,1e-5))
|
||||
CHECK('error',result.atPose2(10).equals(origin,1e-5))
|
||||
CHECK('error',result.atPoint2(1).equals(Point2(0,1),1e-5))
|
||||
CHECK('error',result.atPoint2(2).equals(Point2(0,1),1e-5))
|
||||
CHECK('error',result.atPoint2(1) - Point2(0,1) < 1e-5)
|
||||
CHECK('error',result.atPoint2(2) - Point2(0,1) < 1e-5)
|
||||
CHECK('error',result.atPose2(20).equals(origin,1e-5))
|
||||
CHECK('error',result.atPose2(200).equals(b2,1e-5))
|
||||
|
||||
|
|
|
@ -0,0 +1,107 @@
|
|||
set(GTSAM_PYTHON_BUILD_DIRECTORY ${PROJECT_BINARY_DIR}/python)
|
||||
|
||||
if (NOT GTSAM_BUILD_PYTHON)
|
||||
return()
|
||||
endif()
|
||||
|
||||
# Generate setup.py.
|
||||
file(READ "${PROJECT_SOURCE_DIR}/README.md" README_CONTENTS)
|
||||
configure_file(${PROJECT_SOURCE_DIR}/python/setup.py.in
|
||||
${GTSAM_PYTHON_BUILD_DIRECTORY}/setup.py)
|
||||
|
||||
set(WRAP_USE_CUSTOM_PYTHON_LIBRARY ${GTSAM_USE_CUSTOM_PYTHON_LIBRARY})
|
||||
set(WRAP_PYTHON_VERSION ${GTSAM_PYTHON_VERSION})
|
||||
|
||||
include(PybindWrap)
|
||||
|
||||
add_custom_target(gtsam_header DEPENDS "${PROJECT_SOURCE_DIR}/gtsam/gtsam.i")
|
||||
add_custom_target(gtsam_unstable_header DEPENDS "${PROJECT_SOURCE_DIR}/gtsam_unstable/gtsam_unstable.i")
|
||||
|
||||
# ignoring the non-concrete types (type aliases)
|
||||
set(ignore
|
||||
gtsam::Point2
|
||||
gtsam::Point3
|
||||
gtsam::LieVector
|
||||
gtsam::LieMatrix
|
||||
gtsam::ISAM2ThresholdMapValue
|
||||
gtsam::FactorIndices
|
||||
gtsam::FactorIndexSet
|
||||
gtsam::BetweenFactorPose3s
|
||||
gtsam::Point2Vector
|
||||
gtsam::Pose3Vector
|
||||
gtsam::KeyVector)
|
||||
|
||||
pybind_wrap(gtsam_py # target
|
||||
${PROJECT_SOURCE_DIR}/gtsam/gtsam.i # interface_header
|
||||
"gtsam.cpp" # generated_cpp
|
||||
"gtsam" # module_name
|
||||
"gtsam" # top_namespace
|
||||
"${ignore}" # ignore_classes
|
||||
${PROJECT_SOURCE_DIR}/python/gtsam/gtsam.tpl
|
||||
gtsam # libs
|
||||
"gtsam;gtsam_header" # dependencies
|
||||
ON # use_boost
|
||||
)
|
||||
|
||||
set_target_properties(gtsam_py PROPERTIES
|
||||
INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib"
|
||||
INSTALL_RPATH_USE_LINK_PATH TRUE
|
||||
OUTPUT_NAME "gtsam"
|
||||
LIBRARY_OUTPUT_DIRECTORY "${GTSAM_PYTHON_BUILD_DIRECTORY}/gtsam"
|
||||
DEBUG_POSTFIX "" # Otherwise you will have a wrong name
|
||||
RELWITHDEBINFO_POSTFIX "" # Otherwise you will have a wrong name
|
||||
)
|
||||
|
||||
set(GTSAM_MODULE_PATH ${GTSAM_PYTHON_BUILD_DIRECTORY}/gtsam)
|
||||
|
||||
# Symlink all tests .py files to build folder.
|
||||
create_symlinks("${CMAKE_CURRENT_SOURCE_DIR}/gtsam"
|
||||
"${GTSAM_MODULE_PATH}")
|
||||
|
||||
if(GTSAM_UNSTABLE_BUILD_PYTHON)
|
||||
set(ignore
|
||||
gtsam::Point2
|
||||
gtsam::Point3
|
||||
gtsam::LieVector
|
||||
gtsam::LieMatrix
|
||||
gtsam::ISAM2ThresholdMapValue
|
||||
gtsam::FactorIndices
|
||||
gtsam::FactorIndexSet
|
||||
gtsam::BetweenFactorPose3s
|
||||
gtsam::Point2Vector
|
||||
gtsam::Pose3Vector
|
||||
gtsam::KeyVector
|
||||
gtsam::FixedLagSmootherKeyTimestampMapValue)
|
||||
pybind_wrap(gtsam_unstable_py # target
|
||||
${PROJECT_SOURCE_DIR}/gtsam_unstable/gtsam_unstable.i # interface_header
|
||||
"gtsam_unstable.cpp" # generated_cpp
|
||||
"gtsam_unstable" # module_name
|
||||
"gtsam" # top_namespace
|
||||
"${ignore}" # ignore_classes
|
||||
${PROJECT_SOURCE_DIR}/python/gtsam_unstable/gtsam_unstable.tpl
|
||||
gtsam_unstable # libs
|
||||
"gtsam_unstable;gtsam_unstable_header" # dependencies
|
||||
ON # use_boost
|
||||
)
|
||||
|
||||
set_target_properties(gtsam_unstable_py PROPERTIES
|
||||
INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib"
|
||||
INSTALL_RPATH_USE_LINK_PATH TRUE
|
||||
OUTPUT_NAME "gtsam_unstable"
|
||||
LIBRARY_OUTPUT_DIRECTORY "${GTSAM_PYTHON_BUILD_DIRECTORY}/gtsam_unstable"
|
||||
DEBUG_POSTFIX "" # Otherwise you will have a wrong name
|
||||
RELWITHDEBINFO_POSTFIX "" # Otherwise you will have a wrong name
|
||||
)
|
||||
|
||||
set(GTSAM_UNSTABLE_MODULE_PATH ${GTSAM_PYTHON_BUILD_DIRECTORY}/gtsam_unstable)
|
||||
|
||||
# Symlink all tests .py files to build folder.
|
||||
create_symlinks("${CMAKE_CURRENT_SOURCE_DIR}/gtsam_unstable"
|
||||
"${GTSAM_UNSTABLE_MODULE_PATH}")
|
||||
endif()
|
||||
|
||||
set(GTSAM_PYTHON_INSTALL_TARGET python-install)
|
||||
add_custom_target(${GTSAM_PYTHON_INSTALL_TARGET}
|
||||
COMMAND ${PYTHON_EXECUTABLE} ${GTSAM_PYTHON_BUILD_DIRECTORY}/setup.py install
|
||||
DEPENDS gtsam_py gtsam_unstable_py
|
||||
WORKING_DIRECTORY ${GTSAM_PYTHON_BUILD_DIRECTORY})
|
|
@ -0,0 +1,65 @@
|
|||
# README
|
||||
|
||||
# Python Wrapper
|
||||
|
||||
This is the Python wrapper around the GTSAM C++ library. We use our custom [wrap library](https://github.com/borglab/wrap) to generate the bindings to the underlying C++ code.
|
||||
|
||||
## Requirements
|
||||
|
||||
- If you want to build the GTSAM python library for a specific python version (eg 3.6),
|
||||
use the `-DGTSAM_PYTHON_VERSION=3.6` option when running `cmake` otherwise the default interpreter will be used.
|
||||
- If the interpreter is inside an environment (such as an anaconda environment or virtualenv environment),
|
||||
then the environment should be active while building GTSAM.
|
||||
- This wrapper needs `pyparsing(>=2.4.2)`, and `numpy(>=1.11.0)`. These can be installed as follows:
|
||||
|
||||
```bash
|
||||
pip install -r <gtsam_folder>/python/requirements.txt
|
||||
```
|
||||
|
||||
## Install
|
||||
|
||||
- Run cmake with the `GTSAM_BUILD_PYTHON` cmake flag enabled to configure building the wrapper. The wrapped module will be built and copied to the directory `<PROJECT_BINARY_DIR>/python`.
|
||||
|
||||
- Build GTSAM and the wrapper with `make` (or `ninja` if you use `-GNinja`).
|
||||
|
||||
- To install, simply run `make python-install` (`ninja python-install`).
|
||||
- The same command can be used to install into a virtual environment if it is active.
|
||||
- **NOTE**: if you don't want GTSAM to install to a system directory such as `/usr/local`, pass `-DCMAKE_INSTALL_PREFIX="./install"` to cmake to install GTSAM to a subdirectory of the build directory.
|
||||
|
||||
- You can also directly run `make python-install` without running `make`, and it will compile all the dependencies accordingly.
|
||||
|
||||
## Unit Tests
|
||||
|
||||
The Python toolbox also has a small set of unit tests located in the
|
||||
test directory. To run them:
|
||||
|
||||
```bash
|
||||
cd <GTSAM_SOURCE_DIRECTORY>/python/gtsam/tests
|
||||
python -m unittest discover
|
||||
```
|
||||
|
||||
## Utils
|
||||
|
||||
TODO
|
||||
|
||||
## Examples
|
||||
|
||||
TODO
|
||||
|
||||
## Writing Your Own Scripts
|
||||
|
||||
See the tests for examples.
|
||||
|
||||
### Some Important Notes:
|
||||
|
||||
- Vector/Matrix:
|
||||
|
||||
- GTSAM expects double-precision floating point vectors and matrices.
|
||||
Hence, you should pass numpy matrices with `dtype=float`, or `float64`, to avoid any conversion needed.
|
||||
- Also, GTSAM expects _column-major_ matrices, unlike the default storage
|
||||
scheme in numpy. But this is only performance-related as `pybind11` should translate them when needed. However, this will result a copy if your matrix is not in the expected type
|
||||
and storage order.
|
||||
|
||||
## Wrapping Custom GTSAM-based Project
|
||||
|
||||
Please refer to the template project and the corresponding tutorial available [here](https://github.com/borglab/GTSAM-project-python).
|
|
@ -0,0 +1,27 @@
|
|||
from .gtsam import *
|
||||
|
||||
|
||||
def _init():
|
||||
"""This function is to add shims for the long-gone Point2 and Point3 types"""
|
||||
|
||||
import numpy as np
|
||||
|
||||
global Point2 # export function
|
||||
|
||||
def Point2(x=0, y=0):
|
||||
"""Shim for the deleted Point2 type."""
|
||||
return np.array([x, y], dtype=float)
|
||||
|
||||
global Point3 # export function
|
||||
|
||||
def Point3(x=0, y=0, z=0):
|
||||
"""Shim for the deleted Point3 type."""
|
||||
return np.array([x, y, z], dtype=float)
|
||||
|
||||
# for interactive debugging
|
||||
if __name__ == "__main__":
|
||||
# we want all definitions accessible
|
||||
globals().update(locals())
|
||||
|
||||
|
||||
_init()
|
|
@ -35,17 +35,17 @@ def run(args):
|
|||
graph = gtsam.NonlinearFactorGraph()
|
||||
|
||||
# Priors
|
||||
prior = gtsam.noiseModel_Isotropic.Sigma(3, 1)
|
||||
prior = gtsam.noiseModel.Isotropic.Sigma(3, 1)
|
||||
graph.add(gtsam.PriorFactorPose2(11, T11, prior))
|
||||
graph.add(gtsam.PriorFactorPose2(21, T21, prior))
|
||||
|
||||
# Odometry
|
||||
model = gtsam.noiseModel_Diagonal.Sigmas(np.array([0.01, 0.01, 0.3]))
|
||||
model = gtsam.noiseModel.Diagonal.Sigmas(np.array([0.01, 0.01, 0.3]))
|
||||
graph.add(gtsam.BetweenFactorPose2(11, 12, T11.between(T12), model))
|
||||
graph.add(gtsam.BetweenFactorPose2(21, 22, T21.between(T22), model))
|
||||
|
||||
# Range
|
||||
model_rho = gtsam.noiseModel_Isotropic.Sigma(1, 0.01)
|
||||
model_rho = gtsam.noiseModel.Isotropic.Sigma(1, 0.01)
|
||||
graph.add(gtsam.RangeFactorPose2(12, 22, 1.0, model_rho))
|
||||
|
||||
params = gtsam.DoglegParams()
|
|
@ -26,8 +26,8 @@ lon0 = -84.30626
|
|||
h0 = 274
|
||||
|
||||
# Create noise models
|
||||
GPS_NOISE = gtsam.noiseModel_Isotropic.Sigma(3, 0.1)
|
||||
PRIOR_NOISE = gtsam.noiseModel_Isotropic.Sigma(6, 0.25)
|
||||
GPS_NOISE = gtsam.noiseModel.Isotropic.Sigma(3, 0.1)
|
||||
PRIOR_NOISE = gtsam.noiseModel.Isotropic.Sigma(6, 0.25)
|
||||
|
||||
# Create an empty nonlinear factor graph
|
||||
graph = gtsam.NonlinearFactorGraph()
|
|
@ -0,0 +1,180 @@
|
|||
"""
|
||||
GTSAM Copyright 2010-2019, Georgia Tech Research Corporation,
|
||||
Atlanta, Georgia 30332-0415
|
||||
All Rights Reserved
|
||||
|
||||
See LICENSE for the license information
|
||||
|
||||
A script validating and demonstrating the ImuFactor inference.
|
||||
|
||||
Author: Frank Dellaert, Varun Agrawal
|
||||
"""
|
||||
|
||||
from __future__ import print_function
|
||||
|
||||
import argparse
|
||||
import math
|
||||
|
||||
import gtsam
|
||||
import matplotlib.pyplot as plt
|
||||
import numpy as np
|
||||
from gtsam.symbol_shorthand import B, V, X
|
||||
from gtsam.utils.plot import plot_pose3
|
||||
from mpl_toolkits.mplot3d import Axes3D
|
||||
|
||||
from PreintegrationExample import POSES_FIG, PreintegrationExample
|
||||
|
||||
BIAS_KEY = B(0)
|
||||
|
||||
|
||||
np.set_printoptions(precision=3, suppress=True)
|
||||
|
||||
|
||||
class ImuFactorExample(PreintegrationExample):
|
||||
|
||||
def __init__(self, twist_scenario="sick_twist"):
|
||||
self.velocity = np.array([2, 0, 0])
|
||||
self.priorNoise = gtsam.noiseModel.Isotropic.Sigma(6, 0.1)
|
||||
self.velNoise = gtsam.noiseModel.Isotropic.Sigma(3, 0.1)
|
||||
|
||||
# Choose one of these twists to change scenario:
|
||||
twist_scenarios = dict(
|
||||
zero_twist=(np.zeros(3), np.zeros(3)),
|
||||
forward_twist=(np.zeros(3), self.velocity),
|
||||
loop_twist=(np.array([0, -math.radians(30), 0]), self.velocity),
|
||||
sick_twist=(np.array([math.radians(30), -math.radians(30), 0]),
|
||||
self.velocity)
|
||||
)
|
||||
|
||||
accBias = np.array([-0.3, 0.1, 0.2])
|
||||
gyroBias = np.array([0.1, 0.3, -0.1])
|
||||
bias = gtsam.imuBias.ConstantBias(accBias, gyroBias)
|
||||
|
||||
dt = 1e-2
|
||||
super(ImuFactorExample, self).__init__(twist_scenarios[twist_scenario],
|
||||
bias, dt)
|
||||
|
||||
def addPrior(self, i, graph):
|
||||
state = self.scenario.navState(i)
|
||||
graph.push_back(gtsam.PriorFactorPose3(
|
||||
X(i), state.pose(), self.priorNoise))
|
||||
graph.push_back(gtsam.PriorFactorVector(
|
||||
V(i), state.velocity(), self.velNoise))
|
||||
|
||||
def run(self, T=12, compute_covariances=False, verbose=True):
|
||||
graph = gtsam.NonlinearFactorGraph()
|
||||
|
||||
# initialize data structure for pre-integrated IMU measurements
|
||||
pim = gtsam.PreintegratedImuMeasurements(self.params, self.actualBias)
|
||||
|
||||
T = 12
|
||||
num_poses = T # assumes 1 factor per second
|
||||
initial = gtsam.Values()
|
||||
initial.insert(BIAS_KEY, self.actualBias)
|
||||
|
||||
# simulate the loop
|
||||
i = 0 # state index
|
||||
initial_state_i = self.scenario.navState(0)
|
||||
initial.insert(X(i), initial_state_i.pose())
|
||||
initial.insert(V(i), initial_state_i.velocity())
|
||||
|
||||
# add prior on beginning
|
||||
self.addPrior(0, graph)
|
||||
|
||||
for k, t in enumerate(np.arange(0, T, self.dt)):
|
||||
# get measurements and add them to PIM
|
||||
measuredOmega = self.runner.measuredAngularVelocity(t)
|
||||
measuredAcc = self.runner.measuredSpecificForce(t)
|
||||
pim.integrateMeasurement(measuredAcc, measuredOmega, self.dt)
|
||||
|
||||
# Plot IMU many times
|
||||
if k % 10 == 0:
|
||||
self.plotImu(t, measuredOmega, measuredAcc)
|
||||
|
||||
if (k+1) % int(1 / self.dt) == 0:
|
||||
# Plot every second
|
||||
self.plotGroundTruthPose(t, scale=1)
|
||||
plt.title("Ground Truth Trajectory")
|
||||
|
||||
# create IMU factor every second
|
||||
factor = gtsam.ImuFactor(X(i), V(i),
|
||||
X(i + 1), V(i + 1),
|
||||
BIAS_KEY, pim)
|
||||
graph.push_back(factor)
|
||||
|
||||
if verbose:
|
||||
print(factor)
|
||||
print(pim.predict(actual_state_i, self.actualBias))
|
||||
|
||||
pim.resetIntegration()
|
||||
|
||||
rotationNoise = gtsam.Rot3.Expmap(np.random.randn(3)*0.1)
|
||||
translationNoise = gtsam.Point3(*np.random.randn(3)*1)
|
||||
poseNoise = gtsam.Pose3(rotationNoise, translationNoise)
|
||||
|
||||
actual_state_i = self.scenario.navState(t + self.dt)
|
||||
print("Actual state at {0}:\n{1}".format(
|
||||
t+self.dt, actual_state_i))
|
||||
|
||||
noisy_state_i = gtsam.NavState(
|
||||
actual_state_i.pose().compose(poseNoise),
|
||||
actual_state_i.velocity() + np.random.randn(3)*0.1)
|
||||
|
||||
initial.insert(X(i+1), noisy_state_i.pose())
|
||||
initial.insert(V(i+1), noisy_state_i.velocity())
|
||||
i += 1
|
||||
|
||||
# add priors on end
|
||||
# self.addPrior(num_poses - 1, graph)
|
||||
|
||||
initial.print_("Initial values:")
|
||||
|
||||
# optimize using Levenberg-Marquardt optimization
|
||||
params = gtsam.LevenbergMarquardtParams()
|
||||
params.setVerbosityLM("SUMMARY")
|
||||
optimizer = gtsam.LevenbergMarquardtOptimizer(graph, initial, params)
|
||||
result = optimizer.optimize()
|
||||
|
||||
result.print_("Optimized values:")
|
||||
|
||||
if compute_covariances:
|
||||
# Calculate and print marginal covariances
|
||||
marginals = gtsam.Marginals(graph, result)
|
||||
print("Covariance on bias:\n",
|
||||
marginals.marginalCovariance(BIAS_KEY))
|
||||
for i in range(num_poses):
|
||||
print("Covariance on pose {}:\n{}\n".format(
|
||||
i, marginals.marginalCovariance(X(i))))
|
||||
print("Covariance on vel {}:\n{}\n".format(
|
||||
i, marginals.marginalCovariance(V(i))))
|
||||
|
||||
# Plot resulting poses
|
||||
i = 0
|
||||
while result.exists(X(i)):
|
||||
pose_i = result.atPose3(X(i))
|
||||
plot_pose3(POSES_FIG+1, pose_i, 1)
|
||||
i += 1
|
||||
plt.title("Estimated Trajectory")
|
||||
|
||||
gtsam.utils.plot.set_axes_equal(POSES_FIG+1)
|
||||
|
||||
print("Bias Values", result.atConstantBias(BIAS_KEY))
|
||||
|
||||
plt.ioff()
|
||||
plt.show()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
parser = argparse.ArgumentParser("ImuFactorExample.py")
|
||||
parser.add_argument("--twist_scenario",
|
||||
default="sick_twist",
|
||||
choices=("zero_twist", "forward_twist", "loop_twist", "sick_twist"))
|
||||
parser.add_argument("--time", "-T", default=12,
|
||||
type=int, help="Total time in seconds")
|
||||
parser.add_argument("--compute_covariances",
|
||||
default=False, action='store_true')
|
||||
parser.add_argument("--verbose", default=False, action='store_true')
|
||||
args = parser.parse_args()
|
||||
|
||||
ImuFactorExample(args.twist_scenario).run(
|
||||
args.time, args.compute_covariances, args.verbose)
|
|
@ -1,6 +1,6 @@
|
|||
"""
|
||||
iSAM2 example with ImuFactor.
|
||||
Author: Robert Truax (C++), Frank Dellaert (Python)
|
||||
Author: Robert Truax (C++), Frank Dellaert, Varun Agrawal
|
||||
"""
|
||||
# pylint: disable=invalid-name, E1101
|
||||
|
||||
|
@ -9,7 +9,6 @@ from __future__ import print_function
|
|||
import math
|
||||
|
||||
import gtsam
|
||||
import gtsam.utils.plot as gtsam_plot
|
||||
import matplotlib.pyplot as plt
|
||||
import numpy as np
|
||||
from gtsam import (ISAM2, BetweenFactorConstantBias, Cal3_S2,
|
||||
|
@ -17,9 +16,8 @@ from gtsam import (ISAM2, BetweenFactorConstantBias, Cal3_S2,
|
|||
PinholeCameraCal3_S2, Point3, Pose3,
|
||||
PriorFactorConstantBias, PriorFactorPose3,
|
||||
PriorFactorVector, Rot3, Values)
|
||||
from gtsam import symbol_shorthand_B as B
|
||||
from gtsam import symbol_shorthand_V as V
|
||||
from gtsam import symbol_shorthand_X as X
|
||||
from gtsam.symbol_shorthand import B, V, X
|
||||
from gtsam.utils import plot
|
||||
from mpl_toolkits.mplot3d import Axes3D # pylint: disable=W0611
|
||||
|
||||
|
||||
|
@ -28,46 +26,45 @@ def vector3(x, y, z):
|
|||
return np.array([x, y, z], dtype=np.float)
|
||||
|
||||
|
||||
def ISAM2_plot(values, fignum=0):
|
||||
"""Plot poses."""
|
||||
fig = plt.figure(fignum)
|
||||
axes = fig.gca(projection='3d')
|
||||
plt.cla()
|
||||
|
||||
i = 0
|
||||
min_bounds = 0, 0, 0
|
||||
max_bounds = 0, 0, 0
|
||||
while values.exists(X(i)):
|
||||
pose_i = values.atPose3(X(i))
|
||||
gtsam_plot.plot_pose3(fignum, pose_i, 10)
|
||||
position = pose_i.translation().vector()
|
||||
min_bounds = [min(v1, v2) for (v1, v2) in zip(position, min_bounds)]
|
||||
max_bounds = [max(v1, v2) for (v1, v2) in zip(position, max_bounds)]
|
||||
# max_bounds = min(pose_i.x(), max_bounds[0]), 0, 0
|
||||
i += 1
|
||||
|
||||
# draw
|
||||
axes.set_xlim3d(min_bounds[0]-1, max_bounds[0]+1)
|
||||
axes.set_ylim3d(min_bounds[1]-1, max_bounds[1]+1)
|
||||
axes.set_zlim3d(min_bounds[2]-1, max_bounds[2]+1)
|
||||
plt.pause(1)
|
||||
|
||||
|
||||
# IMU preintegration parameters
|
||||
# Default Params for a Z-up navigation frame, such as ENU: gravity points along negative Z-axis
|
||||
g = 9.81
|
||||
n_gravity = vector3(0, 0, -g)
|
||||
PARAMS = gtsam.PreintegrationParams.MakeSharedU(g)
|
||||
I = np.eye(3)
|
||||
PARAMS.setAccelerometerCovariance(I * 0.1)
|
||||
PARAMS.setGyroscopeCovariance(I * 0.1)
|
||||
PARAMS.setIntegrationCovariance(I * 0.1)
|
||||
PARAMS.setUse2ndOrderCoriolis(False)
|
||||
PARAMS.setOmegaCoriolis(vector3(0, 0, 0))
|
||||
|
||||
BIAS_COVARIANCE = gtsam.noiseModel_Isotropic.Variance(6, 0.1)
|
||||
DELTA = Pose3(Rot3.Rodrigues(0, 0, 0),
|
||||
Point3(0.05, -0.10, 0.20))
|
||||
|
||||
def preintegration_parameters():
|
||||
# IMU preintegration parameters
|
||||
# Default Params for a Z-up navigation frame, such as ENU: gravity points along negative Z-axis
|
||||
PARAMS = gtsam.PreintegrationParams.MakeSharedU(g)
|
||||
I = np.eye(3)
|
||||
PARAMS.setAccelerometerCovariance(I * 0.1)
|
||||
PARAMS.setGyroscopeCovariance(I * 0.1)
|
||||
PARAMS.setIntegrationCovariance(I * 0.1)
|
||||
PARAMS.setUse2ndOrderCoriolis(False)
|
||||
PARAMS.setOmegaCoriolis(vector3(0, 0, 0))
|
||||
|
||||
BIAS_COVARIANCE = gtsam.noiseModel.Isotropic.Variance(6, 0.1)
|
||||
DELTA = Pose3(Rot3.Rodrigues(0, 0, 0),
|
||||
Point3(0.05, -0.10, 0.20))
|
||||
|
||||
return PARAMS, BIAS_COVARIANCE, DELTA
|
||||
|
||||
|
||||
def get_camera(radius):
|
||||
up = Point3(0, 0, 1)
|
||||
target = Point3(0, 0, 0)
|
||||
position = Point3(radius, 0, 0)
|
||||
camera = PinholeCameraCal3_S2.Lookat(position, target, up, Cal3_S2())
|
||||
return camera
|
||||
|
||||
|
||||
def get_scenario(radius, pose_0, angular_velocity, delta_t):
|
||||
"""Create the set of ground-truth landmarks and poses"""
|
||||
|
||||
angular_velocity_vector = vector3(0, -angular_velocity, 0)
|
||||
linear_velocity_vector = vector3(radius * angular_velocity, 0, 0)
|
||||
scenario = ConstantTwistScenario(
|
||||
angular_velocity_vector, linear_velocity_vector, pose_0)
|
||||
|
||||
return scenario
|
||||
|
||||
|
||||
def IMU_example():
|
||||
|
@ -75,23 +72,17 @@ def IMU_example():
|
|||
|
||||
# Start with a camera on x-axis looking at origin
|
||||
radius = 30
|
||||
up = Point3(0, 0, 1)
|
||||
target = Point3(0, 0, 0)
|
||||
position = Point3(radius, 0, 0)
|
||||
camera = PinholeCameraCal3_S2.Lookat(position, target, up, Cal3_S2())
|
||||
camera = get_camera(radius)
|
||||
pose_0 = camera.pose()
|
||||
|
||||
# Create the set of ground-truth landmarks and poses
|
||||
angular_velocity = math.radians(180) # rad/sec
|
||||
delta_t = 1.0/18 # makes for 10 degrees per step
|
||||
angular_velocity = math.radians(180) # rad/sec
|
||||
scenario = get_scenario(radius, pose_0, angular_velocity, delta_t)
|
||||
|
||||
angular_velocity_vector = vector3(0, -angular_velocity, 0)
|
||||
linear_velocity_vector = vector3(radius * angular_velocity, 0, 0)
|
||||
scenario = ConstantTwistScenario(
|
||||
angular_velocity_vector, linear_velocity_vector, pose_0)
|
||||
PARAMS, BIAS_COVARIANCE, DELTA = preintegration_parameters()
|
||||
|
||||
# Create a factor graph
|
||||
newgraph = NonlinearFactorGraph()
|
||||
graph = NonlinearFactorGraph()
|
||||
|
||||
# Create (incremental) ISAM2 solver
|
||||
isam = ISAM2()
|
||||
|
@ -102,23 +93,23 @@ def IMU_example():
|
|||
|
||||
# Add a prior on pose x0. This indirectly specifies where the origin is.
|
||||
# 30cm std on x,y,z 0.1 rad on roll,pitch,yaw
|
||||
noise = gtsam.noiseModel_Diagonal.Sigmas(
|
||||
noise = gtsam.noiseModel.Diagonal.Sigmas(
|
||||
np.array([0.1, 0.1, 0.1, 0.3, 0.3, 0.3]))
|
||||
newgraph.push_back(PriorFactorPose3(X(0), pose_0, noise))
|
||||
graph.push_back(PriorFactorPose3(X(0), pose_0, noise))
|
||||
|
||||
# Add imu priors
|
||||
biasKey = B(0)
|
||||
biasnoise = gtsam.noiseModel_Isotropic.Sigma(6, 0.1)
|
||||
biasprior = PriorFactorConstantBias(biasKey, gtsam.imuBias_ConstantBias(),
|
||||
biasnoise = gtsam.noiseModel.Isotropic.Sigma(6, 0.1)
|
||||
biasprior = PriorFactorConstantBias(biasKey, gtsam.imuBias.ConstantBias(),
|
||||
biasnoise)
|
||||
newgraph.push_back(biasprior)
|
||||
initialEstimate.insert(biasKey, gtsam.imuBias_ConstantBias())
|
||||
velnoise = gtsam.noiseModel_Isotropic.Sigma(3, 0.1)
|
||||
graph.push_back(biasprior)
|
||||
initialEstimate.insert(biasKey, gtsam.imuBias.ConstantBias())
|
||||
velnoise = gtsam.noiseModel.Isotropic.Sigma(3, 0.1)
|
||||
|
||||
# Calculate with correct initial velocity
|
||||
n_velocity = vector3(0, angular_velocity * radius, 0)
|
||||
velprior = PriorFactorVector(V(0), n_velocity, velnoise)
|
||||
newgraph.push_back(velprior)
|
||||
graph.push_back(velprior)
|
||||
initialEstimate.insert(V(0), n_velocity)
|
||||
|
||||
accum = gtsam.PreintegratedImuMeasurements(PARAMS)
|
||||
|
@ -139,9 +130,9 @@ def IMU_example():
|
|||
if i % 5 == 0:
|
||||
biasKey += 1
|
||||
factor = BetweenFactorConstantBias(
|
||||
biasKey - 1, biasKey, gtsam.imuBias_ConstantBias(), BIAS_COVARIANCE)
|
||||
newgraph.add(factor)
|
||||
initialEstimate.insert(biasKey, gtsam.imuBias_ConstantBias())
|
||||
biasKey - 1, biasKey, gtsam.imuBias.ConstantBias(), BIAS_COVARIANCE)
|
||||
graph.add(factor)
|
||||
initialEstimate.insert(biasKey, gtsam.imuBias.ConstantBias())
|
||||
|
||||
# Predict acceleration and gyro measurements in (actual) body frame
|
||||
nRb = scenario.rotation(t).matrix()
|
||||
|
@ -152,21 +143,24 @@ def IMU_example():
|
|||
|
||||
# Add Imu Factor
|
||||
imufac = ImuFactor(X(i - 1), V(i - 1), X(i), V(i), biasKey, accum)
|
||||
newgraph.add(imufac)
|
||||
graph.add(imufac)
|
||||
|
||||
# insert new velocity, which is wrong
|
||||
initialEstimate.insert(V(i), n_velocity)
|
||||
accum.resetIntegration()
|
||||
|
||||
# Incremental solution
|
||||
isam.update(newgraph, initialEstimate)
|
||||
isam.update(graph, initialEstimate)
|
||||
result = isam.calculateEstimate()
|
||||
ISAM2_plot(result)
|
||||
plot.plot_incremental_trajectory(0, result,
|
||||
start=i, scale=3, time_interval=0.01)
|
||||
|
||||
# reset
|
||||
newgraph = NonlinearFactorGraph()
|
||||
graph = NonlinearFactorGraph()
|
||||
initialEstimate.clear()
|
||||
|
||||
plt.show()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
IMU_example()
|
|
@ -21,8 +21,8 @@ import matplotlib.pyplot as plt
|
|||
import gtsam.utils.plot as gtsam_plot
|
||||
|
||||
# Create noise models
|
||||
ODOMETRY_NOISE = gtsam.noiseModel_Diagonal.Sigmas(np.array([0.2, 0.2, 0.1]))
|
||||
PRIOR_NOISE = gtsam.noiseModel_Diagonal.Sigmas(np.array([0.3, 0.3, 0.1]))
|
||||
ODOMETRY_NOISE = gtsam.noiseModel.Diagonal.Sigmas(np.array([0.2, 0.2, 0.1]))
|
||||
PRIOR_NOISE = gtsam.noiseModel.Diagonal.Sigmas(np.array([0.3, 0.3, 0.1]))
|
||||
|
||||
# Create an empty nonlinear factor graph
|
||||
graph = gtsam.NonlinearFactorGraph()
|
|
@ -167,13 +167,11 @@ class ThreeLinkArm(object):
|
|||
axes = fig.gca()
|
||||
|
||||
sXl1 = Pose2(0, 0, math.radians(90))
|
||||
t = sXl1.translation()
|
||||
p1 = np.array([t.x(), t.y()])
|
||||
p1 = sXl1.translation()
|
||||
gtsam_plot.plot_pose2_on_axes(axes, sXl1)
|
||||
|
||||
def plot_line(p, g, color):
|
||||
t = g.translation()
|
||||
q = np.array([t.x(), t.y()])
|
||||
q = g.translation()
|
||||
line = np.append(p[np.newaxis], q[np.newaxis], axis=0)
|
||||
axes.plot(line[:, 0], line[:, 1], color)
|
||||
return q
|
|
@ -13,15 +13,15 @@ Author: Alex Cunningham (C++), Kevin Deng & Frank Dellaert (Python)
|
|||
|
||||
from __future__ import print_function
|
||||
|
||||
import gtsam
|
||||
import numpy as np
|
||||
from gtsam import symbol_shorthand_L as L
|
||||
from gtsam import symbol_shorthand_X as X
|
||||
|
||||
import gtsam
|
||||
from gtsam.symbol_shorthand import X, L
|
||||
|
||||
# Create noise models
|
||||
PRIOR_NOISE = gtsam.noiseModel_Diagonal.Sigmas(np.array([0.3, 0.3, 0.1]))
|
||||
ODOMETRY_NOISE = gtsam.noiseModel_Diagonal.Sigmas(np.array([0.2, 0.2, 0.1]))
|
||||
MEASUREMENT_NOISE = gtsam.noiseModel_Diagonal.Sigmas(np.array([0.1, 0.2]))
|
||||
PRIOR_NOISE = gtsam.noiseModel.Diagonal.Sigmas(np.array([0.3, 0.3, 0.1]))
|
||||
ODOMETRY_NOISE = gtsam.noiseModel.Diagonal.Sigmas(np.array([0.2, 0.2, 0.1]))
|
||||
MEASUREMENT_NOISE = gtsam.noiseModel.Diagonal.Sigmas(np.array([0.1, 0.2]))
|
||||
|
||||
# Create an empty nonlinear factor graph
|
||||
graph = gtsam.NonlinearFactorGraph()
|
|
@ -27,10 +27,9 @@ def vector3(x, y, z):
|
|||
"""Create 3d double numpy array."""
|
||||
return np.array([x, y, z], dtype=np.float)
|
||||
|
||||
|
||||
# Create noise models
|
||||
PRIOR_NOISE = gtsam.noiseModel_Diagonal.Sigmas(vector3(0.3, 0.3, 0.1))
|
||||
ODOMETRY_NOISE = gtsam.noiseModel_Diagonal.Sigmas(vector3(0.2, 0.2, 0.1))
|
||||
PRIOR_NOISE = gtsam.noiseModel.Diagonal.Sigmas(vector3(0.3, 0.3, 0.1))
|
||||
ODOMETRY_NOISE = gtsam.noiseModel.Diagonal.Sigmas(vector3(0.2, 0.2, 0.1))
|
||||
|
||||
# 1. Create a factor graph container and add factors to it
|
||||
graph = gtsam.NonlinearFactorGraph()
|
|
@ -53,7 +53,7 @@ graph, initial = gtsam.readG2o(g2oFile, is3D)
|
|||
assert args.kernel == "none", "Supplied kernel type is not yet implemented"
|
||||
|
||||
# Add prior on the pose having index (key) = 0
|
||||
priorModel = gtsam.noiseModel_Diagonal.Variances(vector3(1e-6, 1e-6, 1e-8))
|
||||
priorModel = gtsam.noiseModel.Diagonal.Variances(vector3(1e-6, 1e-6, 1e-8))
|
||||
graph.add(gtsam.PriorFactorPose2(0, gtsam.Pose2(), priorModel))
|
||||
|
||||
params = gtsam.GaussNewtonParams()
|
||||
|
@ -82,7 +82,7 @@ else:
|
|||
print ("Done!")
|
||||
|
||||
if args.plot:
|
||||
resultPoses = gtsam.utilities_extractPose2(result)
|
||||
resultPoses = gtsam.utilities.extractPose2(result)
|
||||
for i in range(resultPoses.shape[0]):
|
||||
plot.plot_pose2(1, gtsam.Pose2(resultPoses[i, :]))
|
||||
plt.show()
|
|
@ -39,11 +39,11 @@ is3D = True
|
|||
graph, initial = gtsam.readG2o(g2oFile, is3D)
|
||||
|
||||
# Add Prior on the first key
|
||||
priorModel = gtsam.noiseModel_Diagonal.Variances(vector6(1e-6, 1e-6, 1e-6,
|
||||
priorModel = gtsam.noiseModel.Diagonal.Variances(vector6(1e-6, 1e-6, 1e-6,
|
||||
1e-4, 1e-4, 1e-4))
|
||||
|
||||
print("Adding prior to g2o file ")
|
||||
firstKey = initial.keys().at(0)
|
||||
firstKey = initial.keys()[0]
|
||||
graph.add(gtsam.PriorFactorPose3(firstKey, gtsam.Pose3(), priorModel))
|
||||
|
||||
params = gtsam.GaussNewtonParams()
|
||||
|
@ -65,7 +65,7 @@ else:
|
|||
print ("Done!")
|
||||
|
||||
if args.plot:
|
||||
resultPoses = gtsam.utilities_allPose3s(result)
|
||||
resultPoses = gtsam.utilities.allPose3s(result)
|
||||
for i in range(resultPoses.size()):
|
||||
plot.plot_pose3(1, resultPoses.atPose3(i))
|
||||
plt.show()
|
|
@ -24,9 +24,9 @@ is3D = True
|
|||
graph, initial = gtsam.readG2o(g2oFile, is3D)
|
||||
|
||||
# Add prior on the first key. TODO: assumes first key ios z
|
||||
priorModel = gtsam.noiseModel_Diagonal.Variances(
|
||||
priorModel = gtsam.noiseModel.Diagonal.Variances(
|
||||
np.array([1e-6, 1e-6, 1e-6, 1e-4, 1e-4, 1e-4]))
|
||||
firstKey = initial.keys().at(0)
|
||||
firstKey = initial.keys()[0]
|
||||
graph.add(gtsam.PriorFactorPose3(0, gtsam.Pose3(), priorModel))
|
||||
|
||||
# Initializing Pose3 - chordal relaxation"
|
|
@ -10,12 +10,11 @@ A script validating the Preintegration of IMU measurements
|
|||
|
||||
import math
|
||||
|
||||
import gtsam
|
||||
import matplotlib.pyplot as plt
|
||||
import numpy as np
|
||||
from mpl_toolkits.mplot3d import Axes3D
|
||||
|
||||
import gtsam
|
||||
from gtsam.utils.plot import plot_pose3
|
||||
from mpl_toolkits.mplot3d import Axes3D
|
||||
|
||||
IMU_FIG = 1
|
||||
POSES_FIG = 2
|
||||
|
@ -68,60 +67,62 @@ class PreintegrationExample(object):
|
|||
else:
|
||||
accBias = np.array([0, 0.1, 0])
|
||||
gyroBias = np.array([0, 0, 0])
|
||||
self.actualBias = gtsam.imuBias_ConstantBias(accBias, gyroBias)
|
||||
self.actualBias = gtsam.imuBias.ConstantBias(accBias, gyroBias)
|
||||
|
||||
self.runner = gtsam.ScenarioRunner(
|
||||
self.scenario, self.params, self.dt, self.actualBias)
|
||||
|
||||
fig, self.axes = plt.subplots(4, 3)
|
||||
fig.set_tight_layout(True)
|
||||
|
||||
def plotImu(self, t, measuredOmega, measuredAcc):
|
||||
plt.figure(IMU_FIG)
|
||||
|
||||
# plot angular velocity
|
||||
omega_b = self.scenario.omega_b(t)
|
||||
for i, (label, color) in enumerate(zip(self.labels, self.colors)):
|
||||
plt.subplot(4, 3, i + 1)
|
||||
plt.scatter(t, omega_b[i], color='k', marker='.')
|
||||
plt.scatter(t, measuredOmega[i], color=color, marker='.')
|
||||
plt.xlabel('angular velocity ' + label)
|
||||
ax = self.axes[0][i]
|
||||
ax.scatter(t, omega_b[i], color='k', marker='.')
|
||||
ax.scatter(t, measuredOmega[i], color=color, marker='.')
|
||||
ax.set_xlabel('angular velocity ' + label)
|
||||
|
||||
# plot acceleration in nav
|
||||
acceleration_n = self.scenario.acceleration_n(t)
|
||||
for i, (label, color) in enumerate(zip(self.labels, self.colors)):
|
||||
plt.subplot(4, 3, i + 4)
|
||||
plt.scatter(t, acceleration_n[i], color=color, marker='.')
|
||||
plt.xlabel('acceleration in nav ' + label)
|
||||
ax = self.axes[1][i]
|
||||
ax.scatter(t, acceleration_n[i], color=color, marker='.')
|
||||
ax.set_xlabel('acceleration in nav ' + label)
|
||||
|
||||
# plot acceleration in body
|
||||
acceleration_b = self.scenario.acceleration_b(t)
|
||||
for i, (label, color) in enumerate(zip(self.labels, self.colors)):
|
||||
plt.subplot(4, 3, i + 7)
|
||||
plt.scatter(t, acceleration_b[i], color=color, marker='.')
|
||||
plt.xlabel('acceleration in body ' + label)
|
||||
ax = self.axes[2][i]
|
||||
ax.scatter(t, acceleration_b[i], color=color, marker='.')
|
||||
ax.set_xlabel('acceleration in body ' + label)
|
||||
|
||||
# plot actual specific force, as well as corrupted
|
||||
actual = self.runner.actualSpecificForce(t)
|
||||
for i, (label, color) in enumerate(zip(self.labels, self.colors)):
|
||||
plt.subplot(4, 3, i + 10)
|
||||
plt.scatter(t, actual[i], color='k', marker='.')
|
||||
plt.scatter(t, measuredAcc[i], color=color, marker='.')
|
||||
plt.xlabel('specific force ' + label)
|
||||
ax = self.axes[3][i]
|
||||
ax.scatter(t, actual[i], color='k', marker='.')
|
||||
ax.scatter(t, measuredAcc[i], color=color, marker='.')
|
||||
ax.set_xlabel('specific force ' + label)
|
||||
|
||||
def plotGroundTruthPose(self, t):
|
||||
def plotGroundTruthPose(self, t, scale=0.3, time_interval=0.01):
|
||||
# plot ground truth pose, as well as prediction from integrated IMU measurements
|
||||
actualPose = self.scenario.pose(t)
|
||||
plot_pose3(POSES_FIG, actualPose, 0.3)
|
||||
t = actualPose.translation()
|
||||
self.maxDim = max([abs(t.x()), abs(t.y()), abs(t.z()), self.maxDim])
|
||||
self.maxDim = max([max(np.abs(t)), self.maxDim])
|
||||
ax = plt.gca()
|
||||
ax.set_xlim3d(-self.maxDim, self.maxDim)
|
||||
ax.set_ylim3d(-self.maxDim, self.maxDim)
|
||||
ax.set_zlim3d(-self.maxDim, self.maxDim)
|
||||
|
||||
plt.pause(0.01)
|
||||
plt.pause(time_interval)
|
||||
|
||||
def run(self):
|
||||
def run(self, T=12):
|
||||
# simulate the loop
|
||||
T = 12
|
||||
for i, t in enumerate(np.arange(0, T, self.dt)):
|
||||
measuredOmega = self.runner.measuredAngularVelocity(t)
|
||||
measuredAcc = self.runner.measuredSpecificForce(t)
|
|
@ -1,17 +1,12 @@
|
|||
These examples are almost identical to the old handwritten python wrapper
|
||||
examples. However, there are just some slight name changes, for example
|
||||
`noiseModel.Diagonal` becomes `noiseModel_Diagonal` etc...
|
||||
Also, instead of `gtsam.Symbol('b', 0)` we can simply say `gtsam.symbol_shorthand_B(0)` or `B(0)` if we use python aliasing.
|
||||
|
||||
# Porting Progress
|
||||
|
||||
| C++ Example Name | Ported |
|
||||
|-------------------------------------------------------|--------|
|
||||
| CameraResectioning | |
|
||||
| CreateSFMExampleData | |
|
||||
| DiscreteBayesNet_FG | none of the required discrete functionality is exposed through cython |
|
||||
| easyPoint2KalmanFilter | ExtendedKalmanFilter not exposed through cython |
|
||||
| elaboratePoint2KalmanFilter | GaussianSequentialSolver not exposed through cython |
|
||||
| DiscreteBayesNet_FG | none of the required discrete functionality is exposed through Python |
|
||||
| easyPoint2KalmanFilter | ExtendedKalmanFilter not yet exposed through Python |
|
||||
| elaboratePoint2KalmanFilter | GaussianSequentialSolver not yet exposed through Python |
|
||||
| ImuFactorExample2 | X |
|
||||
| ImuFactorsExample | |
|
||||
| ISAM2Example_SmartFactor | |
|
||||
|
@ -25,7 +20,7 @@ Also, instead of `gtsam.Symbol('b', 0)` we can simply say `gtsam.symbol_shorthan
|
|||
| Pose2SLAMExample_g2o | X |
|
||||
| Pose2SLAMExample_graph | |
|
||||
| Pose2SLAMExample_graphviz | |
|
||||
| Pose2SLAMExample_lago | lago not exposed through cython |
|
||||
| Pose2SLAMExample_lago | lago not yet exposed through Python |
|
||||
| Pose2SLAMStressTest | |
|
||||
| Pose2SLAMwSPCG | |
|
||||
| Pose3SLAMExample_changeKeys | |
|
||||
|
@ -47,11 +42,11 @@ Also, instead of `gtsam.Symbol('b', 0)` we can simply say `gtsam.symbol_shorthan
|
|||
| StereoVOExample | |
|
||||
| StereoVOExample_large | |
|
||||
| TimeTBB | |
|
||||
| UGM_chain | discrete functionality not exposed |
|
||||
| UGM_small | discrete functionality not exposed |
|
||||
| UGM_chain | discrete functionality not yet exposed |
|
||||
| UGM_small | discrete functionality not yet exposed |
|
||||
| VisualISAM2Example | X |
|
||||
| VisualISAMExample | X |
|
||||
|
||||
Extra Examples (with no C++ equivalent)
|
||||
- PlanarManipulatorExample
|
||||
- SFMData
|
||||
- SFMData
|
|
@ -13,14 +13,15 @@ from __future__ import print_function
|
|||
import gtsam
|
||||
import matplotlib.pyplot as plt
|
||||
import numpy as np
|
||||
from gtsam import symbol_shorthand_L as L
|
||||
from gtsam import symbol_shorthand_X as X
|
||||
from gtsam import symbol_shorthand
|
||||
L = symbol_shorthand.L
|
||||
X = symbol_shorthand.X
|
||||
|
||||
from gtsam.examples import SFMdata
|
||||
from gtsam.gtsam import (Cal3_S2, DoglegOptimizer,
|
||||
from gtsam import (Cal3_S2, DoglegOptimizer,
|
||||
GenericProjectionFactorCal3_S2, Marginals,
|
||||
NonlinearFactorGraph, PinholeCameraCal3_S2, Point3,
|
||||
Pose3, PriorFactorPoint3, PriorFactorPose3, Rot3,
|
||||
SimpleCamera, Values)
|
||||
Pose3, PriorFactorPoint3, PriorFactorPose3, Rot3, Values)
|
||||
from gtsam.utils import plot
|
||||
|
||||
|
||||
|
@ -56,7 +57,7 @@ def main():
|
|||
K = Cal3_S2(50.0, 50.0, 0.0, 50.0, 50.0)
|
||||
|
||||
# Define the camera observation noise model
|
||||
measurement_noise = gtsam.noiseModel_Isotropic.Sigma(2, 1.0) # one pixel in u and v
|
||||
measurement_noise = gtsam.noiseModel.Isotropic.Sigma(2, 1.0) # one pixel in u and v
|
||||
|
||||
# Create the set of ground-truth landmarks
|
||||
points = SFMdata.createPoints()
|
||||
|
@ -69,7 +70,7 @@ def main():
|
|||
|
||||
# Add a prior on pose x1. This indirectly specifies where the origin is.
|
||||
# 0.3 rad std on roll,pitch,yaw and 0.1m on x,y,z
|
||||
pose_noise = gtsam.noiseModel_Diagonal.Sigmas(np.array([0.3, 0.3, 0.3, 0.1, 0.1, 0.1]))
|
||||
pose_noise = gtsam.noiseModel.Diagonal.Sigmas(np.array([0.3, 0.3, 0.3, 0.1, 0.1, 0.1]))
|
||||
factor = PriorFactorPose3(X(0), poses[0], pose_noise)
|
||||
graph.push_back(factor)
|
||||
|
||||
|
@ -85,7 +86,7 @@ def main():
|
|||
# Because the structure-from-motion problem has a scale ambiguity, the problem is still under-constrained
|
||||
# Here we add a prior on the position of the first landmark. This fixes the scale by indicating the distance
|
||||
# between the first camera and the first landmark. All other landmark positions are interpreted using this scale.
|
||||
point_noise = gtsam.noiseModel_Isotropic.Sigma(3, 0.1)
|
||||
point_noise = gtsam.noiseModel.Isotropic.Sigma(3, 0.1)
|
||||
factor = PriorFactorPoint3(L(0), points[0], point_noise)
|
||||
graph.push_back(factor)
|
||||
graph.print_('Factor Graph:\n')
|
||||
|
@ -97,7 +98,7 @@ def main():
|
|||
transformed_pose = pose.retract(0.1*np.random.randn(6,1))
|
||||
initial_estimate.insert(X(i), transformed_pose)
|
||||
for j, point in enumerate(points):
|
||||
transformed_point = Point3(point.vector() + 0.1*np.random.randn(3))
|
||||
transformed_point = point + 0.1*np.random.randn(3)
|
||||
initial_estimate.insert(L(j), transformed_point)
|
||||
initial_estimate.print_('Initial Estimates:\n')
|
||||
|
|
@ -33,7 +33,8 @@ def createPoses(K):
|
|||
poses = []
|
||||
for theta in angles:
|
||||
position = gtsam.Point3(radius*np.cos(theta),
|
||||
radius*np.sin(theta), height)
|
||||
radius*np.sin(theta),
|
||||
height)
|
||||
camera = gtsam.PinholeCameraCal3_S2.Lookat(position, target, up, K)
|
||||
poses.append(camera.pose())
|
||||
return poses
|
|
@ -10,10 +10,9 @@ This example will perform a relatively trivial optimization on
|
|||
a single variable with a single factor.
|
||||
"""
|
||||
|
||||
import gtsam
|
||||
import numpy as np
|
||||
from gtsam import symbol_shorthand_X as X
|
||||
|
||||
import gtsam
|
||||
from gtsam.symbol_shorthand import X
|
||||
|
||||
def main():
|
||||
"""
|
||||
|
@ -33,7 +32,7 @@ def main():
|
|||
"""
|
||||
prior = gtsam.Rot2.fromAngle(np.deg2rad(30))
|
||||
prior.print_('goal angle')
|
||||
model = gtsam.noiseModel_Isotropic.Sigma(dim=1, sigma=np.deg2rad(1))
|
||||
model = gtsam.noiseModel.Isotropic.Sigma(dim=1, sigma=np.deg2rad(1))
|
||||
key = X(1)
|
||||
factor = gtsam.PriorFactorRot2(key, prior, model)
|
||||
|
|
@ -17,8 +17,7 @@ import gtsam
|
|||
import gtsam.utils.plot as gtsam_plot
|
||||
import matplotlib.pyplot as plt
|
||||
import numpy as np
|
||||
from gtsam import symbol_shorthand_L as L
|
||||
from gtsam import symbol_shorthand_X as X
|
||||
from gtsam.symbol_shorthand import L, X
|
||||
from gtsam.examples import SFMdata
|
||||
from mpl_toolkits.mplot3d import Axes3D # pylint: disable=W0611
|
||||
|
||||
|
@ -64,7 +63,7 @@ def visual_ISAM2_example():
|
|||
K = gtsam.Cal3_S2(50.0, 50.0, 0.0, 50.0, 50.0)
|
||||
|
||||
# Define the camera observation noise model
|
||||
measurement_noise = gtsam.noiseModel_Isotropic.Sigma(
|
||||
measurement_noise = gtsam.noiseModel.Isotropic.Sigma(
|
||||
2, 1.0) # one pixel in u and v
|
||||
|
||||
# Create the set of ground-truth landmarks
|
||||
|
@ -110,12 +109,12 @@ def visual_ISAM2_example():
|
|||
# at least twice before adding it to iSAM.
|
||||
if i == 0:
|
||||
# Add a prior on pose x0
|
||||
pose_noise = gtsam.noiseModel_Diagonal.Sigmas(np.array(
|
||||
pose_noise = gtsam.noiseModel.Diagonal.Sigmas(np.array(
|
||||
[0.1, 0.1, 0.1, 0.3, 0.3, 0.3])) # 30cm std on x,y,z 0.1 rad on roll,pitch,yaw
|
||||
graph.push_back(gtsam.PriorFactorPose3(X(0), poses[0], pose_noise))
|
||||
|
||||
# Add a prior on landmark l0
|
||||
point_noise = gtsam.noiseModel_Isotropic.Sigma(3, 0.1)
|
||||
point_noise = gtsam.noiseModel.Isotropic.Sigma(3, 0.1)
|
||||
graph.push_back(gtsam.PriorFactorPoint3(
|
||||
L(0), points[0], point_noise)) # add directly to graph
|
||||
|
||||
|
@ -123,7 +122,7 @@ def visual_ISAM2_example():
|
|||
# Intentionally initialize the variables off from the ground truth
|
||||
for j, point in enumerate(points):
|
||||
initial_estimate.insert(L(j), gtsam.Point3(
|
||||
point.x()-0.25, point.y()+0.20, point.z()+0.15))
|
||||
point[0]-0.25, point[1]+0.20, point[2]+0.15))
|
||||
else:
|
||||
# Update iSAM with the new factors
|
||||
isam.update(graph, initial_estimate)
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue