63 #define IKFAST_NO_MAIN // Don't include main() from IKFast 218 const std::vector<double> &ik_seed_state,
219 std::vector<double> &solution,
220 moveit_msgs::MoveItErrorCodes &error_code,
245 const std::vector<double> &ik_seed_state,
246 std::vector<std::vector<double>> &solutions,
261 const std::vector<double> &ik_seed_state,
262 double timeout, std::vector<double> &solution,
263 moveit_msgs::MoveItErrorCodes &error_code,
279 const std::vector<double> &ik_seed_state,
281 const std::vector<double> &consistency_limits,
282 std::vector<double> &solution,
283 moveit_msgs::MoveItErrorCodes &error_code,
298 const std::vector<double> &ik_seed_state,
299 double timeout, std::vector<double> &solution,
301 moveit_msgs::MoveItErrorCodes &error_code,
321 const std::vector<double> &ik_seed_state,
323 const std::vector<double> &consistency_limits,
324 std::vector<double> &solution,
326 moveit_msgs::MoveItErrorCodes &error_code,
339 bool getPositionFK(
const std::vector<std::string> &link_names,
340 const std::vector<double> &joint_angles,
341 std::vector<geometry_msgs::Pose> &poses)
const;
364 bool initialize(
const std::string &robot_description,
365 const std::string &group_name,
const std::string &base_name,
366 const std::string &tip_name,
double search_discretization);
379 std::vector<double> &solution)
const;
381 double harmonize(
const std::vector<double> &ik_seed_state,
382 std::vector<double> &solution)
const;
386 const std::vector<double> &ik_seed_state,
387 std::vector<double> &solution)
const;
389 bool getCount(
int &count,
const int &max_count,
const int &min_count)
const;
400 std::vector<double> &sampled_joint_vals)
const;
405 const std::string &group_name,
406 const std::string &base_name,
407 const std::string &tip_name,
408 double search_discretization) {
409 setValues(robot_description, group_name, base_name, tip_name,
410 search_discretization);
415 node_handle.param(
"robot", robot, std::string());
421 if (free_params_.size() > 1) {
424 }
else if (free_params_.size() == 1) {
433 std::string urdf_xml, full_urdf_xml;
434 node_handle.param(
"urdf_xml", urdf_xml, robot_description);
435 node_handle.searchParam(urdf_xml, full_urdf_xml);
438 if (!node_handle.getParam(full_urdf_xml, xml_string)) {
440 "Could not load the xml from parameter server: %s",
445 node_handle.param(full_urdf_xml, xml_string, std::string());
450 urdf::LinkConstSharedPtr link = robot_model.getLink(
getTipFrame());
453 link_names_.push_back(link->name);
454 urdf::JointSharedPtr joint = link->parent_joint;
456 if (joint->type != urdf::Joint::UNKNOWN &&
457 joint->type != urdf::Joint::FIXED) {
460 joint_names_.push_back(joint->name);
463 if (joint->type != urdf::Joint::CONTINUOUS) {
465 lower = joint->safety->soft_lower_limit;
466 upper = joint->safety->soft_upper_limit;
468 lower = joint->limits->lower;
469 upper = joint->limits->upper;
478 joint_has_limits_vector_.push_back(
true);
479 joint_min_vector_.push_back(lower);
480 joint_max_vector_.push_back(upper);
482 joint_has_limits_vector_.push_back(
false);
483 joint_min_vector_.push_back(-M_PI);
484 joint_max_vector_.push_back(M_PI);
491 link = link->getParent();
496 << joint_names_.size()
501 std::reverse(link_names_.begin(), link_names_.end());
502 std::reverse(joint_names_.begin(), joint_names_.end());
503 std::reverse(joint_min_vector_.begin(), joint_min_vector_.end());
504 std::reverse(joint_max_vector_.begin(), joint_max_vector_.end());
505 std::reverse(joint_has_limits_vector_.begin(),
506 joint_has_limits_vector_.end());
510 <<
" " << joint_min_vector_[i] <<
" " 511 << joint_max_vector_[i] <<
" " 512 << joint_has_limits_vector_[i]);
519 const std::map<int, double> &discretization) {
520 if (discretization.empty()) {
521 ROS_ERROR(
"The 'discretization' map is empty");
531 std::string redundant_joint = joint_names_[free_params_[0]];
533 << discretization.begin()->first <<
", only joint '" 534 << redundant_joint <<
"' with index " 539 if (discretization.begin()->second <= 0.0) {
546 discretization.begin()->second;
550 const std::vector<unsigned int> &redundant_joint_indices) {
552 "Changing the redundant joints isn't permitted by this group's solver ");
557 const std::vector<double> &vfree,
563 trans[0] = pose_frame.
p[0];
564 trans[1] = pose_frame.
p[1];
565 trans[2] = pose_frame.
p[2];
579 vals[0] = mult(0, 0);
580 vals[1] = mult(0, 1);
581 vals[2] = mult(0, 2);
582 vals[3] = mult(1, 0);
583 vals[4] = mult(1, 1);
584 vals[5] = mult(1, 2);
585 vals[6] = mult(2, 0);
586 vals[7] = mult(2, 1);
587 vals[8] = mult(2, 2);
590 ComputeIk(trans, vals, vfree.size() > 0 ? &vfree[0] : NULL, solutions);
601 ComputeIk(trans, direction.
data, vfree.size() > 0 ? &vfree[0] : NULL,
612 "IK for this IkParameterizationType not implemented yet.");
620 "IK for this IkParameterizationType not implemented yet.");
631 "IK for this IkParameterizationType not implemented yet.");
635 ROS_ERROR_NAMED(
"ikfast",
"Unknown IkParameterizationType! Was the solver " 636 "generated with an incompatible version " 644 std::vector<double> &solution)
const {
646 solution.resize(num_joints_);
650 std::vector<IkReal> vsolfree(sol.
GetFree().size());
651 sol.
GetSolution(&solution[0], vsolfree.size() > 0 ? &vsolfree[0] : NULL);
663 std::vector<double> &solution)
const {
665 std::vector<double> ss = ik_seed_state;
666 for (
size_t i = 0; i < ik_seed_state.size(); ++i) {
667 while (ss[i] > 2 *
M_PI) {
670 while (ss[i] < 2 *
M_PI) {
673 while (solution[i] > 2 *
M_PI) {
674 solution[i] -= 2 *
M_PI;
676 while (solution[i] < 2 *
M_PI) {
677 solution[i] += 2 *
M_PI;
679 dist_sqr += fabs(ik_seed_state[i] - solution[i]);
710 const std::vector<double> &ik_seed_state,
711 std::vector<double> &solution)
const {
712 double mindist = DBL_MAX;
714 std::vector<double> sol;
719 double dist =
harmonize(ik_seed_state, sol);
722 if (minindex == -1 || dist < mindist) {
734 free_params_.clear();
735 for (
int i = 0; i < count; ++i)
736 free_params_.push_back(array[i]);
740 const int &min_count)
const {
742 if (-count >= min_count) {
745 }
else if (count + 1 <= max_count) {
752 if (1 - count <= max_count) {
755 }
else if (count - 1 >= min_count) {
764 const std::vector<std::string> &link_names,
765 const std::vector<double> &joint_angles,
766 std::vector<geometry_msgs::Pose> &poses)
const {
772 ROS_ERROR_NAMED(
"ikfast",
"Can only compute FK for Transform6D IK type!");
777 if (link_names.size() == 0) {
782 if (link_names.size() != 1 || link_names[0] !=
getTipFrame()) {
790 IkReal eerot[9], eetrans[3];
791 IkReal
angles[joint_angles.size()];
792 for (
unsigned char i = 0; i < joint_angles.size(); i++)
793 angles[i] = joint_angles[i];
798 for (
int i = 0; i < 3; ++i)
799 p_out.
p.
data[i] = eetrans[i];
801 for (
int i = 0; i < 9; ++i)
802 p_out.
M.
data[i] = eerot[i];
811 const geometry_msgs::Pose &ik_pose,
812 const std::vector<double> &ik_seed_state,
double timeout,
813 std::vector<double> &solution, moveit_msgs::MoveItErrorCodes &error_code,
816 std::vector<double> consistency_limits;
818 return searchPositionIK(ik_pose, ik_seed_state, timeout, consistency_limits,
819 solution, solution_callback, error_code, options);
823 const geometry_msgs::Pose &ik_pose,
824 const std::vector<double> &ik_seed_state,
double timeout,
825 const std::vector<double> &consistency_limits,
826 std::vector<double> &solution, moveit_msgs::MoveItErrorCodes &error_code,
829 return searchPositionIK(ik_pose, ik_seed_state, timeout, consistency_limits,
830 solution, solution_callback, error_code, options);
834 const geometry_msgs::Pose &ik_pose,
835 const std::vector<double> &ik_seed_state,
double timeout,
836 std::vector<double> &solution,
const IKCallbackFn &solution_callback,
837 moveit_msgs::MoveItErrorCodes &error_code,
839 std::vector<double> consistency_limits;
840 return searchPositionIK(ik_pose, ik_seed_state, timeout, consistency_limits,
841 solution, solution_callback, error_code, options);
845 const geometry_msgs::Pose &ik_pose,
846 const std::vector<double> &ik_seed_state,
double timeout,
847 const std::vector<double> &consistency_limits,
848 std::vector<double> &solution,
const IKCallbackFn &solution_callback,
849 moveit_msgs::MoveItErrorCodes &error_code,
857 if (free_params_.size() == 0) {
859 "ikfast",
"No need to search since no free params/redundant joints");
862 if (!
getPositionIK(ik_pose, ik_seed_state, solution, error_code)) {
864 error_code.val = moveit_msgs::MoveItErrorCodes::NO_IK_SOLUTION;
869 if (!solution_callback.empty()) {
870 solution_callback(ik_pose, solution, error_code);
871 if (error_code.val == moveit_msgs::MoveItErrorCodes::SUCCESS) {
888 error_code.val = error_code.NO_IK_SOLUTION;
894 << num_joints_ <<
" instead of size " 895 << ik_seed_state.size());
896 error_code.val = error_code.NO_IK_SOLUTION;
900 if (!consistency_limits.empty() && consistency_limits.size() !=
num_joints_) {
902 "Consistency limits be empty or must have size " 903 << num_joints_ <<
" instead of size " 904 << consistency_limits.size());
905 error_code.val = error_code.NO_IK_SOLUTION;
915 std::vector<double> vfree(free_params_.size());
920 double initial_guess = ik_seed_state[free_params_[0]];
921 vfree[0] = initial_guess;
925 int num_positive_increments;
926 int num_negative_increments;
928 if (!consistency_limits.empty()) {
932 fmin(joint_max_vector_[free_params_[0]],
933 initial_guess + consistency_limits[free_params_[0]]);
935 fmax(joint_min_vector_[free_params_[0]],
936 initial_guess - consistency_limits[free_params_[0]]);
938 num_positive_increments =
940 num_negative_increments =
944 num_positive_increments =
945 (joint_max_vector_[free_params_[0]] - initial_guess) /
947 num_negative_increments =
948 (initial_guess - joint_min_vector_[free_params_[0]]) /
956 "ikfast",
"Free param is " 957 << free_params_[0] <<
" initial guess is " << initial_guess
958 <<
", # positive increments: " << num_positive_increments
959 <<
", # negative increments: " << num_negative_increments);
961 (num_positive_increments + num_negative_increments) > 1000)
964 "Large search space, consider increasing the search discretization");
966 double best_costs = -1.0;
967 std::vector<double> best_solution;
968 int nattempts = 0, nvalid = 0;
972 int numsol =
solve(frame, vfree, solutions);
975 <<
" solutions from IKFast");
980 for (
int s = 0;
s < numsol; ++
s) {
982 std::vector<double> sol;
985 bool obeys_limits =
true;
986 for (
unsigned int i = 0; i < sol.size(); i++) {
987 if (joint_has_limits_vector_[i] && (sol[i] < joint_min_vector_[i] ||
988 sol[i] > joint_max_vector_[i])) {
989 obeys_limits =
false;
1002 if (!solution_callback.empty()) {
1003 solution_callback(ik_pose, solution, error_code);
1005 error_code.val = error_code.SUCCESS;
1008 if (error_code.val == error_code.SUCCESS) {
1010 if (search_mode & OPTIMIZE_MAX_JOINT) {
1013 for (
unsigned int i = 0; i < solution.size(); i++) {
1014 double d = fabs(ik_seed_state[i] - solution[i]);
1018 if (costs < best_costs || best_costs == -1.0) {
1020 best_solution = solution;
1030 if (!
getCount(counter, num_positive_increments, -num_negative_increments)) {
1032 error_code.val = moveit_msgs::MoveItErrorCodes::NO_IK_SOLUTION;
1044 if ((search_mode & OPTIMIZE_MAX_JOINT) && best_costs != -1.0) {
1045 solution = best_solution;
1046 error_code.val = error_code.SUCCESS;
1051 error_code.val = moveit_msgs::MoveItErrorCodes::NO_IK_SOLUTION;
1057 const geometry_msgs::Pose &ik_pose,
1058 const std::vector<double> &ik_seed_state, std::vector<double> &solution,
1059 moveit_msgs::MoveItErrorCodes &error_code,
1070 << ik_seed_state.size()
1071 <<
" entries, this ikfast solver requires " 1077 for (
unsigned int i = 0; i < ik_seed_state.size(); i++) {
1079 if (joint_has_limits_vector_[i] &&
1083 "ikseed",
"Not in limits! " 1084 << i <<
" value " << ik_seed_state[i]
1085 <<
" has limit: " << joint_has_limits_vector_[i]
1086 <<
" being " << joint_min_vector_[i] <<
" to " 1087 << joint_max_vector_[i]);
1092 std::vector<double> vfree(free_params_.size());
1093 for (std::size_t i = 0; i < free_params_.size(); ++i) {
1094 int p = free_params_[i];
1095 ROS_ERROR(
"%u is %f", p, ik_seed_state[p]);
1096 vfree[i] = ik_seed_state[p];
1103 int numsol =
solve(frame, vfree, solutions);
1104 std::vector<std::vector<double>> solutions_obey_limits;
1105 std::vector<double> dists;
1106 bool solution_found =
false;
1109 <<
" solutions from IKFast");
1112 std::vector<double> solution_obey_limits;
1113 for (
int s = 0;
s < numsol; ++
s) {
1114 std::vector<double> sol;
1117 sol[0], sol[1], sol[2], sol[3], sol[4], sol[5]);
1119 bool obeys_limits =
true;
1120 for (
unsigned int i = 0; i < sol.size(); i++) {
1122 if (joint_has_limits_vector_[i] &&
1126 obeys_limits =
false;
1128 "ikfast",
"Not in limits! " 1129 << i <<
" value " << sol[i]
1130 <<
" has limit: " << joint_has_limits_vector_[i]
1131 <<
" being " << joint_min_vector_[i] <<
" to " 1132 << joint_max_vector_[i]);
1138 solution_found =
true;
1141 for (
size_t i = 0; i < ik_seed_state.size(); ++i) {
1142 dist += fabs(ik_seed_state[i] - solution_obey_limits[i]);
1146 solutions_obey_limits.push_back(solution_obey_limits);
1147 dists.push_back(dist);
1156 if (solution_found) {
1157 bool swap_flag =
true;
1158 std::vector<double> temp_sol;
1160 for (std::size_t i = 0; i < solutions_obey_limits.size(); ++i) {
1162 for (std::size_t j = 0; j < solutions_obey_limits.size() - 1; ++j) {
1163 if (dists[j + 1] < dists[j]) {
1164 temp_sol = solutions_obey_limits[j];
1165 temp_dist = dists[j];
1166 solutions_obey_limits[j] = solutions_obey_limits[j + 1];
1167 solutions_obey_limits[j + 1] = temp_sol;
1168 dists[j] = dists[j + 1];
1169 dists[j + 1] = temp_dist;
1174 solution = solutions_obey_limits[0];
1175 error_code.val = moveit_msgs::MoveItErrorCodes::SUCCESS;
1179 error_code.val = moveit_msgs::MoveItErrorCodes::NO_IK_SOLUTION;
1184 const std::vector<geometry_msgs::Pose> &ik_poses,
1185 const std::vector<double> &ik_seed_state,
1186 std::vector<std::vector<double>> &solutions,
1197 if (ik_poses.empty()) {
1203 if (ik_poses.size() > 1) {
1204 ROS_ERROR(
"ik_poses contains multiple entries, only one is allowed");
1212 << ik_seed_state.size()
1213 <<
" entries, this ikfast solver requires " 1222 std::vector<IkSolutionList<IkReal>> solution_set;
1224 std::vector<double> vfree;
1226 std::vector<double> sampled_joint_vals;
1234 joint_has_limits_vector_[redundant_joint_indices_.front()]) {
1235 double joint_min = joint_min_vector_[redundant_joint_indices_.front()];
1236 double joint_max = joint_max_vector_[redundant_joint_indices_.front()];
1238 double jv = sampled_joint_vals[0];
1251 sampled_joint_vals)) {
1257 for (
unsigned int i = 0; i < sampled_joint_vals.size(); i++) {
1259 vfree.push_back(sampled_joint_vals[i]);
1260 numsol +=
solve(frame, vfree, ik_solutions);
1261 solution_set.push_back(ik_solutions);
1265 numsol =
solve(frame, vfree, ik_solutions);
1266 solution_set.push_back(ik_solutions);
1270 <<
" solutions from IKFast");
1271 bool solutions_found =
false;
1277 for (
unsigned int r = 0;
r < solution_set.size();
r++) {
1278 ik_solutions = solution_set[
r];
1280 for (
int s = 0;
s < numsol; ++
s) {
1281 std::vector<double> sol;
1284 bool obeys_limits =
true;
1285 for (
unsigned int i = 0; i < sol.size(); i++) {
1287 if (joint_has_limits_vector_[i] &&
1291 obeys_limits =
false;
1293 "ikfast",
"Not in limits! " 1294 << i <<
" value " << sol[i]
1295 <<
" has limit: " << joint_has_limits_vector_[i]
1296 <<
" being " << joint_min_vector_[i] <<
" to " 1297 << joint_max_vector_[i]);
1303 solutions_found =
true;
1304 solutions.push_back(sol);
1309 if (solutions_found) {
1323 std::vector<double> &sampled_joint_vals)
const {
1324 double joint_min = -
M_PI;
1325 double joint_max =
M_PI;
1330 joint_min = joint_min_vector_[index];
1331 joint_max = joint_max_vector_[index];
1336 int steps = std::ceil((joint_max - joint_min) / joint_dscrt);
1337 for (
unsigned int i = 0; i < steps; i++) {
1338 sampled_joint_vals.push_back(joint_min + joint_dscrt * i);
1340 sampled_joint_vals.push_back(joint_max);
1343 int steps = std::ceil((joint_max - joint_min) / joint_dscrt);
1344 steps = steps > 0 ? steps : 1;
1345 double diff = joint_max - joint_min;
1346 for (
int i = 0; i < steps; i++) {
1347 sampled_joint_vals.push_back(
1348 ((diff * std::rand()) / (static_cast<double>(RAND_MAX))) + joint_min);
1357 ROS_ERROR_STREAM(
"Discretization method " << method <<
" is not supported");
std::vector< unsigned int > redundant_joint_indices_
virtual const IkSolutionBase< T > & GetSolution(size_t index) const
returns the solution pointer
KinematicError kinematic_error
bool initialize(const std::string &robot_description, const std::string &group_name, const std::string &base_name, const std::string &tip_name, double search_discretization)
const std::vector< std::string > & getLinkNames() const
#define ROS_DEBUG_STREAM_NAMED(name, args)
#define ROS_ERROR_STREAM_NAMED(name, args)
URDF_EXPORT bool initString(const std::string &xmlstring)
#define ROS_WARN_NAMED(name,...)
bool getCount(int &count, const int &max_count, const int &min_count) const
virtual size_t GetNumSolutions() const
returns the number of solutions stored
the mask for the unique ids
void getClosestSolution(const IkSolutionList< IkReal > &solutions, const std::vector< double > &ik_seed_state, std::vector< double > &solution) const
void setSearchDiscretization(const std::map< int, double > &discretization)
Sets the discretization value for the redundant joint.
UNSUPORTED_DISCRETIZATION_REQUESTED
IMETHOD Vector diff(const Vector &p_w_a, const Vector &p_w_b, double dt=1)
IkParameterizationType
The types of inverse kinematics parameterizations supported.
std::vector< int > free_params_
The discrete solutions are returned in this structure.
bool sampleRedundantJoint(kinematics::DiscretizationMethod method, std::vector< double > &sampled_joint_vals) const
samples the designated redundant joint using the chosen discretization method
std::vector< std::string > link_names_
#define ROS_INFO_STREAM_NAMED(name, args)
2D translation along XY plane
virtual void Clear()
clears all current solutions, note that any memory addresses returned from GetSolution will be invali...
virtual const std::vector< int > & GetFree() const =0
Gets the indices of the configuration space that have to be preset before a full solution can be retu...
bool searchPositionIK(const geometry_msgs::Pose &ik_pose, const std::vector< double > &ik_seed_state, double timeout, std::vector< double > &solution, moveit_msgs::MoveItErrorCodes &error_code, const kinematics::KinematicsQueryOptions &options=kinematics::KinematicsQueryOptions()) const
Given a desired pose of the end-effector, search for the joint angles required to reach it...
IKFAST_API int GetNumFreeParameters()
void fillFreeParams(int count, int *array)
number of parameterizations (does not count IKP_None)
#define ROS_DEBUG_NAMED(name,...)
bool setRedundantJoints(const std::vector< unsigned int > &redundant_joint_indices)
Overrides the default method to prevent changing the redundant joints.
#define ROS_WARN_STREAM_ONCE_NAMED(name, args)
end effector reaches desired 6D transformation
virtual const std::string & getTipFrame() const
end effector reaches desired 3D rotation
#define ROS_FATAL_STREAM_NAMED(name, args)
IKFAST_API bool ComputeIk(const IkReal *eetrans, const IkReal *eerot, const IkReal *pfree, IkSolutionListBase< IkReal > &solutions)
PLUGINLIB_EXPORT_CLASS(ikfast_kinematics_plugin::IKFastKinematicsPlugin, kinematics::KinematicsBase)
std::vector< bool > joint_has_limits_vector_
void poseMsgToKDL(const geometry_msgs::Pose &m, KDL::Frame &k)
IKFAST_API int * GetFreeParameters()
DiscretizationMethod discretization_method
std::vector< DiscretizationMethod > supported_methods_
double harmonize(const std::vector< double > &ik_seed_state, std::vector< double > &solution) const
virtual void setValues(const std::string &robot_description, const std::string &group_name, const std::string &base_frame, const std::string &tip_frame, double search_discretization)
def xml_string(rootXml, addHeader=True)
boost::function< void(const geometry_msgs::Pose &ik_pose, const std::vector< double > &ik_solution, moveit_msgs::MoveItErrorCodes &error_code)> IKCallbackFn
std::map< int, double > redundant_joint_discretization_
virtual void GetSolution(T *solution, const T *freevalues) const =0
gets a concrete solution
static const double DEFAULT_SEARCH_DISCRETIZATION
const std::vector< std::string > & getJointNames() const
void poseKDLToMsg(const KDL::Frame &k, geometry_msgs::Pose &m)
Default implementation of IkSolutionListBase.
double search_discretization_
#define ROS_FATAL_NAMED(name,...)
#define ROS_ERROR_NAMED(name,...)
IKFAST_API int GetIkType()
SEARCH_MODE
Search modes for searchPositionIK(), see there.
MULTIPLE_TIPS_NOT_SUPPORTED
IKFAST_API int GetNumJoints()
#define ROS_ERROR_STREAM(args)
bool getPositionIK(const geometry_msgs::Pose &ik_pose, const std::vector< double > &ik_seed_state, std::vector< double > &solution, moveit_msgs::MoveItErrorCodes &error_code, const kinematics::KinematicsQueryOptions &options=kinematics::KinematicsQueryOptions()) const
Given a desired pose of the end-effector, compute the joint angles to reach it.
int solve(KDL::Frame &pose_frame, const std::vector< double > &vfree, IkSolutionList< IkReal > &solutions) const
Calls the IK solver from IKFast.
const double LIMIT_TOLERANCE
end effector origin reaches desired 3D translation
std::vector< double > joint_min_vector_
std::vector< std::string > joint_names_
IKFAST_API void ComputeFk(const IkReal *j, IkReal *eetrans, IkReal *eerot)
bool getPositionFK(const std::vector< std::string > &link_names, const std::vector< double > &joint_angles, std::vector< geometry_msgs::Pose > &poses) const
Given a set of joint angles and a set of links, compute their pose.
std::vector< double > joint_max_vector_
void getSolution(const IkSolutionList< IkReal > &solutions, int i, std::vector< double > &solution) const
Gets a specific solution from the set.
#define ROS_WARN_STREAM_NAMED(name, args)