katana_450_6m90a_ikfast_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 Butterworth, KAIST; Mathias Lüdtke, Fraunhofer
6  *IPA
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  *
13  * * Redistributions of source code must retain the above copyright
14  * notice, this list of conditions and the following disclaimer.
15  * * Redistributions in binary form must reproduce the above copyright
16  * notice, this list of conditions and the following disclaimer in the
17  * documentation and/or other materials provided with the distribution.
18  * * Neither the name of the all of the author's companies nor the names of its
19  * contributors may be used to endorse or promote products derived from
20  * this software without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
23  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
26  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
27  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
28  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
29  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
30  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
31  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32  * POSSIBILITY OF SUCH DAMAGE.
33  *
34  *********************************************************************/
35 
36 /*
37  * IKFast Plugin Template for moveit
38  *
39  * AUTO-GENERATED by create_ikfast_moveit_plugin.py in arm_kinematics_tools
40  * You should run create_ikfast_moveit_plugin.py to generate your own plugin.
41  *
42  * Creates a kinematics plugin using the output of IKFast from OpenRAVE.
43  * This plugin and the move_group node can be used as a general
44  * kinematics service, from within the moveit planning environment, or in
45  * your own ROS node.
46  *
47  */
48 
49 #include <ros/ros.h>
51 #include <urdf/model.h>
52 #include <tf_conversions/tf_kdl.h>
53 
54 // Need a floating point tolerance when checking joint limits, in case the joint starts at limit
55 const double LIMIT_TOLERANCE = .0000001;
58 {
61 };
62 
64 {
65 #define IKFAST_NO_MAIN // Don't include main() from IKFast
66 
73 {
74  IKP_None = 0,
75  IKP_Transform6D = 0x67000001,
76  IKP_Rotation3D = 0x34000002,
77  IKP_Translation3D = 0x33000003,
78  IKP_Direction3D = 0x23000004,
79  IKP_Ray4D = 0x46000005,
80  IKP_Lookat3D = 0x23000006,
82  IKP_TranslationXY2D = 0x22000008,
86  IKP_TranslationLocalGlobal6D = 0x3600000a,
89 
91  IKP_TranslationYAxisAngle4D = 0x4400000c,
94  IKP_TranslationZAxisAngle4D = 0x4400000d,
97 
101  IKP_TranslationYAxisAngleXNorm4D = 0x4400000f,
105  IKP_TranslationZAxisAngleYNorm4D = 0x44000010,
109 
114 
116  0x00008000,
133 
134  IKP_UniqueIdMask = 0x0000ffff,
135  IKP_CustomDataBit = 0x00010000,
136 };
139 // Code generated by IKFast56/61
141 
143 {
144  std::vector<std::string> joint_names_;
145  std::vector<double> joint_min_vector_;
146  std::vector<double> joint_max_vector_;
147  std::vector<bool> joint_has_limits_vector_;
148  std::vector<std::string> link_names_;
149  size_t num_joints_;
150  std::vector<int> free_params_;
151  bool active_; // Internal variable that indicates whether solvers are configured and ready
152 
153  const std::vector<std::string>& getJointNames() const
154  {
155  return joint_names_;
156  }
157  const std::vector<std::string>& getLinkNames() const
158  {
159  return link_names_;
160  }
162 public:
166  IKFastKinematicsPlugin() : active_(false)
167  {
168  srand(time(NULL));
172  }
173 
183  // Returns the first IK solution that is within joint limits, this is called by get_ik() service
184  bool getPositionIK(const geometry_msgs::Pose& ik_pose, const std::vector<double>& ik_seed_state,
185  std::vector<double>& solution, moveit_msgs::MoveItErrorCodes& error_code,
187 
203  bool getPositionIK(const std::vector<geometry_msgs::Pose>& ik_poses, const std::vector<double>& ik_seed_state,
204  std::vector<std::vector<double> >& solutions, kinematics::KinematicsResult& result,
205  const kinematics::KinematicsQueryOptions& options) const;
206 
215  bool searchPositionIK(const geometry_msgs::Pose& ik_pose, const std::vector<double>& ik_seed_state, double timeout,
216  std::vector<double>& solution, moveit_msgs::MoveItErrorCodes& error_code,
218 
228  bool searchPositionIK(const geometry_msgs::Pose& ik_pose, const std::vector<double>& ik_seed_state, double timeout,
229  const std::vector<double>& consistency_limits, std::vector<double>& solution,
230  moveit_msgs::MoveItErrorCodes& error_code,
232 
241  bool searchPositionIK(const geometry_msgs::Pose& ik_pose, const std::vector<double>& ik_seed_state, double timeout,
242  std::vector<double>& solution, const IKCallbackFn& solution_callback,
243  moveit_msgs::MoveItErrorCodes& error_code,
245 
256  bool searchPositionIK(const geometry_msgs::Pose& ik_pose, const std::vector<double>& ik_seed_state, double timeout,
257  const std::vector<double>& consistency_limits, std::vector<double>& solution,
258  const IKCallbackFn& solution_callback, moveit_msgs::MoveItErrorCodes& error_code,
260 
269  bool getPositionFK(const std::vector<std::string>& link_names, const std::vector<double>& joint_angles,
270  std::vector<geometry_msgs::Pose>& poses) const;
271 
281  void setSearchDiscretization(const std::map<int, double>& discretization);
282 
286  bool setRedundantJoints(const std::vector<unsigned int>& redundant_joint_indices);
287 
288 private:
289  bool initialize(const std::string& robot_description, const std::string& group_name, const std::string& base_name,
290  const std::string& tip_name, double search_discretization);
291 
296  int solve(KDL::Frame& pose_frame, const std::vector<double>& vfree, IkSolutionList<IkReal>& solutions) const;
297 
301  void getSolution(const IkSolutionList<IkReal>& solutions, int i, std::vector<double>& solution) const;
302 
303  double harmonize(const std::vector<double>& ik_seed_state, std::vector<double>& solution) const;
304  // void getOrderedSolutions(const std::vector<double> &ik_seed_state, std::vector<std::vector<double> >& solslist);
305  void getClosestSolution(const IkSolutionList<IkReal>& solutions, const std::vector<double>& ik_seed_state,
306  std::vector<double>& solution) const;
307  void fillFreeParams(int count, int* array);
308  bool getCount(int& count, const int& max_count, const int& min_count) const;
309 
316  bool sampleRedundantJoint(kinematics::DiscretizationMethod method, std::vector<double>& sampled_joint_vals) const;
317 
318 }; // end class
319 
320 bool IKFastKinematicsPlugin::initialize(const std::string& robot_description, const std::string& group_name,
321  const std::string& base_name, const std::string& tip_name,
322  double search_discretization)
323 {
324  setValues(robot_description, group_name, base_name, tip_name, search_discretization);
325 
326  ros::NodeHandle node_handle("~/" + group_name);
327 
328  std::string robot;
329  node_handle.param("robot", robot, std::string());
330 
331  // IKFast56/61
333  num_joints_ = GetNumJoints();
334 
335  if (free_params_.size() > 1)
336  {
337  ROS_FATAL("Only one free joint parameter supported!");
338  return false;
339  }
340  else if (free_params_.size() == 1)
341  {
342  redundant_joint_indices_.clear();
343  redundant_joint_indices_.push_back(free_params_[0]);
344  KinematicsBase::setSearchDiscretization(DEFAULT_SEARCH_DISCRETIZATION);
345  }
346 
347  urdf::Model robot_model;
348  std::string xml_string;
349 
350  std::string urdf_xml, full_urdf_xml;
351  node_handle.param("urdf_xml", urdf_xml, robot_description);
352  node_handle.searchParam(urdf_xml, full_urdf_xml);
353 
354  ROS_DEBUG_NAMED("ikfast", "Reading xml file from parameter server");
355  if (!node_handle.getParam(full_urdf_xml, xml_string))
356  {
357  ROS_FATAL_NAMED("ikfast", "Could not load the xml from parameter server: %s", urdf_xml.c_str());
358  return false;
359  }
360 
361  node_handle.param(full_urdf_xml, xml_string, std::string());
362  robot_model.initString(xml_string);
363 
364  ROS_DEBUG_STREAM_NAMED("ikfast", "Reading joints and links from URDF");
365 
366  urdf::LinkConstSharedPtr link = robot_model.getLink(getTipFrame());
367  while (link->name != base_frame_ && joint_names_.size() <= num_joints_)
368  {
369  ROS_DEBUG_NAMED("ikfast", "Link %s", link->name.c_str());
370  link_names_.push_back(link->name);
371  urdf::JointSharedPtr joint = link->parent_joint;
372  if (joint)
373  {
374  if (joint->type != urdf::Joint::UNKNOWN && joint->type != urdf::Joint::FIXED)
375  {
376  ROS_DEBUG_STREAM_NAMED("ikfast", "Adding joint " << joint->name);
377 
378  joint_names_.push_back(joint->name);
379  float lower, upper;
380  int hasLimits;
381  if (joint->type != urdf::Joint::CONTINUOUS)
382  {
383  if (joint->safety)
384  {
385  lower = joint->safety->soft_lower_limit;
386  upper = joint->safety->soft_upper_limit;
387  }
388  else
389  {
390  lower = joint->limits->lower;
391  upper = joint->limits->upper;
392  }
393  hasLimits = 1;
394  }
395  else
396  {
397  lower = -M_PI;
398  upper = M_PI;
399  hasLimits = 0;
400  }
401  if (hasLimits)
402  {
403  joint_has_limits_vector_.push_back(true);
404  joint_min_vector_.push_back(lower);
405  joint_max_vector_.push_back(upper);
406  }
407  else
408  {
409  joint_has_limits_vector_.push_back(false);
410  joint_min_vector_.push_back(-M_PI);
411  joint_max_vector_.push_back(M_PI);
412  }
413  }
414  }
415  else
416  {
417  ROS_WARN_NAMED("ikfast", "no joint corresponding to %s", link->name.c_str());
418  }
419  link = link->getParent();
420  }
421 
422  if (joint_names_.size() != num_joints_)
423  {
424  ROS_FATAL_STREAM_NAMED("ikfast", "Joint numbers mismatch: URDF has " << joint_names_.size() << " and IKFast has "
425  << num_joints_);
426  return false;
427  }
428 
429  std::reverse(link_names_.begin(), link_names_.end());
430  std::reverse(joint_names_.begin(), joint_names_.end());
431  std::reverse(joint_min_vector_.begin(), joint_min_vector_.end());
432  std::reverse(joint_max_vector_.begin(), joint_max_vector_.end());
433  std::reverse(joint_has_limits_vector_.begin(), joint_has_limits_vector_.end());
434 
435  for (size_t i = 0; i < num_joints_; ++i)
436  ROS_DEBUG_STREAM_NAMED("ikfast", joint_names_[i] << " " << joint_min_vector_[i] << " " << joint_max_vector_[i]
437  << " " << joint_has_limits_vector_[i]);
438 
439  active_ = true;
440  return true;
441 }
442 
443 void IKFastKinematicsPlugin::setSearchDiscretization(const std::map<int, double>& discretization)
444 {
445  if (discretization.empty())
446  {
447  ROS_ERROR("The 'discretization' map is empty");
448  return;
449  }
450 
451  if (redundant_joint_indices_.empty())
452  {
453  ROS_ERROR_STREAM("This group's solver doesn't support redundant joints");
454  return;
455  }
456 
457  if (discretization.begin()->first != redundant_joint_indices_[0])
458  {
459  std::string redundant_joint = joint_names_[free_params_[0]];
460  ROS_ERROR_STREAM("Attempted to discretize a non-redundant joint "
461  << discretization.begin()->first << ", only joint '" << redundant_joint << "' with index "
462  << redundant_joint_indices_[0] << " is redundant.");
463  return;
464  }
465 
466  if (discretization.begin()->second <= 0.0)
467  {
468  ROS_ERROR_STREAM("Discretization can not takes values that are <= 0");
469  return;
470  }
471 
473  redundant_joint_discretization_[redundant_joint_indices_[0]] = discretization.begin()->second;
474 }
475 
476 bool IKFastKinematicsPlugin::setRedundantJoints(const std::vector<unsigned int>& redundant_joint_indices)
477 {
478  ROS_ERROR_STREAM("Changing the redundant joints isn't permitted by this group's solver ");
479  return false;
480 }
481 
482 int IKFastKinematicsPlugin::solve(KDL::Frame& pose_frame, const std::vector<double>& vfree,
483  IkSolutionList<IkReal>& solutions) const
484 {
485  // IKFast56/61
486  solutions.Clear();
487 
488  double trans[3];
489  trans[0] = pose_frame.p[0]; //-.18;
490  trans[1] = pose_frame.p[1];
491  trans[2] = pose_frame.p[2];
492 
493  KDL::Rotation mult;
494  KDL::Vector direction;
495 
496  switch (GetIkType())
497  {
498  case IKP_Transform6D:
499  case IKP_Translation3D:
500  // For **Transform6D**, eerot is 9 values for the 3x3 rotation matrix. For **Translation3D**, these are ignored.
501 
502  mult = pose_frame.M;
503 
504  double vals[9];
505  vals[0] = mult(0, 0);
506  vals[1] = mult(0, 1);
507  vals[2] = mult(0, 2);
508  vals[3] = mult(1, 0);
509  vals[4] = mult(1, 1);
510  vals[5] = mult(1, 2);
511  vals[6] = mult(2, 0);
512  vals[7] = mult(2, 1);
513  vals[8] = mult(2, 2);
514 
515  // IKFast56/61
516  ComputeIk(trans, vals, vfree.size() > 0 ? &vfree[0] : NULL, solutions);
517  return solutions.GetNumSolutions();
518 
519  case IKP_Direction3D:
520  case IKP_Ray4D:
522  // For **Direction3D**, **Ray4D**, and **TranslationDirection5D**, the first 3 values represent the target
523  // direction.
524 
525  direction = pose_frame.M * KDL::Vector(0, 0, 1);
526  ComputeIk(trans, direction.data, vfree.size() > 0 ? &vfree[0] : NULL, solutions);
527  return solutions.GetNumSolutions();
528 
532  // For **TranslationXAxisAngle4D**, **TranslationYAxisAngle4D**, and **TranslationZAxisAngle4D**, the first value
533  // represents the angle.
534  ROS_ERROR_NAMED("ikfast", "IK for this IkParameterizationType not implemented yet.");
535  return 0;
536 
538  // For **TranslationLocalGlobal6D**, the diagonal elements ([0],[4],[8]) are the local translation inside the end
539  // effector coordinate system.
540  ROS_ERROR_NAMED("ikfast", "IK for this IkParameterizationType not implemented yet.");
541  return 0;
542 
543  case IKP_Rotation3D:
544  case IKP_Lookat3D:
545  case IKP_TranslationXY2D:
550  ROS_ERROR_NAMED("ikfast", "IK for this IkParameterizationType not implemented yet.");
551  return 0;
552 
553  default:
554  ROS_ERROR_NAMED("ikfast", "Unknown IkParameterizationType! Was the solver generated with an incompatible version "
555  "of Openrave?");
556  return 0;
557  }
558 }
559 
561  std::vector<double>& solution) const
562 {
563  solution.clear();
564  solution.resize(num_joints_);
565 
566  // IKFast56/61
567  const IkSolutionBase<IkReal>& sol = solutions.GetSolution(i);
568  std::vector<IkReal> vsolfree(sol.GetFree().size());
569  sol.GetSolution(&solution[0], vsolfree.size() > 0 ? &vsolfree[0] : NULL);
570 
571  // std::cout << "solution " << i << ":" ;
572  // for(int j=0;j<num_joints_; ++j)
573  // std::cout << " " << solution[j];
574  // std::cout << std::endl;
575 
576  // ROS_ERROR("%f %d",solution[2],vsolfree.size());
577 }
578 
579 double IKFastKinematicsPlugin::harmonize(const std::vector<double>& ik_seed_state, std::vector<double>& solution) const
580 {
581  double dist_sqr = 0;
582  std::vector<double> ss = ik_seed_state;
583  for (size_t i = 0; i < ik_seed_state.size(); ++i)
584  {
585  while (ss[i] > 2 * M_PI)
586  {
587  ss[i] -= 2 * M_PI;
588  }
589  while (ss[i] < 2 * M_PI)
590  {
591  ss[i] += 2 * M_PI;
592  }
593  while (solution[i] > 2 * M_PI)
594  {
595  solution[i] -= 2 * M_PI;
596  }
597  while (solution[i] < 2 * M_PI)
598  {
599  solution[i] += 2 * M_PI;
600  }
601  dist_sqr += fabs(ik_seed_state[i] - solution[i]);
602  }
603  return dist_sqr;
604 }
605 
606 // void IKFastKinematicsPlugin::getOrderedSolutions(const std::vector<double> &ik_seed_state,
607 // std::vector<std::vector<double> >& solslist)
608 // {
609 // std::vector<double>
610 // double mindist = 0;
611 // int minindex = -1;
612 // std::vector<double> sol;
613 // for(size_t i=0;i<solslist.size();++i){
614 // getSolution(i,sol);
615 // double dist = harmonize(ik_seed_state, sol);
616 // //std::cout << "dist[" << i << "]= " << dist << std::endl;
617 // if(minindex == -1 || dist<mindist){
618 // minindex = i;
619 // mindist = dist;
620 // }
621 // }
622 // if(minindex >= 0){
623 // getSolution(minindex,solution);
624 // harmonize(ik_seed_state, solution);
625 // index = minindex;
626 // }
627 // }
628 
630  const std::vector<double>& ik_seed_state,
631  std::vector<double>& solution) const
632 {
633  double mindist = DBL_MAX;
634  int minindex = -1;
635  std::vector<double> sol;
636 
637  // IKFast56/61
638  for (size_t i = 0; i < solutions.GetNumSolutions(); ++i)
639  {
640  getSolution(solutions, i, sol);
641  double dist = harmonize(ik_seed_state, sol);
642  ROS_INFO_STREAM_NAMED("ikfast", "Dist " << i << " dist " << dist);
643  // std::cout << "dist[" << i << "]= " << dist << std::endl;
644  if (minindex == -1 || dist < mindist)
645  {
646  minindex = i;
647  mindist = dist;
648  }
649  }
650  if (minindex >= 0)
651  {
652  getSolution(solutions, minindex, solution);
653  harmonize(ik_seed_state, solution);
654  }
655 }
656 
657 void IKFastKinematicsPlugin::fillFreeParams(int count, int* array)
658 {
659  free_params_.clear();
660  for (int i = 0; i < count; ++i)
661  free_params_.push_back(array[i]);
662 }
663 
664 bool IKFastKinematicsPlugin::getCount(int& count, const int& max_count, const int& min_count) const
665 {
666  if (count > 0)
667  {
668  if (-count >= min_count)
669  {
670  count = -count;
671  return true;
672  }
673  else if (count + 1 <= max_count)
674  {
675  count = count + 1;
676  return true;
677  }
678  else
679  {
680  return false;
681  }
682  }
683  else
684  {
685  if (1 - count <= max_count)
686  {
687  count = 1 - count;
688  return true;
689  }
690  else if (count - 1 >= min_count)
691  {
692  count = count - 1;
693  return true;
694  }
695  else
696  return false;
697  }
698 }
699 
700 bool IKFastKinematicsPlugin::getPositionFK(const std::vector<std::string>& link_names,
701  const std::vector<double>& joint_angles,
702  std::vector<geometry_msgs::Pose>& poses) const
703 {
704  if (GetIkType() != IKP_Transform6D)
705  {
706  // ComputeFk() is the inverse function of ComputeIk(), so the format of
707  // eerot differs depending on IK type. The Transform6D IK type is the only
708  // one for which a 3x3 rotation matrix is returned, which means we can only
709  // compute FK for that IK type.
710  ROS_ERROR_NAMED("ikfast", "Can only compute FK for Transform6D IK type!");
711  return false;
712  }
713 
714  KDL::Frame p_out;
715  if (link_names.size() == 0)
716  {
717  ROS_WARN_STREAM_NAMED("ikfast", "Link names with nothing");
718  return false;
719  }
720 
721  if (link_names.size() != 1 || link_names[0] != getTipFrame())
722  {
723  ROS_ERROR_NAMED("ikfast", "Can compute FK for %s only", getTipFrame().c_str());
724  return false;
725  }
726 
727  bool valid = true;
728 
729  IkReal eerot[9], eetrans[3];
730  IkReal angles[joint_angles.size()];
731  for (unsigned char i = 0; i < joint_angles.size(); i++)
732  angles[i] = joint_angles[i];
733 
734  // IKFast56/61
735  ComputeFk(angles, eetrans, eerot);
736 
737  for (int i = 0; i < 3; ++i)
738  p_out.p.data[i] = eetrans[i];
739 
740  for (int i = 0; i < 9; ++i)
741  p_out.M.data[i] = eerot[i];
742 
743  poses.resize(1);
744  tf::poseKDLToMsg(p_out, poses[0]);
745 
746  return valid;
747 }
748 
749 bool IKFastKinematicsPlugin::searchPositionIK(const geometry_msgs::Pose& ik_pose,
750  const std::vector<double>& ik_seed_state, double timeout,
751  std::vector<double>& solution, moveit_msgs::MoveItErrorCodes& error_code,
752  const kinematics::KinematicsQueryOptions& options) const
753 {
754  const IKCallbackFn solution_callback = 0;
755  std::vector<double> consistency_limits;
756 
757  return searchPositionIK(ik_pose, ik_seed_state, timeout, consistency_limits, solution, solution_callback, error_code,
758  options);
759 }
760 
761 bool IKFastKinematicsPlugin::searchPositionIK(const geometry_msgs::Pose& ik_pose,
762  const std::vector<double>& ik_seed_state, double timeout,
763  const std::vector<double>& consistency_limits,
764  std::vector<double>& solution, moveit_msgs::MoveItErrorCodes& error_code,
765  const kinematics::KinematicsQueryOptions& options) const
766 {
767  const IKCallbackFn solution_callback = 0;
768  return searchPositionIK(ik_pose, ik_seed_state, timeout, consistency_limits, solution, solution_callback, error_code,
769  options);
770 }
771 
772 bool IKFastKinematicsPlugin::searchPositionIK(const geometry_msgs::Pose& ik_pose,
773  const std::vector<double>& ik_seed_state, double timeout,
774  std::vector<double>& solution, const IKCallbackFn& solution_callback,
775  moveit_msgs::MoveItErrorCodes& error_code,
776  const kinematics::KinematicsQueryOptions& options) const
777 {
778  std::vector<double> consistency_limits;
779  return searchPositionIK(ik_pose, ik_seed_state, timeout, consistency_limits, solution, solution_callback, error_code,
780  options);
781 }
782 
783 bool IKFastKinematicsPlugin::searchPositionIK(const geometry_msgs::Pose& ik_pose,
784  const std::vector<double>& ik_seed_state, double timeout,
785  const std::vector<double>& consistency_limits,
786  std::vector<double>& solution, const IKCallbackFn& solution_callback,
787  moveit_msgs::MoveItErrorCodes& error_code,
788  const kinematics::KinematicsQueryOptions& options) const
789 {
790  ROS_DEBUG_STREAM_NAMED("ikfast", "searchPositionIK");
791 
793  SEARCH_MODE search_mode = OPTIMIZE_MAX_JOINT;
794 
795  // Check if there are no redundant joints
796  if (free_params_.size() == 0)
797  {
798  ROS_DEBUG_STREAM_NAMED("ikfast", "No need to search since no free params/redundant joints");
799 
800  // Find first IK solution, within joint limits
801  if (!getPositionIK(ik_pose, ik_seed_state, solution, error_code))
802  {
803  ROS_DEBUG_STREAM_NAMED("ikfast", "No solution whatsoever");
804  error_code.val = moveit_msgs::MoveItErrorCodes::NO_IK_SOLUTION;
805  return false;
806  }
807 
808  // check for collisions if a callback is provided
809  if (!solution_callback.empty())
810  {
811  solution_callback(ik_pose, solution, error_code);
812  if (error_code.val == moveit_msgs::MoveItErrorCodes::SUCCESS)
813  {
814  ROS_DEBUG_STREAM_NAMED("ikfast", "Solution passes callback");
815  return true;
816  }
817  else
818  {
819  ROS_DEBUG_STREAM_NAMED("ikfast", "Solution has error code " << error_code);
820  return false;
821  }
822  }
823  else
824  {
825  return true; // no collision check callback provided
826  }
827  }
828 
829  // -------------------------------------------------------------------------------------------------
830  // Error Checking
831  if (!active_)
832  {
833  ROS_ERROR_STREAM_NAMED("ikfast", "Kinematics not active");
834  error_code.val = error_code.NO_IK_SOLUTION;
835  return false;
836  }
837 
838  if (ik_seed_state.size() != num_joints_)
839  {
840  ROS_ERROR_STREAM_NAMED("ikfast", "Seed state must have size " << num_joints_ << " instead of size "
841  << ik_seed_state.size());
842  error_code.val = error_code.NO_IK_SOLUTION;
843  return false;
844  }
845 
846  if (!consistency_limits.empty() && consistency_limits.size() != num_joints_)
847  {
848  ROS_ERROR_STREAM_NAMED("ikfast", "Consistency limits be empty or must have size "
849  << num_joints_ << " instead of size " << consistency_limits.size());
850  error_code.val = error_code.NO_IK_SOLUTION;
851  return false;
852  }
853 
854  // -------------------------------------------------------------------------------------------------
855  // Initialize
856 
857  KDL::Frame frame;
858  tf::poseMsgToKDL(ik_pose, frame);
859 
860  std::vector<double> vfree(free_params_.size());
861 
862  ros::Time maxTime = ros::Time::now() + ros::Duration(timeout);
863  int counter = 0;
864 
865  double initial_guess = ik_seed_state[free_params_[0]];
866  vfree[0] = initial_guess;
867 
868  // -------------------------------------------------------------------------------------------------
869  // Handle consitency limits if needed
870  int num_positive_increments;
871  int num_negative_increments;
872 
873  if (!consistency_limits.empty())
874  {
875  // moveit replaced consistency_limit (scalar) w/ consistency_limits (vector)
876  // Assume [0]th free_params element for now. Probably wrong.
877  double max_limit = fmin(joint_max_vector_[free_params_[0]], initial_guess + consistency_limits[free_params_[0]]);
878  double min_limit = fmax(joint_min_vector_[free_params_[0]], initial_guess - consistency_limits[free_params_[0]]);
879 
880  num_positive_increments = (int)((max_limit - initial_guess) / search_discretization_);
881  num_negative_increments = (int)((initial_guess - min_limit) / search_discretization_);
882  }
883  else // no consitency limits provided
884  {
885  num_positive_increments = (joint_max_vector_[free_params_[0]] - initial_guess) / search_discretization_;
886  num_negative_increments = (initial_guess - joint_min_vector_[free_params_[0]]) / search_discretization_;
887  }
888 
889  // -------------------------------------------------------------------------------------------------
890  // Begin searching
891 
892  ROS_DEBUG_STREAM_NAMED("ikfast", "Free param is " << free_params_[0] << " initial guess is " << initial_guess
893  << ", # positive increments: " << num_positive_increments
894  << ", # negative increments: " << num_negative_increments);
895  if ((search_mode & OPTIMIZE_MAX_JOINT) && (num_positive_increments + num_negative_increments) > 1000)
896  ROS_WARN_STREAM_ONCE_NAMED("ikfast", "Large search space, consider increasing the search discretization");
897 
898  double best_costs = -1.0;
899  std::vector<double> best_solution;
900  int nattempts = 0, nvalid = 0;
901 
902  while (true)
903  {
904  IkSolutionList<IkReal> solutions;
905  int numsol = solve(frame, vfree, solutions);
906 
907  ROS_DEBUG_STREAM_NAMED("ikfast", "Found " << numsol << " solutions from IKFast");
908 
909  // ROS_INFO("%f",vfree[0]);
910 
911  if (numsol > 0)
912  {
913  for (int s = 0; s < numsol; ++s)
914  {
915  nattempts++;
916  std::vector<double> sol;
917  getSolution(solutions, s, sol);
918 
919  bool obeys_limits = true;
920  for (unsigned int i = 0; i < sol.size(); i++)
921  {
922  if (joint_has_limits_vector_[i] && (sol[i] < joint_min_vector_[i] || sol[i] > joint_max_vector_[i]))
923  {
924  obeys_limits = false;
925  break;
926  }
927  // ROS_INFO_STREAM_NAMED("ikfast","Num " << i << " value " << sol[i] << " has limits " <<
928  // joint_has_limits_vector_[i] << " " << joint_min_vector_[i] << " " << joint_max_vector_[i]);
929  }
930  if (obeys_limits)
931  {
932  getSolution(solutions, s, solution);
933 
934  // This solution is within joint limits, now check if in collision (if callback provided)
935  if (!solution_callback.empty())
936  {
937  solution_callback(ik_pose, solution, error_code);
938  }
939  else
940  {
941  error_code.val = error_code.SUCCESS;
942  }
943 
944  if (error_code.val == error_code.SUCCESS)
945  {
946  nvalid++;
947  if (search_mode & OPTIMIZE_MAX_JOINT)
948  {
949  // Costs for solution: Largest joint motion
950  double costs = 0.0;
951  for (unsigned int i = 0; i < solution.size(); i++)
952  {
953  double d = fabs(ik_seed_state[i] - solution[i]);
954  if (d > costs)
955  costs = d;
956  }
957  if (costs < best_costs || best_costs == -1.0)
958  {
959  best_costs = costs;
960  best_solution = solution;
961  }
962  }
963  else
964  // Return first feasible solution
965  return true;
966  }
967  }
968  }
969  }
970 
971  if (!getCount(counter, num_positive_increments, -num_negative_increments))
972  {
973  // Everything searched
974  error_code.val = moveit_msgs::MoveItErrorCodes::NO_IK_SOLUTION;
975  break;
976  }
977 
978  vfree[0] = initial_guess + search_discretization_ * counter;
979  // ROS_DEBUG_STREAM_NAMED("ikfast","Attempt " << counter << " with 0th free joint having value " << vfree[0]);
980  }
981 
982  ROS_DEBUG_STREAM_NAMED("ikfast", "Valid solutions: " << nvalid << "/" << nattempts);
983 
984  if ((search_mode & OPTIMIZE_MAX_JOINT) && best_costs != -1.0)
985  {
986  solution = best_solution;
987  error_code.val = error_code.SUCCESS;
988  return true;
989  }
990 
991  // No solution found
992  error_code.val = moveit_msgs::MoveItErrorCodes::NO_IK_SOLUTION;
993  return false;
994 }
995 
996 // Used when there are no redundant joints - aka no free params
997 bool IKFastKinematicsPlugin::getPositionIK(const geometry_msgs::Pose& ik_pose, const std::vector<double>& ik_seed_state,
998  std::vector<double>& solution, moveit_msgs::MoveItErrorCodes& error_code,
999  const kinematics::KinematicsQueryOptions& options) const
1000 {
1001  ROS_DEBUG_STREAM_NAMED("ikfast", "getPositionIK");
1002 
1003  if (!active_)
1004  {
1005  ROS_ERROR("kinematics not active");
1006  return false;
1007  }
1008 
1009  std::vector<double> vfree(free_params_.size());
1010  for (std::size_t i = 0; i < free_params_.size(); ++i)
1011  {
1012  int p = free_params_[i];
1013  ROS_ERROR("%u is %f", p, ik_seed_state[p]); // DTC
1014  vfree[i] = ik_seed_state[p];
1015  }
1016 
1017  KDL::Frame frame;
1018  tf::poseMsgToKDL(ik_pose, frame);
1019 
1020  IkSolutionList<IkReal> solutions;
1021  int numsol = solve(frame, vfree, solutions);
1022 
1023  ROS_DEBUG_STREAM_NAMED("ikfast", "Found " << numsol << " solutions from IKFast");
1024 
1025  if (numsol)
1026  {
1027  for (int s = 0; s < numsol; ++s)
1028  {
1029  std::vector<double> sol;
1030  getSolution(solutions, s, sol);
1031  ROS_DEBUG_NAMED("ikfast", "Sol %d: %e %e %e %e %e %e", s, sol[0], sol[1], sol[2], sol[3], sol[4],
1032  sol[5]);
1033 
1034  bool obeys_limits = true;
1035  for (unsigned int i = 0; i < sol.size(); i++)
1036  {
1037  // Add tolerance to limit check
1038  if (joint_has_limits_vector_[i] && ((sol[i] < (joint_min_vector_[i] - LIMIT_TOLERANCE)) ||
1039  (sol[i] > (joint_max_vector_[i] + LIMIT_TOLERANCE))))
1040  {
1041  // One element of solution is not within limits
1042  obeys_limits = false;
1043  ROS_DEBUG_STREAM_NAMED("ikfast", "Not in limits! " << i << " value " << sol[i] << " has limit: "
1044  << joint_has_limits_vector_[i] << " being "
1045  << joint_min_vector_[i] << " to " << joint_max_vector_[i]);
1046  break;
1047  }
1048  }
1049  if (obeys_limits)
1050  {
1051  // All elements of solution obey limits
1052  getSolution(solutions, s, solution);
1053  error_code.val = moveit_msgs::MoveItErrorCodes::SUCCESS;
1054  return true;
1055  }
1056  }
1057  }
1058  else
1059  {
1060  ROS_DEBUG_STREAM_NAMED("ikfast", "No IK solution");
1061  }
1062 
1063  error_code.val = moveit_msgs::MoveItErrorCodes::NO_IK_SOLUTION;
1064  return false;
1065 }
1066 
1067 bool IKFastKinematicsPlugin::getPositionIK(const std::vector<geometry_msgs::Pose>& ik_poses,
1068  const std::vector<double>& ik_seed_state,
1069  std::vector<std::vector<double> >& solutions,
1071  const kinematics::KinematicsQueryOptions& options) const
1072 {
1073  ROS_DEBUG_STREAM_NAMED("ikfast", "getPositionIK with multiple solutions");
1074 
1075  if (!active_)
1076  {
1077  ROS_ERROR("kinematics not active");
1079  return false;
1080  }
1081 
1082  if (ik_poses.empty())
1083  {
1084  ROS_ERROR("ik_poses is empty");
1086  return false;
1087  }
1088 
1089  if (ik_poses.size() > 1)
1090  {
1091  ROS_ERROR("ik_poses contains multiple entries, only one is allowed");
1093  return false;
1094  }
1095 
1096  if (ik_seed_state.size() < num_joints_)
1097  {
1098  ROS_ERROR_STREAM("ik_seed_state only has " << ik_seed_state.size() << " entries, this ikfast solver requires "
1099  << num_joints_);
1100  return false;
1101  }
1102 
1103  KDL::Frame frame;
1104  tf::poseMsgToKDL(ik_poses[0], frame);
1105 
1106  // solving ik
1107  std::vector<IkSolutionList<IkReal> > solution_set;
1108  IkSolutionList<IkReal> ik_solutions;
1109  std::vector<double> vfree;
1110  int numsol = 0;
1111  std::vector<double> sampled_joint_vals;
1112  if (!redundant_joint_indices_.empty())
1113  {
1114  // initializing from seed
1115  sampled_joint_vals.push_back(ik_seed_state[redundant_joint_indices_[0]]);
1116 
1117  // checking joint limits when using no discretization
1119  joint_has_limits_vector_[redundant_joint_indices_.front()])
1120  {
1121  double joint_min = joint_min_vector_[redundant_joint_indices_.front()];
1122  double joint_max = joint_max_vector_[redundant_joint_indices_.front()];
1123 
1124  double jv = sampled_joint_vals[0];
1125  if (!((jv > (joint_min - LIMIT_TOLERANCE)) && (jv < (joint_max + LIMIT_TOLERANCE))))
1126  {
1128  ROS_ERROR_STREAM("ik seed is out of bounds");
1129  return false;
1130  }
1131  }
1132 
1133  // computing all solutions sets for each sampled value of the redundant joint
1134  if (!sampleRedundantJoint(options.discretization_method, sampled_joint_vals))
1135  {
1137  return false;
1138  }
1139 
1140  for (unsigned int i = 0; i < sampled_joint_vals.size(); i++)
1141  {
1142  vfree.clear();
1143  vfree.push_back(sampled_joint_vals[i]);
1144  numsol += solve(frame, vfree, ik_solutions);
1145  solution_set.push_back(ik_solutions);
1146  }
1147  }
1148  else
1149  {
1150  // computing for single solution set
1151  numsol = solve(frame, vfree, ik_solutions);
1152  solution_set.push_back(ik_solutions);
1153  }
1154 
1155  ROS_DEBUG_STREAM_NAMED("ikfast", "Found " << numsol << " solutions from IKFast");
1156  bool solutions_found = false;
1157  if (numsol > 0)
1158  {
1159  /*
1160  Iterating through all solution sets and storing those that do not exceed joint limits.
1161  */
1162  for (unsigned int r = 0; r < solution_set.size(); r++)
1163  {
1164  ik_solutions = solution_set[r];
1165  numsol = ik_solutions.GetNumSolutions();
1166  for (int s = 0; s < numsol; ++s)
1167  {
1168  std::vector<double> sol;
1169  getSolution(ik_solutions, s, sol);
1170 
1171  bool obeys_limits = true;
1172  for (unsigned int i = 0; i < sol.size(); i++)
1173  {
1174  // Add tolerance to limit check
1175  if (joint_has_limits_vector_[i] && ((sol[i] < (joint_min_vector_[i] - LIMIT_TOLERANCE)) ||
1176  (sol[i] > (joint_max_vector_[i] + LIMIT_TOLERANCE))))
1177  {
1178  // One element of solution is not within limits
1179  obeys_limits = false;
1181  "ikfast", "Not in limits! " << i << " value " << sol[i] << " has limit: " << joint_has_limits_vector_[i]
1182  << " being " << joint_min_vector_[i] << " to " << joint_max_vector_[i]);
1183  break;
1184  }
1185  }
1186  if (obeys_limits)
1187  {
1188  // All elements of solution obey limits
1189  solutions_found = true;
1190  solutions.push_back(sol);
1191  }
1192  }
1193  }
1194 
1195  if (solutions_found)
1196  {
1198  return true;
1199  }
1200  }
1201  else
1202  {
1203  ROS_DEBUG_STREAM_NAMED("ikfast", "No IK solution");
1204  }
1205 
1207  return false;
1208 }
1209 
1211  std::vector<double>& sampled_joint_vals) const
1212 {
1213  double joint_min = -M_PI;
1214  double joint_max = M_PI;
1215  int index = redundant_joint_indices_.front();
1216  double joint_dscrt = redundant_joint_discretization_.at(index);
1217 
1218  if (joint_has_limits_vector_[redundant_joint_indices_.front()])
1219  {
1220  joint_min = joint_min_vector_[index];
1221  joint_max = joint_max_vector_[index];
1222  }
1223 
1224  switch (method)
1225  {
1227  {
1228  int steps = std::ceil((joint_max - joint_min) / joint_dscrt);
1229  for (unsigned int i = 0; i < steps; i++)
1230  {
1231  sampled_joint_vals.push_back(joint_min + joint_dscrt * i);
1232  }
1233  sampled_joint_vals.push_back(joint_max);
1234  }
1235  break;
1237  {
1238  int steps = std::ceil((joint_max - joint_min) / joint_dscrt);
1239  steps = steps > 0 ? steps : 1;
1240  double diff = joint_max - joint_min;
1241  for (int i = 0; i < steps; i++)
1242  {
1243  sampled_joint_vals.push_back(((diff * std::rand()) / (static_cast<double>(RAND_MAX))) + joint_min);
1244  }
1245  }
1246 
1247  break;
1249 
1250  break;
1251  default:
1252  ROS_ERROR_STREAM("Discretization method " << method << " is not supported");
1253  return false;
1254  }
1255 
1256  return true;
1257 }
1258 
1259 } // end namespace
1260 
1261 // 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:283
KinematicError kinematic_error
SEARCH_MODE
Search modes for searchPositionIK(), see there.
#define ROS_FATAL(...)
local point on end effector origin reaches desired 3D global point
#define ROS_DEBUG_STREAM_NAMED(name, args)
#define ROS_ERROR_STREAM_NAMED(name, args)
URDF_EXPORT bool initString(const std::string &xmlstring)
end effector origin reaches desired 3D translation
#define ROS_WARN_NAMED(name,...)
end effector reaches desired 6D transformation
virtual size_t GetNumSolutions() const
returns the number of solutions stored
Definition: ikfast.h:294
PLUGINLIB_EXPORT_CLASS(katana_450_6m90a_kinematics::IKFastKinematicsPlugin, kinematics::KinematicsBase)
XmlRpcServer s
IMETHOD Vector diff(const Vector &p_w_a, const Vector &p_w_b, double dt=1)
The discrete solutions are returned in this structure.
Definition: ikfast.h:70
#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:299
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...
const double LIMIT_TOLERANCE
void getSolution(const IkSolutionList< IkReal > &solutions, int i, std::vector< double > &solution) const
Gets a specific solution from the set.
number of parameterizations (does not count IKP_None)
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.
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.
IKFAST_API void ComputeFk(const IkReal *j, IkReal *eetrans, IkReal *eerot)
Rotation M
void setSearchDiscretization(const std::map< int, double > &discretization)
Sets the discretization value for the redundant joint.
#define ROS_DEBUG_NAMED(name,...)
unsigned int index
#define ROS_WARN_STREAM_ONCE_NAMED(name, args)
virtual const std::string & getTipFrame() const
#define ROS_FATAL_STREAM_NAMED(name, args)
ray on end effector coordinate system reaches desired global ray
bool searchParam(const std::string &key, std::string &result) const
bool param(const std::string &param_name, T &param_val, const T &default_val) const
double data[3]
void poseMsgToKDL(const geometry_msgs::Pose &m, KDL::Frame &k)
double harmonize(const std::vector< double > &ik_seed_state, std::vector< double > &solution) const
direction on end effector coordinate system points to desired 3D position
DiscretizationMethod discretization_method
std::vector< DiscretizationMethod > supported_methods_
bool getCount(int &count, const int &max_count, const int &min_count) 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)
bit is set if the data represents the time-derivate velocity of an IkParameterization ...
boost::function< void(const geometry_msgs::Pose &ik_pose, const std::vector< double > &ik_solution, moveit_msgs::MoveItErrorCodes &error_code)> IKCallbackFn
IkParameterizationType
The types of inverse kinematics parameterizations supported.
std::map< int, double > redundant_joint_discretization_
virtual void GetSolution(T *solution, const T *freevalues) const =0
gets a concrete solution
bool setRedundantJoints(const std::vector< unsigned int > &redundant_joint_indices)
Overrides the default method to prevent changing the redundant joints.
static const double DEFAULT_SEARCH_DISCRETIZATION
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)
int solve(KDL::Frame &pose_frame, const std::vector< double > &vfree, IkSolutionList< IkReal > &solutions) const
Calls the IK solver from IKFast.
void poseKDLToMsg(const KDL::Frame &k, geometry_msgs::Pose &m)
void getClosestSolution(const IkSolutionList< IkReal > &solutions, const std::vector< double > &ik_seed_state, std::vector< double > &solution) const
bool sampleRedundantJoint(kinematics::DiscretizationMethod method, std::vector< double > &sampled_joint_vals) const
samples the designated redundant joint using the chosen discretization method
Default implementation of IkSolutionListBase.
Definition: ikfast.h:273
bool getParam(const std::string &key, std::string &s) const
IKFAST_API bool ComputeIk(const IkReal *eetrans, const IkReal *eerot, const IkReal *pfree, IkSolutionListBase< IkReal > &solutions)
#define ROS_FATAL_NAMED(name,...)
#define ROS_ERROR_NAMED(name,...)
static Time now()
#define ROS_ERROR_STREAM(args)
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...
r
#define ROS_ERROR(...)
direction on end effector coordinate system reaches desired direction
#define ROS_WARN_STREAM_NAMED(name, args)
double data[9]


katana_moveit_ikfast_plugin
Author(s): Martin Günther
autogenerated on Fri Jun 7 2019 22:06:30