self_mask.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2008, Willow Garage, Inc.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *
8  * * Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  * * Redistributions in binary form must reproduce the above copyright
11  * notice, this list of conditions and the following disclaimer in the
12  * documentation and/or other materials provided with the distribution.
13  * * Neither the name of the Willow Garage, Inc. nor the names of its
14  * contributors may be used to endorse or promote products derived from
15  * this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
21  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27  * POSSIBILITY OF SUCH DAMAGE.
28  */
29 
30 #ifndef ROBOT_SELF_FILTER_SELF_MASK_
31 #define ROBOT_SELF_FILTER_SELF_MASK_
32 
33 #include <pcl/point_types.h>
34 #include <pcl_ros/point_cloud.h>
35 #include <sensor_msgs/PointCloud2.h>
37 #include <tf/transform_listener.h>
38 #include <boost/bind.hpp>
39 #include <boost/filesystem.hpp>
40 #include <string>
41 #include <vector>
42 
43 #include <urdf/model.h>
45 
47 {
48 
50  enum
51  {
52  INSIDE = 0,
53  OUTSIDE = 1,
54  SHADOW = 2,
55  };
56 
57 struct LinkInfo
58 {
59  std::string name;
60  double padding;
61  double scale;
62 };
63 
64  static inline tf::Transform urdfPose2TFTransform(const urdf::Pose &pose)
65  {
66  return tf::Transform(tf::Quaternion(pose.rotation.x, pose.rotation.y, pose.rotation.z, pose.rotation.w),
67  tf::Vector3(pose.position.x, pose.position.y, pose.position.z));
68  }
69 
70  static shapes::Shape* constructShape(const urdf::Geometry *geom)
71  {
72  ROS_ASSERT(geom);
73 
74  shapes::Shape *result = NULL;
75  switch (geom->type)
76  {
78  result = new shapes::Sphere(dynamic_cast<const urdf::Sphere*>(geom)->radius);
79  break;
81  {
82  urdf::Vector3 dim = dynamic_cast<const urdf::Box*>(geom)->dim;
83  result = new shapes::Box(dim.x, dim.y, dim.z);
84  }
85  break;
87  result = new shapes::Cylinder(dynamic_cast<const urdf::Cylinder*>(geom)->radius,
88  dynamic_cast<const urdf::Cylinder*>(geom)->length);
89  break;
91  {
92  const urdf::Mesh *mesh = dynamic_cast<const urdf::Mesh*>(geom);
93  if (!mesh->filename.empty())
94  {
97  bool ok = true;
98 
99  try
100  {
101  res = retriever.get(mesh->filename);
102  }
104  {
105  ROS_ERROR("%s", e.what());
106  ok = false;
107  }
108 
109  if (ok)
110  {
111  if (res.size == 0)
112  ROS_WARN("Retrieved empty mesh for resource '%s'", mesh->filename.c_str());
113  else
114  {
115  boost::filesystem::path model_path(mesh->filename);
116  std::string ext = model_path.extension().string();
117  if (ext == ".dae" || ext == ".DAE") {
118  result = shapes::createMeshFromBinaryDAE(mesh->filename.c_str());
119  }
120  else {
121  result = shapes::createMeshFromBinaryStlData(reinterpret_cast<char*>(res.data.get()), res.size);
122  }
123  if (result == NULL)
124  ROS_ERROR("Failed to load mesh '%s'", mesh->filename.c_str());
125  }
126  }
127  }
128  else
129  ROS_WARN("Empty mesh filename");
130  }
131 
132  break;
133  default:
134  ROS_ERROR("Unknown geometry type: %d", (int)geom->type);
135  break;
136  }
137 
138  return result;
139  }
140 
144  template <typename PointT>
145  class SelfMask
146  {
147  protected:
148 
149  struct SeeLink
150  {
151  SeeLink(void)
152  {
153  body = unscaledBody = NULL;
154  }
155 
156  std::string name;
160  double volume;
161  };
162 
163  struct SortBodies
164  {
165  bool operator()(const SeeLink &b1, const SeeLink &b2)
166  {
167  return b1.volume > b2.volume;
168  }
169  };
170 
171  public:
172  typedef pcl::PointCloud<PointT> PointCloud;
173 
175  SelfMask(tf::TransformListener &tf, const std::vector<LinkInfo> &links) : tf_(tf)
176  {
177  configure(links);
178  }
179 
182  ~SelfMask(void)
183  {
184  freeMemory();
185  }
186 
190  void maskContainment(const PointCloud& data_in, std::vector<int> &mask)
191  {
192  mask.resize(data_in.points.size());
193  if (bodies_.empty())
194  std::fill(mask.begin(), mask.end(), (int)OUTSIDE);
195  else
196  {
197  std_msgs::Header header = pcl_conversions::fromPCL(data_in.header);
198  assumeFrame(header);
199  maskAuxContainment(data_in, mask);
200  }
201 
202  }
203 
213  void maskIntersection(const PointCloud& data_in, const std::string &sensor_frame, const double min_sensor_dist,
214  std::vector<int> &mask, const boost::function<void(const tf::Vector3&)> &intersectionCallback = NULL)
215  {
216  mask.resize(data_in.points.size());
217  if (bodies_.empty()) {
218  std::fill(mask.begin(), mask.end(), (int)OUTSIDE);
219  }
220  else
221  {
222  std_msgs::Header header = pcl_conversions::fromPCL(data_in.header);
223  assumeFrame(header, sensor_frame, min_sensor_dist);
224  if (sensor_frame.empty())
225  maskAuxContainment(data_in, mask);
226  else
227  maskAuxIntersection(data_in, mask, intersectionCallback);
228  }
229 
230  }
231 
232 
239  void maskIntersection(const PointCloud& data_in, const tf::Vector3 &sensor_pos, const double min_sensor_dist,
240  std::vector<int> &mask, const boost::function<void(const tf::Vector3&)> &intersectionCallback = NULL)
241  {
242  mask.resize(data_in.points.size());
243  if (bodies_.empty())
244  std::fill(mask.begin(), mask.end(), (int)OUTSIDE);
245  else
246  {
247  std_msgs::Header header = pcl_conversions::fromPCL(data_in.header);
248  assumeFrame(header, sensor_pos, min_sensor_dist);
249  maskAuxIntersection(data_in, mask, intersectionCallback);
250  }
251 
252  }
253 
256  void assumeFrame(const std_msgs::Header& header)
257  {
258  const unsigned int bs = bodies_.size();
259 
260  // place the links in the assumed frame
261  for (unsigned int i = 0 ; i < bs ; ++i)
262  {
263  std::string err;
264  if(!tf_.waitForTransform(header.frame_id, bodies_[i].name, header.stamp, ros::Duration(.1), ros::Duration(.01), &err)) {
265  ROS_ERROR("WaitForTransform timed out from %s to %s after 100ms. Error string: %s", bodies_[i].name.c_str(), header.frame_id.c_str(), err.c_str());
266 
267  }
268 
269  // find the transform between the link's frame and the pointcloud frame
270  tf::StampedTransform transf;
271  try
272  {
273  tf_.lookupTransform(header.frame_id, bodies_[i].name, header.stamp, transf);
274  }
275  catch(tf::TransformException& ex)
276  {
277  transf.setIdentity();
278  ROS_ERROR("Unable to lookup transform from %s to %s. Exception: %s", bodies_[i].name.c_str(), header.frame_id.c_str(), ex.what());
279  }
280 
281  // set it for each body; we also include the offset specified in URDF
282  bodies_[i].body->setPose(transf * bodies_[i].constTransf);
283  bodies_[i].unscaledBody->setPose(transf * bodies_[i].constTransf);
284  }
285 
286  computeBoundingSpheres();
287 
288  }
289 
290 
293  void assumeFrame(const std_msgs::Header& header, const tf::Vector3 &sensor_pos, const double min_sensor_dist)
294  {
295  assumeFrame(header);
296  sensor_pos_ = sensor_pos;
297  min_sensor_dist_ = min_sensor_dist;
298  }
299 
302  void assumeFrame(const std_msgs::Header& header, const std::string &sensor_frame, const double min_sensor_dist)
303  {
304  assumeFrame(header);
305 
306  std::string err;
307  if(!tf_.waitForTransform(header.frame_id, sensor_frame, header.stamp, ros::Duration(.1), ros::Duration(.01), &err)) {
308  ROS_ERROR("WaitForTransform timed out from %s to %s after 100ms. Error string: %s", sensor_frame.c_str(), header.frame_id.c_str(), err.c_str());
309  sensor_pos_.setValue(0, 0, 0);
310  }
311 
312  //transform should be there
313  // compute the origin of the sensor in the frame of the cloud
314  try
315  {
316  tf::StampedTransform transf;
317  tf_.lookupTransform(header.frame_id, sensor_frame, header.stamp, transf);
318  sensor_pos_ = transf.getOrigin();
319  }
320  catch(tf::TransformException& ex)
321  {
322  sensor_pos_.setValue(0, 0, 0);
323  ROS_ERROR("Unable to lookup transform from %s to %s. Exception: %s", sensor_frame.c_str(), header.frame_id.c_str(), ex.what());
324  }
325 
326  min_sensor_dist_ = min_sensor_dist;
327 
328  }
329 
332  int getMaskContainment(const tf::Vector3 &pt) const
333  {
334  const unsigned int bs = bodies_.size();
335  int out = OUTSIDE;
336  for (unsigned int j = 0 ; out == OUTSIDE && j < bs ; ++j)
337  if (bodies_[j].body->containsPoint(pt))
338  out = INSIDE;
339  return out;
340  }
341 
344  int getMaskContainment(double x, double y, double z) const
345  {
346  return getMaskContainment(tf::Vector3(x, y, z));
347  }
348 
352  int getMaskIntersection(double x, double y, double z, const boost::function<void(const tf::Vector3&)> &intersectionCallback = NULL) const
353  {
354  return getMaskIntersection(tf::Vector3(x, y, z), intersectionCallback);
355  }
356 
360  int getMaskIntersection(const tf::Vector3 &pt, const boost::function<void(const tf::Vector3&)> &intersectionCallback = NULL) const
361  {
362  const unsigned int bs = bodies_.size();
363 
364  // we first check is the point is in the unscaled body.
365  // if it is, the point is definitely inside
366  int out = OUTSIDE;
367  for (unsigned int j = 0 ; out == OUTSIDE && j < bs ; ++j)
368  if (bodies_[j].unscaledBody->containsPoint(pt))
369  out = INSIDE;
370 
371  if (out == OUTSIDE)
372  {
373 
374  // we check it the point is a shadow point
375  tf::Vector3 dir(sensor_pos_ - pt);
376  tfScalar lng = dir.length();
377  if (lng < min_sensor_dist_)
378  out = INSIDE;
379  else
380  {
381  dir /= lng;
382 
383  std::vector<tf::Vector3> intersections;
384  for (unsigned int j = 0 ; out == OUTSIDE && j < bs ; ++j)
385  if (bodies_[j].body->intersectsRay(pt, dir, &intersections, 1))
386  {
387  if (dir.dot(sensor_pos_ - intersections[0]) >= 0.0)
388  {
389  if (intersectionCallback)
390  intersectionCallback(intersections[0]);
391  out = SHADOW;
392  }
393  }
394 
395  // if it is not a shadow point, we check if it is inside the scaled body
396  for (unsigned int j = 0 ; out == OUTSIDE && j < bs ; ++j)
397  if (bodies_[j].body->containsPoint(pt))
398  out = INSIDE;
399  }
400  }
401  return out;
402 
403  }
404 
406  void getLinkNames(std::vector<std::string> &frames) const
407  {
408  for (unsigned int i = 0 ; i < bodies_.size() ; ++i)
409  frames.push_back(bodies_[i].name);
410  }
411 
412  private:
413 
415  void freeMemory(void)
416  {
417  for (unsigned int i = 0 ; i < bodies_.size() ; ++i)
418  {
419  if (bodies_[i].body)
420  delete bodies_[i].body;
421  if (bodies_[i].unscaledBody)
422  delete bodies_[i].unscaledBody;
423  }
424 
425  bodies_.clear();
426  }
427 
428 
430  bool configure(const std::vector<LinkInfo> &links)
431  {
432  // in case configure was called before, we free the memory
433  freeMemory();
434  sensor_pos_.setValue(0, 0, 0);
435 
436  std::string content;
438 
439  if (nh_.getParam("robot_description", content))
440  {
441  urdfModel = boost::shared_ptr<urdf::Model>(new urdf::Model());
442  if (!urdfModel->initString(content))
443  {
444  ROS_ERROR("Unable to parse URDF description!");
445  return false;
446  }
447  }
448  else
449  {
450  ROS_ERROR("Robot model not found! Did you remap 'robot_description'?");
451  return false;
452  }
453 
454  std::stringstream missing;
455 
456  // from the geometric model, find the shape of each link of interest
457  // and create a body from it, one that knows about poses and can
458  // check for point inclusion
459  for (unsigned int i = 0 ; i < links.size() ; ++i)
460  {
461  const urdf::Link *link = urdfModel->getLink(links[i].name).get();
462  if (!link)
463  {
464  missing << " " << links[i].name;
465  continue;
466  }
467 
468  if (!(link->collision && link->collision->geometry))
469  {
470  ROS_WARN("No collision geometry specified for link '%s'", links[i].name.c_str());
471  continue;
472  }
473 
474  shapes::Shape *shape = constructShape(link->collision->geometry.get());
475 
476  if (!shape)
477  {
478  ROS_ERROR("Unable to construct collision shape for link '%s'", links[i].name.c_str());
479  continue;
480  }
481 
482  SeeLink sl;
483  sl.body = bodies::createBodyFromShape(shape);
484 
485  if (sl.body)
486  {
487  sl.name = links[i].name;
488 
489  // collision models may have an offset, in addition to what TF gives
490  // so we keep it around
491  sl.constTransf = urdfPose2TFTransform(link->collision->origin);
492 
493  sl.body->setScale(links[i].scale);
494  sl.body->setPadding(links[i].padding);
495  ROS_INFO_STREAM("Self see link name " << links[i].name << " padding " << links[i].padding);
496  sl.volume = sl.body->computeVolume();
497  sl.unscaledBody = bodies::createBodyFromShape(shape);
498  bodies_.push_back(sl);
499  }
500  else
501  ROS_WARN("Unable to create point inclusion body for link '%s'", links[i].name.c_str());
502 
503  delete shape;
504  }
505 
506  if (missing.str().size() > 0)
507  ROS_WARN("Some links were included for self mask but they do not exist in the model:%s", missing.str().c_str());
508 
509  if (bodies_.empty())
510  ROS_WARN("No robot links will be checked for self mask");
511 
512  // put larger volume bodies first -- higher chances of containing a point
513  std::sort(bodies_.begin(), bodies_.end(), SortBodies());
514 
515  bspheres_.resize(bodies_.size());
516  bspheresRadius2_.resize(bodies_.size());
517 
518  for (unsigned int i = 0 ; i < bodies_.size() ; ++i)
519  ROS_DEBUG("Self mask includes link %s with volume %f", bodies_[i].name.c_str(), bodies_[i].volume);
520 
521  //ROS_INFO("Self filter using %f padding and %f scaling", padd, scale);
522 
523  return true;
524 
525  }
526 
529  {
530  const unsigned int bs = bodies_.size();
531  for (unsigned int i = 0 ; i < bs ; ++i)
532  {
533  bodies_[i].body->computeBoundingSphere(bspheres_[i]);
534  bspheresRadius2_[i] = bspheres_[i].radius * bspheres_[i].radius;
535  }
536  }
537 
538 
540  void maskAuxContainment(const PointCloud& data_in, std::vector<int> &mask)
541  {
542  const unsigned int bs = bodies_.size();
543  const unsigned int np = data_in.points.size();
544 
545  // compute a sphere that bounds the entire robot
547  bodies::mergeBoundingSpheres(bspheres_, bound);
548  tfScalar radiusSquared = bound.radius * bound.radius;
549 
550  // we now decide which points we keep
551  //#pragma omp parallel for schedule(dynamic)
552  for (int i = 0 ; i < (int)np ; ++i)
553  {
554  tf::Vector3 pt = tf::Vector3(data_in.points[i].x, data_in.points[i].y, data_in.points[i].z);
555  int out = OUTSIDE;
556  if (bound.center.distance2(pt) < radiusSquared)
557  for (unsigned int j = 0 ; out == OUTSIDE && j < bs ; ++j)
558  if (bodies_[j].body->containsPoint(pt))
559  out = INSIDE;
560 
561  mask[i] = out;
562  }
563  }
564 
566  void maskAuxIntersection(const PointCloud& data_in, std::vector<int> &mask, const boost::function<void(const tf::Vector3&)> &callback)
567  {
568  const unsigned int bs = bodies_.size();
569  const unsigned int np = data_in.points.size();
570 
571  // compute a sphere that bounds the entire robot
573  bodies::mergeBoundingSpheres(bspheres_, bound);
574  tfScalar radiusSquared = bound.radius * bound.radius;
575 
576  //std::cout << "Testing " << np << " points\n";
577 
578  // we now decide which points we keep
579  //#pragma omp parallel for schedule(dynamic)
580  for (int i = 0 ; i < (int)np ; ++i)
581  {
582  bool print = false;
583  //if(i%100 == 0) print = true;
584  tf::Vector3 pt = tf::Vector3(data_in.points[i].x, data_in.points[i].y, data_in.points[i].z);
585  int out = OUTSIDE;
586 
587  // we first check is the point is in the unscaled body.
588  // if it is, the point is definitely inside
589  if (bound.center.distance2(pt) < radiusSquared)
590  for (unsigned int j = 0 ; out == OUTSIDE && j < bs ; ++j)
591  if (bodies_[j].unscaledBody->containsPoint(pt)) {
592  if(print)
593  std::cout << "Point " << i << " in unscaled body part " << bodies_[j].name << std::endl;
594  out = INSIDE;
595  }
596 
597  // if the point is not inside the unscaled body,
598  if (out == OUTSIDE)
599  {
600  // we check it the point is a shadow point
601  tf::Vector3 dir(sensor_pos_ - pt);
602  tfScalar lng = dir.length();
603  if (lng < min_sensor_dist_) {
604  out = INSIDE;
605  //std::cout << "Point " << i << " less than min sensor distance away\n";
606  }
607  else
608  {
609  dir /= lng;
610 
611  std::vector<tf::Vector3> intersections;
612  for (unsigned int j = 0 ; out == OUTSIDE && j < bs ; ++j) {
613  if (bodies_[j].body->intersectsRay(pt, dir, &intersections, 1))
614  {
615  if (dir.dot(sensor_pos_ - intersections[0]) >= 0.0)
616  {
617  if (callback)
618  callback(intersections[0]);
619  out = SHADOW;
620  if(print) std::cout << "Point " << i << " shadowed by body part " << bodies_[j].name << std::endl;
621  }
622  }
623  }
624  // if it is not a shadow point, we check if it is inside the scaled body
625  if (out == OUTSIDE && bound.center.distance2(pt) < radiusSquared)
626  for (unsigned int j = 0 ; out == OUTSIDE && j < bs ; ++j)
627  if (bodies_[j].body->containsPoint(pt)) {
628  if(print) std::cout << "Point " << i << " in scaled body part " << bodies_[j].name << std::endl;
629  out = INSIDE;
630  }
631  }
632  }
633  mask[i] = out;
634  }
635  }
636 
639 
642 
643  std::vector<SeeLink> bodies_;
644  std::vector<double> bspheresRadius2_;
645  std::vector<bodies::BoundingSphere> bspheres_;
646 
647  };
648 
649 }
650 
651 #endif
void getLinkNames(std::vector< std::string > &frames) const
Get the set of link names that have been instantiated for self filtering.
Definition: self_mask.h:406
~SelfMask(void)
Destructor to clean up.
Definition: self_mask.h:182
Definition of a cylinder.
Definition: shapes.h:109
tf::Vector3 center
Definition: bodies.h:62
double tfScalar
void assumeFrame(const std_msgs::Header &header, const std::string &sensor_frame, const double min_sensor_dist)
Assume subsequent calls to getMaskX() will be in the frame passed to this function. The frame in which the sensor is located is optional.
Definition: self_mask.h:302
tf::TransformListener & tf_
Definition: self_mask.h:637
void freeMemory(void)
Free memory.
Definition: self_mask.h:415
void maskAuxContainment(const PointCloud &data_in, std::vector< int > &mask)
Perform the actual mask computation.
Definition: self_mask.h:540
void maskIntersection(const PointCloud &data_in, const tf::Vector3 &sensor_pos, const double min_sensor_dist, std::vector< int > &mask, const boost::function< void(const tf::Vector3 &)> &intersectionCallback=NULL)
Compute the intersection mask for a given pointcloud. If a mask element can have one of the values IN...
Definition: self_mask.h:239
bool operator()(const SeeLink &b1, const SeeLink &b2)
Definition: self_mask.h:165
int getMaskIntersection(const tf::Vector3 &pt, const boost::function< void(const tf::Vector3 &)> &intersectionCallback=NULL) const
Get the intersection mask (INSIDE, OUTSIDE or SHADOW) value for an individual point. No setup is performed, assumeFrame() should be called before use.
Definition: self_mask.h:360
#define ROS_WARN(...)
ROSCONSOLE_DECL void print(FilterBase *filter, void *logger, Level level, const char *file, int line, const char *function, const char *fmt,...) ROSCONSOLE_PRINTF_ATTRIBUTE(7
TFSIMD_FORCE_INLINE void setValue(const tfScalar &x, const tfScalar &y, const tfScalar &z)
void maskIntersection(const PointCloud &data_in, const std::string &sensor_frame, const double min_sensor_dist, std::vector< int > &mask, const boost::function< void(const tf::Vector3 &)> &intersectionCallback=NULL)
Compute the intersection mask for a given pointcloud. If a mask element can have one of the values IN...
Definition: self_mask.h:213
bool configure(const std::vector< LinkInfo > &links)
Configure the filter.
Definition: self_mask.h:430
Definition of a sphere that bounds another object.
Definition: bodies.h:60
void setIdentity()
Mesh * createMeshFromBinaryStlData(const char *data, unsigned int size)
Load a mesh from a binary STL stream. Normals are recomputed and repeating vertices are identified...
Definition: load_mesh.cpp:462
SelfMask(tf::TransformListener &tf, const std::vector< LinkInfo > &links)
Construct the filter.
Definition: self_mask.h:175
Mesh * createMeshFromBinaryDAE(const char *filename)
Load a mesh from a binary DAE file. Normals are recomputed and repeating vertices are identified...
Definition: load_mesh.cpp:520
void fromPCL(const pcl::uint64_t &pcl_stamp, ros::Time &stamp)
int getMaskContainment(const tf::Vector3 &pt) const
Get the containment mask (INSIDE or OUTSIDE) value for an individual point. No setup is performed...
Definition: self_mask.h:332
void mergeBoundingSpheres(const std::vector< BoundingSphere > &spheres, BoundingSphere &mergedSphere)
Compute a bounding sphere to enclose a set of bounding spheres.
Definition: bodies.cpp:71
A basic definition of a shape. Shapes are considered centered at origin.
Definition: shapes.h:58
TFSIMD_FORCE_INLINE tfScalar dot(const Vector3 &v) const
TFSIMD_FORCE_INLINE tfScalar distance2(const Vector3 &v) const
static shapes::Shape * constructShape(const urdf::Geometry *geom)
Definition: self_mask.h:70
boost::shared_array< uint8_t > data
int getMaskContainment(double x, double y, double z) const
Get the containment mask (INSIDE or OUTSIDE) value for an individual point. No setup is performed...
Definition: self_mask.h:344
Body * createBodyFromShape(const shapes::Shape *shape)
Create a body from a given shape.
Definition: bodies.cpp:44
static tf::Transform urdfPose2TFTransform(const urdf::Pose &pose)
Definition: self_mask.h:64
pcl::PointCloud< PointT > PointCloud
Definition: self_mask.h:172
void maskContainment(const PointCloud &data_in, std::vector< int > &mask)
Compute the containment mask (INSIDE or OUTSIDE) for a given pointcloud. If a mask element is INSIDE...
Definition: self_mask.h:190
TFSIMD_FORCE_INLINE Vector3 & getOrigin()
std::vector< bodies::BoundingSphere > bspheres_
Definition: self_mask.h:645
std::vector< SeeLink > bodies_
Definition: self_mask.h:643
Definition of a sphere.
Definition: shapes.h:90
MemoryResource get(const std::string &url)
Computing a mask for a pointcloud that states which points are inside the robot.
Definition: self_mask.h:145
int getMaskIntersection(double x, double y, double z, const boost::function< void(const tf::Vector3 &)> &intersectionCallback=NULL) const
Get the intersection mask (INSIDE, OUTSIDE or SHADOW) value for an individual point. No setup is performed, assumeFrame() should be called before use.
Definition: self_mask.h:352
#define ROS_INFO_STREAM(args)
std::vector< double > bspheresRadius2_
Definition: self_mask.h:644
Definition of a box.
Definition: shapes.h:129
void assumeFrame(const std_msgs::Header &header, const tf::Vector3 &sensor_pos, const double min_sensor_dist)
Assume subsequent calls to getMaskX() will be in the frame passed to this function. Also specify which possition to assume for the sensor (frame is not needed)
Definition: self_mask.h:293
void maskAuxIntersection(const PointCloud &data_in, std::vector< int > &mask, const boost::function< void(const tf::Vector3 &)> &callback)
Perform the actual mask computation.
Definition: self_mask.h:566
TFSIMD_FORCE_INLINE tfScalar length(const Quaternion &q)
#define ROS_ASSERT(cond)
#define ROS_ERROR(...)
A body is a shape + its pose. Point inclusion, ray intersection can be tested, volumes and bounding s...
Definition: bodies.h:69
void computeBoundingSpheres(void)
Compute bounding spheres for the checked robot links.
Definition: self_mask.h:528
TFSIMD_FORCE_INLINE tfScalar length() const
void assumeFrame(const std_msgs::Header &header)
Assume subsequent calls to getMaskX() will be in the frame passed to this function. The frame in which the sensor is located is optional.
Definition: self_mask.h:256
#define ROS_DEBUG(...)


pr2_navigation_self_filter
Author(s): Eitan Marder-Eppstein
autogenerated on Mon Jun 10 2019 14:28:54