39 #include <octomap/math/Vector3.h>
40 #include <octomap/math/Utils.h>
41 #include <octomap/octomap.h>
42 #include <geometric_shapes/shapes.h>
43 #include <rclcpp/logger.hpp>
44 #include <rclcpp/logging.hpp>
48 static const rclcpp::Logger LOGGER = rclcpp::get_logger(
"moveit_collision_detection.collision_octomap_filter");
52 const double& r_multiple,
const octomath::Vector3& contact_point,
53 octomath::Vector3& normal,
double& depth,
bool estimate_depth);
55 bool findSurface(
const octomap::point3d_list& cloud,
const double& spacing,
const double& iso_value,
56 const double& r_multiple,
const octomath::Vector3& seed, octomath::Vector3& surface_point,
57 octomath::Vector3& normal);
59 bool sampleCloud(
const octomap::point3d_list& cloud,
const double& spacing,
const double& r_multiple,
60 const octomath::Vector3& position,
double& intensity, octomath::Vector3& gradient);
63 const double cell_bbx_search_distance,
64 const double allowed_angle_divergence,
const bool estimate_depth,
65 const double iso_value,
const double metaball_radius_multiple)
69 RCLCPP_ERROR(LOGGER,
"No valid Object passed in, cannot refine Normals!");
74 RCLCPP_WARN(LOGGER,
"There do not appear to be any contacts, so there is nothing to refine!");
83 const std::string contact1 = contact.first.first;
84 const std::string contact2 = contact.first.second;
85 std::string octomap_name =
"";
86 std::vector<collision_detection::Contact>& contact_vector = contact.second;
88 if (contact1.find(
"octomap") != std::string::npos)
89 octomap_name = contact1;
90 else if (contact2.find(
"octomap") != std::string::npos)
91 octomap_name = contact2;
98 if (!object->shapes_.empty())
100 const shapes::ShapeConstPtr& shape =
object->shapes_[0];
101 const std::shared_ptr<const shapes::OcTree> shape_octree = std::dynamic_pointer_cast<const shapes::OcTree>(shape);
104 std::shared_ptr<const octomap::OcTree> octree = shape_octree->octree;
105 cell_size = octree->getResolution();
106 for (
auto& contact_info : contact_vector)
111 const octomath::Vector3 contact_point(point[0], point[1], point[2]);
112 const octomath::Vector3 contact_normal(normal[0], normal[1], normal[2]);
113 const octomath::Vector3 diagonal = octomath::Vector3(1, 1, 1);
114 const octomath::Vector3 bbx_min = contact_point - diagonal * cell_size * cell_bbx_search_distance;
115 const octomath::Vector3 bbx_max = contact_point + diagonal * cell_size * cell_bbx_search_distance;
116 octomap::point3d_list node_centers;
117 octomap::OcTreeBaseImpl<octomap::OcTreeNode, octomap::AbstractOccupancyOcTree>::leaf_bbx_iterator it =
118 octree->begin_leafs_bbx(bbx_min, bbx_max);
119 octomap::OcTreeBaseImpl<octomap::OcTreeNode, octomap::AbstractOccupancyOcTree>::leaf_bbx_iterator leafs_end =
120 octree->end_leafs_bbx();
122 for (; it != leafs_end; ++it)
124 const octomap::point3d pt = it.getCoordinate();
126 if (octree->isNodeOccupied(*it))
129 node_centers.push_back(pt);
145 n, depth, estimate_depth))
148 const double divergence = contact_normal.angleTo(n);
149 if (divergence > allowed_angle_divergence)
160 contact_info.depth = depth;
170 const double& r_multiple,
const octomath::Vector3& contact_point,
171 octomath::Vector3& normal,
double& depth,
const bool estimate_depth)
176 octomath::Vector3 surface_point;
177 if (
findSurface(cloud, spacing, iso_value, r_multiple, contact_point, surface_point, normal))
179 depth = normal.dot(surface_point - contact_point);
189 octomath::Vector3 gradient;
190 if (
sampleCloud(cloud, spacing, r_multiple, contact_point, intensity, gradient))
192 normal = gradient.normalized();
206 bool findSurface(
const octomap::point3d_list& cloud,
const double& spacing,
const double& iso_value,
207 const double& r_multiple,
const octomath::Vector3& seed, octomath::Vector3& surface_point,
208 octomath::Vector3& normal)
210 const double epsilon = 1e-10;
211 const int iterations = 10;
212 double intensity = 0;
214 octomath::Vector3
p = seed, dp, gs;
215 for (
int i = 0; i < iterations; ++i)
217 if (!
sampleCloud(cloud, spacing, r_multiple,
p, intensity, gs))
219 const double s = iso_value - intensity;
220 dp = (gs * -s) * (1.0 / std::max(gs.dot(gs), epsilon));
222 if (dp.dot(dp) < epsilon)
225 normal = gs.normalized();
233 bool sampleCloud(
const octomap::point3d_list& cloud,
const double& spacing,
const double& r_multiple,
234 const octomath::Vector3& position,
double& intensity, octomath::Vector3& gradient)
237 gradient = octomath::Vector3(0, 0, 0);
239 const double r = r_multiple * spacing;
242 const int nn = cloud.size();
249 double a = 0, b = 0,
c = 0, r2 = 0, r4 = 0, r6 = 0, a1 = 0, b1 = 0, c1 = 0, a2 = 0, b2 = 0, c2 = 0;
250 const bool wyvill =
true;
252 for (
const octomath::Vector3& v : cloud)
271 RCLCPP_ERROR(LOGGER,
"This should not be called!");
275 octomath::Vector3 f_grad(0, 0, 0);
277 octomath::Vector3 pos = position - v;
278 const double r = pos.norm();
279 pos = pos * (1.0 /
r);
284 const double r2 =
r *
r;
285 const double r3 =
r * r2;
286 const double r4 = r2 * r2;
287 const double r5 = r3 * r2;
288 const double r6 = r3 * r3;
292 f_val = (a1 * r6 + b1 * r4 + c1 * r2 + 1);
293 f_grad = pos * (a2 * r5 + b2 * r3 + c2 *
r);
297 RCLCPP_ERROR(LOGGER,
"This should not be called!");
298 const double r_scaled =
r /
r;
300 f_val = pow((1 - r_scaled), 4) * (4 * r_scaled + 1);
301 f_grad = pos * (-4.0 /
r * pow(1.0 - r_scaled, 3) * (4.0 * r_scaled + 1.0) + 4.0 /
r * pow(1 - r_scaled, 4));
bool getMetaballSurfaceProperties(const octomap::point3d_list &cloud, const double &spacing, const double &iso_value, const double &r_multiple, const octomath::Vector3 &contact_point, octomath::Vector3 &normal, double &depth, bool estimate_depth)
bool sampleCloud(const octomap::point3d_list &cloud, const double &spacing, const double &r_multiple, const octomath::Vector3 &position, double &intensity, octomath::Vector3 &gradient)
bool findSurface(const octomap::point3d_list &cloud, const double &spacing, const double &iso_value, const double &r_multiple, const octomath::Vector3 &seed, octomath::Vector3 &surface_point, octomath::Vector3 &normal)
int refineContactNormals(const World::ObjectConstPtr &object, CollisionResult &res, double cell_bbx_search_distance=1.0, double allowed_angle_divergence=0.0, bool estimate_depth=false, double iso_value=0.5, double metaball_radius_multiple=1.5)
Re-proceses contact normals for an octomap by estimating a metaball iso-surface using the centers of ...
Vec3fX< details::Vec3Data< double > > Vector3d
Representation of a collision checking result.
std::size_t contact_count
Number of contacts returned.