seed_search.cpp
Go to the documentation of this file.
00001 #include <descartes_moveit/seed_search.h>
00002 
00003 #include <ros/ros.h>
00004 
00005 using namespace descartes_moveit;
00006 
00007 typedef std::vector<unsigned> BijectionVec;
00008 typedef std::pair<unsigned, unsigned> JointPair;
00009 typedef std::vector<JointPair> JointPairVec;
00010 typedef std::vector<double> JointConfig;
00011 typedef std::vector<JointConfig> JointConfigVec;
00012 
00016 bool doFK(moveit::core::RobotState& state,
00017           const moveit::core::JointModelGroup* group,
00018           const std::string& tool,
00019           const JointConfig& joint_pose,
00020           Eigen::Affine3d& result)
00021 {
00022   state.setJointGroupPositions(group, joint_pose);
00023   if (!state.knowsFrameTransform(tool))
00024   {
00025     ROS_WARN("No transform to this tool frame");
00026     return false;
00027   }
00028 
00029   if (!state.satisfiesBounds())
00030   {
00031     ROS_WARN("Joint angles do not satisfy robot bounds");
00032     return false;
00033   }
00034 
00035   result = state.getFrameTransform(tool);
00036   return true;
00037 }
00038 
00043 bool doIK(moveit::core::RobotState& state,
00044           const moveit::core::JointModelGroup* group,
00045           const std::string& group_name,
00046           const std::string& tool,
00047           const Eigen::Affine3d& pose,
00048           const JointConfig& seed,
00049           JointConfig& result)
00050 {
00051   const static int N_ATTEMPTS = 1;
00052   const static double IK_TIMEOUT = 0.01;
00053 
00054   state.setJointGroupPositions(group_name, seed);
00055   if (!state.setFromIK(group, pose, tool, N_ATTEMPTS, IK_TIMEOUT))
00056   {
00057     return false;
00058   }
00059   state.copyJointGroupPositions(group, result);
00060   return true;
00061 }
00062 
00066 bool isSingularity(moveit::core::RobotState& state,
00067                    const moveit::core::JointModelGroup* group)
00068 {
00069  const static double MIN_DETERMINANT_VALUE = 0.0001;
00070  Eigen::Vector3d reference_point_position(0.0, 0.0, 0.0);
00071  Eigen::MatrixXd jacobian;
00072  state.getJacobian(group, state.getLinkModel(group->getLinkModelNames().back()),
00073                    reference_point_position, jacobian);
00074 
00075  return std::abs(jacobian.determinant()) < MIN_DETERMINANT_VALUE;
00076 }
00077 
00078 // Compares the first n_compare bijection joint values from a and b and tests
00079 // whether they are within 45 degrees of one another
00080 inline bool isSameJointConfig(const JointConfig& a, const JointConfig& b, const JointPair& pair)
00081 {
00082   const static double MIN_DIFF = M_PI_4;
00083   return std::abs(a[pair.first] - b[pair.first]) < MIN_DIFF &&
00084          std::abs(a[pair.second] - b[pair.second]) < MIN_DIFF;
00085 }
00086 
00087 // Tests whether a given joint configuration, c, is similar to any joint set already
00088 // in set using the given bijection values and number of joints.
00089 inline bool isInJointSet(const JointConfig& c, const JointConfigVec& set, const JointPair& pair)
00090 {
00091   for (std::size_t i = 0; i < set.size(); ++i)
00092   {
00093     if (isSameJointConfig(c, set[i], pair)) return true;
00094   }
00095   return false;
00096 }
00097 
00098 std::vector<double> createValidJointPositions(const moveit::core::JointModel& model,
00099                                               double increment)
00100 {
00101   // Should never be called with fixed joint
00102   const moveit::core::JointModel::Bounds& bounds = model.getVariableBounds();
00103   double min = bounds[0].min_position_;
00104   double max = bounds[0].max_position_;
00105 
00106   std::vector<double> result;
00107   while (min <= max)
00108   {
00109       result.push_back(min);
00110       min += increment;
00111   }
00112 
00113   return result;
00114 }
00115 
00116 std::vector<double> createSeedFromPerms(const std::vector<double>& initial,
00117                                         const std::vector<double>& a_perms,
00118                                         unsigned a_joint_idx,
00119                                         const std::vector<double>& b_perms,
00120                                         unsigned b_joint_idx,
00121                                         unsigned n)
00122 {
00123   std::vector<double> seed = initial;
00124   double a_value = a_perms[n / b_perms.size()];
00125   double b_value = b_perms[n % b_perms.size()];
00126   seed[a_joint_idx] = a_value;
00127   seed[b_joint_idx] = b_value;
00128   return seed;
00129 }
00130 
00131 JointConfigVec findSeedStatesForPair(moveit::core::RobotState& state,
00132                                      const std::string& group_name,
00133                                      const std::string& tool_frame,
00134                                      const JointPair& pair)
00135 {
00136   using namespace moveit::core;
00137   
00138   const JointModelGroup* group = state.getJointModelGroup(group_name);
00139   const std::vector<const JointModel*> active_joints = group->getActiveJointModels();
00140 
00141   // check each joint to see if it is revolute
00142   for (const JointModel* model : active_joints)
00143   {
00144     if (model->getType() != JointModel::REVOLUTE)
00145       ROS_WARN_STREAM("Joint '" << model->getName() << "' does not appear to be revolute");
00146   }
00147 
00148   // compute random starting values for all joints
00149   state.setToRandomPositions();
00150   JointConfig init_state;
00151   state.copyJointGroupPositions(group, init_state);
00152 
00153   // Precompute the valid positions for the two joints we'll iterate over
00154   std::vector<double> joint1_perms = createValidJointPositions(*active_joints[pair.first], M_PI_2);
00155   std::vector<double> joint2_perms = createValidJointPositions(*active_joints[pair.second], M_PI_2);
00156 
00157   std::set<size_t> final_seed_states;
00158 
00159   // Walk the valid combos
00160   const size_t iterations = joint1_perms.size() * joint2_perms.size();
00161   for (std::size_t i = 0; i < iterations; ++i)
00162   {
00163     // Make the seed state for this index from permutations
00164     JointConfig round_ik = createSeedFromPerms(init_state, joint1_perms, pair.first,
00165                                                joint2_perms, pair.second, i);
00166     // Containers for the valid seeds and ik solutions for THIS round
00167     std::vector<size_t> this_round_seeds;
00168     JointConfigVec this_round_iks;
00169 
00170     // Forward kinematics
00171     Eigen::Affine3d target_pose;
00172     if (!doFK(state, group, tool_frame, round_ik, target_pose))
00173     {
00174       ROS_DEBUG_STREAM("No FK for pose " << i);
00175       continue;
00176     }
00177 
00178     // Check to make sure we're not in a singularity
00179     if (isSingularity(state, group))
00180     {
00181       ROS_DEBUG_STREAM("Pose " << i << " at singularity.");
00182       continue;
00183     }
00184 
00185     // Add initial states to the iks/seeds for this point
00186     this_round_seeds.push_back(i);
00187     this_round_iks.push_back(round_ik);
00188 
00189     // Now we'll walk through all of the other seeds, starting with the ones that have worked so far
00190     for (size_t idx : final_seed_states)
00191     {
00192       // create joint config fom handle
00193       JointConfig seed = createSeedFromPerms(init_state, joint1_perms, pair.first,
00194                                              joint2_perms, pair.second, idx);
00195       JointConfig ik;
00196       // perform ik
00197       if (!doIK(state, group, group_name, tool_frame, target_pose, seed, ik))
00198       {
00199         continue;
00200       }
00201       // If we have a unique IK solution, then add to the iks seen this round
00202       if (!isInJointSet(ik, this_round_iks, pair))
00203       {
00204         this_round_iks.push_back(ik);
00205         this_round_seeds.push_back(idx);
00206       }
00207     }
00208 
00209     // Now try the rest of the joint possible seed states if they haven't been tried
00210     for (std::size_t j = 0; j < iterations; ++j)
00211     {
00212       // skip the situation where pose is generated from current seed we already have that ik
00213       if (i == j) continue;
00214 
00215       unsigned count = final_seed_states.count(j);
00216       if (count != 0) continue;
00217 
00218       JointConfig seed = createSeedFromPerms(init_state, joint1_perms, pair.first,
00219                                              joint2_perms, pair.second, j);
00220       JointConfig ik;
00221       if (!doIK(state, group, group_name, tool_frame, target_pose, seed, ik))
00222       {
00223         continue;
00224       }
00225 
00226       // If we have a new IK solution here, then it was generated
00227       // by a seed that has not yet been added to the overall seed
00228       // states to be returned
00229       if (!isInJointSet(ik, this_round_iks, pair))
00230       {
00231         this_round_iks.push_back(ik);
00232         this_round_seeds.push_back(j);
00233         final_seed_states.insert(j);
00234       }
00235     }
00236 
00237     ROS_DEBUG_STREAM("Calculated " << this_round_iks.size() << " unique IK states this round");
00238   } // outer loop end
00239 
00240   // Consolidate set into vector for the result
00241   JointConfigVec result;
00242   result.reserve(final_seed_states.size());
00243   for (size_t idx : final_seed_states)
00244   {
00245     result.push_back(createSeedFromPerms(init_state, joint1_perms,
00246                                          pair.first, joint2_perms,
00247                                          pair.second, idx));
00248   }
00249   return result;
00250 }
00251 
00252 JointConfigVec seed::findSeedStatesByPairs(moveit::core::RobotState& state,
00253                                            const std::string& group_name,
00254                                            const std::string& tool_frame,
00255                                            const JointPairVec& pairs)
00256 {
00257   JointConfigVec result;
00258   for (const auto& pair : pairs)
00259   {
00260     JointConfigVec partial_answer = findSeedStatesForPair(state, group_name, tool_frame, pair);
00261     result.insert(result.end(), partial_answer.begin(), partial_answer.end());
00262   }
00263   return result;
00264 }
00265 
00266 JointConfigVec seed::findRandomSeeds(moveit::core::RobotState& state,
00267                                      const std::string& group_name,
00268                                      unsigned n)
00269 {
00270   auto group = state.getJointModelGroup(group_name);
00271 
00272   JointConfigVec result;
00273   
00274   for (unsigned i = 0; i < n; ++i)
00275   {
00276     state.setToRandomPositions();
00277 
00278     JointConfig c;
00279     state.copyJointGroupPositions(group, c);
00280     
00281     result.push_back(c);
00282   }
00283   return result;
00284 }


descartes_moveit
Author(s): Shaun Edwards
autogenerated on Wed Aug 26 2015 11:21:41