39 #include <boost/math/special_functions/binomial.hpp>
40 #include <boost/thread.hpp>
41 #include <boost/unordered_map.hpp>
42 #include <boost/assign.hpp>
52 const boost::unordered_map<DisabledReason, std::string>
REASONS_TO_STRING = boost::assign::map_list_of(
NEVER,
"Never")(
60 typedef std::set<std::pair<std::string, std::string> >
StringPairSet;
63 struct ThreadComputation
66 int thread_id,
int num_trials,
StringPairSet* links_seen_colliding, boost::mutex* lock,
67 unsigned int* progress)
87 typedef std::map<const moveit::core::LinkModel*, std::set<const moveit::core::LinkModel*> >
LinkGraph;
150 StringPairSet& links_seen_colliding,
double min_collision_faction = 0.95);
162 StringPairSet& links_seen_colliding,
unsigned int* progress);
174 const bool include_never_colliding,
const unsigned int num_trials,
175 const double min_collision_fraction,
const bool verbose)
178 planning_scene::PlanningScenePtr scene = parent_scene->diff();
204 boost::this_thread::interruption_point();
210 boost::this_thread::interruption_point();
225 boost::this_thread::interruption_point();
229 unsigned int num_always =
233 boost::this_thread::interruption_point();
237 unsigned int num_never = 0;
238 if (include_never_colliding)
248 unsigned int num_disabled = 0;
249 for (LinkPairMap::const_iterator pair_it = link_pairs.begin(); pair_it != link_pairs.end(); ++pair_it)
251 if (pair_it->second.disable_check)
255 ROS_INFO(
"-------------------------------------------------------------------------------");
257 unsigned int num_links = int(link_graph.size());
258 double num_possible = boost::math::binomial_coefficient<double>(num_links, 2);
259 unsigned int num_sometimes = num_possible - num_disabled;
261 ROS_INFO(
"%6d : %s", num_links,
"Total Links");
262 ROS_INFO(
"%6.0f : %s", num_possible,
"Total possible collisions");
263 ROS_INFO(
"%6d : %s", num_always,
"Always in collision");
264 ROS_INFO(
"%6d : %s", num_never,
"Never in collision");
265 ROS_INFO(
"%6d : %s", num_default,
"Default in collision");
266 ROS_INFO(
"%6d : %s", num_adjacent,
"Adjacent links disabled");
267 ROS_INFO(
"%6d : %s", num_sometimes,
"Sometimes in collision");
268 ROS_INFO(
"%6d : %s", num_disabled,
"TOTAL DISABLED");
286 bool is_unique =
false;
289 std::pair<std::string, std::string> link_pair;
294 link_pair = std::pair<std::string, std::string>(linkA, linkB);
298 link_pair = std::pair<std::string, std::string>(linkB, linkA);
302 LinkPairData* link_pair_ptr = &link_pairs[link_pair];
305 if (!link_pairs[link_pair].disable_check)
308 link_pair_ptr->reason = reason;
312 link_pair_ptr->disable_check = (reason !=
NOT_DISABLED);
323 const std::vector<std::string>& names = scene.
getRobotModel()->getLinkModelNamesWithCollisionGeometry();
325 std::pair<std::string, std::string> temp_pair;
328 for (std::size_t i = 0; i < names.size(); ++i)
330 for (std::size_t j = i + 1; j < names.size(); ++j)
354 for (LinkGraph::const_iterator edge_it = link_graph.begin(); edge_it != link_graph.end(); ++edge_it)
356 if (edge_it->first->getShapes().empty())
359 std::vector<const moveit::core::LinkModel*> temp_list;
364 temp_list.push_back(adj_it);
369 for (std::size_t i = 0; i < temp_list.size(); ++i)
371 for (std::size_t j = i + 1; j < temp_list.size(); ++j)
376 if (link_graph[temp_list[i]].insert(temp_list[j]).second)
378 if (link_graph[temp_list[j]].insert(temp_list[i]).second)
401 link_graph[
next].insert(start_link);
402 link_graph[start_link].insert(next);
410 ROS_ERROR(
"Joint exists in URDF with no link!");
419 int num_disabled = 0;
420 for (LinkGraph::const_iterator link_graph_it = link_graph.begin(); link_graph_it != link_graph.end(); ++link_graph_it)
423 for (std::set<const moveit::core::LinkModel*>::const_iterator adj_it = link_graph_it->second.begin();
424 adj_it != link_graph_it->second.end(); ++adj_it)
429 if (!link_graph_it->first->getShapes().empty() && !(*adj_it)->getShapes().empty())
431 num_disabled +=
setLinkPair(link_graph_it->first->getName(), (*adj_it)->getName(),
ADJACENT, link_pairs);
456 int num_disabled = 0;
457 for (collision_detection::CollisionResult::ContactMap::const_iterator it =
res.contacts.begin();
458 it !=
res.contacts.end(); ++it)
476 double min_collision_faction)
479 static const unsigned int SMALL_TRIAL_COUNT = 200;
480 static const unsigned int SMALL_TRIAL_LIMIT = (
unsigned int)((
double)SMALL_TRIAL_COUNT * min_collision_faction);
483 unsigned int num_disabled = 0;
488 std::map<std::pair<std::string, std::string>,
unsigned int> collision_count;
491 for (
unsigned int i = 0; i < SMALL_TRIAL_COUNT; ++i)
500 for (collision_detection::CollisionResult::ContactMap::const_iterator it =
res.contacts.begin();
501 it !=
res.contacts.end(); ++it)
503 collision_count[it->first]++;
504 links_seen_colliding.insert(it->first);
505 nc += it->second.size();
521 for (std::map<std::pair<std::string, std::string>,
unsigned int>::const_iterator it = collision_count.begin();
522 it != collision_count.end(); ++it)
525 if (it->second > SMALL_TRIAL_LIMIT)
527 num_disabled +=
setLinkPair(it->first.first, it->first.second,
ALWAYS, link_pairs);
553 unsigned int num_disabled = 0;
555 boost::thread_group bgroup;
558 int num_threads = boost::thread::hardware_concurrency();
562 for (
int i = 0; i < num_threads; ++i)
564 ThreadComputation tc(scene, req, i, num_trials / num_threads, &links_seen_colliding, &lock, progress);
572 catch (boost::thread_interrupted)
574 ROS_WARN(
"disableNeverInCollision interrupted");
575 bgroup.interrupt_all();
581 for (std::pair<
const std::pair<std::string, std::string>,
LinkPairData>& link_pair : link_pairs)
583 if (!link_pair.second.disable_check)
587 if (links_seen_colliding.find(link_pair.first) == links_seen_colliding.end())
590 link_pair.second.reason =
NEVER;
591 link_pair.second.disable_check =
true;
611 const unsigned int progress_interval = std::max(1u, tc.num_trials_ / 100);
617 for (
unsigned int i = 0; i < tc.num_trials_; ++i)
619 boost::this_thread::interruption_point();
622 if (i % progress_interval == 0 && tc.thread_id_ == 0)
624 (*tc.progress_) = i * 92 / tc.num_trials_ + 8;
628 robot_state.setToRandomPositions();
629 tc.scene_.checkSelfCollision(tc.req_, res, robot_state);
632 for (collision_detection::CollisionResult::ContactMap::const_iterator it =
res.contacts.begin();
633 it !=
res.contacts.end(); ++it)
636 if (tc.links_seen_colliding_->find(it->first) == tc.links_seen_colliding_->end())
640 boost::mutex::scoped_lock slock(*tc.lock_);
641 tc.links_seen_colliding_->insert(it->first);
643 tc.scene_.getAllowedCollisionMatrixNonConst().setEntry(it->first.first, it->first.second,
668 catch (
const std::out_of_range&)