diff --git a/.cproject b/.cproject
index 42f61fa16..72285e057 100644
--- a/.cproject
+++ b/.cproject
@@ -681,6 +681,22 @@
true
true
+
+ make
+ -j2
+ tests/testPose2.run
+ true
+ true
+ true
+
+
+ make
+ -j2
+ tests/testPose3.run
+ true
+ true
+ true
+
make
-j2
@@ -1385,6 +1401,14 @@
true
true
+
+ make
+ -j2
+ check
+ true
+ true
+ true
+
make
-j2
diff --git a/examples/CameraResectioning.cpp b/examples/CameraResectioning.cpp
index 07dc69dc7..d26b8b3af 100644
--- a/examples/CameraResectioning.cpp
+++ b/examples/CameraResectioning.cpp
@@ -20,7 +20,7 @@
#include
#include
#include
-#include
+#include
#include
#include
#include
@@ -28,7 +28,7 @@
using namespace gtsam;
typedef TypedSymbol PoseKey;
-typedef LieValues PoseValues;
+typedef Values PoseValues;
/**
* Unary factor for the pose.
diff --git a/examples/PlanarSLAMExample_easy.cpp b/examples/PlanarSLAMExample_easy.cpp
index f840c443d..d697ae261 100644
--- a/examples/PlanarSLAMExample_easy.cpp
+++ b/examples/PlanarSLAMExample_easy.cpp
@@ -76,7 +76,7 @@ int main(int argc, char** argv) {
graph.print("full graph");
// initialize to noisy points
- Values initialEstimate;
+ planarSLAM::Values initialEstimate;
initialEstimate.insert(x1, Pose2(0.5, 0.0, 0.2));
initialEstimate.insert(x2, Pose2(2.3, 0.1,-0.2));
initialEstimate.insert(x3, Pose2(4.1, 0.1, 0.1));
@@ -86,7 +86,7 @@ int main(int argc, char** argv) {
initialEstimate.print("initial estimate");
// optimize using Levenberg-Marquardt optimization with an ordering from colamd
- Values result = optimize(graph, initialEstimate);
+ planarSLAM::Values result = optimize(graph, initialEstimate);
result.print("final result");
return 0;
diff --git a/examples/PlanarSLAMSelfContained_advanced.cpp b/examples/PlanarSLAMSelfContained_advanced.cpp
index df58e557c..549acabae 100644
--- a/examples/PlanarSLAMSelfContained_advanced.cpp
+++ b/examples/PlanarSLAMSelfContained_advanced.cpp
@@ -43,12 +43,12 @@
// Main typedefs
typedef gtsam::TypedSymbol PoseKey; // Key for poses, with type included
typedef gtsam::TypedSymbol PointKey; // Key for points, with type included
-typedef gtsam::LieValues PoseValues; // config type for poses
-typedef gtsam::LieValues PointValues; // config type for points
-typedef gtsam::TupleValues2 Values; // main config with two variable classes
-typedef gtsam::NonlinearFactorGraph Graph; // graph structure
-typedef gtsam::NonlinearOptimizer OptimizerSeqential; // optimization engine for this domain
-typedef gtsam::NonlinearOptimizer OptimizerMultifrontal; // optimization engine for this domain
+typedef gtsam::Values PoseValues; // config type for poses
+typedef gtsam::Values PointValues; // config type for points
+typedef gtsam::TupleValues2 PlanarValues; // main config with two variable classes
+typedef gtsam::NonlinearFactorGraph Graph; // graph structure
+typedef gtsam::NonlinearOptimizer OptimizerSeqential; // optimization engine for this domain
+typedef gtsam::NonlinearOptimizer OptimizerMultifrontal; // optimization engine for this domain
using namespace std;
using namespace gtsam;
@@ -74,7 +74,7 @@ int main(int argc, char** argv) {
// gaussian for prior
SharedDiagonal prior_model = noiseModel::Diagonal::Sigmas(Vector_(3, 0.3, 0.3, 0.1));
Pose2 prior_measurement(0.0, 0.0, 0.0); // prior at origin
- PriorFactor posePrior(x1, prior_measurement, prior_model); // create the factor
+ PriorFactor posePrior(x1, prior_measurement, prior_model); // create the factor
graph->add(posePrior); // add the factor to the graph
/* add odometry */
@@ -82,8 +82,8 @@ int main(int argc, char** argv) {
SharedDiagonal odom_model = noiseModel::Diagonal::Sigmas(Vector_(3, 0.2, 0.2, 0.1));
Pose2 odom_measurement(2.0, 0.0, 0.0); // create a measurement for both factors (the same in this case)
// create between factors to represent odometry
- BetweenFactor odom12(x1, x2, odom_measurement, odom_model);
- BetweenFactor odom23(x2, x3, odom_measurement, odom_model);
+ BetweenFactor odom12(x1, x2, odom_measurement, odom_model);
+ BetweenFactor odom23(x2, x3, odom_measurement, odom_model);
graph->add(odom12); // add both to graph
graph->add(odom23);
@@ -100,9 +100,9 @@ int main(int argc, char** argv) {
range32 = 2.0;
// create bearing/range factors
- BearingRangeFactor meas11(x1, l1, bearing11, range11, meas_model);
- BearingRangeFactor meas21(x2, l1, bearing21, range21, meas_model);
- BearingRangeFactor meas32(x3, l2, bearing32, range32, meas_model);
+ BearingRangeFactor meas11(x1, l1, bearing11, range11, meas_model);
+ BearingRangeFactor meas21(x2, l1, bearing21, range21, meas_model);
+ BearingRangeFactor meas32(x3, l2, bearing32, range32, meas_model);
// add the factors
graph->add(meas11);
@@ -112,7 +112,7 @@ int main(int argc, char** argv) {
graph->print("Full Graph");
// initialize to noisy points
- boost::shared_ptr initial(new Values);
+ boost::shared_ptr initial(new PlanarValues);
initial->insert(x1, Pose2(0.5, 0.0, 0.2));
initial->insert(x2, Pose2(2.3, 0.1,-0.2));
initial->insert(x3, Pose2(4.1, 0.1, 0.1));
diff --git a/examples/Pose2SLAMExample_advanced.cpp b/examples/Pose2SLAMExample_advanced.cpp
index 2b54b3403..13e419def 100644
--- a/examples/Pose2SLAMExample_advanced.cpp
+++ b/examples/Pose2SLAMExample_advanced.cpp
@@ -57,7 +57,7 @@ int main(int argc, char** argv) {
/* 3. Create the data structure to hold the initial estimate to the solution
* initialize to noisy points */
- shared_ptr initial(new Values);
+ shared_ptr initial(new pose2SLAM::Values);
initial->insert(x1, Pose2(0.5, 0.0, 0.2));
initial->insert(x2, Pose2(2.3, 0.1,-0.2));
initial->insert(x3, Pose2(4.1, 0.1, 0.1));
@@ -72,7 +72,7 @@ int main(int argc, char** argv) {
Optimizer optimizer(graph, initial, ordering, params);
Optimizer optimizer_result = optimizer.levenbergMarquardt();
- Values result = *optimizer_result.values();
+ pose2SLAM::Values result = *optimizer_result.values();
result.print("final result");
/* Get covariances */
diff --git a/examples/Pose2SLAMExample_easy.cpp b/examples/Pose2SLAMExample_easy.cpp
index cf6a5613c..1e48157f0 100644
--- a/examples/Pose2SLAMExample_easy.cpp
+++ b/examples/Pose2SLAMExample_easy.cpp
@@ -55,7 +55,7 @@ int main(int argc, char** argv) {
/* 3. Create the data structure to hold the initial estinmate to the solution
* initialize to noisy points */
- Values initial;
+ pose2SLAM::Values initial;
initial.insert(x1, Pose2(0.5, 0.0, 0.2));
initial.insert(x2, Pose2(2.3, 0.1,-0.2));
initial.insert(x3, Pose2(4.1, 0.1, 0.1));
@@ -63,7 +63,7 @@ int main(int argc, char** argv) {
/* 4 Single Step Optimization
* optimize using Levenberg-Marquardt optimization with an ordering from colamd */
- Values result = optimize(graph, initial);
+ pose2SLAM::Values result = optimize(graph, initial);
result.print("final result");
diff --git a/examples/Pose2SLAMwSPCG_advanced.cpp b/examples/Pose2SLAMwSPCG_advanced.cpp
index c63b249dc..4b91d625c 100644
--- a/examples/Pose2SLAMwSPCG_advanced.cpp
+++ b/examples/Pose2SLAMwSPCG_advanced.cpp
@@ -27,17 +27,17 @@ using namespace gtsam;
using namespace pose2SLAM;
typedef boost::shared_ptr sharedGraph ;
-typedef boost::shared_ptr sharedValue ;
+typedef boost::shared_ptr sharedValue ;
//typedef NonlinearOptimizer > SPCGOptimizer;
-typedef SubgraphSolver Solver;
+typedef SubgraphSolver Solver;
typedef boost::shared_ptr sharedSolver ;
-typedef NonlinearOptimizer SPCGOptimizer;
+typedef NonlinearOptimizer SPCGOptimizer;
sharedGraph graph;
sharedValue initial;
-Values result;
+pose2SLAM::Values result;
/* ************************************************************************* */
int main(void) {
@@ -47,7 +47,7 @@ int main(void) {
Key x1(1), x2(2), x3(3), x4(4), x5(5), x6(6), x7(7), x8(8), x9(9);
graph = boost::make_shared() ;
- initial = boost::make_shared() ;
+ initial = boost::make_shared() ;
// create a 3 by 3 grid
// x3 x6 x9
diff --git a/examples/Pose2SLAMwSPCG_easy.cpp b/examples/Pose2SLAMwSPCG_easy.cpp
index a1c1cb57e..d1a33678c 100644
--- a/examples/Pose2SLAMwSPCG_easy.cpp
+++ b/examples/Pose2SLAMwSPCG_easy.cpp
@@ -27,8 +27,7 @@ using namespace gtsam;
using namespace pose2SLAM;
Graph graph;
-Values initial;
-Values result;
+pose2SLAM::Values initial, result;
/* ************************************************************************* */
int main(void) {
diff --git a/examples/SimpleRotation.cpp b/examples/SimpleRotation.cpp
index 0429a701d..c31e91b5f 100644
--- a/examples/SimpleRotation.cpp
+++ b/examples/SimpleRotation.cpp
@@ -23,12 +23,12 @@
#include
#include
#include
-#include
+#include
#include
#include
/*
- * TODO: make factors independent of Values
+ * TODO: make factors independent of RotValues
* TODO: make toplevel documentation
* TODO: Clean up nonlinear optimization API
*/
@@ -44,17 +44,17 @@ using namespace gtsam;
*
* To create a domain:
* - variable types need to have a key defined to act as a label in graphs
- * - a "Values" structure needs to be defined to store the system state
- * - a graph container acting on a given Values
+ * - a "RotValues" structure needs to be defined to store the system state
+ * - a graph container acting on a given RotValues
*
* In a typical scenario, these typedefs could be placed in a header
- * file and reused between projects. Also, LieValues can be combined to
+ * file and reused between projects. Also, RotValues can be combined to
* form a "TupleValues" to enable multiple variable types, such as 2D points
* and 2D poses.
*/
typedef TypedSymbol Key; /// Variable labels for a specific type
-typedef LieValues Values; /// Class to store values - acts as a state for the system
-typedef NonlinearFactorGraph Graph; /// Graph container for constraints - needs to know type of variables
+typedef Values RotValues; /// Class to store values - acts as a state for the system
+typedef NonlinearFactorGraph Graph; /// Graph container for constraints - needs to know type of variables
const double degree = M_PI / 180;
@@ -71,7 +71,7 @@ int main() {
* with a model of the noise on the measurement.
*
* The "Key" created here is a label used to associate parts of the
- * state (stored in "Values") with particular factors. They require
+ * state (stored in "RotValues") with particular factors. They require
* an index to allow for lookup, and should be unique.
*
* In general, creating a factor requires:
@@ -83,7 +83,7 @@ int main() {
prior.print("goal angle");
SharedDiagonal model = noiseModel::Isotropic::Sigma(1, 1 * degree);
Key key(1);
- PriorFactor factor(key, prior, model);
+ PriorFactor factor(key, prior, model);
/**
* Step 3: create a graph container and add the factor to it
@@ -101,7 +101,7 @@ int main() {
/**
* Step 4: create an initial estimate
* An initial estimate of the solution for the system is necessary to
- * start optimization. This system state is the "Values" structure,
+ * start optimization. This system state is the "RotValues" structure,
* which is similar in structure to a STL map, in that it maps
* keys (the label created in step 1) to specific values.
*
@@ -110,11 +110,11 @@ int main() {
* all of the variables in the graph have a corresponding value in
* this structure.
*
- * The interface to all Values types is the same, it only depends
+ * The interface to all RotValues types is the same, it only depends
* on the type of key used to find the appropriate value map if there
* are multiple types of variables.
*/
- Values initial;
+ RotValues initial;
initial.insert(key, Rot2::fromAngle(20 * degree));
initial.print("initial estimate");
@@ -123,10 +123,10 @@ int main() {
* After formulating the problem with a graph of constraints
* and an initial estimate, executing optimization is as simple
* as calling a general optimization function with the graph and
- * initial estimate. This will yield a new Values structure
+ * initial estimate. This will yield a new RotValues structure
* with the final state of the optimization.
*/
- Values result = optimize(graph, initial);
+ RotValues result = optimize(graph, initial);
result.print("final result");
return 0;
diff --git a/examples/easyPoint2KalmanFilter.cpp b/examples/easyPoint2KalmanFilter.cpp
index 5081f6356..3b8ee2980 100644
--- a/examples/easyPoint2KalmanFilter.cpp
+++ b/examples/easyPoint2KalmanFilter.cpp
@@ -24,7 +24,7 @@
#include
#include
#include
-#include
+#include
#include
using namespace std;
@@ -32,7 +32,7 @@ using namespace gtsam;
// Define Types for Linear System Test
typedef TypedSymbol LinearKey;
-typedef LieValues LinearValues;
+typedef Values LinearValues;
typedef Point2 LinearMeasurement;
int main() {
diff --git a/examples/elaboratePoint2KalmanFilter.cpp b/examples/elaboratePoint2KalmanFilter.cpp
index 23870a888..73efc653c 100644
--- a/examples/elaboratePoint2KalmanFilter.cpp
+++ b/examples/elaboratePoint2KalmanFilter.cpp
@@ -22,7 +22,7 @@
#include
#include
-#include
+#include
#include
#include
#include
@@ -35,7 +35,7 @@ using namespace std;
using namespace gtsam;
typedef TypedSymbol Key; /// Variable labels for a specific type
-typedef LieValues Values; /// Class to store values - acts as a state for the system
+typedef Values KalmanValues; /// Class to store values - acts as a state for the system
int main() {
@@ -48,7 +48,7 @@ int main() {
Ordering::shared_ptr ordering(new Ordering);
// Create a structure to hold the linearization points
- Values linearizationPoints;
+ KalmanValues linearizationPoints;
// Ground truth example
// Start at origin, move to the right (x-axis): 0,0 0,1 0,2
@@ -64,7 +64,7 @@ int main() {
// This is equivalent to x_0 and P_0
Point2 x_initial(0,0);
SharedDiagonal P_initial = noiseModel::Diagonal::Sigmas(Vector_(2, 0.1, 0.1));
- PriorFactor factor1(x0, x_initial, P_initial);
+ PriorFactor factor1(x0, x_initial, P_initial);
// Linearize the factor and add it to the linear factor graph
linearizationPoints.insert(x0, x_initial);
linearFactorGraph->push_back(factor1.linearize(linearizationPoints, *ordering));
@@ -95,7 +95,7 @@ int main() {
Point2 difference(1,0);
SharedDiagonal Q = noiseModel::Diagonal::Sigmas(Vector_(2, 0.1, 0.1));
- BetweenFactor factor2(x0, x1, difference, Q);
+ BetweenFactor factor2(x0, x1, difference, Q);
// Linearize the factor and add it to the linear factor graph
linearizationPoints.insert(x1, x_initial);
linearFactorGraph->push_back(factor2.linearize(linearizationPoints, *ordering));
@@ -118,7 +118,7 @@ int main() {
// Extract the current estimate of x1,P1 from the Bayes Network
VectorValues result = optimize(*linearBayesNet);
- Point2 x1_predict = linearizationPoints[x1].expmap(result[ordering->at(x1)]);
+ Point2 x1_predict = linearizationPoints[x1].retract(result[ordering->at(x1)]);
x1_predict.print("X1 Predict");
// Update the new linearization point to the new estimate
@@ -173,7 +173,7 @@ int main() {
// This can be modeled using the PriorFactor, where the mean is z_{t} and the covariance is R.
Point2 z1(1.0, 0.0);
SharedDiagonal R1 = noiseModel::Diagonal::Sigmas(Vector_(2, 0.25, 0.25));
- PriorFactor factor4(x1, z1, R1);
+ PriorFactor factor4(x1, z1, R1);
// Linearize the factor and add it to the linear factor graph
linearFactorGraph->push_back(factor4.linearize(linearizationPoints, *ordering));
@@ -190,7 +190,7 @@ int main() {
// Extract the current estimate of x1 from the Bayes Network
result = optimize(*linearBayesNet);
- Point2 x1_update = linearizationPoints[x1].expmap(result[ordering->at(x1)]);
+ Point2 x1_update = linearizationPoints[x1].retract(result[ordering->at(x1)]);
x1_update.print("X1 Update");
// Update the linearization point to the new estimate
@@ -225,7 +225,7 @@ int main() {
// Create a nonlinear factor describing the motion model
difference = Point2(1,0);
Q = noiseModel::Diagonal::Sigmas(Vector_(2, 0.1, 0.1));
- BetweenFactor factor6(x1, x2, difference, Q);
+ BetweenFactor factor6(x1, x2, difference, Q);
// Linearize the factor and add it to the linear factor graph
linearizationPoints.insert(x2, x1_update);
@@ -237,7 +237,7 @@ int main() {
// Extract the current estimate of x2 from the Bayes Network
result = optimize(*linearBayesNet);
- Point2 x2_predict = linearizationPoints[x2].expmap(result[ordering->at(x2)]);
+ Point2 x2_predict = linearizationPoints[x2].retract(result[ordering->at(x2)]);
x2_predict.print("X2 Predict");
// Update the linearization point to the new estimate
@@ -263,7 +263,7 @@ int main() {
// And update using z2 ...
Point2 z2(2.0, 0.0);
SharedDiagonal R2 = noiseModel::Diagonal::Sigmas(Vector_(2, 0.25, 0.25));
- PriorFactor factor8(x2, z2, R2);
+ PriorFactor factor8(x2, z2, R2);
// Linearize the factor and add it to the linear factor graph
linearFactorGraph->push_back(factor8.linearize(linearizationPoints, *ordering));
@@ -281,7 +281,7 @@ int main() {
// Extract the current estimate of x2 from the Bayes Network
result = optimize(*linearBayesNet);
- Point2 x2_update = linearizationPoints[x2].expmap(result[ordering->at(x2)]);
+ Point2 x2_update = linearizationPoints[x2].retract(result[ordering->at(x2)]);
x2_update.print("X2 Update");
// Update the linearization point to the new estimate
@@ -314,7 +314,7 @@ int main() {
// Create a nonlinear factor describing the motion model
difference = Point2(1,0);
Q = noiseModel::Diagonal::Sigmas(Vector_(2, 0.1, 0.1));
- BetweenFactor factor10(x2, x3, difference, Q);
+ BetweenFactor factor10(x2, x3, difference, Q);
// Linearize the factor and add it to the linear factor graph
linearizationPoints.insert(x3, x2_update);
@@ -326,7 +326,7 @@ int main() {
// Extract the current estimate of x3 from the Bayes Network
result = optimize(*linearBayesNet);
- Point2 x3_predict = linearizationPoints[x3].expmap(result[ordering->at(x3)]);
+ Point2 x3_predict = linearizationPoints[x3].retract(result[ordering->at(x3)]);
x3_predict.print("X3 Predict");
// Update the linearization point to the new estimate
@@ -352,7 +352,7 @@ int main() {
// And update using z3 ...
Point2 z3(3.0, 0.0);
SharedDiagonal R3 = noiseModel::Diagonal::Sigmas(Vector_(2, 0.25, 0.25));
- PriorFactor factor12(x3, z3, R3);
+ PriorFactor factor12(x3, z3, R3);
// Linearize the factor and add it to the linear factor graph
linearFactorGraph->push_back(factor12.linearize(linearizationPoints, *ordering));
@@ -370,7 +370,7 @@ int main() {
// Extract the current estimate of x2 from the Bayes Network
result = optimize(*linearBayesNet);
- Point2 x3_update = linearizationPoints[x3].expmap(result[ordering->at(x3)]);
+ Point2 x3_update = linearizationPoints[x3].retract(result[ordering->at(x3)]);
x3_update.print("X3 Update");
// Update the linearization point to the new estimate
diff --git a/examples/vSLAMexample/vISAMexample.cpp b/examples/vSLAMexample/vISAMexample.cpp
index 1e5040509..300124c4e 100644
--- a/examples/vSLAMexample/vISAMexample.cpp
+++ b/examples/vSLAMexample/vISAMexample.cpp
@@ -81,7 +81,7 @@ void readAllDataISAM() {
/**
* Setup newFactors and initialValues for each new pose and set of measurements at each frame.
*/
-void createNewFactors(shared_ptr& newFactors, boost::shared_ptr& initialValues,
+void createNewFactors(shared_ptr& newFactors, boost::shared_ptr& initialValues,
int pose_id, Pose3& pose, std::vector& measurements, SharedNoiseModel measurementSigma, shared_ptrK calib) {
// Create a graph of newFactors with new measurements
@@ -102,7 +102,7 @@ void createNewFactors(shared_ptr& newFactors, boost::shared_ptr&
}
// Create initial values for all nodes in the newFactors
- initialValues = shared_ptr (new Values());
+ initialValues = shared_ptr (new visualSLAM::Values());
initialValues->insert(pose_id, pose);
for (size_t i = 0; i < measurements.size(); i++) {
initialValues->insert(measurements[i].m_idLandmark, g_landmarks[measurements[i].m_idLandmark]);
@@ -125,17 +125,17 @@ int main(int argc, char* argv[]) {
// Create an NonlinearISAM which will be relinearized and reordered after every "relinearizeInterval" updates
int relinearizeInterval = 3;
- NonlinearISAM isam(relinearizeInterval);
+ NonlinearISAM isam(relinearizeInterval);
// At each frame i with new camera pose and new set of measurements associated with it,
// create a graph of new factors and update ISAM
for (size_t i = 0; i < g_measurements.size(); i++) {
shared_ptr newFactors;
- shared_ptr initialValues;
+ shared_ptr initialValues;
createNewFactors(newFactors, initialValues, i, g_poses[i], g_measurements[i], measurementSigma, g_calib);
isam.update(*newFactors, *initialValues);
- Values currentEstimate = isam.estimate();
+ visualSLAM::Values currentEstimate = isam.estimate();
cout << "****************************************************" << endl;
currentEstimate.print("Current estimate: ");
}
diff --git a/examples/vSLAMexample/vSFMexample.cpp b/examples/vSLAMexample/vSFMexample.cpp
index 8027fa571..6aaf04442 100644
--- a/examples/vSLAMexample/vSFMexample.cpp
+++ b/examples/vSLAMexample/vSFMexample.cpp
@@ -103,9 +103,9 @@ Graph setupGraph(std::vector& measurements, SharedNoiseModel measurem
* Create a structure of initial estimates for all nodes (landmarks and poses) in the graph.
* The returned Values structure contains all initial values for all nodes.
*/
-Values initialize(std::map landmarks, std::map poses) {
+visualSLAM::Values initialize(std::map landmarks, std::map poses) {
- Values initValues;
+ visualSLAM::Values initValues;
// Initialize landmarks 3D positions.
for (map::iterator lmit = landmarks.begin(); lmit != landmarks.end(); lmit++)
@@ -136,7 +136,7 @@ int main(int argc, char* argv[]) {
boost::shared_ptr graph(new Graph(setupGraph(g_measurements, measurementSigma, g_calib)));
// Create an initial Values structure using groundtruth values as the initial estimates
- boost::shared_ptr initialEstimates(new Values(initialize(g_landmarks, g_poses)));
+ boost::shared_ptr initialEstimates(new visualSLAM::Values(initialize(g_landmarks, g_poses)));
cout << "*******************************************************" << endl;
initialEstimates->print("INITIAL ESTIMATES: ");
@@ -148,7 +148,7 @@ int main(int argc, char* argv[]) {
// Optimize the graph
cout << "*******************************************************" << endl;
NonlinearOptimizationParameters::sharedThis params = NonlinearOptimizationParameters::newVerbosity(Optimizer::Parameters::DAMPED);
- Optimizer::shared_values result = Optimizer::optimizeGN(graph, initialEstimates, params);
+ visualSLAM::Optimizer::shared_values result = visualSLAM::Optimizer::optimizeGN(graph, initialEstimates, params);
// Print final results
cout << "*******************************************************" << endl;
diff --git a/gtsam/base/Group.h b/gtsam/base/Group.h
new file mode 100644
index 000000000..3c56a541a
--- /dev/null
+++ b/gtsam/base/Group.h
@@ -0,0 +1,47 @@
+/**
+ * @file Group.h
+ *
+ * @brief Concept check class for variable types with Group properties
+ * A Group concept extends a Manifold
+ *
+ * @date Nov 5, 2011
+ * @author Alex Cunningham
+ */
+
+#pragma once
+
+namespace gtsam {
+
+/**
+ * Concept check for general Group structure
+ */
+template
+class GroupConcept {
+private:
+ static void concept_check(const T& t) {
+ /** assignment */
+ T t2 = t;
+
+ /** compose with another object */
+ T compose_ret = t.compose(t2);
+
+ /** invert the object and yield a new one */
+ T inverse_ret = t.inverse();
+
+ /** identity */
+ T identity = T::identity();
+ }
+};
+
+} // \namespace gtsam
+
+/**
+ * Macros for using the GroupConcept
+ * - An instantiation for use inside unit tests
+ * - A typedef for use inside generic algorithms
+ *
+ * NOTE: intentionally not in the gtsam namespace to allow for classes not in
+ * the gtsam namespace to be more easily enforced as testable
+ */
+#define GTSAM_CONCEPT_GROUP_INST(T) template class gtsam::GroupConcept;
+#define GTSAM_CONCEPT_GROUP_TYPE(T) typedef gtsam::GroupConcept _gtsam_GroupConcept_##T;
diff --git a/gtsam/base/Lie-inl.h b/gtsam/base/Lie-inl.h
index 559a01960..f1bb947a2 100644
--- a/gtsam/base/Lie-inl.h
+++ b/gtsam/base/Lie-inl.h
@@ -23,8 +23,6 @@
#define INSTANTIATE_LIE(T) \
template T between_default(const T&, const T&); \
template Vector logmap_default(const T&, const T&); \
- template T expmap_default(const T&, const Vector&); \
- template bool equal(const T&, const T&, double); \
- template bool equal(const T&, const T&); \
- template class Lie;
+ template T expmap_default(const T&, const Vector&);
+
diff --git a/gtsam/base/Lie.h b/gtsam/base/Lie.h
index ea3c730bf..756790f16 100644
--- a/gtsam/base/Lie.h
+++ b/gtsam/base/Lie.h
@@ -15,26 +15,18 @@
* @author Richard Roberts
* @author Alex Cunningham
*
+ * This concept check provides a specialization on the Manifold type,
+ * in which the Manifolds represented require an algebra and group structure.
+ * All Lie types must also be a Manifold.
+ *
* The necessary functions to implement for Lie are defined
* below with additional details as to the interface. The
* concept checking function in class Lie will check whether or not
* the function exists and throw compile-time errors.
*
- * Returns dimensionality of the tangent space
- * inline size_t dim() const;
- *
- * Returns Exponential map update of T
- * A default implementation of expmap(*this, lp) is available:
- * expmap_default()
- * T expmap(const Vector& v) const;
- *
- * expmap around identity
+ * Expmap around identity
* static T Expmap(const Vector& v);
*
- * Returns Log map
- * A default implementation of logmap(*this, lp) is available:
- * logmap_default()
- * Vector logmap(const T& lp) const;
*
* Logmap around identity
* static Vector Logmap(const T& p);
@@ -44,19 +36,13 @@
* between_default()
* T between(const T& l2) const;
*
- * compose with another object
- * T compose(const T& p) const;
- *
- * invert the object and yield a new one
- * T inverse() const;
- *
*/
#pragma once
-#include
-#include
+#include
+#include
namespace gtsam {
@@ -78,18 +64,15 @@ namespace gtsam {
inline T expmap_default(const T& t, const Vector& d) {return t.compose(T::Expmap(d));}
/**
- * Base class for Lie group type
- * This class uses the Curiously Recurring Template design pattern to allow for
- * concept checking using a private function.
+ * Concept check class for Lie group type
*
- * T is the derived Lie type, like Point2, Pose3, etc.
+ * T is the Lie type, like Point2, Pose3, etc.
*
* By convention, we use capital letters to designate a static function
*/
template
- class Lie {
+ class LieConcept {
private:
-
/** concept checking function - implement the functions this demands */
static void concept_check(const T& t) {
@@ -101,54 +84,18 @@ namespace gtsam {
*/
size_t dim_ret = t.dim();
- /**
- * Returns Exponential map update of T
- * Default implementation calls global binary function
- */
- T expmap_ret = t.expmap(gtsam::zero(dim_ret));
-
/** expmap around identity */
T expmap_identity_ret = T::Expmap(gtsam::zero(dim_ret));
- /**
- * Returns Log map
- * Default Implementation calls global binary function
- */
- Vector logmap_ret = t.logmap(t2);
-
/** Logmap around identity */
Vector logmap_identity_ret = T::Logmap(t);
/** Compute l0 s.t. l2=l1*l0, where (*this) is l1 */
T between_ret = t.between(t2);
-
- /** compose with another object */
- T compose_ret = t.compose(t2);
-
- /** invert the object and yield a new one */
- T inverse_ret = t.inverse();
}
};
- /** Call print on the object */
- template
- inline void print(const T& object, const std::string& s = "") {
- object.print(s);
- }
-
- /** Call equal on the object */
- template
- inline bool equal(const T& obj1, const T& obj2, double tol) {
- return obj1.equals(obj2, tol);
- }
-
- /** Call equal on the object without tolerance (use default tolerance) */
- template
- inline bool equal(const T& obj1, const T& obj2) {
- return obj1.equals(obj2);
- }
-
/**
* Three term approximation of the Baker�Campbell�Hausdorff formula
* In non-commutative Lie groups, when composing exp(Z) = exp(X)exp(Y)
@@ -156,6 +103,7 @@ namespace gtsam {
* formula: Z = X + Y + [X,Y]/2 + [X-Y,[X,Y]]/12 - [Y,[X,[X,Y]]]/24
* http://en.wikipedia.org/wiki/Baker�Campbell�Hausdorff_formula
*/
+ /// AGC: bracket() only appears in Rot3 tests, should this be used elsewhere?
template
T BCH(const T& X, const T& Y) {
static const double _2 = 1. / 2., _12 = 1. / 12., _24 = 1. / 24.;
@@ -182,25 +130,22 @@ namespace gtsam {
return expm(xhat,K);
}
- /**
- * function wrappers for full versions of expmap/logmap
- * these will default simple types to using the existing expmap/logmap,
- * but more complex ones can be specialized to use improved versions
- *
- * TODO: replace this approach with a naming scheme that doesn't call
- * non-expmap operations "expmap" - use same approach, but with "update"
- */
-
- /** unary versions */
- template
- T ExpmapFull(const Vector& xi) { return T::Expmap(xi); }
- template
- Vector LogmapFull(const T& p) { return T::Logmap(p); }
-
- /** binary versions */
- template
- T expmapFull(const T& t, const Vector& v) { return t.expmap(v); }
- template
- Vector logmapFull(const T& t, const T& p2) { return t.logmap(p2); }
-
} // namespace gtsam
+
+/**
+ * Macros for using the LieConcept
+ * - An instantiation for use inside unit tests
+ * - A typedef for use inside generic algorithms
+ *
+ * NOTE: intentionally not in the gtsam namespace to allow for classes not in
+ * the gtsam namespace to be more easily enforced as testable
+ */
+#define GTSAM_CONCEPT_LIE_INST(T) \
+ template class gtsam::ManifoldConcept; \
+ template class gtsam::GroupConcept; \
+ template class gtsam::LieConcept;
+
+#define GTSAM_CONCEPT_LIE_TYPE(T) \
+ typedef gtsam::ManifoldConcept _gtsam_ManifoldConcept_##T; \
+ typedef gtsam::GroupConcept _gtsam_GroupConcept_##T; \
+ typedef gtsam::LieConcept _gtsam_LieConcept_##T;
diff --git a/gtsam/base/LieScalar.h b/gtsam/base/LieScalar.h
index 7d73255b7..51439c6f1 100644
--- a/gtsam/base/LieScalar.h
+++ b/gtsam/base/LieScalar.h
@@ -24,10 +24,10 @@ namespace gtsam {
/**
* LieScalar is a wrapper around double to allow it to be a Lie type
*/
- struct LieScalar : public Lie {
+ struct LieScalar {
- /** default constructor - should be unnecessary */
- LieScalar() {}
+ /** default constructor */
+ LieScalar() : d_(0.0) {}
/** wrap a double */
LieScalar(double d) : d_(d) {}
@@ -45,33 +45,51 @@ namespace gtsam {
return fabs(expected.d_ - d_) <= tol;
}
- /**
- * Returns dimensionality of the tangent space
- * with member and static versions
- */
+ // Manifold requirements
+
+ /** Returns dimensionality of the tangent space */
inline size_t dim() const { return 1; }
inline static size_t Dim() { return 1; }
- /**
- * Returns Exponential map update of T
- * Default implementation calls global binary function
- */
- inline LieScalar expmap(const Vector& v) const { return LieScalar(d_ + v(0)); }
+ /** Update the LieScalar with a tangent space update */
+ inline LieScalar retract(const Vector& v) const { return LieScalar(value() + v(0)); }
- /** expmap around identity */
- static inline LieScalar Expmap(const Vector& v) { return LieScalar(v(0)); }
+ /** @return the local coordinates of another object */
+ inline Vector localCoordinates(const LieScalar& t2) const { return Vector_(1,(t2.value() - value())); }
- /**
- * Returns Log map
- * Default Implementation calls global binary function
- */
- inline Vector logmap(const LieScalar& lp) const {
- return Vector_(1, lp.d_ - d_);
+ // Group requirements
+
+ /** identity */
+ inline static LieScalar identity() {
+ return LieScalar();
}
- /** Logmap around identity - just returns with default cast back */
- static inline Vector Logmap(const LieScalar& p) { return Vector_(1, p.d_); }
+ /** compose with another object */
+ inline LieScalar compose(const LieScalar& p) const {
+ return LieScalar(d_ + p.d_);
+ }
+ /** between operation */
+ inline LieScalar between(const LieScalar& l2,
+ boost::optional H1=boost::none,
+ boost::optional H2=boost::none) const {
+ if(H1) *H1 = -eye(1);
+ if(H2) *H2 = eye(1);
+ return LieScalar(l2.value() - value());
+ }
+
+ /** invert the object and yield a new one */
+ inline LieScalar inverse() const {
+ return LieScalar(-1.0 * value());
+ }
+
+ // Lie functions
+
+ /** Expmap around identity */
+ static inline LieScalar Expmap(const Vector& v) { return LieScalar(v(0)); }
+
+ /** Logmap around identity - just returns with default cast back */
+ static inline Vector Logmap(const LieScalar& p) { return Vector_(1,p.value()); }
private:
double d_;
diff --git a/gtsam/base/LieVector.h b/gtsam/base/LieVector.h
index bec42f775..5a1b3d580 100644
--- a/gtsam/base/LieVector.h
+++ b/gtsam/base/LieVector.h
@@ -25,7 +25,7 @@ namespace gtsam {
/**
* LieVector is a wrapper around vector to allow it to be a Lie type
*/
-struct LieVector : public Vector, public Lie {
+struct LieVector : public Vector {
/** default constructor - should be unnecessary */
LieVector() {}
@@ -57,31 +57,25 @@ struct LieVector : public Vector, public Lie {
return gtsam::equal(vector(), expected.vector(), tol);
}
- /**
- * Returns dimensionality of the tangent space
- */
+ // Manifold requirements
+
+ /** Returns dimensionality of the tangent space */
inline size_t dim() const { return this->size(); }
- /**
- * Returns Exponential map update of T
- * Default implementation calls global binary function
- */
- inline LieVector expmap(const Vector& v) const { return LieVector(vector() + v); }
+ /** Update the LieVector with a tangent space update */
+ inline LieVector retract(const Vector& v) const { return LieVector(vector() + v); }
- /** expmap around identity */
- static inline LieVector Expmap(const Vector& v) { return LieVector(v); }
+ /** @return the local coordinates of another object */
+ inline Vector localCoordinates(const LieVector& t2) const { return LieVector(t2 - vector()); }
- /**
- * Returns Log map
- * Default Implementation calls global binary function
- */
- inline Vector logmap(const LieVector& lp) const {
- return lp.vector() - vector();
+ // Group requirements
+
+ /** identity - NOTE: no known size at compile time - so zero length */
+ inline static LieVector identity() {
+ throw std::runtime_error("LieVector::identity(): Don't use this function");
+ return LieVector();
}
- /** Logmap around identity - just returns with default cast back */
- static inline Vector Logmap(const LieVector& p) { return p; }
-
/** compose with another object */
inline LieVector compose(const LieVector& p) const {
return LieVector(vector() + p);
@@ -100,5 +94,14 @@ struct LieVector : public Vector, public Lie {
inline LieVector inverse() const {
return LieVector(-1.0 * vector());
}
+
+ // Lie functions
+
+ /** Expmap around identity */
+ static inline LieVector Expmap(const Vector& v) { return LieVector(v); }
+
+ /** Logmap around identity - just returns with default cast back */
+ static inline Vector Logmap(const LieVector& p) { return p; }
+
};
} // \namespace gtsam
diff --git a/gtsam/base/Makefile.am b/gtsam/base/Makefile.am
index 1414532b7..0d4189dd7 100644
--- a/gtsam/base/Makefile.am
+++ b/gtsam/base/Makefile.am
@@ -25,7 +25,8 @@ headers += Testable.h TestableAssertions.h numericalDerivative.h
sources += timing.cpp debug.cpp
check_PROGRAMS += tests/testDebug tests/testTestableAssertions
-# Lie Groups
+# Manifolds and Lie Groups
+headers += Manifold.h Group.h
headers += Lie.h Lie-inl.h lieProxies.h LieScalar.h
sources += LieVector.cpp
check_PROGRAMS += tests/testLieVector tests/testLieScalar
diff --git a/gtsam/base/Manifold.h b/gtsam/base/Manifold.h
new file mode 100644
index 000000000..87506f31f
--- /dev/null
+++ b/gtsam/base/Manifold.h
@@ -0,0 +1,87 @@
+/* ----------------------------------------------------------------------------
+
+ * 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 Manifold.h
+ * @brief Base class and basic functions for Manifold types
+ * @author Richard Roberts
+ * @author Alex Cunningham
+ *
+ * The necessary functions to implement for Manifold are defined
+ * below with additional details as to the interface. The
+ * concept checking function in class Manifold will check whether or not
+ * the function exists and throw compile-time errors.
+ *
+ * Returns dimensionality of the tangent space
+ * inline size_t dim() const;
+ *
+ * Returns Retraction update of T
+ * T retract(const Vector& v) const;
+ *
+ * Returns inverse retraction operation
+ * Vector localCoordinates(const T& lp) const;
+ *
+ */
+
+#pragma once
+
+#include
+#include
+
+namespace gtsam {
+
+ /**
+ * Concept check class for Manifold types
+ * Requires a mapping between a linear tangent space and the underlying
+ * manifold, of which Lie is a specialization.
+ *
+ * T is the Manifold type, like Point2, Pose3, etc.
+ *
+ * By convention, we use capital letters to designate a static function
+ */
+ template
+ class ManifoldConcept {
+ private:
+ /** concept checking function - implement the functions this demands */
+ static void concept_check(const T& t) {
+
+ /** assignment */
+ T t2 = t;
+
+ /**
+ * Returns dimensionality of the tangent space
+ */
+ size_t dim_ret = t.dim();
+
+ /**
+ * Returns Retraction update of T
+ */
+ T retract_ret = t.retract(gtsam::zero(dim_ret));
+
+ /**
+ * Returns local coordinates of another object
+ */
+ Vector localCoords_ret = t.localCoordinates(t2);
+ }
+ };
+
+} // namespace gtsam
+
+/**
+ * Macros for using the ManifoldConcept
+ * - An instantiation for use inside unit tests
+ * - A typedef for use inside generic algorithms
+ *
+ * NOTE: intentionally not in the gtsam namespace to allow for classes not in
+ * the gtsam namespace to be more easily enforced as testable
+ */
+#define GTSAM_CONCEPT_MANIFOLD_INST(T) template class gtsam::ManifoldConcept;
+#define GTSAM_CONCEPT_MANIFOLD_TYPE(T) typedef gtsam::ManifoldConcept _gtsam_ManifoldConcept_##T;
diff --git a/gtsam/base/Testable.h b/gtsam/base/Testable.h
index 7fa8bca80..d8829798b 100644
--- a/gtsam/base/Testable.h
+++ b/gtsam/base/Testable.h
@@ -63,6 +63,24 @@ namespace gtsam {
}
};
+ /** Call print on the object */
+ template
+ inline void print(const T& object, const std::string& s = "") {
+ object.print(s);
+ }
+
+ /** Call equal on the object */
+ template
+ inline bool equal(const T& obj1, const T& obj2, double tol) {
+ return obj1.equals(obj2, tol);
+ }
+
+ /** Call equal on the object without tolerance (use default tolerance) */
+ template
+ inline bool equal(const T& obj1, const T& obj2) {
+ return obj1.equals(obj2);
+ }
+
/**
* This template works for any type with equals
*/
@@ -111,6 +129,5 @@ namespace gtsam {
* NOTE: intentionally not in the gtsam namespace to allow for classes not in
* the gtsam namespace to be more easily enforced as testable
*/
-/// TODO: find better name for "INST" macro, something like "UNIT" or similar
#define GTSAM_CONCEPT_TESTABLE_INST(T) template class gtsam::TestableConcept;
#define GTSAM_CONCEPT_TESTABLE_TYPE(T) typedef gtsam::TestableConcept _gtsam_TestableConcept_##T;
diff --git a/gtsam/base/lieProxies.h b/gtsam/base/lieProxies.h
index 41e031cf7..b1992f741 100644
--- a/gtsam/base/lieProxies.h
+++ b/gtsam/base/lieProxies.h
@@ -36,13 +36,6 @@ namespace testing {
template
T compose(const T& t1, const T& t2) { return t1.compose(t2); }
- /** expmap and logmap */
- template
- Vector logmap(const T& t1, const T& t2) { return t1.logmap(t2); }
-
- template
- T expmap(const T& t1, const Vector& t2) { return t1.expmap(t2); }
-
/** unary functions */
template
T inverse(const T& t) { return t.inverse(); }
@@ -54,6 +47,7 @@ namespace testing {
template
P unrotate(const T& r, const P& pt) { return r.unrotate(pt); }
-}
-}
+} // \namespace testing
+} // \namespace gtsam
+
diff --git a/gtsam/base/numericalDerivative.h b/gtsam/base/numericalDerivative.h
index 04bc3eb84..d18db38be 100644
--- a/gtsam/base/numericalDerivative.h
+++ b/gtsam/base/numericalDerivative.h
@@ -67,8 +67,8 @@ namespace gtsam {
const size_t n = x.dim();
Vector d = zero(n), g = zero(n);
for (size_t j=0;j
#include
+#include
#include
using namespace gtsam;
GTSAM_CONCEPT_TESTABLE_INST(LieScalar)
+GTSAM_CONCEPT_LIE_INST(LieScalar)
const double tol=1e-9;
@@ -37,10 +39,10 @@ TEST( testLieScalar, construction ) {
}
/* ************************************************************************* */
-TEST( testLieScalar, logmap ) {
+TEST( testLieScalar, localCoordinates ) {
LieScalar lie1(1.), lie2(3.);
- EXPECT(assert_equal(Vector_(1, 2.), lie1.logmap(lie2)));
+ EXPECT(assert_equal(Vector_(1, 2.), lie1.localCoordinates(lie2)));
}
/* ************************************************************************* */
diff --git a/gtsam/base/tests/testLieVector.cpp b/gtsam/base/tests/testLieVector.cpp
index e8dfae741..c4c88dc9b 100644
--- a/gtsam/base/tests/testLieVector.cpp
+++ b/gtsam/base/tests/testLieVector.cpp
@@ -17,11 +17,13 @@
#include
#include
+#include
#include
using namespace gtsam;
GTSAM_CONCEPT_TESTABLE_INST(LieVector)
+GTSAM_CONCEPT_LIE_INST(LieVector)
/* ************************************************************************* */
TEST( testLieVector, construction ) {
diff --git a/gtsam/geometry/Cal3Bundler.cpp b/gtsam/geometry/Cal3Bundler.cpp
index 6bdef025c..18bcf8db8 100644
--- a/gtsam/geometry/Cal3Bundler.cpp
+++ b/gtsam/geometry/Cal3Bundler.cpp
@@ -23,21 +23,35 @@
namespace gtsam {
+/* ************************************************************************* */
Cal3Bundler::Cal3Bundler() : f_(1), k1_(0), k2_(0) {}
+
+/* ************************************************************************* */
Cal3Bundler::Cal3Bundler(const Vector &v) : f_(v(0)), k1_(v(1)), k2_(v(2)) {}
+
+/* ************************************************************************* */
Cal3Bundler::Cal3Bundler(const double f, const double k1, const double k2) : f_(f), k1_(k1), k2_(k2) {}
+/* ************************************************************************* */
Matrix Cal3Bundler::K() const { return Matrix_(3,3, f_, 0.0, 0.0, 0.0, f_, 0.0, 0.0, 0.0, 1.0); }
+
+/* ************************************************************************* */
Vector Cal3Bundler::k() const { return Vector_(4, k1_, k2_, 0, 0) ; }
+
+/* ************************************************************************* */
Vector Cal3Bundler::vector() const { return Vector_(3, f_, k1_, k2_) ; }
+
+/* ************************************************************************* */
void Cal3Bundler::print(const std::string& s) const { gtsam::print(vector(), s + ".K") ; }
+/* ************************************************************************* */
bool Cal3Bundler::equals(const Cal3Bundler& K, double tol) const {
if (fabs(f_ - K.f_) > tol || fabs(k1_ - K.k1_) > tol || fabs(k2_ - K.k2_) > tol)
return false;
return true ;
}
+/* ************************************************************************* */
Point2 Cal3Bundler::uncalibrate(const Point2& p,
boost::optional H1,
boost::optional H2) const {
@@ -78,6 +92,7 @@ Point2 Cal3Bundler::uncalibrate(const Point2& p,
return Point2(fg * x, fg * y) ;
}
+/* ************************************************************************* */
Matrix Cal3Bundler::D2d_intrinsic(const Point2& p) const {
const double x = p.x(), y = p.y(), xx = x*x, yy = y*y;
const double r = xx + yy ;
@@ -95,6 +110,7 @@ Matrix Cal3Bundler::D2d_intrinsic(const Point2& p) const {
return DK * DR;
}
+/* ************************************************************************* */
Matrix Cal3Bundler::D2d_calibration(const Point2& p) const {
const double x = p.x(), y = p.y(), xx = x*x, yy = y*y ;
@@ -109,6 +125,7 @@ Matrix Cal3Bundler::D2d_calibration(const Point2& p) const {
g*y, f*y*r , f*y*r2);
}
+/* ************************************************************************* */
Matrix Cal3Bundler::D2d_intrinsic_calibration(const Point2& p) const {
const double x = p.x(), y = p.y(), xx = x*x, yy = y*y;
@@ -128,12 +145,10 @@ Matrix Cal3Bundler::D2d_intrinsic_calibration(const Point2& p) const {
return H ;
}
+/* ************************************************************************* */
+Cal3Bundler Cal3Bundler::retract(const Vector& d) const { return Cal3Bundler(vector() + d) ; }
-Cal3Bundler Cal3Bundler::expmap(const Vector& d) const { return Cal3Bundler(vector() + d) ; }
-Vector Cal3Bundler::logmap(const Cal3Bundler& T2) const { return vector() - T2.vector(); }
-Cal3Bundler Cal3Bundler::Expmap(const Vector& v) { return Cal3Bundler(v) ; }
-Vector Cal3Bundler::Logmap(const Cal3Bundler& p) { return p.vector(); }
-
-
+/* ************************************************************************* */
+Vector Cal3Bundler::localCoordinates(const Cal3Bundler& T2) const { return vector() - T2.vector(); }
}
diff --git a/gtsam/geometry/Cal3Bundler.h b/gtsam/geometry/Cal3Bundler.h
index 620dabad6..bb8ea59c8 100644
--- a/gtsam/geometry/Cal3Bundler.h
+++ b/gtsam/geometry/Cal3Bundler.h
@@ -44,18 +44,15 @@ public:
bool equals(const Cal3Bundler& K, double tol = 10e-9) const;
Point2 uncalibrate(const Point2& p,
- boost::optional H1 = boost::none,
- boost::optional H2 = boost::none) const ;
+ boost::optional H1 = boost::none,
+ boost::optional H2 = boost::none) const ;
Matrix D2d_intrinsic(const Point2& p) const ;
Matrix D2d_calibration(const Point2& p) const ;
Matrix D2d_intrinsic_calibration(const Point2& p) const ;
- Cal3Bundler expmap(const Vector& d) const ;
- Vector logmap(const Cal3Bundler& T2) const ;
-
- static Cal3Bundler Expmap(const Vector& v) ;
- static Vector Logmap(const Cal3Bundler& p) ;
+ Cal3Bundler retract(const Vector& d) const ;
+ Vector localCoordinates(const Cal3Bundler& T2) const ;
int dim() const { return 3 ; }
static size_t Dim() { return 3; }
diff --git a/gtsam/geometry/Cal3DS2.cpp b/gtsam/geometry/Cal3DS2.cpp
index 069ec4efb..dcb6d6d54 100644
--- a/gtsam/geometry/Cal3DS2.cpp
+++ b/gtsam/geometry/Cal3DS2.cpp
@@ -23,20 +23,30 @@
namespace gtsam {
+/* ************************************************************************* */
Cal3DS2::Cal3DS2():fx_(1), fy_(1), s_(0), u0_(0), v0_(0), k1_(0), k2_(0), k3_(0), k4_(0){}
-// Construction
+/* ************************************************************************* */
Cal3DS2::Cal3DS2(double fx, double fy, double s, double u0, double v0, double k1, double k2, double k3, double k4) :
fx_(fx), fy_(fy), s_(s), u0_(u0), v0_(v0), k1_(k1), k2_(k2), k3_(k3), k4_(k4) {}
+/* ************************************************************************* */
Cal3DS2::Cal3DS2(const Vector &v):
fx_(v[0]), fy_(v[1]), s_(v[2]), u0_(v[3]), v0_(v[4]), k1_(v[5]), k2_(v[6]), k3_(v[7]), k4_(v[8]){}
+/* ************************************************************************* */
Matrix Cal3DS2::K() const { return Matrix_(3,3, fx_, s_, u0_, 0.0, fy_, v0_, 0.0, 0.0, 1.0); }
+
+/* ************************************************************************* */
Vector Cal3DS2::k() const { return Vector_(4, k1_, k2_, k3_, k4_); }
+
+/* ************************************************************************* */
Vector Cal3DS2::vector() const { return Vector_(9, fx_, fy_, s_, u0_, v0_, k1_, k2_, k3_, k4_) ; }
+
+/* ************************************************************************* */
void Cal3DS2::print(const std::string& s) const { gtsam::print(K(), s + ".K") ; gtsam::print(k(), s + ".k") ; }
+/* ************************************************************************* */
bool Cal3DS2::equals(const Cal3DS2& K, double tol) const {
if (fabs(fx_ - K.fx_) > tol || fabs(fy_ - K.fy_) > tol || fabs(s_ - K.s_) > tol ||
fabs(u0_ - K.u0_) > tol || fabs(v0_ - K.v0_) > tol || fabs(k1_ - K.k1_) > tol ||
@@ -45,6 +55,7 @@ bool Cal3DS2::equals(const Cal3DS2& K, double tol) const {
return true ;
}
+/* ************************************************************************* */
Point2 Cal3DS2::uncalibrate(const Point2& p,
boost::optional H1,
boost::optional H2) const {
@@ -67,6 +78,7 @@ Point2 Cal3DS2::uncalibrate(const Point2& p,
return Point2(fx_* x2 + s_ * y2 + u0_, fy_ * y2 + v0_) ;
}
+/* ************************************************************************* */
Matrix Cal3DS2::D2d_intrinsic(const Point2& p) const {
//const double fx = fx_, fy = fy_, s = s_ ;
const double k1 = k1_, k2 = k2_, k3 = k3_, k4 = k4_;
@@ -94,7 +106,7 @@ Matrix Cal3DS2::D2d_intrinsic(const Point2& p) const {
return DK * DR;
}
-
+/* ************************************************************************* */
Matrix Cal3DS2::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 r = xx + yy ;
@@ -111,10 +123,11 @@ Matrix Cal3DS2::D2d_calibration(const Point2& p) const {
0.0, pny, 0.0, 0.0, 1.0, fy*y*r , fy*y*r2 , fy*(r+2*yy) , fy*(2*xy) );
}
-Cal3DS2 Cal3DS2::expmap(const Vector& d) const { return Cal3DS2(vector() + d) ; }
-Vector Cal3DS2::logmap(const Cal3DS2& T2) const { return vector() - T2.vector(); }
-Cal3DS2 Cal3DS2::Expmap(const Vector& v) { return Cal3DS2(v) ; }
-Vector Cal3DS2::Logmap(const Cal3DS2& p) { return p.vector(); }
+/* ************************************************************************* */
+Cal3DS2 Cal3DS2::retract(const Vector& d) const { return Cal3DS2(vector() + d) ; }
+
+/* ************************************************************************* */
+Vector Cal3DS2::localCoordinates(const Cal3DS2& T2) const { return vector() - T2.vector(); }
}
/* ************************************************************************* */
diff --git a/gtsam/geometry/Cal3DS2.h b/gtsam/geometry/Cal3DS2.h
index 595247249..dcb596d70 100644
--- a/gtsam/geometry/Cal3DS2.h
+++ b/gtsam/geometry/Cal3DS2.h
@@ -22,72 +22,69 @@
namespace gtsam {
- /**
- * @brief Calibration of a camera with radial distortion
- * @ingroup geometry
- */
- class Cal3DS2 {
- private:
- double fx_, fy_, s_, u0_, v0_ ; // focal length, skew and principal point
- double k1_, k2_ ; // radial 2nd-order and 4th-order
- double k3_, k4_ ; // tagential distortion
+/**
+ * @brief Calibration of a camera with radial distortion
+ * @ingroup geometry
+ */
+class Cal3DS2 {
+private:
+ double fx_, fy_, s_, u0_, v0_ ; // focal length, skew and principal point
+ double k1_, k2_ ; // radial 2nd-order and 4th-order
+ double k3_, k4_ ; // tagential distortion
- // K = [ fx s u0 ; 0 fy v0 ; 0 0 1 ]
- // r = Pn.x^2 + Pn.y^2
- // \hat{pn} = (1 + k1*r + k2*r^2 ) pn + [ 2*k3 pn.x pn.y + k4 (r + 2 Pn.x^2) ;
- // k3 (r + 2 Pn.y^2) + 2*k4 pn.x pn.y ]
- // pi = K*pn
+ // K = [ fx s u0 ; 0 fy v0 ; 0 0 1 ]
+ // r = Pn.x^2 + Pn.y^2
+ // \hat{pn} = (1 + k1*r + k2*r^2 ) pn + [ 2*k3 pn.x pn.y + k4 (r + 2 Pn.x^2) ;
+ // k3 (r + 2 Pn.y^2) + 2*k4 pn.x pn.y ]
+ // pi = K*pn
- public:
- // Default Constructor with only unit focal length
- Cal3DS2();
+public:
+ // Default Constructor with only unit focal length
+ Cal3DS2();
- // Construction
- Cal3DS2(double fx, double fy, double s, double u0, double v0,
- double k1, double k2, double k3, double k4) ;
+ // Construction
+ Cal3DS2(double fx, double fy, double s, double u0, double v0,
+ double k1, double k2, double k3, double k4) ;
- Cal3DS2(const Vector &v) ;
+ Cal3DS2(const Vector &v) ;
- Matrix K() const ;
- Vector k() const ;
- Vector vector() const ;
- void print(const std::string& s = "") const ;
- bool equals(const Cal3DS2& K, double tol = 10e-9) const;
+ Matrix K() const ;
+ Vector k() const ;
+ Vector vector() const ;
+ void print(const std::string& s = "") const ;
+ bool equals(const Cal3DS2& K, double tol = 10e-9) const;
- Point2 uncalibrate(const Point2& p,
- boost::optional H1 = boost::none,
- boost::optional H2 = boost::none) const ;
+ Point2 uncalibrate(const Point2& p,
+ boost::optional H1 = boost::none,
+ boost::optional H2 = boost::none) const ;
- Matrix D2d_intrinsic(const Point2& p) const ;
- Matrix D2d_calibration(const Point2& p) const ;
+ Matrix D2d_intrinsic(const Point2& p) const ;
+ Matrix D2d_calibration(const Point2& p) const ;
- Cal3DS2 expmap(const Vector& d) const ;
- Vector logmap(const Cal3DS2& T2) const ;
+ Cal3DS2 retract(const Vector& d) const ;
+ Vector localCoordinates(const Cal3DS2& T2) const ;
- static Cal3DS2 Expmap(const Vector& v) ;
- static Vector Logmap(const Cal3DS2& p) ;
+ int dim() const { return 9 ; }
+ static size_t Dim() { return 9; }
- int dim() const { return 9 ; }
- static size_t Dim() { return 9; }
+private:
+ /** Serialization function */
+ friend class boost::serialization::access;
+ template
+ void serialize(Archive & ar, const unsigned int version)
+ {
+ ar & BOOST_SERIALIZATION_NVP(fx_);
+ ar & BOOST_SERIALIZATION_NVP(fy_);
+ ar & BOOST_SERIALIZATION_NVP(s_);
+ ar & BOOST_SERIALIZATION_NVP(u0_);
+ ar & BOOST_SERIALIZATION_NVP(v0_);
+ ar & BOOST_SERIALIZATION_NVP(k1_);
+ ar & BOOST_SERIALIZATION_NVP(k2_);
+ ar & BOOST_SERIALIZATION_NVP(k3_);
+ ar & BOOST_SERIALIZATION_NVP(k4_);
+ }
- private:
- /** Serialization function */
- friend class boost::serialization::access;
- template
- void serialize(Archive & ar, const unsigned int version)
- {
- ar & BOOST_SERIALIZATION_NVP(fx_);
- ar & BOOST_SERIALIZATION_NVP(fy_);
- ar & BOOST_SERIALIZATION_NVP(s_);
- ar & BOOST_SERIALIZATION_NVP(u0_);
- ar & BOOST_SERIALIZATION_NVP(v0_);
- ar & BOOST_SERIALIZATION_NVP(k1_);
- ar & BOOST_SERIALIZATION_NVP(k2_);
- ar & BOOST_SERIALIZATION_NVP(k3_);
- ar & BOOST_SERIALIZATION_NVP(k4_);
- }
-
- };
+};
}
diff --git a/gtsam/geometry/Cal3_S2.h b/gtsam/geometry/Cal3_S2.h
index d2235e699..e78b1d418 100644
--- a/gtsam/geometry/Cal3_S2.h
+++ b/gtsam/geometry/Cal3_S2.h
@@ -129,12 +129,12 @@ namespace gtsam {
}
/// Given 5-dim tangent vector, create new calibration
- inline Cal3_S2 expmap(const Vector& d) const {
+ inline Cal3_S2 retract(const Vector& d) const {
return Cal3_S2(fx_ + d(0), fy_ + d(1), s_ + d(2), u0_ + d(3), v0_ + d(4));
}
- /// logmap for the calibration
- Vector logmap(const Cal3_S2& T2) const {
+ /// Unretraction for the calibration
+ Vector localCoordinates(const Cal3_S2& T2) const {
return vector() - T2.vector();
}
diff --git a/gtsam/geometry/CalibratedCamera.cpp b/gtsam/geometry/CalibratedCamera.cpp
index 6b528b51a..f0c70408e 100644
--- a/gtsam/geometry/CalibratedCamera.cpp
+++ b/gtsam/geometry/CalibratedCamera.cpp
@@ -21,77 +21,73 @@
namespace gtsam {
- CalibratedCamera::CalibratedCamera() {}
+/* ************************************************************************* */
+CalibratedCamera::CalibratedCamera(const Pose3& pose) :
+ pose_(pose) {
+}
- CalibratedCamera::CalibratedCamera(const Pose3& pose) :
- pose_(pose) {
+/* ************************************************************************* */
+CalibratedCamera::CalibratedCamera(const Vector &v) : pose_(Pose3::Expmap(v)) {}
+
+/* ************************************************************************* */
+Point2 CalibratedCamera::project_to_camera(const Point3& P, boost::optional 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);
}
+ return Point2(P.x() / P.z(), P.y() / P.z());
+}
- CalibratedCamera::CalibratedCamera(const Vector &v) : pose_(Pose3::Expmap(v)) {}
+/* ************************************************************************* */
+Point3 CalibratedCamera::backproject_from_camera(const Point2& p, const double scale) {
+ return Point3(p.x() * scale, p.y() * scale, scale);
+}
- CalibratedCamera::~CalibratedCamera() {}
+/* ************************************************************************* */
+CalibratedCamera CalibratedCamera::level(const Pose2& pose2, double height) {
+ double st = sin(pose2.theta()), ct = cos(pose2.theta());
+ Point3 x(st, -ct, 0), y(0, 0, -1), z(ct, st, 0);
+ Rot3 wRc(x, y, z);
+ Point3 t(pose2.x(), pose2.y(), height);
+ Pose3 pose3(wRc, t);
+ return CalibratedCamera(pose3);
+}
- Point2 CalibratedCamera::project_to_camera(const Point3& P, boost::optional 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);
- }
- return Point2(P.x() / P.z(), P.y() / P.z());
+/* ************************************************************************* */
+Point2 CalibratedCamera::project(const Point3& point,
+ boost::optional D_intrinsic_pose,
+ boost::optional D_intrinsic_point) const {
+ const Pose3& pose = pose_;
+ const Rot3& R = pose.rotation();
+ const Point3& r1 = R.r1(), r2 = R.r2(), r3 = R.r3();
+ Point3 q = pose.transform_to(point);
+
+ if (D_intrinsic_pose || D_intrinsic_point) {
+ double X = q.x(), Y = q.y(), Z = q.z();
+ double d = 1.0 / Z, d2 = d * d, Xd2 = X*d2, Yd2 = Y*d2;
+ double dp11 = d*r1.x()-r3.x()*Xd2, dp12 = d*r1.y()-r3.y()*Xd2, dp13 = d*r1.z()-r3.z()*Xd2;
+ double dp21 = d*r2.x()-r3.x()*Yd2, dp22 = d*r2.y()-r3.y()*Yd2, dp23 = d*r2.z()-r3.z()*Yd2;
+ if (D_intrinsic_pose)
+ *D_intrinsic_pose = Matrix_(2,6,
+ X*Yd2, -Z*d-X*Xd2, d*Y, -dp11, -dp12, -dp13,
+ d*Z+Y*Yd2, -X*Yd2, -d*X, -dp21, -dp22, -dp23);
+ if (D_intrinsic_point)
+ *D_intrinsic_point = Matrix_(2,3,
+ dp11, dp12, dp13,
+ dp21, dp22, dp23);
}
+ return project_to_camera(q);
+}
- Point3 CalibratedCamera::backproject_from_camera(const Point2& p, const double scale) {
- return Point3(p.x() * scale, p.y() * scale, scale);
- }
+/* ************************************************************************* */
+CalibratedCamera CalibratedCamera::retract(const Vector& d) const {
+ return CalibratedCamera(pose().retract(d)) ;
+}
- CalibratedCamera CalibratedCamera::level(const Pose2& pose2, double height) {
- double st = sin(pose2.theta()), ct = cos(pose2.theta());
- Point3 x(st, -ct, 0), y(0, 0, -1), z(ct, st, 0);
- Rot3 wRc(x, y, z);
- Point3 t(pose2.x(), pose2.y(), height);
- Pose3 pose3(wRc, t);
- return CalibratedCamera(pose3);
- }
-
- Point2 CalibratedCamera::project(const Point3& point,
- boost::optional D_intrinsic_pose,
- boost::optional D_intrinsic_point) const {
- const Pose3& pose = pose_;
- const Rot3& R = pose.rotation();
- const Point3& r1 = R.r1(), r2 = R.r2(), r3 = R.r3();
- Point3 q = pose.transform_to(point);
-
- if (D_intrinsic_pose || D_intrinsic_point) {
- double X = q.x(), Y = q.y(), Z = q.z();
- double d = 1.0 / Z, d2 = d * d, Xd2 = X*d2, Yd2 = Y*d2;
- double dp11 = d*r1.x()-r3.x()*Xd2, dp12 = d*r1.y()-r3.y()*Xd2, dp13 = d*r1.z()-r3.z()*Xd2;
- double dp21 = d*r2.x()-r3.x()*Yd2, dp22 = d*r2.y()-r3.y()*Yd2, dp23 = d*r2.z()-r3.z()*Yd2;
- if (D_intrinsic_pose)
- *D_intrinsic_pose = Matrix_(2,6,
- X*Yd2, -Z*d-X*Xd2, d*Y, -dp11, -dp12, -dp13,
- d*Z+Y*Yd2, -X*Yd2, -d*X, -dp21, -dp22, -dp23);
- if (D_intrinsic_point)
- *D_intrinsic_point = Matrix_(2,3,
- dp11, dp12, dp13,
- dp21, dp22, dp23);
- }
- return project_to_camera(q);
- }
-
-
- CalibratedCamera CalibratedCamera::expmap(const Vector& d) const {
- return CalibratedCamera(pose().expmap(d)) ;
- }
- Vector CalibratedCamera::logmap(const CalibratedCamera& T2) const {
- return pose().logmap(T2.pose()) ;
- }
-
- CalibratedCamera CalibratedCamera::Expmap(const Vector& v) {
- return CalibratedCamera(Pose3::Expmap(v)) ;
- }
-
- Vector CalibratedCamera::Logmap(const CalibratedCamera& p) {
- return Pose3::Logmap(p.pose()) ;
- }
+/* ************************************************************************* */
+Vector CalibratedCamera::localCoordinates(const CalibratedCamera& T2) const {
+ return pose().localCoordinates(T2.pose()) ;
+}
/* ************************************************************************* */
}
diff --git a/gtsam/geometry/CalibratedCamera.h b/gtsam/geometry/CalibratedCamera.h
index a7d11d13e..880bb9316 100644
--- a/gtsam/geometry/CalibratedCamera.h
+++ b/gtsam/geometry/CalibratedCamera.h
@@ -34,10 +34,10 @@ namespace gtsam {
Pose3 pose_; // 6DOF pose
public:
- CalibratedCamera(); ///< default constructor
+ CalibratedCamera() {} ///< default constructor
CalibratedCamera(const Pose3& pose); ///< construct with pose
CalibratedCamera(const Vector &v) ; ///< construct from vector
- virtual ~CalibratedCamera(); ///< destructor
+ virtual ~CalibratedCamera() {} ///< destructor
/// return pose
inline const Pose3& pose() const { return pose_; }
@@ -58,16 +58,10 @@ namespace gtsam {
}
/// move a cameras pose according to d
- CalibratedCamera expmap(const Vector& d) const;
+ CalibratedCamera retract(const Vector& d) const;
/// Return canonical coordinate
- Vector logmap(const CalibratedCamera& T2) const;
-
- /// move a cameras pose according to d
- static CalibratedCamera Expmap(const Vector& v);
-
- /// Return canonical coordinate
- static Vector Logmap(const CalibratedCamera& p);
+ Vector localCoordinates(const CalibratedCamera& T2) const;
/// Lie group dimensionality
inline size_t dim() const { return 6 ; }
diff --git a/gtsam/geometry/CalibratedCameraT.h b/gtsam/geometry/CalibratedCameraT.h
index c432364e6..bfc622851 100644
--- a/gtsam/geometry/CalibratedCameraT.h
+++ b/gtsam/geometry/CalibratedCameraT.h
@@ -17,6 +17,7 @@ namespace gtsam {
* A Calibrated camera class [R|-R't], calibration K.
* If calibration is known, it is more computationally efficient
* to calibrate the measurements rather than try to predict in pixels.
+ * AGC: Is this used or tested anywhere?
* @ingroup geometry
*/
template
@@ -49,11 +50,11 @@ namespace gtsam {
return CalibratedCameraT( pose_.inverse(), k_ ) ;
}
- CalibratedCameraT expmap(const Vector& d) const {
- return CalibratedCameraT(pose().expmap(d), k_) ;
+ CalibratedCameraT retract(const Vector& d) const {
+ return CalibratedCameraT(pose().retract(d), k_) ;
}
- Vector logmap(const CalibratedCameraT& T2) const {
- return pose().logmap(T2.pose()) ;
+ Vector localCoordinates(const CalibratedCameraT& T2) const {
+ return pose().localCoordinates(T2.pose()) ;
}
void print(const std::string& s = "") const {
diff --git a/gtsam/geometry/GeneralCameraT.h b/gtsam/geometry/GeneralCameraT.h
index 6ec87e0d8..61d82b62b 100644
--- a/gtsam/geometry/GeneralCameraT.h
+++ b/gtsam/geometry/GeneralCameraT.h
@@ -32,181 +32,164 @@ namespace gtsam {
template
class GeneralCameraT {
- private:
- Camera calibrated_; // Calibrated camera
- Calibration calibration_; // Calibration
+private:
+ Camera calibrated_; // Calibrated camera
+ Calibration calibration_; // Calibration
- public:
- GeneralCameraT(){}
- GeneralCameraT(const Camera& calibrated, const Calibration& K) : calibrated_(calibrated), calibration_(K) {}
- GeneralCameraT(const Camera& calibrated ) : calibrated_(calibrated) {}
- GeneralCameraT(const Pose3& pose, const Calibration& K) : calibrated_(pose), calibration_(K) {}
- GeneralCameraT(const Pose3& pose) : calibrated_(pose) {}
- GeneralCameraT(const Pose3& pose, const Vector &v) : calibrated_(pose), calibration_(v) {}
+public:
+ GeneralCameraT(){}
+ GeneralCameraT(const Camera& calibrated, const Calibration& K) : calibrated_(calibrated), calibration_(K) {}
+ GeneralCameraT(const Camera& calibrated ) : calibrated_(calibrated) {}
+ GeneralCameraT(const Pose3& pose, const Calibration& K) : calibrated_(pose), calibration_(K) {}
+ GeneralCameraT(const Pose3& pose) : calibrated_(pose) {}
+ GeneralCameraT(const Pose3& pose, const Vector &v) : calibrated_(pose), calibration_(v) {}
- // Vector Initialization
- GeneralCameraT(const Vector &v) :
- calibrated_(sub(v, 0, Camera::Dim())),
- calibration_(sub(v, Camera::Dim(), Camera::Dim() + Calibration::Dim() )) {}
+ // Vector Initialization
+ GeneralCameraT(const Vector &v) :
+ calibrated_(sub(v, 0, Camera::Dim())),
+ calibration_(sub(v, Camera::Dim(), Camera::Dim() + Calibration::Dim() )) {}
- inline const Pose3& pose() const { return calibrated_.pose(); }
- inline const Camera& calibrated() const { return calibrated_; }
- inline const Calibration& calibration() const { return calibration_; }
+ inline const Pose3& pose() const { return calibrated_.pose(); }
+ inline const Camera& calibrated() const { return calibrated_; }
+ inline const Calibration& calibration() const { return calibration_; }
- std::pair projectSafe(
- const Point3& P,
- boost::optional H1 = boost::none,
- boost::optional H2 = boost::none) const {
+ std::pair projectSafe(
+ const Point3& P,
+ boost::optional H1 = boost::none,
+ boost::optional H2 = boost::none) const {
- Point3 cameraPoint = calibrated_.pose().transform_to(P);
- return std::pair(
- project(P,H1,H2),
- cameraPoint.z() > 0);
+ Point3 cameraPoint = calibrated_.pose().transform_to(P);
+ return std::pair(
+ project(P,H1,H2),
+ cameraPoint.z() > 0);
+ }
+
+ Point3 backproject(const Point2& projection, const double scale) const {
+ Point2 intrinsic = calibration_.calibrate(projection);
+ Point3 cameraPoint = CalibratedCamera::backproject_from_camera(intrinsic, scale);
+ return calibrated_.pose().transform_from(cameraPoint);
+ }
+
+ /**
+ * project function that does not merge the Jacobians of calibration and pose
+ */
+ Point2 project(const Point3& P, Matrix& H1_pose, Matrix& H1_k, Matrix& H2_pt) const {
+ Matrix tmp;
+ Point2 intrinsic = calibrated_.project(P, H1_pose, H2_pt);
+ Point2 projection = calibration_.uncalibrate(intrinsic, H1_k, tmp);
+ H1_pose = tmp * H1_pose;
+ H2_pt = tmp * H2_pt;
+ return projection;
+ }
+
+ /**
+ * project a 3d point to the camera
+ * P is point in camera coordinate
+ * H1 is respect to pose + calibration
+ * H2 is respect to landmark
+ */
+ Point2 project(const Point3& P,
+ boost::optional H1 = boost::none,
+ boost::optional H2 = boost::none) const {
+
+ if (!H1 && !H2) {
+ Point2 intrinsic = calibrated_.project(P);
+ return calibration_.uncalibrate(intrinsic) ;
}
- Point3 backproject(const Point2& projection, const double scale) const {
- Point2 intrinsic = calibration_.calibrate(projection);
- Point3 cameraPoint = CalibratedCamera::backproject_from_camera(intrinsic, scale);
- return calibrated_.pose().transform_from(cameraPoint);
- }
+ Matrix H1_k, H1_pose, H2_pt;
+ Point2 projection = project(P, H1_pose, H1_k, H2_pt);
+ if ( H1 ) *H1 = collect(2, &H1_pose, &H1_k);
+ if ( H2 ) *H2 = H2_pt;
- /**
- * project function that does not merge the Jacobians of calibration and pose
- */
- Point2 project(const Point3& P, Matrix& H1_pose, Matrix& H1_k, Matrix& H2_pt) const {
- Matrix tmp;
- Point2 intrinsic = calibrated_.project(P, H1_pose, H2_pt);
- Point2 projection = calibration_.uncalibrate(intrinsic, H1_k, tmp);
- H1_pose = tmp * H1_pose;
- H2_pt = tmp * H2_pt;
- return projection;
- }
+ return projection;
+ }
- /**
- * project a 3d point to the camera
- * P is point in camera coordinate
- * H1 is respect to pose + calibration
- * H2 is respect to landmark
- */
- Point2 project(const Point3& P,
- boost::optional H1 = boost::none,
- boost::optional H2 = boost::none) const {
+ // dump functions for compilation for now
+ bool equals (const GeneralCameraT &camera, double tol = 1e-9) const {
+ return calibrated_.equals(camera.calibrated_, tol) &&
+ calibration_.equals(camera.calibration_, tol) ;
+ }
- if (!H1 && !H2) {
- Point2 intrinsic = calibrated_.project(P);
- return calibration_.uncalibrate(intrinsic) ;
- }
+ void print(const std::string& s = "") const {
+ calibrated_.pose().print(s + ".camera.") ;
+ calibration_.print(s + ".calibration.") ;
+ }
- Matrix H1_k, H1_pose, H2_pt;
- Point2 projection = project(P, H1_pose, H1_k, H2_pt);
- if ( H1 ) *H1 = collect(2, &H1_pose, &H1_k);
- if ( H2 ) *H2 = H2_pt;
+ GeneralCameraT retract(const Vector &v) const {
+ Vector v1 = sub(v,0,Camera::Dim());
+ Vector v2 = sub(v,Camera::Dim(),Camera::Dim()+Calibration::Dim());
+ return GeneralCameraT(calibrated_.retract(v1), calibration_.retract(v2));
+ }
- return projection;
- }
+ Vector localCoordinates(const GeneralCameraT &C) const {
+ const Vector v1(calibrated().localCoordinates(C.calibrated())),
+ v2(calibration().localCoordinates(C.calibration()));
+ return concatVectors(2,&v1,&v2) ;
+ }
- // dump functions for compilation for now
- bool equals (const GeneralCameraT &camera, double tol = 1e-9) const {
- return calibrated_.equals(camera.calibrated_, tol) &&
- calibration_.equals(camera.calibration_, tol) ;
- }
+ inline GeneralCameraT compose(const Pose3 &p) const {
+ return GeneralCameraT( pose().compose(p), calibration_ ) ;
+ }
- void print(const std::string& s = "") const {
- calibrated_.pose().print(s + ".camera.") ;
- calibration_.print(s + ".calibration.") ;
- }
+ Matrix D2d_camera(const Point3& point) const {
+ Point2 intrinsic = calibrated_.project(point);
+ Matrix D_intrinsic_pose = Dproject_pose(calibrated_, point);
+ Matrix D_2d_intrinsic = calibration_.D2d_intrinsic(intrinsic);
+ Matrix D_2d_pose = D_2d_intrinsic * D_intrinsic_pose;
+ Matrix D_2d_calibration = calibration_.D2d_calibration(intrinsic);
- GeneralCameraT expmap(const Vector &v) const {
- Vector v1 = sub(v,0,Camera::Dim());
- Vector v2 = sub(v,Camera::Dim(),Camera::Dim()+Calibration::Dim());
- return GeneralCameraT(calibrated_.expmap(v1), calibration_.expmap(v2));
- }
+ const int n1 = calibrated_.dim() ;
+ const int n2 = calibration_.dim() ;
+ Matrix D(2,n1+n2) ;
- Vector logmap(const GeneralCameraT &C) const {
- //std::cout << "logmap" << std::endl;
- const Vector v1(calibrated().logmap(C.calibrated())),
- v2(calibration().logmap(C.calibration()));
- return concatVectors(2,&v1,&v2) ;
- }
+ sub(D,0,2,0,n1) = D_2d_pose ;
+ sub(D,0,2,n1,n1+n2) = D_2d_calibration ;
+ return D;
+ }
- static GeneralCameraT Expmap(const Vector& v) {
- //std::cout << "Expmap" << std::endl;
- return GeneralCameraT(
- Camera::Expmap(sub(v,0,Camera::Dim())),
- Calibration::Expmap(sub(v,Camera::Dim(), Camera::Dim()+Calibration::Dim()))
- );
- }
+ Matrix D2d_3d(const Point3& point) const {
+ Point2 intrinsic = calibrated_.project(point);
+ Matrix D_intrinsic_3d = Dproject_point(calibrated_, point);
+ Matrix D_2d_intrinsic = calibration_.D2d_intrinsic(intrinsic);
+ return D_2d_intrinsic * D_intrinsic_3d;
+ }
- static Vector Logmap(const GeneralCameraT& p) {
- //std::cout << "Logmap" << std::endl;
- const Vector v1(Camera::Logmap(p.calibrated())),
- v2(Calibration::Logmap(p.calibration()));
- return concatVectors(2,&v1,&v2);
+ Matrix D2d_camera_3d(const Point3& point) const {
+ Point2 intrinsic = calibrated_.project(point);
+ Matrix D_intrinsic_pose = Dproject_pose(calibrated_, point);
+ Matrix D_2d_intrinsic = calibration_.D2d_intrinsic(intrinsic);
+ Matrix D_2d_pose = D_2d_intrinsic * D_intrinsic_pose;
+ Matrix D_2d_calibration = calibration_.D2d_calibration(intrinsic);
- }
+ Matrix D_intrinsic_3d = Dproject_point(calibrated_, point);
+ Matrix D_2d_3d = D_2d_intrinsic * D_intrinsic_3d;
- inline GeneralCameraT compose(const Pose3 &p) const {
- return GeneralCameraT( pose().compose(p), calibration_ ) ;
- }
+ const int n1 = calibrated_.dim() ;
+ const int n2 = calibration_.dim() ;
- Matrix D2d_camera(const Point3& point) const {
- Point2 intrinsic = calibrated_.project(point);
- Matrix D_intrinsic_pose = Dproject_pose(calibrated_, point);
- Matrix D_2d_intrinsic = calibration_.D2d_intrinsic(intrinsic);
- Matrix D_2d_pose = D_2d_intrinsic * D_intrinsic_pose;
- Matrix D_2d_calibration = calibration_.D2d_calibration(intrinsic);
+ Matrix D(2,n1+n2+3) ;
- const int n1 = calibrated_.dim() ;
- const int n2 = calibration_.dim() ;
- Matrix D(2,n1+n2) ;
+ sub(D,0,2,0,n1) = D_2d_pose ;
+ sub(D,0,2,n1,n1+n2) = D_2d_calibration ;
+ sub(D,0,2,n1+n2,n1+n2+3) = D_2d_3d ;
+ return D;
+ }
- sub(D,0,2,0,n1) = D_2d_pose ;
- sub(D,0,2,n1,n1+n2) = D_2d_calibration ;
- return D;
- }
-
- Matrix D2d_3d(const Point3& point) const {
- Point2 intrinsic = calibrated_.project(point);
- Matrix D_intrinsic_3d = Dproject_point(calibrated_, point);
- Matrix D_2d_intrinsic = calibration_.D2d_intrinsic(intrinsic);
- return D_2d_intrinsic * D_intrinsic_3d;
- }
-
- Matrix D2d_camera_3d(const Point3& point) const {
- Point2 intrinsic = calibrated_.project(point);
- Matrix D_intrinsic_pose = Dproject_pose(calibrated_, point);
- Matrix D_2d_intrinsic = calibration_.D2d_intrinsic(intrinsic);
- Matrix D_2d_pose = D_2d_intrinsic * D_intrinsic_pose;
- Matrix D_2d_calibration = calibration_.D2d_calibration(intrinsic);
-
- Matrix D_intrinsic_3d = Dproject_point(calibrated_, point);
- Matrix D_2d_3d = D_2d_intrinsic * D_intrinsic_3d;
-
- const int n1 = calibrated_.dim() ;
- const int n2 = calibration_.dim() ;
-
- Matrix D(2,n1+n2+3) ;
-
- sub(D,0,2,0,n1) = D_2d_pose ;
- sub(D,0,2,n1,n1+n2) = D_2d_calibration ;
- sub(D,0,2,n1+n2,n1+n2+3) = D_2d_3d ;
- return D;
- }
-
- //inline size_t dim() { return Camera::dim() + Calibration::dim() ; }
- inline size_t dim() const { return calibrated().dim() + calibration().dim() ; }
- static inline size_t Dim() { return Camera::Dim() + Calibration::Dim() ; }
+ //inline size_t dim() { return Camera::dim() + Calibration::dim() ; }
+ inline size_t dim() const { return calibrated().dim() + calibration().dim() ; }
+ static inline size_t Dim() { return Camera::Dim() + Calibration::Dim() ; }
private:
- friend class boost::serialization::access;
- template
- void serialize(Archive & ar, const unsigned int version)
- {
- ar & BOOST_SERIALIZATION_NVP(calibrated_);
- ar & BOOST_SERIALIZATION_NVP(calibration_);
- }
+ friend class boost::serialization::access;
+ template
+ void serialize(Archive & ar, const unsigned int version)
+ {
+ ar & BOOST_SERIALIZATION_NVP(calibrated_);
+ ar & BOOST_SERIALIZATION_NVP(calibration_);
+ }
- };
+};
typedef GeneralCameraT Cal3BundlerCamera;
typedef GeneralCameraT Cal3DS2Camera;
diff --git a/gtsam/geometry/Makefile.am b/gtsam/geometry/Makefile.am
index 820922d32..e8c7510f4 100644
--- a/gtsam/geometry/Makefile.am
+++ b/gtsam/geometry/Makefile.am
@@ -24,7 +24,7 @@ check_PROGRAMS += tests/testCal3DS2 tests/testCal3_S2 tests/testCal3Bundler test
# Stereo
sources += StereoPoint2.cpp StereoCamera.cpp
-check_PROGRAMS += tests/testStereoCamera
+check_PROGRAMS += tests/testStereoCamera tests/testStereoPoint2
# Tensors
headers += tensors.h Tensor1.h Tensor2.h Tensor3.h Tensor4.h Tensor5.h
diff --git a/gtsam/geometry/Point2.cpp b/gtsam/geometry/Point2.cpp
index ca83dfa8a..0834cdcda 100644
--- a/gtsam/geometry/Point2.cpp
+++ b/gtsam/geometry/Point2.cpp
@@ -22,22 +22,22 @@ using namespace std;
namespace gtsam {
- /** Explicit instantiation of base class to export members */
- INSTANTIATE_LIE(Point2);
+/** Explicit instantiation of base class to export members */
+INSTANTIATE_LIE(Point2);
- /* ************************************************************************* */
- void Point2::print(const string& s) const {
- cout << s << "(" << x_ << ", " << y_ << ")" << endl;
- }
+/* ************************************************************************* */
+void Point2::print(const string& s) const {
+ cout << s << "(" << x_ << ", " << y_ << ")" << endl;
+}
- /* ************************************************************************* */
- bool Point2::equals(const Point2& q, double tol) const {
- return (fabs(x_ - q.x()) < tol && fabs(y_ - q.y()) < tol);
- }
+/* ************************************************************************* */
+bool Point2::equals(const Point2& q, double tol) const {
+ return (fabs(x_ - q.x()) < tol && fabs(y_ - q.y()) < tol);
+}
- /* ************************************************************************* */
- double Point2::norm() const {
- return sqrt(x_*x_ + y_*y_);
- }
+/* ************************************************************************* */
+double Point2::norm() const {
+ return sqrt(x_*x_ + y_*y_);
+}
} // namespace gtsam
diff --git a/gtsam/geometry/Point2.h b/gtsam/geometry/Point2.h
index 0e9acdbf4..5b335f564 100644
--- a/gtsam/geometry/Point2.h
+++ b/gtsam/geometry/Point2.h
@@ -23,112 +23,122 @@
namespace gtsam {
- /**
- * A 2D point
- * Complies with the Testable Concept
- * Functional, so no set functions: once created, a point is constant.
- * @ingroup geometry
- */
- class Point2: public Lie {
- public:
- /// dimension of the variable - used to autodetect sizes
- static const size_t dimension = 2;
- private:
- double x_, y_;
-
- public:
- Point2(): x_(0), y_(0) {}
- Point2(const Point2 &p) : x_(p.x_), y_(p.y_) {}
- Point2(double x, double y): x_(x), y_(y) {}
- Point2(const Vector& v) : x_(v(0)), y_(v(1)) { assert(v.size() == 2); }
+/**
+ * A 2D point
+ * Complies with the Testable Concept
+ * Functional, so no set functions: once created, a point is constant.
+ * @ingroup geometry
+ */
+class Point2 {
+public:
+ /// dimension of the variable - used to autodetect sizes
+ static const size_t dimension = 2;
+private:
+ double x_, y_;
- /** dimension of the variable - used to autodetect sizes */
- inline static size_t Dim() { return dimension; }
+public:
+ Point2(): x_(0), y_(0) {}
+ Point2(const Point2 &p) : x_(p.x_), y_(p.y_) {}
+ Point2(double x, double y): x_(x), y_(y) {}
+ Point2(const Vector& v) : x_(v(0)), y_(v(1)) { assert(v.size() == 2); }
- /** print with optional string */
- void print(const std::string& s = "") const;
+ /** dimension of the variable - used to autodetect sizes */
+ inline static size_t Dim() { return dimension; }
- /** equals with an tolerance, prints out message if unequal*/
- bool equals(const Point2& q, double tol = 1e-9) const;
+ /** print with optional string */
+ void print(const std::string& s = "") const;
- /** Lie requirements */
+ /** equals with an tolerance, prints out message if unequal*/
+ bool equals(const Point2& q, double tol = 1e-9) const;
- /** Size of the tangent space of the Lie type */
- inline size_t dim() const { return dimension; }
+ // Group requirements
- /** "Compose", just adds the coordinates of two points. With optional derivatives */
- inline Point2 compose(const Point2& p2,
- boost::optional H1=boost::none,
- boost::optional H2=boost::none) const {
- if(H1) *H1 = eye(2);
- if(H2) *H2 = eye(2);
- return *this + p2;
- }
+ /** "Compose", just adds the coordinates of two points. With optional derivatives */
+ inline Point2 compose(const Point2& p2,
+ boost::optional H1=boost::none,
+ boost::optional H2=boost::none) const {
+ if(H1) *H1 = eye(2);
+ if(H2) *H2 = eye(2);
+ return *this + p2;
+ }
- /** "Inverse" - negates each coordinate such that compose(p,inverse(p))=Point2() */
- inline Point2 inverse() const { return Point2(-x_, -y_); }
+ /** identity */
+ inline static Point2 identity() {
+ return Point2();
+ }
- /** Binary expmap - just adds the points */
- inline Point2 expmap(const Vector& v) const { return *this + Point2(v); }
+ /** "Inverse" - negates each coordinate such that compose(p,inverse(p))=Point2() */
+ inline Point2 inverse() const { return Point2(-x_, -y_); }
- /** Binary Logmap - just subtracts the points */
- inline Vector logmap(const Point2& p2) const { return Logmap(between(p2));}
+ // Manifold requirements
- /** Exponential map around identity - just create a Point2 from a vector */
- static inline Point2 Expmap(const Vector& v) { return Point2(v); }
+ /** Size of the tangent space */
+ inline size_t dim() const { return dimension; }
- /** Log map around identity - just return the Point2 as a vector */
- static inline Vector Logmap(const Point2& dp) { return Vector_(2, dp.x(), dp.y()); }
+ /** Updates a with tangent space delta */
+ inline Point2 retract(const Vector& v) const { return *this + Point2(v); }
- /** "Between", subtracts point coordinates */
- inline Point2 between(const Point2& p2,
- boost::optional H1=boost::none,
- boost::optional H2=boost::none) const {
- if(H1) *H1 = -eye(2);
- if(H2) *H2 = eye(2);
- return p2 - (*this);
- }
+ /// Local coordinates of manifold neighborhood around current value
+ inline Vector localCoordinates(const Point2& t2) const { return Logmap(between(t2)); }
- /** get functions for x, y */
- double x() const {return x_;}
- double y() const {return y_;}
+ /** Lie requirements */
- /** return vectorized form (column-wise) */
- Vector vector() const { return Vector_(2, x_, y_); }
+ /** Exponential map around identity - just create a Point2 from a vector */
+ static inline Point2 Expmap(const Vector& v) { return Point2(v); }
- /** operators */
- inline void operator += (const Point2& q) {x_+=q.x_;y_+=q.y_;}
- inline void operator *= (double s) {x_*=s;y_*=s;}
- inline bool operator ==(const Point2& q) const {return x_==q.x_ && q.y_==q.y_;}
- inline Point2 operator- () const {return Point2(-x_,-y_);}
- inline Point2 operator + (const Point2& q) const {return Point2(x_+q.x_,y_+q.y_);}
- inline Point2 operator - (const Point2& q) const {return Point2(x_-q.x_,y_-q.y_);}
- inline Point2 operator * (double s) const {return Point2(x_*s,y_*s);}
- inline Point2 operator / (double q) const {return Point2(x_/q,y_/q);}
+ /** Log map around identity - just return the Point2 as a vector */
+ static inline Vector Logmap(const Point2& dp) { return Vector_(2, dp.x(), dp.y()); }
- /** norm of point */
- double norm() const;
- /** creates a unit vector */
- Point2 unit() const { return *this/norm(); }
+ /** "Between", subtracts point coordinates */
+ inline Point2 between(const Point2& p2,
+ boost::optional H1=boost::none,
+ boost::optional H2=boost::none) const {
+ if(H1) *H1 = -eye(2);
+ if(H2) *H2 = eye(2);
+ return p2 - (*this);
+ }
- /** distance between two points */
- inline double dist(const Point2& p2) const {
- return (p2 - *this).norm();
- }
+ /** get functions for x, y */
+ double x() const {return x_;}
+ double y() const {return y_;}
- private:
- /** Serialization function */
- friend class boost::serialization::access;
- template
- void serialize(ARCHIVE & ar, const unsigned int version)
- {
- ar & BOOST_SERIALIZATION_NVP(x_);
- ar & BOOST_SERIALIZATION_NVP(y_);
- }
- };
+ /** return vectorized form (column-wise) */
+ Vector vector() const { return Vector_(2, x_, y_); }
- /** multiply with scalar */
- inline Point2 operator*(double s, const Point2& p) {return p*s;}
+ /** operators */
+ inline void operator += (const Point2& q) {x_+=q.x_;y_+=q.y_;}
+ inline void operator *= (double s) {x_*=s;y_*=s;}
+ inline bool operator ==(const Point2& q) const {return x_==q.x_ && q.y_==q.y_;}
+ inline Point2 operator- () const {return Point2(-x_,-y_);}
+ inline Point2 operator + (const Point2& q) const {return Point2(x_+q.x_,y_+q.y_);}
+ inline Point2 operator - (const Point2& q) const {return Point2(x_-q.x_,y_-q.y_);}
+ inline Point2 operator * (double s) const {return Point2(x_*s,y_*s);}
+ inline Point2 operator / (double q) const {return Point2(x_/q,y_/q);}
+
+ /** norm of point */
+ double norm() const;
+
+ /** creates a unit vector */
+ Point2 unit() const { return *this/norm(); }
+
+ /** distance between two points */
+ inline double dist(const Point2& p2) const {
+ return (p2 - *this).norm();
+ }
+
+private:
+ /** Serialization function */
+ friend class boost::serialization::access;
+ template
+ void serialize(ARCHIVE & ar, const unsigned int version)
+ {
+ ar & BOOST_SERIALIZATION_NVP(x_);
+ ar & BOOST_SERIALIZATION_NVP(y_);
+ }
+};
+
+/** multiply with scalar */
+inline Point2 operator*(double s, const Point2& p) {return p*s;}
}
diff --git a/gtsam/geometry/Point3.cpp b/gtsam/geometry/Point3.cpp
index 9573cc187..c9f89d83c 100644
--- a/gtsam/geometry/Point3.cpp
+++ b/gtsam/geometry/Point3.cpp
@@ -20,71 +20,71 @@
namespace gtsam {
- /** Explicit instantiation of base class to export members */
- INSTANTIATE_LIE(Point3);
+/** Explicit instantiation of base class to export members */
+INSTANTIATE_LIE(Point3);
- /* ************************************************************************* */
- bool Point3::equals(const Point3 & q, double tol) const {
- return (fabs(x_ - q.x()) < tol && fabs(y_ - q.y()) < tol && fabs(z_ - q.z()) < tol);
- }
+/* ************************************************************************* */
+bool Point3::equals(const Point3 & q, double tol) const {
+ return (fabs(x_ - q.x()) < tol && fabs(y_ - q.y()) < tol && fabs(z_ - q.z()) < tol);
+}
- /* ************************************************************************* */
+/* ************************************************************************* */
- void Point3::print(const std::string& s) const {
- std::cout << s << "(" << x_ << ", " << y_ << ", " << z_ << ")" << std::endl;
- }
+void Point3::print(const std::string& s) const {
+ std::cout << s << "(" << x_ << ", " << y_ << ", " << z_ << ")" << std::endl;
+}
- /* ************************************************************************* */
+/* ************************************************************************* */
- bool Point3::operator== (const Point3& q) const {
- return x_ == q.x_ && y_ == q.y_ && z_ == q.z_;
- }
+bool Point3::operator== (const Point3& q) const {
+ return x_ == q.x_ && y_ == q.y_ && z_ == q.z_;
+}
- /* ************************************************************************* */
- Point3 Point3::operator+(const Point3& q) const {
- return Point3( x_ + q.x_, y_ + q.y_, z_ + q.z_ );
- }
+/* ************************************************************************* */
+Point3 Point3::operator+(const Point3& q) const {
+ return Point3( x_ + q.x_, y_ + q.y_, z_ + q.z_ );
+}
- /* ************************************************************************* */
- Point3 Point3::operator- (const Point3& q) const {
- return Point3( x_ - q.x_, y_ - q.y_, z_ - q.z_ );
- }
- /* ************************************************************************* */
- Point3 Point3::operator*(double s) const {
- return Point3(x_ * s, y_ * s, z_ * s);
- }
- /* ************************************************************************* */
- Point3 Point3::operator/(double s) const {
- return Point3(x_ / s, y_ / s, z_ / s);
- }
- /* ************************************************************************* */
- Point3 Point3::add(const Point3 &q,
- boost::optional H1, boost::optional H2) const {
- if (H1) *H1 = eye(3,3);
- if (H2) *H2 = eye(3,3);
- return *this + q;
- }
- /* ************************************************************************* */
- Point3 Point3::sub(const Point3 &q,
- boost::optional H1, boost::optional H2) const {
- if (H1) *H1 = eye(3,3);
- if (H2) *H2 = -eye(3,3);
- return *this - q;
- }
- /* ************************************************************************* */
- Point3 Point3::cross(const Point3 &q) const {
- return Point3( y_*q.z_ - z_*q.y_,
- z_*q.x_ - x_*q.z_,
- x_*q.y_ - y_*q.x_ );
- }
- /* ************************************************************************* */
- double Point3::dot(const Point3 &q) const {
- return ( x_*q.x_ + y_*q.y_ + z_*q.z_ );
- }
- /* ************************************************************************* */
- double Point3::norm() const {
- return sqrt( x_*x_ + y_*y_ + z_*z_ );
- }
- /* ************************************************************************* */
+/* ************************************************************************* */
+Point3 Point3::operator- (const Point3& q) const {
+ return Point3( x_ - q.x_, y_ - q.y_, z_ - q.z_ );
+}
+/* ************************************************************************* */
+Point3 Point3::operator*(double s) const {
+ return Point3(x_ * s, y_ * s, z_ * s);
+}
+/* ************************************************************************* */
+Point3 Point3::operator/(double s) const {
+ return Point3(x_ / s, y_ / s, z_ / s);
+}
+/* ************************************************************************* */
+Point3 Point3::add(const Point3 &q,
+ boost::optional H1, boost::optional H2) const {
+ if (H1) *H1 = eye(3,3);
+ if (H2) *H2 = eye(3,3);
+ return *this + q;
+}
+/* ************************************************************************* */
+Point3 Point3::sub(const Point3 &q,
+ boost::optional H1, boost::optional H2) const {
+ if (H1) *H1 = eye(3,3);
+ if (H2) *H2 = -eye(3,3);
+ return *this - q;
+}
+/* ************************************************************************* */
+Point3 Point3::cross(const Point3 &q) const {
+ return Point3( y_*q.z_ - z_*q.y_,
+ z_*q.x_ - x_*q.z_,
+ x_*q.y_ - y_*q.x_ );
+}
+/* ************************************************************************* */
+double Point3::dot(const Point3 &q) const {
+ return ( x_*q.x_ + y_*q.y_ + z_*q.z_ );
+}
+/* ************************************************************************* */
+double Point3::norm() const {
+ return sqrt( x_*x_ + y_*y_ + z_*z_ );
+}
+/* ************************************************************************* */
} // namespace gtsam
diff --git a/gtsam/geometry/Point3.h b/gtsam/geometry/Point3.h
index 095a2d9fe..2f8c9f8cc 100644
--- a/gtsam/geometry/Point3.h
+++ b/gtsam/geometry/Point3.h
@@ -60,6 +60,11 @@ namespace gtsam {
/** return DOF, dimensionality of tangent space */
inline size_t dim() const { return dimension; }
+ /** identity */
+ inline static Point3 identity() {
+ return Point3();
+ }
+
/** "Inverse" - negates the coordinates such that compose(p, inverse(p)) = Point3() */
inline Point3 inverse() const { return Point3(-x_, -y_, -z_); }
@@ -78,9 +83,14 @@ namespace gtsam {
/** Log map at identity - return the x,y,z of this point */
static inline Vector Logmap(const Point3& dp) { return Vector_(3, dp.x(), dp.y(), dp.z()); }
- /** default implementations of binary functions */
- inline Point3 expmap(const Vector& v) const { return gtsam::expmap_default(*this, v); }
- inline Vector logmap(const Point3& p2) const { return gtsam::logmap_default(*this, p2);}
+ // Manifold requirements
+
+ inline Point3 retract(const Vector& v) const { return compose(Expmap(v)); }
+
+ /**
+ * Returns inverse retraction
+ */
+ inline Vector localCoordinates(const Point3& t2) const { return Logmap(t2) - Logmap(*this); }
/** Between using the default implementation */
inline Point3 between(const Point3& p2,
diff --git a/gtsam/geometry/Pose2.cpp b/gtsam/geometry/Pose2.cpp
index 605163d5d..a15929c67 100644
--- a/gtsam/geometry/Pose2.cpp
+++ b/gtsam/geometry/Pose2.cpp
@@ -25,287 +25,278 @@ using namespace std;
namespace gtsam {
- /** Explicit instantiation of base class to export members */
- INSTANTIATE_LIE(Pose2);
+/** Explicit instantiation of base class to export members */
+INSTANTIATE_LIE(Pose2);
- /** instantiate concept checks */
- GTSAM_CONCEPT_POSE_INST(Pose2);
+/** instantiate concept checks */
+GTSAM_CONCEPT_POSE_INST(Pose2);
- static const Matrix I3 = eye(3), Z12 = zeros(1,2);
- static const Rot2 R_PI_2(Rot2::fromCosSin(0., 1.));
+static const Matrix I3 = eye(3), Z12 = zeros(1,2);
+static const Rot2 R_PI_2(Rot2::fromCosSin(0., 1.));
- /* ************************************************************************* */
- Matrix Pose2::matrix() const {
- Matrix R = r_.matrix();
- R = stack(2, &R, &Z12);
- Matrix T = Matrix_(3,1, t_.x(), t_.y(), 1.0);
- return collect(2, &R, &T);
- }
+/* ************************************************************************* */
+Matrix Pose2::matrix() const {
+ Matrix R = r_.matrix();
+ R = stack(2, &R, &Z12);
+ Matrix T = Matrix_(3,1, t_.x(), t_.y(), 1.0);
+ return collect(2, &R, &T);
+}
- /* ************************************************************************* */
- void Pose2::print(const string& s) const {
- cout << s << "(" << t_.x() << ", " << t_.y() << ", " << r_.theta() << ")" << endl;
- }
+/* ************************************************************************* */
+void Pose2::print(const string& s) const {
+ cout << s << "(" << t_.x() << ", " << t_.y() << ", " << r_.theta() << ")" << endl;
+}
- /* ************************************************************************* */
- bool Pose2::equals(const Pose2& q, double tol) const {
- return t_.equals(q.t_, tol) && r_.equals(q.r_, tol);
- }
+/* ************************************************************************* */
+bool Pose2::equals(const Pose2& q, double tol) const {
+ return t_.equals(q.t_, tol) && r_.equals(q.r_, tol);
+}
- /* ************************************************************************* */
- Pose2 Pose2::ExpmapFull(const Vector& xi) {
- assert(xi.size() == 3);
- Point2 v(xi(0),xi(1));
- double w = xi(2);
- if (std::abs(w) < 1e-10)
- return Pose2(xi[0], xi[1], xi[2]);
- else {
- Rot2 R(Rot2::fromAngle(w));
- Point2 v_ortho = R_PI_2 * v; // points towards rot center
- Point2 t = (v_ortho - R.rotate(v_ortho)) / w;
- return Pose2(R, t);
- }
+/* ************************************************************************* */
+Pose2 Pose2::Expmap(const Vector& xi) {
+ assert(xi.size() == 3);
+ Point2 v(xi(0),xi(1));
+ double w = xi(2);
+ if (std::abs(w) < 1e-10)
+ return Pose2(xi[0], xi[1], xi[2]);
+ else {
+ Rot2 R(Rot2::fromAngle(w));
+ Point2 v_ortho = R_PI_2 * v; // points towards rot center
+ Point2 t = (v_ortho - R.rotate(v_ortho)) / w;
+ return Pose2(R, t);
}
+}
- /* ************************************************************************* */
- Vector Pose2::LogmapFull(const Pose2& p) {
- const Rot2& R = p.r();
- const Point2& t = p.t();
- double w = R.theta();
- if (std::abs(w) < 1e-10)
- return Vector_(3, t.x(), t.y(), w);
- else {
- double c_1 = R.c()-1.0, s = R.s();
- double det = c_1*c_1 + s*s;
- Point2 p = R_PI_2 * (R.unrotate(t) - t);
- Point2 v = (w/det) * p;
- return Vector_(3, v.x(), v.y(), w);
- }
- }
+/* ************************************************************************* */
+Vector Pose2::Logmap(const Pose2& p) {
+ const Rot2& R = p.r();
+ const Point2& t = p.t();
+ double w = R.theta();
+ if (std::abs(w) < 1e-10)
+ return Vector_(3, t.x(), t.y(), w);
+ else {
+ double c_1 = R.c()-1.0, s = R.s();
+ double det = c_1*c_1 + s*s;
+ Point2 p = R_PI_2 * (R.unrotate(t) - t);
+ Point2 v = (w/det) * p;
+ return Vector_(3, v.x(), v.y(), w);
+ }
+}
- /* ************************************************************************* */
+/* ************************************************************************* */
+Pose2 Pose2::retract(const Vector& v) const {
#ifdef SLOW_BUT_CORRECT_EXPMAP
- /* ************************************************************************* */
- // Changes default to use the full verions of expmap/logmap
- /* ************************************************************************* */
- Pose2 Pose2::Expmap(const Vector& xi) {
- return ExpmapFull(xi);
- }
-
- /* ************************************************************************* */
- Vector Pose2::Logmap(const Pose2& p) {
- return LogmapFull(p);
- }
-
+ return compose(Expmap(v));
#else
-
- /* ************************************************************************* */
- Pose2 Pose2::Expmap(const Vector& v) {
- assert(v.size() == 3);
- return Pose2(v[0], v[1], v[2]);
- }
-
- /* ************************************************************************* */
- Vector Pose2::Logmap(const Pose2& p) {
- return Vector_(3, p.x(), p.y(), p.theta());
- }
-
+ assert(v.size() == 3);
+ return compose(Pose2(v[0], v[1], v[2]));
#endif
+}
- /* ************************************************************************* */
- // Calculate Adjoint map
- // Ad_pose is 3*3 matrix that when applied to twist xi, returns Ad_pose(xi)
- Matrix Pose2::AdjointMap() const {
- double c = r_.c(), s = r_.s(), x = t_.x(), y = t_.y();
- return Matrix_(3,3,
- c, -s, y,
- s, c, -x,
- 0.0, 0.0, 1.0
- );
- }
+/* ************************************************************************* */
+Vector Pose2::localCoordinates(const Pose2& p2) const {
+#ifdef SLOW_BUT_CORRECT_EXPMAP
+ return Logmap(between(p2));
+#else
+ Pose2 r = between(p2);
+ return Vector_(3, r.x(), r.y(), r.theta());
+#endif
+}
- /* ************************************************************************* */
- Pose2 Pose2::inverse(boost::optional H1) const {
- if (H1) *H1 = -AdjointMap();
- return Pose2(r_.inverse(), r_.unrotate(Point2(-t_.x(), -t_.y())));
- }
+/* ************************************************************************* */
+// Calculate Adjoint map
+// Ad_pose is 3*3 matrix that when applied to twist xi, returns Ad_pose(xi)
+Matrix Pose2::AdjointMap() const {
+ double c = r_.c(), s = r_.s(), x = t_.x(), y = t_.y();
+ return Matrix_(3,3,
+ c, -s, y,
+ s, c, -x,
+ 0.0, 0.0, 1.0
+ );
+}
- /* ************************************************************************* */
- // see doc/math.lyx, SE(2) section
- Point2 Pose2::transform_to(const Point2& point,
- boost::optional H1, boost::optional H2) const {
- Point2 d = point - t_;
- Point2 q = r_.unrotate(d);
- if (!H1 && !H2) return q;
- if (H1) *H1 = Matrix_(2, 3,
- -1.0, 0.0, q.y(),
- 0.0, -1.0, -q.x());
- if (H2) *H2 = r_.transpose();
- return q;
+/* ************************************************************************* */
+Pose2 Pose2::inverse(boost::optional H1) const {
+ if (H1) *H1 = -AdjointMap();
+ return Pose2(r_.inverse(), r_.unrotate(Point2(-t_.x(), -t_.y())));
+}
+
+/* ************************************************************************* */
+// see doc/math.lyx, SE(2) section
+Point2 Pose2::transform_to(const Point2& point,
+ boost::optional H1, boost::optional H2) const {
+ Point2 d = point - t_;
+ Point2 q = r_.unrotate(d);
+ if (!H1 && !H2) return q;
+ if (H1) *H1 = Matrix_(2, 3,
+ -1.0, 0.0, q.y(),
+ 0.0, -1.0, -q.x());
+ if (H2) *H2 = r_.transpose();
+ return q;
+}
+
+/* ************************************************************************* */
+// see doc/math.lyx, SE(2) section
+Pose2 Pose2::compose(const Pose2& p2, boost::optional H1,
+ boost::optional H2) const {
+ // TODO: inline and reuse?
+ if(H1) *H1 = p2.inverse().AdjointMap();
+ if(H2) *H2 = I3;
+ return (*this)*p2;
+}
+
+/* ************************************************************************* */
+// see doc/math.lyx, SE(2) section
+Point2 Pose2::transform_from(const Point2& p,
+ boost::optional H1, boost::optional H2) const {
+ const Point2 q = r_ * p;
+ if (H1 || H2) {
+ const Matrix R = r_.matrix();
+ const Matrix Drotate1 = Matrix_(2, 1, -q.y(), q.x());
+ if (H1) *H1 = collect(2, &R, &Drotate1); // [R R_{pi/2}q]
+ if (H2) *H2 = R; // R
+ }
+ return q + t_;
+}
+
+/* ************************************************************************* */
+Pose2 Pose2::between(const Pose2& p2, boost::optional H1,
+ boost::optional H2) const {
+ // get cosines and sines from rotation matrices
+ const Rot2& R1 = r_, R2 = p2.r();
+ double c1=R1.c(), s1=R1.s(), c2=R2.c(), s2=R2.s();
+
+ // Assert that R1 and R2 are normalized
+ assert(std::abs(c1*c1 + s1*s1 - 1.0) < 1e-5 && std::abs(c2*c2 + s2*s2 - 1.0) < 1e-5);
+
+ // Calculate delta rotation = between(R1,R2)
+ double c = c1 * c2 + s1 * s2, s = -s1 * c2 + c1 * s2;
+ Rot2 R(Rot2::atan2(s,c)); // normalizes
+
+ // Calculate delta translation = unrotate(R1, dt);
+ Point2 dt = p2.t() - t_;
+ double x = dt.x(), y = dt.y();
+ Point2 t(c1 * x + s1 * y, -s1 * x + c1 * y);
+
+ // FD: This is just -AdjointMap(between(p2,p1)) inlined and re-using above
+ if (H1) {
+ double dt1 = -s2 * x + c2 * y;
+ double dt2 = -c2 * x - s2 * y;
+ *H1 = Matrix_(3,3,
+ -c, -s, dt1,
+ s, -c, dt2,
+ 0.0, 0.0,-1.0);
+ }
+ if (H2) *H2 = I3;
+
+ return Pose2(R,t);
+}
+
+/* ************************************************************************* */
+Rot2 Pose2::bearing(const Point2& point,
+ boost::optional H1, boost::optional H2) const {
+ Point2 d = transform_to(point, H1, H2);
+ if (!H1 && !H2) return Rot2::relativeBearing(d);
+ Matrix D_result_d;
+ Rot2 result = Rot2::relativeBearing(d, D_result_d);
+ if (H1) *H1 = D_result_d * (*H1);
+ if (H2) *H2 = D_result_d * (*H2);
+ return result;
+}
+
+/* ************************************************************************* */
+Rot2 Pose2::bearing(const Pose2& point,
+ boost::optional H1, boost::optional