00001
00029 #include <ctime>
00030 #include <isam/Slam.h>
00031 #include <isam/slam2d.h>
00032 #include <isam/glc.h>
00033
00034 using namespace std;
00035 using namespace isam;
00036 using namespace Eigen;
00037
00038 MatrixXd get_info (Slam *slam) {
00039 const SparseSystem& R = slam->get_R();
00040 const int *a_to_r = R.a_to_r();
00041 MatrixXd Rsub(R.num_rows(), R.num_cols());
00042
00043 for (int i=0; i<R.num_rows(); i++) {
00044 for (int j=0; j<R.num_cols(); j++) {
00045 Rsub(i,j) = R(a_to_r[i], a_to_r[j]);
00046 }
00047 }
00048
00049 return Rsub.transpose()*Rsub;
00050 }
00051
00052 void print_all(Slam& slam) {
00053 list<Node*> ids = slam.get_nodes();
00054 for (list<Node*>::iterator iter = ids.begin(); iter != ids.end(); iter++) {
00055 Pose2d_Node* pose = dynamic_cast<Pose2d_Node*>(*iter);
00056 cout << pose->value() << endl;
00057 }
00058 }
00059
00060 double snrv (void) {
00061 srand(time(0));
00062 double U = rand() / double(RAND_MAX);
00063 double V = rand() / double(RAND_MAX);
00064
00065 return sqrt (-2.0*log(U)) * cos(2.0*M_PI*V);
00066 }
00067
00068 Pose2d add_noise(Pose2d in, double sigma) {
00069 Pose2d out (in.x()+sigma*snrv(),
00070 in.y()+sigma*snrv(),
00071 in.t()+sigma*snrv());
00072 return out;
00073 }
00074
00075 Point2d add_noise(Point2d in, double sigma) {
00076 Point2d out (in.x()+sigma*snrv(),
00077 in.y()+sigma*snrv());
00078 return out;
00079 }
00080
00081 int main() {
00082
00083
00084 Pose2d x0 (0, 0, M_PI/9.0);
00085 Pose2d x1 (10, 10, 0.0 );
00086 Pose2d x2 (20, 20, M_PI/6.0);
00087 Pose2d x3 (30, 30, -M_PI/4.0);
00088 Pose2d x4 (40, 40, -M_PI/8.0);
00089
00090 Point2d la (100, 100);
00091
00092
00093 Pose2d z0 = x0;
00094 Pose2d z01 = x1.ominus(x0);
00095 Pose2d z12 = x2.ominus(x1);
00096 Pose2d z23 = x3.ominus(x2);
00097 Pose2d z34 = x4.ominus(x3);
00098 Pose2d z13 = x3.ominus(x1);
00099
00100 Point2d z1a = x1.transform_to(la);
00101
00102
00103 double sigma = 0.01;
00104 MatrixXd Q = sigma*sigma*eye(3);
00105 Noise Qsqinf = Information(Q.inverse());
00106 MatrixXd Q2 = sigma*sigma*eye(2);
00107 Noise Q2sqinf = Information(Q2.inverse());
00108 z0 = add_noise(z0, sigma);
00109 z01 = add_noise(z01, sigma);
00110 z12 = add_noise(z12, sigma);
00111 z23 = add_noise(z23, sigma);
00112 z34 = add_noise(z34, sigma);
00113 z13 = add_noise(z13, sigma);
00114 z1a = add_noise(z1a, sigma);
00115
00116
00117 Pose2d_Node* n0 = new Pose2d_Node();
00118 Pose2d_Node* n1 = new Pose2d_Node();
00119 Pose2d_Node* n2 = new Pose2d_Node();
00120 Pose2d_Node* n3 = new Pose2d_Node();
00121 Pose2d_Node* n4 = new Pose2d_Node();
00122 Point2d_Node* na = new Point2d_Node();
00123
00124
00125 Slam slam;
00126 Properties prop;
00127 prop.verbose = true; prop.quiet = false; prop.method = GAUSS_NEWTON;
00128 slam.set_properties(prop);
00129
00130
00131 slam.add_node(n0);
00132 slam.add_node(n1);
00133 slam.add_node(n2),
00134 slam.add_node(n3);
00135 slam.add_node(n4);
00136 slam.add_node(na);
00137
00138
00139 Pose2d_Factor* z0f = new Pose2d_Factor(n0, z0, Qsqinf);
00140 slam.add_factor(z0f);
00141 Pose2d_Pose2d_Factor* z01f = new Pose2d_Pose2d_Factor(n0, n1, z01, Qsqinf);
00142 slam.add_factor(z01f);
00143 Pose2d_Pose2d_Factor* z12f = new Pose2d_Pose2d_Factor(n1, n2, z12, Qsqinf);
00144 slam.add_factor(z12f);
00145 Pose2d_Pose2d_Factor* z23f = new Pose2d_Pose2d_Factor(n2, n3, z23, Qsqinf);
00146 slam.add_factor(z23f);
00147 Pose2d_Pose2d_Factor* z34f = new Pose2d_Pose2d_Factor(n3, n4, z34, Qsqinf);
00148 slam.add_factor(z34f);
00149 Pose2d_Pose2d_Factor* z13f = new Pose2d_Pose2d_Factor(n1, n3, z13, Qsqinf);
00150 slam.add_factor(z13f);
00151 Pose2d_Point2d_Factor* z1af = new Pose2d_Point2d_Factor(n1, na, z1a, Q2sqinf);
00152 slam.add_factor(z1af);
00153
00154 slam.batch_optimization();
00155 slam.print_stats();
00156 ofstream f; f.open ("before.graph"); slam.write(f); f.close();
00157
00158
00159
00160
00161 list<Node*> nodes_subset;
00162 nodes_subset.push_back(n0);
00163 nodes_subset.push_back(n2);
00164 nodes_subset.push_back(n3);
00165 nodes_subset.push_back(n4);
00166 MatrixXd P_true = slam.covariances().marginal(nodes_subset);
00167
00168 VectorXd mu_true(12);
00169 mu_true.segment<3>(0) = n0->value().vector();
00170 mu_true.segment<3>(3) = n2->value().vector();
00171 mu_true.segment<3>(6) = n3->value().vector();
00172 mu_true.segment<3>(9) = n4->value().vector();
00173
00174
00175 bool sparse = true;
00176 vector<Factor*> felim = glc_elim_factors (n1);
00177
00178 GLC_RootShift rs;
00179 vector<Factor*> fnew = glc_remove_node (slam, n1, sparse, &rs);
00180
00181 cout << felim.size() << " factor(s) removed." << endl;
00182 cout << fnew.size() << " new GLC factor(s) added." << endl;
00183 slam.batch_optimization();
00184 slam.print_stats();
00185 f.open ("after.graph"); slam.write(f); f.close();
00186
00187
00188 MatrixXd P_glc = slam.covariances().marginal(nodes_subset);
00189
00190 VectorXd mu_glc(12);
00191 mu_glc.segment<3>(0) = n0->value().vector();
00192 mu_glc.segment<3>(3) = n2->value().vector();
00193 mu_glc.segment<3>(6) = n3->value().vector();
00194 mu_glc.segment<3>(9) = n4->value().vector();
00195
00196
00197 int n = mu_glc.size();
00198 double A = (P_glc.inverse() * P_true).trace();
00199 VectorXd du = mu_glc - mu_true;
00200
00201 for(int i=0; i<du.size(); i++) {
00202 if(i % 3 == 2)
00203 du(i) = standardRad(du(i));
00204 }
00205 double B = du.transpose() * P_glc.inverse() * du;
00206 double C = log(P_true.determinant()) - log(P_glc.determinant());
00207 double kld = 0.5*(A + B - C - n);
00208 cout << "KLD: " << kld << endl;
00209
00210 return 0;
00211 }