changed the SFMdata functions so that it allows the passage of function arguments to generate a trajectory; default arguments result in the original behaviour (described in header). In the range bearing examples: fixed weirdo text-artifacts, add newline for readability, added underscore the prediction expression.

release/4.3a0
Thomas Horstink 2019-01-04 16:17:33 +01:00
parent ba03b398f4
commit 9c382b6c14
2 changed files with 40 additions and 61 deletions

View File

@ -11,86 +11,65 @@
#include <gtsam/nonlinear/ExpressionFactorGraph.h>
#include <gtsam/nonlinear/LevenbergMarquardtOptimizer.h>
#include <gtsam/nonlinear/Values.h>
#include <examples/SFMdata.h>
using namespace gtsam;
typedef BearingRange<Pose3, Point3> BearingRange3D;
// These functions are very similar to those in the SFM example, except that you can give it a fixed delta in between poses for n steps.
/* ************************************************************************* */
std::vector<Point3> createPoints() {
// Create the set of ground-truth landmarks
std::vector<Point3> points;
points.push_back(Point3(10.0,10.0,10.0));
points.push_back(Point3(-10.0,10.0,10.0));
points.push_back(Point3(-10.0,-10.0,10.0));
points.push_back(Point3(10.0,-10.0,10.0));
points.push_back(Point3(10.0,10.0,-10.0));
points.push_back(Point3(-10.0,10.0,-10.0));
points.push_back(Point3(-10.0,-10.0,-10.0));
points.push_back(Point3(10.0,-10.0,-10.0));
return points;
}
/* ************************************************************************* */
std::vector<Pose3> createPoses(Pose3 delta, int steps) {
// Create the set of ground-truth poses
std::vector<Pose3> poses;
Pose3 pose = Pose3();
int i = 0;
for(; i < steps; ++i) {
poses.push_back(pose);
pose = pose.compose(delta);
}
poses.push_back(pose);
return poses;
}
/* ************************************************************************* */
int main(int argc, char* argv[]) {
// Move around so the whole state (including the sensor tf) is observable
Pose3 init_pose = Pose3();
Pose3 delta_pose1 = Pose3(Rot3().Yaw(2*M_PI/8).Pitch(M_PI/8), Point3(1, 0, 0));
Pose3 delta_pose2 = Pose3(Rot3().Pitch(-M_PI/8), Point3(1, 0, 0));
Pose3 delta_pose3 = Pose3(Rot3().Yaw(-2*M_PI/8), Point3(1, 0, 0));
int steps = 4;
auto poses = createPoses(delta_pose1, steps);
auto poses2 = createPoses(delta_pose2, steps);
auto poses3 = createPoses(delta_pose3, steps);
auto poses = createPoses(init_pose, delta_pose1, steps);
auto poses2 = createPoses(init_pose, delta_pose2, steps);
auto poses3 = createPoses(init_pose, delta_pose3, steps);
// concatenate poses to create trajectory
// Concatenate poses to create trajectory
poses.insert( poses.end(), poses2.begin(), poses2.end() );
poses.insert( poses.end(), poses3.begin(), poses3.end() ); // std::vector of Pose3
auto points = createPoints(); // std::vector of Point3
// (ground-truth) sensor pose in body frame, further an unknown variable
Pose3 body_T_sensor_gt(Rot3::RzRyRx(-M_PI_2, 0.0, -M_PI_2), Point3(0.25, -0.10, 1.0));
// a graph
// The graph
ExpressionFactorGraph graph;
// Specify uncertainty on first pose prior and also for between factor (simplicity reasons)
auto poseNoise = noiseModel::Diagonal::Sigmas((Vector(6)<<0.3,0.3,0.3,0.1,0.1,0.1).finished());ExpressiExpression exampExpression exampExpression exampExpression exampExpression exampExpression exampExpression exampExpression exampExpression exampExpression exampExpression exampExpression exampExpression exampExpression exampExpression exampExpression exampExpression exampExpression exampExpression exampExpression exampExpression exampExpression exampExpression exampExpression exampExpression exampExpression exampExpression exampExpression exampExpression exampExpression exampExpression exampExpression exampExpression exampon examp
auto poseNoise = noiseModel::Diagonal::Sigmas((Vector(6)<<0.3,0.3,0.3,0.1,0.1,0.1).finished());
// Uncertainty bearing range measurement;
auto bearingRangeNoise = noiseModel::Diagonal::Sigmas((Vector(3)<<0.01,0.03,0.05).finished());
// Expressions for body-frame at key 0 and sensor-tf
Pose3_ x_('x', 0);nice
Pose3_ x_('x', 0);
Pose3_ body_T_sensor_('T', 0);
// add a prior on the body-pose.
// Add a prior on the body-pose
graph.addExpressionFactor(x_, poses[0], poseNoise);
// Simulated measurements from pose
for (size_t i = 0; i < poses.size(); ++i) {
auto world_T_sensor = poses[i].compose(body_T_sensor_gt);
for (size_t j = 0; j < points.size(); ++j) {
// Create the expression
auto prediction = Expression<BearingRange3D>( BearingRange3D::Measure, Pose3_('x',i)*body_T_sensor_, Point3_('l',j));
// Create a *perfect* measurementExpression exampExpreExpression exampExpression exampExpression exampssion examp
// This expression is the key feature of this example: it creates a differentiable expression of the measurement after being displaced by sensor transform.
auto prediction_ = Expression<BearingRange3D>( BearingRange3D::Measure, Pose3_('x',i)*body_T_sensor_, Point3_('l',j));
// Create a *perfect* measurement
auto measurement = BearingRange3D(world_T_sensor.bearing(points[j]), world_T_sensor.range(points[j]));
// Add factor
graph.addExpressionFactor(prediction, measurement, bearingRangeNoise);
graph.addExpressionFactor(prediction_, measurement, bearingRangeNoise);
}
// and add a between factor to the graph
if (i > 0)
{
@ -107,7 +86,7 @@ int main(int argc, char* argv[]) {
for (size_t j = 0; j < points.size(); ++j)
initial.insert<Point3>(Symbol('l', j), points[j] + Point3(-0.25, 0.20, 0.15));
// initialize body_T_sensor wrongly (because we do not know!)
// Initialize body_T_sensor wrongly (because we do not know!)
initial.insert<Pose3>(Symbol('T',0), Pose3());
std::cout << "initial error: " << graph.error(initial) << std::endl;

View File

@ -16,9 +16,10 @@
*/
/**
* A structure-from-motion example with landmarks
* A structure-from-motion example with landmarks, default function arguments give
* - The landmarks form a 10 meter cube
* - The robot rotates around the landmarks, always facing towards the cube
* Passing function argument allows to specificy an initial position, a pose increment and step count.
*/
// As this is a full 3D problem, we will use Pose3 variables to represent the camera
@ -49,20 +50,19 @@ std::vector<gtsam::Point3> createPoints() {
}
/* ************************************************************************* */
std::vector<gtsam::Pose3> createPoses() {
std::vector<gtsam::Pose3> createPoses(
const gtsam::Pose3& init = gtsam::Pose3(gtsam::Rot3::Ypr(M_PI/2,0,-M_PI/2), gtsam::Point3(30, 0, 0)),
const gtsam::Pose3& delta = gtsam::Pose3(gtsam::Rot3::Ypr(0,-M_PI/4,0), gtsam::Point3(sin(M_PI/4)*30, 0, 30*(1-sin(M_PI/4)))),
int steps = 8) {
// Create the set of ground-truth poses
// Default values give a circular trajectory, radius 30 at pi/4 intervals, always facing the circle center
std::vector<gtsam::Pose3> poses;
double radius = 30.0;
int i = 0;
double theta = 0.0;
gtsam::Point3 up(0,0,1);
gtsam::Point3 target(0,0,0);
for(; i < 8; ++i, theta += 2*M_PI/8) {
gtsam::Point3 position = gtsam::Point3(radius*cos(theta), radius*sin(theta), 0.0);
gtsam::SimpleCamera camera = gtsam::SimpleCamera::Lookat(position, target, up);
poses.push_back(camera.pose());
int i = 1;
poses.push_back(init);
for(; i < steps; ++i) {
poses.push_back(poses[i-1].compose(delta));
}
return poses;
}
/* ************************************************************************* */
}