prbt_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 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 <tf2_kdl/tf2_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,
134  IKP_UniqueIdMask = 0x0000ffff,
135  IKP_CustomDataBit = 0x00010000,
136 };
138 
139 // struct for storing and sorting solutions
141 {
142  std::vector<double> value;
144 
145  bool operator<(const LimitObeyingSol& a) const
146  {
147  return dist_from_seed < a.dist_from_seed;
148  }
149 };
150 
151 // Code generated by IKFast56/61
153 
155 {
156  std::vector<std::string> joint_names_;
157  std::vector<double> joint_min_vector_;
158  std::vector<double> joint_max_vector_;
159  std::vector<bool> joint_has_limits_vector_;
160  std::vector<std::string> link_names_;
161  const size_t num_joints_;
162  std::vector<int> free_params_;
163  bool active_; // Internal variable that indicates whether solvers are configured and ready
164  const std::string name_{ "ikfast" };
165 
166  const std::vector<std::string>& getJointNames() const
167  {
168  return joint_names_;
169  }
170  const std::vector<std::string>& getLinkNames() const
171  {
172  return link_names_;
173  }
175 public:
179  IKFastKinematicsPlugin() : num_joints_(GetNumJoints()), active_(false)
180  {
181  srand(time(NULL));
182  supported_methods_.push_back(kinematics::DiscretizationMethods::NO_DISCRETIZATION);
183  supported_methods_.push_back(kinematics::DiscretizationMethods::ALL_DISCRETIZED);
185  }
186 
196  // Returns the IK solution that is within joint limits closest to ik_seed_state
197  bool getPositionIK(const geometry_msgs::Pose& ik_pose, const std::vector<double>& ik_seed_state,
198  std::vector<double>& solution, moveit_msgs::MoveItErrorCodes& error_code,
200 
216  bool getPositionIK(const std::vector<geometry_msgs::Pose>& ik_poses, const std::vector<double>& ik_seed_state,
217  std::vector<std::vector<double>>& solutions, kinematics::KinematicsResult& result,
218  const kinematics::KinematicsQueryOptions& options) const;
219 
228  bool searchPositionIK(const geometry_msgs::Pose& ik_pose, const std::vector<double>& ik_seed_state, double timeout,
229  std::vector<double>& solution, moveit_msgs::MoveItErrorCodes& error_code,
231 
241  bool searchPositionIK(const geometry_msgs::Pose& ik_pose, const std::vector<double>& ik_seed_state, double timeout,
242  const std::vector<double>& consistency_limits, std::vector<double>& solution,
243  moveit_msgs::MoveItErrorCodes& error_code,
245 
254  bool searchPositionIK(const geometry_msgs::Pose& ik_pose, const std::vector<double>& ik_seed_state, double timeout,
255  std::vector<double>& solution, const IKCallbackFn& solution_callback,
256  moveit_msgs::MoveItErrorCodes& error_code,
258 
269  bool searchPositionIK(const geometry_msgs::Pose& ik_pose, const std::vector<double>& ik_seed_state, double timeout,
270  const std::vector<double>& consistency_limits, std::vector<double>& solution,
271  const IKCallbackFn& solution_callback, moveit_msgs::MoveItErrorCodes& error_code,
273 
282  bool getPositionFK(const std::vector<std::string>& link_names, const std::vector<double>& joint_angles,
283  std::vector<geometry_msgs::Pose>& poses) const;
284 
294  void setSearchDiscretization(const std::map<unsigned int, double>& discretization);
295 
299  bool setRedundantJoints(const std::vector<unsigned int>& redundant_joint_indices);
300 
301 private:
302  bool initialize(const std::string& robot_description, const std::string& group_name, const std::string& base_name,
303  const std::vector<std::string>& tip_names, double search_discretization);
305  bool initialize(const std::string& robot_description, const std::string& group_name, const std::string& base_name,
306  const std::string& tip_name, double search_discretization);
307 
312  unsigned int solve(KDL::Frame& pose_frame, const std::vector<double>& vfree, IkSolutionList<IkReal>& solutions) const;
313 
317  void getSolution(const IkSolutionList<IkReal>& solutions, int i, std::vector<double>& solution) const;
318 
322  void getSolution(const IkSolutionList<IkReal>& solutions, const std::vector<double>& ik_seed_state, int i,
323  std::vector<double>& solution) const;
324 
325  double harmonize(const std::vector<double>& ik_seed_state, std::vector<double>& solution) const;
326  // void getOrderedSolutions(const std::vector<double> &ik_seed_state, std::vector<std::vector<double> >& solslist);
327  void getClosestSolution(const IkSolutionList<IkReal>& solutions, const std::vector<double>& ik_seed_state,
328  std::vector<double>& solution) const;
329  void fillFreeParams(int count, int* array);
330  bool getCount(int& count, const int& max_count, const int& min_count) const;
331 
338  bool sampleRedundantJoint(kinematics::DiscretizationMethod method, std::vector<double>& sampled_joint_vals) const;
339 
340 }; // end class
341 
342 bool IKFastKinematicsPlugin::initialize(const std::string& robot_description, const std::string& group_name,
343  const std::string& base_name, const std::string& tip_name,
344  double search_discretization)
345 {
346 
347  std::vector<std::string> tipnames {tip_name};
348  return initialize(robot_description, group_name, base_name, tipnames, search_discretization);
349 }
350 
351 bool IKFastKinematicsPlugin::initialize(const std::string& robot_description, const std::string& group_name,
352  const std::string& base_name, const std::vector<std::string>& tip_names,
353  double search_discretization)
354 {
355  setValues(robot_description, group_name, base_name, tip_names, search_discretization);
356 
357  ros::NodeHandle node_handle("~/" + group_name);
358 
359  std::string robot;
360  lookupParam("robot", robot, std::string());
361 
362  // IKFast56/61
363  fillFreeParams(GetNumFreeParameters(), GetFreeParameters());
364 
365  if (free_params_.size() > 1)
366  {
367  ROS_FATAL("Only one free joint parameter supported!");
368  return false;
369  }
370  else if (free_params_.size() == 1)
371  {
372  redundant_joint_indices_.clear();
373  redundant_joint_indices_.push_back(free_params_[0]);
374  KinematicsBase::setSearchDiscretization(DEFAULT_SEARCH_DISCRETIZATION);
375  }
376 
377  urdf::Model robot_model;
378  std::string xml_string;
380  std::string urdf_xml, full_urdf_xml;
381  lookupParam("urdf_xml", urdf_xml, robot_description);
382  node_handle.searchParam(urdf_xml, full_urdf_xml);
384  ROS_DEBUG_NAMED(name_, "Reading xml file from parameter server");
385  if (!node_handle.getParam(full_urdf_xml, xml_string))
386  {
387  ROS_FATAL_NAMED(name_, "Could not load the xml from parameter server: %s", urdf_xml.c_str());
388  return false;
389  }
390 
391  robot_model.initString(xml_string);
392 
393  ROS_DEBUG_STREAM_NAMED(name_, "Reading joints and links from URDF");
394 
395  urdf::LinkConstSharedPtr link = robot_model.getLink(getTipFrame());
396  while (link->name != base_frame_ && joint_names_.size() <= num_joints_)
397  {
398  ROS_DEBUG_NAMED(name_, "Link %s", link->name.c_str());
399  link_names_.push_back(link->name);
400  urdf::JointSharedPtr joint = link->parent_joint;
401  if (joint)
402  {
403  if (joint->type != urdf::Joint::UNKNOWN && joint->type != urdf::Joint::FIXED)
404  {
405  ROS_DEBUG_STREAM_NAMED(name_, "Adding joint " << joint->name);
406 
407  joint_names_.push_back(joint->name);
408  float lower, upper;
409  int hasLimits;
410  if (joint->type != urdf::Joint::CONTINUOUS)
411  {
412  if (joint->safety)
413  {
414  lower = joint->safety->soft_lower_limit;
415  upper = joint->safety->soft_upper_limit;
416  }
417  else
418  {
419  lower = joint->limits->lower;
420  upper = joint->limits->upper;
421  }
422  hasLimits = 1;
423  }
424  else
425  {
426  lower = -M_PI;
427  upper = M_PI;
428  hasLimits = 0;
429  }
430  if (hasLimits)
431  {
432  joint_has_limits_vector_.push_back(true);
433  joint_min_vector_.push_back(lower);
434  joint_max_vector_.push_back(upper);
435  }
436  else
437  {
438  joint_has_limits_vector_.push_back(false);
439  joint_min_vector_.push_back(-M_PI);
440  joint_max_vector_.push_back(M_PI);
441  }
442  }
443  }
444  else
445  {
446  ROS_WARN_NAMED(name_, "no joint corresponding to %s", link->name.c_str());
447  }
448  link = link->getParent();
449  }
450 
451  if (joint_names_.size() != num_joints_)
452  {
453  ROS_FATAL_STREAM_NAMED(name_, "Joint numbers mismatch: URDF has " << joint_names_.size() << " and IKFast has "
454  << num_joints_);
455  return false;
456  }
457 
458  std::reverse(link_names_.begin(), link_names_.end());
459  std::reverse(joint_names_.begin(), joint_names_.end());
460  std::reverse(joint_min_vector_.begin(), joint_min_vector_.end());
461  std::reverse(joint_max_vector_.begin(), joint_max_vector_.end());
462  std::reverse(joint_has_limits_vector_.begin(), joint_has_limits_vector_.end());
463 
464  for (size_t i = 0; i < num_joints_; ++i)
465  ROS_DEBUG_STREAM_NAMED(name_, joint_names_[i] << " " << joint_min_vector_[i] << " " << joint_max_vector_[i] << " "
466  << joint_has_limits_vector_[i]);
467 
468  active_ = true;
469  return true;
470 }
471 
472 void IKFastKinematicsPlugin::setSearchDiscretization(const std::map<unsigned int, double>& discretization)
473 {
474  if (discretization.empty())
475  {
476  ROS_ERROR("The 'discretization' map is empty");
477  return;
478  }
479 
480  if (redundant_joint_indices_.empty())
481  {
482  ROS_ERROR_STREAM("This group's solver doesn't support redundant joints");
483  return;
484  }
485 
486  if (discretization.begin()->first != redundant_joint_indices_[0])
487  {
488  std::string redundant_joint = joint_names_[free_params_[0]];
489  ROS_ERROR_STREAM("Attempted to discretize a non-redundant joint "
490  << discretization.begin()->first << ", only joint '" << redundant_joint << "' with index "
491  << redundant_joint_indices_[0] << " is redundant.");
492  return;
493  }
494 
495  if (discretization.begin()->second <= 0.0)
496  {
497  ROS_ERROR_STREAM("Discretization can not takes values that are <= 0");
498  return;
499  }
500 
501  redundant_joint_discretization_.clear();
502  redundant_joint_discretization_[redundant_joint_indices_[0]] = discretization.begin()->second;
503 }
504 
505 bool IKFastKinematicsPlugin::setRedundantJoints(const std::vector<unsigned int>& redundant_joint_indices)
506 {
507  ROS_ERROR_STREAM("Changing the redundant joints isn't permitted by this group's solver ");
508  return false;
509 }
510 
511 unsigned int IKFastKinematicsPlugin::solve(KDL::Frame& pose_frame, const std::vector<double>& vfree,
512  IkSolutionList<IkReal>& solutions) const
513 {
514  // IKFast56/61
515  solutions.Clear();
516 
517  double trans[3];
518  trans[0] = pose_frame.p[0]; //-.18;
519  trans[1] = pose_frame.p[1];
520  trans[2] = pose_frame.p[2];
521 
522  KDL::Rotation mult;
523  KDL::Vector direction;
524 
525  switch (GetIkType())
526  {
527  case IKP_Transform6D:
528  case IKP_Translation3D:
529  // For **Transform6D**, eerot is 9 values for the 3x3 rotation matrix. For **Translation3D**, these are ignored.
530 
531  mult = pose_frame.M;
532 
533  double vals[9];
534  vals[0] = mult(0, 0);
535  vals[1] = mult(0, 1);
536  vals[2] = mult(0, 2);
537  vals[3] = mult(1, 0);
538  vals[4] = mult(1, 1);
539  vals[5] = mult(1, 2);
540  vals[6] = mult(2, 0);
541  vals[7] = mult(2, 1);
542  vals[8] = mult(2, 2);
543 
544  // IKFast56/61
545  ComputeIk(trans, vals, vfree.size() > 0 ? &vfree[0] : NULL, solutions);
546  return solutions.GetNumSolutions();
547 
548  case IKP_Direction3D:
549  case IKP_Ray4D:
551  // For **Direction3D**, **Ray4D**, and **TranslationDirection5D**, the first 3 values represent the target
552  // direction.
553 
554  direction = pose_frame.M * KDL::Vector(0, 0, 1);
555  ComputeIk(trans, direction.data, vfree.size() > 0 ? &vfree[0] : NULL, solutions);
556  return solutions.GetNumSolutions();
557 
561  // For *TranslationXAxisAngle4D*, *TranslationYAxisAngle4D*, *TranslationZAxisAngle4D* - end effector origin
562  // reaches desired 3D translation, manipulator direction makes a specific angle with x/y/z-axis (defined in the
563  // manipulator base link’s coordinate system)
564  ROS_ERROR_NAMED(name_, "IK for this IkParameterizationType not implemented yet.");
565  return 0;
566 
568  // For **TranslationLocalGlobal6D**, the diagonal elements ([0],[4],[8]) are the local translation inside the end
569  // effector coordinate system.
570  ROS_ERROR_NAMED(name_, "IK for this IkParameterizationType not implemented yet.");
571  return 0;
572 
573  case IKP_Rotation3D:
574  case IKP_Lookat3D:
575  case IKP_TranslationXY2D:
577  ROS_ERROR_NAMED(name_, "IK for this IkParameterizationType not implemented yet.");
578  return 0;
579 
581  double roll, pitch, yaw;
582  // For **TranslationXAxisAngleZNorm4D** - end effector origin reaches desired 3D translation, manipulator
583  // direction needs to be orthogonal to z axis and be rotated at a certain angle starting from the x axis (defined
584  // in the manipulator base link’s coordinate system)
585  pose_frame.M.GetRPY(roll, pitch, yaw);
586  ComputeIk(trans, &yaw, vfree.size() > 0 ? &vfree[0] : NULL, solutions);
587  return solutions.GetNumSolutions();
588 
590  // For **TranslationYAxisAngleXNorm4D** - end effector origin reaches desired 3D translation, manipulator
591  // direction needs to be orthogonal to x axis and be rotated at a certain angle starting from the y axis (defined
592  // in the manipulator base link’s coordinate system)
593  pose_frame.M.GetRPY(roll, pitch, yaw);
594  ComputeIk(trans, &roll, vfree.size() > 0 ? &vfree[0] : NULL, solutions);
595  return solutions.GetNumSolutions();
596 
598  // For **TranslationZAxisAngleYNorm4D** - end effector origin reaches desired 3D translation, manipulator
599  // direction needs to be orthogonal to y axis and be rotated at a certain angle starting from the z axis (defined
600  // in the manipulator base link’s coordinate system)
601  pose_frame.M.GetRPY(roll, pitch, yaw);
602  ComputeIk(trans, &pitch, vfree.size() > 0 ? &vfree[0] : NULL, solutions);
603  return solutions.GetNumSolutions();
604 
605  default:
606  ROS_ERROR_NAMED(name_, "Unknown IkParameterizationType! "
607  "Was the solver generated with an incompatible version of Openrave?");
608  return 0;
609  }
610 }
611 
613  std::vector<double>& solution) const
614 {
615  solution.clear();
616  solution.resize(num_joints_);
617 
618  // IKFast56/61
619  const IkSolutionBase<IkReal>& sol = solutions.GetSolution(i);
620  std::vector<IkReal> vsolfree(sol.GetFree().size());
621  sol.GetSolution(&solution[0], vsolfree.size() > 0 ? &vsolfree[0] : NULL);
622 
623  // std::cout << "solution " << i << ":" ;
624  // for(int j=0;j<num_joints_; ++j)
625  // std::cout << " " << solution[j];
626  // std::cout << std::endl;
627 
628  // ROS_ERROR("%f %d",solution[2],vsolfree.size());
629 }
630 
632  const std::vector<double>& ik_seed_state, int i,
633  std::vector<double>& solution) const
634 {
635  solution.clear();
636  solution.resize(num_joints_);
637 
638  // IKFast56/61
639  const IkSolutionBase<IkReal>& sol = solutions.GetSolution(i);
640  std::vector<IkReal> vsolfree(sol.GetFree().size());
641  sol.GetSolution(&solution[0], vsolfree.size() > 0 ? &vsolfree[0] : NULL);
642 
643  // rotate joints by +/-360° where it is possible and useful
644  for (std::size_t i = 0; i < num_joints_; ++i)
645  {
646  if (joint_has_limits_vector_[i])
647  {
648  double signed_distance = solution[i] - ik_seed_state[i];
649  while (signed_distance > M_PI && solution[i] - 2 * M_PI > (joint_min_vector_[i] - LIMIT_TOLERANCE))
650  {
651  signed_distance -= 2 * M_PI;
652  solution[i] -= 2 * M_PI;
653  }
654  while (signed_distance < -M_PI && solution[i] + 2 * M_PI < (joint_max_vector_[i] + LIMIT_TOLERANCE))
655  {
656  signed_distance += 2 * M_PI;
657  solution[i] += 2 * M_PI;
658  }
659  }
660  }
661 }
662 
663 double IKFastKinematicsPlugin::harmonize(const std::vector<double>& ik_seed_state, std::vector<double>& solution) const
664 {
665  double dist_sqr = 0;
666  std::vector<double> ss = ik_seed_state;
667  for (size_t i = 0; i < ik_seed_state.size(); ++i)
668  {
669  while (ss[i] > 2 * M_PI)
670  {
671  ss[i] -= 2 * M_PI;
672  }
673  while (ss[i] < 2 * M_PI)
674  {
675  ss[i] += 2 * M_PI;
676  }
677  while (solution[i] > 2 * M_PI)
678  {
679  solution[i] -= 2 * M_PI;
680  }
681  while (solution[i] < 2 * M_PI)
682  {
683  solution[i] += 2 * M_PI;
684  }
685  dist_sqr += fabs(ik_seed_state[i] - solution[i]);
686  }
687  return dist_sqr;
688 }
689 
690 // void IKFastKinematicsPlugin::getOrderedSolutions(const std::vector<double> &ik_seed_state,
691 // std::vector<std::vector<double> >& solslist)
692 // {
693 // std::vector<double>
694 // double mindist = 0;
695 // int minindex = -1;
696 // std::vector<double> sol;
697 // for(size_t i=0;i<solslist.size();++i){
698 // getSolution(i,sol);
699 // double dist = harmonize(ik_seed_state, sol);
700 // //std::cout << "dist[" << i << "]= " << dist << std::endl;
701 // if(minindex == -1 || dist<mindist){
702 // minindex = i;
703 // mindist = dist;
704 // }
705 // }
706 // if(minindex >= 0){
707 // getSolution(minindex,solution);
708 // harmonize(ik_seed_state, solution);
709 // index = minindex;
710 // }
711 // }
712 
714  const std::vector<double>& ik_seed_state,
715  std::vector<double>& solution) const
716 {
717  double mindist = DBL_MAX;
718  int minindex = -1;
719  std::vector<double> sol;
720 
721  // IKFast56/61
722  for (size_t i = 0; i < solutions.GetNumSolutions(); ++i)
723  {
724  getSolution(solutions, i, sol);
725  double dist = harmonize(ik_seed_state, sol);
726  ROS_INFO_STREAM_NAMED(name_, "Dist " << i << " dist " << dist);
727  // std::cout << "dist[" << i << "]= " << dist << std::endl;
728  if (minindex == -1 || dist < mindist)
729  {
730  minindex = i;
731  mindist = dist;
732  }
733  }
734  if (minindex >= 0)
735  {
736  getSolution(solutions, minindex, solution);
737  harmonize(ik_seed_state, solution);
738  }
739 }
740 
741 void IKFastKinematicsPlugin::fillFreeParams(int count, int* array)
742 {
743  free_params_.clear();
744  for (int i = 0; i < count; ++i)
745  free_params_.push_back(array[i]);
746 }
747 
748 bool IKFastKinematicsPlugin::getCount(int& count, const int& max_count, const int& min_count) const
749 {
750  if (count > 0)
751  {
752  if (-count >= min_count)
753  {
754  count = -count;
755  return true;
756  }
757  else if (count + 1 <= max_count)
758  {
759  count = count + 1;
760  return true;
761  }
762  else
763  {
764  return false;
765  }
766  }
767  else
768  {
769  if (1 - count <= max_count)
770  {
771  count = 1 - count;
772  return true;
773  }
774  else if (count - 1 >= min_count)
775  {
776  count = count - 1;
777  return true;
778  }
779  else
780  return false;
781  }
782 }
783 
784 bool IKFastKinematicsPlugin::getPositionFK(const std::vector<std::string>& link_names,
785  const std::vector<double>& joint_angles,
786  std::vector<geometry_msgs::Pose>& poses) const
787 {
788  if (GetIkType() != IKP_Transform6D)
789  {
790  // ComputeFk() is the inverse function of ComputeIk(), so the format of
791  // eerot differs depending on IK type. The Transform6D IK type is the only
792  // one for which a 3x3 rotation matrix is returned, which means we can only
793  // compute FK for that IK type.
794  ROS_ERROR_NAMED(name_, "Can only compute FK for Transform6D IK type!");
795  return false;
796  }
797 
798  KDL::Frame p_out;
799  if (link_names.size() == 0)
800  {
801  ROS_WARN_STREAM_NAMED(name_, "Link names with nothing");
802  return false;
803  }
804 
805  if (link_names.size() != 1 || link_names[0] != getTipFrame())
806  {
807  ROS_ERROR_NAMED(name_, "Can compute FK for %s only", getTipFrame().c_str());
808  return false;
809  }
810 
811  bool valid = true;
812 
813  IkReal eerot[9], eetrans[3];
814 
815  if (joint_angles.size() != num_joints_)
816  {
817  ROS_ERROR_NAMED(name_, "Unexpected number of joint angles");
818  return false;
819  }
820 
821  IkReal angles[num_joints_];
822  for (unsigned char i = 0; i < num_joints_; i++)
823  angles[i] = joint_angles[i];
824 
825  // IKFast56/61
826  ComputeFk(angles, eetrans, eerot);
827 
828  for (int i = 0; i < 3; ++i)
829  p_out.p.data[i] = eetrans[i];
830 
831  for (int i = 0; i < 9; ++i)
832  p_out.M.data[i] = eerot[i];
833 
834  poses.resize(1);
835  poses[0] = tf2::toMsg(p_out);
836 
837  return valid;
838 }
839 
840 bool IKFastKinematicsPlugin::searchPositionIK(const geometry_msgs::Pose& ik_pose,
841  const std::vector<double>& ik_seed_state, double timeout,
842  std::vector<double>& solution, moveit_msgs::MoveItErrorCodes& error_code,
843  const kinematics::KinematicsQueryOptions& options) const
844 {
845  const IKCallbackFn solution_callback = 0;
846  std::vector<double> consistency_limits;
847 
848  return searchPositionIK(ik_pose, ik_seed_state, timeout, consistency_limits, solution, solution_callback, error_code,
849  options);
850 }
851 
852 bool IKFastKinematicsPlugin::searchPositionIK(const geometry_msgs::Pose& ik_pose,
853  const std::vector<double>& ik_seed_state, double timeout,
854  const std::vector<double>& consistency_limits,
855  std::vector<double>& solution, moveit_msgs::MoveItErrorCodes& error_code,
856  const kinematics::KinematicsQueryOptions& options) const
857 {
858  const IKCallbackFn solution_callback = 0;
859  return searchPositionIK(ik_pose, ik_seed_state, timeout, consistency_limits, solution, solution_callback, error_code,
860  options);
861 }
862 
863 bool IKFastKinematicsPlugin::searchPositionIK(const geometry_msgs::Pose& ik_pose,
864  const std::vector<double>& ik_seed_state, double timeout,
865  std::vector<double>& solution, const IKCallbackFn& solution_callback,
866  moveit_msgs::MoveItErrorCodes& error_code,
867  const kinematics::KinematicsQueryOptions& options) const
868 {
869  std::vector<double> consistency_limits;
870  return searchPositionIK(ik_pose, ik_seed_state, timeout, consistency_limits, solution, solution_callback, error_code,
871  options);
872 }
873 
874 bool IKFastKinematicsPlugin::searchPositionIK(const geometry_msgs::Pose& ik_pose,
875  const std::vector<double>& ik_seed_state, double /*timeout*/,
876  const std::vector<double>& consistency_limits,
877  std::vector<double>& solution, const IKCallbackFn& solution_callback,
878  moveit_msgs::MoveItErrorCodes& error_code,
879  const kinematics::KinematicsQueryOptions& options) const
880 {
881  ROS_DEBUG_STREAM_NAMED(name_, "searchPositionIK");
882 
884  SEARCH_MODE search_mode = OPTIMIZE_MAX_JOINT;
885 
886  // Check if there are no redundant joints
887  if (free_params_.size() == 0)
888  {
889  ROS_DEBUG_STREAM_NAMED(name_, "No need to search since no free params/redundant joints");
890 
891  std::vector<geometry_msgs::Pose> ik_poses(1, ik_pose);
892  std::vector<std::vector<double>> solutions;
893  kinematics::KinematicsResult kinematic_result;
894  // Find all IK solution within joint limits
895  if (!getPositionIK(ik_poses, ik_seed_state, solutions, kinematic_result, options))
896  {
897  ROS_DEBUG_STREAM_NAMED(name_, "No solution whatsoever");
898  error_code.val = moveit_msgs::MoveItErrorCodes::NO_IK_SOLUTION;
899  return false;
900  }
901 
902  // sort solutions by their distance to the seed
903  std::vector<LimitObeyingSol> solutions_obey_limits;
904  for (std::size_t i = 0; i < solutions.size(); ++i)
905  {
906  double dist_from_seed = 0.0;
907  for (std::size_t j = 0; j < ik_seed_state.size(); ++j)
908  {
909  dist_from_seed += fabs(ik_seed_state[j] - solutions[i][j]);
910  }
911 
912  solutions_obey_limits.push_back({ solutions[i], dist_from_seed });
913  }
914  std::sort(solutions_obey_limits.begin(), solutions_obey_limits.end());
915 
916  // check for collisions if a callback is provided
917  if (!solution_callback.empty())
918  {
919  for (std::size_t i = 0; i < solutions_obey_limits.size(); ++i)
920  {
921  solution_callback(ik_pose, solutions_obey_limits[i].value, error_code);
922  if (error_code.val == moveit_msgs::MoveItErrorCodes::SUCCESS)
923  {
924  solution = solutions_obey_limits[i].value;
925  ROS_DEBUG_STREAM_NAMED(name_, "Solution passes callback");
926  return true;
927  }
928  }
929 
930  ROS_DEBUG_STREAM_NAMED(name_, "Solution has error code " << error_code);
931  return false;
932  }
933  else
934  {
935  solution = solutions_obey_limits[0].value;
936  error_code.val = moveit_msgs::MoveItErrorCodes::SUCCESS;
937  return true; // no collision check callback provided
938  }
939  }
940 
941  // -------------------------------------------------------------------------------------------------
942  // Error Checking
943  if (!active_)
944  {
945  ROS_ERROR_STREAM_NAMED(name_, "Kinematics not active");
946  error_code.val = error_code.NO_IK_SOLUTION;
947  return false;
948  }
949 
950  if (ik_seed_state.size() != num_joints_)
951  {
952  ROS_ERROR_STREAM_NAMED(name_, "Seed state must have size " << num_joints_ << " instead of size "
953  << ik_seed_state.size());
954  error_code.val = error_code.NO_IK_SOLUTION;
955  return false;
956  }
957 
958  if (!consistency_limits.empty() && consistency_limits.size() != num_joints_)
959  {
960  ROS_ERROR_STREAM_NAMED(name_, "Consistency limits be empty or must have size " << num_joints_ << " instead of size "
961  << consistency_limits.size());
962  error_code.val = error_code.NO_IK_SOLUTION;
963  return false;
964  }
965 
966  // -------------------------------------------------------------------------------------------------
967  // Initialize
968 
969  KDL::Frame frame;
970  tf2::fromMsg(ik_pose, frame);
971 
972  std::vector<double> vfree(free_params_.size());
973 
974  int counter = 0;
975 
976  double initial_guess = ik_seed_state[free_params_[0]];
977  vfree[0] = initial_guess;
978 
979  // -------------------------------------------------------------------------------------------------
980  // Handle consitency limits if needed
981  int num_positive_increments;
982  int num_negative_increments;
983 
984  if (!consistency_limits.empty())
985  {
986  // MoveIt! replaced consistency_limit (scalar) w/ consistency_limits (vector)
987  // Assume [0]th free_params element for now. Probably wrong.
988  double max_limit = fmin(joint_max_vector_[free_params_[0]], initial_guess + consistency_limits[free_params_[0]]);
989  double min_limit = fmax(joint_min_vector_[free_params_[0]], initial_guess - consistency_limits[free_params_[0]]);
990 
991  num_positive_increments = (int)((max_limit - initial_guess) / redundant_joint_discretization_.at(0));
992  num_negative_increments = (int)((initial_guess - min_limit) / redundant_joint_discretization_.at(0));
993  }
994  else // no consitency limits provided
995  {
996  num_positive_increments = (joint_max_vector_[free_params_[0]] - initial_guess)
997  / redundant_joint_discretization_.at(0);
998  num_negative_increments = (initial_guess - joint_min_vector_[free_params_[0]])
999  / redundant_joint_discretization_.at(0);
1000  }
1001 
1002  // -------------------------------------------------------------------------------------------------
1003  // Begin searching
1004 
1005  ROS_DEBUG_STREAM_NAMED(name_, "Free param is " << free_params_[0] << " initial guess is " << initial_guess
1006  << ", # positive increments: " << num_positive_increments
1007  << ", # negative increments: " << num_negative_increments);
1008  if ((search_mode & OPTIMIZE_MAX_JOINT) && (num_positive_increments + num_negative_increments) > 1000)
1009  ROS_WARN_STREAM_ONCE_NAMED(name_, "Large search space, consider increasing the search discretization");
1010 
1011  double best_costs = -1.0;
1012  std::vector<double> best_solution;
1013  int nattempts = 0, nvalid = 0;
1014 
1015  while (true)
1016  {
1017  IkSolutionList<IkReal> solutions;
1018  unsigned int numsol = solve(frame, vfree, solutions);
1019 
1020  ROS_DEBUG_STREAM_NAMED(name_, "Found " << numsol << " solutions from IKFast");
1021 
1022  // ROS_INFO("%f",vfree[0]);
1023 
1024  if (numsol > 0)
1025  {
1026  for (unsigned int s = 0; s < numsol; ++s)
1027  {
1028  nattempts++;
1029  std::vector<double> sol;
1030  getSolution(solutions, ik_seed_state, s, sol);
1031 
1032  bool obeys_limits = true;
1033  for (unsigned int i = 0; i < sol.size(); i++)
1034  {
1035  if (joint_has_limits_vector_[i] && (sol[i] < joint_min_vector_[i] || sol[i] > joint_max_vector_[i]))
1036  {
1037  obeys_limits = false;
1038  break;
1039  }
1040  // ROS_INFO_STREAM_NAMED(name_,"Num " << i << " value " << sol[i] << " has limits " <<
1041  // joint_has_limits_vector_[i] << " " << joint_min_vector_[i] << " " << joint_max_vector_[i]);
1042  }
1043  if (obeys_limits)
1044  {
1045  getSolution(solutions, ik_seed_state, s, solution);
1046 
1047  // This solution is within joint limits, now check if in collision (if callback provided)
1048  if (!solution_callback.empty())
1049  {
1050  solution_callback(ik_pose, solution, error_code);
1051  }
1052  else
1053  {
1054  error_code.val = error_code.SUCCESS;
1055  }
1056 
1057  if (error_code.val == error_code.SUCCESS)
1058  {
1059  nvalid++;
1060  if (search_mode & OPTIMIZE_MAX_JOINT)
1061  {
1062  // Costs for solution: Largest joint motion
1063  double costs = 0.0;
1064  for (unsigned int i = 0; i < solution.size(); i++)
1065  {
1066  double d = fabs(ik_seed_state[i] - solution[i]);
1067  if (d > costs)
1068  costs = d;
1069  }
1070  if (costs < best_costs || best_costs == -1.0)
1071  {
1072  best_costs = costs;
1073  best_solution = solution;
1074  }
1075  }
1076  else
1077  // Return first feasible solution
1078  return true;
1079  }
1080  }
1081  }
1082  }
1083 
1084  if (!getCount(counter, num_positive_increments, -num_negative_increments))
1085  {
1086  // Everything searched
1087  error_code.val = moveit_msgs::MoveItErrorCodes::NO_IK_SOLUTION;
1088  break;
1089  }
1090 
1091  vfree[0] = initial_guess + redundant_joint_discretization_.at(0) * counter;
1092  // ROS_DEBUG_STREAM_NAMED(name_,"Attempt " << counter << " with 0th free joint having value " << vfree[0]);
1093  }
1094 
1095  ROS_DEBUG_STREAM_NAMED(name_, "Valid solutions: " << nvalid << "/" << nattempts);
1096 
1097  if ((search_mode & OPTIMIZE_MAX_JOINT) && best_costs != -1.0)
1098  {
1099  solution = best_solution;
1100  error_code.val = error_code.SUCCESS;
1101  return true;
1102  }
1103 
1104  // No solution found
1105  error_code.val = moveit_msgs::MoveItErrorCodes::NO_IK_SOLUTION;
1106  return false;
1107 }
1108 
1109 // Used when there are no redundant joints - aka no free params
1110 bool IKFastKinematicsPlugin::getPositionIK(const geometry_msgs::Pose& ik_pose, const std::vector<double>& ik_seed_state,
1111  std::vector<double>& solution, moveit_msgs::MoveItErrorCodes& error_code,
1112  const kinematics::KinematicsQueryOptions& /*options*/) const
1113 {
1114  ROS_DEBUG_STREAM_NAMED(name_, "getPositionIK");
1115 
1116  if (!active_)
1117  {
1118  ROS_ERROR("kinematics not active");
1119  return false;
1120  }
1121 
1122  if (ik_seed_state.size() < num_joints_)
1123  {
1124  ROS_ERROR_STREAM("ik_seed_state only has " << ik_seed_state.size() << " entries, this ikfast solver requires "
1125  << num_joints_);
1126  return false;
1127  }
1128 
1129  // Check if seed is in bound
1130  for (std::size_t i = 0; i < ik_seed_state.size(); i++)
1131  {
1132  // Add tolerance to limit check
1133  if (joint_has_limits_vector_[i] && ((ik_seed_state[i] < (joint_min_vector_[i] - LIMIT_TOLERANCE)) ||
1134  (ik_seed_state[i] > (joint_max_vector_[i] + LIMIT_TOLERANCE))))
1135  {
1136  ROS_DEBUG_STREAM_NAMED("ikseed", "Not in limits! " << (int)i << " value " << ik_seed_state[i]
1137  << " has limit: " << joint_has_limits_vector_[i] << " being "
1138  << joint_min_vector_[i] << " to " << joint_max_vector_[i]);
1139  return false;
1140  }
1141  }
1142 
1143  std::vector<double> vfree(free_params_.size());
1144  for (std::size_t i = 0; i < free_params_.size(); ++i)
1145  {
1146  int p = free_params_[i];
1147  ROS_ERROR("%u is %f", p, ik_seed_state[p]); // DTC
1148  vfree[i] = ik_seed_state[p];
1149  }
1150 
1151  KDL::Frame frame;
1152  tf2::fromMsg(ik_pose, frame);
1153 
1154  IkSolutionList<IkReal> solutions;
1155  unsigned int numsol = solve(frame, vfree, solutions);
1156  ROS_DEBUG_STREAM_NAMED(name_, "Found " << numsol << " solutions from IKFast");
1157 
1158  std::vector<LimitObeyingSol> solutions_obey_limits;
1159 
1160  if (numsol)
1161  {
1162  std::vector<double> solution_obey_limits;
1163  for (std::size_t s = 0; s < numsol; ++s)
1164  {
1165  std::vector<double> sol;
1166  getSolution(solutions, ik_seed_state, s, sol);
1167  ROS_DEBUG_NAMED(name_, "Sol %d: %e %e %e %e %e %e", (int)s, sol[0], sol[1], sol[2], sol[3], sol[4],
1168  sol[5]);
1169 
1170  bool obeys_limits = true;
1171  for (std::size_t i = 0; i < sol.size(); i++)
1172  {
1173  // Add tolerance to limit check
1174  if (joint_has_limits_vector_[i] && ((sol[i] < (joint_min_vector_[i] - LIMIT_TOLERANCE)) ||
1175  (sol[i] > (joint_max_vector_[i] + LIMIT_TOLERANCE))))
1176  {
1177  // One element of solution is not within limits
1178  obeys_limits = false;
1179  ROS_DEBUG_STREAM_NAMED(name_, "Not in limits! " << (int)i << " value " << sol[i] << " has limit: "
1180  << joint_has_limits_vector_[i] << " being "
1181  << joint_min_vector_[i] << " to " << joint_max_vector_[i]);
1182  break;
1183  }
1184  }
1185  if (obeys_limits)
1186  {
1187  // All elements of this solution obey limits
1188  getSolution(solutions, ik_seed_state, s, solution_obey_limits);
1189  double dist_from_seed = 0.0;
1190  for (std::size_t i = 0; i < ik_seed_state.size(); ++i)
1191  {
1192  dist_from_seed += fabs(ik_seed_state[i] - solution_obey_limits[i]);
1193  }
1194 
1195  solutions_obey_limits.push_back({ solution_obey_limits, dist_from_seed });
1196  }
1197  }
1198  }
1199  else
1200  {
1201  ROS_DEBUG_STREAM_NAMED(name_, "No IK solution");
1202  }
1203 
1204  // Sort the solutions under limits and find the one that is closest to ik_seed_state
1205  if (!solutions_obey_limits.empty())
1206  {
1207  std::sort(solutions_obey_limits.begin(), solutions_obey_limits.end());
1208  solution = solutions_obey_limits[0].value;
1209  error_code.val = moveit_msgs::MoveItErrorCodes::SUCCESS;
1210  return true;
1211  }
1212 
1213  error_code.val = moveit_msgs::MoveItErrorCodes::NO_IK_SOLUTION;
1214  return false;
1215 }
1216 
1217 bool IKFastKinematicsPlugin::getPositionIK(const std::vector<geometry_msgs::Pose>& ik_poses,
1218  const std::vector<double>& ik_seed_state,
1219  std::vector<std::vector<double>>& solutions,
1221  const kinematics::KinematicsQueryOptions& options) const
1222 {
1223  ROS_DEBUG_STREAM_NAMED(name_, "getPositionIK with multiple solutions");
1224 
1225  if (!active_)
1226  {
1227  ROS_ERROR("kinematics not active");
1229  return false;
1230  }
1231 
1232  if (ik_poses.empty())
1233  {
1234  ROS_ERROR("ik_poses is empty");
1236  return false;
1237  }
1238 
1239  if (ik_poses.size() > 1)
1240  {
1241  ROS_ERROR("ik_poses contains multiple entries, only one is allowed");
1243  return false;
1244  }
1245 
1246  if (ik_seed_state.size() < num_joints_)
1247  {
1248  ROS_ERROR_STREAM("ik_seed_state only has " << ik_seed_state.size() << " entries, this ikfast solver requires "
1249  << num_joints_);
1250  return false;
1251  }
1252 
1253  KDL::Frame frame;
1254  tf2::fromMsg(ik_poses[0], frame);
1255 
1256  // solving ik
1257  std::vector<IkSolutionList<IkReal>> solution_set;
1258  IkSolutionList<IkReal> ik_solutions;
1259  std::vector<double> vfree;
1260  unsigned int numsol = 0;
1261  std::vector<double> sampled_joint_vals;
1262  if (!redundant_joint_indices_.empty())
1263  {
1264  // initializing from seed
1265  sampled_joint_vals.push_back(ik_seed_state[redundant_joint_indices_[0]]);
1266 
1267  // checking joint limits when using no discretization
1269  joint_has_limits_vector_[redundant_joint_indices_.front()])
1270  {
1271  double joint_min = joint_min_vector_[redundant_joint_indices_.front()];
1272  double joint_max = joint_max_vector_[redundant_joint_indices_.front()];
1273 
1274  double jv = sampled_joint_vals[0];
1275  if (!((jv > (joint_min - LIMIT_TOLERANCE)) && (jv < (joint_max + LIMIT_TOLERANCE))))
1276  {
1278  ROS_ERROR_STREAM("ik seed is out of bounds");
1279  return false;
1280  }
1281  }
1282 
1283  // computing all solutions sets for each sampled value of the redundant joint
1284  if (!sampleRedundantJoint(options.discretization_method, sampled_joint_vals))
1285  {
1287  return false;
1288  }
1289 
1290  for (unsigned int i = 0; i < sampled_joint_vals.size(); i++)
1291  {
1292  vfree.clear();
1293  vfree.push_back(sampled_joint_vals[i]);
1294  numsol += solve(frame, vfree, ik_solutions);
1295  solution_set.push_back(ik_solutions);
1296  }
1297  }
1298  else
1299  {
1300  // computing for single solution set
1301  numsol = solve(frame, vfree, ik_solutions);
1302  solution_set.push_back(ik_solutions);
1303  }
1304 
1305  ROS_DEBUG_STREAM_NAMED(name_, "Found " << numsol << " solutions from IKFast");
1306  bool solutions_found = false;
1307  if (numsol > 0)
1308  {
1309  /*
1310  Iterating through all solution sets and storing those that do not exceed joint limits.
1311  */
1312  for (unsigned int r = 0; r < solution_set.size(); r++)
1313  {
1314  ik_solutions = solution_set[r];
1315  numsol = ik_solutions.GetNumSolutions();
1316  for (unsigned int s = 0; s < numsol; ++s)
1317  {
1318  std::vector<double> sol;
1319  getSolution(ik_solutions, ik_seed_state, s, sol);
1320 
1321  bool obeys_limits = true;
1322  for (unsigned int i = 0; i < sol.size(); i++)
1323  {
1324  // Add tolerance to limit check
1325  if (joint_has_limits_vector_[i] && ((sol[i] < (joint_min_vector_[i] - LIMIT_TOLERANCE)) ||
1326  (sol[i] > (joint_max_vector_[i] + LIMIT_TOLERANCE))))
1327  {
1328  // One element of solution is not within limits
1329  obeys_limits = false;
1330  ROS_DEBUG_STREAM_NAMED(name_, "Not in limits! " << i << " value " << sol[i] << " has limit: "
1331  << joint_has_limits_vector_[i] << " being "
1332  << joint_min_vector_[i] << " to " << joint_max_vector_[i]);
1333  break;
1334  }
1335  }
1336  if (obeys_limits)
1337  {
1338  // All elements of solution obey limits
1339  solutions_found = true;
1340  solutions.push_back(sol);
1341  }
1342  }
1343  }
1344 
1345  if (solutions_found)
1346  {
1348  return true;
1349  }
1350  }
1351  else
1352  {
1353  ROS_DEBUG_STREAM_NAMED(name_, "No IK solution");
1354  }
1355 
1357  return false;
1358 }
1359 
1361  std::vector<double>& sampled_joint_vals) const
1362 {
1363  double joint_min = -M_PI;
1364  double joint_max = M_PI;
1365  int index = redundant_joint_indices_.front();
1366  double joint_dscrt = redundant_joint_discretization_.at(index);
1367 
1368  if (joint_has_limits_vector_[redundant_joint_indices_.front()])
1369  {
1370  joint_min = joint_min_vector_[index];
1371  joint_max = joint_max_vector_[index];
1372  }
1373 
1374  switch (method)
1375  {
1377  {
1378  unsigned int steps = std::ceil((joint_max - joint_min) / joint_dscrt);
1379  for (unsigned int i = 0; i < steps; i++)
1380  {
1381  sampled_joint_vals.push_back(joint_min + joint_dscrt * i);
1382  }
1383  sampled_joint_vals.push_back(joint_max);
1384  }
1385  break;
1387  {
1388  unsigned int steps = std::ceil((joint_max - joint_min) / joint_dscrt);
1389  steps = steps > 0 ? steps : 1;
1390  double diff = joint_max - joint_min;
1391  for (unsigned int i = 0; i < steps; i++)
1392  {
1393  sampled_joint_vals.push_back(((diff * std::rand()) / (static_cast<double>(RAND_MAX))) + joint_min);
1394  }
1395  }
1396 
1397  break;
1399 
1400  break;
1401  default:
1402  ROS_ERROR_STREAM("Discretization method " << method << " is not supported");
1403  return false;
1404  }
1405 
1406  return true;
1407 }
1408 
1409 } // end namespace
1410 
1411 // register IKFastKinematicsPlugin as a KinematicsBase implementation
d
virtual const IkSolutionBase< T > & GetSolution(size_t index) const
returns the solution pointer
Definition: ikfast.h:283
KinematicError kinematic_error
#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 initialize(const std::string &robot_description, const std::string &group_name, const std::string &base_name, const std::vector< std::string > &tip_names, double search_discretization)
bool getCount(int &count, const int &max_count, const int &min_count) const
ROSCONSOLE_DECL void initialize()
virtual size_t GetNumSolutions() const
returns the number of solutions stored
Definition: ikfast.h:294
XmlRpcServer s
void getClosestSolution(const IkSolutionList< IkReal > &solutions, const std::vector< double > &ik_seed_state, std::vector< double > &solution) const
ray on end effector coordinate system reaches desired global ray
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:70
unsigned int solve(KDL::Frame &pose_frame, const std::vector< double > &vfree, IkSolutionList< IkReal > &solutions) const
Calls the IK solver from IKFast.
bool sampleRedundantJoint(kinematics::DiscretizationMethod method, std::vector< double > &sampled_joint_vals) const
samples the designated redundant joint using the chosen discretization method
local point on end effector origin reaches desired 3D global point
void setSearchDiscretization(const std::map< unsigned int, double > &discretization)
Sets the discretization value for the redundant joint.
#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...
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,...)
const double LIMIT_TOLERANCE
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)
PLUGINLIB_EXPORT_CLASS(ikfast_kinematics_plugin::IKFastKinematicsPlugin, kinematics::KinematicsBase)
end effector reaches desired 6D transformation
#define ROS_FATAL_STREAM_NAMED(name, args)
IKFAST_API bool ComputeIk(const IkReal *eetrans, const IkReal *eerot, const IkReal *pfree, IkSolutionListBase< IkReal > &solutions)
bool searchParam(const std::string &key, std::string &result) const
double data[3]
void fromMsg(const A &, B &b)
direction on end effector coordinate system points to desired 3D position
DiscretizationMethod discretization_method
double harmonize(const std::vector< double > &ik_seed_state, std::vector< double > &solution) const
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
void GetRPY(double &roll, double &pitch, double &yaw) const
direction on end effector coordinate system reaches desired direction
virtual void GetSolution(T *solution, const T *freevalues) const =0
gets a concrete solution
B toMsg(const A &a)
bit is set if the data represents the time-derivate velocity of an IkParameterization ...
Default implementation of IkSolutionListBase.
Definition: ikfast.h:273
bool getParam(const std::string &key, std::string &s) const
#define ROS_FATAL_NAMED(name,...)
#define ROS_ERROR_NAMED(name,...)
#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.
static constexpr double DEFAULT_SEARCH_DISCRETIZATION
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)
SEARCH_MODE
Search modes for searchPositionIK(), see there.
double data[9]


prbt_ikfast_manipulator_plugin
Author(s):
autogenerated on Tue Feb 2 2021 03:50:29