motoman_mh5_manipulator_ikfast_moveit_plugin.cpp
Go to the documentation of this file.
1 /*********************************************************************
2  *
3  * Software License Agreement (BSD License)
4  *
5  * Copyright (c) 2013, Dave Coleman, CU Boulder; Jeremy Zoss, SwRI; David
6  *Butterworth, KAIST; Mathias Lüdtke, Fraunhofer
7  *IPA
8  * All rights reserved.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  *
14  * * Redistributions of source code must retain the above copyright
15  * notice, this list of conditions and the following disclaimer.
16  * * Redistributions in binary form must reproduce the above copyright
17  * notice, this list of conditions and the following disclaimer in the
18  * documentation and/or other materials provided with the distribution.
19  * * Neither the name of the all of the author's companies nor the names of
20  *its
21  * contributors may be used to endorse or promote products derived from
22  * this software without specific prior written permission.
23  *
24  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
25  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
28  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
30  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
32  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34  * POSSIBILITY OF SUCH DAMAGE.
35  *
36  *********************************************************************/
37 
38 /*
39  * IKFast Plugin Template for moveit
40  *
41  * AUTO-GENERATED by create_ikfast_moveit_plugin.py in arm_kinematics_tools
42  * You should run create_ikfast_moveit_plugin.py to generate your own plugin.
43  *
44  * Creates a kinematics plugin using the output of IKFast from OpenRAVE.
45  * This plugin and the move_group node can be used as a general
46  * kinematics service, from within the moveit planning environment, or in
47  * your own ROS node.
48  *
49  */
50 
52 #include <ros/ros.h>
53 #include <tf_conversions/tf_kdl.h>
54 #include <urdf/model.h>
55 
56 // Need a floating point tolerance when checking joint limits, in case the joint
57 // starts at limit
58 const double LIMIT_TOLERANCE = .0000001;
61 
63 #define IKFAST_NO_MAIN // Don't include main() from IKFast
64 
73  IKP_None = 0,
75  0x67000001,
76  IKP_Rotation3D = 0x34000002,
78  0x33000003,
79  IKP_Direction3D = 0x23000004,
80  IKP_Ray4D = 0x46000005,
82  IKP_Lookat3D = 0x23000006,
84  IKP_TranslationDirection5D = 0x56000007,
86  IKP_TranslationXY2D = 0x22000008,
92  IKP_TranslationLocalGlobal6D = 0x3600000a,
97 
101  IKP_TranslationYAxisAngle4D = 0x4400000c,
106  IKP_TranslationZAxisAngle4D = 0x4400000d,
123  IKP_TranslationZAxisAngleYNorm4D = 0x44000010,
129 
136  16,
137 
138  IKP_VelocityDataBit = 0x00008000,
166 
167  IKP_UniqueIdMask = 0x0000ffff,
168  IKP_CustomDataBit = 0x00010000,
169 };
172 
173 // Code generated by IKFast56/61
177  std::vector<std::string> joint_names_;
178  std::vector<double> joint_min_vector_;
179  std::vector<double> joint_max_vector_;
180  std::vector<bool> joint_has_limits_vector_;
181  std::vector<std::string> link_names_;
182  size_t num_joints_;
183  std::vector<int> free_params_;
184  bool active_; // Internal variable that indicates whether solvers are
185  // configured and ready
186 
187  const std::vector<std::string> &getJointNames() const { return joint_names_; }
188  const std::vector<std::string> &getLinkNames() const { return link_names_; }
189 
190 public:
194  IKFastKinematicsPlugin() : active_(false) {
195  srand(time(NULL));
196  supported_methods_.push_back(
198  supported_methods_.push_back(
200  supported_methods_.push_back(
202  }
203 
215  // Returns the IK solution that is within joint limits closest to
216  // ik_seed_state
217  bool getPositionIK(const geometry_msgs::Pose &ik_pose,
218  const std::vector<double> &ik_seed_state,
219  std::vector<double> &solution,
220  moveit_msgs::MoveItErrorCodes &error_code,
223 
244  bool getPositionIK(const std::vector<geometry_msgs::Pose> &ik_poses,
245  const std::vector<double> &ik_seed_state,
246  std::vector<std::vector<double>> &solutions,
248  const kinematics::KinematicsQueryOptions &options) const;
260  bool searchPositionIK(const geometry_msgs::Pose &ik_pose,
261  const std::vector<double> &ik_seed_state,
262  double timeout, std::vector<double> &solution,
263  moveit_msgs::MoveItErrorCodes &error_code,
264  const kinematics::KinematicsQueryOptions &options =
266 
278  bool searchPositionIK(const geometry_msgs::Pose &ik_pose,
279  const std::vector<double> &ik_seed_state,
280  double timeout,
281  const std::vector<double> &consistency_limits,
282  std::vector<double> &solution,
283  moveit_msgs::MoveItErrorCodes &error_code,
284  const kinematics::KinematicsQueryOptions &options =
286 
297  bool searchPositionIK(const geometry_msgs::Pose &ik_pose,
298  const std::vector<double> &ik_seed_state,
299  double timeout, std::vector<double> &solution,
300  const IKCallbackFn &solution_callback,
301  moveit_msgs::MoveItErrorCodes &error_code,
302  const kinematics::KinematicsQueryOptions &options =
304 
320  bool searchPositionIK(const geometry_msgs::Pose &ik_pose,
321  const std::vector<double> &ik_seed_state,
322  double timeout,
323  const std::vector<double> &consistency_limits,
324  std::vector<double> &solution,
325  const IKCallbackFn &solution_callback,
326  moveit_msgs::MoveItErrorCodes &error_code,
327  const kinematics::KinematicsQueryOptions &options =
329 
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;
342 
354  void setSearchDiscretization(const std::map<int, double> &discretization);
355 
360  bool
361  setRedundantJoints(const std::vector<unsigned int> &redundant_joint_indices);
362 
363 private:
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);
367 
372  int solve(KDL::Frame &pose_frame, const std::vector<double> &vfree,
373  IkSolutionList<IkReal> &solutions) const;
374 
378  void getSolution(const IkSolutionList<IkReal> &solutions, int i,
379  std::vector<double> &solution) const;
380 
381  double harmonize(const std::vector<double> &ik_seed_state,
382  std::vector<double> &solution) const;
383  // void getOrderedSolutions(const std::vector<double> &ik_seed_state,
384  // std::vector<std::vector<double> >& solslist);
385  void getClosestSolution(const IkSolutionList<IkReal> &solutions,
386  const std::vector<double> &ik_seed_state,
387  std::vector<double> &solution) const;
388  void fillFreeParams(int count, int *array);
389  bool getCount(int &count, const int &max_count, const int &min_count) const;
390 
400  std::vector<double> &sampled_joint_vals) const;
401 
402 }; // end class
403 
404 bool IKFastKinematicsPlugin::initialize(const std::string &robot_description,
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);
411 
412  ros::NodeHandle node_handle("~/" + group_name);
413 
414  std::string robot;
415  node_handle.param("robot", robot, std::string());
417  // IKFast56/61
419  num_joints_ = GetNumJoints();
420 
421  if (free_params_.size() > 1) {
422  ROS_FATAL("Only one free joint parameter supported!");
423  return false;
424  } else if (free_params_.size() == 1) {
426  redundant_joint_indices_.push_back(free_params_[0]);
427  KinematicsBase::setSearchDiscretization(DEFAULT_SEARCH_DISCRETIZATION);
428  }
429 
430  urdf::Model robot_model;
431  std::string xml_string;
432 
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);
436 
437  ROS_DEBUG_NAMED("ikfast", "Reading xml file from parameter server");
438  if (!node_handle.getParam(full_urdf_xml, xml_string)) {
439  ROS_FATAL_NAMED("ikfast",
440  "Could not load the xml from parameter server: %s",
441  urdf_xml.c_str());
442  return false;
443  }
444 
445  node_handle.param(full_urdf_xml, xml_string, std::string());
446  robot_model.initString(xml_string);
447 
448  ROS_DEBUG_STREAM_NAMED("ikfast", "Reading joints and links from URDF");
449 
450  urdf::LinkConstSharedPtr link = robot_model.getLink(getTipFrame());
451  while (link->name != base_frame_ && joint_names_.size() <= num_joints_) {
452  ROS_DEBUG_NAMED("ikfast", "Link %s", link->name.c_str());
453  link_names_.push_back(link->name);
454  urdf::JointSharedPtr joint = link->parent_joint;
455  if (joint) {
456  if (joint->type != urdf::Joint::UNKNOWN &&
457  joint->type != urdf::Joint::FIXED) {
458  ROS_DEBUG_STREAM_NAMED("ikfast", "Adding joint " << joint->name);
459 
460  joint_names_.push_back(joint->name);
461  float lower, upper;
462  int hasLimits;
463  if (joint->type != urdf::Joint::CONTINUOUS) {
464  if (joint->safety) {
465  lower = joint->safety->soft_lower_limit;
466  upper = joint->safety->soft_upper_limit;
467  } else {
468  lower = joint->limits->lower;
469  upper = joint->limits->upper;
470  }
471  hasLimits = 1;
472  } else {
473  lower = -M_PI;
474  upper = M_PI;
475  hasLimits = 0;
476  }
477  if (hasLimits) {
478  joint_has_limits_vector_.push_back(true);
479  joint_min_vector_.push_back(lower);
480  joint_max_vector_.push_back(upper);
481  } else {
482  joint_has_limits_vector_.push_back(false);
483  joint_min_vector_.push_back(-M_PI);
484  joint_max_vector_.push_back(M_PI);
485  }
486  }
487  } else {
488  ROS_WARN_NAMED("ikfast", "no joint corresponding to %s",
489  link->name.c_str());
490  }
491  link = link->getParent();
492  }
493 
494  if (joint_names_.size() != num_joints_) {
495  ROS_FATAL_STREAM_NAMED("ikfast", "Joint numbers mismatch: URDF has "
496  << joint_names_.size()
497  << " and IKFast has " << num_joints_);
498  return false;
499  }
500 
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());
507 
508  for (size_t i = 0; i < num_joints_; ++i)
509  ROS_DEBUG_STREAM_NAMED("ikfast", joint_names_[i]
510  << " " << joint_min_vector_[i] << " "
511  << joint_max_vector_[i] << " "
512  << joint_has_limits_vector_[i]);
513 
514  active_ = true;
515  return true;
516 }
517 
519  const std::map<int, double> &discretization) {
520  if (discretization.empty()) {
521  ROS_ERROR("The 'discretization' map is empty");
522  return;
523  }
524 
525  if (redundant_joint_indices_.empty()) {
526  ROS_ERROR_STREAM("This group's solver doesn't support redundant joints");
527  return;
528  }
529 
530  if (discretization.begin()->first != redundant_joint_indices_[0]) {
531  std::string redundant_joint = joint_names_[free_params_[0]];
532  ROS_ERROR_STREAM("Attempted to discretize a non-redundant joint "
533  << discretization.begin()->first << ", only joint '"
534  << redundant_joint << "' with index "
535  << redundant_joint_indices_[0] << " is redundant.");
536  return;
537  }
538 
539  if (discretization.begin()->second <= 0.0) {
540  ROS_ERROR_STREAM("Discretization can not takes values that are <= 0");
541  return;
542  }
543 
546  discretization.begin()->second;
547 }
548 
550  const std::vector<unsigned int> &redundant_joint_indices) {
552  "Changing the redundant joints isn't permitted by this group's solver ");
553  return false;
554 }
555 
557  const std::vector<double> &vfree,
558  IkSolutionList<IkReal> &solutions) const {
559  // IKFast56/61
560  solutions.Clear();
561 
562  double trans[3];
563  trans[0] = pose_frame.p[0]; //-.18;
564  trans[1] = pose_frame.p[1];
565  trans[2] = pose_frame.p[2];
566 
567  KDL::Rotation mult;
568  KDL::Vector direction;
569 
570  switch (GetIkType()) {
571  case IKP_Transform6D:
572  case IKP_Translation3D:
573  // For **Transform6D**, eerot is 9 values for the 3x3 rotation matrix. For
574  // **Translation3D**, these are ignored.
575 
576  mult = pose_frame.M;
577 
578  double vals[9];
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);
588 
589  // IKFast56/61
590  ComputeIk(trans, vals, vfree.size() > 0 ? &vfree[0] : NULL, solutions);
591  return solutions.GetNumSolutions();
592 
593  case IKP_Direction3D:
594  case IKP_Ray4D:
596  // For **Direction3D**, **Ray4D**, and **TranslationDirection5D**, the first
597  // 3 values represent the target
598  // direction.
599 
600  direction = pose_frame.M * KDL::Vector(0, 0, 1);
601  ComputeIk(trans, direction.data, vfree.size() > 0 ? &vfree[0] : NULL,
602  solutions);
603  return solutions.GetNumSolutions();
604 
608  // For **TranslationXAxisAngle4D**, **TranslationYAxisAngle4D**, and
609  // **TranslationZAxisAngle4D**, the first value
610  // represents the angle.
611  ROS_ERROR_NAMED("ikfast",
612  "IK for this IkParameterizationType not implemented yet.");
613  return 0;
614 
616  // For **TranslationLocalGlobal6D**, the diagonal elements ([0],[4],[8]) are
617  // the local translation inside the end
618  // effector coordinate system.
619  ROS_ERROR_NAMED("ikfast",
620  "IK for this IkParameterizationType not implemented yet.");
621  return 0;
622 
623  case IKP_Rotation3D:
624  case IKP_Lookat3D:
625  case IKP_TranslationXY2D:
630  ROS_ERROR_NAMED("ikfast",
631  "IK for this IkParameterizationType not implemented yet.");
632  return 0;
633 
634  default:
635  ROS_ERROR_NAMED("ikfast", "Unknown IkParameterizationType! Was the solver "
636  "generated with an incompatible version "
637  "of Openrave?");
638  return 0;
639  }
640 }
641 
643  const IkSolutionList<IkReal> &solutions, int i,
644  std::vector<double> &solution) const {
645  solution.clear();
646  solution.resize(num_joints_);
647 
648  // IKFast56/61
649  const IkSolutionBase<IkReal> &sol = solutions.GetSolution(i);
650  std::vector<IkReal> vsolfree(sol.GetFree().size());
651  sol.GetSolution(&solution[0], vsolfree.size() > 0 ? &vsolfree[0] : NULL);
652 
653  // std::cout << "solution " << i << ":" ;
654  // for(int j=0;j<num_joints_; ++j)
655  // std::cout << " " << solution[j];
656  // std::cout << std::endl;
657 
658  // ROS_ERROR("%f %d",solution[2],vsolfree.size());
659 }
660 
661 double
662 IKFastKinematicsPlugin::harmonize(const std::vector<double> &ik_seed_state,
663  std::vector<double> &solution) const {
664  double dist_sqr = 0;
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) {
668  ss[i] -= 2 * M_PI;
669  }
670  while (ss[i] < 2 * M_PI) {
671  ss[i] += 2 * M_PI;
672  }
673  while (solution[i] > 2 * M_PI) {
674  solution[i] -= 2 * M_PI;
675  }
676  while (solution[i] < 2 * M_PI) {
677  solution[i] += 2 * M_PI;
678  }
679  dist_sqr += fabs(ik_seed_state[i] - solution[i]);
680  }
681  return dist_sqr;
682 }
683 
684 // void IKFastKinematicsPlugin::getOrderedSolutions(const std::vector<double>
685 // &ik_seed_state,
686 // std::vector<std::vector<double> >& solslist)
687 // {
688 // std::vector<double>
689 // double mindist = 0;
690 // int minindex = -1;
691 // std::vector<double> sol;
692 // for(size_t i=0;i<solslist.size();++i){
693 // getSolution(i,sol);
694 // double dist = harmonize(ik_seed_state, sol);
695 // //std::cout << "dist[" << i << "]= " << dist << std::endl;
696 // if(minindex == -1 || dist<mindist){
697 // minindex = i;
698 // mindist = dist;
699 // }
700 // }
701 // if(minindex >= 0){
702 // getSolution(minindex,solution);
703 // harmonize(ik_seed_state, solution);
704 // index = minindex;
705 // }
706 // }
707 
709  const IkSolutionList<IkReal> &solutions,
710  const std::vector<double> &ik_seed_state,
711  std::vector<double> &solution) const {
712  double mindist = DBL_MAX;
713  int minindex = -1;
714  std::vector<double> sol;
715 
716  // IKFast56/61
717  for (size_t i = 0; i < solutions.GetNumSolutions(); ++i) {
718  getSolution(solutions, i, sol);
719  double dist = harmonize(ik_seed_state, sol);
720  ROS_INFO_STREAM_NAMED("ikfast", "Dist " << i << " dist " << dist);
721  // std::cout << "dist[" << i << "]= " << dist << std::endl;
722  if (minindex == -1 || dist < mindist) {
723  minindex = i;
724  mindist = dist;
725  }
726  }
727  if (minindex >= 0) {
728  getSolution(solutions, minindex, solution);
729  harmonize(ik_seed_state, solution);
730  }
731 }
732 
733 void IKFastKinematicsPlugin::fillFreeParams(int count, int *array) {
734  free_params_.clear();
735  for (int i = 0; i < count; ++i)
736  free_params_.push_back(array[i]);
737 }
738 
739 bool IKFastKinematicsPlugin::getCount(int &count, const int &max_count,
740  const int &min_count) const {
741  if (count > 0) {
742  if (-count >= min_count) {
743  count = -count;
744  return true;
745  } else if (count + 1 <= max_count) {
746  count = count + 1;
747  return true;
748  } else {
749  return false;
750  }
751  } else {
752  if (1 - count <= max_count) {
753  count = 1 - count;
754  return true;
755  } else if (count - 1 >= min_count) {
756  count = count - 1;
757  return true;
758  } else
759  return false;
760  }
761 }
762 
764  const std::vector<std::string> &link_names,
765  const std::vector<double> &joint_angles,
766  std::vector<geometry_msgs::Pose> &poses) const {
767  if (GetIkType() != IKP_Transform6D) {
768  // ComputeFk() is the inverse function of ComputeIk(), so the format of
769  // eerot differs depending on IK type. The Transform6D IK type is the only
770  // one for which a 3x3 rotation matrix is returned, which means we can only
771  // compute FK for that IK type.
772  ROS_ERROR_NAMED("ikfast", "Can only compute FK for Transform6D IK type!");
773  return false;
774  }
775 
776  KDL::Frame p_out;
777  if (link_names.size() == 0) {
778  ROS_WARN_STREAM_NAMED("ikfast", "Link names with nothing");
779  return false;
780  }
781 
782  if (link_names.size() != 1 || link_names[0] != getTipFrame()) {
783  ROS_ERROR_NAMED("ikfast", "Can compute FK for %s only",
784  getTipFrame().c_str());
785  return false;
786  }
787 
788  bool valid = true;
789 
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];
794 
795  // IKFast56/61
796  ComputeFk(angles, eetrans, eerot);
797 
798  for (int i = 0; i < 3; ++i)
799  p_out.p.data[i] = eetrans[i];
800 
801  for (int i = 0; i < 9; ++i)
802  p_out.M.data[i] = eerot[i];
803 
804  poses.resize(1);
805  tf::poseKDLToMsg(p_out, poses[0]);
806 
807  return valid;
808 }
809 
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,
814  const kinematics::KinematicsQueryOptions &options) const {
815  const IKCallbackFn solution_callback = 0;
816  std::vector<double> consistency_limits;
817 
818  return searchPositionIK(ik_pose, ik_seed_state, timeout, consistency_limits,
819  solution, solution_callback, error_code, options);
820 }
821 
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,
827  const kinematics::KinematicsQueryOptions &options) const {
828  const IKCallbackFn solution_callback = 0;
829  return searchPositionIK(ik_pose, ik_seed_state, timeout, consistency_limits,
830  solution, solution_callback, error_code, options);
831 }
832 
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,
838  const kinematics::KinematicsQueryOptions &options) const {
839  std::vector<double> consistency_limits;
840  return searchPositionIK(ik_pose, ik_seed_state, timeout, consistency_limits,
841  solution, solution_callback, error_code, options);
842 }
843 
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,
850  const kinematics::KinematicsQueryOptions &options) const {
851  ROS_DEBUG_STREAM_NAMED("ikfast", "searchPositionIK");
852 
854  SEARCH_MODE search_mode = OPTIMIZE_MAX_JOINT;
855 
856  // Check if there are no redundant joints
857  if (free_params_.size() == 0) {
859  "ikfast", "No need to search since no free params/redundant joints");
860 
861  // Find first IK solution, within joint limits
862  if (!getPositionIK(ik_pose, ik_seed_state, solution, error_code)) {
863  ROS_DEBUG_STREAM_NAMED("ikfast", "No solution whatsoever");
864  error_code.val = moveit_msgs::MoveItErrorCodes::NO_IK_SOLUTION;
865  return false;
866  }
867 
868  // check for collisions if a callback is provided
869  if (!solution_callback.empty()) {
870  solution_callback(ik_pose, solution, error_code);
871  if (error_code.val == moveit_msgs::MoveItErrorCodes::SUCCESS) {
872  ROS_DEBUG_STREAM_NAMED("ikfast", "Solution passes callback");
873  return true;
874  } else {
875  ROS_DEBUG_STREAM_NAMED("ikfast", "Solution has error code "
876  << error_code);
877  return false;
878  }
879  } else {
880  return true; // no collision check callback provided
881  }
882  }
883 
884  // -------------------------------------------------------------------------------------------------
885  // Error Checking
886  if (!active_) {
887  ROS_ERROR_STREAM_NAMED("ikfast", "Kinematics not active");
888  error_code.val = error_code.NO_IK_SOLUTION;
889  return false;
890  }
891 
892  if (ik_seed_state.size() != num_joints_) {
893  ROS_ERROR_STREAM_NAMED("ikfast", "Seed state must have size "
894  << num_joints_ << " instead of size "
895  << ik_seed_state.size());
896  error_code.val = error_code.NO_IK_SOLUTION;
897  return false;
898  }
899 
900  if (!consistency_limits.empty() && consistency_limits.size() != num_joints_) {
901  ROS_ERROR_STREAM_NAMED("ikfast",
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;
906  return false;
907  }
908 
909  // -------------------------------------------------------------------------------------------------
910  // Initialize
911 
912  KDL::Frame frame;
913  tf::poseMsgToKDL(ik_pose, frame);
914 
915  std::vector<double> vfree(free_params_.size());
916 
917  ros::Time maxTime = ros::Time::now() + ros::Duration(timeout);
918  int counter = 0;
919 
920  double initial_guess = ik_seed_state[free_params_[0]];
921  vfree[0] = initial_guess;
922 
923  // -------------------------------------------------------------------------------------------------
924  // Handle consitency limits if needed
925  int num_positive_increments;
926  int num_negative_increments;
927 
928  if (!consistency_limits.empty()) {
929  // moveit replaced consistency_limit (scalar) w/ consistency_limits (vector)
930  // Assume [0]th free_params element for now. Probably wrong.
931  double max_limit =
932  fmin(joint_max_vector_[free_params_[0]],
933  initial_guess + consistency_limits[free_params_[0]]);
934  double min_limit =
935  fmax(joint_min_vector_[free_params_[0]],
936  initial_guess - consistency_limits[free_params_[0]]);
937 
938  num_positive_increments =
939  (int)((max_limit - initial_guess) / search_discretization_);
940  num_negative_increments =
941  (int)((initial_guess - min_limit) / search_discretization_);
942  } else // no consitency limits provided
943  {
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]]) /
950  }
951 
952  // -------------------------------------------------------------------------------------------------
953  // Begin searching
954 
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);
960  if ((search_mode & OPTIMIZE_MAX_JOINT) &&
961  (num_positive_increments + num_negative_increments) > 1000)
963  "ikfast",
964  "Large search space, consider increasing the search discretization");
965 
966  double best_costs = -1.0;
967  std::vector<double> best_solution;
968  int nattempts = 0, nvalid = 0;
969 
970  while (true) {
971  IkSolutionList<IkReal> solutions;
972  int numsol = solve(frame, vfree, solutions);
973 
974  ROS_DEBUG_STREAM_NAMED("ikfast", "Found " << numsol
975  << " solutions from IKFast");
976 
977  // ROS_INFO("%f",vfree[0]);
978 
979  if (numsol > 0) {
980  for (int s = 0; s < numsol; ++s) {
981  nattempts++;
982  std::vector<double> sol;
983  getSolution(solutions, s, sol);
984 
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;
990  break;
991  }
992  // ROS_INFO_STREAM_NAMED("ikfast","Num " << i << " value " << sol[i]
993  // << " has limits " <<
994  // joint_has_limits_vector_[i] << " " << joint_min_vector_[i] << " "
995  // << joint_max_vector_[i]);
996  }
997  if (obeys_limits) {
998  getSolution(solutions, s, solution);
999 
1000  // This solution is within joint limits, now check if in collision (if
1001  // callback provided)
1002  if (!solution_callback.empty()) {
1003  solution_callback(ik_pose, solution, error_code);
1004  } else {
1005  error_code.val = error_code.SUCCESS;
1006  }
1007 
1008  if (error_code.val == error_code.SUCCESS) {
1009  nvalid++;
1010  if (search_mode & OPTIMIZE_MAX_JOINT) {
1011  // Costs for solution: Largest joint motion
1012  double costs = 0.0;
1013  for (unsigned int i = 0; i < solution.size(); i++) {
1014  double d = fabs(ik_seed_state[i] - solution[i]);
1015  if (d > costs)
1016  costs = d;
1017  }
1018  if (costs < best_costs || best_costs == -1.0) {
1019  best_costs = costs;
1020  best_solution = solution;
1021  }
1022  } else
1023  // Return first feasible solution
1024  return true;
1025  }
1026  }
1027  }
1028  }
1029 
1030  if (!getCount(counter, num_positive_increments, -num_negative_increments)) {
1031  // Everything searched
1032  error_code.val = moveit_msgs::MoveItErrorCodes::NO_IK_SOLUTION;
1033  break;
1034  }
1035 
1036  vfree[0] = initial_guess + search_discretization_ * counter;
1037  // ROS_DEBUG_STREAM_NAMED("ikfast","Attempt " << counter << " with 0th free
1038  // joint having value " << vfree[0]);
1039  }
1040 
1041  ROS_DEBUG_STREAM_NAMED("ikfast", "Valid solutions: " << nvalid << "/"
1042  << nattempts);
1043 
1044  if ((search_mode & OPTIMIZE_MAX_JOINT) && best_costs != -1.0) {
1045  solution = best_solution;
1046  error_code.val = error_code.SUCCESS;
1047  return true;
1048  }
1049 
1050  // No solution found
1051  error_code.val = moveit_msgs::MoveItErrorCodes::NO_IK_SOLUTION;
1052  return false;
1053 }
1054 
1055 // Used when there are no redundant joints - aka no free params
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,
1060  const kinematics::KinematicsQueryOptions &options) const {
1061  ROS_DEBUG_STREAM_NAMED("ikfast", "getPositionIK");
1062 
1063  if (!active_) {
1064  ROS_ERROR("kinematics not active");
1065  return false;
1066  }
1067 
1068  if (ik_seed_state.size() < num_joints_) {
1069  ROS_ERROR_STREAM("ik_seed_state only has "
1070  << ik_seed_state.size()
1071  << " entries, this ikfast solver requires "
1072  << num_joints_);
1073  return false;
1074  }
1075 
1076  // Check if seed is in bound
1077  for (unsigned int i = 0; i < ik_seed_state.size(); i++) {
1078  // Add tolerance to limit check
1079  if (joint_has_limits_vector_[i] &&
1080  ((ik_seed_state[i] < (joint_min_vector_[i] - LIMIT_TOLERANCE)) ||
1081  (ik_seed_state[i] > (joint_max_vector_[i] + LIMIT_TOLERANCE)))) {
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]);
1088  return false;
1089  }
1090  }
1091 
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]); // DTC
1096  vfree[i] = ik_seed_state[p];
1097  }
1098 
1099  KDL::Frame frame;
1100  tf::poseMsgToKDL(ik_pose, frame);
1101 
1102  IkSolutionList<IkReal> solutions;
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;
1108  ROS_DEBUG_STREAM_NAMED("ikfast", "Found " << numsol
1109  << " solutions from IKFast");
1110 
1111  if (numsol) {
1112  std::vector<double> solution_obey_limits;
1113  for (int s = 0; s < numsol; ++s) {
1114  std::vector<double> sol;
1115  getSolution(solutions, s, sol);
1116  ROS_DEBUG_NAMED("ikfast", "Sol %d: %e %e %e %e %e %e", s,
1117  sol[0], sol[1], sol[2], sol[3], sol[4], sol[5]);
1118 
1119  bool obeys_limits = true;
1120  for (unsigned int i = 0; i < sol.size(); i++) {
1121  // Add tolerance to limit check
1122  if (joint_has_limits_vector_[i] &&
1123  ((sol[i] < (joint_min_vector_[i] - LIMIT_TOLERANCE)) ||
1124  (sol[i] > (joint_max_vector_[i] + LIMIT_TOLERANCE)))) {
1125  // One element of solution is not within limits
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]);
1133  break;
1134  }
1135  }
1136  if (obeys_limits) {
1137  // All elements of this solution obey limits
1138  solution_found = true;
1139  getSolution(solutions, s, solution_obey_limits);
1140  double dist = 0;
1141  for (size_t i = 0; i < ik_seed_state.size(); ++i) {
1142  dist += fabs(ik_seed_state[i] - solution_obey_limits[i]);
1143  }
1144 
1145  ROS_DEBUG_STREAM_NAMED("ikfast", "Dist " << s << " dist " << dist);
1146  solutions_obey_limits.push_back(solution_obey_limits);
1147  dists.push_back(dist);
1148  }
1149  }
1150  } else {
1151  ROS_DEBUG_STREAM_NAMED("ikfast", "No IK solution");
1152  }
1153 
1154  // Sort the solutions under limits and find the one that is closest to
1155  // ik_seed_state
1156  if (solution_found) {
1157  bool swap_flag = true;
1158  std::vector<double> temp_sol;
1159  double temp_dist;
1160  for (std::size_t i = 0; i < solutions_obey_limits.size(); ++i) {
1161  swap_flag = false;
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;
1170  swap_flag = true;
1171  }
1172  }
1173  }
1174  solution = solutions_obey_limits[0];
1175  error_code.val = moveit_msgs::MoveItErrorCodes::SUCCESS;
1176  return true;
1177  }
1178 
1179  error_code.val = moveit_msgs::MoveItErrorCodes::NO_IK_SOLUTION;
1180  return false;
1181 }
1182 
1184  const std::vector<geometry_msgs::Pose> &ik_poses,
1185  const std::vector<double> &ik_seed_state,
1186  std::vector<std::vector<double>> &solutions,
1188  const kinematics::KinematicsQueryOptions &options) const {
1189  ROS_DEBUG_STREAM_NAMED("ikfast", "getPositionIK with multiple solutions");
1190 
1191  if (!active_) {
1192  ROS_ERROR("kinematics not active");
1194  return false;
1195  }
1196 
1197  if (ik_poses.empty()) {
1198  ROS_ERROR("ik_poses is empty");
1200  return false;
1201  }
1202 
1203  if (ik_poses.size() > 1) {
1204  ROS_ERROR("ik_poses contains multiple entries, only one is allowed");
1205  result.kinematic_error =
1207  return false;
1208  }
1209 
1210  if (ik_seed_state.size() < num_joints_) {
1211  ROS_ERROR_STREAM("ik_seed_state only has "
1212  << ik_seed_state.size()
1213  << " entries, this ikfast solver requires "
1214  << num_joints_);
1215  return false;
1216  }
1217 
1218  KDL::Frame frame;
1219  tf::poseMsgToKDL(ik_poses[0], frame);
1220 
1221  // solving ik
1222  std::vector<IkSolutionList<IkReal>> solution_set;
1223  IkSolutionList<IkReal> ik_solutions;
1224  std::vector<double> vfree;
1225  int numsol = 0;
1226  std::vector<double> sampled_joint_vals;
1227  if (!redundant_joint_indices_.empty()) {
1228  // initializing from seed
1229  sampled_joint_vals.push_back(ik_seed_state[redundant_joint_indices_[0]]);
1230 
1231  // checking joint limits when using no discretization
1232  if (options.discretization_method ==
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()];
1237 
1238  double jv = sampled_joint_vals[0];
1239  if (!((jv > (joint_min - LIMIT_TOLERANCE)) &&
1240  (jv < (joint_max + LIMIT_TOLERANCE)))) {
1241  result.kinematic_error =
1243  ROS_ERROR_STREAM("ik seed is out of bounds");
1244  return false;
1245  }
1246  }
1247 
1248  // computing all solutions sets for each sampled value of the redundant
1249  // joint
1251  sampled_joint_vals)) {
1252  result.kinematic_error =
1254  return false;
1255  }
1256 
1257  for (unsigned int i = 0; i < sampled_joint_vals.size(); i++) {
1258  vfree.clear();
1259  vfree.push_back(sampled_joint_vals[i]);
1260  numsol += solve(frame, vfree, ik_solutions);
1261  solution_set.push_back(ik_solutions);
1262  }
1263  } else {
1264  // computing for single solution set
1265  numsol = solve(frame, vfree, ik_solutions);
1266  solution_set.push_back(ik_solutions);
1267  }
1268 
1269  ROS_DEBUG_STREAM_NAMED("ikfast", "Found " << numsol
1270  << " solutions from IKFast");
1271  bool solutions_found = false;
1272  if (numsol > 0) {
1273  /*
1274  Iterating through all solution sets and storing those that do not exceed
1275  joint limits.
1276  */
1277  for (unsigned int r = 0; r < solution_set.size(); r++) {
1278  ik_solutions = solution_set[r];
1279  numsol = ik_solutions.GetNumSolutions();
1280  for (int s = 0; s < numsol; ++s) {
1281  std::vector<double> sol;
1282  getSolution(ik_solutions, s, sol);
1283 
1284  bool obeys_limits = true;
1285  for (unsigned int i = 0; i < sol.size(); i++) {
1286  // Add tolerance to limit check
1287  if (joint_has_limits_vector_[i] &&
1288  ((sol[i] < (joint_min_vector_[i] - LIMIT_TOLERANCE)) ||
1289  (sol[i] > (joint_max_vector_[i] + LIMIT_TOLERANCE)))) {
1290  // One element of solution is not within limits
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]);
1298  break;
1299  }
1300  }
1301  if (obeys_limits) {
1302  // All elements of solution obey limits
1303  solutions_found = true;
1304  solutions.push_back(sol);
1305  }
1306  }
1307  }
1308 
1309  if (solutions_found) {
1311  return true;
1312  }
1313  } else {
1314  ROS_DEBUG_STREAM_NAMED("ikfast", "No IK solution");
1315  }
1316 
1318  return false;
1319 }
1320 
1323  std::vector<double> &sampled_joint_vals) const {
1324  double joint_min = -M_PI;
1325  double joint_max = M_PI;
1326  int index = redundant_joint_indices_.front();
1327  double joint_dscrt = redundant_joint_discretization_.at(index);
1328 
1329  if (joint_has_limits_vector_[redundant_joint_indices_.front()]) {
1330  joint_min = joint_min_vector_[index];
1331  joint_max = joint_max_vector_[index];
1332  }
1333 
1334  switch (method) {
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);
1339  }
1340  sampled_joint_vals.push_back(joint_max);
1341  } break;
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);
1349  }
1350  }
1351 
1352  break;
1354 
1355  break;
1356  default:
1357  ROS_ERROR_STREAM("Discretization method " << method << " is not supported");
1358  return false;
1359  }
1360 
1361  return true;
1362 }
1363 
1364 } // end namespace
1365 
1366 // register IKFastKinematicsPlugin as a KinematicsBase implementation
std::vector< unsigned int > redundant_joint_indices_
d
virtual const IkSolutionBase< T > & GetSolution(size_t index) const
returns the solution pointer
Definition: ikfast.h:253
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)
#define ROS_FATAL(...)
#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
Definition: ikfast.h:263
XmlRpcServer s
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.
IMETHOD Vector diff(const Vector &p_w_a, const Vector &p_w_b, double dt=1)
IkParameterizationType
The types of inverse kinematics parameterizations supported.
The discrete solutions are returned in this structure.
Definition: ikfast.h:76
bool sampleRedundantJoint(kinematics::DiscretizationMethod method, std::vector< double > &sampled_joint_vals) const
samples the designated redundant joint using the chosen discretization method
#define ROS_INFO_STREAM_NAMED(name, args)
#define M_PI
virtual void Clear()
clears all current solutions, note that any memory addresses returned from GetSolution will be invali...
Definition: ikfast.h:265
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...
Rotation M
#define ROS_DEBUG_NAMED(name,...)
unsigned int index
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)
virtual const std::string & getTipFrame() const
#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)
double data[3]
void poseMsgToKDL(const geometry_msgs::Pose &m, KDL::Frame &k)
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
void poseKDLToMsg(const KDL::Frame &k, geometry_msgs::Pose &m)
Default implementation of IkSolutionListBase.
Definition: ikfast.h:243
#define ROS_FATAL_NAMED(name,...)
#define ROS_ERROR_NAMED(name,...)
static Time now()
SEARCH_MODE
Search modes for searchPositionIK(), see there.
#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.
r
#define ROS_ERROR(...)
end effector origin reaches desired 3D translation
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.
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)
double data[9]


motoman_mh5_ikfast_manipulator_plugin
Author(s):
autogenerated on Sat Sep 26 2020 03:53:08