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 Kinematics Solver Plugin for MoveIt wrapping an ikfast solver from OpenRAVE.
38  *
39  * AUTO-GENERATED by create_ikfast_moveit_plugin.py in moveit_kinematics package.
40  *
41  * This file, including the ikfast cpp from OpenRAVE below, forms a MoveIt kinematics plugin.
42  */
43 
44 #include <ros/ros.h>
47 #include <Eigen/Geometry>
48 #include <tf2_kdl/tf2_kdl.h>
49 #include <tf2_eigen/tf2_eigen.h>
51 
52 using namespace moveit::core;
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,
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 };
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_;
164  // The ikfast and base frame are the start and end of the kinematic chain for which the
165  // IKFast analytic solution was generated.
166  const std::string IKFAST_TIP_FRAME_ = "flange";
167  const std::string IKFAST_BASE_FRAME_ = "base_link";
169  // prefix added to tip- and baseframe to allow different namespaces or multi-robot setups
170  std::string link_prefix_;
172  // The transform tip and base bool are set to true if this solver is used with a kinematic
173  // chain that extends beyond the ikfast tip and base frame. The solution will be valid so
174  // long as there are no active, passive, or mimic joints between either the ikfast_tip_frame
175  // and the tip_frame of the group or the ikfast_base_frame and the base_frame for the group.
178 
179  // We store the transform from the ikfast_base_frame to the group base_frame as well as the
180  // ikfast_tip_frame to the group tip_frame to transform input poses into the solver frame.
181  Eigen::Isometry3d chain_base_to_group_base_;
182  Eigen::Isometry3d group_tip_to_chain_tip_;
183 
184  bool initialized_; // Internal variable that indicates whether solvers are configured and ready
185  const std::string name_{ "ikfast" };
186 
187  const std::vector<std::string>& getJointNames() const override
188  {
189  return joint_names_;
190  }
191  const std::vector<std::string>& getLinkNames() const override
192  {
193  return link_names_;
194  }
195 
196 public:
200  IKFastKinematicsPlugin() : num_joints_(GetNumJoints()), initialized_(false)
201  {
202  srand(time(nullptr));
203  supported_methods_.push_back(kinematics::DiscretizationMethods::NO_DISCRETIZATION);
204  supported_methods_.push_back(kinematics::DiscretizationMethods::ALL_DISCRETIZED);
205  supported_methods_.push_back(kinematics::DiscretizationMethods::ALL_RANDOM_SAMPLED);
206  }
207 
217  // Returns the IK solution that is within joint limits closest to ik_seed_state
218  bool getPositionIK(
219  const geometry_msgs::Pose& ik_pose, const std::vector<double>& ik_seed_state, std::vector<double>& solution,
220  moveit_msgs::MoveItErrorCodes& error_code,
222 
238  bool getPositionIK(const std::vector<geometry_msgs::Pose>& ik_poses, const std::vector<double>& ik_seed_state,
239  std::vector<std::vector<double>>& solutions, kinematics::KinematicsResult& result,
240  const kinematics::KinematicsQueryOptions& options) const override;
250  bool searchPositionIK(
251  const geometry_msgs::Pose& ik_pose, const std::vector<double>& ik_seed_state, double timeout,
252  std::vector<double>& solution, moveit_msgs::MoveItErrorCodes& error_code,
254 
264  bool searchPositionIK(
265  const geometry_msgs::Pose& ik_pose, const std::vector<double>& ik_seed_state, double timeout,
266  const std::vector<double>& consistency_limits, std::vector<double>& solution,
267  moveit_msgs::MoveItErrorCodes& error_code,
269 
278  bool searchPositionIK(
279  const geometry_msgs::Pose& ik_pose, const std::vector<double>& ik_seed_state, double timeout,
280  std::vector<double>& solution, const IKCallbackFn& solution_callback, moveit_msgs::MoveItErrorCodes& error_code,
282 
293  bool searchPositionIK(
294  const geometry_msgs::Pose& ik_pose, const std::vector<double>& ik_seed_state, double timeout,
295  const std::vector<double>& consistency_limits, std::vector<double>& solution,
296  const IKCallbackFn& solution_callback, moveit_msgs::MoveItErrorCodes& error_code,
298 
307  bool getPositionFK(const std::vector<std::string>& link_names, const std::vector<double>& joint_angles,
308  std::vector<geometry_msgs::Pose>& poses) const override;
309 
319  void setSearchDiscretization(const std::map<unsigned int, double>& discretization);
320 
324  bool setRedundantJoints(const std::vector<unsigned int>& redundant_joint_indices) override;
325 
326 private:
327  bool initialize(const moveit::core::RobotModel& robot_model, const std::string& group_name,
328  const std::string& base_frame, const std::vector<std::string>& tip_frames,
329  double search_discretization) override;
330 
335  size_t solve(KDL::Frame& pose_frame, const std::vector<double>& vfree, IkSolutionList<IkReal>& solutions) const;
336 
340  void getSolution(const IkSolutionList<IkReal>& solutions, int i, std::vector<double>& solution) const;
341 
345  void getSolution(const IkSolutionList<IkReal>& solutions, const std::vector<double>& ik_seed_state, int i,
346  std::vector<double>& solution) const;
347 
351  double enforceLimits(double val, double min, double max) const;
352 
353  void fillFreeParams(int count, int* array);
354  bool getCount(int& count, const int& max_count, const int& min_count) const;
355 
362  bool sampleRedundantJoint(kinematics::DiscretizationMethod method, std::vector<double>& sampled_joint_vals) const;
365  bool computeRelativeTransform(const std::string& from, const std::string& to, Eigen::Isometry3d& transform,
366  bool& differs_from_identity);
373  void transformToChainFrame(const geometry_msgs::Pose& ik_pose, KDL::Frame& ik_pose_chain) const;
374 }; // end class
375 
376 bool IKFastKinematicsPlugin::computeRelativeTransform(const std::string& from, const std::string& to,
377  Eigen::Isometry3d& transform, bool& differs_from_identity)
378 {
379  RobotStatePtr robot_state;
380  robot_state.reset(new RobotState(robot_model_));
381  robot_state->setToDefaultValues();
382 
383  auto* from_link = robot_model_->getLinkModel(from);
384  auto* to_link = robot_model_->getLinkModel(to);
385  if (!from_link || !to_link)
386  return false;
387 
388  if (robot_model_->getRigidlyConnectedParentLinkModel(from_link) !=
389  robot_model_->getRigidlyConnectedParentLinkModel(to_link))
390  {
391  ROS_ERROR_STREAM_NAMED(name_, "Link frames " << from << " and " << to << " are not rigidly connected.");
392  return false;
393  }
394 
395  transform = robot_state->getGlobalLinkTransform(from_link).inverse() * robot_state->getGlobalLinkTransform(to_link);
396  differs_from_identity = !transform.matrix().isIdentity();
397  return true;
398 }
399 
400 bool IKFastKinematicsPlugin::initialize(const moveit::core::RobotModel& robot_model, const std::string& group_name,
401  const std::string& base_frame, const std::vector<std::string>& tip_frames,
402  double search_discretization)
403 {
404  if (tip_frames.size() != 1)
405  {
406  ROS_ERROR_NAMED(name_, "Expecting exactly one tip frame.");
407  return false;
408  }
409 
410  storeValues(robot_model, group_name, base_frame, tip_frames, search_discretization);
411  if (!lookupParam("link_prefix", link_prefix_, std::string("")))
412  {
413  ROS_INFO_NAMED(name_, "Using empty link_prefix.");
414  }
415  else
416  {
417  ROS_INFO_STREAM_NAMED(name_, "Using link_prefix: '" << link_prefix_ << "'");
418  }
419 
420  // verbose error output. subsequent checks in computeRelativeTransform return false then
421  if (!robot_model.hasLinkModel(tip_frames_[0]))
422  ROS_ERROR_STREAM_NAMED(name_, "tip frame '" << tip_frames_[0] << "' does not exist.");
423  if (!robot_model.hasLinkModel(base_frame_))
424  ROS_ERROR_STREAM_NAMED(name_, "base_frame '" << base_frame_ << "' does not exist.");
425 
426  if (!robot_model.hasLinkModel(link_prefix_ + IKFAST_TIP_FRAME_))
427  ROS_ERROR_STREAM_NAMED(name_, "prefixed tip frame '" << link_prefix_ + IKFAST_TIP_FRAME_
428  << "' does not exist. "
429  "Please check your link_prefix parameter.");
430  if (!robot_model.hasLinkModel(link_prefix_ + IKFAST_BASE_FRAME_))
431  ROS_ERROR_STREAM_NAMED(name_, "prefixed base frame '" << link_prefix_ + IKFAST_BASE_FRAME_
432  << "' does not exist. "
433  "Please check your link_prefix parameter.");
434  // This IKFast solution was generated with IKFAST_TIP_FRAME_ and IKFAST_BASE_FRAME_.
435  // It is often the case that fixed joints are added to these links to model things like
436  // a robot mounted on a table or a robot with an end effector attached to the last link.
437  // To support these use cases, we store the transform from the IKFAST_BASE_FRAME_ to the
438  // base_frame_ and IKFAST_TIP_FRAME_ the tip_frame_ and transform to the input pose accordingly
439  if (!computeRelativeTransform(tip_frames_[0], link_prefix_ + IKFAST_TIP_FRAME_, group_tip_to_chain_tip_,
440  tip_transform_required_) ||
441  !computeRelativeTransform(link_prefix_ + IKFAST_BASE_FRAME_, base_frame_, chain_base_to_group_base_,
442  base_transform_required_))
443  {
444  return false;
445  }
446 
447  // IKFast56/61
448  fillFreeParams(GetNumFreeParameters(), GetFreeParameters());
449 
450  if (free_params_.size() > 1)
451  {
452  ROS_ERROR_NAMED(name_, "Only one free joint parameter supported!");
453  return false;
454  }
455  else if (free_params_.size() == 1)
456  {
457  redundant_joint_indices_.clear();
458  redundant_joint_indices_.push_back(free_params_[0]);
459  KinematicsBase::setSearchDiscretization(search_discretization);
460  }
461 
462  const moveit::core::JointModelGroup* jmg = robot_model_->getJointModelGroup(group_name);
463  if (!jmg)
464  {
465  ROS_ERROR_STREAM_NAMED(name_, "Unknown planning group: " << group_name);
466  return false;
467  }
468 
469  ROS_DEBUG_STREAM_NAMED(name_, "Registering joints and links");
470  const moveit::core::LinkModel* link = robot_model_->getLinkModel(tip_frames_[0]);
471  const moveit::core::LinkModel* base_link = robot_model_->getLinkModel(base_frame_);
472  while (link && link != base_link)
473  {
474  ROS_DEBUG_STREAM_NAMED(name_, "Link " << link->getName());
475  link_names_.push_back(link->getName());
476  const moveit::core::JointModel* joint = link->getParentJointModel();
477  if (joint->getType() != joint->UNKNOWN && joint->getType() != joint->FIXED && joint->getVariableCount() == 1)
478  {
479  ROS_DEBUG_STREAM_NAMED(name_, "Adding joint " << joint->getName());
480 
481  joint_names_.push_back(joint->getName());
482  const moveit::core::VariableBounds& bounds = joint->getVariableBounds()[0];
483  joint_has_limits_vector_.push_back(bounds.position_bounded_);
484  joint_min_vector_.push_back(bounds.min_position_);
485  joint_max_vector_.push_back(bounds.max_position_);
486  }
487  link = link->getParentLinkModel();
488  }
489 
490  if (joint_names_.size() != num_joints_)
491  {
492  ROS_FATAL_NAMED(name_, "Joint numbers of RobotModel (%zd) and IKFast solver (%zd) do not match",
493  joint_names_.size(), num_joints_);
494  return false;
495  }
496 
497  std::reverse(link_names_.begin(), link_names_.end());
498  std::reverse(joint_names_.begin(), joint_names_.end());
499  std::reverse(joint_min_vector_.begin(), joint_min_vector_.end());
500  std::reverse(joint_max_vector_.begin(), joint_max_vector_.end());
501  std::reverse(joint_has_limits_vector_.begin(), joint_has_limits_vector_.end());
502 
503  for (size_t joint_id = 0; joint_id < num_joints_; ++joint_id)
504  ROS_DEBUG_STREAM_NAMED(name_, joint_names_[joint_id] << " " << joint_min_vector_[joint_id] << " "
505  << joint_max_vector_[joint_id] << " "
506  << joint_has_limits_vector_[joint_id]);
507 
508  initialized_ = true;
509  return true;
510 }
511 
512 void IKFastKinematicsPlugin::setSearchDiscretization(const std::map<unsigned int, double>& discretization)
513 {
514  if (discretization.empty())
515  {
516  ROS_ERROR("The 'discretization' map is empty");
517  return;
518  }
519 
520  if (redundant_joint_indices_.empty())
521  {
522  ROS_ERROR_STREAM_NAMED(name_, "This group's solver doesn't support redundant joints");
523  return;
524  }
525 
526  if (discretization.begin()->first != redundant_joint_indices_[0])
527  {
528  std::string redundant_joint = joint_names_[free_params_[0]];
529  ROS_ERROR_STREAM_NAMED(name_, "Attempted to discretize a non-redundant joint "
530  << discretization.begin()->first << ", only joint '" << redundant_joint
531  << "' with index " << redundant_joint_indices_[0] << " is redundant.");
532  return;
533  }
534 
535  if (discretization.begin()->second <= 0.0)
536  {
537  ROS_ERROR_STREAM_NAMED(name_, "Discretization can not takes values that are <= 0");
538  return;
539  }
540 
541  redundant_joint_discretization_.clear();
542  redundant_joint_discretization_[redundant_joint_indices_[0]] = discretization.begin()->second;
543 }
544 
545 bool IKFastKinematicsPlugin::setRedundantJoints(const std::vector<unsigned int>& redundant_joint_indices)
546 {
547  ROS_ERROR_STREAM_NAMED(name_, "Changing the redundant joints isn't permitted by this group's solver ");
548  return false;
549 }
550 
551 size_t IKFastKinematicsPlugin::solve(KDL::Frame& pose_frame, const std::vector<double>& vfree,
552  IkSolutionList<IkReal>& solutions) const
553 {
554  // IKFast56/61
555  solutions.Clear();
556 
557  double trans[3];
558  trans[0] = pose_frame.p[0]; //-.18;
559  trans[1] = pose_frame.p[1];
560  trans[2] = pose_frame.p[2];
561 
562  KDL::Rotation mult;
563  KDL::Vector direction;
564 
565  switch (GetIkType())
566  {
567  case IKP_Transform6D:
568  case IKP_Translation3D:
569  // For **Transform6D**, eerot is 9 values for the 3x3 rotation matrix. For **Translation3D**, these are ignored.
570 
571  mult = pose_frame.M;
572 
573  double vals[9];
574  vals[0] = mult(0, 0);
575  vals[1] = mult(0, 1);
576  vals[2] = mult(0, 2);
577  vals[3] = mult(1, 0);
578  vals[4] = mult(1, 1);
579  vals[5] = mult(1, 2);
580  vals[6] = mult(2, 0);
581  vals[7] = mult(2, 1);
582  vals[8] = mult(2, 2);
583 
584  // IKFast56/61
585  ComputeIk(trans, vals, vfree.size() > 0 ? &vfree[0] : nullptr, solutions);
586  return solutions.GetNumSolutions();
587 
588  case IKP_Direction3D:
589  case IKP_Ray4D:
591  // For **Direction3D**, **Ray4D**, and **TranslationDirection5D**, the first 3 values represent the target
592  // direction.
593 
594  direction = pose_frame.M * KDL::Vector(0, 0, 1);
595  ComputeIk(trans, direction.data, vfree.size() > 0 ? &vfree[0] : nullptr, solutions);
596  return solutions.GetNumSolutions();
597 
601  // For *TranslationXAxisAngle4D*, *TranslationYAxisAngle4D*, *TranslationZAxisAngle4D* - end effector origin
602  // reaches desired 3D translation, manipulator direction makes a specific angle with x/y/z-axis (defined in the
603  // manipulator base link’s coordinate system)
604  ROS_ERROR_NAMED(name_, "IK for this IkParameterizationType not implemented yet.");
605  return 0;
606 
608  // For **TranslationLocalGlobal6D**, the diagonal elements ([0],[4],[8]) are the local translation inside the end
609  // effector coordinate system.
610  ROS_ERROR_NAMED(name_, "IK for this IkParameterizationType not implemented yet.");
611  return 0;
612 
613  case IKP_Rotation3D:
614  case IKP_Lookat3D:
615  case IKP_TranslationXY2D:
617  ROS_ERROR_NAMED(name_, "IK for this IkParameterizationType not implemented yet.");
618  return 0;
619 
621  double roll, pitch, yaw;
622  // For **TranslationXAxisAngleZNorm4D** - end effector origin reaches desired 3D translation, manipulator
623  // direction needs to be orthogonal to z axis and be rotated at a certain angle starting from the x axis (defined
624  // in the manipulator base link’s coordinate system)
625  pose_frame.M.GetRPY(roll, pitch, yaw);
626  ComputeIk(trans, &yaw, vfree.size() > 0 ? &vfree[0] : nullptr, solutions);
627  return solutions.GetNumSolutions();
628 
630  // For **TranslationYAxisAngleXNorm4D** - end effector origin reaches desired 3D translation, manipulator
631  // direction needs to be orthogonal to x axis and be rotated at a certain angle starting from the y axis (defined
632  // in the manipulator base link’s coordinate system)
633  pose_frame.M.GetRPY(roll, pitch, yaw);
634  ComputeIk(trans, &roll, vfree.size() > 0 ? &vfree[0] : nullptr, solutions);
635  return solutions.GetNumSolutions();
636 
638  // For **TranslationZAxisAngleYNorm4D** - end effector origin reaches desired 3D translation, manipulator
639  // direction needs to be orthogonal to y axis and be rotated at a certain angle starting from the z axis (defined
640  // in the manipulator base link’s coordinate system)
641  pose_frame.M.GetRPY(roll, pitch, yaw);
642  ComputeIk(trans, &pitch, vfree.size() > 0 ? &vfree[0] : nullptr, solutions);
643  return solutions.GetNumSolutions();
644 
645  default:
646  ROS_ERROR_NAMED(name_, "Unknown IkParameterizationType! "
647  "Was the solver generated with an incompatible version of Openrave?");
648  return 0;
649  }
650 }
651 
652 void IKFastKinematicsPlugin::getSolution(const IkSolutionList<IkReal>& solutions, int i,
653  std::vector<double>& solution) const
654 {
655  solution.clear();
656  solution.resize(num_joints_);
657 
658  // IKFast56/61
659  const IkSolutionBase<IkReal>& sol = solutions.GetSolution(i);
660  std::vector<IkReal> vsolfree(sol.GetFree().size());
661  sol.GetSolution(&solution[0], vsolfree.size() > 0 ? &vsolfree[0] : nullptr);
662 
663  for (std::size_t joint_id = 0; joint_id < num_joints_; ++joint_id)
664  {
665  if (joint_has_limits_vector_[joint_id])
666  {
667  solution[joint_id] = enforceLimits(solution[joint_id], joint_min_vector_[joint_id], joint_max_vector_[joint_id]);
668  }
669  }
670 }
671 
672 void IKFastKinematicsPlugin::getSolution(const IkSolutionList<IkReal>& solutions,
673  const std::vector<double>& ik_seed_state, int i,
674  std::vector<double>& solution) const
675 {
676  solution.clear();
677  solution.resize(num_joints_);
678 
679  // IKFast56/61
680  const IkSolutionBase<IkReal>& sol = solutions.GetSolution(i);
681  std::vector<IkReal> vsolfree(sol.GetFree().size());
682  sol.GetSolution(&solution[0], vsolfree.size() > 0 ? &vsolfree[0] : nullptr);
683 
684  // rotate joints by +/-360° where it is possible and useful
685  for (std::size_t i = 0; i < num_joints_; ++i)
686  {
687  if (joint_has_limits_vector_[i])
688  {
689  solution[i] = enforceLimits(solution[i], joint_min_vector_[i], joint_max_vector_[i]);
690  double signed_distance = solution[i] - ik_seed_state[i];
691  while (signed_distance > M_PI && solution[i] - 2 * M_PI > (joint_min_vector_[i] - LIMIT_TOLERANCE))
692  {
693  signed_distance -= 2 * M_PI;
694  solution[i] -= 2 * M_PI;
695  }
696  while (signed_distance < -M_PI && solution[i] + 2 * M_PI < (joint_max_vector_[i] + LIMIT_TOLERANCE))
697  {
698  signed_distance += 2 * M_PI;
699  solution[i] += 2 * M_PI;
700  }
701  }
702  }
703 }
704 
705 double IKFastKinematicsPlugin::enforceLimits(double joint_value, double min, double max) const
706 {
707  // If the joint_value is greater than max subtract 2 * PI until it is less than the max
708  while (joint_value > max)
709  {
710  joint_value -= 2 * M_PI;
711  }
712 
713  // If the joint_value is less than the min, add 2 * PI until it is more than the min
714  while (joint_value < min)
715  {
716  joint_value += 2 * M_PI;
717  }
718  return joint_value;
719 }
720 
721 void IKFastKinematicsPlugin::fillFreeParams(int count, int* array)
722 {
723  free_params_.clear();
724  for (int i = 0; i < count; ++i)
725  free_params_.push_back(array[i]);
726 }
727 
728 bool IKFastKinematicsPlugin::getCount(int& count, const int& max_count, const int& min_count) const
729 {
730  if (count > 0)
731  {
732  if (-count >= min_count)
733  {
734  count = -count;
735  return true;
736  }
737  else if (count + 1 <= max_count)
738  {
739  count = count + 1;
740  return true;
741  }
742  else
743  {
744  return false;
745  }
746  }
747  else
748  {
749  if (1 - count <= max_count)
750  {
751  count = 1 - count;
752  return true;
753  }
754  else if (count - 1 >= min_count)
755  {
756  count = count - 1;
757  return true;
758  }
759  else
760  return false;
761  }
762 }
763 
764 bool IKFastKinematicsPlugin::getPositionFK(const std::vector<std::string>& link_names,
765  const std::vector<double>& joint_angles,
766  std::vector<geometry_msgs::Pose>& poses) const
767 {
768  if (GetIkType() != IKP_Transform6D)
769  {
770  // ComputeFk() is the inverse function of ComputeIk(), so the format of
771  // eerot differs depending on IK type. The Transform6D IK type is the only
772  // one for which a 3x3 rotation matrix is returned, which means we can only
773  // compute FK for that IK type.
774  ROS_ERROR_NAMED(name_, "Can only compute FK for Transform6D IK type!");
775  return false;
776  }
777 
778  KDL::Frame p_out;
779  if (link_names.size() == 0)
780  {
781  ROS_WARN_STREAM_NAMED(name_, "Link names with nothing");
782  return false;
783  }
784 
785  if (link_names.size() != 1 || link_names[0] != getTipFrame())
786  {
787  ROS_ERROR_NAMED(name_, "Can compute FK for %s only", getTipFrame().c_str());
788  return false;
789  }
790 
791  bool valid = true;
792 
793  IkReal eerot[9], eetrans[3];
794 
795  if (joint_angles.size() != num_joints_)
796  {
797  ROS_ERROR_NAMED(name_, "Unexpected number of joint angles");
798  return false;
799  }
800 
801  IkReal angles[num_joints_];
802  for (unsigned char i = 0; i < num_joints_; i++)
803  angles[i] = joint_angles[i];
804 
805  // IKFast56/61
806  ComputeFk(angles, eetrans, eerot);
807 
808  for (int i = 0; i < 3; ++i)
809  p_out.p.data[i] = eetrans[i];
810 
811  for (int i = 0; i < 9; ++i)
812  p_out.M.data[i] = eerot[i];
813 
814  poses.resize(1);
815  poses[0] = tf2::toMsg(p_out);
816 
817  return valid;
818 }
819 
820 bool IKFastKinematicsPlugin::searchPositionIK(const geometry_msgs::Pose& ik_pose,
821  const std::vector<double>& ik_seed_state, double timeout,
822  std::vector<double>& solution, moveit_msgs::MoveItErrorCodes& error_code,
823  const kinematics::KinematicsQueryOptions& options) const
824 {
825  std::vector<double> consistency_limits;
826  return searchPositionIK(ik_pose, ik_seed_state, timeout, consistency_limits, solution, IKCallbackFn(), error_code,
827  options);
828 }
829 
830 bool IKFastKinematicsPlugin::searchPositionIK(const geometry_msgs::Pose& ik_pose,
831  const std::vector<double>& ik_seed_state, double timeout,
832  const std::vector<double>& consistency_limits,
833  std::vector<double>& solution, moveit_msgs::MoveItErrorCodes& error_code,
834  const kinematics::KinematicsQueryOptions& options) const
835 {
836  return searchPositionIK(ik_pose, ik_seed_state, timeout, consistency_limits, solution, IKCallbackFn(), error_code,
837  options);
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, const IKCallbackFn& solution_callback,
843  moveit_msgs::MoveItErrorCodes& error_code,
844  const kinematics::KinematicsQueryOptions& options) const
845 {
846  std::vector<double> consistency_limits;
847  return searchPositionIK(ik_pose, ik_seed_state, timeout, consistency_limits, solution, solution_callback, error_code,
848  options);
849 }
850 
851 bool IKFastKinematicsPlugin::searchPositionIK(const geometry_msgs::Pose& ik_pose,
852  const std::vector<double>& ik_seed_state, double timeout,
853  const std::vector<double>& consistency_limits,
854  std::vector<double>& solution, const IKCallbackFn& solution_callback,
855  moveit_msgs::MoveItErrorCodes& error_code,
856  const kinematics::KinematicsQueryOptions& options) const
857 {
858  // "SEARCH_MODE" is fixed during code generation
859  SEARCH_MODE search_mode = OPTIMIZE_MAX_JOINT;
860 
861  // Check if there are no redundant joints
862  if (free_params_.size() == 0)
863  {
864  ROS_DEBUG_STREAM_NAMED(name_, "No need to search since no free params/redundant joints");
865 
866  std::vector<geometry_msgs::Pose> ik_poses(1, ik_pose);
867  std::vector<std::vector<double>> solutions;
869  // Find all IK solutions within joint limits
870  if (!getPositionIK(ik_poses, ik_seed_state, solutions, kinematic_result, options))
871  {
872  ROS_DEBUG_STREAM_NAMED(name_, "No solution whatsoever");
873  error_code.val = moveit_msgs::MoveItErrorCodes::NO_IK_SOLUTION;
874  return false;
875  }
876 
877  // sort solutions by their distance to the seed
878  std::vector<LimitObeyingSol> solutions_obey_limits;
879  for (std::size_t i = 0; i < solutions.size(); ++i)
880  {
881  double dist_from_seed = 0.0;
882  for (std::size_t j = 0; j < ik_seed_state.size(); ++j)
883  {
884  dist_from_seed += fabs(ik_seed_state[j] - solutions[i][j]);
885  }
886 
887  solutions_obey_limits.push_back({ solutions[i], dist_from_seed });
888  }
889  std::sort(solutions_obey_limits.begin(), solutions_obey_limits.end());
890 
891  // check for collisions if a callback is provided
892  if (!solution_callback.empty())
893  {
894  for (std::size_t i = 0; i < solutions_obey_limits.size(); ++i)
895  {
896  solution_callback(ik_pose, solutions_obey_limits[i].value, error_code);
897  if (error_code.val == moveit_msgs::MoveItErrorCodes::SUCCESS)
898  {
899  solution = solutions_obey_limits[i].value;
900  ROS_DEBUG_STREAM_NAMED(name_, "Solution passes callback");
901  return true;
902  }
903  }
904 
905  ROS_DEBUG_STREAM_NAMED(name_, "Solution has error code " << error_code);
906  return false;
907  }
908  else
909  {
910  solution = solutions_obey_limits[0].value;
911  error_code.val = moveit_msgs::MoveItErrorCodes::SUCCESS;
912  return true; // no collision check callback provided
913  }
914  }
915 
916  // -------------------------------------------------------------------------------------------------
917  // Error Checking
918  if (!initialized_)
919  {
920  ROS_ERROR_STREAM_NAMED(name_, "Kinematics not active");
921  error_code.val = error_code.NO_IK_SOLUTION;
922  return false;
923  }
924 
925  if (ik_seed_state.size() != num_joints_)
926  {
927  ROS_ERROR_STREAM_NAMED(name_, "Seed state must have size " << num_joints_ << " instead of size "
928  << ik_seed_state.size());
929  error_code.val = error_code.NO_IK_SOLUTION;
930  return false;
931  }
932 
933  if (!consistency_limits.empty() && consistency_limits.size() != num_joints_)
934  {
935  ROS_ERROR_STREAM_NAMED(name_, "Consistency limits be empty or must have size " << num_joints_ << " instead of size "
936  << consistency_limits.size());
937  error_code.val = error_code.NO_IK_SOLUTION;
938  return false;
939  }
940 
941  // -------------------------------------------------------------------------------------------------
942  // Initialize
943 
944  KDL::Frame frame;
945  transformToChainFrame(ik_pose, frame);
946 
947  std::vector<double> vfree(free_params_.size());
948 
949  int counter = 0;
950 
951  double initial_guess = ik_seed_state[free_params_[0]];
952  vfree[0] = initial_guess;
953 
954  // -------------------------------------------------------------------------------------------------
955  // Handle consitency limits if needed
956  int num_positive_increments;
957  int num_negative_increments;
958  double search_discretization = redundant_joint_discretization_.at(free_params_[0]);
959 
960  if (!consistency_limits.empty())
961  {
962  // MoveIt replaced consistency_limit (scalar) w/ consistency_limits (vector)
963  // Assume [0]th free_params element for now. Probably wrong.
964  double max_limit = fmin(joint_max_vector_[free_params_[0]], initial_guess + consistency_limits[free_params_[0]]);
965  double min_limit = fmax(joint_min_vector_[free_params_[0]], initial_guess - consistency_limits[free_params_[0]]);
966 
967  num_positive_increments = static_cast<int>((max_limit - initial_guess) / search_discretization);
968  num_negative_increments = static_cast<int>((initial_guess - min_limit) / search_discretization);
969  }
970  else // no consistency limits provided
971  {
972  num_positive_increments = (joint_max_vector_[free_params_[0]] - initial_guess) / search_discretization;
973  num_negative_increments = (initial_guess - joint_min_vector_[free_params_[0]]) / search_discretization;
974  }
975 
976  // -------------------------------------------------------------------------------------------------
977  // Begin searching
978 
979  ROS_DEBUG_STREAM_NAMED(name_, "Free param is " << free_params_[0] << " initial guess is " << initial_guess
980  << ", # positive increments: " << num_positive_increments
981  << ", # negative increments: " << num_negative_increments);
982  if ((search_mode & OPTIMIZE_MAX_JOINT) && (num_positive_increments + num_negative_increments) > 1000)
983  ROS_WARN_STREAM_ONCE_NAMED(name_, "Large search space, consider increasing the search discretization");
984 
985  double best_costs = -1.0;
986  std::vector<double> best_solution;
987  int nattempts = 0, nvalid = 0;
988 
989  while (true)
990  {
991  IkSolutionList<IkReal> solutions;
992  size_t numsol = solve(frame, vfree, solutions);
993 
994  ROS_DEBUG_STREAM_NAMED(name_, "Found " << numsol << " solutions from IKFast");
995 
996  if (numsol > 0)
997  {
998  for (size_t s = 0; s < numsol; ++s)
999  {
1000  nattempts++;
1001  std::vector<double> sol;
1002  getSolution(solutions, ik_seed_state, s, sol);
1003 
1004  bool obeys_limits = true;
1005  for (size_t i = 0; i < sol.size(); i++)
1006  {
1007  if (joint_has_limits_vector_[i] && (sol[i] < joint_min_vector_[i] || sol[i] > joint_max_vector_[i]))
1008  {
1009  obeys_limits = false;
1010  break;
1011  }
1012  // ROS_INFO_STREAM_NAMED(name_,"Num " << i << " value " << sol[i] << " has limits " <<
1013  // joint_has_limits_vector_[i] << " " << joint_min_vector_[i] << " " << joint_max_vector_[i]);
1014  }
1015  if (obeys_limits)
1016  {
1017  getSolution(solutions, ik_seed_state, s, solution);
1018 
1019  // This solution is within joint limits, now check if in collision (if callback provided)
1020  if (!solution_callback.empty())
1021  {
1022  solution_callback(ik_pose, solution, error_code);
1023  }
1024  else
1025  {
1026  error_code.val = error_code.SUCCESS;
1027  }
1028 
1029  if (error_code.val == error_code.SUCCESS)
1030  {
1031  nvalid++;
1032  if (search_mode & OPTIMIZE_MAX_JOINT)
1033  {
1034  // Costs for solution: Largest joint motion
1035  double costs = 0.0;
1036  for (unsigned int i = 0; i < solution.size(); i++)
1037  {
1038  double d = fabs(ik_seed_state[i] - solution[i]);
1039  if (d > costs)
1040  costs = d;
1041  }
1042  if (costs < best_costs || best_costs == -1.0)
1043  {
1044  best_costs = costs;
1045  best_solution = solution;
1046  }
1047  }
1048  else
1049  // Return first feasible solution
1050  return true;
1051  }
1052  }
1053  }
1054  }
1055 
1056  if (!getCount(counter, num_positive_increments, -num_negative_increments))
1057  {
1058  // Everything searched
1059  error_code.val = moveit_msgs::MoveItErrorCodes::NO_IK_SOLUTION;
1060  break;
1061  }
1062 
1063  vfree[0] = initial_guess + search_discretization * counter;
1064  // ROS_DEBUG_STREAM_NAMED(name_,"Attempt " << counter << " with 0th free joint having value " << vfree[0]);
1065  }
1066 
1067  ROS_DEBUG_STREAM_NAMED(name_, "Valid solutions: " << nvalid << "/" << nattempts);
1068 
1069  if ((search_mode & OPTIMIZE_MAX_JOINT) && best_costs != -1.0)
1070  {
1071  solution = best_solution;
1072  error_code.val = error_code.SUCCESS;
1073  return true;
1074  }
1075 
1076  // No solution found
1077  error_code.val = moveit_msgs::MoveItErrorCodes::NO_IK_SOLUTION;
1078  return false;
1079 }
1080 
1081 // Used when there are no redundant joints - aka no free params
1082 bool IKFastKinematicsPlugin::getPositionIK(const geometry_msgs::Pose& ik_pose, const std::vector<double>& ik_seed_state,
1083  std::vector<double>& solution, moveit_msgs::MoveItErrorCodes& error_code,
1084  const kinematics::KinematicsQueryOptions& options) const
1085 {
1086  ROS_DEBUG_STREAM_NAMED(name_, "getPositionIK");
1087 
1088  if (!initialized_)
1089  {
1090  ROS_ERROR_NAMED(name_, "kinematics not active");
1091  return false;
1092  }
1093 
1094  if (ik_seed_state.size() < num_joints_)
1095  {
1096  ROS_ERROR_STREAM_NAMED(name_, "ik_seed_state only has " << ik_seed_state.size()
1097  << " entries, this ikfast solver requires " << num_joints_);
1098  return false;
1099  }
1100 
1101  // Check if seed is in bound
1102  for (std::size_t i = 0; i < ik_seed_state.size(); i++)
1103  {
1104  // Add tolerance to limit check
1105  if (joint_has_limits_vector_[i] && ((ik_seed_state[i] < (joint_min_vector_[i] - LIMIT_TOLERANCE)) ||
1106  (ik_seed_state[i] > (joint_max_vector_[i] + LIMIT_TOLERANCE))))
1107  {
1108  ROS_DEBUG_STREAM_NAMED(name_, "IK seed not in limits! " << static_cast<int>(i) << " value " << ik_seed_state[i]
1109  << " has limit: " << joint_has_limits_vector_[i]
1110  << " being " << joint_min_vector_[i] << " to "
1111  << joint_max_vector_[i]);
1112  return false;
1113  }
1114  }
1115 
1116  std::vector<double> vfree(free_params_.size());
1117  for (std::size_t i = 0; i < free_params_.size(); ++i)
1118  {
1119  int p = free_params_[i];
1120  ROS_ERROR("%u is %f", p, ik_seed_state[p]); // DTC
1121  vfree[i] = ik_seed_state[p];
1122  }
1123 
1124  KDL::Frame frame;
1125  transformToChainFrame(ik_pose, frame);
1126 
1127  IkSolutionList<IkReal> solutions;
1128  size_t numsol = solve(frame, vfree, solutions);
1129  ROS_DEBUG_STREAM_NAMED(name_, "Found " << numsol << " solutions from IKFast");
1130 
1131  std::vector<LimitObeyingSol> solutions_obey_limits;
1132 
1133  if (numsol)
1134  {
1135  std::vector<double> solution_obey_limits;
1136  for (std::size_t s = 0; s < numsol; ++s)
1137  {
1138  std::vector<double> sol;
1139  getSolution(solutions, ik_seed_state, s, sol);
1140  ROS_DEBUG_NAMED(name_, "Sol %d: %e %e %e %e %e %e", static_cast<int>(s), sol[0], sol[1], sol[2], sol[3],
1141  sol[4], sol[5]);
1142 
1143  bool obeys_limits = true;
1144  for (std::size_t i = 0; i < sol.size(); i++)
1145  {
1146  // Add tolerance to limit check
1147  if (joint_has_limits_vector_[i] && ((sol[i] < (joint_min_vector_[i] - LIMIT_TOLERANCE)) ||
1148  (sol[i] > (joint_max_vector_[i] + LIMIT_TOLERANCE))))
1149  {
1150  // One element of solution is not within limits
1151  obeys_limits = false;
1152  ROS_DEBUG_STREAM_NAMED(name_, "Not in limits! " << static_cast<int>(i) << " value " << sol[i]
1153  << " has limit: " << joint_has_limits_vector_[i]
1154  << " being " << joint_min_vector_[i] << " to "
1155  << joint_max_vector_[i]);
1156  break;
1157  }
1158  }
1159  if (obeys_limits)
1160  {
1161  // All elements of this solution obey limits
1162  getSolution(solutions, ik_seed_state, s, solution_obey_limits);
1163  double dist_from_seed = 0.0;
1164  for (std::size_t i = 0; i < ik_seed_state.size(); ++i)
1165  {
1166  dist_from_seed += fabs(ik_seed_state[i] - solution_obey_limits[i]);
1167  }
1168 
1169  solutions_obey_limits.push_back({ solution_obey_limits, dist_from_seed });
1170  }
1171  }
1172  }
1173  else
1174  {
1175  ROS_DEBUG_STREAM_NAMED(name_, "No IK solution");
1176  }
1177 
1178  // Sort the solutions under limits and find the one that is closest to ik_seed_state
1179  if (!solutions_obey_limits.empty())
1180  {
1181  std::sort(solutions_obey_limits.begin(), solutions_obey_limits.end());
1182  solution = solutions_obey_limits[0].value;
1183  error_code.val = moveit_msgs::MoveItErrorCodes::SUCCESS;
1184  return true;
1185  }
1186 
1187  error_code.val = moveit_msgs::MoveItErrorCodes::NO_IK_SOLUTION;
1188  return false;
1189 }
1190 
1191 bool IKFastKinematicsPlugin::getPositionIK(const std::vector<geometry_msgs::Pose>& ik_poses,
1192  const std::vector<double>& ik_seed_state,
1193  std::vector<std::vector<double>>& solutions,
1195  const kinematics::KinematicsQueryOptions& options) const
1196 {
1197  ROS_DEBUG_STREAM_NAMED(name_, "getPositionIK with multiple solutions");
1198 
1199  if (!initialized_)
1200  {
1201  ROS_ERROR_NAMED(name_, "kinematics not active");
1203  return false;
1204  }
1205 
1206  if (ik_poses.empty())
1207  {
1208  ROS_ERROR_NAMED(name_, "ik_poses is empty");
1210  return false;
1211  }
1212 
1213  if (ik_poses.size() > 1)
1214  {
1215  ROS_ERROR_NAMED(name_, "ik_poses contains multiple entries, only one is allowed");
1217  return false;
1218  }
1219 
1220  if (ik_seed_state.size() < num_joints_)
1221  {
1222  ROS_ERROR_STREAM_NAMED(name_, "ik_seed_state only has " << ik_seed_state.size()
1223  << " entries, this ikfast solver requires " << num_joints_);
1224  return false;
1225  }
1226 
1227  KDL::Frame frame;
1228  transformToChainFrame(ik_poses[0], frame);
1229 
1230  // solving ik
1231  std::vector<IkSolutionList<IkReal>> solution_set;
1232  IkSolutionList<IkReal> ik_solutions;
1233  std::vector<double> vfree;
1234  int numsol = 0;
1235  std::vector<double> sampled_joint_vals;
1236  if (!redundant_joint_indices_.empty())
1237  {
1238  // initializing from seed
1239  sampled_joint_vals.push_back(ik_seed_state[redundant_joint_indices_[0]]);
1240 
1241  // checking joint limits when using no discretization
1243  joint_has_limits_vector_[redundant_joint_indices_.front()])
1244  {
1245  double joint_min = joint_min_vector_[redundant_joint_indices_.front()];
1246  double joint_max = joint_max_vector_[redundant_joint_indices_.front()];
1247 
1248  double jv = sampled_joint_vals[0];
1249  if (!((jv > (joint_min - LIMIT_TOLERANCE)) && (jv < (joint_max + LIMIT_TOLERANCE))))
1250  {
1252  ROS_ERROR_STREAM_NAMED(name_, "ik seed is out of bounds");
1253  return false;
1254  }
1255  }
1256 
1257  // computing all solutions sets for each sampled value of the redundant joint
1258  if (!sampleRedundantJoint(options.discretization_method, sampled_joint_vals))
1259  {
1261  return false;
1262  }
1263 
1264  for (unsigned int i = 0; i < sampled_joint_vals.size(); i++)
1265  {
1266  vfree.clear();
1267  vfree.push_back(sampled_joint_vals[i]);
1268  numsol += solve(frame, vfree, ik_solutions);
1269  solution_set.push_back(ik_solutions);
1270  }
1271  }
1272  else
1273  {
1274  // computing for single solution set
1275  numsol = solve(frame, vfree, ik_solutions);
1276  solution_set.push_back(ik_solutions);
1277  }
1278 
1279  ROS_DEBUG_STREAM_NAMED(name_, "Found " << numsol << " solutions from IKFast");
1280  bool solutions_found = false;
1281  if (numsol > 0)
1282  {
1283  /*
1284  Iterating through all solution sets and storing those that do not exceed joint limits.
1285  */
1286  for (unsigned int r = 0; r < solution_set.size(); r++)
1287  {
1288  ik_solutions = solution_set[r];
1289  numsol = ik_solutions.GetNumSolutions();
1290  for (int s = 0; s < numsol; ++s)
1291  {
1292  std::vector<double> sol;
1293  getSolution(ik_solutions, ik_seed_state, s, sol);
1294 
1295  bool obeys_limits = true;
1296  for (unsigned int i = 0; i < sol.size(); i++)
1297  {
1298  // Add tolerance to limit check
1299  if (joint_has_limits_vector_[i] && ((sol[i] < (joint_min_vector_[i] - LIMIT_TOLERANCE)) ||
1300  (sol[i] > (joint_max_vector_[i] + LIMIT_TOLERANCE))))
1301  {
1302  // One element of solution is not within limits
1303  obeys_limits = false;
1304  ROS_DEBUG_STREAM_NAMED(name_, "Not in limits! " << i << " value " << sol[i] << " has limit: "
1305  << joint_has_limits_vector_[i] << " being "
1306  << joint_min_vector_[i] << " to " << joint_max_vector_[i]);
1307  break;
1308  }
1309  }
1310  if (obeys_limits)
1311  {
1312  // All elements of solution obey limits
1313  solutions_found = true;
1314  solutions.push_back(sol);
1315  }
1316  }
1317  }
1318 
1319  if (solutions_found)
1320  {
1322  return true;
1323  }
1324  }
1325  else
1326  {
1327  ROS_DEBUG_STREAM_NAMED(name_, "No IK solution");
1328  }
1329 
1331  return false;
1332 }
1333 
1334 bool IKFastKinematicsPlugin::sampleRedundantJoint(kinematics::DiscretizationMethod method,
1335  std::vector<double>& sampled_joint_vals) const
1336 {
1337  int index = redundant_joint_indices_.front();
1338  double joint_dscrt = redundant_joint_discretization_.at(index);
1339  double joint_min = joint_min_vector_[index];
1340  double joint_max = joint_max_vector_[index];
1341 
1342  switch (method)
1343  {
1345  {
1346  size_t steps = std::ceil((joint_max - joint_min) / joint_dscrt);
1347  for (size_t i = 0; i < steps; i++)
1348  {
1349  sampled_joint_vals.push_back(joint_min + joint_dscrt * i);
1350  }
1351  sampled_joint_vals.push_back(joint_max);
1352  }
1353  break;
1355  {
1356  int steps = std::ceil((joint_max - joint_min) / joint_dscrt);
1357  steps = steps > 0 ? steps : 1;
1358  double diff = joint_max - joint_min;
1359  for (int i = 0; i < steps; i++)
1360  {
1361  sampled_joint_vals.push_back(((diff * std::rand()) / (static_cast<double>(RAND_MAX))) + joint_min);
1362  }
1363  }
1364 
1365  break;
1367 
1368  break;
1369  default:
1370  ROS_ERROR_STREAM_NAMED(name_, "Discretization method " << method << " is not supported");
1371  return false;
1372  }
1373 
1374  return true;
1375 }
1376 
1377 void IKFastKinematicsPlugin::transformToChainFrame(const geometry_msgs::Pose& ik_pose, KDL::Frame& ik_pose_chain) const
1378 {
1379  if (tip_transform_required_ || base_transform_required_)
1380  {
1381  Eigen::Isometry3d ik_eigen_pose;
1382  tf2::fromMsg(ik_pose, ik_eigen_pose);
1383  if (tip_transform_required_)
1384  ik_eigen_pose = ik_eigen_pose * group_tip_to_chain_tip_;
1385 
1386  if (base_transform_required_)
1387  ik_eigen_pose = chain_base_to_group_base_ * ik_eigen_pose;
1388 
1389  tf::transformEigenToKDL(ik_eigen_pose, ik_pose_chain);
1390  }
1391  else
1392  {
1393  tf2::fromMsg(ik_pose, ik_pose_chain);
1394  }
1395 }
1396 
1397 } // end namespace
1398 
1399 // register IKFastKinematicsPlugin as a KinematicsBase implementation
d
const std::string & getName() const
virtual const IkSolutionBase< T > & GetSolution(size_t index) const
returns the solution pointer
Definition: ikfast.h:283
KinematicError kinematic_error
const std::string & getName() const
number of parameterizations (does not count IKP_None)
std::size_t getVariableCount() const
PLUGINLIB_EXPORT_CLASS(prbt_manipulator::IKFastKinematicsPlugin, kinematics::KinematicsBase)
#define ROS_INFO_NAMED(name,...)
#define ROS_DEBUG_STREAM_NAMED(name, args)
#define ROS_ERROR_STREAM_NAMED(name, args)
const std::vector< std::string > & getLinkNames() const override
ROSCONSOLE_DECL void initialize()
virtual size_t GetNumSolutions() const
returns the number of solutions stored
Definition: ikfast.h:294
IKFAST_API int GetNumJoints()
IkParameterizationType
The types of inverse kinematics parameterizations supported.
direction on end effector coordinate system reaches desired direction
XmlRpcServer s
IKFAST_API bool ComputeIk(const IkReal *eetrans, const IkReal *eerot, const IkReal *pfree, IkSolutionListBase< IkReal > &solutions)
end effector origin reaches desired 3D translation
IMETHOD Vector diff(const Vector &p_w_a, const Vector &p_w_b, double dt=1)
end effector reaches desired 3D rotation
The discrete solutions are returned in this structure.
Definition: ikfast.h:70
IKFAST_API void ComputeFk(const IkReal *j, IkReal *eetrans, IkReal *eerot)
ray on end effector coordinate system reaches desired global ray
#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...
IKFAST_API int GetIkType()
void transformEigenToKDL(const Eigen::Affine3d &e, KDL::Frame &k)
bit is set if the data represents the time-derivate velocity of an IkParameterization ...
Rotation M
const JointModel * getParentJointModel() const
#define ROS_DEBUG_NAMED(name,...)
const double LIMIT_TOLERANCE
unsigned int index
#define ROS_WARN_STREAM_ONCE_NAMED(name, args)
end effector reaches desired 6D transformation
double data[3]
void fromMsg(const A &, B &b)
IKFAST_API int GetNumFreeParameters()
IKFAST_API int * GetFreeParameters()
DiscretizationMethod discretization_method
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
virtual void GetSolution(T *solution, const T *freevalues) const =0
gets a concrete solution
B toMsg(const A &a)
direction on end effector coordinate system points to desired 3D position
Default implementation of IkSolutionListBase.
Definition: ikfast.h:273
#define ROS_FATAL_NAMED(name,...)
#define ROS_ERROR_NAMED(name,...)
bool hasLinkModel(const std::string &name) const
const LinkModel * getParentLinkModel() const
const VariableBounds & getVariableBounds(const std::string &variable) const
r
#define ROS_ERROR(...)
JointType getType() const
local point on end effector origin reaches desired 3D global point
#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 Mon May 3 2021 02:19:27