diff --git a/.cproject b/.cproject
index 241afea81..617aa3795 100644
--- a/.cproject
+++ b/.cproject
@@ -592,6 +592,7 @@
make
+
tests/testBayesTree.run
true
false
@@ -599,6 +600,7 @@
make
+
testBinaryBayesNet.run
true
false
@@ -646,6 +648,7 @@
make
+
testSymbolicBayesNet.run
true
false
@@ -653,6 +656,7 @@
make
+
tests/testSymbolicFactor.run
true
false
@@ -660,6 +664,7 @@
make
+
testSymbolicFactorGraph.run
true
false
@@ -675,6 +680,7 @@
make
+
tests/testBayesTree
true
false
@@ -848,6 +854,14 @@
true
true
+
+ make
+ -j4
+ testSmartStereoProjectionPoseFactor.run
+ true
+ true
+ true
+
make
-j5
@@ -1122,6 +1136,7 @@
make
+
testErrors.run
true
false
@@ -1351,6 +1366,46 @@
true
true
+
+ make
+ -j5
+ testBTree.run
+ true
+ true
+ true
+
+
+ make
+ -j5
+ testDSF.run
+ true
+ true
+ true
+
+
+ make
+ -j5
+ testDSFMap.run
+ true
+ true
+ true
+
+
+ make
+ -j5
+ testDSFVector.run
+ true
+ true
+ true
+
+
+ make
+ -j5
+ testFixedVector.run
+ true
+ true
+ true
+
make
-j2
@@ -1433,7 +1488,6 @@
make
-
testSimulated2DOriented.run
true
false
@@ -1473,7 +1527,6 @@
make
-
testSimulated2D.run
true
false
@@ -1481,7 +1534,6 @@
make
-
testSimulated3D.run
true
false
@@ -1495,46 +1547,6 @@
true
true
-
- make
- -j5
- testBTree.run
- true
- true
- true
-
-
- make
- -j5
- testDSF.run
- true
- true
- true
-
-
- make
- -j5
- testDSFMap.run
- true
- true
- true
-
-
- make
- -j5
- testDSFVector.run
- true
- true
- true
-
-
- make
- -j5
- testFixedVector.run
- true
- true
- true
-
make
-j5
@@ -1792,6 +1804,7 @@
cpack
+
-G DEB
true
false
@@ -1799,6 +1812,7 @@
cpack
+
-G RPM
true
false
@@ -1806,6 +1820,7 @@
cpack
+
-G TGZ
true
false
@@ -1813,6 +1828,7 @@
cpack
+
--config CPackSourceConfig.cmake
true
false
@@ -2425,6 +2441,14 @@
true
true
+
+ make
+ -j4
+ testGlobalFunction.run
+ true
+ true
+ true
+
make
-j5
@@ -2659,6 +2683,7 @@
make
+
testGraph.run
true
false
@@ -2666,6 +2691,7 @@
make
+
testJunctionTree.run
true
false
@@ -2673,6 +2699,7 @@
make
+
testSymbolicBayesNetB.run
true
false
@@ -2934,6 +2961,14 @@
true
true
+
+ make
+ -j4
+ testRangeFactor.run
+ true
+ true
+ true
+
make
-j2
@@ -3216,7 +3251,6 @@
make
-
tests/testGaussianISAM2
true
false
diff --git a/.gitignore b/.gitignore
index 60633adaf..f3f1efd5b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -5,3 +5,5 @@
/examples/Data/dubrovnik-3-7-pre-rewritten.txt
/examples/Data/pose2example-rewritten.txt
/examples/Data/pose3example-rewritten.txt
+*.txt.user
+*.txt.user.6d59f0c
diff --git a/README.md b/README.md
index 460f51bf3..623b1ff32 100644
--- a/README.md
+++ b/README.md
@@ -1,47 +1,49 @@
-README - Georgia Tech Smoothing and Mapping library
-===================================================
-
-What is GTSAM?
---------------
-
-GTSAM is a library of C++ classes that implement smoothing and
-mapping (SAM) in robotics and vision, using factor graphs and Bayes
-networks as the underlying computing paradigm rather than sparse
-matrices.
-
-On top of the C++ library, GTSAM includes a MATLAB interface (enable
-GTSAM_INSTALL_MATLAB_TOOLBOX in CMake to build it). A Python interface
-is under development.
-
-Quickstart
-----------
-
-In the root library folder execute:
-
-```
-#!bash
-$ mkdir build
-$ cd build
-$ cmake ..
-$ make check (optional, runs unit tests)
-$ make install
-```
-
-Prerequisites:
-
-- [Boost](http://www.boost.org/users/download/) >= 1.43 (Ubuntu: `sudo apt-get install libboost-all-dev`)
-- [CMake](http://www.cmake.org/cmake/resources/software.html) >= 2.6 (Ubuntu: `sudo apt-get install cmake`)
-
-Optional prerequisites - used automatically if findable by CMake:
-
-- [Intel Threaded Building Blocks (TBB)](http://www.threadingbuildingblocks.org/) (Ubuntu: `sudo apt-get install libtbb-dev`)
-- [Intel Math Kernel Library (MKL)](http://software.intel.com/en-us/intel-mkl)
-
-Additional Information
-----------------------
-
-See the [`INSTALL`](https://bitbucket.org/gtborg/gtsam/src/develop/INSTALL) file for more detailed installation instructions.
-
-GTSAM is open source under the BSD license, see the [`LICENSE`](https://bitbucket.org/gtborg/gtsam/src/develop/LICENSE) and [`LICENSE.BSD`](https://bitbucket.org/gtborg/gtsam/src/develop/LICENSE.BSD) files.
-
-Please see the [`examples/`](https://bitbucket.org/gtborg/gtsam/src/develop/examples) directory and the [`USAGE`](https://bitbucket.org/gtborg/gtsam/src/develop/USAGE) file for examples on how to use GTSAM.
+README - Georgia Tech Smoothing and Mapping library
+===================================================
+
+What is GTSAM?
+--------------
+
+GTSAM is a library of C++ classes that implement smoothing and
+mapping (SAM) in robotics and vision, using factor graphs and Bayes
+networks as the underlying computing paradigm rather than sparse
+matrices.
+
+On top of the C++ library, GTSAM includes a MATLAB interface (enable
+GTSAM_INSTALL_MATLAB_TOOLBOX in CMake to build it). A Python interface
+is under development.
+
+Quickstart
+----------
+
+In the root library folder execute:
+
+```
+#!bash
+$ mkdir build
+$ cd build
+$ cmake ..
+$ make check (optional, runs unit tests)
+$ make install
+```
+
+Prerequisites:
+
+- [Boost](http://www.boost.org/users/download/) >= 1.43 (Ubuntu: `sudo apt-get install libboost-all-dev`)
+- [CMake](http://www.cmake.org/cmake/resources/software.html) >= 2.6 (Ubuntu: `sudo apt-get install cmake`)
+
+Optional prerequisites - used automatically if findable by CMake:
+
+- [Intel Threaded Building Blocks (TBB)](http://www.threadingbuildingblocks.org/) (Ubuntu: `sudo apt-get install libtbb-dev`)
+- [Intel Math Kernel Library (MKL)](http://software.intel.com/en-us/intel-mkl)
+
+Additional Information
+----------------------
+
+Read about important [`GTSAM-Concepts`] here.
+
+See the [`INSTALL`] file for more detailed installation instructions.
+
+GTSAM is open source under the BSD license, see the [`LICENSE`](https://bitbucket.org/gtborg/gtsam/src/develop/LICENSE) and [`LICENSE.BSD`](https://bitbucket.org/gtborg/gtsam/src/develop/LICENSE.BSD) files.
+
+Please see the [`examples/`](examples) directory and the [`USAGE`] file for examples on how to use GTSAM.
\ No newline at end of file
diff --git a/cmake/GtsamBuildTypes.cmake b/cmake/GtsamBuildTypes.cmake
index 9a0b297ab..2f11df94e 100644
--- a/cmake/GtsamBuildTypes.cmake
+++ b/cmake/GtsamBuildTypes.cmake
@@ -15,8 +15,8 @@ option(GTSAM_BUILD_TYPE_POSTFIXES "Enable/Disable appending the build typ
# Add debugging flags but only on the first pass
if(NOT FIRST_PASS_DONE)
if(MSVC)
- set(CMAKE_C_FLAGS_DEBUG "/D_DEBUG /MDd /Zi /Ob0 /Od /RTC1 /W3 /GR /EHsc /MP /DWINDOWS_LEAN_AND_MEAN" CACHE STRING "Flags used by the compiler during debug builds." FORCE)
- set(CMAKE_CXX_FLAGS_DEBUG "/D_DEBUG /MDd /Zi /Ob0 /Od /RTC1 /W3 /GR /EHsc /MP /DWINDOWS_LEAN_AND_MEAN" CACHE STRING "Flags used by the compiler during debug builds." FORCE)
+ set(CMAKE_C_FLAGS_DEBUG "/D_DEBUG /MDd /Zi /Ob0 /Od /RTC1 /W3 /GR /EHsc /MP /DWINDOWS_LEAN_AND_MEAN /DEIGEN_INITIALIZE_MATRICES_BY_NAN" CACHE STRING "Flags used by the compiler during debug builds." FORCE)
+ set(CMAKE_CXX_FLAGS_DEBUG "/D_DEBUG /MDd /Zi /Ob0 /Od /RTC1 /W3 /GR /EHsc /MP /DWINDOWS_LEAN_AND_MEAN /DEIGEN_INITIALIZE_MATRICES_BY_NAN" CACHE STRING "Flags used by the compiler during debug builds." FORCE)
set(CMAKE_C_FLAGS_RELWITHDEBINFO "/MD /O2 /DNDEBUG /W3 /GR /EHsc /MP /Zi /d2Zi+ /DWINDOWS_LEAN_AND_MEAN" CACHE STRING "Flags used by the compiler during relwithdebinfo builds." FORCE)
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "/MD /O2 /DNDEBUG /W3 /GR /EHsc /MP /Zi /d2Zi+ /DWINDOWS_LEAN_AND_MEAN" CACHE STRING "Flags used by the compiler during relwithdebinfo builds." FORCE)
set(CMAKE_C_FLAGS_RELEASE "/MD /O2 /DNDEBUG /W3 /GR /EHsc /MP /DWINDOWS_LEAN_AND_MEAN" CACHE STRING "Flags used by the compiler during release builds." FORCE)
@@ -34,8 +34,8 @@ if(NOT FIRST_PASS_DONE)
set(CMAKE_MODULE_LINKER_FLAGS_PROFILING "${CMAKE_MODULE_LINKER_FLAGS_RELEASE}" CACHE STRING "Linker flags during profiling builds." FORCE)
mark_as_advanced(CMAKE_C_FLAGS_PROFILING CMAKE_CXX_FLAGS_PROFILING CMAKE_EXE_LINKER_FLAGS_PROFILING CMAKE_SHARED_LINKER_FLAGS_PROFILING CMAKE_MODULE_LINKER_FLAGS_PROFILING)
else()
- set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -fno-inline -Wall" CACHE STRING "Flags used by the compiler during debug builds." FORCE)
- set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -fno-inline -Wall" CACHE STRING "Flags used by the compiler during debug builds." FORCE)
+ set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -fno-inline -Wall -DEIGEN_INITIALIZE_MATRICES_BY_NAN" CACHE STRING "Flags used by the compiler during debug builds." FORCE)
+ set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -fno-inline -Wall -DEIGEN_INITIALIZE_MATRICES_BY_NAN" CACHE STRING "Flags used by the compiler during debug builds." FORCE)
set(CMAKE_C_FLAGS_RELWITHDEBINFO "-g -O3 -Wall -DNDEBUG" CACHE STRING "Flags used by the compiler during relwithdebinfo builds." FORCE)
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-g -O3 -Wall -DNDEBUG" CACHE STRING "Flags used by the compiler during relwithdebinfo builds." FORCE)
set(CMAKE_C_FLAGS_RELEASE "-O3 -Wall -DNDEBUG -Wall" CACHE STRING "Flags used by the compiler during release builds." FORCE)
diff --git a/gtsam.h b/gtsam.h
index 96d51117a..67b3f2888 100644
--- a/gtsam.h
+++ b/gtsam.h
@@ -758,10 +758,6 @@ class CalibratedCamera {
gtsam::CalibratedCamera retract(const Vector& d) const;
Vector localCoordinates(const gtsam::CalibratedCamera& T2) const;
- // Group
- gtsam::CalibratedCamera compose(const gtsam::CalibratedCamera& c) const;
- gtsam::CalibratedCamera inverse() const;
-
// Action on Point3
gtsam::Point2 project(const gtsam::Point3& point) const;
static gtsam::Point2 project_to_camera(const gtsam::Point3& cameraPoint);
@@ -2198,10 +2194,14 @@ typedef gtsam::RangeFactor RangeFactorPosePoint2;
typedef gtsam::RangeFactor RangeFactorPosePoint3;
typedef gtsam::RangeFactor RangeFactorPose2;
typedef gtsam::RangeFactor RangeFactorPose3;
-typedef gtsam::RangeFactor RangeFactorCalibratedCameraPoint;
-typedef gtsam::RangeFactor RangeFactorSimpleCameraPoint;
-typedef gtsam::RangeFactor RangeFactorCalibratedCamera;
-typedef gtsam::RangeFactor RangeFactorSimpleCamera;
+
+// Commented out by Frank Dec 2014: not poses!
+// If needed, we need a RangeFactor that takes a camera, extracts the pose
+// Should be easy with Expressions
+//typedef gtsam::RangeFactor RangeFactorCalibratedCameraPoint;
+//typedef gtsam::RangeFactor RangeFactorSimpleCameraPoint;
+//typedef gtsam::RangeFactor RangeFactorCalibratedCamera;
+//typedef gtsam::RangeFactor RangeFactorSimpleCamera;
#include
diff --git a/gtsam/3rdparty/CMakeLists.txt b/gtsam/3rdparty/CMakeLists.txt
index 49d5a2fbb..301548dcf 100644
--- a/gtsam/3rdparty/CMakeLists.txt
+++ b/gtsam/3rdparty/CMakeLists.txt
@@ -45,6 +45,8 @@ endif()
option(GTSAM_BUILD_METIS_EXECUTABLES "Build metis library executables" OFF)
add_subdirectory(metis)
+add_subdirectory(ceres)
+
############ NOTE: When updating GeographicLib be sure to disable building their examples
############ and unit tests by commenting out their lines:
# add_subdirectory (examples)
diff --git a/gtsam/3rdparty/ceres/CMakeLists.txt b/gtsam/3rdparty/ceres/CMakeLists.txt
new file mode 100644
index 000000000..98b2cffce
--- /dev/null
+++ b/gtsam/3rdparty/ceres/CMakeLists.txt
@@ -0,0 +1,2 @@
+file(GLOB ceres_headers "${CMAKE_CURRENT_SOURCE_DIR}/*.h")
+install(FILES ${ceres_headers} DESTINATION include/gtsam/3rdparty/ceres)
\ No newline at end of file
diff --git a/gtsam_unstable/nonlinear/ceres_autodiff.h b/gtsam/3rdparty/ceres/autodiff.h
similarity index 98%
rename from gtsam_unstable/nonlinear/ceres_autodiff.h
rename to gtsam/3rdparty/ceres/autodiff.h
index 2a0ac8987..f124425cc 100644
--- a/gtsam_unstable/nonlinear/ceres_autodiff.h
+++ b/gtsam/3rdparty/ceres/autodiff.h
@@ -142,10 +142,10 @@
#include
-#include
-#include
-#include
-#include
+#include
+#include
+#include
+#include
#define DCHECK assert
#define DCHECK_GT(a,b) assert((a)>(b))
diff --git a/gtsam_unstable/nonlinear/ceres_eigen.h b/gtsam/3rdparty/ceres/eigen.h
similarity index 100%
rename from gtsam_unstable/nonlinear/ceres_eigen.h
rename to gtsam/3rdparty/ceres/eigen.h
diff --git a/gtsam_unstable/nonlinear/ceres_example.h b/gtsam/3rdparty/ceres/example.h
similarity index 98%
rename from gtsam_unstable/nonlinear/ceres_example.h
rename to gtsam/3rdparty/ceres/example.h
index 45ec3428e..6b051fce0 100644
--- a/gtsam_unstable/nonlinear/ceres_example.h
+++ b/gtsam/3rdparty/ceres/example.h
@@ -33,7 +33,7 @@
#pragma once
-#include
+#include
// Templated pinhole camera model for used with Ceres. The camera is
// parameterized using 9 parameters: 3 for rotation, 3 for translation, 1 for
diff --git a/gtsam_unstable/nonlinear/ceres_fixed_array.h b/gtsam/3rdparty/ceres/fixed_array.h
similarity index 98%
rename from gtsam_unstable/nonlinear/ceres_fixed_array.h
rename to gtsam/3rdparty/ceres/fixed_array.h
index 69a426379..db1591636 100644
--- a/gtsam_unstable/nonlinear/ceres_fixed_array.h
+++ b/gtsam/3rdparty/ceres/fixed_array.h
@@ -34,8 +34,8 @@
#include
#include
-#include
-#include
+#include
+#include
namespace ceres {
namespace internal {
diff --git a/gtsam_unstable/nonlinear/ceres_fpclassify.h b/gtsam/3rdparty/ceres/fpclassify.h
similarity index 100%
rename from gtsam_unstable/nonlinear/ceres_fpclassify.h
rename to gtsam/3rdparty/ceres/fpclassify.h
diff --git a/gtsam_unstable/nonlinear/ceres_jet.h b/gtsam/3rdparty/ceres/jet.h
similarity index 99%
rename from gtsam_unstable/nonlinear/ceres_jet.h
rename to gtsam/3rdparty/ceres/jet.h
index ed4834caf..12d4e8bc9 100644
--- a/gtsam_unstable/nonlinear/ceres_jet.h
+++ b/gtsam/3rdparty/ceres/jet.h
@@ -163,7 +163,7 @@
#include
#include
-#include
+#include
namespace ceres {
diff --git a/gtsam_unstable/nonlinear/ceres_macros.h b/gtsam/3rdparty/ceres/macros.h
similarity index 100%
rename from gtsam_unstable/nonlinear/ceres_macros.h
rename to gtsam/3rdparty/ceres/macros.h
diff --git a/gtsam_unstable/nonlinear/ceres_manual_constructor.h b/gtsam/3rdparty/ceres/manual_constructor.h
similarity index 100%
rename from gtsam_unstable/nonlinear/ceres_manual_constructor.h
rename to gtsam/3rdparty/ceres/manual_constructor.h
diff --git a/gtsam_unstable/nonlinear/ceres_rotation.h b/gtsam/3rdparty/ceres/rotation.h
similarity index 100%
rename from gtsam_unstable/nonlinear/ceres_rotation.h
rename to gtsam/3rdparty/ceres/rotation.h
diff --git a/gtsam_unstable/nonlinear/ceres_variadic_evaluate.h b/gtsam/3rdparty/ceres/variadic_evaluate.h
similarity index 97%
rename from gtsam_unstable/nonlinear/ceres_variadic_evaluate.h
rename to gtsam/3rdparty/ceres/variadic_evaluate.h
index 7d22fe22e..86aec4829 100644
--- a/gtsam_unstable/nonlinear/ceres_variadic_evaluate.h
+++ b/gtsam/3rdparty/ceres/variadic_evaluate.h
@@ -34,9 +34,9 @@
#include
-#include
-#include
-#include
+#include
+#include
+#include
namespace ceres {
namespace internal {
diff --git a/gtsam/base/LieMatrix.h b/gtsam/base/LieMatrix.h
index f1fc69e71..7b120df1c 100644
--- a/gtsam/base/LieMatrix.h
+++ b/gtsam/base/LieMatrix.h
@@ -19,6 +19,12 @@
#include
+#ifdef _MSC_VER
+#pragma message("LieMatrix.h is deprecated. Please use Eigen::Matrix instead.")
+#else
+#warning "LieMatrix.h is deprecated. Please use Eigen::Matrix instead."
+#endif
+
#include
#include
#include
@@ -27,7 +33,9 @@
namespace gtsam {
/**
- * LieVector is a wrapper around vector to allow it to be a Lie type
+ * @deprecated: LieScalar, LieVector and LieMatrix are obsolete in GTSAM 4.0 as
+ * we can directly add double, Vector, and Matrix into values now, because of
+ * gtsam::traits.
*/
struct LieMatrix : public Matrix {
diff --git a/gtsam/base/LieScalar.h b/gtsam/base/LieScalar.h
index 5125340be..b208a584a 100644
--- a/gtsam/base/LieScalar.h
+++ b/gtsam/base/LieScalar.h
@@ -17,6 +17,12 @@
#pragma once
+#ifdef _MSC_VER
+#pragma message("LieScalar.h is deprecated. Please use double/float instead.")
+#else
+ #warning "LieScalar.h is deprecated. Please use double/float instead."
+#endif
+
#include
#include
#include
@@ -24,7 +30,9 @@
namespace gtsam {
/**
- * LieScalar is a wrapper around double to allow it to be a Lie type
+ * @deprecated: LieScalar, LieVector and LieMatrix are obsolete in GTSAM 4.0 as
+ * we can directly add double, Vector, and Matrix into values now, because of
+ * gtsam::traits.
*/
struct GTSAM_EXPORT LieScalar {
diff --git a/gtsam/base/LieVector.h b/gtsam/base/LieVector.h
index d1b2ad78c..d158548ad 100644
--- a/gtsam/base/LieVector.h
+++ b/gtsam/base/LieVector.h
@@ -17,6 +17,12 @@
#pragma once
+#ifdef _MSC_VER
+#pragma message("LieVector.h is deprecated. Please use Eigen::Vector instead.")
+#else
+#warning "LieVector.h is deprecated. Please use Eigen::Vector instead."
+#endif
+
#include
#include
#include
@@ -24,7 +30,9 @@
namespace gtsam {
/**
- * LieVector is a wrapper around vector to allow it to be a Lie type
+ * @deprecated: LieScalar, LieVector and LieMatrix are obsolete in GTSAM 4.0 as
+ * we can directly add double, Vector, and Matrix into values now, because of
+ * gtsam::traits.
*/
struct LieVector : public Vector {
diff --git a/gtsam/base/Matrix.h b/gtsam/base/Matrix.h
index 132bf79ad..3ecfcf8fa 100644
--- a/gtsam/base/Matrix.h
+++ b/gtsam/base/Matrix.h
@@ -37,27 +37,31 @@ namespace gtsam {
typedef Eigen::MatrixXd Matrix;
typedef Eigen::Matrix MatrixRowMajor;
-typedef Eigen::Matrix2d Matrix2;
-typedef Eigen::Matrix3d Matrix3;
-typedef Eigen::Matrix4d Matrix4;
-typedef Eigen::Matrix Matrix5;
-typedef Eigen::Matrix Matrix6;
+// Create handy typedefs and constants for square-size matrices
+// MatrixMN, MatrixN = MatrixNN, I_NxN, and Z_NxN, for M,N=1..9
+#define GTSAM_MAKE_TYPEDEFS(SIZE, SUFFIX) \
+typedef Eigen::Matrix Matrix##SUFFIX; \
+typedef Eigen::Matrix Matrix1##SUFFIX; \
+typedef Eigen::Matrix Matrix2##SUFFIX; \
+typedef Eigen::Matrix Matrix3##SUFFIX; \
+typedef Eigen::Matrix Matrix4##SUFFIX; \
+typedef Eigen::Matrix Matrix5##SUFFIX; \
+typedef Eigen::Matrix Matrix6##SUFFIX; \
+typedef Eigen::Matrix Matrix7##SUFFIX; \
+typedef Eigen::Matrix Matrix8##SUFFIX; \
+typedef Eigen::Matrix Matrix9##SUFFIX; \
+static const Eigen::MatrixBase::IdentityReturnType I_##SUFFIX##x##SUFFIX = Matrix##SUFFIX::Identity(); \
+static const Eigen::MatrixBase::ConstantReturnType Z_##SUFFIX##x##SUFFIX = Matrix##SUFFIX::Zero();
-typedef Eigen::Matrix Matrix23;
-typedef Eigen::Matrix Matrix24;
-typedef Eigen::Matrix Matrix25;
-typedef Eigen::Matrix Matrix26;
-typedef Eigen::Matrix Matrix27;
-typedef Eigen::Matrix Matrix28;
-typedef Eigen::Matrix Matrix29;
-
-typedef Eigen::Matrix Matrix32;
-typedef Eigen::Matrix Matrix34;
-typedef Eigen::Matrix Matrix35;
-typedef Eigen::Matrix Matrix36;
-typedef Eigen::Matrix Matrix37;
-typedef Eigen::Matrix Matrix38;
-typedef Eigen::Matrix Matrix39;
+GTSAM_MAKE_TYPEDEFS(1,1);
+GTSAM_MAKE_TYPEDEFS(2,2);
+GTSAM_MAKE_TYPEDEFS(3,3);
+GTSAM_MAKE_TYPEDEFS(4,4);
+GTSAM_MAKE_TYPEDEFS(5,5);
+GTSAM_MAKE_TYPEDEFS(6,6);
+GTSAM_MAKE_TYPEDEFS(7,7);
+GTSAM_MAKE_TYPEDEFS(8,8);
+GTSAM_MAKE_TYPEDEFS(9,9);
// Matrix expressions for accessing parts of matrices
typedef Eigen::Block SubMatrix;
diff --git a/gtsam/base/OptionalJacobian.h b/gtsam/base/OptionalJacobian.h
new file mode 100644
index 000000000..5651816ba
--- /dev/null
+++ b/gtsam/base/OptionalJacobian.h
@@ -0,0 +1,115 @@
+/* ----------------------------------------------------------------------------
+
+ * GTSAM Copyright 2010, Georgia Tech Research Corporation,
+ * Atlanta, Georgia 30332-0415
+ * All Rights Reserved
+ * Authors: Frank Dellaert, et al. (see THANKS for the full author list)
+
+ * See LICENSE for the license information
+
+ * -------------------------------------------------------------------------- */
+
+/**
+ * @file OptionalJacobian.h
+ * @brief Special class for optional Matrix arguments
+ * @author Frank Dellaert
+ * @author Natesh Srinivasan
+ * @date Nov 28, 2014
+ */
+
+#pragma once
+
+#include
+
+#ifndef OPTIONALJACOBIAN_NOBOOST
+#include
+#endif
+
+namespace gtsam {
+
+/**
+ * OptionalJacobian is an Eigen::Ref like class that can take be constructed using
+ * either a fixed size or dynamic Eigen matrix. In the latter case, the dynamic
+ * matrix will be resized. Finally, there is a constructor that takes
+ * boost::none, the default constructor acts like boost::none, and
+ * boost::optional is also supported for backwards compatibility.
+ */
+template
+class OptionalJacobian {
+
+public:
+
+ /// Fixed size type
+ typedef Eigen::Matrix Fixed;
+
+private:
+
+ Eigen::Map map_; /// View on constructor argument, if given
+
+ // Trick from http://eigen.tuxfamily.org/dox/group__TutorialMapClass.html
+ // uses "placement new" to make map_ usurp the memory of the fixed size matrix
+ void usurp(double* data) {
+ new (&map_) Eigen::Map(data);
+ }
+
+public:
+
+ /// Default constructor acts like boost::none
+ OptionalJacobian() :
+ map_(NULL) {
+ }
+
+ /// Constructor that will usurp data of a fixed-size matrix
+ OptionalJacobian(Fixed& fixed) :
+ map_(NULL) {
+ usurp(fixed.data());
+ }
+
+ /// Constructor that will usurp data of a fixed-size matrix, pointer version
+ OptionalJacobian(Fixed* fixedPtr) :
+ map_(NULL) {
+ if (fixedPtr)
+ usurp(fixedPtr->data());
+ }
+
+ /// Constructor that will resize a dynamic matrix (unless already correct)
+ OptionalJacobian(Eigen::MatrixXd& dynamic) :
+ map_(NULL) {
+ dynamic.resize(Rows, Cols); // no malloc if correct size
+ usurp(dynamic.data());
+ }
+
+#ifndef OPTIONALJACOBIAN_NOBOOST
+
+ /// Constructor with boost::none just makes empty
+ OptionalJacobian(boost::none_t none) :
+ map_(NULL) {
+ }
+
+ /// Constructor compatible with old-style derivatives
+ OptionalJacobian(const boost::optional optional) :
+ map_(NULL) {
+ if (optional) {
+ optional->resize(Rows, Cols);
+ usurp(optional->data());
+ }
+ }
+
+#endif
+
+ /// Return true is allocated, false if default constructor was used
+ operator bool() const {
+ return map_.data();
+ }
+
+ /// De-reference, like boost optional
+ Eigen::Map& operator*() {
+ return map_;
+ }
+
+ /// TODO: operator->()
+ Eigen::Map* operator->(){ return &map_; }
+};
+
+} // namespace gtsam
+
diff --git a/gtsam/base/Vector.h b/gtsam/base/Vector.h
index 1be8408d2..74cd248a1 100644
--- a/gtsam/base/Vector.h
+++ b/gtsam/base/Vector.h
@@ -34,6 +34,7 @@ namespace gtsam {
typedef Eigen::VectorXd Vector;
// Commonly used fixed size vectors
+typedef Eigen::Matrix Vector1;
typedef Eigen::Vector2d Vector2;
typedef Eigen::Vector3d Vector3;
typedef Eigen::Matrix Vector4;
@@ -42,6 +43,7 @@ typedef Eigen::Matrix Vector6;
typedef Eigen::Matrix Vector7;
typedef Eigen::Matrix Vector8;
typedef Eigen::Matrix Vector9;
+typedef Eigen::Matrix Vector10;
typedef Eigen::VectorBlock SubVector;
typedef Eigen::VectorBlock ConstSubVector;
diff --git a/gtsam/base/debug.cpp b/gtsam/base/debug.cpp
index e50e3af35..6abc98642 100644
--- a/gtsam/base/debug.cpp
+++ b/gtsam/base/debug.cpp
@@ -17,9 +17,32 @@
*/
#include
+#ifdef GTSAM_USE_TBB
+#include
+#endif
namespace gtsam {
- GTSAM_EXPORT FastMap > debugFlags;
+GTSAM_EXPORT FastMap > debugFlags;
+
+#ifdef GTSAM_USE_TBB
+tbb::mutex debugFlagsMutex;
+#endif
+
+/* ************************************************************************* */
+bool guardedIsDebug(const std::string& s) {
+#ifdef GTSAM_USE_TBB
+ tbb::mutex::scoped_lock lock(debugFlagsMutex);
+#endif
+ return gtsam::debugFlags[s];
+}
+
+/* ************************************************************************* */
+void guardedSetDebug(const std::string& s, const bool v) {
+#ifdef GTSAM_USE_TBB
+ tbb::mutex::scoped_lock lock(debugFlagsMutex);
+#endif
+ gtsam::debugFlags[s] = v;
+}
}
diff --git a/gtsam/base/debug.h b/gtsam/base/debug.h
index f416bd826..e21efcc83 100644
--- a/gtsam/base/debug.h
+++ b/gtsam/base/debug.h
@@ -43,6 +43,10 @@
namespace gtsam {
GTSAM_EXTERN_EXPORT FastMap > debugFlags;
+
+ // Non-guarded use led to crashes, and solved in commit cd35db2
+ bool GTSAM_EXPORT guardedIsDebug(const std::string& s);
+ void GTSAM_EXPORT guardedSetDebug(const std::string& s, const bool v);
}
#undef ISDEBUG
@@ -50,8 +54,8 @@ namespace gtsam {
#ifdef GTSAM_ENABLE_DEBUG
-#define ISDEBUG(S) (gtsam::debugFlags[S])
-#define SETDEBUG(S,V) ((void)(gtsam::debugFlags[S] = (V)))
+#define ISDEBUG(S) (gtsam::guardedIsDebug(S))
+#define SETDEBUG(S,V) ((void)(gtsam::guardedSetDebug(S,V)))
#else
diff --git a/gtsam/base/tests/testOptionalJacobian.cpp b/gtsam/base/tests/testOptionalJacobian.cpp
new file mode 100644
index 000000000..6584c82d1
--- /dev/null
+++ b/gtsam/base/tests/testOptionalJacobian.cpp
@@ -0,0 +1,105 @@
+/* ----------------------------------------------------------------------------
+
+ * GTSAM Copyright 2010, Georgia Tech Research Corporation,
+ * Atlanta, Georgia 30332-0415
+ * All Rights Reserved
+ * Authors: Frank Dellaert, et al. (see THANKS for the full author list)
+
+ * See LICENSE for the license information
+
+ * -------------------------------------------------------------------------- */
+
+/**
+ * @file testOptionalJacobian.cpp
+ * @brief Unit test for OptionalJacobian
+ * @author Frank Dellaert
+ * @date Nov 28, 2014
+ **/
+
+#include
+#include
+#include
+
+using namespace std;
+using namespace gtsam;
+
+//******************************************************************************
+TEST( OptionalJacobian, Constructors ) {
+ Matrix23 fixed;
+
+ OptionalJacobian<2, 3> H1;
+ EXPECT(!H1);
+
+ OptionalJacobian<2, 3> H2(fixed);
+ EXPECT(H2);
+
+ OptionalJacobian<2, 3> H3(&fixed);
+ EXPECT(H3);
+
+ Matrix dynamic;
+ OptionalJacobian<2, 3> H4(dynamic);
+ EXPECT(H4);
+
+ OptionalJacobian<2, 3> H5(boost::none);
+ EXPECT(!H5);
+
+ boost::optional optional(dynamic);
+ OptionalJacobian<2, 3> H6(optional);
+ EXPECT(H6);
+}
+
+//******************************************************************************
+void test(OptionalJacobian<2, 3> H = boost::none) {
+ if (H)
+ *H = Matrix23::Zero();
+}
+
+void testPtr(Matrix23* H = NULL) {
+ if (H)
+ *H = Matrix23::Zero();
+}
+
+TEST( OptionalJacobian, Ref2) {
+
+ Matrix expected;
+ expected = Matrix23::Zero();
+
+ // Default argument does nothing
+ test();
+
+ // Fixed size, no copy
+ Matrix23 fixed1;
+ fixed1.setOnes();
+ test(fixed1);
+ EXPECT(assert_equal(expected,fixed1));
+
+ // Fixed size, no copy, pointer style
+ Matrix23 fixed2;
+ fixed2.setOnes();
+ test(&fixed2);
+ EXPECT(assert_equal(expected,fixed2));
+
+ // Empty is no longer a sign we don't want a matrix, we want it resized
+ Matrix dynamic0;
+ test(dynamic0);
+ EXPECT(assert_equal(expected,dynamic0));
+
+ // Dynamic wrong size
+ Matrix dynamic1(3, 5);
+ dynamic1.setOnes();
+ test(dynamic1);
+ EXPECT(assert_equal(expected,dynamic0));
+
+ // Dynamic right size
+ Matrix dynamic2(2, 5);
+ dynamic2.setOnes();
+ test(dynamic2);
+ EXPECT(assert_equal(dynamic2,dynamic0));
+}
+
+//******************************************************************************
+int main() {
+ TestResult tr;
+ return TestRegistry::runAllTests(tr);
+}
+//******************************************************************************
diff --git a/gtsam/geometry/Cal3Bundler.cpp b/gtsam/geometry/Cal3Bundler.cpp
index 8ff728d26..368ae6c98 100644
--- a/gtsam/geometry/Cal3Bundler.cpp
+++ b/gtsam/geometry/Cal3Bundler.cpp
@@ -34,20 +34,22 @@ Cal3Bundler::Cal3Bundler(double f, double k1, double k2, double u0, double v0) :
}
/* ************************************************************************* */
-Matrix Cal3Bundler::K() const {
+Matrix3 Cal3Bundler::K() const {
Matrix3 K;
K << f_, 0, u0_, 0, f_, v0_, 0, 0, 1;
return K;
}
/* ************************************************************************* */
-Vector Cal3Bundler::k() const {
- return (Vector(4) << k1_, k2_, 0, 0).finished();
+Vector4 Cal3Bundler::k() const {
+ Vector4 rvalue_;
+ rvalue_ << k1_, k2_, 0, 0;
+ return rvalue_;
}
/* ************************************************************************* */
Vector3 Cal3Bundler::vector() const {
- return (Vector(3) << f_, k1_, k2_).finished();
+ return Vector3(f_, k1_, k2_);
}
/* ************************************************************************* */
@@ -64,21 +66,9 @@ bool Cal3Bundler::equals(const Cal3Bundler& K, double tol) const {
return true;
}
-/* ************************************************************************* */
-Point2 Cal3Bundler::uncalibrate(const Point2& p) const {
- // r = x^2 + y^2;
- // g = (1 + k(1)*r + k(2)*r^2);
- // pi(:,i) = g * pn(:,i)
- const double x = p.x(), y = p.y();
- const double r = x * x + y * y;
- const double g = 1. + (k1_ + k2_ * r) * r;
- const double u = g * x, v = g * y;
- return Point2(u0_ + f_ * u, v0_ + f_ * v);
-}
-
/* ************************************************************************* */
Point2 Cal3Bundler::uncalibrate(const Point2& p, //
- boost::optional Dcal, boost::optional Dp) const {
+ OptionalJacobian<2, 3> Dcal, OptionalJacobian<2, 2> Dp) const {
// r = x^2 + y^2;
// g = (1 + k(1)*r + k(2)*r^2);
// pi(:,i) = g * pn(:,i)
@@ -103,35 +93,6 @@ Point2 Cal3Bundler::uncalibrate(const Point2& p, //
return Point2(u0_ + f_ * u, v0_ + f_ * v);
}
-/* ************************************************************************* */
-Point2 Cal3Bundler::uncalibrate(const Point2& p, //
- boost::optional Dcal, boost::optional Dp) const {
- // r = x^2 + y^2;
- // g = (1 + k(1)*r + k(2)*r^2);
- // pi(:,i) = g * pn(:,i)
- const double x = p.x(), y = p.y();
- const double r = x * x + y * y;
- const double g = 1. + (k1_ + k2_ * r) * r;
- const double u = g * x, v = g * y;
-
- // Derivatives make use of intermediate variables above
- if (Dcal) {
- double rx = r * x, ry = r * y;
- Dcal->resize(2, 3);
- *Dcal << u, f_ * rx, f_ * r * rx, v, f_ * ry, f_ * r * ry;
- }
-
- if (Dp) {
- const double a = 2. * (k1_ + 2. * k2_ * r);
- const double axx = a * x * x, axy = a * x * y, ayy = a * y * y;
- Dp->resize(2,2);
- *Dp << g + axx, axy, axy, g + ayy;
- *Dp *= f_;
- }
-
- return Point2(u0_ + f_ * u, v0_ + f_ * v);
-}
-
/* ************************************************************************* */
Point2 Cal3Bundler::calibrate(const Point2& pi, const double tol) const {
// Copied from Cal3DS2 :-(
@@ -161,24 +122,25 @@ Point2 Cal3Bundler::calibrate(const Point2& pi, const double tol) const {
}
/* ************************************************************************* */
-Matrix Cal3Bundler::D2d_intrinsic(const Point2& p) const {
- Matrix Dp;
+Matrix2 Cal3Bundler::D2d_intrinsic(const Point2& p) const {
+ Matrix2 Dp;
uncalibrate(p, boost::none, Dp);
return Dp;
}
/* ************************************************************************* */
-Matrix Cal3Bundler::D2d_calibration(const Point2& p) const {
- Matrix Dcal;
+Matrix23 Cal3Bundler::D2d_calibration(const Point2& p) const {
+ Matrix23 Dcal;
uncalibrate(p, Dcal, boost::none);
return Dcal;
}
/* ************************************************************************* */
-Matrix Cal3Bundler::D2d_intrinsic_calibration(const Point2& p) const {
- Matrix Dcal, Dp;
+Matrix25 Cal3Bundler::D2d_intrinsic_calibration(const Point2& p) const {
+ Matrix23 Dcal;
+ Matrix2 Dp;
uncalibrate(p, Dcal, Dp);
- Matrix H(2, 5);
+ Matrix25 H;
H << Dp, Dcal;
return H;
}
diff --git a/gtsam/geometry/Cal3Bundler.h b/gtsam/geometry/Cal3Bundler.h
index 4c77fdf23..fc1d63e10 100644
--- a/gtsam/geometry/Cal3Bundler.h
+++ b/gtsam/geometry/Cal3Bundler.h
@@ -69,8 +69,8 @@ public:
/// @name Standard Interface
/// @{
- Matrix K() const; ///< Standard 3*3 calibration matrix
- Vector k() const; ///< Radial distortion parameters (4 of them, 2 0)
+ Matrix3 K() const; ///< Standard 3*3 calibration matrix
+ Vector4 k() const; ///< Radial distortion parameters (4 of them, 2 0)
Vector3 vector() const;
@@ -106,43 +106,27 @@ public:
/**
- * convert intrinsic coordinates xy to image coordinates uv
- * @param p point in intrinsic coordinates
- * @return point in image coordinates
- */
- Point2 uncalibrate(const Point2& p) const;
-
- /**
- * Version of uncalibrate with fixed derivatives
+ * @brief: convert intrinsic coordinates xy to image coordinates uv
+ * Version of uncalibrate with derivatives
* @param p point in intrinsic coordinates
* @param Dcal optional 2*3 Jacobian wrpt CalBundler parameters
* @param Dp optional 2*2 Jacobian wrpt intrinsic coordinates
* @return point in image coordinates
*/
- Point2 uncalibrate(const Point2& p, boost::optional Dcal,
- boost::optional Dp) const;
-
- /**
- * Version of uncalibrate with dynamic derivatives
- * @param p point in intrinsic coordinates
- * @param Dcal optional 2*3 Jacobian wrpt CalBundler parameters
- * @param Dp optional 2*2 Jacobian wrpt intrinsic coordinates
- * @return point in image coordinates
- */
- Point2 uncalibrate(const Point2& p, boost::optional Dcal,
- boost::optional Dp) const;
+ Point2 uncalibrate(const Point2& p, OptionalJacobian<2, 3> Dcal = boost::none,
+ OptionalJacobian<2, 2> Dp = boost::none) const;
/// Conver a pixel coordinate to ideal coordinate
Point2 calibrate(const Point2& pi, const double tol = 1e-5) const;
/// @deprecated might be removed in next release, use uncalibrate
- Matrix D2d_intrinsic(const Point2& p) const;
+ Matrix2 D2d_intrinsic(const Point2& p) const;
/// @deprecated might be removed in next release, use uncalibrate
- Matrix D2d_calibration(const Point2& p) const;
+ Matrix23 D2d_calibration(const Point2& p) const;
/// @deprecated might be removed in next release, use uncalibrate
- Matrix D2d_intrinsic_calibration(const Point2& p) const;
+ Matrix25 D2d_intrinsic_calibration(const Point2& p) const;
/// @}
/// @name Manifold
diff --git a/gtsam/geometry/Cal3DS2_Base.cpp b/gtsam/geometry/Cal3DS2_Base.cpp
index 1105fecfb..12060c12d 100644
--- a/gtsam/geometry/Cal3DS2_Base.cpp
+++ b/gtsam/geometry/Cal3DS2_Base.cpp
@@ -28,18 +28,22 @@ Cal3DS2_Base::Cal3DS2_Base(const Vector &v):
fx_(v[0]), fy_(v[1]), s_(v[2]), u0_(v[3]), v0_(v[4]), k1_(v[5]), k2_(v[6]), p1_(v[7]), p2_(v[8]){}
/* ************************************************************************* */
-Matrix Cal3DS2_Base::K() const {
- return (Matrix(3, 3) << fx_, s_, u0_, 0.0, fy_, v0_, 0.0, 0.0, 1.0).finished();
+Matrix3 Cal3DS2_Base::K() const {
+ Matrix3 K;
+ K << fx_, s_, u0_, 0.0, fy_, v0_, 0.0, 0.0, 1.0;
+ return K;
}
/* ************************************************************************* */
-Vector Cal3DS2_Base::vector() const {
- return (Vector(9) << fx_, fy_, s_, u0_, v0_, k1_, k2_, p1_, p2_).finished();
+Vector9 Cal3DS2_Base::vector() const {
+ Vector9 v;
+ v << fx_, fy_, s_, u0_, v0_, k1_, k2_, p1_, p2_;
+ return v;
}
/* ************************************************************************* */
void Cal3DS2_Base::print(const std::string& s_) const {
- gtsam::print(K(), s_ + ".K");
+ gtsam::print((Matrix)K(), s_ + ".K");
gtsam::print(Vector(k()), s_ + ".k");
}
@@ -91,8 +95,7 @@ static Matrix2 D2dintrinsic(double x, double y, double rr,
/* ************************************************************************* */
Point2 Cal3DS2_Base::uncalibrate(const Point2& p,
- boost::optional H1,
- boost::optional H2) const {
+ OptionalJacobian<2,9> H1, OptionalJacobian<2,2> H2) const {
// rr = x^2 + y^2;
// g = (1 + k(1)*rr + k(2)*rr^2);
@@ -126,26 +129,6 @@ Point2 Cal3DS2_Base::uncalibrate(const Point2& p,
return Point2(fx_ * pnx + s_ * pny + u0_, fy_ * pny + v0_);
}
-/* ************************************************************************* */
-Point2 Cal3DS2_Base::uncalibrate(const Point2& p,
- boost::optional H1,
- boost::optional H2) const {
-
- if (H1 || H2) {
- Matrix29 D1;
- Matrix2 D2;
- Point2 pu = uncalibrate(p, D1, D2);
- if (H1)
- *H1 = D1;
- if (H2)
- *H2 = D2;
- return pu;
-
- } else {
- return uncalibrate(p);
- }
-}
-
/* ************************************************************************* */
Point2 Cal3DS2_Base::calibrate(const Point2& pi, const double tol) const {
// Use the following fixed point iteration to invert the radial distortion.
@@ -177,7 +160,7 @@ Point2 Cal3DS2_Base::calibrate(const Point2& pi, const double tol) const {
}
/* ************************************************************************* */
-Matrix Cal3DS2_Base::D2d_intrinsic(const Point2& p) const {
+Matrix2 Cal3DS2_Base::D2d_intrinsic(const Point2& p) const {
const double x = p.x(), y = p.y(), xx = x * x, yy = y * y;
const double rr = xx + yy;
const double r4 = rr * rr;
@@ -188,7 +171,7 @@ Matrix Cal3DS2_Base::D2d_intrinsic(const Point2& p) const {
}
/* ************************************************************************* */
-Matrix Cal3DS2_Base::D2d_calibration(const Point2& p) const {
+Matrix29 Cal3DS2_Base::D2d_calibration(const Point2& p) const {
const double x = p.x(), y = p.y(), xx = x * x, yy = y * y, xy = x * y;
const double rr = xx + yy;
const double r4 = rr * rr;
diff --git a/gtsam/geometry/Cal3DS2_Base.h b/gtsam/geometry/Cal3DS2_Base.h
index 61c01e349..37c156743 100644
--- a/gtsam/geometry/Cal3DS2_Base.h
+++ b/gtsam/geometry/Cal3DS2_Base.h
@@ -45,9 +45,9 @@ protected:
double p1_, p2_ ; // tangential distortion
public:
- Matrix K() const ;
- Eigen::Vector4d k() const { return Eigen::Vector4d(k1_, k2_, p1_, p2_); }
- Vector vector() const ;
+ Matrix3 K() const ;
+ Vector4 k() const { return Vector4(k1_, k2_, p1_, p2_); }
+ Vector9 vector() const ;
/// @name Standard Constructors
/// @{
@@ -113,23 +113,18 @@ public:
* @param Dp optional 2*2 Jacobian wrpt intrinsic coordinates
* @return point in (distorted) image coordinates
*/
-
Point2 uncalibrate(const Point2& p,
- boost::optional Dcal = boost::none,
- boost::optional Dp = boost::none) const ;
-
- Point2 uncalibrate(const Point2& p,
- boost::optional Dcal,
- boost::optional Dp) const ;
+ OptionalJacobian<2,9> Dcal = boost::none,
+ OptionalJacobian<2,2> Dp = boost::none) const ;
/// Convert (distorted) image coordinates uv to intrinsic coordinates xy
Point2 calibrate(const Point2& p, const double tol=1e-5) const;
/// Derivative of uncalibrate wrpt intrinsic coordinates
- Matrix D2d_intrinsic(const Point2& p) const ;
+ Matrix2 D2d_intrinsic(const Point2& p) const ;
/// Derivative of uncalibrate wrpt the calibration parameters
- Matrix D2d_calibration(const Point2& p) const ;
+ Matrix29 D2d_calibration(const Point2& p) const ;
private:
diff --git a/gtsam/geometry/Cal3Unified.cpp b/gtsam/geometry/Cal3Unified.cpp
index 6bc4c4bb3..8b7c1abf4 100644
--- a/gtsam/geometry/Cal3Unified.cpp
+++ b/gtsam/geometry/Cal3Unified.cpp
@@ -29,8 +29,10 @@ Cal3Unified::Cal3Unified(const Vector &v):
Base(v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7], v[8]), xi_(v[9]) {}
/* ************************************************************************* */
-Vector Cal3Unified::vector() const {
- return (Vector(10) << Base::vector(), xi_).finished();
+Vector10 Cal3Unified::vector() const {
+ Vector10 v;
+ v << Base::vector(), xi_;
+ return v;
}
/* ************************************************************************* */
@@ -52,8 +54,8 @@ bool Cal3Unified::equals(const Cal3Unified& K, double tol) const {
/* ************************************************************************* */
// todo: make a fixed sized jacobian version of this
Point2 Cal3Unified::uncalibrate(const Point2& p,
- boost::optional H1,
- boost::optional H2) const {
+ OptionalJacobian<2,10> H1,
+ OptionalJacobian<2,2> H2) const {
// this part of code is modified from Cal3DS2,
// since the second part of this model (after project to normalized plane)
@@ -81,10 +83,7 @@ Point2 Cal3Unified::uncalibrate(const Point2& p,
Vector2 DU;
DU << -xs * sqrt_nx * xi_sqrt_nx2, //
-ys * sqrt_nx * xi_sqrt_nx2;
-
- H1->resize(2,10);
- H1->block<2,9>(0,0) = H1base;
- H1->block<2,1>(0,9) = H2base * DU;
+ *H1 << H1base, H2base * DU;
}
// Inlined derivative for points
@@ -96,7 +95,7 @@ Point2 Cal3Unified::uncalibrate(const Point2& p,
DU << (sqrt_nx + xi*(ys*ys + 1)) * denom, mid, //
mid, (sqrt_nx + xi*(xs*xs + 1)) * denom;
- *H2 = H2base * DU;
+ *H2 << H2base * DU;
}
return puncalib;
@@ -136,7 +135,7 @@ Cal3Unified Cal3Unified::retract(const Vector& d) const {
}
/* ************************************************************************* */
-Vector Cal3Unified::localCoordinates(const Cal3Unified& T2) const {
+Vector10 Cal3Unified::localCoordinates(const Cal3Unified& T2) const {
return T2.vector() - vector();
}
diff --git a/gtsam/geometry/Cal3Unified.h b/gtsam/geometry/Cal3Unified.h
index f65b27780..e2aa3fc8b 100644
--- a/gtsam/geometry/Cal3Unified.h
+++ b/gtsam/geometry/Cal3Unified.h
@@ -51,7 +51,7 @@ private:
public:
- Vector vector() const ;
+ Vector10 vector() const ;
/// @name Standard Constructors
/// @{
@@ -96,8 +96,8 @@ public:
* @return point in image coordinates
*/
Point2 uncalibrate(const Point2& p,
- boost::optional Dcal = boost::none,
- boost::optional Dp = boost::none) const ;
+ OptionalJacobian<2,10> Dcal = boost::none,
+ OptionalJacobian<2,2> Dp = boost::none) const ;
/// Conver a pixel coordinate to ideal coordinate
Point2 calibrate(const Point2& p, const double tol=1e-5) const;
@@ -116,7 +116,7 @@ public:
Cal3Unified retract(const Vector& d) const ;
/// Given a different calibration, calculate update to obtain it
- Vector localCoordinates(const Cal3Unified& T2) const ;
+ Vector10 localCoordinates(const Cal3Unified& T2) const ;
/// Return dimensions of calibration manifold object
virtual size_t dim() const { return 10 ; } //TODO: make a final dimension variable (also, usually size_t in other classes e.g. Pose2)
diff --git a/gtsam/geometry/Cal3_S2.cpp b/gtsam/geometry/Cal3_S2.cpp
index aece1ded1..3ec29bbd2 100644
--- a/gtsam/geometry/Cal3_S2.cpp
+++ b/gtsam/geometry/Cal3_S2.cpp
@@ -53,7 +53,7 @@ Cal3_S2::Cal3_S2(const std::string &path) :
/* ************************************************************************* */
void Cal3_S2::print(const std::string& s) const {
- gtsam::print(matrix(), s);
+ gtsam::print((Matrix)matrix(), s);
}
/* ************************************************************************* */
@@ -72,32 +72,13 @@ bool Cal3_S2::equals(const Cal3_S2& K, double tol) const {
}
/* ************************************************************************* */
-Point2 Cal3_S2::uncalibrate(const Point2& p, boost::optional Dcal,
- boost::optional Dp) const {
+Point2 Cal3_S2::uncalibrate(const Point2& p, OptionalJacobian<2, 5> Dcal,
+ OptionalJacobian<2, 2> Dp) const {
const double x = p.x(), y = p.y();
- if (Dcal) {
- Dcal->resize(2,5);
+ if (Dcal)
*Dcal << x, 0.0, y, 1.0, 0.0, 0.0, y, 0.0, 0.0, 1.0;
- }
- if (Dp) {
- Dp->resize(2,2);
+ if (Dp)
*Dp << fx_, s_, 0.0, fy_;
- }
- return Point2(fx_ * x + s_ * y + u0_, fy_ * y + v0_);
-}
-
-/* ************************************************************************* */
-Point2 Cal3_S2::uncalibrate(const Point2& p, boost::optional Dcal,
- boost::optional Dp) const {
- const double x = p.x(), y = p.y();
- if (Dcal) *Dcal << x, 0.0, y, 1.0, 0.0, 0.0, y, 0.0, 0.0, 1.0;
- if (Dp) *Dp << fx_, s_, 0.0, fy_;
- return Point2(fx_ * x + s_ * y + u0_, fy_ * y + v0_);
-}
-
-/* ************************************************************************* */
-Point2 Cal3_S2::uncalibrate(const Point2& p) const {
- const double x = p.x(), y = p.y();
return Point2(fx_ * x + s_ * y + u0_, fy_ * y + v0_);
}
diff --git a/gtsam/geometry/Cal3_S2.h b/gtsam/geometry/Cal3_S2.h
index 6317d251d..e6b56eea0 100644
--- a/gtsam/geometry/Cal3_S2.h
+++ b/gtsam/geometry/Cal3_S2.h
@@ -117,37 +117,33 @@ public:
}
/// vectorized form (column-wise)
- Vector vector() const {
- double r[] = { fx_, fy_, s_, u0_, v0_ };
- Vector v(5);
- std::copy(r, r + 5, v.data());
+ Vector5 vector() const {
+ Vector5 v;
+ v << fx_, fy_, s_, u0_, v0_;
return v;
}
/// return calibration matrix K
- Matrix K() const {
- return (Matrix(3, 3) << fx_, s_, u0_, 0.0, fy_, v0_, 0.0, 0.0, 1.0).finished();
+ Matrix3 K() const {
+ Matrix3 K;
+ K << fx_, s_, u0_, 0.0, fy_, v0_, 0.0, 0.0, 1.0;
+ return K;
}
/** @deprecated The following function has been deprecated, use K above */
- Matrix matrix() const {
+ Matrix3 matrix() const {
return K();
}
/// return inverted calibration matrix inv(K)
- Matrix matrix_inverse() const {
+ Matrix3 matrix_inverse() const {
const double fxy = fx_ * fy_, sv0 = s_ * v0_, fyu0 = fy_ * u0_;
- return (Matrix(3, 3) << 1.0 / fx_, -s_ / fxy, (sv0 - fyu0) / fxy, 0.0,
- 1.0 / fy_, -v0_ / fy_, 0.0, 0.0, 1.0).finished();
+ Matrix3 K_inverse;
+ K_inverse << 1.0 / fx_, -s_ / fxy, (sv0 - fyu0) / fxy, 0.0,
+ 1.0 / fy_, -v0_ / fy_, 0.0, 0.0, 1.0;
+ return K_inverse;
}
- /**
- * convert intrinsic coordinates xy to image coordinates uv
- * @param p point in intrinsic coordinates
- * @return point in image coordinates
- */
- Point2 uncalibrate(const Point2& p) const;
-
/**
* convert intrinsic coordinates xy to image coordinates uv, fixed derivaitves
* @param p point in intrinsic coordinates
@@ -155,18 +151,8 @@ public:
* @param Dp optional 2*2 Jacobian wrpt intrinsic coordinates
* @return point in image coordinates
*/
- Point2 uncalibrate(const Point2& p, boost::optional Dcal,
- boost::optional Dp) const;
-
- /**
- * convert intrinsic coordinates xy to image coordinates uv, dynamic derivaitves
- * @param p point in intrinsic coordinates
- * @param Dcal optional 2*5 Jacobian wrpt Cal3_S2 parameters
- * @param Dp optional 2*2 Jacobian wrpt intrinsic coordinates
- * @return point in image coordinates
- */
- Point2 uncalibrate(const Point2& p, boost::optional Dcal,
- boost::optional Dp) const;
+ Point2 uncalibrate(const Point2& p, OptionalJacobian<2,5> Dcal = boost::none,
+ OptionalJacobian<2,2> Dp = boost::none) const;
/**
* convert image coordinates uv to intrinsic coordinates xy
@@ -184,10 +170,10 @@ public:
/// "Between", subtracts calibrations. between(p,q) == compose(inverse(p),q)
inline Cal3_S2 between(const Cal3_S2& q,
- boost::optional H1=boost::none,
- boost::optional H2=boost::none) const {
- if(H1) *H1 = -eye(5);
- if(H2) *H2 = eye(5);
+ OptionalJacobian<5,5> H1=boost::none,
+ OptionalJacobian<5,5> H2=boost::none) const {
+ if(H1) *H1 = -I_5x5;
+ if(H2) *H2 = I_5x5;
return Cal3_S2(q.fx_-fx_, q.fy_-fy_, q.s_-s_, q.u0_-u0_, q.v0_-v0_);
}
@@ -212,7 +198,7 @@ public:
}
/// Unretraction for the calibration
- Vector localCoordinates(const Cal3_S2& T2) const {
+ Vector5 localCoordinates(const Cal3_S2& T2) const {
return T2.vector() - vector();
}
diff --git a/gtsam/geometry/Cal3_S2Stereo.h b/gtsam/geometry/Cal3_S2Stereo.h
index b47153547..68732ea8e 100644
--- a/gtsam/geometry/Cal3_S2Stereo.h
+++ b/gtsam/geometry/Cal3_S2Stereo.h
@@ -103,6 +103,38 @@ namespace gtsam {
/// return baseline
inline double baseline() const { return b_; }
+ /// vectorized form (column-wise)
+ Vector6 vector() const {
+ Vector6 v;
+ v << K_.vector(), b_;
+ return v;
+ }
+
+ /// @}
+ /// @name Manifold
+ /// @{
+
+ /// return DOF, dimensionality of tangent space
+ inline size_t dim() const {
+ return 6;
+ }
+
+ /// return DOF, dimensionality of tangent space
+ static size_t Dim() {
+ return 6;
+ }
+
+ /// Given 6-dim tangent vector, create new calibration
+ inline Cal3_S2Stereo retract(const Vector& d) const {
+ return Cal3_S2Stereo(K_.fx() + d(0), K_.fy() + d(1), K_.skew() + d(2), K_.px() + d(3), K_.py() + d(4), b_ + d(5));
+ }
+
+ /// Unretraction for the calibration
+ Vector6 localCoordinates(const Cal3_S2Stereo& T2) const {
+ return T2.vector() - vector();
+ }
+
+
/// @}
/// @name Advanced Interface
/// @{
@@ -119,4 +151,23 @@ namespace gtsam {
/// @}
};
+
+ // Define GTSAM traits
+ namespace traits {
+
+ template<>
+ struct GTSAM_EXPORT is_manifold : public boost::true_type{
+ };
+
+ template<>
+ struct GTSAM_EXPORT dimension : public boost::integral_constant{
+ };
+
+ template<>
+ struct GTSAM_EXPORT zero {
+ static Cal3_S2Stereo value() { return Cal3_S2Stereo();}
+ };
+
+ }
+
} // \ namespace gtsam
diff --git a/gtsam/geometry/CalibratedCamera.cpp b/gtsam/geometry/CalibratedCamera.cpp
index 392a53858..1f5f1f8a5 100644
--- a/gtsam/geometry/CalibratedCamera.cpp
+++ b/gtsam/geometry/CalibratedCamera.cpp
@@ -33,10 +33,10 @@ CalibratedCamera::CalibratedCamera(const Vector &v) :
/* ************************************************************************* */
Point2 CalibratedCamera::project_to_camera(const Point3& P,
- boost::optional H1) {
+ OptionalJacobian<2,3> H1) {
if (H1) {
double d = 1.0 / P.z(), d2 = d * d;
- *H1 = (Matrix(2, 3) << d, 0.0, -P.x() * d2, 0.0, d, -P.y() * d2).finished();
+ *H1 << d, 0.0, -P.x() * d2, 0.0, d, -P.y() * d2;
}
return Point2(P.x() / P.z(), P.y() / P.z());
}
@@ -59,10 +59,12 @@ CalibratedCamera CalibratedCamera::Level(const Pose2& pose2, double height) {
/* ************************************************************************* */
Point2 CalibratedCamera::project(const Point3& point,
- boost::optional Dpose, boost::optional Dpoint) const {
+ OptionalJacobian<2,6> Dpose, OptionalJacobian<2,3> Dpoint) const {
#ifdef CALIBRATEDCAMERA_CHAIN_RULE
- Point3 q = pose_.transform_to(point, Dpose, Dpoint);
+ Matrix36 Dpose_;
+ Matrix3 Dpoint_;
+ Point3 q = pose_.transform_to(point, Dpose ? Dpose_ : 0, Dpoint ? Dpoint_ : 0);
#else
Point3 q = pose_.transform_to(point);
#endif
@@ -75,23 +77,26 @@ Point2 CalibratedCamera::project(const Point3& point,
if (Dpose || Dpoint) {
#ifdef CALIBRATEDCAMERA_CHAIN_RULE
// just implement chain rule
- Matrix H;
- project_to_camera(q,H);
- if (Dpose) *Dpose = H * (*Dpose);
- if (Dpoint) *Dpoint = H * (*Dpoint);
+ if(Dpose && Dpoint) {
+ Matrix23 H;
+ project_to_camera(q,H);
+ if (Dpose) *Dpose = H * (*Dpose_);
+ if (Dpoint) *Dpoint = H * (*Dpoint_);
+ }
#else
// optimized version, see CalibratedCamera.nb
const double z = q.z(), d = 1.0 / z;
const double u = intrinsic.x(), v = intrinsic.y(), uv = u * v;
if (Dpose)
- *Dpose = (Matrix(2, 6) << uv, -(1. + u * u), v, -d, 0., d * u, (1. + v * v),
- -uv, -u, 0., -d, d * v).finished();
+ *Dpose << uv, -(1. + u * u), v, -d, 0., d * u, (1. + v * v),
+ -uv, -u, 0., -d, d * v;
if (Dpoint) {
- const Matrix R(pose_.rotation().matrix());
- *Dpoint = d
- * (Matrix(2, 3) << R(0, 0) - u * R(0, 2), R(1, 0) - u * R(1, 2),
+ const Matrix3 R(pose_.rotation().matrix());
+ Matrix23 Dpoint_;
+ Dpoint_ << R(0, 0) - u * R(0, 2), R(1, 0) - u * R(1, 2),
R(2, 0) - u * R(2, 2), R(0, 1) - v * R(0, 2),
- R(1, 1) - v * R(1, 2), R(2, 1) - v * R(2, 2)).finished();
+ R(1, 1) - v * R(1, 2), R(2, 1) - v * R(2, 2);
+ *Dpoint = d * Dpoint_;
}
#endif
}
diff --git a/gtsam/geometry/CalibratedCamera.h b/gtsam/geometry/CalibratedCamera.h
index c66941091..f5a8b4469 100644
--- a/gtsam/geometry/CalibratedCamera.h
+++ b/gtsam/geometry/CalibratedCamera.h
@@ -18,9 +18,8 @@
#pragma once
-#include
-#include
#include
+#include
namespace gtsam {
@@ -88,26 +87,6 @@ public:
return pose_;
}
- /// compose the two camera poses: TODO Frank says this might not make sense
- inline const CalibratedCamera compose(const CalibratedCamera &c,
- boost::optional H1 = boost::none, boost::optional H2 =
- boost::none) const {
- return CalibratedCamera(pose_.compose(c.pose(), H1, H2));
- }
-
- /// between the two camera poses: TODO Frank says this might not make sense
- inline const CalibratedCamera between(const CalibratedCamera& c,
- boost::optional H1 = boost::none, boost::optional H2 =
- boost::none) const {
- return CalibratedCamera(pose_.between(c.pose(), H1, H2));
- }
-
- /// invert the camera pose: TODO Frank says this might not make sense
- inline const CalibratedCamera inverse(boost::optional H1 =
- boost::none) const {
- return CalibratedCamera(pose_.inverse(H1));
- }
-
/**
* Create a level camera at the given 2D pose and height
* @param pose2 specifies the location and viewing direction
@@ -152,8 +131,8 @@ public:
* @return the intrinsic coordinates of the projected point
*/
Point2 project(const Point3& point,
- boost::optional Dpose = boost::none,
- boost::optional Dpoint = boost::none) const;
+ OptionalJacobian<2, 6> Dpose = boost::none,
+ OptionalJacobian<2, 3> Dpoint = boost::none) const;
/**
* projects a 3-dimensional point in camera coordinates into the
@@ -161,7 +140,7 @@ public:
* With optional 2by3 derivative
*/
static Point2 project_to_camera(const Point3& cameraPoint,
- boost::optional H1 = boost::none);
+ OptionalJacobian<2, 3> H1 = boost::none);
/**
* backproject a 2-dimensional point to a 3-dimension point
@@ -175,8 +154,8 @@ public:
* @param H2 optionally computed Jacobian with respect to the 3D point
* @return range (double)
*/
- double range(const Point3& point, boost::optional H1 = boost::none,
- boost::optional H2 = boost::none) const {
+ double range(const Point3& point, OptionalJacobian<1, 6> H1 = boost::none,
+ OptionalJacobian<1, 3> H2 = boost::none) const {
return pose_.range(point, H1, H2);
}
@@ -187,8 +166,8 @@ public:
* @param H2 optionally computed Jacobian with respect to the 3D point
* @return range (double)
*/
- double range(const Pose3& pose, boost::optional H1 = boost::none,
- boost::optional H2 = boost::none) const {
+ double range(const Pose3& pose, OptionalJacobian<1, 6> H1 = boost::none,
+ OptionalJacobian<1, 6> H2 = boost::none) const {
return pose_.range(pose, H1, H2);
}
@@ -199,8 +178,8 @@ public:
* @param H2 optionally computed Jacobian with respect to the 3D point
* @return range (double)
*/
- double range(const CalibratedCamera& camera, boost::optional H1 =
- boost::none, boost::optional H2 = boost::none) const {
+ double range(const CalibratedCamera& camera, OptionalJacobian<1, 6> H1 =
+ boost::none, OptionalJacobian<1, 6> H2 = boost::none) const {
return pose_.range(camera.pose_, H1, H2);
}
@@ -224,15 +203,16 @@ private:
namespace traits {
template<>
-struct GTSAM_EXPORT is_group : public boost::true_type{
+struct GTSAM_EXPORT is_group : public boost::true_type {
};
template<>
-struct GTSAM_EXPORT is_manifold : public boost::true_type{
+struct GTSAM_EXPORT is_manifold : public boost::true_type {
};
template<>
-struct GTSAM_EXPORT dimension : public boost::integral_constant{
+struct GTSAM_EXPORT dimension : public boost::integral_constant<
+ int, 6> {
};
}
diff --git a/gtsam/geometry/EssentialMatrix.cpp b/gtsam/geometry/EssentialMatrix.cpp
index e65e5d097..062178fea 100644
--- a/gtsam/geometry/EssentialMatrix.cpp
+++ b/gtsam/geometry/EssentialMatrix.cpp
@@ -14,7 +14,7 @@ namespace gtsam {
/* ************************************************************************* */
EssentialMatrix EssentialMatrix::FromPose3(const Pose3& _1P2_,
- boost::optional H) {
+ OptionalJacobian<5, 6> H) {
const Rot3& _1R2_ = _1P2_.rotation();
const Point3& _1T2_ = _1P2_.translation();
if (!H) {
@@ -25,13 +25,10 @@ EssentialMatrix EssentialMatrix::FromPose3(const Pose3& _1P2_,
// Calculate the 5*6 Jacobian H = D_E_1P2
// D_E_1P2 = [D_E_1R2 D_E_1T2], 5*3 wrpt rotation, 5*3 wrpt translation
// First get 2*3 derivative from Unit3::FromPoint3
- Matrix D_direction_1T2;
+ Matrix23 D_direction_1T2;
Unit3 direction = Unit3::FromPoint3(_1T2_, D_direction_1T2);
- H->resize(5, 6);
- H->block<3, 3>(0, 0) << Matrix::Identity(3, 3); // upper left
- H->block<2, 3>(3, 0) << Matrix::Zero(2, 3); // lower left
- H->block<3, 3>(0, 3) << Matrix::Zero(3, 3); // upper right
- H->block<2, 3>(3, 3) << D_direction_1T2 * _1R2_.matrix(); // lower right
+ *H << I_3x3, Z_3x3, //
+ Matrix23::Zero(), D_direction_1T2 * _1R2_.matrix();
return EssentialMatrix(_1R2_, direction);
}
}
@@ -54,23 +51,26 @@ EssentialMatrix EssentialMatrix::retract(const Vector& xi) const {
}
/* ************************************************************************* */
-Vector EssentialMatrix::localCoordinates(const EssentialMatrix& other) const {
- return (Vector(5) <<
- aRb_.localCoordinates(other.aRb_), aTb_.localCoordinates(other.aTb_)).finished();
+Vector5 EssentialMatrix::localCoordinates(const EssentialMatrix& other) const {
+ Vector5 v;
+ v << aRb_.localCoordinates(other.aRb_),
+ aTb_.localCoordinates(other.aTb_);
+ return v;
}
/* ************************************************************************* */
-Point3 EssentialMatrix::transform_to(const Point3& p,
- boost::optional DE, boost::optional Dpoint) const {
+Point3 EssentialMatrix::transform_to(const Point3& p, OptionalJacobian<3, 5> DE,
+ OptionalJacobian<3, 3> Dpoint) const {
Pose3 pose(aRb_, aTb_.point3());
- Point3 q = pose.transform_to(p, DE, Dpoint);
+ Matrix36 DE_;
+ Point3 q = pose.transform_to(p, DE ? &DE_ : 0, Dpoint);
if (DE) {
// DE returned by pose.transform_to is 3*6, but we need it to be 3*5
// The last 3 columns are derivative with respect to change in translation
// The derivative of translation with respect to a 2D sphere delta is 3*2 aTb_.basis()
// Duy made an educated guess that this needs to be rotated to the local frame
- Matrix H(3, 5);
- H << DE->block<3, 3>(0, 0), -aRb_.transpose() * aTb_.basis();
+ Matrix35 H;
+ H << DE_.block < 3, 3 > (0, 0), -aRb_.transpose() * aTb_.basis();
*DE = H;
}
return q;
@@ -78,7 +78,7 @@ Point3 EssentialMatrix::transform_to(const Point3& p,
/* ************************************************************************* */
EssentialMatrix EssentialMatrix::rotate(const Rot3& cRb,
- boost::optional HE, boost::optional HR) const {
+ OptionalJacobian<5, 5> HE, OptionalJacobian<5, 3> HR) const {
// The rotation must be conjugated to act in the camera frame
Rot3 c1Rc2 = aRb_.conjugate(cRb);
@@ -89,18 +89,16 @@ EssentialMatrix EssentialMatrix::rotate(const Rot3& cRb,
return EssentialMatrix(c1Rc2, c1Tc2);
} else {
// Calculate derivatives
- Matrix D_c1Tc2_cRb, D_c1Tc2_aTb; // 2*3 and 2*2
+ Matrix23 D_c1Tc2_cRb; // 2*3
+ Matrix2 D_c1Tc2_aTb; // 2*2
Unit3 c1Tc2 = cRb.rotate(aTb_, D_c1Tc2_cRb, D_c1Tc2_aTb);
- if (HE) {
- *HE = zeros(5, 5);
- HE->block<3, 3>(0, 0) << cRb.matrix(); // a change in aRb_ will yield a rotated change in c1Rc2
- HE->block<2, 2>(3, 3) << D_c1Tc2_aTb; // (2*2)
- }
+ if (HE)
+ *HE << cRb.matrix(), Matrix32::Zero(), //
+ Matrix23::Zero(), D_c1Tc2_aTb;
if (HR) {
throw runtime_error(
"EssentialMatrix::rotate: derivative HR not implemented yet");
/*
- HR->resize(5, 3);
HR->block<3, 3>(0, 0) << zeros(3, 3); // a change in the rotation yields ?
HR->block<2, 3>(3, 0) << zeros(2, 3); // (2*3) * (3*3) ?
*/
@@ -110,13 +108,12 @@ EssentialMatrix EssentialMatrix::rotate(const Rot3& cRb,
}
/* ************************************************************************* */
-double EssentialMatrix::error(const Vector& vA, const Vector& vB, //
- boost::optional H) const {
+double EssentialMatrix::error(const Vector3& vA, const Vector3& vB, //
+ OptionalJacobian<1, 5> H) const {
if (H) {
- H->resize(1, 5);
// See math.lyx
- Matrix HR = vA.transpose() * E_ * skewSymmetric(-vB);
- Matrix HD = vA.transpose() * skewSymmetric(-aRb_.matrix() * vB)
+ Matrix13 HR = vA.transpose() * E_ * skewSymmetric(-vB);
+ Matrix12 HD = vA.transpose() * skewSymmetric(-aRb_.matrix() * vB)
* aTb_.basis();
*H << HR, HD;
}
diff --git a/gtsam/geometry/EssentialMatrix.h b/gtsam/geometry/EssentialMatrix.h
index fd5f45160..546e432b9 100644
--- a/gtsam/geometry/EssentialMatrix.h
+++ b/gtsam/geometry/EssentialMatrix.h
@@ -31,8 +31,8 @@ private:
public:
/// Static function to convert Point2 to homogeneous coordinates
- static Vector Homogeneous(const Point2& p) {
- return (Vector(3) << p.x(), p.y(), 1).finished();
+ static Vector3 Homogeneous(const Point2& p) {
+ return Vector3(p.x(), p.y(), 1);
}
/// @name Constructors and named constructors
@@ -50,7 +50,7 @@ public:
/// Named constructor converting a Pose3 with scale to EssentialMatrix (no scale)
static EssentialMatrix FromPose3(const Pose3& _1P2_,
- boost::optional H = boost::none);
+ OptionalJacobian<5, 6> H = boost::none);
/// Random, using Rot3::Random and Unit3::Random
template
@@ -84,15 +84,15 @@ public:
}
/// Return the dimensionality of the tangent space
- virtual size_t dim() const {
+ size_t dim() const {
return 5;
}
/// Retract delta to manifold
- virtual EssentialMatrix retract(const Vector& xi) const;
+ EssentialMatrix retract(const Vector& xi) const;
/// Compute the coordinates in the tangent space
- virtual Vector localCoordinates(const EssentialMatrix& other) const;
+ Vector5 localCoordinates(const EssentialMatrix& other) const;
/// @}
@@ -132,16 +132,16 @@ public:
* @return point in pose coordinates
*/
Point3 transform_to(const Point3& p,
- boost::optional DE = boost::none,
- boost::optional Dpoint = boost::none) const;
+ OptionalJacobian<3,5> DE = boost::none,
+ OptionalJacobian<3,3> Dpoint = boost::none) const;
/**
* Given essential matrix E in camera frame B, convert to body frame C
* @param cRb rotation from body frame to camera frame
* @param E essential matrix E in camera frame C
*/
- EssentialMatrix rotate(const Rot3& cRb, boost::optional HE =
- boost::none, boost::optional HR = boost::none) const;
+ EssentialMatrix rotate(const Rot3& cRb, OptionalJacobian<5, 5> HE =
+ boost::none, OptionalJacobian<5, 3> HR = boost::none) const;
/**
* Given essential matrix E in camera frame B, convert to body frame C
@@ -153,8 +153,8 @@ public:
}
/// epipolar error, algebraic
- double error(const Vector& vA, const Vector& vB, //
- boost::optional H = boost::none) const;
+ double error(const Vector3& vA, const Vector3& vB, //
+ OptionalJacobian<1,5> H = boost::none) const;
/// @}
diff --git a/gtsam/geometry/PinholeCamera.h b/gtsam/geometry/PinholeCamera.h
index c5174ae65..9b881dc78 100644
--- a/gtsam/geometry/PinholeCamera.h
+++ b/gtsam/geometry/PinholeCamera.h
@@ -18,16 +18,9 @@
#pragma once
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
#include
+#include
+#include
namespace gtsam {
@@ -42,7 +35,9 @@ private:
Pose3 pose_;
Calibration K_;
- static const int DimK = traits::dimension::value;
+ // Get dimensions of calibration type and This at compile time
+ static const int DimK = traits::dimension::value, //
+ DimC = 6 + DimK;
public:
@@ -114,9 +109,9 @@ public:
/// @{
explicit PinholeCamera(const Vector &v) {
- pose_ = Pose3::Expmap(v.head(Pose3::Dim()));
- if (v.size() > Pose3::Dim()) {
- K_ = Calibration(v.tail(Calibration::Dim()));
+ pose_ = Pose3::Expmap(v.head(6));
+ if (v.size() > 6) {
+ K_ = Calibration(v.tail(DimK));
}
}
@@ -167,82 +162,30 @@ public:
return K_;
}
- /// @}
- /// @name Group ?? Frank says this might not make sense
- /// @{
-
- /// compose two cameras: TODO Frank says this might not make sense
- inline const PinholeCamera compose(const PinholeCamera &c,
- boost::optional H1 = boost::none, boost::optional H2 =
- boost::none) const {
- PinholeCamera result(pose_.compose(c.pose(), H1, H2), K_);
- if (H1) {
- H1->conservativeResize(Dim(), Dim());
- H1->topRightCorner(Pose3::Dim(), Calibration::Dim()) = zeros(Pose3::Dim(),
- Calibration::Dim());
- H1->bottomRows(Calibration::Dim()) = zeros(Calibration::Dim(), Dim());
- }
- if (H2) {
- H2->conservativeResize(Dim(), Dim());
- H2->topRightCorner(Pose3::Dim(), Calibration::Dim()) = zeros(Pose3::Dim(),
- Calibration::Dim());
- H2->bottomRows(Calibration::Dim()) = zeros(Calibration::Dim(), Dim());
- }
- return result;
- }
-
- /// between two cameras: TODO Frank says this might not make sense
- inline const PinholeCamera between(const PinholeCamera& c,
- boost::optional H1 = boost::none, boost::optional H2 =
- boost::none) const {
- PinholeCamera result(pose_.between(c.pose(), H1, H2), K_);
- if (H1) {
- H1->conservativeResize(Dim(), Dim());
- H1->topRightCorner(Pose3::Dim(), Calibration::Dim()) = zeros(Pose3::Dim(),
- Calibration::Dim());
- H1->bottomRows(Calibration::Dim()) = zeros(Calibration::Dim(), Dim());
- }
- if (H2) {
- H2->conservativeResize(Dim(), Dim());
- H2->topRightCorner(Pose3::Dim(), Calibration::Dim()) = zeros(Pose3::Dim(),
- Calibration::Dim());
- H2->bottomRows(Calibration::Dim()) = zeros(Calibration::Dim(), Dim());
- }
- return result;
- }
-
- /// inverse camera: TODO Frank says this might not make sense
- inline const PinholeCamera inverse(
- boost::optional H1 = boost::none) const {
- PinholeCamera result(pose_.inverse(H1), K_);
- if (H1) {
- H1->conservativeResize(Dim(), Dim());
- H1->topRightCorner(Pose3::Dim(), Calibration::Dim()) = zeros(Pose3::Dim(),
- Calibration::Dim());
- H1->bottomRows(Calibration::Dim()) = zeros(Calibration::Dim(), Dim());
- }
- return result;
- }
-
- /// compose two cameras: TODO Frank says this might not make sense
- inline const PinholeCamera compose(const Pose3 &c) const {
- return PinholeCamera(pose_.compose(c), K_);
- }
-
/// @}
/// @name Manifold
/// @{
- /// move a cameras according to d
- PinholeCamera retract(const Vector& d) const {
- if ((size_t) d.size() == pose_.dim())
- return PinholeCamera(pose().retract(d), calibration());
- else
- return PinholeCamera(pose().retract(d.head(pose().dim())),
- calibration().retract(d.tail(calibration().dim())));
+ /// Manifold dimension
+ inline size_t dim() const {
+ return DimC;
}
- typedef Eigen::Matrix VectorK6;
+ /// Manifold dimension
+ inline static size_t Dim() {
+ return DimC;
+ }
+
+ typedef Eigen::Matrix VectorK6;
+
+ /// move a cameras according to d
+ PinholeCamera retract(const Vector& d) const {
+ if ((size_t) d.size() == 6)
+ return PinholeCamera(pose().retract(d), calibration());
+ else
+ return PinholeCamera(pose().retract(d.head(6)),
+ calibration().retract(d.tail(calibration().dim())));
+ }
/// return canonical coordinate
VectorK6 localCoordinates(const PinholeCamera& T2) const {
@@ -252,16 +195,6 @@ public:
return d;
}
- /// Manifold dimension
- inline size_t dim() const {
- return pose_.dim() + K_.dim();
- }
-
- /// Manifold dimension
- inline static size_t Dim() {
- return Pose3::Dim() + Calibration::Dim();
- }
-
/// @}
/// @name Transformations and measurement functions
/// @{
@@ -272,8 +205,8 @@ public:
* @param P A point in camera coordinates
* @param Dpoint is the 2*3 Jacobian w.r.t. P
*/
- inline static Point2 project_to_camera(const Point3& P,
- boost::optional Dpoint = boost::none) {
+ static Point2 project_to_camera(const Point3& P, //
+ OptionalJacobian<2, 3> Dpoint = boost::none) {
#ifdef GTSAM_THROW_CHEIRALITY_EXCEPTION
if (P.z() <= 0)
throw CheiralityException();
@@ -292,21 +225,7 @@ public:
return std::make_pair(K_.uncalibrate(pn), pc.z() > 0);
}
- /** project a point from world coordinate to the image
- * @param pw is a point in world coordinates
- */
- inline Point2 project(const Point3& pw) const {
-
- // Transform to camera coordinates and check cheirality
- const Point3 pc = pose_.transform_to(pw);
-
- // Project to normalized image coordinates
- const Point2 pn = project_to_camera(pc);
-
- return K_.uncalibrate(pn);
- }
-
- typedef Eigen::Matrix Matrix2K;
+ typedef Eigen::Matrix Matrix2K;
/** project a point from world coordinate to the image
* @param pw is a point in world coordinates
@@ -314,11 +233,9 @@ public:
* @param Dpoint is the Jacobian w.r.t. point3
* @param Dcal is the Jacobian w.r.t. calibration
*/
- inline Point2 project(
- const Point3& pw, //
- boost::optional Dpose,
- boost::optional Dpoint,
- boost::optional Dcal) const {
+ inline Point2 project(const Point3& pw, OptionalJacobian<2, 6> Dpose =
+ boost::none, OptionalJacobian<2, 3> Dpoint = boost::none,
+ OptionalJacobian<2, DimK> Dcal = boost::none) const {
// Transform to camera coordinates and check cheirality
const Point3 pc = pose_.transform_to(pw);
@@ -340,46 +257,7 @@ public:
calculateDpoint(pn, d, pose_.rotation().matrix(), Dpi_pn, *Dpoint);
return pi;
} else
- return K_.uncalibrate(pn, Dcal, boost::none);
- }
-
- /** project a point from world coordinate to the image
- * @param pw is a point in world coordinates
- * @param Dpose is the Jacobian w.r.t. pose3
- * @param Dpoint is the Jacobian w.r.t. point3
- * @param Dcal is the Jacobian w.r.t. calibration
- */
- inline Point2 project(
- const Point3& pw, //
- boost::optional Dpose,
- boost::optional Dpoint,
- boost::optional Dcal) const {
-
- // Transform to camera coordinates and check cheirality
- const Point3 pc = pose_.transform_to(pw);
-
- // Project to normalized image coordinates
- const Point2 pn = project_to_camera(pc);
-
- if (Dpose || Dpoint) {
- const double z = pc.z(), d = 1.0 / z;
-
- // uncalibration
- Matrix Dpi_pn(2, 2);
- const Point2 pi = K_.uncalibrate(pn, Dcal, Dpi_pn);
-
- // chain the Jacobian matrices
- if (Dpose) {
- Dpose->resize(2, 6);
- calculateDpose(pn, d, Dpi_pn, *Dpose);
- }
- if (Dpoint) {
- Dpoint->resize(2, 3);
- calculateDpoint(pn, d, pose_.rotation().matrix(), Dpi_pn, *Dpoint);
- }
- return pi;
- } else
- return K_.uncalibrate(pn, Dcal, boost::none);
+ return K_.uncalibrate(pn, Dcal);
}
/** project a point at infinity from world coordinate to the image
@@ -388,11 +266,10 @@ public:
* @param Dpoint is the Jacobian w.r.t. point3
* @param Dcal is the Jacobian w.r.t. calibration
*/
- inline Point2 projectPointAtInfinity(
- const Point3& pw, //
- boost::optional Dpose = boost::none,
- boost::optional Dpoint = boost::none,
- boost::optional Dcal = boost::none) const {
+ inline Point2 projectPointAtInfinity(const Point3& pw,
+ OptionalJacobian<2, 6> Dpose = boost::none,
+ OptionalJacobian<2, 2> Dpoint = boost::none,
+ OptionalJacobian<2, DimK> Dcal = boost::none) const {
if (!Dpose && !Dpoint && !Dcal) {
const Point3 pc = pose_.rotation().unrotate(pw); // get direction in camera frame (translation does not matter)
@@ -401,40 +278,30 @@ public:
}
// world to camera coordinate
- Matrix Dpc_rot /* 3*3 */, Dpc_point /* 3*3 */;
+ Matrix3 Dpc_rot, Dpc_point;
const Point3 pc = pose_.rotation().unrotate(pw, Dpc_rot, Dpc_point);
- Matrix Dpc_pose = Matrix::Zero(3, 6);
- Dpc_pose.block(0, 0, 3, 3) = Dpc_rot;
+ Matrix36 Dpc_pose;
+ Dpc_pose.setZero();
+ Dpc_pose.leftCols<3>() = Dpc_rot;
// camera to normalized image coordinate
Matrix23 Dpn_pc; // 2*3
const Point2 pn = project_to_camera(pc, Dpn_pc);
// uncalibration
- Matrix Dpi_pn; // 2*2
+ Matrix2 Dpi_pn; // 2*2
const Point2 pi = K_.uncalibrate(pn, Dcal, Dpi_pn);
// chain the Jacobian matrices
- const Matrix Dpi_pc = Dpi_pn * Dpn_pc;
+ const Matrix23 Dpi_pc = Dpi_pn * Dpn_pc;
if (Dpose)
*Dpose = Dpi_pc * Dpc_pose;
if (Dpoint)
- *Dpoint = (Dpi_pc * Dpc_point).block(0, 0, 2, 2); // only 2dof are important for the point (direction-only)
+ *Dpoint = (Dpi_pc * Dpc_point).leftCols<2>(); // only 2dof are important for the point (direction-only)
return pi;
}
- typedef Eigen::Matrix Matrix2K6;
-
- /** project a point from world coordinate to the image
- * @param pw is a point in the world coordinate
- */
- Point2 project2(const Point3& pw) const {
- const Point3 pc = pose_.transform_to(pw);
- const Point2 pn = project_to_camera(pc);
- return K_.uncalibrate(pn);
- }
-
/** project a point from world coordinate to the image, fixed Jacobians
* @param pw is a point in the world coordinate
* @param Dcamera is the Jacobian w.r.t. [pose3 calibration]
@@ -442,8 +309,8 @@ public:
*/
Point2 project2(
const Point3& pw, //
- boost::optional Dcamera,
- boost::optional Dpoint) const {
+ OptionalJacobian<2, DimC> Dcamera = boost::none,
+ OptionalJacobian<2, 3> Dpoint = boost::none) const {
const Point3 pc = pose_.transform_to(pw);
const Point2 pn = project_to_camera(pc);
@@ -459,8 +326,8 @@ public:
const Point2 pi = K_.uncalibrate(pn, Dcal, Dpi_pn);
if (Dcamera) { // TODO why does leftCols<6>() not compile ??
- calculateDpose(pn, d, Dpi_pn, Dcamera->leftCols(6));
- Dcamera->rightCols(K_.dim()) = Dcal; // Jacobian wrt calib
+ calculateDpose(pn, d, Dpi_pn, (*Dcamera).leftCols(6));
+ (*Dcamera).rightCols(DimK) = Dcal; // Jacobian wrt calib
}
if (Dpoint) {
calculateDpoint(pn, d, pose_.rotation().matrix(), Dpi_pn, *Dpoint);
@@ -469,40 +336,6 @@ public:
}
}
- /** project a point from world coordinate to the image
- * @param pw is a point in the world coordinate
- * @param Dcamera is the Jacobian w.r.t. [pose3 calibration]
- * @param Dpoint is the Jacobian w.r.t. point3
- */
- Point2 project2(const Point3& pw, //
- boost::optional Dcamera, boost::optional Dpoint) const {
-
- const Point3 pc = pose_.transform_to(pw);
- const Point2 pn = project_to_camera(pc);
-
- if (!Dcamera && !Dpoint) {
- return K_.uncalibrate(pn);
- } else {
- const double z = pc.z(), d = 1.0 / z;
-
- // uncalibration
- Matrix2K Dcal;
- Matrix2 Dpi_pn;
- const Point2 pi = K_.uncalibrate(pn, Dcal, Dpi_pn);
-
- if (Dcamera) {
- Dcamera->resize(2, this->dim());
- calculateDpose(pn, d, Dpi_pn, Dcamera->leftCols<6>());
- Dcamera->rightCols(K_.dim()) = Dcal; // Jacobian wrt calib
- }
- if (Dpoint) {
- Dpoint->resize(2, 3);
- calculateDpoint(pn, d, pose_.rotation().matrix(), Dpi_pn, *Dpoint);
- }
- return pi;
- }
- }
-
/// backproject a 2-dimensional point to a 3-dimensional point at given depth
inline Point3 backproject(const Point2& p, double depth) const {
const Point2 pn = K_.calibrate(p);
@@ -520,71 +353,64 @@ public:
/**
* Calculate range to a landmark
* @param point 3D location of landmark
- * @param Dpose the optionally computed Jacobian with respect to pose
+ * @param Dcamera the optionally computed Jacobian with respect to pose
* @param Dpoint the optionally computed Jacobian with respect to the landmark
* @return range (double)
*/
double range(
const Point3& point, //
- boost::optional Dpose = boost::none,
- boost::optional Dpoint = boost::none) const {
- double result = pose_.range(point, Dpose, Dpoint);
- if (Dpose) {
- // Add columns of zeros to Jacobian for calibration
- Matrix& H1r(*Dpose);
- H1r.conservativeResize(Eigen::NoChange, pose_.dim() + K_.dim());
- H1r.block(0, pose_.dim(), 1, K_.dim()) = Matrix::Zero(1, K_.dim());
- }
+ OptionalJacobian<1, DimC> Dcamera = boost::none,
+ OptionalJacobian<1, 3> Dpoint = boost::none) const {
+ Matrix16 Dpose_;
+ double result = pose_.range(point, Dcamera ? &Dpose_ : 0, Dpoint);
+ if (Dcamera)
+ *Dcamera << Dpose_, Eigen::Matrix::Zero();
return result;
}
/**
* Calculate range to another pose
* @param pose Other SO(3) pose
- * @param Dpose the optionally computed Jacobian with respect to pose
+ * @param Dcamera the optionally computed Jacobian with respect to pose
* @param Dpose2 the optionally computed Jacobian with respect to the other pose
* @return range (double)
*/
double range(
const Pose3& pose, //
- boost::optional Dpose = boost::none,
- boost::optional Dpose2 = boost::none) const {
- double result = pose_.range(pose, Dpose, Dpose2);
- if (Dpose) {
- // Add columns of zeros to Jacobian for calibration
- Matrix& H1r(*Dpose);
- H1r.conservativeResize(Eigen::NoChange, pose_.dim() + K_.dim());
- H1r.block(0, pose_.dim(), 1, K_.dim()) = Matrix::Zero(1, K_.dim());
- }
+ OptionalJacobian<1, DimC> Dcamera = boost::none,
+ OptionalJacobian<1, 6> Dpose = boost::none) const {
+ Matrix16 Dpose_;
+ double result = pose_.range(pose, Dcamera ? &Dpose_ : 0, Dpose);
+ if (Dcamera)
+ *Dcamera << Dpose_, Eigen::Matrix::Zero();
return result;
}
/**
* Calculate range to another camera
* @param camera Other camera
- * @param Dpose the optionally computed Jacobian with respect to pose
+ * @param Dcamera the optionally computed Jacobian with respect to pose
* @param Dother the optionally computed Jacobian with respect to the other camera
* @return range (double)
*/
template
double range(
const PinholeCamera& camera, //
- boost::optional Dpose = boost::none,
- boost::optional Dother = boost::none) const {
- double result = pose_.range(camera.pose_, Dpose, Dother);
- if (Dpose) {
- // Add columns of zeros to Jacobian for calibration
- Matrix& H1r(*Dpose);
- H1r.conservativeResize(Eigen::NoChange, pose_.dim() + K_.dim());
- H1r.block(0, pose_.dim(), 1, K_.dim()) = Matrix::Zero(1, K_.dim());
+ OptionalJacobian<1, DimC> Dcamera = boost::none,
+// OptionalJacobian<1, 6 + traits::dimension::value> Dother =
+ boost::optional Dother =
+ boost::none) const {
+ Matrix16 Dcamera_, Dother_;
+ double result = pose_.range(camera.pose(), Dcamera ? &Dcamera_ : 0,
+ Dother ? &Dother_ : 0);
+ if (Dcamera) {
+ Dcamera->resize(1, 6 + DimK);
+ *Dcamera << Dcamera_, Eigen::Matrix::Zero();
}
if (Dother) {
- // Add columns of zeros to Jacobian for calibration
- Matrix& H2r(*Dother);
- H2r.conservativeResize(Eigen::NoChange,
- camera.pose().dim() + camera.calibration().dim());
- H2r.block(0, camera.pose().dim(), 1, camera.calibration().dim()) =
- Matrix::Zero(1, camera.calibration().dim());
+ Dother->resize(1, 6+traits::dimension::value);
+ Dother->setZero();
+ Dother->block(0, 0, 1, 6) = Dother_;
}
return result;
}
@@ -592,15 +418,15 @@ public:
/**
* Calculate range to another camera
* @param camera Other camera
- * @param Dpose the optionally computed Jacobian with respect to pose
+ * @param Dcamera the optionally computed Jacobian with respect to pose
* @param Dother the optionally computed Jacobian with respect to the other camera
* @return range (double)
*/
double range(
const CalibratedCamera& camera, //
- boost::optional Dpose = boost::none,
- boost::optional Dother = boost::none) const {
- return pose_.range(camera.pose_, Dpose, Dother);
+ OptionalJacobian<1, DimC> Dcamera = boost::none,
+ OptionalJacobian<1, 6> Dother = boost::none) const {
+ return range(camera.pose(), Dcamera, Dother);
}
private:
@@ -663,7 +489,7 @@ private:
namespace traits {
template
-struct GTSAM_EXPORT is_manifold > : public boost::true_type{
+struct GTSAM_EXPORT is_manifold > : public boost::true_type {
};
template
diff --git a/gtsam/geometry/Point2.cpp b/gtsam/geometry/Point2.cpp
index 8b90aed63..17e3ef370 100644
--- a/gtsam/geometry/Point2.cpp
+++ b/gtsam/geometry/Point2.cpp
@@ -38,15 +38,9 @@ bool Point2::equals(const Point2& q, double tol) const {
}
/* ************************************************************************* */
-double Point2::norm() const {
- return sqrt(x_ * x_ + y_ * y_);
-}
-
-/* ************************************************************************* */
-double Point2::norm(boost::optional H) const {
- double r = norm();
+double Point2::norm(OptionalJacobian<1,2> H) const {
+ double r = sqrt(x_ * x_ + y_ * y_);
if (H) {
- H->resize(1,2);
if (fabs(r) > 1e-10)
*H << x_ / r, y_ / r;
else
@@ -56,12 +50,11 @@ double Point2::norm(boost::optional H) const {
}
/* ************************************************************************* */
-static const Matrix I2 = eye(2);
-double Point2::distance(const Point2& point, boost::optional H1,
- boost::optional H2) const {
+double Point2::distance(const Point2& point, OptionalJacobian<1,2> H1,
+ OptionalJacobian<1,2> H2) const {
Point2 d = point - *this;
if (H1 || H2) {
- Matrix H;
+ Matrix12 H;
double r = d.norm(H);
if (H1) *H1 = -H;
if (H2) *H2 = H;
diff --git a/gtsam/geometry/Point2.h b/gtsam/geometry/Point2.h
index a4e0cc296..5dabc4bd6 100644
--- a/gtsam/geometry/Point2.h
+++ b/gtsam/geometry/Point2.h
@@ -20,7 +20,7 @@
#include
#include
-#include
+#include
#include
namespace gtsam {
@@ -125,10 +125,10 @@ public:
/// "Compose", just adds the coordinates of two points. With optional derivatives
inline Point2 compose(const Point2& q,
- boost::optional H1=boost::none,
- boost::optional H2=boost::none) const {
- if(H1) *H1 = eye(2);
- if(H2) *H2 = eye(2);
+ OptionalJacobian<2,2> H1=boost::none,
+ OptionalJacobian<2,2> H2=boost::none) const {
+ if(H1) *H1 = I_2x2;
+ if(H2) *H2 = I_2x2;
return *this + q;
}
@@ -137,10 +137,10 @@ public:
/// "Between", subtracts point coordinates. between(p,q) == compose(inverse(p),q)
inline Point2 between(const Point2& q,
- boost::optional