Add supplimentary files used by the new pybind11 wrapper
parent
03306cba9c
commit
d790f235a7
|
@ -1,57 +1,104 @@
|
|||
# Install cython components
|
||||
include(GtsamCythonWrap)
|
||||
set(GTSAM_PYTHON_BUILD_DIRECTORY ${PROJECT_BINARY_DIR}/python)
|
||||
|
||||
# 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})
|
||||
if(GTSAM_BUILD_PYTHON)
|
||||
# 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)
|
||||
|
||||
# build and include the eigency version of eigency
|
||||
add_subdirectory(gtsam_eigency)
|
||||
include_directories(${GTSAM_EIGENCY_INSTALL_PATH})
|
||||
set(WRAP_USE_CUSTOM_PYTHON_LIBRARY ${GTSAM_USE_CUSTOM_PYTHON_LIBRARY})
|
||||
set(WRAP_PYTHON_VERSION ${GTSAM_PYTHON_VERSION})
|
||||
|
||||
# Fix for error "C1128: number of sections exceeded object file format limit"
|
||||
if(MSVC)
|
||||
add_compile_options(/bigobj)
|
||||
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()
|
||||
|
||||
# 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 ()
|
||||
set(GTSAM_PYTHON_INSTALL_TARGET python-install)
|
||||
add_custom_target(${GTSAM_PYTHON_INSTALL_TARGET}
|
||||
COMMAND ${PYTHON_EXECUTABLE} ${GTSAM_PYTHON_BUILD_DIRECTORY}/setup.py install
|
||||
WORKING_DIRECTORY ${GTSAM_PYTHON_BUILD_DIRECTORY})
|
||||
endif()
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
# README
|
||||
|
||||
# Python Wrapper
|
||||
|
||||
This is the Python wrapper around the GTSAM C++ library. We use Cython to generate the bindings to the underlying C++ code.
|
||||
|
@ -83,65 +85,3 @@ See the tests for examples.
|
|||
## 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 +1,27 @@
|
|||
from .gtsam import *
|
||||
|
||||
try:
|
||||
import gtsam_unstable
|
||||
|
||||
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())
|
||||
|
||||
|
||||
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
|
||||
|
||||
_init()
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
{include_boost}
|
||||
|
||||
#include <pybind11/eigen.h>
|
||||
#include <pybind11/stl_bind.h>
|
||||
#include <pybind11/pybind11.h>
|
||||
#include "gtsam/base/serialization.h"
|
||||
#include "gtsam/nonlinear/utilities.h" // for RedirectCout.
|
||||
|
||||
{includes}
|
||||
#include <boost/serialization/export.hpp>
|
||||
|
||||
{boost_class_export}
|
||||
|
||||
{hoder_type}
|
||||
|
||||
#include "python/gtsam/preamble.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace py = pybind11;
|
||||
|
||||
PYBIND11_MODULE({module_name}, m_) {{
|
||||
m_.doc() = "pybind11 wrapper of {module_name}";
|
||||
|
||||
{wrapped_namespace}
|
||||
|
||||
#include "python/gtsam/specializations.h"
|
||||
|
||||
}}
|
||||
|
|
@ -0,0 +1 @@
|
|||
from .gtsam.imuBias import *
|
|
@ -0,0 +1 @@
|
|||
from .gtsam.noiseModel import *
|
|
@ -0,0 +1,4 @@
|
|||
PYBIND11_MAKE_OPAQUE(std::vector<gtsam::Key>);
|
||||
PYBIND11_MAKE_OPAQUE(std::vector<gtsam::Point2, Eigen::aligned_allocator<gtsam::Point2> >);
|
||||
PYBIND11_MAKE_OPAQUE(std::vector<gtsam::Pose3>);
|
||||
PYBIND11_MAKE_OPAQUE(std::vector<gtsam::BetweenFactor<gtsam::Pose3>>);
|
|
@ -0,0 +1,4 @@
|
|||
py::bind_vector<std::vector<gtsam::Key> >(m_, "KeyVector");
|
||||
py::bind_vector<std::vector<gtsam::Point2, Eigen::aligned_allocator<gtsam::Point2> > >(m_, "Point2Vector");
|
||||
py::bind_vector<std::vector<gtsam::Pose3> >(m_, "Pose3Vector");
|
||||
py::bind_vector<std::vector<boost::shared_ptr<gtsam::BetweenFactor<gtsam::Pose3> > > >(m_, "BetweenFactorPose3s");
|
|
@ -0,0 +1 @@
|
|||
from .gtsam.symbol_shorthand import *
|
|
@ -0,0 +1,32 @@
|
|||
{include_boost}
|
||||
|
||||
#include <pybind11/eigen.h>
|
||||
#include <pybind11/stl_bind.h>
|
||||
#include <pybind11/pybind11.h>
|
||||
#include "gtsam/base/serialization.h"
|
||||
#include "gtsam/nonlinear/utilities.h" // for RedirectCout.
|
||||
|
||||
{includes}
|
||||
#include <boost/serialization/export.hpp>
|
||||
|
||||
{boost_class_export}
|
||||
|
||||
{hoder_type}
|
||||
|
||||
#include "python/gtsam_unstable/preamble.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace py = pybind11;
|
||||
|
||||
PYBIND11_MODULE({module_name}, m_) {{
|
||||
m_.doc() = "pybind11 wrapper of {module_name}";
|
||||
|
||||
py::module::import("gtsam");
|
||||
|
||||
{wrapped_namespace}
|
||||
|
||||
#include "python/gtsam_unstable/specializations.h"
|
||||
|
||||
}}
|
||||
|
|
@ -1,3 +1,2 @@
|
|||
Cython>=0.25.2
|
||||
backports_abc>=0.5
|
||||
numpy>=1.11.0
|
||||
pyparsing>=2.4.2
|
||||
|
|
|
@ -1,25 +1,20 @@
|
|||
import os
|
||||
import sys
|
||||
|
||||
try:
|
||||
from setuptools import setup, find_packages
|
||||
except ImportError:
|
||||
from distutils.core import setup, find_packages
|
||||
|
||||
packages = find_packages()
|
||||
|
||||
packages = find_packages(where=".")
|
||||
print("PACKAGES: ", packages)
|
||||
package_data = {
|
||||
package:
|
||||
[f for f in os.listdir(package.replace('.', os.path.sep)) if os.path.splitext(f)[1] in ('.so', '.pyd')]
|
||||
for package in packages
|
||||
'': [
|
||||
'./*.so',
|
||||
'./*.dll',
|
||||
]
|
||||
}
|
||||
|
||||
cython_install_requirements = open("${CYTHON_INSTALL_REQUIREMENTS_FILE}").readlines()
|
||||
|
||||
install_requires = [line.strip() \
|
||||
for line in cython_install_requirements \
|
||||
if len(line.strip()) > 0 and not line.strip().startswith('#')
|
||||
]
|
||||
|
||||
# Cleaner to read in the contents rather than copy them over.
|
||||
readme_contents = open("${PROJECT_SOURCE_DIR}/README.md").read()
|
||||
|
||||
|
@ -33,8 +28,6 @@ setup(
|
|||
license='Simplified BSD license',
|
||||
keywords='slam sam robotics localization mapping optimization',
|
||||
long_description=readme_contents,
|
||||
long_description_content_type='text/markdown',
|
||||
python_requires='>=2.7',
|
||||
# https://pypi.org/pypi?%3Aaction=list_classifiers
|
||||
classifiers=[
|
||||
'Development Status :: 5 - Production/Stable',
|
||||
|
@ -48,8 +41,9 @@ setup(
|
|||
'Programming Language :: Python :: 2',
|
||||
'Programming Language :: Python :: 3',
|
||||
],
|
||||
|
||||
packages=packages,
|
||||
package_data=package_data,
|
||||
install_requires=install_requires
|
||||
test_suite="gtsam.tests",
|
||||
install_requires=["numpy"],
|
||||
zip_safe=False,
|
||||
)
|
||||
|
|
Loading…
Reference in New Issue