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
00079
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
00088
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
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
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
00149 state.setToRandomPositions();
00150 JointConfig init_state;
00151 state.copyJointGroupPositions(group, init_state);
00152
00153
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
00160 const size_t iterations = joint1_perms.size() * joint2_perms.size();
00161 for (std::size_t i = 0; i < iterations; ++i)
00162 {
00163
00164 JointConfig round_ik = createSeedFromPerms(init_state, joint1_perms, pair.first,
00165 joint2_perms, pair.second, i);
00166
00167 std::vector<size_t> this_round_seeds;
00168 JointConfigVec this_round_iks;
00169
00170
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
00179 if (isSingularity(state, group))
00180 {
00181 ROS_DEBUG_STREAM("Pose " << i << " at singularity.");
00182 continue;
00183 }
00184
00185
00186 this_round_seeds.push_back(i);
00187 this_round_iks.push_back(round_ik);
00188
00189
00190 for (size_t idx : final_seed_states)
00191 {
00192
00193 JointConfig seed = createSeedFromPerms(init_state, joint1_perms, pair.first,
00194 joint2_perms, pair.second, idx);
00195 JointConfig ik;
00196
00197 if (!doIK(state, group, group_name, tool_frame, target_pose, seed, ik))
00198 {
00199 continue;
00200 }
00201
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
00210 for (std::size_t j = 0; j < iterations; ++j)
00211 {
00212
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
00227
00228
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 }
00239
00240
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 }