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


moveit_setup_assistant
Author(s): Dave Coleman
autogenerated on Mon Oct 6 2014 02:32:27