gtsam/cython
Frank Dellaert 84afc94458
Feature/shonan averaging (#473)
Shonan Rotation Averaging.

199 commit messages below, many are obsolete as design has changed quite a bit over time, especially from the earlier period where I thought we only needed SO(4).

* prototyping weighted sampler

* Moved WeightedSampler into its own header

* Random now uses std header <random>.

* Removed boost/random usage from linear and discrete directories

* Made into class

* Now using new WeightedSampler class

* Inlined random direction generation

* eradicated last vestiges of boost/random in gtsam_unstable

* Added 3D example g2o file

* Added Frobenius norm factors

* Shonan averaging algorithm, using SOn class

* Wrapping Frobenius and Shonan

* Fixed issues with <<

* Use Builder parameters

* Refactored Shonan interface

* Fixed << issues as well as MATLAB segfault, using eval(), as discussed in issue #451

* ShonanAveragingParameters

* New factor FrobeniusWormholeFactorP computes |Rj*P - Ri*P*Rij|

* Fixed broken GetDimension for Lie groups with variable dimension.

* Removed all but Shonan averaging factor and made everything work with new SOn

* Just a single WormholeFactor, wrapped noise model

* Use std <random>

* comments/todos

* added timing script

* add script to process ShonanAveraging timing results

* Now producing a CSV file

* Parse csv file and make combined plot

* Fixed range

* change p value and set two flags on

* input file path, all the csv files proceeses at the same time

* add check convergence rate part

* csv file have name according to input  data name

* correct one mistake in initialization

* generate the convergence rate for each p value

* add yticks for the bar plot

* add noises to the measurements

* test add noise

* Basic structure for checkOptimalityAt

* change optimizer method to cholesky

* buildQ now working. Tests should be better but visually inspected.

* multiple test with cholesky

* back

* computeLambda now works

* make combined plots while make bar plot

* Calculate minimum eigenvalue - the very expensive version

* Exposed computeMinEigenValue

* make plots and bar  togenter

* method change to jacobi

* add time for check optimality, min_eigen_value, sub_bound

* updated plot min_eigen value and subounds

* Adding Spectra headers

* David's min eigenvalue code inserted and made to compile.

* Made it work

* Made "run" method work.

* add rim.g2o name

* Fixed bug in shifting eigenvalues

* roundSolution which replaces projectFrom

* removed extra arguments

* Added to wrapper

* Add SOn to template lists

* roundSolution delete the extra arguement p

* only calculate p=5 and change to the correct way computing f_R

* Fixed conflict and made Google-style name changes

* prototype descent code and unit test for initializeWithDescent

* add averaging cost/time part in processing data

* initializewithDescent success in test

* Formatting and find example rather than hardcode

* Removed accidentally checked in cmake files

* give value to xi by block

* correct gradient descent

* correct xi

* }

* Fix wrapper

* Make Hat/Vee have alternating signs

* MakeATangentVector helpder function

* Fixed cmake files

* changed sign

* add line search

* unit test for line search

* test real data with line search

* correct comment

* Fix boost::uniform_real

* add save .dat file

* correct test case

* add explanation

* delete redundant cout

* add name to .dat output file

* correct checkR

* add get poses_  in shonan

* add Vector Point type for savig data

* Remove cmake file which magically re-appeared??

* Switched to std random library.

* Prepare Klaus test

* Add klaus3.g2o data.

* fix comment

* Fix derivatives

* Fixed broken GetDimension for Lie groups with variable dimension.

* Fix SOn tests to report correct dimension

* Added tests for Klaus3 data

* Add runWithRandomKlaus test for shonan.

* Finish runWithRandomKlaus unittest.

* Correct datafile.

* Correct the format.

* Added measured and keys methods

* Shonan works on Klaus data

* Create dense versions for wrappers, for testing

* Now store D, Q, and L

* Remove another cmake file incorrectly checked in.

* Found and fixed the bug in ComputeLambda !

* Now using Q in Lambdas calculation, so Lambdas agree with Eriksson18cvpr.

* Make FrobeniusFactor not use deprecated methods

* FrobeniusWormholeFactor takes Rot3 as argument

* Wrapped some more methods.

* Wrapped more methods

* Allow creating and populating BetweenFactorPose3s in python

* New constructors for ShonanAveraging

* add function of get measurements number

* Remove option not to use noise model

* wrap Use nrMeasurements

* Made Logmap a bit more tolerant of slightly degenerate rotations (with trace < -1)

* Allow for Anchor index

* Fix anchor bug

* Change outside view to Rot3 rather than SO3

* Add Lift in SOn class

* Make comet working

* Small fixes

* Delete extra function

* Add SOn::Lift

* Removed hardcoded flag

* Moved Frobenius factor to gtsam from unstable

* Added new tests and made an old regression pass again

* Cleaned up formatting and some comments, added EXPORT directives

* Throw exception if wrongly dimensioned values are given

* static_cast and other throw

* Fixed run-time dimension

* Added gauge-constraining factor

* LM parameters now passed in, added Gauge fixing

* 2D test scaffold

* Comments

* Pre-allocated generators

* Document API

* Add optional weight

* New prior weeights infrastructure

* Made d a template parameter

