SRBA: Sparser Relative Bundle Adjustment
/home/travis/build/MRPT/srba/examples/cpp/tutorial-srba-monocular-se3.cpp
00001 /* +---------------------------------------------------------------------------+
00002    |                     Mobile Robot Programming Toolkit (MRPT)               |
00003    |                          http://www.mrpt.org/                             |
00004    |                                                                           |
00005    | Copyright (c) 2005-2015, Individual contributors, see AUTHORS file        |
00006    | See: http://www.mrpt.org/Authors - All rights reserved.                   |
00007    | Released under BSD License. See details in http://www.mrpt.org/License    |
00008    +---------------------------------------------------------------------------+ */
00009 
00010 #include <srba.h>
00011 #include <mrpt/gui.h>  // For rendering results as a 3D scene
00012 #include <mrpt/random.h>  // For rendering results as a 3D scene
00013 
00014 using namespace srba;
00015 using namespace mrpt::random;
00016 using namespace std;
00017 using mrpt::utils::DEG2RAD;
00018 
00019 struct RBA_OPTIONS : public RBA_OPTIONS_DEFAULT
00020 {
00021 //  typedef ecps::local_areas_fixed_size            edge_creation_policy_t;  //!< One of the most important choices: how to construct the relative coordinates graph problem
00022     typedef options::sensor_pose_on_robot_se3        sensor_pose_on_robot_t;
00023     typedef options::observation_noise_identity      obs_noise_matrix_t;      // The sensor noise matrix is the same for all observations and equal to \sigma * I(identity)
00024 //  typedef options::solver_LM_schur_dense_cholesky solver_t;                //!< Solver algorithm (Default: Lev-Marq, with Schur, with dense Cholesky)
00025 };
00026 
00027 typedef RbaEngine<
00028     kf2kf_poses::SE3,              // Parameterization  of KF-to-KF poses
00029     landmarks::Euclidean3D,        // Parameterization of landmark positions
00030     observations::MonocularCamera, // Type of observations
00031     RBA_OPTIONS
00032     >  my_srba_t;
00033 
00034 // --------------------------------------------------------------------------------
00035 // A test dataset. Generated with https://github.com/jlblancoc/recursive-world-toolkit
00036 //  and the script: tutorials_dataset-monocular.cfg
00037 // --------------------------------------------------------------------------------
00038 const double SENSOR_NOISE_STD = 1e-4;
00039 
00040 struct basic_monocular_dataset_entry_t
00041 {
00042     unsigned int landmark_id;
00043     double px_x, px_y;
00044 };
00045 // Observations for KF#0: GT_Pose= 0.000000 0.000000 0.000000 0.564787 -0.517532 0.434261 -0.473913
00046 basic_monocular_dataset_entry_t dataset0[] = {
00047  {   146, 397.16046143, 371.29309082},
00048  {   144, 325.15927124, 432.81069946},
00049  {   118, 191.95759583, 391.00930786},
00050  {    55, 556.79144287, 405.27206421},
00051  {    39, 427.63507080, 337.36282349},
00052  {    35, 403.34268188, 345.97265625},
00053  {    20,  19.02102661, 376.73773193},
00054  {    28, 437.69879150, 350.98776245},
00055  {    52, 173.58599854, 203.18234253},
00056  {   141, 490.49987793, 384.93002319},
00057  {    84, 285.96942139, 291.06143188},
00058  {    76, 448.31323242, 298.45452881},
00059  {    71, 399.07693481, 195.52038574},
00060  {    37, 485.42114258, 248.38455200},
00061  {   100, 162.51091003, 170.75312805},
00062  {   127, 293.27337646, 409.78048706},
00063  {   115, 186.95903015, 264.30618286},
00064  {    59, 492.91369629, 300.95275879},
00065  {     6, 492.14477539, 370.06378174},
00066  {   113, 298.54818726, 336.68572998},
00067  {    99, 209.10960388, 364.52743530},
00068  {   128, 340.99240112, 268.45800781},
00069  {    86, 370.48016357, 251.53149414},
00070  {    13, 373.14675903, 373.82769775}
00071 };
00072 // Observations for KF#10: GT_Pose = 1.226072 0.293638 0.110099 0.521317 -0.478835 0.477946 -0.520108
00073 basic_monocular_dataset_entry_t dataset1[] = {
00074  {    39, 427.21511841, 369.39392090},
00075  {    35, 380.21871948, 382.86489868},
00076  {    28, 434.43206787, 383.05078125},
00077  {    76, 447.35217285, 298.07504272},
00078  {    84, 129.46676636, 276.64343262},
00079  {   141, 520.18365479, 438.30242920},
00080  {    71, 374.61349487, 122.72018433},
00081  {    37, 499.87155151, 225.80770874},
00082  {    59, 502.13192749, 302.56442261},
00083  {   113, 190.50091553, 361.21731567},
00084  {   128, 277.86718750, 248.40679932},
00085  {     6, 499.41741943, 398.28195190},
00086  {    86, 326.98937988, 226.08045959},
00087  {    13, 328.80868530, 407.59310913},
00088  {    26, 434.39413452, 283.76858521},
00089  {    77, 375.84552002, 298.24645996},
00090  {    66,  88.29249573, 319.89883423},
00091  {    97, 278.99508667, 320.07223511},
00092  {    32, 446.65643311, 288.50265503},
00093  {     3, 456.27807617, 234.08326721},
00094  {    94, 104.95476532,  64.29298401},
00095  {   105, 310.90158081, 354.13259888},
00096  {    24, 263.15136719, 176.80107117},
00097  {     1, 593.76177979, 250.52128601},
00098  {    12, 310.85137939, 313.02230835},
00099  {   132, 295.56417847, 462.04772949},
00100  {   106, 623.83544922, 347.87551880},
00101  {    81, 515.14727783, 337.15591431},
00102  {     2, 313.69470215, 261.66650391},
00103  {    85, 256.50866699, 368.93145752},
00104  {   121, 578.39721680, 324.32101440},
00105 };
00106 
00107 int main(int argc, char**argv)
00108 {
00109     my_srba_t rba;     //  Create an empty RBA problem
00110 
00111     // --------------------------------------------------------------------------------
00112     // Set parameters
00113     // --------------------------------------------------------------------------------
00114     rba.setVerbosityLevel( 2 );   // 0: None; 1:Important only; 2:Verbose
00115 
00116     rba.parameters.srba.use_robust_kernel = true;
00117     rba.parameters.obs_noise.std_noise_observations = 0.5;  // pixels
00118 
00119     // =========== Topology parameters ===========
00120     rba.parameters.srba.max_tree_depth       = 3;
00121     rba.parameters.srba.max_optimize_depth   = 3;
00122     // ===========================================
00123 
00124     // Set camera calib:
00125     mrpt::utils::TCamera & c = rba.parameters.sensor.camera_calib;
00126     c.ncols = 800;
00127     c.nrows = 640;
00128     c.cx(400);
00129     c.cy(320);
00130     c.fx(200);
00131     c.fy(200);
00132     c.dist.setZero();
00133 
00134     // Sensor pose on the robot parameters:
00135     rba.parameters.sensor_pose.relative_pose = mrpt::poses::CPose3D(0,0,0,DEG2RAD(-90),DEG2RAD(0),DEG2RAD(-90) ); // Set camera pointing forwards (camera's +Z is robot +X)
00136 
00137     // Alternatively, parameters can be loaded from an .ini-like config file
00138     // -----------------------------------------------------------------------
00139     // rba.parameters.loadFromConfigFileName("config_file.cfg", "srba");
00140     //rba.sensor_params.camera_calib.loadFromConfigFile("CAMERA","config_file.cfg");
00141 
00142     // --------------------------------------------------------------------------------
00143     // Dump parameters to console (for checking/debugging only)
00144     // --------------------------------------------------------------------------------
00145     //cout << "RBA parameters:\n-----------------\n";
00146     //rba.parameters.dumpToConsole();
00147 
00148     // --------------------------------------------------------------------------------
00149     // Define observations of KF #0:
00150     // --------------------------------------------------------------------------------
00151     my_srba_t::new_kf_observations_t  list_obs;
00152     my_srba_t::new_kf_observation_t   obs_field;
00153 
00154     obs_field.is_fixed = false;   // Landmarks have unknown relative positions (i.e. treat them as unknowns to be estimated)
00155     obs_field.is_unknown_with_init_val = false; // We don't have any guess on the initial LM position (will invoke the inverse sensor model)
00156 
00157     for (size_t i=0;i<sizeof(dataset0)/sizeof(dataset0[0]);i++)
00158     {
00159         obs_field.obs.feat_id = dataset0[i].landmark_id;
00160         obs_field.obs.obs_data.px.x = dataset0[i].px_x + randomGenerator.drawGaussian1D(0,SENSOR_NOISE_STD);
00161         obs_field.obs.obs_data.px.y = dataset0[i].px_y + randomGenerator.drawGaussian1D(0,SENSOR_NOISE_STD);
00162         list_obs.push_back( obs_field );
00163     }
00164 
00165 
00166     //  Here happens the main stuff: create Key-frames, build structures, run optimization, etc.
00167     //  ============================================================================================
00168     my_srba_t::TNewKeyFrameInfo new_kf_info;
00169     rba.define_new_keyframe(
00170         list_obs,      // Input observations for the new KF
00171         new_kf_info,   // Output info
00172         true           // Also run local optimization?
00173         );
00174 
00175     cout << "Created KF #" << new_kf_info.kf_id
00176         << " | # kf-to-kf edges created:" <<  new_kf_info.created_edge_ids.size()  << endl
00177         << "Optimization error: " << new_kf_info.optimize_results.total_sqr_error_init << " -> " << new_kf_info.optimize_results.total_sqr_error_final << endl
00178         << "-------------------------------------------------------" << endl;
00179 
00180 
00181     // --------------------------------------------------------------------------------
00182     // Define observations of KF #1:
00183     // --------------------------------------------------------------------------------
00184     list_obs.clear();
00185 
00186     for (size_t i=0;i<sizeof(dataset1)/sizeof(dataset1[0]);i++)
00187     {
00188         obs_field.obs.feat_id = dataset1[i].landmark_id;
00189         obs_field.obs.obs_data.px.x = dataset1[i].px_x + randomGenerator.drawGaussian1D(0,SENSOR_NOISE_STD);
00190         obs_field.obs.obs_data.px.y = dataset1[i].px_y + randomGenerator.drawGaussian1D(0,SENSOR_NOISE_STD);
00191         list_obs.push_back( obs_field );
00192     }
00193 
00194     //  Here happens the main stuff: create Key-frames, build structures, run optimization, etc.
00195     //  ============================================================================================
00196     rba.define_new_keyframe(
00197         list_obs,      // Input observations for the new KF
00198         new_kf_info,   // Output info
00199         true           // Also run local optimization?
00200         );
00201 
00202     cout << "Created KF #" << new_kf_info.kf_id
00203         << " | # kf-to-kf edges created:" <<  new_kf_info.created_edge_ids.size() << endl
00204         << "Optimization error: " << new_kf_info.optimize_results.total_sqr_error_init << " -> " << new_kf_info.optimize_results.total_sqr_error_final << endl
00205         << "-------------------------------------------------------" << endl;
00206 
00207 
00208     // Dump the relative pose of KF#0 wrt KF#1:
00209     cout << "inv_pose of KF-to-KF edge #0 (relative pose of KF#0 wrt KF#1):\n" << rba.get_k2k_edges()[0].inv_pose << endl;
00210 
00211     // --------------------------------------------------------------------------------
00212     // Saving RBA graph as a DOT file:
00213     // --------------------------------------------------------------------------------
00214     const string sFil = "graph.dot";
00215     cout << "Saving final graph of KFs and LMs to: " << sFil << endl;
00216     rba.save_graph_as_dot(sFil, true /* LMs=save */);
00217     cout << "Done.\n";
00218 
00219     // --------------------------------------------------------------------------------
00220     // Show 3D view of the resulting map:
00221     // --------------------------------------------------------------------------------
00222     my_srba_t::TOpenGLRepresentationOptions  opengl_options;
00223     mrpt::opengl::CSetOfObjectsPtr rba_3d = mrpt::opengl::CSetOfObjects::Create();
00224 
00225     rba.build_opengl_representation(
00226         0,  // Root KF,
00227         opengl_options, // Rendering options
00228         rba_3d  // Output scene
00229         );
00230 
00231     // Display:
00232 #if MRPT_HAS_WXWIDGETS
00233     mrpt::gui::CDisplayWindow3D win("RBA results",640,480);
00234     {
00235         mrpt::opengl::COpenGLScenePtr &scene = win.get3DSceneAndLock();
00236         scene->insert(rba_3d);
00237         win.unlockAccess3DScene();
00238     }
00239     win.setCameraZoom( 4 );
00240     win.repaint();
00241 
00242     cout << "Press any key or close window to exit.\n";
00243     win.waitForKey();
00244 #endif
00245 
00246     return 0; // All ok
00247 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends