fake_object_recognition.cpp
Go to the documentation of this file.
1 
19 #include <rapidxml.hpp>
20 #include <rapidxml_utils.hpp>
21 #include <ros/package.h>
22 #include <boost/algorithm/string/predicate.hpp>
23 #include <boost/lexical_cast.hpp>
24 #include <boost/algorithm/string.hpp>
25 #include "rating.h"
26 #include "error_simulation.h"
27 #include <unistd.h>
28 #include <algorithm>
29 //Eigen
30 #include <Eigen/Geometry>
31 
32 #include "asr_object_database/ObjectMetaData.h"
33 #include "ApproxMVBB/ComputeApproxMVBB.hpp"
34 
35 namespace fake_object_recognition {
36 
37 FakeObjectRecognition::FakeObjectRecognition() : nh_(NODE_NAME), config_changed_(false), recognition_released_(true) {
38  ROS_DEBUG("Initialize process");
39  nh_.getParam("fovx", fovx_); // Field of view in x.
40  nh_.getParam("fovy", fovy_); // Field of view in y.
41  nh_.getParam("ncp", ncp_); // Near clipping plane of fustrum.
42  nh_.getParam("fcp", fcp_); // Far clipping plane of fustrum.
43  nh_.getParam("frame_world", frame_world_);
44  nh_.getParam("frame_camera_left", frame_camera_left_);
45  nh_.getParam("frame_camera_right", frame_camera_right_);
46  nh_.getParam("config_file_path", config_file_path_);
47  nh_.getParam("output_rec_objects_topic", output_rec_objects_topic_);
48  nh_.getParam("output_rec_marker_topic", output_rec_markers_topic_);
49  nh_.getParam("output_constellation_topic", output_constellation_marker_topic_);
50  nh_.getParam("output_normals_topic", output_normals_topic_);
51  nh_.getParam("rating_threshold_d", rating_threshold_d_);
52  nh_.getParam("rating_threshold_x", rating_threshold_x_);
53  nh_.getParam("rating_threshold_y", rating_threshold_y_);
54  nh_.getParam("timer_duration", timer_duration_);
55 
56  reconfigure_server_.setCallback(boost::bind(&FakeObjectRecognition::configCallback, this, _1, _2));
57 
60 
63 
67  object_normals_pub_ = nh_.advertise<visualization_msgs::MarkerArray>(output_normals_topic_, 100);
68 
70 
71  //Only used here to visualize object constellation. The rest (errors etc) is done at first doRecognition() call.
72  loadObjects();
73 
74  // initialize bounding boxes and normals:
75  ROS_DEBUG_STREAM("Initializing object bounding boxes and normals");
76  // Set up service to get normals:
77  ros::service::waitForService("/asr_object_database/object_meta_data");
78  object_metadata_service_client_ = nh_.serviceClient<asr_object_database::ObjectMetaData>("/asr_object_database/object_meta_data");
79  // Set bounding box corner point filename:
80  bb_corners_file_name_ = ros::package::getPath("asr_fake_object_recognition") + "/config/bounding_box_corners.xml";
81  // Set object databse package name:
82  object_database_name_ = "asr_object_database";
83 
84  for (std::vector<ObjectConfig>::iterator iter = objects_.begin(); iter != objects_.end(); ++iter) {
85  if (normals_.find(iter->getType()) == normals_.end()) { // if normals of object type not yet initialized
86  ROS_DEBUG_STREAM("Initializing normals of object type " << iter->getType());
87  normals_[iter->getType()] = getNormals(*iter);
88  ROS_DEBUG_STREAM("Found " << normals_[iter->getType()].size() << " normals. Normals initialized.");
89  }
90  if (bounding_box_corners_.find(iter->getType()) == bounding_box_corners_.end()) { // if bounding box corners of object type not yet initialized
91  ROS_DEBUG_STREAM("Initializing bounding box of object type " << iter->getType());
92  std::array<geometry_msgs::Point, 8> corner_points;
93  if (!getBBfromFile(corner_points, iter->getType())) { // No corners were found in file: calculate and write them to file
94  corner_points = calculateBB(*iter);
95  }
96  bounding_box_corners_[iter->getType()] = corner_points;
97  ROS_DEBUG_STREAM("Found " << bounding_box_corners_[iter->getType()].size() << " bounding box corner points. Bounding box initialized.");
98  }
99  }
100  ROS_INFO("Recognition is initially released");
101 }
102 
104  objects_.clear();
105 
106  std::string xml_path;
107  if (boost::starts_with(config_file_path_, ".")) //if path starts with a point, assume it's a relative path.
108  {
109  xml_path = ros::package::getPath("asr_fake_object_recognition") + config_file_path_.substr(1);
110  }
111  else //Otherwise use it as an absolute path
112  {
113  xml_path = config_file_path_;
114  }
115  ROS_DEBUG_STREAM("Path to objects.xml: " << xml_path);
116 
117  try {
118  rapidxml::file<> xmlFile(xml_path.c_str());
119  rapidxml::xml_document<> doc;
120  doc.parse<0>(xmlFile.data());
121 
122  rapidxml::xml_node<> *root_node = doc.first_node();
123  if (root_node) {
124  rapidxml::xml_node<> *child_node = root_node->first_node();
125  while (child_node) {
126  rapidxml::xml_attribute<> *type_attribute = child_node->first_attribute("type");
127  rapidxml::xml_attribute<> *id_attribute = child_node->first_attribute("id");
128  rapidxml::xml_attribute<> *mesh_attribute = child_node->first_attribute("mesh");
129  rapidxml::xml_attribute<> *angles_attribute = child_node->first_attribute("angles");
130  if (type_attribute && id_attribute && mesh_attribute && angles_attribute) {
131  std::string type = type_attribute->value();
132  std::string mesh = mesh_attribute->value();
133  std::string id = id_attribute->value();
134  std::string pose_string = child_node->value();
135  std::string angles = angles_attribute->value();
136  geometry_msgs::Pose pose;
137  if (parsePoseString(pose_string, pose, " ,", angles)) {
138  objects_.push_back(ObjectConfig(type, id, pose, mesh));
139  }
140  }
141  child_node = child_node->next_sibling();
142  }
143  }
144  } catch(std::runtime_error err) {
145  ROS_DEBUG_STREAM("Can't parse xml-file. Runtime error: " << err.what());
146  } catch (rapidxml::parse_error err) {
147  ROS_DEBUG_STREAM("Can't parse xml-file Parse error: " << err.what());
148  }
149 
150 }
151 
152 
153 bool FakeObjectRecognition::parsePoseString(std::string pose_in, geometry_msgs::Pose &pose_out, std::string delim, std::string angles) {
154  std::vector<std::string> strvec;
155 
156  boost::algorithm::trim_if(pose_in, boost::algorithm::is_any_of(delim));
157  boost::algorithm::split(strvec, pose_in, boost::algorithm::is_any_of(delim), boost::algorithm::token_compress_on);
158  if (strvec.size() == 6 || strvec.size() == 7) {
159  try {
160  pose_out.position.x = boost::lexical_cast<double>(strvec[0]);
161  pose_out.position.y = boost::lexical_cast<double>(strvec[1]);
162  pose_out.position.z = boost::lexical_cast<double>(strvec[2]);
163 
164  if(angles == "quaternion" && strvec.size() == 7)
165  {
166  pose_out.orientation.w = boost::lexical_cast<double>(strvec[3]);
167  pose_out.orientation.x = boost::lexical_cast<double>(strvec[4]);
168  pose_out.orientation.y = boost::lexical_cast<double>(strvec[5]);
169  pose_out.orientation.z = boost::lexical_cast<double>(strvec[6]);
170  }
171  else if(angles == "euler" && strvec.size() == 6)
172  {
173  double euler0,euler1,euler2;
174  euler0 = boost::lexical_cast<double>(strvec[3]);
175  euler1 = boost::lexical_cast<double>(strvec[4]);
176  euler2 = boost::lexical_cast<double>(strvec[5]);
177 
178  Eigen::Matrix3d rotationMatrix;
179  rotationMatrix = Eigen::AngleAxisd(euler0 * (M_PI / 180), Eigen::Vector3d::UnitX())
180  * Eigen::AngleAxisd(euler1 * (M_PI / 180), Eigen::Vector3d::UnitY())
181  * Eigen::AngleAxisd(euler2 * (M_PI / 180), Eigen::Vector3d::UnitZ());
182 
183  Eigen::Quaternion<double> result(rotationMatrix);
184  pose_out.orientation.w = result.w();
185  pose_out.orientation.x = result.x();
186  pose_out.orientation.y = result.y();
187  pose_out.orientation.z = result.z();
188  }
189  else
190  {
191  ROS_ERROR("Invalid XML syntax.");
192  nh_.shutdown();
193  }
194 
195  return true;
196  } catch (boost::bad_lexical_cast err) {
197  ROS_DEBUG_STREAM("Can't cast node-value. Cast error: " << err.what());
198  }
199  }
200  return false;
201 }
202 
203 bool FakeObjectRecognition::processGetRecognizerRequest(GetRecognizer::Request &req, GetRecognizer::Response &res) {
204  ROS_DEBUG("Get recognizer request");
205  if(std::find(objects_to_rec_.begin(), objects_to_rec_.end(), req.object_type_name) != objects_to_rec_.end()) {
206  ROS_DEBUG("Requested object is already in list of recognizable objects");
207  } else {
208  ROS_DEBUG("Add requested object to recognizable object list");
209  objects_to_rec_.push_back(req.object_type_name);
210  recognition_released_ = false;
211  }
212  return true;
213 }
214 
215 bool FakeObjectRecognition::processReleaseRecognizerRequest(ReleaseRecognizer::Request &req, ReleaseRecognizer::Response &res) {
216  ROS_DEBUG("Release recognizer request");
217  objects_to_rec_.erase(std::remove(objects_to_rec_.begin(), objects_to_rec_.end(), req.object_type_name), objects_to_rec_.end());
218  if (!(objects_to_rec_.size() > 0)) {
219  recognition_released_ = true;
220  }
221  return true;
222 }
223 
224 bool FakeObjectRecognition::processGetAllRecognizersRequest(GetAllRecognizers::Request &req, GetAllRecognizers::Response &res) {
225  ROS_DEBUG("Get all recognizers request");
226 
227  objects_to_rec_.clear();
228  for(std::vector<ObjectConfig>::iterator objectIt = objects_.begin(); objectIt != objects_.end(); objectIt++){
229  ROS_DEBUG_STREAM("Adding objects " << objectIt->getType() << " to recognizable list");
230  objects_to_rec_.push_back(objectIt->getType());
231 
232  }
233 
234  recognition_released_ = false;
235  return true;
236 
237 }
238 
239 bool FakeObjectRecognition::processClearAllRecognizers(ClearAllRecognizers::Request &req, ClearAllRecognizers::Response &res) {
240  ROS_DEBUG("Clear all recognizers request");
241  objects_to_rec_.clear();
242  recognition_released_ = true;
243  return true;
244 }
245 
247  for (std::vector<ObjectConfig>::iterator iter = objects_.begin(); iter != objects_.end(); ++iter) {
248  //Generating marker for each object that is present in config file.
249  asr_msgs::AsrObjectPtr asr_msg = createAsrMessage(*iter, iter->getPose(), frame_world_);
251  // Generating normal markers for each object.
252  visualization_msgs::MarkerArray::Ptr normal_markers = createNormalMarker(*iter, (iter - objects_.begin()) * 100, 10 * timer_duration_);
253  object_normals_pub_.publish(normal_markers); // can have up to 100 normals
254  }
255  if (!recognition_released_) {
256  doRecognition();
257  }
258 }
259 
260 void FakeObjectRecognition::configCallback(FakeObjectRecognitionConfig &config, uint32_t level) {
261  config_changed_ = true;
262  config_ = config;
263 }
264 
266  ROS_INFO("Do recognition");
267  // React to changed config:
268  if (config_changed_) {
269  ROS_DEBUG("Configuration change");
270  ROS_DEBUG("Load Objects");
271  if (config_file_path_ != config_.config_file_path) {
272  ROS_INFO_STREAM("Path to config file has changed. Recognition is released");
273  config_file_path_ = config_.config_file_path;
274  objects_to_rec_.clear();
275  recognition_released_ = true;
276  return;
277  }
278  loadObjects();
279  err_sim_ = ErrorSimulation(config_.use_pose_invalidation, config_.use_position_noise, config_.use_orientation_noise);
280  err_sim_.setProbPoseInval(config_.prob_pose_invalidation);
281  err_sim_.setPoseNoiseDistMean(config_.pos_noise_normal_dist_mean);
282  err_sim_.setPoseNoiseDistDev(config_.pos_noise_normal_dist_dev);
283  err_sim_.setOrXNoiseDistMean(config_.or_x_noise_normal_dist_mean);
284  err_sim_.setOrXNoiseDistDev(config_.or_x_noise_normal_dist_dev);
285  err_sim_.setOrYNoiseDistMean(config_.or_y_noise_normal_dist_mean);
286  err_sim_.setOrYNoiseDistDev(config_.or_y_noise_normal_dist_dev);
287  err_sim_.setOrZNoiseDistMean(config_.or_z_noise_normal_dist_mean);
288  err_sim_.setOrZNoiseDistDev(config_.or_z_noise_normal_dist_dev);
289  config_changed_ = false;
290  }
291  // Print all loaded objects to debug stream:
292  std::string recognizable_objects;
293  std::string objects_to_rec;
294  for (std::vector<ObjectConfig>::iterator iter = objects_.begin(); iter != objects_.end(); ++iter) {
295  recognizable_objects += iter->getType() + " ";
296  }
297  ROS_DEBUG_STREAM("All recognizable objects: " << recognizable_objects);
298  // Print all Objects for which recognition has been requested (via processGetRecognizerRequest or processGetAllRecognizersRequest) to debug stream:
299  for (std::vector<std::string>::iterator iter = objects_to_rec_.begin(); iter != objects_to_rec_.end(); ++iter) {
300  objects_to_rec += *iter + " ";
301  }
302  ROS_DEBUG_STREAM("Objects to recognize: " << objects_to_rec);
303 
304  for (std::vector<ObjectConfig>::iterator iter = objects_.begin(); iter != objects_.end(); ++iter) { // for all loaded (recognizable) objects:
305  if(std::find(objects_to_rec_.begin(), objects_to_rec_.end(), iter->getType()) == objects_to_rec_.end()) { // unless end of vector of requested objects is reached:
306  continue;
307  }
308  ROS_INFO_STREAM("Current object: '" << iter->getType() << "'");
309  geometry_msgs::Pose pose_left;
310  geometry_msgs::Pose pose_right;
311 
312  std::array<geometry_msgs::Point, 8> bounding_box = bounding_box_corners_[iter->getType()]; // Bounding box, given as corner points relative to object frame
313  std::array<geometry_msgs::Point, 8> bb_left;
314  std::array<geometry_msgs::Point, 8> bb_right;
315 
316  std::vector<geometry_msgs::Point> normals = normals_[iter->getType()]; // Object normals
317  std::vector<geometry_msgs::Point> normals_left;
318  std::vector<geometry_msgs::Point> normals_right;
319 
320  try {
321  if (config_.use_camera_pose) { // If camera pose is used:
322  ROS_DEBUG_STREAM("Transform into camera frame");
323 
324  pose_left = transformFrame((*iter).getPose(), frame_world_, frame_camera_left_);
325  pose_right = transformFrame((*iter).getPose(), frame_world_, frame_camera_right_);
326 
327  ROS_DEBUG_STREAM("Pose left: " << pose_left.position.x << " " << pose_left.position.y << " " << pose_left.position.z << " " << pose_left.orientation.w << " " << pose_left.orientation.x << " " << pose_left.orientation.y << " " << pose_left.orientation.z << " ");
328  ROS_DEBUG_STREAM("Pose right: " << pose_right.position.x << " " << pose_right.position.y << " " << pose_right.position.z << " " << pose_right.orientation.w << " " << pose_right.orientation.x << " " << pose_right.orientation.y << " " << pose_right.orientation.z << " ");
329 
331  pose_right = err_sim_.addNoiseToOrientation(err_sim_.addNoiseToPosition(pose_right));
332 
333  ROS_DEBUG_STREAM("Pose left (with errors): " << pose_left.position.x << " " << pose_left.position.y << " " << pose_left.position.z << " " << pose_left.orientation.w << " " << pose_left.orientation.x << " " << pose_left.orientation.y << " " << pose_left.orientation.z << " ");
334  ROS_DEBUG_STREAM("Pose right (with errors): " << pose_right.position.x << " " << pose_right.position.y << " " << pose_right.position.z << " " << pose_right.orientation.w << " " << pose_right.orientation.x << " " << pose_right.orientation.y << " " << pose_right.orientation.z << " ");
335 
336  // for bounding box and normals transformation:
337  Eigen::Quaterniond rot_left(pose_left.orientation.w, pose_left.orientation.x, pose_left.orientation.y, pose_left.orientation.z);
338  Eigen::Quaterniond rot_right(pose_right.orientation.w, pose_right.orientation.x, pose_right.orientation.y, pose_right.orientation.z);
339  // Transform bounding box corner points:
340  ROS_DEBUG_STREAM("Transform " << bounding_box.size() << " bounding box corner points.");
341  Eigen::Vector3d trans_left(pose_left.position.x, pose_left.position.y, pose_left.position.z);
342  Eigen::Vector3d trans_right(pose_right.position.x, pose_right.position.y, pose_right.position.z);
343  bb_left = transformPoints(bounding_box, rot_left, trans_left);
344  bb_right = transformPoints(bounding_box, rot_right, trans_right);
345 
346  //Transform normals (Rotate according to object pose):
347  ROS_DEBUG_STREAM("Transform " << normals.size() << " normals.");
348  normals_left = transformPoints(normals, rot_left, Eigen::Vector3d(0.0, 0.0, 0.0));
349  normals_right = transformPoints(normals, rot_right, Eigen::Vector3d(0.0, 0.0, 0.0));
350  } else {
351  ROS_DEBUG_STREAM("Camera pose is not used");
352  }
353  } catch (tf2::LookupException &exc) {
354  ROS_DEBUG_STREAM("Lookup exception at doRecognition: " << exc.what());
355  continue;
356  } catch (tf2::ExtrapolationException &exc) {
357  ROS_DEBUG_STREAM("Extrapolation exception at doRecognition: " << exc.what());
358  continue;
359  } catch (tf2::InvalidArgumentException &exc) {
360  ROS_DEBUG_STREAM("Invalid argument exception at doRecognition: " << exc.what());
361  continue;
362  } catch (tf2::ConnectivityException &exc) {
363  ROS_DEBUG_STREAM("Connectivity exception at doRecognition: " << exc.what());
364  continue;
365  }
366 
367  //if (!(config_.use_camera_pose) || objectIsVisible(pose_left, pose_right)) { // old way of doing the following
368  if (!(config_.use_camera_pose) || objectIsVisible(bb_left, bb_right, pose_left, pose_right, normals_left, normals_right)) { // If camera pose is not used OR camera pose is used and objectIsVisible() returns true:
369  ROS_INFO_STREAM("Object '" << (*iter).getType() << "' was found");
370  asr_msgs::AsrObjectPtr asr_msg;
371  if (!(config_.use_camera_pose)) {
372  asr_msg = createAsrMessage(*iter, iter->getPose(), frame_world_);
373  } else {
374  asr_msg = createAsrMessage(*iter, pose_left, frame_camera_left_);
375  }
378  }
379  }
380  ROS_INFO("---------------------------------- \n");
381 }
382 
383 geometry_msgs::Pose FakeObjectRecognition::transformFrame(const geometry_msgs::Pose &pose, const std::string &frame_from, const std::string &frame_to) {
384  //lookup transform to get latest timestamp
385  tf::StampedTransform transform;
386  listener_.lookupTransform(frame_from, frame_to, ros::Time(0), transform);
387 
388  geometry_msgs::PoseStamped stamped_in;
389  stamped_in.header.frame_id = frame_from;
390  stamped_in.header.stamp = transform.stamp_;
391  stamped_in.pose.position = pose.position;
392  stamped_in.pose.orientation = pose.orientation;
393 
394  geometry_msgs::PoseStamped stamped_out;
395  listener_.transformPose(frame_to, stamped_in, stamped_out);
396 
397  geometry_msgs::Pose result;
398  result.position = stamped_out.pose.position;
399  result.orientation = stamped_out.pose.orientation;
400 
401  return result;
402 }
403 // Currently not used anymore:
404 bool FakeObjectRecognition::objectIsVisible(const geometry_msgs::Pose &pose_left, const geometry_msgs::Pose &pose_right) {
405  Rating rating(fovx_, fovy_, ncp_, fcp_);
406  bool pose_inval = err_sim_.poseInvalidation();
407  if (!pose_inval) {ROS_DEBUG("Pose is invalid (simulated error)");}
408 
409  bool rating_result = false;
410  ROS_DEBUG("Rating in left camera:");
411  bool left_rating = rating.ratePose(pose_left, rating_threshold_d_, rating_threshold_x_, rating_threshold_y_);
412  ROS_DEBUG("Rating in left camera:");
413  bool right_rating = rating.ratePose(pose_right, rating_threshold_d_, rating_threshold_x_, rating_threshold_y_);
414 
415  switch(config_.frustum_mode) {
416  case 1: rating_result = left_rating | right_rating; ROS_DEBUG("Rating left and right pose (OR)"); break;
417  case 2: rating_result = left_rating; ROS_DEBUG("Rating left pose only"); break;
418  case 3: rating_result = right_rating; ROS_DEBUG("Rating right pose only"); break;
419  default: rating_result = left_rating & right_rating; ROS_DEBUG("Rating left and right pose (AND)");
420  }
421 
422 
423  if (rating_result && pose_inval) {
424  return true;
425  }
426  return false;
427 }
428 // Currently used:
429 bool FakeObjectRecognition::objectIsVisible(const std::array<geometry_msgs::Point, 8> &bb_left, const std::array<geometry_msgs::Point, 8> &bb_right,
430  const geometry_msgs::Pose &pose_left, const geometry_msgs::Pose &pose_right,
431  const std::vector<geometry_msgs::Point> &normals_left, const std::vector<geometry_msgs::Point> &normals_right) {
432  Rating rating(fovx_, fovy_, ncp_, fcp_);
433  bool pose_inval = err_sim_.poseInvalidation();
434  if (!pose_inval) {ROS_DEBUG("Pose is invalid (simulated error)");}
435 
436  bool rating_result = false;
437  bool left_rating = rating.rateBBandNormal(pose_left, bb_left, normals_left, rating_threshold_);
438  bool right_rating = rating.rateBBandNormal(pose_right, bb_right, normals_right, rating_threshold_);
439 
440 
441  switch(config_.frustum_mode) {
442  case 1: rating_result = left_rating | right_rating; ROS_DEBUG("Rating left and right pose (OR)"); break;
443  case 2: rating_result = left_rating; ROS_DEBUG("Rating left pose only"); break;
444  case 3: rating_result = right_rating; ROS_DEBUG("Rating right pose only"); break;
445  default: rating_result = left_rating & right_rating; ROS_DEBUG("Rating left and right pose (AND)");
446  }
447 
448 
449  if (rating_result && pose_inval) {
450  return true;
451  }
452  return false;
453 }
454 
455 asr_msgs::AsrObjectPtr FakeObjectRecognition::createAsrMessage(const ObjectConfig &object_config, const geometry_msgs::Pose &pose, const std::string &frame_id) {
456  asr_msgs::AsrObjectPtr object;
457  object.reset(new asr_msgs::AsrObject());
458 
459  std_msgs::Header header;
460  header.frame_id = frame_id;
461  header.stamp = ros::Time::now();
462  object->header = header;
463  object->providedBy = "fake_object_recognition";
464 
465  geometry_msgs::PoseWithCovariance pose_covariance;
466  pose_covariance.pose.position.x = pose.position.x;
467  pose_covariance.pose.position.y = pose.position.y;
468  pose_covariance.pose.position.z = pose.position.z;
469  pose_covariance.pose.orientation.w = pose.orientation.w;
470  pose_covariance.pose.orientation.x = pose.orientation.x;
471  pose_covariance.pose.orientation.y = pose.orientation.y;
472  pose_covariance.pose.orientation.z = pose.orientation.z;
473 
474  for(unsigned int i = 0; i < pose_covariance.covariance.size(); i++) {
475  pose_covariance.covariance.at(i) = 0.0f;
476  }
477  object->sampledPoses.push_back(pose_covariance);
478 
479  // Bounding Box:
480  boost::array< ::geometry_msgs::Point_<std::allocator<void> > , 8> bounding_box;
481  std::array<geometry_msgs::Point, 8> object_bb = bounding_box_corners_[object_config.getType()];
482  for (unsigned int i = 0; i < 8; i++) {
483  bounding_box[i] = object_bb.at(i);
484  }
485  object->boundingBox = bounding_box;
486 
487  if(object_config.getId() == std::string("0"))
488  {
489  object->colorName = "textured";
490  }
491  else
492  {
493  object->color = getMeshColor(object_config.getId());
494  }
495  object->type = object_config.getType();
496 
497  object->identifier = object_config.getId();
498  object->meshResourcePath = object_config.getMeshName();
499 
500  //object->sizeConfidence = pose_rec->getResults().at(results_index)->getScore3D();
501  //object->typeConfidence = pose_rec->getResults().at(results_index)->getScore2D();
502 
503  return object;
504 }
505 
506 visualization_msgs::Marker FakeObjectRecognition::createMarker(const asr_msgs::AsrObjectPtr &object, int id, int lifetime, bool use_col_init) {
507  visualization_msgs::Marker marker;
508  marker.header = object->header;
509  marker.id = id;
510  marker.action = visualization_msgs::Marker::ADD;
511  marker.pose.position = object->sampledPoses.front().pose.position;
512  marker.pose.orientation = object->sampledPoses.front().pose.orientation;
513 
514  if (use_col_init) {
515  marker.color = createColorRGBA(0.0, 0.0, 1.0, 0.4);
516  marker.ns = "Available objects";
517  } else {
518  marker.color = getMeshColor(object->identifier);
519  marker.ns = "Recognition results";
520  }
521 
522  marker.scale.x = 0.001;
523  marker.scale.y = 0.001;
524  marker.scale.z = 0.001;
525 
526  marker.mesh_use_embedded_materials = true;
527  marker.type = visualization_msgs::Marker::MESH_RESOURCE;
528  marker.mesh_resource = object->meshResourcePath;
529  marker.lifetime = ros::Duration(lifetime);
530 
531  return marker;
532 }
533 
534 
535 /* only working because the shape-based recognizer sets the observedId with the object color */
536 std_msgs::ColorRGBA FakeObjectRecognition::getMeshColor(std::string observed_id)
537 {
538  std_msgs::ColorRGBA retColor = FakeObjectRecognition::createColorRGBA(0.0, 0.0, 0.0, 0.0);
539 
540  if (( observed_id.length() == 12 ) && ( observed_id.find_first_not_of("0123456789") == std::string::npos )) {
541  float rgba[4];
542  bool isColor = true;
543  try {
544  for (int i = 0; i <= 3; i++) {
545  std::string temp;
546  temp = observed_id.substr( (i * 3), 3 );
547  rgba[i] = std::stof(temp) / 100.0;
548  }
549  } catch (std::invalid_argument& ia) {
550  ROS_DEBUG_STREAM(ia.what());
551  isColor = false;
552  }
553 
554  if(isColor) {
555  retColor = FakeObjectRecognition::createColorRGBA(rgba[0], rgba[1], rgba[2], 1.0);
556  }
557  }
558  return retColor;
559 }
560 
561 std_msgs::ColorRGBA FakeObjectRecognition::createColorRGBA(float red, float green, float blue, float alpha) {
562  std_msgs::ColorRGBA color;
563 
564  color.r = red;
565  color.g = green;
566  color.b = blue;
567  color.a = alpha;
568 
569  return color;
570 }
571 
572 std::vector<geometry_msgs::Point> FakeObjectRecognition::transformPoints(std::vector<geometry_msgs::Point> points_list, Eigen::Quaterniond rotation, Eigen::Vector3d translation) {
573  std::vector<geometry_msgs::Point> result_list = points_list;
574  rotation.normalize();
575  Eigen::Matrix3d rot_mat = rotation.toRotationMatrix();
576  for (unsigned int i = 0; i < points_list.size(); i++) {
577  Eigen::Vector3d current_point = Eigen::Vector3d(points_list.at(i).x, points_list.at(i).y, points_list.at(i).z);
578  current_point = rot_mat * current_point;
579  current_point += translation;
580  result_list.at(i) = createPoint(current_point.x(), current_point.y(), current_point.z());
581  }
582  return result_list;
583 }
584 
585 std::array<geometry_msgs::Point, 8> FakeObjectRecognition::transformPoints(std::array<geometry_msgs::Point, 8> points_list, Eigen::Quaterniond rotation, Eigen::Vector3d translation) {
586  std::vector<geometry_msgs::Point> points_vector;
587  for (unsigned int i = 0; i < points_list.size(); i++) {
588  points_vector.push_back(points_list.at(i));
589  }
590  points_vector = transformPoints(points_vector, rotation, translation);
591  std::array<geometry_msgs::Point, 8> result_array;
592  for (unsigned int i = 0; i < result_array.size(); i++) {
593  result_array.at(i) = points_vector.at(i);
594  }
595  return result_array;
596 }
597 
598 visualization_msgs::MarkerArray::Ptr FakeObjectRecognition::createNormalMarker(const ObjectConfig &object, int id, int lifetime) {
599  // Visualize normals (similar to next_best_view VisualizationsHelper.hpp, MarkerHelper.cpp:
600  visualization_msgs::MarkerArray::Ptr objectNormalsMarkerArrayPtr;
601 
602  Eigen::Matrix<float, 4, 1> color = Eigen::Matrix<float, 4, 1>(1.0, 1.0, 0.0, 1.0);
603  Eigen::Matrix<float, 3, 1> scale = Eigen::Matrix<float, 3, 1>(0.005, 0.01, 0.005);
604  std::string ns = "ObjectNormals";
605 
606  // create common arrow marker:
607  visualization_msgs::Marker objectNormalMarker;
608  objectNormalMarker.header.frame_id = "/map";
609  objectNormalMarker.lifetime = ros::Duration(lifetime);
610  objectNormalMarker.ns = ns;
611  objectNormalMarker.action = visualization_msgs::Marker::ADD;
612 
613  objectNormalMarker.type = visualization_msgs::Marker::ARROW;
614  objectNormalMarker.pose.position = createPoint(0, 0, 0);
615  objectNormalMarker.pose.orientation.x = 0.0;
616  objectNormalMarker.pose.orientation.y = 0.0;
617  objectNormalMarker.pose.orientation.z = 0.0;
618  objectNormalMarker.pose.orientation.w = 1.0;
619  // the model size unit is mm
620  objectNormalMarker.scale.x = scale[0];
621  objectNormalMarker.scale.y = scale[1];
622  objectNormalMarker.scale.z = scale[2];
623 
624  objectNormalMarker.color.r = color[0];
625  objectNormalMarker.color.g = color[1];
626  objectNormalMarker.color.b = color[2];
627  objectNormalMarker.color.a = color[3];
628 
629  objectNormalsMarkerArrayPtr = boost::make_shared<visualization_msgs::MarkerArray>();
630  // transform normals into world frame
631  std::vector<geometry_msgs::Point> normals = normals_[object.getType()];
632  geometry_msgs::Pose object_pose = object.getPose();
633  Eigen::Quaterniond rotation(object_pose.orientation.w, object_pose.orientation.x, object_pose.orientation.y, object_pose.orientation.z);
634  normals = transformPoints(normals, rotation, Eigen::Vector3d(0.0, 0.0, 0.0));
635  for(unsigned int i = 0; i < normals_[object.getType()].size(); i++) {
636  geometry_msgs::Point start = object.getPose().position;
637  geometry_msgs::Point end;
638  end = createPoint(0.07 * normals.at(i).x, 0.07 * normals.at(i).y, 0.07 * normals.at(i).z);
639  end.x += start.x;
640  end.y += start.y;
641  end.z += start.z;
642  // Set individual parts of objectNormalMarker:
643  objectNormalMarker.header.stamp = ros::Time();
644  objectNormalMarker.id = id + i;
645 
646  objectNormalMarker.points = std::vector<geometry_msgs::Point>(); // Reset objectNormalMarker.points
647  objectNormalMarker.points.push_back(start);
648  objectNormalMarker.points.push_back(end);
649 
650  objectNormalsMarkerArrayPtr->markers.push_back(objectNormalMarker);
651  }
652  return objectNormalsMarkerArrayPtr;
653 }
654 
655 std::vector<geometry_msgs::Point> FakeObjectRecognition::getNormals(const ObjectConfig &object) {
656  // init normals: (similar to next_best_view ObjectHelper.h)
657  std::vector<geometry_msgs::Point> temp_normals = std::vector<geometry_msgs::Point>();
658 
659  // Takes the mesh file path and cuts off the beginning ("package://asr_object_database/rsc/databases/")
660  // and everything after the next "_", leaving only the recognizer name of the object.
661  std::vector<std::string> strvec;
662  std::string in = object.getMeshName();
663  boost::algorithm::trim_if(in, boost::algorithm::is_any_of("_/"));
664  boost::algorithm::split(strvec, in, boost::algorithm::is_any_of("_/"));
665  ROS_DEBUG_STREAM("Recognizer name of object: " << strvec.at(7));
666  std::string recognizer = strvec.at(7);
667 
668  // Get the object's meta data containing the normals:
669  asr_object_database::ObjectMetaData objectMetaData;
670  objectMetaData.request.object_type = object.getType();
671  objectMetaData.request.recognizer = recognizer;
672 
673  if (!object_metadata_service_client_.exists()) { ROS_DEBUG_STREAM("/asr_object_database/object_meta_data service is not available"); }
674  else {
675  object_metadata_service_client_.call(objectMetaData);
676  if (!objectMetaData.response.is_valid) { ROS_DEBUG_STREAM("objectMetadata response is not valid for object type " << object.getType()); }
677  else { temp_normals = objectMetaData.response.normal_vectors; }
678  }
679  return temp_normals; // temp_normals: Empty if no normals were found (if some objects don't have any).
680 }
681 
682 bool FakeObjectRecognition::getBBfromFile(std::array<geometry_msgs::Point, 8> &result, std::string object_type) {
683  // init bounding box:
684  // open config/bounding_box_corners.xml and check whether the corners for the respective object have already been calculated and stored there:
685  ROS_DEBUG_STREAM("Looking for bounding box corner points in " << bb_corners_file_name_);
686  std::string corners_string;
687  if (std::ifstream(bb_corners_file_name_)) {
688  try {
689  rapidxml::file<> xmlFile(bb_corners_file_name_.c_str());
690  rapidxml::xml_document<> doc;
691  doc.parse<0>(xmlFile.data());
692  rapidxml::xml_node<> *root_node = doc.first_node();
693  if (root_node) {
694  rapidxml::xml_node<> *child_node = root_node->first_node();
695  while (child_node) {
696  rapidxml::xml_attribute<> *type_attribute = child_node->first_attribute("type");
697  if (type_attribute) {
698  if (object_type == type_attribute->value()) {
699  rapidxml::xml_node<> *bb_corners_node = child_node->first_node();
700  if (bb_corners_node) {
701  corners_string = bb_corners_node->value();
702  }
703  else {
704  ROS_DEBUG_STREAM("Could not find values in node with attribute type = \"" << object_type << "\"");
705  }
706  break;
707  }
708  }
709  child_node = child_node->next_sibling();
710  }
711  }
712  } catch(std::runtime_error err) {
713  ROS_DEBUG_STREAM("Can't parse xml-file. Runtime error: " << err.what());
714  } catch (rapidxml::parse_error err) {
715  ROS_DEBUG_STREAM("Can't parse xml-file Parse error: " << err.what());
716  }
717  }
718  else {
719  ROS_DEBUG_STREAM("File " << bb_corners_file_name_ << " does not exist. Will be created when calculating new bounding box corners.");
720  }
721  std::array<geometry_msgs::Point, 8> corner_points;
722  if (corners_string.length() > 0) { // Bounding box corners were found
723  // get the floats from the input file:
724  std::stringstream cornerstream;
725  cornerstream.str(corners_string);
726  std::string corner_coord;
727  std::vector<float> coord_list;
728  try {
729  while (std::getline(cornerstream, corner_coord, ' ')) {
730  coord_list.push_back(std::stof(corner_coord));
731  }
732  } catch (std::invalid_argument& ia) {
733  ROS_DEBUG_STREAM(ia.what());
734  coord_list = std::vector<float>(); // return empty list: try to calculate new corner points instead
735  }
736  unsigned int j = 0;
737  for (unsigned int i = 0; i <= coord_list.size() - 3; i+=3) {
738  corner_points.at(j) = createPoint(coord_list.at(i), coord_list.at(i+1), coord_list.at(i+2));
739  j++;
740  }
741  }
742  else {
743  return false;
744  }
745  result = corner_points;
746  return true;
747 }
748 
749 std::array<geometry_msgs::Point, 8> FakeObjectRecognition::calculateBB(const ObjectConfig &object) {
750  /* Takes a .dae file, parses it, and finds position vertices of the mesh if available.
751  * Uses the vertices as input for ApproxMVBB, which calculates an approximated Minimum Volume Bounding Box.
752  * Then the 8 corner points of the bouding box are calculated and transformed into the object frame.
753  * Finally, they are scaled with 0.001 so the measurements are in m.
754  * The points appear in the list in the following order (like in pbd_msgs/PbdObject.msg):
755  * 4-----5 z
756  * /| /| / x right
757  * / | / | / y down
758  * 0-----1 | /-------x z forwar
759  * | | | | |
760  * | 6--|--7 |
761  * | / | / |
762  * |/ |/ y
763  * 2-----3
764  * If no bounding box could be found, a vector containing only the object's center 8 times is used.
765  * Result is written to file bb_corners_file_name_.*/
766  // Get mesh input file:
767  std::string to_cut = "package://" + object_database_name_;
768  unsigned int length_to_cut = to_cut.length();
769  std::string mesh_path = ros::package::getPath(object_database_name_) + object.getMeshName().substr(length_to_cut); // cuts off "package://asr_object_database" from object's meshName
770  ROS_DEBUG_STREAM("Looking for mesh in: " << mesh_path);
771 
772  // Parse the input file:
773  std::string vertices;
774  try {
775  rapidxml::file<> xmlFile(mesh_path.c_str());
776  rapidxml::xml_document<> doc;
777  doc.parse<0>(xmlFile.data());
778  rapidxml::xml_node<> *collada_node = doc.first_node("COLLADA");
779  if (!collada_node) ROS_DEBUG_STREAM("Could not find node " << "COLLADA");
780  else {
781  rapidxml::xml_node<> *lib_geom_node = collada_node->first_node("library_geometries");
782  if (!lib_geom_node) ROS_DEBUG_STREAM("Could not find node " << "library_geometries");
783  else {
784  rapidxml::xml_node<> *geom_node = lib_geom_node->first_node("geometry");
785  if (!geom_node) ROS_DEBUG_STREAM("Could not find node " << "geometry");
786  else {
787  rapidxml::xml_node<> *mesh_node = geom_node->first_node("mesh");
788  if (!mesh_node) ROS_DEBUG_STREAM("Could not find node " << "mesh");
789  else {
790  rapidxml::xml_node<> *source_node = mesh_node->first_node("source");
791  while (source_node) {
792  rapidxml::xml_attribute<> *name_attribute = source_node->first_attribute("name");
793  std::string name;
794  if (name_attribute) {
795  name = name_attribute->value();
796  if (name == "position") {
797  rapidxml::xml_node<> *f_array_node = source_node->first_node("float_array");
798  if (!f_array_node) ROS_DEBUG_STREAM("Could not find node " << "float_array");
799  else {
800  rapidxml::xml_node<> *array_node = f_array_node->first_node();
801  if (!array_node) ROS_DEBUG_STREAM("Could not find node " << "containing the position array");
802  else {
803  vertices = array_node->value();
804  break;
805  }
806  }
807  }
808  }
809  source_node = source_node->next_sibling("source");
810  }
811  if (!source_node) ROS_DEBUG_STREAM("Could not find node " << "source with name position and position array");
812  }
813  }
814  }
815  }
816  } catch(std::runtime_error err) {
817  ROS_DEBUG_STREAM("Can't parse xml-file. Runtime error: " << err.what());
818  } catch (rapidxml::parse_error err) {
819  ROS_DEBUG_STREAM("Can't parse xml-file Parse error: " << err.what());
820  }
821 
822  // get the floats from the input file's mesh-source node with name="positions":
823  std::stringstream vertstream;
824  vertstream.str(vertices);
825  std::vector<float> vertex_list;
826  std::string vertex_coord;
827  float sum = 0.0;
828  try {
829  while (std::getline(vertstream, vertex_coord, ' ')) {
830  float value= std::stof(vertex_coord);
831  sum += std::abs(value);
832  vertex_list.push_back(value);
833  }
834  } catch (std::invalid_argument& ia) {
835  ROS_DEBUG_STREAM(ia.what());
836  sum = 0.0; // set sum to 0 to invalidate all vertices found so far and use center point instead
837  }
838 
839  // Set the minimum and maximum coordinates to 0 first
840  float min_x, min_y, min_z, max_x, max_y, max_z;
841  min_x = min_y = min_z = max_x = max_y = max_z = 0.0;
842 
843  ROS_DEBUG_STREAM("Calculating approximated oriented bounding box");
844  ApproxMVBB::OOBB bb;
845 
846  if (sum > 0.0) { // not all vertices were 0. Otherwise the center of the object (0.0) is used instead of the bounding box.
847  // Put the floats into Matrix for ApproxMVBB:
848  ApproxMVBB::Matrix3Dyn points(3,vertex_list.size()/3);
849  unsigned int j = 0;
850  for (unsigned int i = 0; i <= vertex_list.size() - 3; i+=3) {
851  points(0,j) = vertex_list.at(i);
852  points(1,j) = vertex_list.at(i+1);
853  points(2,j) = vertex_list.at(i+2);
854  j++;
855  }
856 
857  // Calculate bounding box:
858  bb = ApproxMVBB::approximateMVBB(points,0.001,500,5,0,5);
859 
860  ApproxMVBB::Matrix33 A_KI = bb.m_q_KI.matrix().transpose();
861  for(unsigned int i = 0; i < points.cols(); ++i) {
862  bb.unite(A_KI*points.col(i));
863  }
864 
865  // Calculate all corner points in OOBB frame:
866  ApproxMVBB::Vector3 min_point = bb.m_minPoint;
867  ApproxMVBB::Vector3 max_point = bb.m_maxPoint;
868  min_x = min_point.x();
869  min_y = min_point.y();
870  min_z = min_point.z();
871  max_x = max_point.x();
872  max_y = max_point.y();
873  max_z = max_point.z();
874  }
875 
876  // Set the corner points:
877  std::array<ApproxMVBB::Vector3, 8> corners_amvbb;
878  corners_amvbb.at(0) = ApproxMVBB::Vector3(min_x, min_y, min_z); // 0 - min_point
879  corners_amvbb.at(1) = ApproxMVBB::Vector3(max_x, min_y, min_z);
880  corners_amvbb.at(2) = ApproxMVBB::Vector3(min_x, max_y, min_z);
881  corners_amvbb.at(3) = ApproxMVBB::Vector3(max_x, max_y, min_z);
882  corners_amvbb.at(4) = ApproxMVBB::Vector3(min_x, min_y, max_z);
883  corners_amvbb.at(5) = ApproxMVBB::Vector3(max_x, min_y, max_z);
884  corners_amvbb.at(6) = ApproxMVBB::Vector3(min_x, max_y, max_z);
885  corners_amvbb.at(7) = ApproxMVBB::Vector3(max_x, max_y, max_z); // 7 - max_point
886 
887  // Into object frame and scaled down with 0.001 (measures assumed to be in mm; to m):
888  if (sum > 0.0) { // see above
889  for (unsigned int i = 0; i < corners_amvbb.size(); i++) {
890  corners_amvbb.at(i) = (bb.m_q_KI * corners_amvbb.at(i)) * 0.001;
891  }
892  }
893 
894  //Transform Vectors into geometry_msgs:
895  std::array<geometry_msgs::Point, 8> corner_points;
896  for (unsigned int i = 0; i < corners_amvbb.size(); i++) {
897  corner_points.at(i) = createPoint(corners_amvbb.at(i).x(), corners_amvbb.at(i).y(), corners_amvbb.at(i).z());
898  }
899 
900  // Writes points into config/bounding_box_corners.xml
901  try {
902  std::string corners_string;
903  for (unsigned int i = 0; i < corner_points.size(); i++) {
904  corners_string += boost::lexical_cast<std::string>(corner_points.at(i).x) + " " + boost::lexical_cast<std::string>(corner_points.at(i).y) + " "
905  + boost::lexical_cast<std::string>(corner_points.at(i).z) + " ";
906  }
907  std::string object_node = "<Object type=\"" + object.getType() + "\">" + corners_string + "</Object>";
908  std::ifstream ifile;
909  std::ofstream ofile;
910  // if necessary, create file:
911  if (!(std::ifstream(bb_corners_file_name_))) { // file does not exists
912  ROS_DEBUG_STREAM("Could not find file " << bb_corners_file_name_ << ". Creating file.");
913  ofile.open(bb_corners_file_name_);
914  if (ofile.is_open()) {
915  ofile << "<Objects></Objects>";
916  ofile.close();
917  }
918  else
919  ROS_DEBUG_STREAM("Could not open file " << bb_corners_file_name_);
920  }
921 
922  ifile.open(bb_corners_file_name_);
923  if (ifile.is_open()) {
924  std::string old_contents;
925  std::string line;
926  while(getline(ifile, line)) {
927  old_contents.append(line);
928  }
929  ifile.close();
930  if (old_contents.find("<Objects>") == 0) {
931  ofile.open(bb_corners_file_name_);
932  if (ofile.is_open()) {
933  std::string inner_nodes = old_contents.substr(9); // Cut off "<Objects>" in the beginning.
934  ofile << "<Objects>" << object_node << inner_nodes; // Reattach it and write new node behind it, followed by the rest of the old file
935  ofile.close();
936  ROS_DEBUG_STREAM("Bounding box corner points written to file " << bb_corners_file_name_);
937  }
938  }
939  else ROS_DEBUG_STREAM("When trying to write bounding box corners to file " << bb_corners_file_name_ << ": Could not find root node " << "<Objects>" << ". Corners not written.");
940  }
941  else {
942  ROS_DEBUG_STREAM("Could not open file " << bb_corners_file_name_ << ". Bounding box corners not written.");
943  }
944  } catch(boost::bad_lexical_cast err) {
945  ROS_DEBUG_STREAM("Can't cast bounding box corner points to string. Cast error: " << err.what());
946  }
947 
948  return corner_points;
949 }
950 
951 geometry_msgs::Point FakeObjectRecognition::createPoint(double x, double y, double z) {
952  geometry_msgs::Point pt;
953  pt.x = x;
954  pt.y = y;
955  pt.z = z;
956  return pt;
957 }
958 
959 }
960 
961 int main(int argc, char** argv) {
962 
963  ros::init (argc, argv, "asr_fake_object_recognition");
964 
966 
967  ros::spin();
968 
969  return 0;
970 }
971 
bool processReleaseRecognizerRequest(ReleaseRecognizer::Request &req, ReleaseRecognizer::Response &res)
ServiceClient serviceClient(const std::string &service_name, bool persistent=false, const M_string &header_values=M_string())
bool objectIsVisible(const geometry_msgs::Pose &pose_left, const geometry_msgs::Pose &pose_right)
Checks whether an object is currently visible.
std::string getMeshName() const
Return the mesh path of the object.
void configCallback(FakeObjectRecognitionConfig &config, uint32_t level)
The callback function which is called when the configuration has changed.
void setOrZNoiseDistMean(double or_z_noise_dist_mean)
Sets the mean value of the normal distribution used by the orientation error generation (z-axis) ...
std::array< geometry_msgs::Point, 8 > calculateBB(const ObjectConfig &object)
calculate approximated oriented bounding box of the object represented by its corner points ...
static const std::string GET_ALL_RECOGNIZERS_SERVICE_NAME("get_all_recognizers")
void publish(const boost::shared_ptr< M > &message) const
This class is used to simulate typical errors of an object recognition system.
int main(int argc, char **argv)
geometry_msgs::Pose transformFrame(const geometry_msgs::Pose &pose, const std::string &frame_from, const std::string &frame_to)
Transforms a given pose from one frame to another.
void setProbPoseInval(double prob_pose_inval)
Set the probability of the pose invalidation.
geometry_msgs::Point createPoint(double x, double y, double z)
creates a Point geometry_msg with the given coordinates
ROSCPP_DECL void init(int &argc, char **argv, const std::string &name, uint32_t options=0)
std::vector< geometry_msgs::Point > transformPoints(std::vector< geometry_msgs::Point > points_list, Eigen::Quaterniond rotation, Eigen::Vector3d translation)
Transforms points locally (as opposed to via a ROS service call in transformFrame) ...
bool call(MReq &req, MRes &res)
bool processGetAllRecognizersRequest(GetAllRecognizers::Request &req, GetAllRecognizers::Response &res)
visualization_msgs::MarkerArray::Ptr createNormalMarker(const ObjectConfig &object, int id, int lifetime)
publishes normal markers (yellow arrows) for all objects in the configuration
void setOrZNoiseDistDev(double or_z_noise_dist_dev)
Sets the standard deviation value of the normal distribution used by the orientation error generation...
FakeObjectRecognition()
The constructor of this class.
This class is used to rate an object&#39;s pose based on the current camera position. ...
Definition: rating.h:30
ServiceServer advertiseService(const std::string &service, bool(T::*srv_func)(MReq &, MRes &), T *obj)
bool parsePoseString(std::string pose_in, geometry_msgs::Pose &pose_out, std::string delim, std::string angles)
This function parses the string containing the pose of an entry in the object-config-file.
std::vector< geometry_msgs::Point > getNormals(const ObjectConfig &object)
get Normals of the object through the object_database/object_meta_data service
bool rateBBandNormal(const geometry_msgs::Pose &object_pose, const std::array< geometry_msgs::Point, 8 > &bounding_box, const std::vector< geometry_msgs::Point > &normals, double threshold)
Rates an objects visibility based on its bounding box and its normals.
Definition: rating.cpp:159
geometry_msgs::Pose addNoiseToOrientation(const geometry_msgs::Pose &pose)
Adds error values to the given pose (orientation only)
ROSCPP_DECL void spin(Spinner &spinner)
void setOrYNoiseDistDev(double or_y_noise_dist_dev)
Sets the standard deviation value of the normal distribution used by the orientation error generation...
std::map< std::string, std::vector< geometry_msgs::Point > > normals_
void setOrXNoiseDistMean(double or_x_noise_dist_mean)
Sets the mean value of the normal distribution used by the orientation error generation (x-axis) ...
bool processClearAllRecognizers(ClearAllRecognizers::Request &req, ClearAllRecognizers::Response &res)
std::map< std::string, std::array< geometry_msgs::Point, 8 > > bounding_box_corners_
static const std::string CLEAR_ALL_RECOGNIZERS_SERVICE_NAME("clear_all_recognizers")
void loadObjects()
This function loads the objects of the object-config-file.
#define ROS_INFO(...)
void setOrYNoiseDistMean(double or_y_noise_dist_mean)
Sets the mean value of the normal distribution used by the orientation error generation (y-axis) ...
static std_msgs::ColorRGBA createColorRGBA(float red, float green, float blue, float alpha)
Creates a std_msgs::ColorRGBA-message from the given values.
Timer createTimer(Rate r, Handler h, Obj o, bool oneshot=false, bool autostart=true) const
static const std::string RELEASE_RECOGNIZER_SERVICE_NAME("release_recognizer")
Publisher advertise(const std::string &topic, uint32_t queue_size, bool latch=false)
bool poseInvalidation()
Invalidates a pose by the probability member of this class.
void doRecognition()
This function is called whenever objects shall be recognized.
#define ROS_DEBUG_STREAM(args)
void lookupTransform(const std::string &target_frame, const std::string &source_frame, const ros::Time &time, StampedTransform &transform) const
ROSLIB_DECL std::string getPath(const std::string &package_name)
static std_msgs::ColorRGBA getMeshColor(std::string observed_id)
Returns the color of a mesh based on the object&#39;s id (Only creates a color if it is an object of the ...
#define ROS_INFO_STREAM(args)
void timerCallback(const ros::TimerEvent &event)
The callback function of the timer.
void transformPose(const std::string &target_frame, const geometry_msgs::PoseStamped &stamped_in, geometry_msgs::PoseStamped &stamped_out) const
dynamic_reconfigure::Server< FakeObjectRecognitionConfig > reconfigure_server_
static const std::string GET_RECOGNIZER_SERVICE_NAME("get_recognizer")
bool getParam(const std::string &key, std::string &s) const
void setPoseNoiseDistMean(double pos_noise_dist_mean)
Sets the mean value of the normal distribution used by the position error generation.
This class is used to save information about an available object.
Definition: object_config.h:32
visualization_msgs::Marker createMarker(const asr_msgs::AsrObjectPtr &object, int id, int lifetime, bool use_col_init=false)
Creates a visualization marker for a found object.
static Time now()
std::string getId() const
Return the id of the object.
asr_msgs::AsrObjectPtr createAsrMessage(const ObjectConfig &object_config, const geometry_msgs::Pose &pose, const std::string &frame_id)
Creates a AsrObject-message for a found object.
bool ratePose(const geometry_msgs::Pose &pose, double threshold_d, double threshold_x, double threshold_y)
Return whether a pose is visible in the camera frustum based on the distance and angle rating...
Definition: rating.cpp:37
geometry_msgs::Pose addNoiseToPosition(const geometry_msgs::Pose &pose)
Adds error values to the given pose (position only)
void setPoseNoiseDistDev(double pos_noise_dist_dev)
Sets the standard deviation value of the normal distribution used by the position error generation...
static const std::string NODE_NAME("asr_fake_object_recognition")
bool getBBfromFile(std::array< geometry_msgs::Point, 8 > &result, std::string object_type)
try to get bounding box corner points from file.
#define ROS_ERROR(...)
The central class of the recognition system used for managing the ros subscriptions, configuration changes, loading of the objects, the recognition itself and the visualisation of the results.
bool processGetRecognizerRequest(GetRecognizer::Request &req, GetRecognizer::Response &res)
std::string getType() const
Return the name of the object.
ROSCPP_DECL bool waitForService(const std::string &service_name, int32_t timeout)
void setOrXNoiseDistDev(double or_x_noise_dist_dev)
Sets the standard deviation value of the normal distribution used by the orientation error generation...
#define ROS_DEBUG(...)


asr_fake_object_recognition
Author(s): Allgeyer Tobias, Aumann Florian, Borella Jocelyn, Meißner Pascal, Qattan Mohamad
autogenerated on Wed Feb 19 2020 03:58:59