error_vector and error unit-tested

release/4.3a0
Frank Dellaert 2009-12-18 05:18:31 +00:00
parent edb72d305f
commit eaf27af92d
8 changed files with 223 additions and 155 deletions

View File

@ -11,7 +11,11 @@ namespace gtsam {
UrbanFactor::UrbanFactor() { UrbanFactor::UrbanFactor() {
// TODO Auto-generated constructor stub // TODO Auto-generated constructor stub
}
UrbanFactor::UrbanFactor(const Vector& z, const double sigma) :
NonlinearFactor<UrbanConfig> (z,sigma) {
// TODO
} }
UrbanFactor::~UrbanFactor() { UrbanFactor::~UrbanFactor() {

View File

@ -13,20 +13,15 @@
namespace gtsam { namespace gtsam {
class UrbanFactor : public NonlinearFactor<UrbanConfig> { /**
* Base class for UrbanMeasurement and UrbanOdometry
*/
class UrbanFactor: public NonlinearFactor<UrbanConfig> {
public: public:
UrbanFactor(); UrbanFactor();
UrbanFactor(const Vector& z, const double sigma);
virtual ~UrbanFactor(); virtual ~UrbanFactor();
/** Vector of errors */
Vector error_vector(const UrbanConfig& c) const { return zero(0); }
/** linearize to a GaussianFactor */
boost::shared_ptr<GaussianFactor> linearize(const UrbanConfig& c) const {
boost::shared_ptr<GaussianFactor> factor(new GaussianFactor);
return factor;
}
}; };
} }

View File

@ -33,9 +33,10 @@ namespace gtsam {
} }
/* ************************************************************************* */ /* ************************************************************************* */
void UrbanGraph::addMeasurement(double x, double y, double sigma, int p1, void UrbanGraph::addMeasurement(double x, double y, double sigma, int i, int j) {
int p2) { Point2 z(x,y);
// TODO sharedFactor factor(new UrbanMeasurement(z,sigma,i,j));
push_back(factor);
} }
; ;

View File

@ -8,7 +8,7 @@
#pragma once #pragma once
#include "NonlinearFactorGraph.h" #include "NonlinearFactorGraph.h"
#include "UrbanFactor.h" #include "UrbanMeasurement.h"
namespace gtsam { namespace gtsam {
@ -35,13 +35,12 @@ namespace gtsam {
/** /**
* Add a landmark constraint * Add a landmark constraint
*/ */
void addMeasurement(double x, double y, double sigma, int p1, int p2); void addMeasurement(double x, double y, double sigma, int i, int j);
/** /**
* Add an odometry constraint * Add an odometry constraint
*/ */
void addOdometry(double dx, double yaw, double sigmadx, double sigmayaw, void addOdometry(double dx, double yaw, double sigmadx, double sigmayaw, int i);
int p);
/** /**
* Add an initial constraint on the first pose * Add an initial constraint on the first pose

View File

@ -5,71 +5,81 @@
* @author Viorela Ila * @author Viorela Ila
*/ */
#include "UrbanConfig.h"
#include "UrbanMeasurement.h" #include "UrbanMeasurement.h"
#include "Pose3.h" #include "Pose3.h"
#include "SimpleCamera.h"
using namespace std; using namespace std;
namespace gtsam{
/** receives the 2D point in world coordinates and transforms it to Pose coordinates */
Point3 transformPoint2_to(const Pose3& pose, const Point2& p);
Matrix DtransformPoint2_to1(const Pose3& pose, const Point2& p);
Matrix DtransformPoint2_to2(const Pose3& pose); // does not depend on p !
/* ************************************************************************* */
UrbanMeasurement::UrbanMeasurement() {
/// Arbitrary values
robotPoseNumber_ = 111;
landmarkNumber_ = 222;
robotPoseName_ = symbol('x',robotPoseNumber_);
landmarkName_ = symbol('l',landmarkNumber_);
keys_.push_back(robotPoseName_);
keys_.push_back(landmarkName_);
}
/* ************************************************************************* */
UrbanMeasurement::UrbanMeasurement(const Point2& z, double sigma, int cn, int ln)
: NonlinearFactor<UrbanConfig>(z.vector(), sigma)
{
robotPoseNumber_ = cn;
landmarkNumber_ = ln;
robotPoseName_ = symbol('x',robotPoseNumber_);
landmarkName_ = symbol('l',landmarkNumber_);
keys_.push_back(robotPoseName_);
keys_.push_back(landmarkName_);
}
/* ************************************************************************* */ namespace gtsam {
void UrbanMeasurement::print(const std::string& s) const {
printf("%s %s %s\n", s.c_str(), robotPoseName_.c_str(), landmarkName_.c_str());
gtsam::print(this->z_, s+".z");
}
/* ************************************************************************* */ /* ************************************************************************* */
bool UrbanMeasurement::equals(const UrbanMeasurement& p, double tol) const { Point2 transform_to(const Pose3& pose, const Point2& p) {
if (&p == NULL) return false; // create a 3D point at our height (Z is assumed up)
if (robotPoseNumber_ != p.robotPoseNumber_ || landmarkNumber_ != p.landmarkNumber_) return false; Point3 global3D(p.x(),p.y(),pose.translation().z());
if (!equal_with_abs_tol(this->z_,p.z_,tol)) return false; // transform into local 3D point
return true; Point3 local3D = transform_to(pose,global3D);
} // take x and y as the local measurement
Point2 local2D(local3D.x(),local3D.y());
return local2D;
}
/* ************************************************************************* */
Matrix Dtransform_to1(const Pose3& pose, const Point2& p) {
return zeros(2, 6);
}
// the difference here that we have a 2d point in a 3D coordinate /* ************************************************************************* */
Vector UrbanMeasurement::predict(const UrbanConfig& c) const { Matrix Dtransform_to2(const Pose3& pose, const Point2& p) {
Pose3 pose = c.robotPose(robotPoseNumber_); return zeros(2, 2);
Point2 landmark = c.landmarkPoint(landmarkNumber_); }
// TODO Implement predict function
Vector v;
return v;
}
/* ************************************************************************* */ /* ************************************************************************* */
Vector UrbanMeasurement::error_vector(const UrbanConfig& c) const { UrbanMeasurement::UrbanMeasurement() {
// Right-hand-side b = (z - h(x))/sigma /// Arbitrary values
Point2 h = predict(c); robotPoseNumber_ = 111;
// TODO Return z-h(x) landmarkNumber_ = 222;
Vector v; robotPoseName_ = symbol('x', robotPoseNumber_);
return v; landmarkName_ = symbol('l', landmarkNumber_);
} keys_.push_back(robotPoseName_);
keys_.push_back(landmarkName_);
}
/* ************************************************************************* */
UrbanMeasurement::UrbanMeasurement(const Point2& z, double sigma, int i,
int j) :
UrbanFactor(z.vector(), sigma) {
robotPoseNumber_ = i;
landmarkNumber_ = j;
robotPoseName_ = symbol('x', robotPoseNumber_);
landmarkName_ = symbol('l', landmarkNumber_);
keys_.push_back(robotPoseName_);
keys_.push_back(landmarkName_);
}
/* ************************************************************************* */
void UrbanMeasurement::print(const std::string& s) const {
printf("%s %s %s\n", s.c_str(), robotPoseName_.c_str(),
landmarkName_.c_str());
gtsam::print(this->z_, s + ".z");
}
/* ************************************************************************* */
bool UrbanMeasurement::equals(const UrbanMeasurement& p, double tol) const {
if (&p == NULL) return false;
if (robotPoseNumber_ != p.robotPoseNumber_ || landmarkNumber_
!= p.landmarkNumber_) return false;
if (!equal_with_abs_tol(this->z_, p.z_, tol)) return false;
return true;
}
/* ************************************************************************* */
Vector UrbanMeasurement::error_vector(const UrbanConfig& x) const {
Pose3 pose = x.robotPose(robotPoseNumber_);
Point2 landmark = x.landmarkPoint(landmarkNumber_);
// Right-hand-side b = (z - h(x))/sigma
Point2 hx = transform_to(pose,landmark);
return (z_ - hx.vector());
}
/* ************************************************************************* */ /* ************************************************************************* */

View File

@ -7,94 +7,93 @@
#pragma once #pragma once
#include "NonlinearFactor.h" #include "UrbanFactor.h"
#include "GaussianFactor.h"
#include "Testable.h"
#include "Point2.h"
namespace gtsam { namespace gtsam {
class UrbanConfig; class UrbanConfig;
/**
* Non-linear factor for a constraint derived from a 2D measurement,
*/
class UrbanMeasurement : public NonlinearFactor<UrbanConfig>, Testable<UrbanMeasurement>
{
private:
int robotPoseNumber_, landmarkNumber_;
std::string robotPoseName_, landmarkName_;
//boost::shared_ptr<Cal3_S2> K_; // Calibration stored in each factor. FD: need to think about this.
typedef NonlinearFactor<UrbanConfig> ConvenientFactor;
public:
typedef boost::shared_ptr<UrbanMeasurement> shared_ptr; // shorthand for a smart pointer to a factor
//typedef boost::shared_ptr<Cal3_S2> shared_ptrK;
/** /**
* Default constructor * Non-linear factor for a constraint derived from a 2D measurement,
*/ */
UrbanMeasurement(); class UrbanMeasurement: public UrbanFactor {
private:
/** int robotPoseNumber_, landmarkNumber_;
* Constructor std::string robotPoseName_, landmarkName_;
* @param z is the 2 dimensional location of landmark respect to the robot (the measurement) //boost::shared_ptr<Cal3_S2> K_; // Calibration stored in each factor. FD: need to think about this.
* @param sigma is the standard deviation typedef NonlinearFactor<UrbanConfig> ConvenientFactor;
* @param robotPoseNumber is basically the pose number
* @param landmarkNumber is the index of the landmark
*
*
*/
UrbanMeasurement(const Point2& z, double sigma, int robotPoseNumber, int landmarkNumber);
public:
/** typedef boost::shared_ptr<UrbanMeasurement> shared_ptr; // shorthand for a smart pointer to a factor
* print //typedef boost::shared_ptr<Cal3_S2> shared_ptrK;
* @param s optional string naming the factor
*/
void print(const std::string& s="UrbanMeasurement") const;
/** /**
* equals * Default constructor
*/ */
bool equals(const UrbanMeasurement&, double tol=1e-9) const; UrbanMeasurement();
/** /**
* predict the measurement (is that update ??) * Constructor
*/ * @param z is the 2 dimensional location of landmark respect to the robot (the measurement)
Vector predict(const UrbanConfig&) const; * @param sigma is the standard deviation
* @param robotPoseNumber is basically the pose number
* @param landmarkNumber is the index of the landmark
*
*
*/
UrbanMeasurement(const Point2& z, double sigma, int robotPoseNumber,
int landmarkNumber);
/** /**
* calculate the error of the factor * print
*/ * @param s optional string naming the factor
Vector error_vector(const UrbanConfig&) const; */
void print(const std::string& s = "UrbanMeasurement") const;
/** /**
* linerarization * equals
*/ */
bool equals(const UrbanMeasurement&, double tol = 1e-9) const;
GaussianFactor::shared_ptr linearize(const UrbanConfig&) const { /**
//TODO implement linearize * calculate the error of the factor
*/
Vector error_vector(const UrbanConfig&) const;
/**
* linerarization
*/
GaussianFactor::shared_ptr linearize(const UrbanConfig&) const {
//TODO implement linearize
}
int getrobotPoseNumber() const {
return robotPoseNumber_;
}
int getLandmarkNumber() const {
return landmarkNumber_;
}
private:
/** Serialization function */
friend class boost::serialization::access;
template<class Archive>
void serialize(Archive & ar, const unsigned int version) {
ar & BOOST_SERIALIZATION_NVP(robotPoseNumber_);
ar & BOOST_SERIALIZATION_NVP(landmarkNumber_);
ar & BOOST_SERIALIZATION_NVP(robotPoseName_);
ar & BOOST_SERIALIZATION_NVP(landmarkName_);
}
}; };
int getrobotPoseNumber() const { return robotPoseNumber_; } /**
int getLandmarkNumber() const { return landmarkNumber_; } * Transform 2D landmark into 6D pose, and its derivatives
*/
Point2 transform_to(const Pose3& pose, const Point2& p);
Matrix Dtransform_to1(const Pose3& pose, const Point2& p);
Matrix Dtransform_to2(const Pose3& pose);
} // namespace gtsam
private:
/** Serialization function */
friend class boost::serialization::access;
template<class Archive>
void serialize(Archive & ar, const unsigned int version) {
ar & BOOST_SERIALIZATION_NVP(robotPoseNumber_);
ar & BOOST_SERIALIZATION_NVP(landmarkNumber_);
ar & BOOST_SERIALIZATION_NVP(robotPoseName_);
ar & BOOST_SERIALIZATION_NVP(landmarkName_);
}
};
}

View File

@ -21,7 +21,7 @@ typedef NonlinearOptimizer<UrbanGraph,UrbanConfig> Optimizer;
/* ************************************************************************* */ /* ************************************************************************* */
Point2 landmark1( 2, 5); Point2 landmark( 2, 5);
Point2 landmark2( 2, 10); Point2 landmark2( 2, 10);
Point2 landmark3( -2, 5); Point2 landmark3( -2, 5);
Point2 landmark4( -2,-10); Point2 landmark4( -2,-10);
@ -29,7 +29,7 @@ Point2 landmark4( -2,-10);
/* Robot is at (0,0,0) looking in global "y" direction. /* Robot is at (0,0,0) looking in global "y" direction.
* For the local frame we used Navlab convention, * For the local frame we used Navlab convention,
* x-looks forward, y-looks right, z- down*/ * x-looks forward, y-looks right, z- down*/
Pose3 robotPose1(Matrix_(3,3, Pose3 robotPose(Matrix_(3,3,
0., 1., 0., 0., 1., 0.,
1., 0., 0., 1., 0., 0.,
0., 0.,-1. 0., 0.,-1.
@ -45,8 +45,28 @@ Pose3 robotPose2(Matrix_(3,3,
Point3(0,1,0)); Point3(0,1,0));
/* ************************************************************************* */ /* ************************************************************************* */
/* the measurements are relative to the robot pose so TEST( UrbanGraph, addMeasurement)
* they are in robot coordinate frame different from the global (above)*/ {
// Check adding a measurement
UrbanGraph g;
double sigma = 0.2;// 20 cm
g.addMeasurement(4, 2, sigma, 1, 1);
LONGS_EQUAL(1,g.size());
// Create a config
UrbanConfig config;
config.addRobotPose(1,robotPose);
config.addLandmark(1,landmark);
// Check error
double expected = 0.5/sigma/sigma;
DOUBLES_EQUAL(expected, g.error(config), 1e-9);
}
/* ************************************************************************* *
* the measurements are relative to the robot pose so
* they are in robot coordinate frame different from the global (above)
*
UrbanGraph testGraph() { UrbanGraph testGraph() {
double sigma = 0.2;// 20 cm double sigma = 0.2;// 20 cm
@ -68,7 +88,7 @@ UrbanGraph testGraph() {
return g; return g;
} }
/* ************************************************************************* */ /* ************************************************************************* *
TEST( UrbanGraph, optimizeLM) TEST( UrbanGraph, optimizeLM)
{ {
// build a graph // build a graph
@ -76,9 +96,9 @@ TEST( UrbanGraph, optimizeLM)
// Create an initial configuration corresponding to the ground truth // Create an initial configuration corresponding to the ground truth
boost::shared_ptr<UrbanConfig> initialEstimate(new UrbanConfig); boost::shared_ptr<UrbanConfig> initialEstimate(new UrbanConfig);
initialEstimate->addRobotPose(1, robotPose1); initialEstimate->addRobotPose(1, robotPose);
initialEstimate->addRobotPose(2, robotPose2); initialEstimate->addRobotPose(2, robotPose2);
initialEstimate->addLandmark(1, landmark1); initialEstimate->addLandmark(1, landmark);
initialEstimate->addLandmark(2, landmark2); initialEstimate->addLandmark(2, landmark2);
initialEstimate->addLandmark(3, landmark3); initialEstimate->addLandmark(3, landmark3);
initialEstimate->addLandmark(4, landmark4); initialEstimate->addLandmark(4, landmark4);

View File

@ -6,13 +6,53 @@
#include "UrbanConfig.h" #include "UrbanConfig.h"
#include "UrbanMeasurement.h" #include "UrbanMeasurement.h"
#include "Vector.h"
using namespace std; using namespace std;
using namespace gtsam; using namespace gtsam;
Point2 landmark(2,5);
/* Robot is at (0,0,0) looking in global "y" direction.
* For the local frame we used Navlab convention,
* x-looks forward, y-looks right, z- down*/
Pose3 robotPose(Matrix_(3,3,
0., 1., 0.,
1., 0., 0.,
0., 0.,-1.
),
Point3(0,0,0));
/* ************************************************************************* */ /* ************************************************************************* */
TEST( UrbanMeasurement, linearize ) TEST( UrbanMeasurement, transform_to )
{ {
Point2 expected(5,2);
Point2 actual = transform_to(robotPose, landmark);
CHECK(assert_equal(expected,actual));
}
/* ************************************************************************* */
TEST( UrbanMeasurement, error_vector )
{
// Create a measurement, no-noise measurement would yield 5,2
Point2 z(4,2);
double sigma = 0.2;
UrbanMeasurement factor(z,sigma,44,66);
// Create a config
UrbanConfig config;
config.addRobotPose(44,robotPose);
config.addLandmark(66,landmark);
// test error_vector
Vector expected = Vector_(2, -1.0, 0.0);
Vector actual = factor.error_vector(config);
CHECK(assert_equal(expected,actual));
// test error
double expected2 = 12.5; // 0.5 * 5^2
double actual2 = factor.error(config);
DOUBLES_EQUAL(expected2,actual2,1e-9);
} }
/* ************************************************************************* */ /* ************************************************************************* */