* Recursive Hat and RetractJacobian test

* Added Spectra 0.9.0 to 3rdparty

* Enabling 2D averaging

* Templatized Wormhole factor

* ignore xcode folder

* Fixed vec and VectorizedGenerators templates for fixed N!=3 or 4

* Simplifying constructors
Moved file loading to tests (for now)
All unit tests pass for d==3!

* Templated some methods internally

* Very generic parseToVector

* refactored load2d

* Very much improved FrobeniusWormholeFactor (Shonan) Jacobians

* SO(2) averaging works !

* Templated parse methods

* Switched to new Dataset paradigm

* Moved Shonan to gtsam

* Checked noise model is correctly gotten from file

* Fixed covariance bug

* Making Shonan wrapper work

* Renamed FrobeniusWormholeFactor to ShonanFactor and moved into its own compilation unit in gtsam/sfm

* Fixed wrong include

* Simplified interface (removed irrelevant random inits) and fixed eigenvector test

* Removed stray boost::none

* Added citation as suggested by Jose

* Made descent test deterministic

* Fixed some comments, commented out flaky test

Co-authored-by: Jing Wu <jingwu@gatech.edu>
Co-authored-by: jingwuOUO <wujing2951@gmail.com>
Co-authored-by: swang <swang736@gatech.edu>
Co-authored-by: ss <ss>
Co-authored-by: Fan Jiang <prof.fan@foxmail.com>
2020-08-17 07:43:10 -04:00
..
gtsam Feature/shonan averaging (#473) 2020-08-17 07:43:10 -04:00
gtsam_eigency Improved paths and added checks 2020-07-05 21:57:18 -05:00
gtsam_unstable Style and dates 2020-03-25 08:59:58 -04:00
CMakeLists.txt fix working directory for python install target 2020-07-07 17:38:27 -04:00
README.md removed unneeded install commands and updated README 2020-07-01 16:23:24 -05:00
requirements.txt Set minimum supported numpy version to 1.11.0 (#366) 2020-06-23 16:08:44 -05:00
setup.py.in Vastly improved setup.py template 2020-06-24 18:39:49 -05:00

README.md

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:

    pip install -r <gtsam_folder>/cython/requirements.txt
    
  • For compatibility with GTSAM's Eigen version, it contains its own cloned version of Eigency, 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:

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.
    • 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 _ in Python.

    Examples: noiseModel_Gaussian, noiseModel_mEstimator_Tukey

  • Casting from a base class to a derive class must be done explicitly.

    Examples:

    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.

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
    • 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:

  • Fix Python tests: don't use " import * ": Bad style!!! (18-03-17 19:50)

  • Unit tests for cython wrappers @done (18-03-17 18:45) -- simply compare generated files

  • Wrap unstable @done (18-03-17 15:30)

  • Unify cython/GTSAM.h and the original GTSAM.h @done (18-03-17 15:30)

  • 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.

  • 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, 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.

  • Convert input numpy Matrix/Vector to float dtype and storage order 'F' automatically, cannot crash! @done (15-03-17 13:00)

  • Remove requirements.txt - Frank: don't bother with only 2 packages and a special case for eigency! @done (08-03-17 10:30)

  • 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?

  • wrap VariableIndex: why is it in inference? If need to, shouldn't have constructors to specific FactorGraphs @done (23-11-16 13:00)

  • Global functions @done (22-11-16 21:00)

  • [REFACTOR] typesEqual --> isSameSignature @done (22-11-16 21:00)

  • Proper overloads (constructors, static methods, methods) @done (20-11-16 21:00)

  • Allow overloading methods. The current solution is annoying!!! @done (20-11-16 21:00)

  • Casting from parent and grandparents @done (16-11-16 17:00)

  • Allow overloading constructors. The current solution is annoying!!! @done (16-11-16 17:00)

  • Support "print obj" @done (16-11-16 17:00)

  • methods for FastVector: at, [], ... @done (16-11-16 17:00)

  • Cython: Key and size_t: traits<size_t> doesn't exist @done (16-09-12 18:34)

  • KeyVector, KeyList, KeySet... @done (16-09-13 17:19)

  • [Nice to have] parse typedef @done (16-09-13 17:19)

  • ctypedef at correct places @done (16-09-12 18:34)

  • expand template variable type in constructor/static methods? @done (16-09-12 18:34)

  • NonlinearOptimizer: copy constructor deleted!!! @done (16-09-13 17:20)

  • Value: no default constructor @done (16-09-13 17:20)

  • ctypedef PriorFactor[Vector] PriorFactorVector @done (16-09-19 12:25)

  • Delete duplicate methods in derived class @done (16-09-12 13:38)

  • Fix return properly @done (16-09-11 17:14)

  • handle pair @done (16-09-11 17:14)

  • Eigency: ambiguous call: A(const T&) A(const Vector& v) and Eigency A(Map[Vector]& v) @done (16-09-11 07:59)

  • Eigency: Constructor: ambiguous construct from Vector/Matrix @done (16-09-11 07:59)

  • Eigency: Fix method template of Vector/Matrix: template argument is [Vector] while arugment is Map[Vector] @done (16-09-11 08:22)

  • 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" ??