00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037 #ifndef _EXHAUSTIVE_FIT_DETECTOR_
00038 #define _EXHAUSTIVE_FIT_DETECTOR_
00039
00040 #include <vector>
00041 #include <set>
00042 #include <boost/filesystem.hpp>
00043 #include <boost/shared_ptr.hpp>
00044
00045 #include <sensor_msgs/PointCloud.h>
00046
00047 #include <household_objects_database_msgs/GetModelList.h>
00048 #include <household_objects_database_msgs/GetModelMesh.h>
00049
00050 #include "tabletop_object_detector/model_fitter.h"
00051
00052 namespace tabletop_object_detector {
00053
00055
00063 template <class Fitter>
00064 class ExhaustiveFitDetector
00065 {
00066 private:
00068 ros::NodeHandle priv_nh_;
00070 ros::NodeHandle nh_;
00072 std::vector<Fitter*> templates;
00073
00075 std::set<int> model_exclusion_set_;
00076 bool negate_exclusions_;
00077
00078 public:
00080 ExhaustiveFitDetector() : priv_nh_("~"), nh_(""), negate_exclusions_(false) {}
00082 ~ExhaustiveFitDetector();
00083
00084 void addModelToExclusionList(int model_id)
00085 {
00086 model_exclusion_set_.insert(model_id);
00087 }
00088
00089 void clearExclusionList()
00090 {
00091 model_exclusion_set_.clear();
00092 }
00093
00094 void setNegateExclusions(bool value)
00095 {
00096 negate_exclusions_ = value;
00097 }
00098
00100 void loadDatabaseModels(std::string model_set);
00101
00103
00108 template <class PointCloudType>
00109 std::vector<ModelFitInfo> fitBestModels(const PointCloudType& cloud, int numResults)
00110 {
00111 std::vector<ModelFitInfo> fit_results;
00112 if (numResults <= 0) return fit_results;
00113
00114 for (size_t i=0; i<templates.size(); ++i)
00115 {
00116 ModelFitInfo current = templates[i]->template fitPointCloud<PointCloudType>(cloud);
00117
00118 bool found = (model_exclusion_set_.find(current.getModelId()) != model_exclusion_set_.end());
00119 if (negate_exclusions_ == found)
00120 {
00121 if ((int)fit_results.size() < numResults)
00122 {
00123 fit_results.push_back(current);
00124 std::sort(fit_results.begin(), fit_results.end(), ModelFitInfo::compareScores);
00125 }
00126 else
00127 {
00128 if (fit_results.back().getScore() > current.getScore())
00129 {
00130 fit_results.back() = current;
00131 std::sort(fit_results.begin(), fit_results.end(), ModelFitInfo::compareScores);
00132 }
00133 }
00134 }
00135 }
00136 return fit_results;
00137 }
00138 };
00139
00140 template <class Fitter>
00141 ExhaustiveFitDetector<Fitter>::~ExhaustiveFitDetector()
00142 {
00143 for (size_t i=0;i<templates.size();++i) {
00144 delete templates[i];
00145 }
00146 }
00147
00159 template <class Fitter>
00160 void ExhaustiveFitDetector<Fitter>::loadDatabaseModels(std::string model_set)
00161 {
00162 std::string get_model_list_srv_name;
00163 priv_nh_.param<std::string>("get_model_list_srv", get_model_list_srv_name, "get_model_list_srv");
00164 while ( !ros::service::waitForService(get_model_list_srv_name, ros::Duration(2.0)) && nh_.ok() )
00165 {
00166 ROS_INFO("Waiting for %s service to come up", get_model_list_srv_name.c_str());
00167 }
00168 if (!nh_.ok()) exit(0);
00169 ros::ServiceClient get_model_list_srv = nh_.serviceClient<household_objects_database_msgs::GetModelList>
00170 (get_model_list_srv_name, true);
00171
00172
00173 std::string get_model_mesh_srv_name;
00174 priv_nh_.param<std::string>("get_model_mesh_srv", get_model_mesh_srv_name, "get_model_mesh_srv");
00175 while ( !ros::service::waitForService(get_model_mesh_srv_name, ros::Duration(2.0)) && nh_.ok() )
00176 {
00177 ROS_INFO("Waiting for %s service to come up", get_model_mesh_srv_name.c_str());
00178 }
00179 if (!nh_.ok()) exit(0);
00180 ros::ServiceClient get_model_mesh_srv = nh_.serviceClient<household_objects_database_msgs::GetModelMesh>
00181 (get_model_mesh_srv_name, true);
00182
00183
00184 household_objects_database_msgs::GetModelList model_list;
00185 model_list.request.model_set = model_set;
00186 if (!get_model_list_srv.call(model_list) ||
00187 model_list.response.return_code.code != model_list.response.return_code.SUCCESS )
00188 {
00189 ROS_ERROR("Could not retrieve list of models from database");
00190 return;
00191 }
00192 if (model_list.response.model_ids.empty())
00193 {
00194 ROS_ERROR("Empty model list retrieved from database");
00195 return;
00196 }
00197
00198 ROS_INFO("Object detector: loading object models");
00199 for(size_t i=0; i<model_list.response.model_ids.size(); i++)
00200 {
00201 int model_id = model_list.response.model_ids[i];
00202
00203 household_objects_database_msgs::GetModelMesh get_mesh;
00204 get_mesh.request.model_id = model_id;
00205 if ( !get_model_mesh_srv.call(get_mesh) ||
00206 get_mesh.response.return_code.code != get_mesh.response.return_code.SUCCESS )
00207 {
00208 ROS_ERROR("Failed to retrieve mesh for model %d", model_id);
00209 continue;
00210 }
00211 if (get_mesh.response.mesh.vertices.empty() || get_mesh.response.mesh.triangles.empty() )
00212 {
00213 ROS_ERROR("Empty mesh for model %d", model_id);
00214 continue;
00215 }
00216
00217 Fitter* fitter = new Fitter();
00218 fitter->initializeFromMesh(get_mesh.response.mesh);
00219 templates.push_back(fitter);
00220
00221 templates.back()->setModelId( model_id );
00222 ROS_INFO(" Loaded database model with id %d", model_id);
00223 }
00224 ROS_INFO("Object detector: loading complete");
00225 }
00226
00227 }
00228
00229 #endif