00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #include "parameter_server.h"
00017
00018 using namespace std;
00019
00020 ParameterServer* ParameterServer::_instance = NULL;
00021
00022 ParameterServer::ParameterServer() {
00023 pre = ros::this_node::getName();
00024 pre += "/config/";
00025
00026 defaultConfig();
00027 getValues();
00028 }
00029
00030 ParameterServer* ParameterServer::instance() {
00031 if (_instance == NULL) {
00032 _instance = new ParameterServer();
00033 }
00034 return _instance;
00035 }
00036
00037 void ParameterServer::addOption(std::string name, boost::any value, std::string description){
00038 config[name] = value;
00039 descriptions[name] = description;
00040 }
00041
00042 void ParameterServer::defaultConfig() {
00043
00044 addOption("topic_image_mono", std::string("/camera/rgb/image_color"), "color or grayscale image ros topic");
00045 addOption("camera_info_topic", std::string("/camera/rgb/camera_info"), "required for backprojection if no pointcloud topic is given");
00046 addOption("topic_image_depth", std::string("/camera/depth/image"), "depth image ros topic");
00047 addOption("topic_points", std::string(""), "If omitted, xyz will be computed from depth image. ");
00048 addOption("wide_topic", std::string(""), "topics for stereo cam, e.g. /wide_stereo/left/image_mono");
00049 addOption("wide_cloud_topic", std::string(""), "topics for stereo cam e.g. /wide_stereo/points2");
00050 addOption("subscriber_queue_size", static_cast<int> (3), "cache incoming data (carefully, RGB-D Clouds are 10MB each)");
00051 addOption("drop_async_frames", static_cast<bool> (false), "Check timestamps of depth and visual image, reject if not in sync ");
00052 addOption("depth_scaling_factor", static_cast<double> (1.0), "Some kinects have a wrongly scaled depth");
00053 addOption("bagfile_name", std::string(""), "read data from a bagfile, make sure to enter the right topics above");
00054 addOption("data_skip_step", static_cast<int> (1), "skip every n-th frame completely ");
00055
00056
00057 addOption("store_pointclouds", static_cast<bool> (true), "if the point clouds are not needed online, setting this to false saves lots of memory ");
00058 addOption("individual_cloud_out_topic", std::string("/rgbdslam/batch_clouds"), "Use this topic when sending the individual clouds with the computed transforms, e.g. for octomap_server");
00059 addOption("aggregate_cloud_out_topic", std::string("/rgbdslam/aggregate_clouds"), "Use this topic when sending the all points in one big registered cloud");
00060 addOption("send_clouds_rate", static_cast<double> (5), "When sending the point clouds (e.g. to RVIZ or Octomap Server) limit sending to this many clouds per second");
00061 addOption("publisher_queue_size", static_cast<int> (5), "ROS standard parameter for all publishers");
00062
00063
00064 addOption("fixed_frame_name", std::string("/map"), "The computed camera transforms are with respect to this frame. It is set to the identity for the first frame processed or, if ground truth is available, to the ground truth of the first frame");
00065 addOption("odom_frame_name", std::string("/odom"), "A fixed frame estimation from somewhere else (e.g. odometry, laser-based mapping). Doesn't need to correspond to the pose of the fixed_frame_name");
00066 addOption("ground_truth_frame_name", std::string(""), "use empty string if no ground truth tf frame available");
00067 addOption("base_frame_name", std::string("/camera_link"), "if the camera is articulated use robot base");
00068 addOption("fixed_camera", static_cast<bool> (true), "is camera fixed relative to base?");
00069
00070
00071 addOption("feature_detector_type", std::string("SURF"), "SURF, SIFT or ORB");
00072 addOption("feature_extractor_type", std::string("SURF"), "SURF, SIFT or ORB");
00073 addOption("matcher_type", std::string("FLANN"), "SIFTGPU or FLANN or BRUTEFORCE");
00074 addOption("max_keypoints", static_cast<int> (2000), "Extract no more than this many keypoints ");
00075 addOption("min_keypoints", static_cast<int> (500), "Extract no less than this many keypoints ");
00076 addOption("min_matches", static_cast<int> (50), "don't try RANSAC if less than this many matches (if using SiftGPU and GLSL you should use max. 60 matches)");
00077 addOption("sufficient_matches", static_cast<int> (1e9), "Extract no less than this many only honored by the adjustable SURF and FAST features");
00078 addOption("adjuster_max_iterations", static_cast<int> (10), "If outside of bounds for max_kp and min_kp, retry this many times with adapted threshold");
00079 addOption("use_feature_min_depth", static_cast<bool>(true), "consider the nearest point in the neighborhood of the feature as its depth, as it will dominate the motion");
00080
00081
00082 addOption("max_translation_meter", static_cast<double> (1e10), "Sanity check for smooth motion.");
00083 addOption("max_rotation_degree", static_cast<int> (360), "Sanity check for smooth motion.");
00084 addOption("min_translation_meter", static_cast<double> (0.05), "frames with motion less than this, will be omitted ");
00085 addOption("min_rotation_degree", static_cast<int> (2.5), "frames with motion less than this, will be omitted ");
00086 addOption("max_dist_for_inliers", static_cast<double> (3), "Mahalanobis distance for matches to be considered inliers by ransac");
00087 addOption("ransac_iterations", static_cast<int> (1000), "these are fast, so high values are ok ");
00088 addOption("max_connections", static_cast<int> (15), "stop frame comparisons after this many succesfully found spation relations ");
00089 addOption("geodesic_depth", static_cast<int> (3), "For comparisons with neighbors, consider those with a graph distance (hop count) equal or below this value as neighbors of the direct predecessor");
00090 addOption("predecessor_candidates", static_cast<int> (10), "Compare Features to this many direct sequential predecessors");
00091 addOption("neighbor_candidates", static_cast<int> (10), "Compare Features to this many graph neighbours. Sample from the candidates");
00092 addOption("min_sampled_candidates", static_cast<int> (10), "Compare Features to this many uniformly sampled nodes for corrspondences ");
00093 addOption("use_icp", static_cast<bool> (false), "Activate GICP Fallback. Ignored if GICP is not compiled in (see top of CMakeLists.txt) ");
00094 addOption("gicp_max_cloud_size", static_cast<int> (10000), "Subsample for increased speed");
00095
00096 addOption("optimizer_iterations", static_cast<int> (1), "maximum of iterations in online operation (i.e., does not affect the final optimization in batch mode). Optimizer stops after convergence anyway");
00097 addOption("optimizer_skip_step", static_cast<int> (1), "optimize every n-th frame. Set high for offline operation ");
00098 addOption("backend_solver", std::string("cholmod"), "Which solver to use in g2o for matrix inversion: 'csparse' , 'cholmod' or 'pcg'");
00099
00100
00101 addOption("use_glwidget", static_cast<bool> (true), "3D view");
00102 addOption("use_gui", static_cast<bool> (true), "GUI vs Headless Mode");
00103 addOption("visualize_mono_depth_overlay", static_cast<bool> (false), "Show Depth and Monochrome image as overlay in featureflow");
00104 addOption("visualization_skip_step", static_cast<int> (1), "draw only every nth pointcloud row and line, high values require higher squared_meshing_threshold ");
00105 addOption("squared_meshing_threshold", static_cast<double> (0.0009), "don't triangulate over depth jumps. Should be increased with increasing visualization_skip_step");
00106 addOption("show_axis", static_cast<bool> (true), "do/don't visualize the pose graph in glwidget");
00107 addOption("scalable_2d_display", static_cast<bool> (false), "whether the input images are expanded. Consumes CPU time");
00108
00109
00110 addOption("start_paused", static_cast<bool> (true), "Whether to directly start mapping with the first input image, or to wait for the user to start manually");
00111 addOption("batch_processing", static_cast<bool> (false), "store results and close after bagfile has been processed");
00112 addOption("concurrent_node_construction", static_cast<bool> (true), "detect+extract features for new frame, while current frame is inserted into graph ");
00113 addOption("concurrent_optimization", static_cast<bool> (true), "detect+extract features for new frame, while current frame is inserted into graph ");
00114 addOption("concurrent_edge_construction", static_cast<bool> (true), "compare current frame to many predecessors in parallel. Note that SIFTGPU matcher and GICP are mutex'ed for thread-safety");
00115 addOption("voxelfilter_size", static_cast<double> (-1.0), "in meter voxefilter displayed and stored pointclouds, incompatible with use_glwidget=true. Set negative to disable");
00116 addOption("nn_distance_ratio", static_cast<double> (0.6), "Feature correspondence is valid if distance to nearest neighbour is smaller than this parameter times the distance to the 2nd neighbour. This needs to be 0.9-1.0 for SIFTGPU w/ FLANN, since SIFTGPU Features are normalized");
00117 addOption("keep_all_nodes", static_cast<bool> (false), "Keep nodes with 'no motion' assumption if too few inliers");
00118 addOption("min_time_reported", static_cast<double> (1e9), "for easy profiling. by default, nothing should be reported");
00119 addOption("preserve_raster_on_save", static_cast<bool> (false), "Filter NaNs when saving clouds, destroying the image raster");
00120 }
00121
00122
00123 std::string ParameterServer::getDescription(std::string param_name) {
00124 return descriptions[param_name];
00125 }
00126
00127 void ParameterServer::getValues() {
00128 map<string, boost::any>::const_iterator itr;
00129 for (itr = config.begin(); itr != config.end(); ++itr) {
00130 string name = itr->first;
00131 if (itr->second.type() == typeid(string)) {
00132 config[name] = getFromParameterServer<string> (pre + name,
00133 boost::any_cast<string>(itr->second));
00134 ROS_DEBUG_STREAM("Value for " << name << ": " << boost::any_cast<string>(itr->second));
00135 } else if (itr->second.type() == typeid(int)) {
00136 config[name] = getFromParameterServer<int> (pre + name,
00137 boost::any_cast<int>(itr->second));
00138 ROS_DEBUG_STREAM("Value for " << name << ": " << boost::any_cast<int>(itr->second));
00139 } else if (itr->second.type() == typeid(double)) {
00140 config[name] = getFromParameterServer<double> (pre + name,
00141 boost::any_cast<double>(itr->second));
00142 ROS_DEBUG_STREAM("Value for " << name << ": " << boost::any_cast<double>(itr->second));
00143 } else if (itr->second.type() == typeid(bool)) {
00144 config[name] = getFromParameterServer<bool> (pre + name,
00145 boost::any_cast<bool>(itr->second));
00146 ROS_DEBUG_STREAM("Value for " << name << ": " << boost::any_cast<bool>(itr->second));
00147 }
00148 }
00149 checkValues();
00150 }
00151
00152 void ParameterServer::checkValues() {
00153 if (get<string>("matcher_type").compare("SIFTGPU") == 0
00154 && get<bool>("concurrent_node_construction") == true) {
00155 config["concurrent_node_construction"] = static_cast<bool>(false);
00156 ROS_WARN("Cannot use concurrent node construction with SiftGPU matcher! 'concurrent_node_construction' was set to false. Everything should work fine, but the CPU-threading won't happen (because you are using the GPU instead).");
00157 }
00158
00159 if (get<string>("matcher_type").compare("SIFTGPU") == 0
00160 && get<bool>("concurrent_edge_construction") == true) {
00161 config["concurrent_edge_construction"] = static_cast<bool>(false);
00162 ROS_WARN("Cannot use concurrent edge construction with SiftGPU matcher! 'concurrent_edge_construction' was set to false. Everything should work fine, but the CPU-threading won't happen (because you are using the GPU instead).");
00163 }
00164 }