moveit2
The MoveIt Motion Planning Framework for ROS 2.
shape_mask.cpp
Go to the documentation of this file.
1 /*********************************************************************
2  * Software License Agreement (BSD License)
3  *
4  * Copyright (c) 2008, Willow Garage, Inc.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  * * Redistributions of source code must retain the above copyright
12  * notice, this list of conditions and the following disclaimer.
13  * * Redistributions in binary form must reproduce the above
14  * copyright notice, this list of conditions and the following
15  * disclaimer in the documentation and/or other materials provided
16  * with the distribution.
17  * * Neither the name of Willow Garage nor the names of its
18  * contributors may be used to endorse or promote products derived
19  * from this software without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32  * POSSIBILITY OF SUCH DAMAGE.
33  *********************************************************************/
34 
35 /* Author: Ioan Sucan */
36 
38 #include <geometric_shapes/body_operations.h>
39 #include <sensor_msgs/point_cloud2_iterator.hpp>
40 #include <rclcpp/logger.hpp>
41 #include <rclcpp/logging.hpp>
42 #include <moveit/utils/logger.hpp>
43 
44 namespace
45 {
46 rclcpp::Logger getLogger()
47 {
48  return moveit::getLogger("moveit.ros.shape_mask");
49 }
50 } // namespace
51 
53  : transform_callback_(transform_callback), next_handle_(1), min_handle_(1)
54 {
55 }
56 
58 {
59  freeMemory();
60 }
61 
62 void point_containment_filter::ShapeMask::freeMemory()
63 {
64  for (const SeeShape& body : bodies_)
65  delete body.body;
66  bodies_.clear();
67 }
68 
70 {
71  std::scoped_lock _(shapes_lock_);
72  transform_callback_ = transform_callback;
73 }
74 
76  double scale, double padding)
77 {
78  std::scoped_lock _(shapes_lock_);
79  SeeShape ss;
80  ss.body = bodies::createEmptyBodyFromShapeType(shape->type);
81  if (ss.body)
82  {
83  ss.body->setDimensionsDirty(shape.get());
84  ss.body->setScaleDirty(scale);
85  ss.body->setPaddingDirty(padding);
86  ss.body->updateInternalData();
87  ss.volume = ss.body->computeVolume();
88  ss.handle = next_handle_;
89  std::pair<std::set<SeeShape, SortBodies>::iterator, bool> insert_op = bodies_.insert(ss);
90  if (!insert_op.second)
91  {
92  RCLCPP_ERROR(getLogger(), "Internal error in management of bodies in ShapeMask. This is a serious error.");
93  }
94  used_handles_[next_handle_] = insert_op.first;
95  }
96  else
97  return 0;
98 
99  ShapeHandle ret = next_handle_;
100  const std::size_t sz = min_handle_ + bodies_.size() + 1;
101  for (std::size_t i = min_handle_; i < sz; ++i)
102  {
103  if (used_handles_.find(i) == used_handles_.end())
104  {
105  next_handle_ = i;
106  break;
107  }
108  }
109  min_handle_ = next_handle_;
110 
111  return ret;
112 }
113 
115 {
116  std::scoped_lock _(shapes_lock_);
117  std::map<ShapeHandle, std::set<SeeShape, SortBodies>::iterator>::iterator it = used_handles_.find(handle);
118  if (it != used_handles_.end())
119  {
120  delete it->second->body;
121  bodies_.erase(it->second);
122  used_handles_.erase(it);
123  min_handle_ = handle;
124  }
125  else
126  RCLCPP_ERROR(getLogger(), "Unable to remove shape handle %u", handle);
127 }
128 
129 void point_containment_filter::ShapeMask::maskContainment(const sensor_msgs::msg::PointCloud2& data_in,
130  const Eigen::Vector3d& /*sensor_origin*/,
131  const double min_sensor_dist, const double max_sensor_dist,
132  std::vector<int>& mask)
133 {
134  std::scoped_lock _(shapes_lock_);
135  const unsigned int np = data_in.data.size() / data_in.point_step;
136  mask.resize(np);
137 
138  if (bodies_.empty())
139  {
140  std::fill(mask.begin(), mask.end(), static_cast<int>(OUTSIDE));
141  }
142  else
143  {
144  Eigen::Isometry3d tmp;
145  bspheres_.resize(bodies_.size());
146  std::size_t j = 0;
147  for (std::set<SeeShape>::const_iterator it = bodies_.begin(); it != bodies_.end(); ++it)
148  {
149  if (!transform_callback_(it->handle, tmp))
150  {
151  if (!it->body)
152  {
153  RCLCPP_ERROR_STREAM(getLogger(),
154  "Missing transform for shape with handle " << it->handle << " without a body");
155  }
156  else
157  {
158  RCLCPP_ERROR_STREAM(getLogger(),
159  "Missing transform for shape " << it->body->getType() << " with handle " << it->handle);
160  }
161  }
162  else
163  {
164  it->body->setPose(tmp);
165  it->body->computeBoundingSphere(bspheres_[j++]);
166  }
167  }
168 
169  // compute a sphere that bounds the entire robot
170  bodies::BoundingSphere bound;
171  bodies::mergeBoundingSpheres(bspheres_, bound);
172  const double radius_squared = bound.radius * bound.radius;
173 
174  // we now decide which points we keep
175  sensor_msgs::PointCloud2ConstIterator<float> iter_x(data_in, "x");
176  sensor_msgs::PointCloud2ConstIterator<float> iter_y(data_in, "y");
177  sensor_msgs::PointCloud2ConstIterator<float> iter_z(data_in, "z");
178 
179  // Cloud iterators are not incremented in the for loop, because of the pragma
180  // Comment out below parallelization as it can result in very high CPU consumption
181  //#pragma omp parallel for schedule(dynamic)
182  for (int i = 0; i < static_cast<int>(np); ++i)
183  {
184  Eigen::Vector3d pt = Eigen::Vector3d(*(iter_x + i), *(iter_y + i), *(iter_z + i));
185  double d = pt.norm();
186  int out = OUTSIDE;
187  if (d < min_sensor_dist || d > max_sensor_dist)
188  {
189  out = CLIP;
190  }
191  else if ((bound.center - pt).squaredNorm() < radius_squared)
192  {
193  for (std::set<SeeShape>::const_iterator it = bodies_.begin(); it != bodies_.end() && out == OUTSIDE; ++it)
194  {
195  if (it->body->containsPoint(pt))
196  out = INSIDE;
197  }
198  }
199  mask[i] = out;
200  }
201  }
202 }
203 
205 {
206  std::scoped_lock _(shapes_lock_);
207 
208  int out = OUTSIDE;
209  for (std::set<SeeShape>::const_iterator it = bodies_.begin(); it != bodies_.end() && out == OUTSIDE; ++it)
210  {
211  if (it->body->containsPoint(pt))
212  out = INSIDE;
213  }
214  return out;
215 }
216 
217 int point_containment_filter::ShapeMask::getMaskContainment(double x, double y, double z) const
218 {
219  return getMaskContainment(Eigen::Vector3d(x, y, z));
220 }
ShapeHandle addShape(const shapes::ShapeConstPtr &shape, double scale=1.0, double padding=0.0)
Definition: shape_mask.cpp:75
std::function< bool(ShapeHandle, Eigen::Isometry3d &)> TransformCallback
Definition: shape_mask.hpp:63
void removeShape(ShapeHandle handle)
Definition: shape_mask.cpp:114
ShapeMask(const TransformCallback &transform_callback=TransformCallback())
Construct the filter.
Definition: shape_mask.cpp:52
void maskContainment(const sensor_msgs::msg::PointCloud2 &data_in, const Eigen::Vector3d &sensor_pos, const double min_sensor_dist, const double max_sensor_dist, std::vector< int > &mask)
Compute the containment mask (INSIDE or OUTSIDE) for a given pointcloud. If a mask element is INSIDE,...
Definition: shape_mask.cpp:129
int getMaskContainment(double x, double y, double z) const
Get the containment mask (INSIDE or OUTSIDE) value for an individual point. It is assumed the point i...
Definition: shape_mask.cpp:217
virtual ~ShapeMask()
Destructor to clean up.
Definition: shape_mask.cpp:57
void setTransformCallback(const TransformCallback &transform_callback)
Definition: shape_mask.cpp:69
Vec3fX< details::Vec3Data< double > > Vector3d
Definition: fcl_compat.hpp:89
rclcpp::Logger getLogger(const std::string &name)
Creates a namespaced logger.
Definition: logger.cpp:79
unsigned int ShapeHandle
Definition: shape_mask.hpp:49