parent
6bf7ea23cf
commit
685b0cb62f
|
@ -2,7 +2,7 @@ This is the Cython/Python wrapper around the GTSAM C++ library.
|
||||||
|
|
||||||
INSTALL
|
INSTALL
|
||||||
=======
|
=======
|
||||||
- This wrapper needs Cython(>=0.25), numpy and eigency, which can be installed
|
- This wrapper needs Cython(>=0.25), numpy and eigency, which can be installed
|
||||||
as follows:
|
as follows:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
@ -35,21 +35,27 @@ See the tests for examples.
|
||||||
|
|
||||||
## Some important notes:
|
## Some important notes:
|
||||||
|
|
||||||
- Vector/Matrix: Due to a design choice of eigency, numpy.array matrices with the default order='A'
|
- Vector/Matrix:
|
||||||
will always be transposed in C++ no matter how you transpose it in Python. Use order='F', or use
|
+ GTSAM expects double-precision floating point vectors and matrices.
|
||||||
two functions Vector and Matrix in cython/gtsam/utils/np_utils.py for your conveniences. These two functions
|
Hence, you should pass numpy matrices with dtype=float, or 'float64'.
|
||||||
also help to avoid a common but very subtle bug of using integers when creating numpy arrays,
|
+ Also, GTSAM expects *column-major* matrices, unlike the default storage
|
||||||
e.g. np.array([1,2,3]). These can't be an input for gtsam functions as they only accept floating-point arrays.
|
scheme in numpy. Hence, you should pass column-major matrices to gtsam using
|
||||||
For more details, see: https://github.com/wouterboomsma/eigency#storage-layout---why-arrays-are-sometimes-transposed
|
the flag order='F'. And you always get column-major matrices back.
|
||||||
|
For more details, see: 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.
|
- Inner namespace: Classes in inner namespace will be prefixed by <innerNamespace>_ in Python.
|
||||||
Examples: noiseModel_Gaussian, noiseModel_mEstimator_Tukey
|
Examples: noiseModel_Gaussian, noiseModel_mEstimator_Tukey
|
||||||
|
|
||||||
- Casting from a base class to a derive class must be done explicitly.
|
- Casting from a base class to a derive class must be done explicitly.
|
||||||
Examples:
|
Examples:
|
||||||
```Python
|
```Python
|
||||||
noiseBase = factor.get_noiseModel()
|
noiseBase = factor.get_noiseModel()
|
||||||
noiseGaussian = dynamic_cast_noiseModel_Gaussian_noiseModel_Base(noiseBase)
|
noiseGaussian = dynamic_cast_noiseModel_Gaussian_noiseModel_Base(noiseBase)
|
||||||
```
|
```
|
||||||
|
|
||||||
WRAPPING YOUR OWN PROJECT THAT USES GTSAM
|
WRAPPING YOUR OWN PROJECT THAT USES GTSAM
|
||||||
|
@ -102,7 +108,7 @@ KNOWN ISSUES
|
||||||
- size-related issue: can only wrap up to a certain number of classes: up to mEstimator!
|
- size-related issue: can only wrap up to a certain number of classes: up to mEstimator!
|
||||||
- Guess: 64 vs 32b? disutils Compiler flags?
|
- 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>
|
- 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
|
- Upgrading to 0.25 solves the problem
|
||||||
- Need default constructor and default copy constructor for almost every classes... :(
|
- Need default constructor and default copy constructor for almost every classes... :(
|
||||||
- support these constructors by default and declare "delete" for special classes?
|
- support these constructors by default and declare "delete" for special classes?
|
||||||
|
|
||||||
|
@ -110,12 +116,20 @@ KNOWN ISSUES
|
||||||
TODO
|
TODO
|
||||||
=====
|
=====
|
||||||
☐ Unify cython/gtsam.h and the original gtsam.h
|
☐ Unify cython/gtsam.h and the original gtsam.h
|
||||||
|
✔ 06-03-17: manage to remove the requirements for default and copy constructors
|
||||||
- 25-11-16:
|
- 25-11-16:
|
||||||
Try to unify but failed. Main reasons are: Key/size_t, std containers, KeyVector/KeyList/KeySet.
|
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>,
|
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>.
|
to FastVector<size_t>.
|
||||||
|
☐ Unit tests for cython wrappers
|
||||||
|
☐ Fix Python tests: don't use " import <package> * ": Bad style!!!
|
||||||
|
☐ Marginal and JointMarginal: revert changes
|
||||||
|
- add doc for generate
|
||||||
|
- matlab 6 arguments?
|
||||||
|
|
||||||
Completed/Cancelled:
|
Completed/Cancelled:
|
||||||
|
✔ 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)
|
✔ CMake install script @done (25-11-16 02:30)
|
||||||
✘ [REFACTOR] better name for uninstantiateClass: very vague!! @cancelled (25-11-16 02:30) -- lazy
|
✘ [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?
|
✘ forward declaration? @cancelled (23-11-16 13:00) - nothing to do, seem to work?
|
||||||
|
@ -150,7 +164,7 @@ Completed/Cancelled:
|
||||||
- what's the purpose of "virtual" ??
|
- what's the purpose of "virtual" ??
|
||||||
|
|
||||||
Installation:
|
Installation:
|
||||||
☐ Prerequisite:
|
☐ Prerequisite:
|
||||||
- Users create venv and pip install requirements before compiling
|
- Users create venv and pip install requirements before compiling
|
||||||
- Wrap cython script in gtsam/cython folder
|
- Wrap cython script in gtsam/cython folder
|
||||||
☐ Install built module into venv?
|
☐ Install built module into venv?
|
||||||
|
|
|
@ -3,9 +3,9 @@ This file contains small experiments to test the wrapper with gtsam_short,
|
||||||
not real unittests. Its name convention is different from other tests so it
|
not real unittests. Its name convention is different from other tests so it
|
||||||
won't be discovered.
|
won't be discovered.
|
||||||
"""
|
"""
|
||||||
from gtsam.gtsam import *
|
from gtsam import *
|
||||||
import numpy as np
|
import numpy as np
|
||||||
from gtsam.utils import Vector, Matrix
|
from utils import Vector, Matrix
|
||||||
|
|
||||||
r = Rot3()
|
r = Rot3()
|
||||||
print(r)
|
print(r)
|
||||||
|
|
|
@ -2,36 +2,39 @@ import unittest
|
||||||
from gtsam import *
|
from gtsam import *
|
||||||
from math import *
|
from math import *
|
||||||
import numpy as np
|
import numpy as np
|
||||||
from gtsam.utils import Matrix, Vector
|
|
||||||
|
|
||||||
class TestJacobianFactor(unittest.TestCase):
|
class TestJacobianFactor(unittest.TestCase):
|
||||||
|
|
||||||
def test_eliminate(self):
|
def test_eliminate(self):
|
||||||
Ax2 = Matrix(
|
# Recommended way to specify a matrix (see cython/README)
|
||||||
[-5., 0.],
|
Ax2 = np.array(
|
||||||
|
[[-5., 0.],
|
||||||
[+0., -5.],
|
[+0., -5.],
|
||||||
[10., 0.],
|
[10., 0.],
|
||||||
[+0., 10.])
|
[+0., 10.]], order='F')
|
||||||
|
|
||||||
Al1 = Matrix(
|
# This is good too
|
||||||
[5., 0.],
|
Al1 = np.array(
|
||||||
[0., 5.],
|
[[5, 0],
|
||||||
[0., 0.],
|
[0, 5],
|
||||||
[0., 0.])
|
[0, 0],
|
||||||
|
[0, 0]], dtype=float, order = 'F')
|
||||||
|
|
||||||
Ax1 = Matrix(
|
# Not recommended for performance reasons, but should still work
|
||||||
[0.00, 0.], # f4
|
# as the wrapper should convert it to the correct type and storage order
|
||||||
[0.00, 0.], # f4
|
Ax1 = np.array(
|
||||||
[-10., 0.], # f2
|
[[0, 0], # f4
|
||||||
[0.00, -10.]) # f2
|
[0, 0], # f4
|
||||||
|
[-10, 0], # f2
|
||||||
|
[0, -10]]) # f2
|
||||||
|
|
||||||
x2 = 1
|
x2 = 1
|
||||||
l1 = 2
|
l1 = 2
|
||||||
x1 = 3
|
x1 = 3
|
||||||
|
|
||||||
# the RHS
|
# the RHS
|
||||||
b2 = Vector(-1., 1.5, 2., -1.)
|
b2 = np.array([-1., 1.5, 2., -1.])
|
||||||
sigmas = Vector(1., 1., 1., 1.)
|
sigmas = np.array([1., 1., 1., 1.])
|
||||||
model4 = noiseModel_Diagonal.Sigmas(sigmas)
|
model4 = noiseModel_Diagonal.Sigmas(sigmas)
|
||||||
combined = JacobianFactor(x2, Ax2, l1, Al1, x1, Ax1, b2, model4)
|
combined = JacobianFactor(x2, Ax2, l1, Al1, x1, Ax1, b2, model4)
|
||||||
|
|
||||||
|
@ -42,29 +45,29 @@ class TestJacobianFactor(unittest.TestCase):
|
||||||
actualCG, lf = combined.eliminate(ord)
|
actualCG, lf = combined.eliminate(ord)
|
||||||
|
|
||||||
# create expected Conditional Gaussian
|
# create expected Conditional Gaussian
|
||||||
R11 = Matrix([11.1803, 0.00],
|
R11 = np.array([[11.1803, 0.00],
|
||||||
[0.00, 11.1803])
|
[0.00, 11.1803]])
|
||||||
S12 = Matrix([-2.23607, 0.00],
|
S12 = np.array([[-2.23607, 0.00],
|
||||||
[+0.00, -2.23607])
|
[+0.00, -2.23607]])
|
||||||
S13 = Matrix([-8.94427, 0.00],
|
S13 = np.array([[-8.94427, 0.00],
|
||||||
[+0.00, -8.94427])
|
[+0.00, -8.94427]])
|
||||||
d = Vector(2.23607, -1.56525)
|
d = np.array([2.23607, -1.56525])
|
||||||
expectedCG = GaussianConditional(
|
expectedCG = GaussianConditional(
|
||||||
x2, d, R11, l1, S12, x1, S13, noiseModel_Unit.Create(2))
|
x2, d, R11, l1, S12, x1, S13, noiseModel_Unit.Create(2))
|
||||||
# check if the result matches
|
# check if the result matches
|
||||||
self.assertTrue(actualCG.equals(expectedCG, 1e-4))
|
self.assertTrue(actualCG.equals(expectedCG, 1e-4))
|
||||||
|
|
||||||
# the expected linear factor
|
# the expected linear factor
|
||||||
Bl1 = Matrix([4.47214, 0.00],
|
Bl1 = np.array([[4.47214, 0.00],
|
||||||
[0.00, 4.47214])
|
[0.00, 4.47214]])
|
||||||
|
|
||||||
Bx1 = Matrix(
|
Bx1 = np.array(
|
||||||
# x1
|
# x1
|
||||||
[-4.47214, 0.00],
|
[[-4.47214, 0.00],
|
||||||
[+0.00, -4.47214])
|
[+0.00, -4.47214]])
|
||||||
|
|
||||||
# the RHS
|
# the RHS
|
||||||
b1 = Vector(0.0, 0.894427)
|
b1 = np.array([0.0, 0.894427])
|
||||||
|
|
||||||
model2 = noiseModel_Diagonal.Sigmas(np.array([1., 1.]))
|
model2 = noiseModel_Diagonal.Sigmas(np.array([1., 1.]))
|
||||||
expectedLF = JacobianFactor(l1, Bl1, x1, Bx1, b1, model2)
|
expectedLF = JacobianFactor(l1, Bl1, x1, Bx1, b1, model2)
|
||||||
|
|
|
@ -2,7 +2,6 @@ import unittest
|
||||||
from gtsam import *
|
from gtsam import *
|
||||||
from math import *
|
from math import *
|
||||||
import numpy as np
|
import numpy as np
|
||||||
from gtsam.utils import Vector, Matrix
|
|
||||||
import gtsam.utils.visual_data_generator as generator
|
import gtsam.utils.visual_data_generator as generator
|
||||||
|
|
||||||
|
|
||||||
|
@ -17,7 +16,7 @@ class TestSFMExample(unittest.TestCase):
|
||||||
|
|
||||||
measurementNoiseSigma = 1.0
|
measurementNoiseSigma = 1.0
|
||||||
pointNoiseSigma = 0.1
|
pointNoiseSigma = 0.1
|
||||||
poseNoiseSigmas = Vector([0.001, 0.001, 0.001, 0.1, 0.1, 0.1])
|
poseNoiseSigmas = np.array([0.001, 0.001, 0.001, 0.1, 0.1, 0.1])
|
||||||
|
|
||||||
graph = NonlinearFactorGraph()
|
graph = NonlinearFactorGraph()
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,6 @@ import unittest
|
||||||
from gtsam import *
|
from gtsam import *
|
||||||
from math import *
|
from math import *
|
||||||
import numpy as np
|
import numpy as np
|
||||||
from gtsam.utils import Vector, Matrix
|
|
||||||
|
|
||||||
|
|
||||||
class TestStereoVOExample(unittest.TestCase):
|
class TestStereoVOExample(unittest.TestCase):
|
||||||
|
@ -32,7 +31,7 @@ class TestStereoVOExample(unittest.TestCase):
|
||||||
## Create realistic calibration and measurement noise model
|
## Create realistic calibration and measurement noise model
|
||||||
# format: fx fy skew cx cy baseline
|
# format: fx fy skew cx cy baseline
|
||||||
K = Cal3_S2Stereo(1000, 1000, 0, 320, 240, 0.2)
|
K = Cal3_S2Stereo(1000, 1000, 0, 320, 240, 0.2)
|
||||||
stereo_model = noiseModel_Diagonal.Sigmas(Vector([1.0, 1.0, 1.0]))
|
stereo_model = noiseModel_Diagonal.Sigmas(np.array([1.0, 1.0, 1.0]))
|
||||||
|
|
||||||
## Add measurements
|
## Add measurements
|
||||||
# pose 1
|
# pose 1
|
||||||
|
|
|
@ -22,11 +22,25 @@ class TestValues(unittest.TestCase):
|
||||||
values.insert(9, E)
|
values.insert(9, E)
|
||||||
values.insert(10, imuBias_ConstantBias())
|
values.insert(10, imuBias_ConstantBias())
|
||||||
|
|
||||||
# special cases for Vector and Matrix:
|
# Special cases for Vectors and Matrices
|
||||||
vec = np.array([1., 2., 3.])
|
# Note that gtsam's Eigen Vectors and Matrices requires double-precision
|
||||||
|
# floating point numbers in column-major (Fortran style) storage order,
|
||||||
|
# whereas by default, numpy.array is in row-major order and the type is
|
||||||
|
# in whatever the number input type is, e.g. np.array([1,2,3])
|
||||||
|
# will have 'int' type.
|
||||||
|
#
|
||||||
|
# The wrapper will automatically fix the type and storage order for you,
|
||||||
|
# but for performace reasons, it's recommended to specify the correct
|
||||||
|
# type and storage order.
|
||||||
|
vec = np.array([1., 2., 3.]) # for vectors, the order is not important, but dtype still is
|
||||||
values.insert(11, vec)
|
values.insert(11, vec)
|
||||||
mat = np.array([[1., 2.], [3., 4.]], order='F')
|
mat = np.array([[1., 2.], [3., 4.]], order='F')
|
||||||
values.insert(12, mat)
|
values.insert(12, mat)
|
||||||
|
# Test with dtype int and the default order='C'
|
||||||
|
# This still works as the wrapper converts to the correct type and order for you
|
||||||
|
# but is nornally not recommended!
|
||||||
|
mat2 = np.array([[1,2,],[3,5]])
|
||||||
|
values.insert(13, mat2)
|
||||||
|
|
||||||
self.assertTrue(values.atPoint2(0).equals(Point2(), tol))
|
self.assertTrue(values.atPoint2(0).equals(Point2(), tol))
|
||||||
self.assertTrue(values.atPoint3(1).equals(Point3(), tol))
|
self.assertTrue(values.atPoint3(1).equals(Point3(), tol))
|
||||||
|
@ -46,6 +60,8 @@ class TestValues(unittest.TestCase):
|
||||||
self.assertTrue(np.allclose(vec, actualVector, tol))
|
self.assertTrue(np.allclose(vec, actualVector, tol))
|
||||||
actualMatrix = values.atMatrix(12)
|
actualMatrix = values.atMatrix(12)
|
||||||
self.assertTrue(np.allclose(mat, actualMatrix, tol))
|
self.assertTrue(np.allclose(mat, actualMatrix, tol))
|
||||||
|
actualMatrix2 = values.atMatrix(13)
|
||||||
|
self.assertTrue(np.allclose(mat2, actualMatrix2, tol))
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
|
|
@ -2,7 +2,6 @@ import unittest
|
||||||
from gtsam import *
|
from gtsam import *
|
||||||
from math import *
|
from math import *
|
||||||
import numpy as np
|
import numpy as np
|
||||||
from gtsam.utils import Vector, Matrix
|
|
||||||
import gtsam.utils.visual_data_generator as generator
|
import gtsam.utils.visual_data_generator as generator
|
||||||
import gtsam.utils.visual_isam as visual_isam
|
import gtsam.utils.visual_isam as visual_isam
|
||||||
|
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
from .np_utils import *
|
|
|
@ -1,6 +1,6 @@
|
||||||
from gtsam import *
|
from gtsam import *
|
||||||
from math import *
|
from math import *
|
||||||
from np_utils import *
|
import numpy as np
|
||||||
|
|
||||||
def circlePose3(numPoses = 8, radius = 1.0, symbolChar = 0):
|
def circlePose3(numPoses = 8, radius = 1.0, symbolChar = 0):
|
||||||
"""
|
"""
|
||||||
|
@ -23,7 +23,7 @@ def circlePose3(numPoses = 8, radius = 1.0, symbolChar = 0):
|
||||||
values = gtsam.Values()
|
values = gtsam.Values()
|
||||||
theta = 0.0
|
theta = 0.0
|
||||||
dtheta = 2*pi/numPoses
|
dtheta = 2*pi/numPoses
|
||||||
gRo = gtsam.Rot3(Matrix([0., 1., 0.], [1., 0., 0.], [0., 0., -1.]))
|
gRo = gtsam.Rot3(np.array([[0., 1., 0.], [1., 0., 0.], [0., 0., -1.]], order='F'))
|
||||||
for i in range(numPoses):
|
for i in range(numPoses):
|
||||||
key = gtsam.symbol(symbolChar, i)
|
key = gtsam.symbol(symbolChar, i)
|
||||||
gti = gtsam.Point3(radius*cos(theta), radius*sin(theta), 0)
|
gti = gtsam.Point3(radius*cos(theta), radius*sin(theta), 0)
|
||||||
|
@ -31,4 +31,4 @@ def circlePose3(numPoses = 8, radius = 1.0, symbolChar = 0):
|
||||||
gTi = gtsam.Pose3(gRo.compose(oRi), gti)
|
gTi = gtsam.Pose3(gRo.compose(oRi), gti)
|
||||||
values.insert(key, gTi)
|
values.insert(key, gTi)
|
||||||
theta = theta + dtheta
|
theta = theta + dtheta
|
||||||
return values
|
return values
|
||||||
|
|
|
@ -1,27 +0,0 @@
|
||||||
import numpy as np
|
|
||||||
|
|
||||||
|
|
||||||
def Vector(*args):
|
|
||||||
"""
|
|
||||||
Convenient function to create numpy vector to use with gtsam cython wrapper
|
|
||||||
Usage: Vector(1), Vector(1,2,3), Vector(3,2,4)
|
|
||||||
"""
|
|
||||||
ret = np.squeeze(np.asarray(args, dtype='float'))
|
|
||||||
if ret.ndim == 0:
|
|
||||||
ret = np.expand_dims(ret, axis=0)
|
|
||||||
return ret
|
|
||||||
|
|
||||||
|
|
||||||
def Matrix(*args):
|
|
||||||
"""
|
|
||||||
Convenient function to create numpy matrix to use with gtsam cython wrapper
|
|
||||||
Usage: Matrix([1])
|
|
||||||
Matrix([1,2,3])
|
|
||||||
Matrix((3,2,4))
|
|
||||||
Matrix([1,2,3],[2,3,4])
|
|
||||||
Matrix((1,2,3),(2,3,4))
|
|
||||||
"""
|
|
||||||
ret = np.asarray(args, dtype='float', order='F')
|
|
||||||
if ret.ndim == 1:
|
|
||||||
ret = np.expand_dims(ret, axis=0)
|
|
||||||
return ret
|
|
|
@ -59,11 +59,11 @@ class Data:
|
||||||
# Set Noise parameters
|
# Set Noise parameters
|
||||||
self.noiseModels = Data.NoiseModels()
|
self.noiseModels = Data.NoiseModels()
|
||||||
self.noiseModels.posePrior = noiseModel_Diagonal.Sigmas(
|
self.noiseModels.posePrior = noiseModel_Diagonal.Sigmas(
|
||||||
Vector([0.001, 0.001, 0.001, 0.1, 0.1, 0.1]))
|
np.array([0.001, 0.001, 0.001, 0.1, 0.1, 0.1]))
|
||||||
# noiseModels.odometry = noiseModel_Diagonal.Sigmas(
|
# noiseModels.odometry = noiseModel_Diagonal.Sigmas(
|
||||||
# Vector([0.001,0.001,0.001,0.1,0.1,0.1]))
|
# np.array([0.001,0.001,0.001,0.1,0.1,0.1]))
|
||||||
self.noiseModels.odometry = noiseModel_Diagonal.Sigmas(
|
self.noiseModels.odometry = noiseModel_Diagonal.Sigmas(
|
||||||
Vector([0.05, 0.05, 0.05, 0.2, 0.2, 0.2]))
|
np.array([0.05, 0.05, 0.05, 0.2, 0.2, 0.2]))
|
||||||
self.noiseModels.pointPrior = noiseModel_Isotropic.Sigma(3, 0.1)
|
self.noiseModels.pointPrior = noiseModel_Isotropic.Sigma(3, 0.1)
|
||||||
self.noiseModels.measurement = noiseModel_Isotropic.Sigma(2, 1.0)
|
self.noiseModels.measurement = noiseModel_Isotropic.Sigma(2, 1.0)
|
||||||
|
|
||||||
|
@ -84,8 +84,7 @@ def generate_data(options):
|
||||||
r = 10
|
r = 10
|
||||||
for j in range(len(truth.points)):
|
for j in range(len(truth.points)):
|
||||||
theta = j * 2 * pi / nrPoints
|
theta = j * 2 * pi / nrPoints
|
||||||
truth.points[j] = Point3(
|
truth.points[j] = Point3(r * cos(theta), r * sin(theta), 0)
|
||||||
v=Vector([r * cos(theta), r * sin(theta), 0]))
|
|
||||||
else: # 3D landmarks as vertices of a cube
|
else: # 3D landmarks as vertices of a cube
|
||||||
truth.points = [Point3(10, 10, 10),
|
truth.points = [Point3(10, 10, 10),
|
||||||
Point3(-10, 10, 10),
|
Point3(-10, 10, 10),
|
||||||
|
@ -101,9 +100,9 @@ def generate_data(options):
|
||||||
r = 40
|
r = 40
|
||||||
for i in range(options.nrCameras):
|
for i in range(options.nrCameras):
|
||||||
theta = i * 2 * pi / options.nrCameras
|
theta = i * 2 * pi / options.nrCameras
|
||||||
t = Point3(Vector(r * cos(theta), r * sin(theta), height))
|
t = Point3(r * cos(theta), r * sin(theta), height)
|
||||||
truth.cameras[i] = SimpleCamera.Lookat(
|
truth.cameras[i] = SimpleCamera.Lookat(
|
||||||
t, Point3(), Point3(Vector(0, 0, 1)), truth.K)
|
t, Point3(), Point3(0, 0, 1), truth.K)
|
||||||
# Create measurements
|
# Create measurements
|
||||||
for j in range(nrPoints):
|
for j in range(nrPoints):
|
||||||
# All landmarks seen in every frame
|
# All landmarks seen in every frame
|
||||||
|
|
Loading…
Reference in New Issue