Added MATLAB utility functions to pose2SLAM
parent
26f1f3fa4f
commit
950bd8fcad
|
@ -12,7 +12,7 @@
|
||||||
|
|
||||||
%% Create graph container and add factors to it
|
%% Create graph container and add factors to it
|
||||||
graph = pose2SLAMGraph;
|
graph = pose2SLAMGraph;
|
||||||
initialEstimate = pose2SLAMValues;
|
initial = pose2SLAMValues;
|
||||||
odometryNoise = gtsamSharedNoiseModel_Sigmas([0.2; 0.2; 0.1]);
|
odometryNoise = gtsamSharedNoiseModel_Sigmas([0.2; 0.2; 0.1]);
|
||||||
constraint=gtsamPose2; % identity
|
constraint=gtsamPose2; % identity
|
||||||
|
|
||||||
|
@ -27,35 +27,33 @@ if fid < 0
|
||||||
error('Cannot open the file ');
|
error('Cannot open the file ');
|
||||||
end
|
end
|
||||||
|
|
||||||
disp('Reading data from file...')
|
columns=textscan(fid,'%s','delimiter','\n');
|
||||||
lines=textscan(fid,'%s','delimiter','\n');
|
|
||||||
fclose(fid);
|
fclose(fid);
|
||||||
n=size(lines{1},1);
|
lines=columns{1};
|
||||||
|
n=size(lines,1);
|
||||||
|
|
||||||
for i=1:n
|
for i=1:n
|
||||||
text=cell2mat(lines{1}(i));
|
line_i=lines{i};
|
||||||
if strcmp('VERTEX2',text(1:7))
|
if strcmp('VERTEX2',line_i(1:7))
|
||||||
v = textscan(text,'%s %d %f %f %f',1);
|
v = textscan(line_i,'%s %d %f %f %f',1);
|
||||||
initialEstimate.insertPose(v{2}, gtsamPose2(v{3}, v{4}, v{5}));
|
initial.insertPose(v{2}, gtsamPose2(v{3}, v{4}, v{5}));
|
||||||
elseif strcmp('EDGE2',text(1:5))
|
elseif strcmp('EDGE2',line_i(1:5))
|
||||||
e = textscan(text,'%s %d %d %f %f %f',1);
|
e = textscan(line_i,'%s %d %d %f %f %f',1);
|
||||||
graph.addOdometry(e{2}, e{3}, gtsamPose2(e{4}, e{5}, e{6}), odometryNoise);
|
graph.addOdometry(e{2}, e{3}, gtsamPose2(e{4}, e{5}, e{6}), odometryNoise);
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
%% Plot Initial Estimate
|
%% Plot Initial Estimate
|
||||||
figure(1)
|
figure(1);clf
|
||||||
clf
|
plot(initial.xs(),initial.ys(),'r-*'); axis equal
|
||||||
plotTrajectory(initialEstimate,'r-*')
|
|
||||||
hold on
|
|
||||||
|
|
||||||
addEquivalences=0;
|
addEquivalences=0;
|
||||||
if addEquivalences
|
if addEquivalences
|
||||||
%% Add equivalence constraints
|
%% Add equivalence constraints
|
||||||
for i=1:n
|
for i=1:n
|
||||||
text=cell2mat(lines{1}(i));
|
line_i=cell2mat(lines(i));
|
||||||
if strcmp('EQUIV',text(1:5))
|
if strcmp('EQUIV',line_i(1:5))
|
||||||
equiv = textscan(text,'%s %d %d',1);
|
equiv = textscan(line_i,'%s %d %d',1);
|
||||||
graph.addOdometry(e{2}, e{3}, constraint, odometryNoise);
|
graph.addOdometry(e{2}, e{3}, constraint, odometryNoise);
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -63,8 +61,8 @@ if addEquivalences
|
||||||
end
|
end
|
||||||
|
|
||||||
%% Optimize using Levenberg-Marquardt optimization with an ordering from colamd
|
%% Optimize using Levenberg-Marquardt optimization with an ordering from colamd
|
||||||
result = graph.optimize(initialEstimate);
|
result = graph.optimize(initial);
|
||||||
plotTrajectory(result,'g-*')
|
hold on; plot(result.xs(),result.ys(),'g-*')
|
||||||
|
|
||||||
%% Plot Covariance Ellipses
|
%% Plot Covariance Ellipses
|
||||||
% marginals = graph.marginals(result);
|
% marginals = graph.marginals(result);
|
||||||
|
|
|
@ -1,10 +0,0 @@
|
||||||
function plotTrajectory(values,color)
|
|
||||||
% plotTrajectory: plot the poses in a values object
|
|
||||||
% assumes keys are 0 to N-1, where N is values.size()
|
|
||||||
X=[];Y=[];
|
|
||||||
for i=0:values.size()-1
|
|
||||||
pose_i = values.pose(i);
|
|
||||||
X=[X;pose_i.x];
|
|
||||||
Y=[Y;pose_i.y];
|
|
||||||
end
|
|
||||||
plot(X,Y,color);
|
|
3
gtsam.h
3
gtsam.h
|
@ -451,6 +451,9 @@ class Values {
|
||||||
size_t size() const;
|
size_t size() const;
|
||||||
void print(string s) const;
|
void print(string s) const;
|
||||||
gtsam::Pose2 pose(size_t i);
|
gtsam::Pose2 pose(size_t i);
|
||||||
|
Vector xs() const;
|
||||||
|
Vector ys() const;
|
||||||
|
Vector thetas() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Graph {
|
class Graph {
|
||||||
|
|
|
@ -31,6 +31,36 @@ namespace pose2SLAM {
|
||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ************************************************************************* */
|
||||||
|
Vector Values::xs() const {
|
||||||
|
size_t j=0;
|
||||||
|
Vector result(size());
|
||||||
|
ConstFiltered<Pose2> poses = filter<Pose2>();
|
||||||
|
BOOST_FOREACH(const ConstFiltered<Pose2>::KeyValuePair& keyValue, poses)
|
||||||
|
result(j++) = keyValue.value.x();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ************************************************************************* */
|
||||||
|
Vector Values::ys() const {
|
||||||
|
size_t j=0;
|
||||||
|
Vector result(size());
|
||||||
|
ConstFiltered<Pose2> poses = filter<Pose2>();
|
||||||
|
BOOST_FOREACH(const ConstFiltered<Pose2>::KeyValuePair& keyValue, poses)
|
||||||
|
result(j++) = keyValue.value.y();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ************************************************************************* */
|
||||||
|
Vector Values::thetas() const {
|
||||||
|
size_t j=0;
|
||||||
|
Vector result(size());
|
||||||
|
ConstFiltered<Pose2> poses = filter<Pose2>();
|
||||||
|
BOOST_FOREACH(const ConstFiltered<Pose2>::KeyValuePair& keyValue, poses)
|
||||||
|
result(j++) = keyValue.value.theta ();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
void Graph::addPrior(Key i, const Pose2& p, const SharedNoiseModel& model) {
|
void Graph::addPrior(Key i, const Pose2& p, const SharedNoiseModel& model) {
|
||||||
sharedFactor factor(new Prior(i, p, model));
|
sharedFactor factor(new Prior(i, p, model));
|
||||||
|
|
|
@ -41,13 +41,15 @@ namespace pose2SLAM {
|
||||||
gtsam::Values(values) {
|
gtsam::Values(values) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convenience for MATLAB wrapper, which does not allow for identically named methods
|
/// insert a pose
|
||||||
|
void insertPose(Key i, const Pose2& pose) { insert(i, pose); }
|
||||||
|
|
||||||
/// get a pose
|
/// get a pose
|
||||||
Pose2 pose(Key i) const { return at<Pose2>(i); }
|
Pose2 pose(Key i) const { return at<Pose2>(i); }
|
||||||
|
|
||||||
/// insert a pose
|
Vector xs() const; ///< get all x coordinates in a matrix
|
||||||
void insertPose(Key i, const Pose2& pose) { insert(i, pose); }
|
Vector ys() const; ///< get all y coordinates in a matrix
|
||||||
|
Vector thetas() const; ///< get all orientations in a matrix
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -41,7 +41,17 @@ static Matrix cov(Matrix_(3, 3,
|
||||||
0.0, 0.0, st*st
|
0.0, 0.0, st*st
|
||||||
));
|
));
|
||||||
static noiseModel::Gaussian::shared_ptr covariance(noiseModel::Gaussian::Covariance(cov));
|
static noiseModel::Gaussian::shared_ptr covariance(noiseModel::Gaussian::Covariance(cov));
|
||||||
//static noiseModel::Gaussian::shared_ptr I3(noiseModel::Unit::Create(3));
|
|
||||||
|
/* ************************************************************************* */
|
||||||
|
TEST_UNSAFE( Pose2SLAM, XYT )
|
||||||
|
{
|
||||||
|
pose2SLAM::Values values;
|
||||||
|
values.insertPose(1,Pose2(1,2,3));
|
||||||
|
values.insertPose(2,Pose2(4,5,6));
|
||||||
|
EXPECT(assert_equal(Vector_(2,1.0,4.0),values.xs()));
|
||||||
|
EXPECT(assert_equal(Vector_(2,2.0,5.0),values.ys()));
|
||||||
|
EXPECT(assert_equal(Vector_(2,3.0,6.0-2*M_PI),values.thetas()));
|
||||||
|
}
|
||||||
|
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
// Test constraint, small displacement
|
// Test constraint, small displacement
|
||||||
|
|
Loading…
Reference in New Issue