compute_default_collisions.cpp
Go to the documentation of this file.
00001 /*********************************************************************
00002  * Software License Agreement (BSD License)
00003  *
00004  *  Copyright (c) 2012, Willow Garage, Inc.
00005  *  All rights reserved.
00006  *
00007  *  Redistribution and use in source and binary forms, with or without
00008  *  modification, are permitted provided that the following conditions
00009  *  are met:
00010  *
00011  *   * Redistributions of source code must retain the above copyright
00012  *     notice, this list of conditions and the following disclaimer.
00013  *   * Redistributions in binary form must reproduce the above
00014  *     copyright notice, this list of conditions and the following
00015  *     disclaimer in the documentation and/or other materials provided
00016  *     with the distribution.
00017  *   * Neither the name of Willow Garage nor the names of its
00018  *     contributors may be used to endorse or promote products derived
00019  *     from this software without specific prior written permission.
00020  *
00021  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00022  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00023  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00024  *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00025  *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00026  *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00027  *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00028  *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00029  *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00030  *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00031  *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00032  *  POSSIBILITY OF SUCH DAMAGE.
00033  *********************************************************************/
00034 
00035 /* Author: Dave Coleman */
00036 
00037 #include <moveit/setup_assistant/tools/compute_default_collisions.h>
00038 #include <boost/math/special_functions/binomial.hpp>  // for statistics at end
00039 #include <boost/thread.hpp>
00040 #include <boost/lexical_cast.hpp>
00041 #include <boost/unordered_map.hpp>
00042 #include <boost/assign.hpp>
00043 #include <ros/console.h>
00044 
00045 namespace moveit_setup_assistant
00046 {
00047 // ******************************************************************************************
00048 // Custom Types, Enums and Structs
00049 // ******************************************************************************************
00050 
00051 // Boost mapping of reasons for disabling a link pair to strings
00052 const boost::unordered_map<DisabledReason, std::string> reasonsToString = boost::assign::map_list_of(NEVER, "Never")(
00053     DEFAULT, "Default")(ADJACENT, "Adjacent")(ALWAYS, "Always")(USER, "User")(NOT_DISABLED, "Not Disabled");
00054 
00055 const boost::unordered_map<std::string, DisabledReason> reasonsFromString = boost::assign::map_list_of("Never", NEVER)(
00056     "Default", DEFAULT)("Adjacent", ADJACENT)("Always", ALWAYS)("User", USER)("Not Disabled", NOT_DISABLED);
00057 
00058 // Unique set of pairs of links in string-based form
00059 typedef std::set<std::pair<std::string, std::string> > StringPairSet;
00060 
00061 // Struct for passing parameters to threads, for cleaner code
00062 struct ThreadComputation
00063 {
00064   ThreadComputation(planning_scene::PlanningScene& scene, const collision_detection::CollisionRequest& req,
00065                     int thread_id, int num_trials, StringPairSet* links_seen_colliding, boost::mutex* lock,
00066                     unsigned int* progress)
00067     : scene_(scene)
00068     , req_(req)
00069     , thread_id_(thread_id)
00070     , num_trials_(num_trials)
00071     , links_seen_colliding_(links_seen_colliding)
00072     , lock_(lock)
00073     , progress_(progress)
00074   {
00075   }
00076   planning_scene::PlanningScene& scene_;
00077   const collision_detection::CollisionRequest& req_;
00078   int thread_id_;
00079   unsigned int num_trials_;
00080   StringPairSet* links_seen_colliding_;
00081   boost::mutex* lock_;
00082   unsigned int* progress_;  // only to be updated by thread 0
00083 };
00084 
00085 // LinkGraph defines a Link's model and a set of unique links it connects
00086 typedef std::map<const robot_model::LinkModel*, std::set<const robot_model::LinkModel*> > LinkGraph;
00087 
00088 // ******************************************************************************************
00089 // Static Prototypes
00090 // ******************************************************************************************
00091 
00100 static bool setLinkPair(const std::string& linkA, const std::string& linkB, const DisabledReason reason,
00101                         LinkPairMap& link_pairs);
00102 
00108 static void computeConnectionGraph(const robot_model::LinkModel* link, LinkGraph& link_graph);
00109 
00115 static void computeConnectionGraphRec(const robot_model::LinkModel* link, LinkGraph& link_graph);
00116 
00124 static unsigned int disableAdjacentLinks(planning_scene::PlanningScene& scene, LinkGraph& link_graph,
00125                                          LinkPairMap& link_pairs);
00126 
00134 static unsigned int disableDefaultCollisions(planning_scene::PlanningScene& scene, LinkPairMap& link_pairs,
00135                                              collision_detection::CollisionRequest& req);
00136 
00147 static unsigned int disableAlwaysInCollision(planning_scene::PlanningScene& scene, LinkPairMap& link_pairs,
00148                                              collision_detection::CollisionRequest& req,
00149                                              StringPairSet& links_seen_colliding, double min_collision_faction = 0.95);
00150 
00159 static unsigned int disableNeverInCollision(const unsigned int num_trials, planning_scene::PlanningScene& scene,
00160                                             LinkPairMap& link_pairs, const collision_detection::CollisionRequest& req,
00161                                             StringPairSet& links_seen_colliding, unsigned int* progress);
00162 
00167 static void disableNeverInCollisionThread(ThreadComputation tc);
00168 
00169 // ******************************************************************************************
00170 // Generates an adjacency list of links that are always and never in collision, to speed up collision detection
00171 // ******************************************************************************************
00172 LinkPairMap computeDefaultCollisions(const planning_scene::PlanningSceneConstPtr& parent_scene, unsigned int* progress,
00173                                      const bool include_never_colliding, const unsigned int num_trials,
00174                                      const double min_collision_fraction, const bool verbose)
00175 {
00176   // Create new instance of planning scene using pointer
00177   planning_scene::PlanningScenePtr scene = parent_scene->diff();
00178 
00179   // Map of disabled collisions that contains a link as a key and an ordered list of links that are connected.
00180   LinkPairMap link_pairs;
00181 
00182   // Track unique edges that have been found to be in collision in some state
00183   StringPairSet links_seen_colliding;
00184 
00185   // LinkGraph is a custom type of a map with a LinkModel as key and a set of LinkModels as second
00186   LinkGraph link_graph;
00187 
00188   // ROS_INFO_STREAM("Initial allowed Collision Matrix Size = " << scene.getAllowedCollisions().getSize() );
00189 
00190   // 0. GENERATE ALL POSSIBLE LINK PAIRS -------------------------------------------------------------
00191   // Generate a list of unique link pairs for all links with geometry. Order pairs alphabetically.
00192   // There should be n choose 2 pairs
00193   computeLinkPairs(*scene, link_pairs);
00194   *progress = 1;
00195 
00196   // 1. FIND CONNECTING LINKS ------------------------------------------------------------------------
00197   // For each link, compute the set of other links it connects to via a single joint (adjacent links)
00198   // or via a chain of joints with intermediate links with no geometry (like a socket joint)
00199 
00200   // Create Connection Graph
00201   computeConnectionGraph(scene->getRobotModel()->getRootLink(), link_graph);
00202   *progress = 2;  // Progress bar feedback
00203 
00204   // 2. DISABLE ALL ADJACENT LINK COLLISIONS ---------------------------------------------------------
00205   // if 2 links are adjacent, or adjacent with a zero-shape between them, disable collision checking for them
00206   unsigned int num_adjacent = disableAdjacentLinks(*scene, link_graph, link_pairs);
00207   *progress = 4;  // Progress bar feedback
00208 
00209   // 3. INITIAL CONTACTS TO CONSIDER GUESS -----------------------------------------------------------
00210   // Create collision detection request object
00211   collision_detection::CollisionRequest req;
00212   req.contacts = true;
00213   // max number of contacts to compute. initial guess is number of links on robot
00214   req.max_contacts = int(link_graph.size());
00215   req.max_contacts_per_pair = 1;
00216   req.verbose = false;
00217 
00218   // 4. DISABLE "DEFAULT" COLLISIONS --------------------------------------------------------
00219   // Disable all collision checks that occur when the robot is started in its default state
00220   unsigned int num_default = disableDefaultCollisions(*scene, link_pairs, req);
00221   *progress = 6;  // Progress bar feedback
00222 
00223   // 5. ALWAYS IN COLLISION --------------------------------------------------------------------
00224   // Compute the links that are always in collision
00225   unsigned int num_always =
00226       disableAlwaysInCollision(*scene, link_pairs, req, links_seen_colliding, min_collision_fraction);
00227   // ROS_INFO("Links seen colliding total = %d", int(links_seen_colliding.size()));
00228   *progress = 8;  // Progress bar feedback
00229 
00230   // 6. NEVER IN COLLISION -------------------------------------------------------------------
00231   // Get the pairs of links that are never in collision
00232   unsigned int num_never = 0;
00233   if (include_never_colliding)  // option of function
00234   {
00235     num_never = disableNeverInCollision(num_trials, *scene, link_pairs, req, links_seen_colliding, progress);
00236   }
00237 
00238   // ROS_INFO("Link pairs seen colliding ever: %d", int(links_seen_colliding.size()));
00239 
00240   if (verbose)
00241   {
00242     // Calculate number of disabled links:
00243     unsigned int num_disabled = 0;
00244     for (LinkPairMap::const_iterator pair_it = link_pairs.begin(); pair_it != link_pairs.end(); ++pair_it)
00245     {
00246       if (pair_it->second.disable_check)  // has a reason to be disabled
00247         ++num_disabled;
00248     }
00249 
00250     ROS_INFO("-------------------------------------------------------------------------------");
00251     ROS_INFO("Statistics:");
00252     unsigned int num_links = int(link_graph.size());
00253     double num_possible = boost::math::binomial_coefficient<double>(num_links, 2);  // n choose 2
00254     unsigned int num_sometimes = num_possible - num_disabled;
00255 
00256     ROS_INFO("%6d : %s", num_links, "Total Links");
00257     ROS_INFO("%6.0f : %s", num_possible, "Total possible collisions");
00258     ROS_INFO("%6d : %s", num_always, "Always in collision");
00259     ROS_INFO("%6d : %s", num_never, "Never in collision");
00260     ROS_INFO("%6d : %s", num_default, "Default in collision");
00261     ROS_INFO("%6d : %s", num_adjacent, "Adjacent links disabled");
00262     ROS_INFO("%6d : %s", num_sometimes, "Sometimes in collision");
00263     ROS_INFO("%6d : %s", num_disabled, "TOTAL DISABLED");
00264 
00265     /*ROS_INFO("Copy to Spreadsheet:");
00266     ROS_INFO_STREAM(num_links << "\t" << num_possible << "\t" << num_always << "\t" << num_never
00267                     << "\t" << num_default << "\t" << num_adjacent << "\t" << num_sometimes
00268                     << "\t" << num_disabled);
00269     */
00270   }
00271 
00272   *progress = 100;  // end the status bar
00273 
00274   return link_pairs;
00275 }
00276 
00277 // ******************************************************************************************
00278 // Helper function for adding two links to the disabled links data structure
00279 // ******************************************************************************************
00280 bool setLinkPair(const std::string& linkA, const std::string& linkB, const DisabledReason reason,
00281                  LinkPairMap& link_pairs)
00282 {
00283   bool isUnique = false;  // determine if this link pair had already existsed in the link_pairs datastructure
00284 
00285   // Determine order of the 2 links in the pair
00286   std::pair<std::string, std::string> link_pair;
00287 
00288   // compare the string names of the two links and add the lesser alphabetically, s.t. the pair is only added once
00289   if (linkA < linkB)
00290   {
00291     link_pair = std::pair<std::string, std::string>(linkA, linkB);
00292   }
00293   else
00294   {
00295     link_pair = std::pair<std::string, std::string>(linkB, linkA);
00296   }
00297 
00298   // Update properties of this link pair using only 1 search
00299   LinkPairData* link_pair_ptr = &link_pairs[link_pair];
00300 
00301   // Check if link pair was already disabled. It also creates the entry if none existed
00302   if (link_pairs[link_pair].disable_check == false)  // it was not previously disabled
00303   {
00304     isUnique = true;
00305     link_pair_ptr->reason = reason;  // only change the reason if the pair was previously enabled
00306   }
00307 
00308   // Only disable collision checking if there is a reason to disable it. This func is also used for initializing pairs
00309   link_pair_ptr->disable_check = (reason != NOT_DISABLED);
00310 
00311   return isUnique;
00312 }
00313 
00314 // ******************************************************************************************
00315 // Generate a list of unique link pairs for all links with geometry. Order pairs alphabetically. n choose 2 pairs
00316 // ******************************************************************************************
00317 void computeLinkPairs(const planning_scene::PlanningScene& scene, LinkPairMap& link_pairs)
00318 {
00319   // Get the names of the link models that have some collision geometry associated to themselves
00320   const std::vector<std::string>& names = scene.getRobotModel()->getLinkModelNamesWithCollisionGeometry();
00321 
00322   std::pair<std::string, std::string> temp_pair;
00323 
00324   // Loop through every combination of name pairs, AB and BA, n^2
00325   for (std::size_t i = 0; i < names.size(); ++i)
00326   {
00327     for (std::size_t j = i + 1; j < names.size(); ++j)
00328     {
00329       // Add to link pairs list
00330       setLinkPair(names[i], names[j], NOT_DISABLED, link_pairs);
00331     }
00332   }
00333 }
00334 // ******************************************************************************************
00335 // Build the robot links connection graph and then check for links with no geomotry
00336 // ******************************************************************************************
00337 void computeConnectionGraph(const robot_model::LinkModel* start_link, LinkGraph& link_graph)
00338 {
00339   link_graph.clear();  // make sure the edges structure is clear
00340 
00341   // Recurively build adj list of link connections
00342   computeConnectionGraphRec(start_link, link_graph);
00343 
00344   // Repeatidly check for links with no geometry and remove them, then re-check until no more removals are detected
00345   bool update = true;  // track if a no geometry link was found
00346   while (update)
00347   {
00348     update = false;  // default
00349 
00350     // Check if each edge has a shape
00351     for (LinkGraph::const_iterator edge_it = link_graph.begin(); edge_it != link_graph.end(); ++edge_it)
00352     {
00353       if (edge_it->first->getShapes().empty())  // link in adjList "link_graph" does not have shape, remove!
00354       {
00355         // Temporary list for connected links
00356         std::vector<const robot_model::LinkModel*> temp_list;
00357 
00358         // Copy link's parent and child links to temp_list
00359         for (std::set<const robot_model::LinkModel*>::const_iterator adj_it = edge_it->second.begin();
00360              adj_it != edge_it->second.end(); ++adj_it)
00361         {
00362           temp_list.push_back(*adj_it);
00363         }
00364 
00365         // Make all preceeding and succeeding links to the no-shape link fully connected
00366         // so that they don't collision check with themselves
00367         for (std::size_t i = 0; i < temp_list.size(); ++i)
00368         {
00369           for (std::size_t j = i + 1; j < temp_list.size(); ++j)
00370           {
00371             // for each LinkModel in temp_list, find its location in the link_graph structure and insert the rest
00372             // of the links into its unique set.
00373             // if the LinkModel is not already in the set, update is set to true so that we keep searching
00374             if (link_graph[temp_list[i]].insert(temp_list[j]).second)
00375               update = true;
00376             if (link_graph[temp_list[j]].insert(temp_list[i]).second)
00377               update = true;
00378           }
00379         }
00380       }
00381     }
00382   }
00383   // ROS_INFO("Generated connection graph with %d links", int(link_graph.size()));
00384 }
00385 
00386 // ******************************************************************************************
00387 // Recursively build the adj list of link connections
00388 // ******************************************************************************************
00389 void computeConnectionGraphRec(const robot_model::LinkModel* start_link, LinkGraph& link_graph)
00390 {
00391   if (start_link)  // check that the link is a valid pointer
00392   {
00393     // Loop through every link attached to start_link
00394     for (std::size_t i = 0; i < start_link->getChildJointModels().size(); ++i)
00395     {
00396       const robot_model::LinkModel* next = start_link->getChildJointModels()[i]->getChildLinkModel();
00397 
00398       // Bi-directional connection
00399       link_graph[next].insert(start_link);
00400       link_graph[start_link].insert(next);
00401 
00402       // Iterate with subsequent link
00403       computeConnectionGraphRec(next, link_graph);
00404     }
00405   }
00406   else
00407   {
00408     ROS_ERROR("Joint exists in URDF with no link!");
00409   }
00410 }
00411 
00412 // ******************************************************************************************
00413 // Disable collision checking for adjacent links, or adjacent with no geometry links between them
00414 // ******************************************************************************************
00415 unsigned int disableAdjacentLinks(planning_scene::PlanningScene& scene, LinkGraph& link_graph, LinkPairMap& link_pairs)
00416 {
00417   int num_disabled = 0;
00418   for (LinkGraph::const_iterator link_graph_it = link_graph.begin(); link_graph_it != link_graph.end(); ++link_graph_it)
00419   {
00420     // disable all connected links to current link by looping through them
00421     for (std::set<const robot_model::LinkModel*>::const_iterator adj_it = link_graph_it->second.begin();
00422          adj_it != link_graph_it->second.end(); ++adj_it)
00423     {
00424       // ROS_INFO("Disabled %s to %s", link_graph_it->first->getName().c_str(), (*adj_it)->getName().c_str() );
00425 
00426       // Check if either of the links have no geometry. If so, do not add (are we sure?)
00427       if (!link_graph_it->first->getShapes().empty() && !(*adj_it)->getShapes().empty())  // both links have geometry
00428       {
00429         num_disabled += setLinkPair(link_graph_it->first->getName(), (*adj_it)->getName(), ADJACENT, link_pairs);
00430 
00431         // disable link checking in the collision matrix
00432         scene.getAllowedCollisionMatrixNonConst().setEntry(link_graph_it->first->getName(), (*adj_it)->getName(), true);
00433       }
00434     }
00435   }
00436   // ROS_INFO("Disabled %d adjancent link pairs from collision checking", num_disabled);
00437 
00438   return num_disabled;
00439 }
00440 
00441 // ******************************************************************************************
00442 // Disable all collision checks that occur when the robot is started in its default state
00443 // ******************************************************************************************
00444 unsigned int disableDefaultCollisions(planning_scene::PlanningScene& scene, LinkPairMap& link_pairs,
00445                                       collision_detection::CollisionRequest& req)
00446 {
00447   // Setup environment
00448   collision_detection::CollisionResult res;
00449   scene.getCurrentStateNonConst().setToDefaultValues();  // set to default values of 0 OR half between low and high
00450                                                          // joint values
00451   scene.checkSelfCollision(req, res);
00452 
00453   // For each collision in default state, always add to disabled links set
00454   int num_disabled = 0;
00455   for (collision_detection::CollisionResult::ContactMap::const_iterator it = res.contacts.begin();
00456        it != res.contacts.end(); ++it)
00457   {
00458     num_disabled += setLinkPair(it->first.first, it->first.second, DEFAULT, link_pairs);
00459 
00460     // disable link checking in the collision matrix
00461     scene.getAllowedCollisionMatrixNonConst().setEntry(it->first.first, it->first.second, true);
00462   }
00463 
00464   // ROS_INFO("Disabled %d link pairs that are in collision in default state from collision checking", num_disabled);
00465 
00466   return num_disabled;
00467 }
00468 
00469 // ******************************************************************************************
00470 // Compute the links that are always in collision
00471 // ******************************************************************************************
00472 unsigned int disableAlwaysInCollision(planning_scene::PlanningScene& scene, LinkPairMap& link_pairs,
00473                                       collision_detection::CollisionRequest& req, StringPairSet& links_seen_colliding,
00474                                       double min_collision_faction)
00475 {
00476   // Trial count variables
00477   static const unsigned int small_trial_count = 200;
00478   static const unsigned int small_trial_limit = (unsigned int)((double)small_trial_count * min_collision_faction);
00479 
00480   bool done = false;
00481   unsigned int num_disabled = 0;
00482 
00483   while (!done)
00484   {
00485     // DO 'small_trial_count' COLLISION CHECKS AND RECORD STATISTICS ---------------------------------------
00486     std::map<std::pair<std::string, std::string>, unsigned int> collision_count;
00487 
00488     // Do a large number of tests
00489     for (unsigned int i = 0; i < small_trial_count; ++i)
00490     {
00491       // Check for collisions
00492       collision_detection::CollisionResult res;
00493       scene.getCurrentStateNonConst().setToRandomPositions();
00494       scene.checkSelfCollision(req, res);
00495 
00496       // Sum the number of collisions
00497       unsigned int nc = 0;
00498       for (collision_detection::CollisionResult::ContactMap::const_iterator it = res.contacts.begin();
00499            it != res.contacts.end(); ++it)
00500       {
00501         collision_count[it->first]++;
00502         links_seen_colliding.insert(it->first);
00503         nc += it->second.size();
00504       }
00505 
00506       // Check if the number of contacts is greater than the max count
00507       if (nc >= req.max_contacts)
00508       {
00509         req.max_contacts *= 2;  // double the max contacts that the CollisionRequest checks for
00510         // ROS_INFO("Doubling max_contacts to %d", int(req.max_contacts));
00511       }
00512     }
00513 
00514     // >= XX% OF TIME IN COLLISION DISABLE -----------------------------------------------------
00515     // Disable collision checking for links that are >= XX% of the time in collision (XX% = 95% by default)
00516     int found = 0;
00517 
00518     // Loop through every pair of link collisions and disable if it meets the threshold
00519     for (std::map<std::pair<std::string, std::string>, unsigned int>::const_iterator it = collision_count.begin();
00520          it != collision_count.end(); ++it)
00521     {
00522       // Disable these two links permanently
00523       if (it->second > small_trial_limit)
00524       {
00525         num_disabled += setLinkPair(it->first.first, it->first.second, ALWAYS, link_pairs);
00526 
00527         // disable link checking in the collision matrix
00528         scene.getAllowedCollisionMatrixNonConst().setEntry(it->first.first, it->first.second, true);
00529 
00530         found++;
00531       }
00532     }
00533 
00534     // if no updates were made to the collision matrix, we stop
00535     if (found == 0)
00536       done = true;
00537 
00538     // ROS_INFO("Disabled %u link pairs that are always in collision from collision checking", found);
00539   }
00540 
00541   return num_disabled;
00542 }
00543 
00544 // ******************************************************************************************
00545 // Get the pairs of links that are never in collision
00546 // ******************************************************************************************
00547 unsigned int disableNeverInCollision(const unsigned int num_trials, planning_scene::PlanningScene& scene,
00548                                      LinkPairMap& link_pairs, const collision_detection::CollisionRequest& req,
00549                                      StringPairSet& links_seen_colliding, unsigned int* progress)
00550 {
00551   unsigned int num_disabled = 0;
00552 
00553   boost::thread_group bgroup;  // create a group of threads
00554   boost::mutex lock;           // used for sharing the same data structures
00555 
00556   int num_threads = boost::thread::hardware_concurrency();  // how many cores does this computer have?
00557   // ROS_INFO_STREAM("Performing " << num_trials << " trials for 'always in collision' checking on " <<
00558   //   num_threads << " threads...");
00559 
00560   for (int i = 0; i < num_threads; ++i)
00561   {
00562     ThreadComputation tc(scene, req, i, num_trials / num_threads, &links_seen_colliding, &lock, progress);
00563     bgroup.create_thread(boost::bind(&disableNeverInCollisionThread, tc));
00564   }
00565 
00566   bgroup.join_all();  // wait for all threads to finish
00567 
00568   // Loop through every possible link pair and check if it has ever been seen in collision
00569   for (LinkPairMap::iterator pair_it = link_pairs.begin(); pair_it != link_pairs.end(); ++pair_it)
00570   {
00571     if (!pair_it->second.disable_check)  // is not disabled yet
00572     {
00573       // Check if current pair has been seen colliding ever. If it has never been seen colliding, add it to disabled
00574       // list
00575       if (links_seen_colliding.find(pair_it->first) == links_seen_colliding.end())
00576       {
00577         // Add to disabled list using pair ordering
00578         pair_it->second.reason = NEVER;
00579         pair_it->second.disable_check = true;
00580 
00581         // Count it
00582         ++num_disabled;
00583       }
00584     }
00585   }
00586   // ROS_INFO("Disabled %d link pairs that are never in collision", num_disabled);
00587 
00588   return num_disabled;
00589 }
00590 
00591 // ******************************************************************************************
00592 // Thread for getting the pairs of links that are never in collision
00593 // ******************************************************************************************
00594 void disableNeverInCollisionThread(ThreadComputation tc)
00595 {
00596   // ROS_INFO_STREAM("Thread " << tc.thread_id_ << " running " << tc.num_trials_ << " trials");
00597 
00598   // User feedback vars
00599   const unsigned int progress_interval = tc.num_trials_ / 20;  // show progress update every 5%
00600 
00601   // Create a new kinematic state for this thread to work on
00602   robot_state::RobotState kstate(tc.scene_.getRobotModel());
00603 
00604   // Do a large number of tests
00605   for (unsigned int i = 0; i < tc.num_trials_; ++i)
00606   {
00607     // Status update at intervals and only for 0 thread
00608     if (i % progress_interval == 0 && tc.thread_id_ == 0)
00609     {
00610       // ROS_INFO("Collision checking %d%% complete", int(i * 100 / tc.num_trials_ ));
00611       (*tc.progress_) = i * 92 / tc.num_trials_ + 8;  // 8 is the amount of progress already completed in prev steps
00612     }
00613 
00614     collision_detection::CollisionResult res;
00615     kstate.setToRandomPositions();
00616     tc.scene_.checkSelfCollision(tc.req_, res, kstate);
00617 
00618     // Check all contacts
00619     for (collision_detection::CollisionResult::ContactMap::const_iterator it = res.contacts.begin();
00620          it != res.contacts.end(); ++it)
00621     {
00622       // Check if this collision pair is unique before doing a thread lock
00623       if (tc.links_seen_colliding_->find(it->first) == tc.links_seen_colliding_->end())
00624       {
00625         // Collision Matrix and links_seen_colliding is modified only if needed, based on above if statement
00626 
00627         boost::mutex::scoped_lock slock(*tc.lock_);
00628         tc.links_seen_colliding_->insert(it->first);
00629 
00630         tc.scene_.getAllowedCollisionMatrixNonConst().setEntry(it->first.first, it->first.second,
00631                                                                true);  // disable link checking in the collision matrix
00632       }
00633     }
00634   }
00635 }
00636 
00637 // ******************************************************************************************
00638 // Converts a reason for disabling a link pair into a string
00639 // ******************************************************************************************
00640 const std::string disabledReasonToString(DisabledReason reason)
00641 {
00642   return reasonsToString.at(reason);
00643 }
00644 
00645 // ******************************************************************************************
00646 // Converts a string reason for disabling a link pair into a struct data type
00647 // ******************************************************************************************
00648 DisabledReason disabledReasonFromString(const std::string& reason)
00649 {
00650   DisabledReason r;
00651   try
00652   {
00653     r = reasonsFromString.at(reason);
00654   }
00655   catch (std::out_of_range)
00656   {
00657     r = USER;
00658   }
00659 
00660   return r;
00661 }
00662 
00663 }  // namespace


moveit_setup_assistant
Author(s): Dave Coleman
autogenerated on Wed Jun 19 2019 19:25:13