167#include "_ROBOT_NAME___GROUP_NAME__ikfast_solver.cpp"
171 std::vector<std::string> joint_names_;
172 std::vector<double> joint_min_vector_;
173 std::vector<double> joint_max_vector_;
174 std::vector<bool> joint_has_limits_vector_;
175 std::vector<std::string> link_names_;
176 const size_t num_joints_;
177 std::vector<int> free_params_;
179 std::shared_ptr<ikfast_kinematics::ParamListener> param_listener_;
180 ikfast_kinematics::Params params_;
184 const std::string IKFAST_TIP_FRAME_ =
"_EEF_LINK_";
185 const std::string IKFAST_BASE_FRAME_ =
"_BASE_LINK_";
191 bool tip_transform_required_;
192 bool base_transform_required_;
196 Eigen::Isometry3d chain_base_to_group_base_;
197 Eigen::Isometry3d group_tip_to_chain_tip_;
201 const std::vector<std::string>&
getJointNames()
const override
205 const std::vector<std::string>&
getLinkNames()
const override
216 srand(time(
nullptr));
233 getPositionIK(
const geometry_msgs::msg::Pose& ik_pose,
const std::vector<double>& ik_seed_state,
234 std::vector<double>& solution, moveit_msgs::msg::MoveItErrorCodes& error_code,
252 bool getPositionIK(
const std::vector<geometry_msgs::msg::Pose>& ik_poses,
const std::vector<double>& ik_seed_state,
265 const geometry_msgs::msg::Pose& ik_pose,
const std::vector<double>& ik_seed_state,
double timeout,
266 std::vector<double>& solution, moveit_msgs::msg::MoveItErrorCodes& error_code,
279 const geometry_msgs::msg::Pose& ik_pose,
const std::vector<double>& ik_seed_state,
double timeout,
280 const std::vector<double>& consistency_limits, std::vector<double>& solution,
281 moveit_msgs::msg::MoveItErrorCodes& error_code,
293 const geometry_msgs::msg::Pose& ik_pose,
const std::vector<double>& ik_seed_state,
double timeout,
294 std::vector<double>& solution,
const IKCallbackFn& solution_callback,
295 moveit_msgs::msg::MoveItErrorCodes& error_code,
309 const geometry_msgs::msg::Pose& ik_pose,
const std::vector<double>& ik_seed_state,
double timeout,
310 const std::vector<double>& consistency_limits, std::vector<double>& solution,
311 const IKCallbackFn& solution_callback, moveit_msgs::msg::MoveItErrorCodes& error_code,
322 bool getPositionFK(
const std::vector<std::string>& link_names,
const std::vector<double>& joint_angles,
323 std::vector<geometry_msgs::msg::Pose>& poses)
const override;
339 bool setRedundantJoints(
const std::vector<unsigned int>& redundant_joint_indices)
override;
343 const std::string& group_name,
const std::string& base_frame,
344 const std::vector<std::string>& tip_frames,
double search_discretization)
override;
350 size_t solve(KDL::Frame& pose_frame,
const std::vector<double>& vfree, IkSolutionList<IkReal>& solutions)
const;
355 void getSolution(
const IkSolutionList<IkReal>& solutions,
int i, std::vector<double>& solution)
const;
360 void getSolution(
const IkSolutionList<IkReal>& solutions,
const std::vector<double>& ik_seed_state,
int i,
361 std::vector<double>& solution)
const;
366 double enforceLimits(
double val,
double min,
double max)
const;
368 void fillFreeParams(
int count,
int* array);
369 bool getCount(
int& count,
int max_count,
int min_count)
const;
380 bool computeRelativeTransform(
const std::string& from,
const std::string& to, Eigen::Isometry3d& transform,
381 bool& differs_from_identity);
388 void transformToChainFrame(
const geometry_msgs::msg::Pose& ik_pose, KDL::Frame& ik_pose_chain)
const;
391bool IKFastKinematicsPlugin::computeRelativeTransform(
const std::string& from,
const std::string& to,
392 Eigen::Isometry3d& transform,
bool& differs_from_identity)
394 RobotStatePtr robot_state;
395 robot_state = std::make_shared<RobotState>(
robot_model_);
396 robot_state->setToDefaultValues();
399 auto* from_link =
robot_model_->getLinkModel(from, &has_link);
400 auto* to_link =
robot_model_->getLinkModel(to, &has_link);
401 if (!from_link || !to_link)
404 if (
robot_model_->getRigidlyConnectedParentLinkModel(from_link) !=
405 robot_model_->getRigidlyConnectedParentLinkModel(to_link))
407 RCLCPP_ERROR_STREAM(
getLogger(),
"Link frames " << from <<
" and " << to <<
" are not rigidly connected.");
411 transform = robot_state->getGlobalLinkTransform(from_link).inverse() * robot_state->getGlobalLinkTransform(to_link);
412 differs_from_identity = !transform.matrix().isIdentity();
416bool IKFastKinematicsPlugin::initialize(
const rclcpp::Node::SharedPtr& node,
417 const moveit::core::RobotModel& robot_model,
const std::string& group_name,
418 const std::string& base_frame,
const std::vector<std::string>& tip_frames,
419 double search_discretization)
421 if (tip_frames.size() != 1)
423 RCLCPP_ERROR(
getLogger(),
"Expecting exactly one tip frame.");
428 std::string kinematics_param_prefix =
"robot_description_kinematics." + group_name;
429 param_listener_ = std::make_shared<ikfast_kinematics::ParamListener>(node, kinematics_param_prefix);
430 params_ = param_listener_->get_params();
432 storeValues(robot_model, group_name, base_frame, tip_frames, search_discretization);
434 RCLCPP_INFO_STREAM(
getLogger(),
"Using link_prefix: '" << params_.link_prefix <<
'\'');
442 if (!robot_model.
hasLinkModel(params_.link_prefix + IKFAST_TIP_FRAME_))
443 RCLCPP_ERROR_STREAM(
getLogger(),
"prefixed tip frame '" << params_.link_prefix + IKFAST_TIP_FRAME_
444 <<
"' does not exist. "
445 "Please check your link_prefix parameter.");
446 if (!robot_model.
hasLinkModel(params_.link_prefix + IKFAST_BASE_FRAME_))
447 RCLCPP_ERROR_STREAM(
getLogger(),
"prefixed base frame '" << params_.link_prefix + IKFAST_BASE_FRAME_
448 <<
"' does not exist. "
449 "Please check your link_prefix parameter.");
455 if (!computeRelativeTransform(
tip_frames_[0], params_.link_prefix + IKFAST_TIP_FRAME_, group_tip_to_chain_tip_,
456 tip_transform_required_) ||
457 !computeRelativeTransform(params_.link_prefix + IKFAST_BASE_FRAME_,
base_frame_, chain_base_to_group_base_,
458 base_transform_required_))
466 if (free_params_.size() > 1)
468 RCLCPP_ERROR(
getLogger(),
"Only one free joint parameter supported!");
471 else if (free_params_.size() == 1)
475 KinematicsBase::setSearchDiscretization(search_discretization);
478 const moveit::core::JointModelGroup* jmg =
robot_model_->getJointModelGroup(group_name);
481 RCLCPP_ERROR_STREAM(
getLogger(),
"Unknown planning group: " << group_name);
485 RCLCPP_DEBUG(
getLogger(),
"Registering joints and links");
488 while (link && link != base_link)
491 link_names_.push_back(link->
getName());
497 joint_names_.push_back(joint->
getName());
506 if (joint_names_.size() != num_joints_)
508 RCLCPP_FATAL(
getLogger(),
"Joint numbers of RobotModel (%zd) and IKFast solver (%zd) do not match",
509 joint_names_.size(), num_joints_);
513 std::reverse(link_names_.begin(), link_names_.end());
514 std::reverse(joint_names_.begin(), joint_names_.end());
515 std::reverse(joint_min_vector_.begin(), joint_min_vector_.end());
516 std::reverse(joint_max_vector_.begin(), joint_max_vector_.end());
517 std::reverse(joint_has_limits_vector_.begin(), joint_has_limits_vector_.end());
519 for (
size_t joint_id = 0; joint_id < num_joints_; ++joint_id)
520 RCLCPP_DEBUG_STREAM(
getLogger(), joint_names_[joint_id] <<
' ' << joint_min_vector_[joint_id] <<
' '
521 << joint_max_vector_[joint_id] <<
' '
522 << joint_has_limits_vector_[joint_id]);
530 if (discretization.empty())
532 RCLCPP_ERROR(
getLogger(),
"The 'discretization' map is empty");
538 RCLCPP_ERROR(
getLogger(),
"This group's solver doesn't support redundant joints");
544 std::string redundant_joint = joint_names_[free_params_[0]];
545 RCLCPP_ERROR_STREAM(
getLogger(),
"Attempted to discretize a non-redundant joint "
546 << discretization.begin()->first <<
", only joint '" << redundant_joint
551 if (discretization.begin()->second <= 0.0)
553 RCLCPP_ERROR_STREAM(
getLogger(),
"Discretization can not takes values that are <= 0");
563 RCLCPP_ERROR(
getLogger(),
"Changing the redundant joints isn't permitted by this group's solver ");
567size_t IKFastKinematicsPlugin::solve(KDL::Frame& pose_frame,
const std::vector<double>& vfree,
568 IkSolutionList<IkReal>& solutions)
const
574 trans[0] = pose_frame.p[0];
575 trans[1] = pose_frame.p[1];
576 trans[2] = pose_frame.p[2];
579 KDL::Vector direction;
590 vals[0] = mult(0, 0);
591 vals[1] = mult(0, 1);
592 vals[2] = mult(0, 2);
593 vals[3] = mult(1, 0);
594 vals[4] = mult(1, 1);
595 vals[5] = mult(1, 2);
596 vals[6] = mult(2, 0);
597 vals[7] = mult(2, 1);
598 vals[8] = mult(2, 2);
601 ComputeIk(trans, vals, vfree.size() > 0 ? &vfree[0] :
nullptr, solutions);
602 return solutions.GetNumSolutions();
610 direction = pose_frame.M * KDL::Vector(0, 0, 1);
611 ComputeIk(trans, direction.data, vfree.size() > 0 ? &vfree[0] :
nullptr, solutions);
612 return solutions.GetNumSolutions();
617 RCLCPP_ERROR(
getLogger(),
"IK for this IkParameterizationType not implemented yet.");
621 ComputeIk(trans, direction.data, vfree.size() > 0 ? &vfree[0] :
nullptr, solutions);
622 return solutions.GetNumSolutions();
627 RCLCPP_ERROR(
getLogger(),
"IK for this IkParameterizationType not implemented yet.");
635 double roll, pitch, yaw;
639 pose_frame.M.GetRPY(roll, pitch, yaw);
640 ComputeIk(trans, &yaw, vfree.size() > 0 ? &vfree[0] :
nullptr, solutions);
641 return solutions.GetNumSolutions();
648 pose_frame.M.GetRPY(roll, pitch, yaw);
649 ComputeIk(trans, &roll, vfree.size() > 0 ? &vfree[0] :
nullptr, solutions);
650 return solutions.GetNumSolutions();
657 pose_frame.M.GetRPY(roll, pitch, yaw);
658 ComputeIk(trans, &pitch, vfree.size() > 0 ? &vfree[0] :
nullptr, solutions);
659 return solutions.GetNumSolutions();
662 RCLCPP_ERROR(
getLogger(),
"Unknown IkParameterizationType! "
663 "Was the solver generated with an incompatible version of Openrave?");
668void IKFastKinematicsPlugin::getSolution(
const IkSolutionList<IkReal>& solutions,
int i,
669 std::vector<double>& solution)
const
672 solution.resize(num_joints_);
675 const IkSolutionBase<IkReal>& sol = solutions.GetSolution(i);
676 std::vector<IkReal> vsolfree(sol.GetFree().size());
677 sol.GetSolution(&solution[0], vsolfree.size() > 0 ? &vsolfree[0] :
nullptr);
679 for (std::size_t joint_id = 0; joint_id < num_joints_; ++joint_id)
681 if (joint_has_limits_vector_[joint_id])
683 solution[joint_id] = enforceLimits(solution[joint_id], joint_min_vector_[joint_id], joint_max_vector_[joint_id]);
688void IKFastKinematicsPlugin::getSolution(
const IkSolutionList<IkReal>& solutions,
689 const std::vector<double>& ik_seed_state,
int i,
690 std::vector<double>& solution)
const
693 solution.resize(num_joints_);
696 const IkSolutionBase<IkReal>& sol = solutions.GetSolution(i);
697 std::vector<IkReal> vsolfree(sol.GetFree().size());
698 sol.GetSolution(&solution[0], vsolfree.size() > 0 ? &vsolfree[0] :
nullptr);
701 for (std::size_t i = 0; i < num_joints_; ++i)
703 if (joint_has_limits_vector_[i])
705 solution[i] = enforceLimits(solution[i], joint_min_vector_[i], joint_max_vector_[i]);
706 double signed_distance = solution[i] - ik_seed_state[i];
707 while (signed_distance > M_PI && solution[i] - 2 * M_PI > (joint_min_vector_[i] -
LIMIT_TOLERANCE))
709 signed_distance -= 2 * M_PI;
710 solution[i] -= 2 * M_PI;
712 while (signed_distance < -M_PI && solution[i] + 2 * M_PI < (joint_max_vector_[i] +
LIMIT_TOLERANCE))
714 signed_distance += 2 * M_PI;
715 solution[i] += 2 * M_PI;
721double IKFastKinematicsPlugin::enforceLimits(
double joint_value,
double min,
double max)
const
724 while (joint_value > max)
726 joint_value -= 2 * M_PI;
730 while (joint_value < min)
732 joint_value += 2 * M_PI;
737void IKFastKinematicsPlugin::fillFreeParams(
int count,
int* array)
739 free_params_.clear();
740 for (
int i = 0; i < count; ++i)
741 free_params_.push_back(array[i]);
744bool IKFastKinematicsPlugin::getCount(
int& count,
int max_count,
int min_count)
const
748 if (-count >= min_count)
753 else if (count + 1 <= max_count)
765 if (1 - count <= max_count)
770 else if (count - 1 >= min_count)
781 const std::vector<double>& joint_angles,
782 std::vector<geometry_msgs::msg::Pose>& poses)
const
790 RCLCPP_ERROR(
getLogger(),
"Can only compute FK for Transform6D IK type!");
795 if (link_names.size() == 0)
797 RCLCPP_WARN_STREAM(
getLogger(),
"Link names with nothing");
801 if (link_names.size() != 1 || link_names[0] !=
getTipFrame())
809 IkReal eerot[9], eetrans[3];
811 if (joint_angles.size() != num_joints_)
813 RCLCPP_ERROR(
getLogger(),
"Unexpected number of joint angles");
818#pragma clang diagnostic push
819#pragma clang diagnostic ignored "-Wvla-cxx-extension"
821 IkReal angles[num_joints_];
823#pragma clang diagnostic pop
825 for (
unsigned char i = 0; i < num_joints_; ++i)
826 angles[i] = joint_angles[i];
831 for (
int i = 0; i < 3; ++i)
832 p_out.p.data[i] = eetrans[i];
834 for (
int i = 0; i < 9; ++i)
835 p_out.M.data[i] = eerot[i];
838 poses[0] = tf2::toMsg(p_out);
844 const std::vector<double>& ik_seed_state,
double timeout,
845 std::vector<double>& solution,
846 moveit_msgs::msg::MoveItErrorCodes& error_code,
849 std::vector<double> consistency_limits;
855 const std::vector<double>& ik_seed_state,
double timeout,
856 const std::vector<double>& consistency_limits,
857 std::vector<double>& solution,
858 moveit_msgs::msg::MoveItErrorCodes& error_code,
866 const std::vector<double>& ik_seed_state,
double timeout,
867 std::vector<double>& solution,
const IKCallbackFn& solution_callback,
868 moveit_msgs::msg::MoveItErrorCodes& error_code,
871 std::vector<double> consistency_limits;
872 return searchPositionIK(ik_pose, ik_seed_state, timeout, consistency_limits, solution, solution_callback, error_code,
877 const std::vector<double>& ik_seed_state,
double timeout,
878 const std::vector<double>& consistency_limits,
879 std::vector<double>& solution,
const IKCallbackFn& solution_callback,
880 moveit_msgs::msg::MoveItErrorCodes& error_code,
887 if (free_params_.size() == 0)
889 RCLCPP_DEBUG_STREAM(
getLogger(),
"No need to search since no free params/redundant joints");
891 std::vector<geometry_msgs::msg::Pose> ik_poses(1, ik_pose);
892 std::vector<std::vector<double>> solutions;
895 if (!
getPositionIK(ik_poses, ik_seed_state, solutions, kinematic_result, options))
897 RCLCPP_DEBUG(
getLogger(),
"No solution whatsoever");
898 error_code.val = moveit_msgs::msg::MoveItErrorCodes::NO_IK_SOLUTION;
903 std::vector<LimitObeyingSol> solutions_obey_limits;
904 for (std::size_t i = 0; i < solutions.size(); ++i)
906 double dist_from_seed = 0.0;
907 for (std::size_t j = 0; j < ik_seed_state.size(); ++j)
909 dist_from_seed += fabs(ik_seed_state[j] - solutions[i][j]);
912 solutions_obey_limits.push_back({ solutions[i], dist_from_seed });
914 std::sort(solutions_obey_limits.begin(), solutions_obey_limits.end());
917 if (solution_callback)
919 for (std::size_t i = 0; i < solutions_obey_limits.size(); ++i)
921 solution_callback(ik_pose, solutions_obey_limits[i].value, error_code);
922 if (error_code.val == moveit_msgs::msg::MoveItErrorCodes::SUCCESS)
924 solution = solutions_obey_limits[i].value;
925 RCLCPP_DEBUG(
getLogger(),
"Solution passes callback");
930 RCLCPP_DEBUG_STREAM(
getLogger(),
"Solution has error code " << error_code.val);
935 solution = solutions_obey_limits[0].value;
936 error_code.val = moveit_msgs::msg::MoveItErrorCodes::SUCCESS;
945 RCLCPP_ERROR(
getLogger(),
"Kinematics not active");
946 error_code.val = error_code.NO_IK_SOLUTION;
950 if (ik_seed_state.size() != num_joints_)
953 "Seed state must have size " << num_joints_ <<
" instead of size " << ik_seed_state.size());
954 error_code.val = error_code.NO_IK_SOLUTION;
958 if (!consistency_limits.empty() && consistency_limits.size() != num_joints_)
960 RCLCPP_ERROR_STREAM(
getLogger(),
"Consistency limits be empty or must have size "
961 << num_joints_ <<
" instead of size " << consistency_limits.size());
962 error_code.val = error_code.NO_IK_SOLUTION;
970 transformToChainFrame(ik_pose, frame);
972 std::vector<double> vfree(free_params_.size());
976 double initial_guess = ik_seed_state[free_params_[0]];
977 vfree[0] = initial_guess;
981 int num_positive_increments;
982 int num_negative_increments;
985 if (!consistency_limits.empty())
989 double max_limit = fmin(joint_max_vector_[free_params_[0]], initial_guess + consistency_limits[free_params_[0]]);
990 double min_limit = fmax(joint_min_vector_[free_params_[0]], initial_guess - consistency_limits[free_params_[0]]);
992 num_positive_increments =
static_cast<int>((max_limit - initial_guess) / search_discretization);
993 num_negative_increments =
static_cast<int>((initial_guess - min_limit) / search_discretization);
997 num_positive_increments = (joint_max_vector_[free_params_[0]] - initial_guess) / search_discretization;
998 num_negative_increments = (initial_guess - joint_min_vector_[free_params_[0]]) / search_discretization;
1004 RCLCPP_DEBUG_STREAM(
getLogger(),
"Free param is " << free_params_[0] <<
" initial guess is " << initial_guess
1005 <<
", # positive increments: " << num_positive_increments
1006 <<
", # negative increments: " << num_negative_increments);
1007 if ((search_mode &
OPTIMIZE_MAX_JOINT) && (num_positive_increments + num_negative_increments) > 1000)
1008 RCLCPP_WARN_STREAM_ONCE(
getLogger(),
"Large search space, consider increasing the search discretization");
1010 double best_costs = -1.0;
1011 std::vector<double> best_solution;
1012 int nattempts = 0, nvalid = 0;
1016 IkSolutionList<IkReal> solutions;
1017 size_t numsol = solve(frame, vfree, solutions);
1019 RCLCPP_DEBUG_STREAM(
getLogger(),
"Found " << numsol <<
" solutions from IKFast");
1023 for (
size_t s = 0; s < numsol; ++s)
1026 std::vector<double> sol;
1027 getSolution(solutions, ik_seed_state, s, sol);
1029 bool obeys_limits =
true;
1030 for (
size_t i = 0; i < sol.size(); ++i)
1032 if (joint_has_limits_vector_[i] && (sol[i] < joint_min_vector_[i] || sol[i] > joint_max_vector_[i]))
1034 obeys_limits =
false;
1042 getSolution(solutions, ik_seed_state, s, solution);
1045 if (solution_callback)
1047 solution_callback(ik_pose, solution, error_code);
1051 error_code.val = error_code.SUCCESS;
1054 if (error_code.val == error_code.SUCCESS)
1061 for (
unsigned int i = 0; i < solution.size(); ++i)
1063 double d = fabs(ik_seed_state[i] - solution[i]);
1067 if (costs < best_costs || best_costs == -1.0)
1070 best_solution = solution;
1081 if (!getCount(counter, num_positive_increments, -num_negative_increments))
1084 error_code.val = moveit_msgs::msg::MoveItErrorCodes::NO_IK_SOLUTION;
1088 vfree[0] = initial_guess + search_discretization * counter;
1092 RCLCPP_DEBUG_STREAM(
getLogger(),
"Valid solutions: " << nvalid <<
'/' << nattempts);
1096 solution = best_solution;
1097 error_code.val = error_code.SUCCESS;
1102 error_code.val = moveit_msgs::msg::MoveItErrorCodes::NO_IK_SOLUTION;
1108 const std::vector<double>& ik_seed_state, std::vector<double>& solution,
1109 moveit_msgs::msg::MoveItErrorCodes& error_code,
1112 RCLCPP_DEBUG_STREAM(
getLogger(),
"getPositionIK");
1116 RCLCPP_ERROR(
getLogger(),
"kinematics not active");
1120 if (ik_seed_state.size() < num_joints_)
1122 RCLCPP_ERROR_STREAM(
getLogger(),
"ik_seed_state only has " << ik_seed_state.size()
1123 <<
" entries, this ikfast solver requires "
1129 for (std::size_t i = 0; i < ik_seed_state.size(); ++i)
1132 if (joint_has_limits_vector_[i] && ((ik_seed_state[i] < (joint_min_vector_[i] -
LIMIT_TOLERANCE)) ||
1135 RCLCPP_DEBUG_STREAM(
getLogger(),
"IK seed not in limits! " <<
static_cast<int>(i) <<
" value " << ik_seed_state[i]
1136 <<
" has limit: " << joint_has_limits_vector_[i]
1137 <<
" being " << joint_min_vector_[i] <<
" to "
1138 << joint_max_vector_[i]);
1143 std::vector<double> vfree(free_params_.size());
1144 for (std::size_t i = 0; i < free_params_.size(); ++i)
1146 int p = free_params_[i];
1147 RCLCPP_ERROR(
getLogger(),
"%u is %f", p, ik_seed_state[p]);
1148 vfree[i] = ik_seed_state[p];
1152 transformToChainFrame(ik_pose, frame);
1154 IkSolutionList<IkReal> solutions;
1155 size_t numsol = solve(frame, vfree, solutions);
1156 RCLCPP_DEBUG_STREAM(
getLogger(),
"Found " << numsol <<
" solutions from IKFast");
1158 std::vector<LimitObeyingSol> solutions_obey_limits;
1162 std::vector<double> solution_obey_limits;
1163 for (std::size_t s = 0; s < numsol; ++s)
1165 std::vector<double> sol;
1166 getSolution(solutions, ik_seed_state, s, sol);
1167 RCLCPP_DEBUG(
getLogger(),
"Sol %d: %e %e %e %e %e %e",
static_cast<int>(s), sol[0], sol[1], sol[2],
1168 sol[3], sol[4], sol[5]);
1170 bool obeys_limits =
true;
1171 for (std::size_t i = 0; i < sol.size(); ++i)
1174 if (joint_has_limits_vector_[i] && ((sol[i] < (joint_min_vector_[i] -
LIMIT_TOLERANCE)) ||
1178 obeys_limits =
false;
1179 RCLCPP_DEBUG_STREAM(
getLogger(),
"Not in limits! " <<
static_cast<int>(i) <<
" value " << sol[i]
1180 <<
" has limit: " << joint_has_limits_vector_[i]
1181 <<
" being " << joint_min_vector_[i] <<
" to "
1182 << joint_max_vector_[i]);
1189 getSolution(solutions, ik_seed_state, s, solution_obey_limits);
1190 double dist_from_seed = 0.0;
1191 for (std::size_t i = 0; i < ik_seed_state.size(); ++i)
1193 dist_from_seed += fabs(ik_seed_state[i] - solution_obey_limits[i]);
1196 solutions_obey_limits.push_back({ solution_obey_limits, dist_from_seed });
1202 RCLCPP_DEBUG(
getLogger(),
"No IK solution");
1206 if (!solutions_obey_limits.empty())
1208 std::sort(solutions_obey_limits.begin(), solutions_obey_limits.end());
1209 solution = solutions_obey_limits[0].value;
1210 error_code.val = moveit_msgs::msg::MoveItErrorCodes::SUCCESS;
1214 error_code.val = moveit_msgs::msg::MoveItErrorCodes::NO_IK_SOLUTION;
1219 const std::vector<double>& ik_seed_state,
1220 std::vector<std::vector<double>>& solutions,
1224 RCLCPP_DEBUG_STREAM(
getLogger(),
"getPositionIK with multiple solutions");
1228 RCLCPP_ERROR(
getLogger(),
"kinematics not active");
1233 if (ik_poses.empty())
1235 RCLCPP_ERROR(
getLogger(),
"ik_poses is empty");
1240 if (ik_poses.size() > 1)
1242 RCLCPP_ERROR(
getLogger(),
"ik_poses contains multiple entries, only one is allowed");
1247 if (ik_seed_state.size() < num_joints_)
1249 RCLCPP_ERROR_STREAM(
getLogger(),
"ik_seed_state only has " << ik_seed_state.size()
1250 <<
" entries, this ikfast solver requires "
1256 transformToChainFrame(ik_poses[0], frame);
1259 std::vector<IkSolutionList<IkReal>> solution_set;
1260 IkSolutionList<IkReal> ik_solutions;
1261 std::vector<double> vfree;
1263 std::vector<double> sampled_joint_vals;
1276 double jv = sampled_joint_vals[0];
1280 RCLCPP_ERROR_STREAM(
getLogger(),
"ik seed is out of bounds");
1286 if (!sampleRedundantJoint(options.discretization_method, sampled_joint_vals))
1292 for (
unsigned int i = 0; i < sampled_joint_vals.size(); ++i)
1295 vfree.push_back(sampled_joint_vals[i]);
1296 numsol += solve(frame, vfree, ik_solutions);
1297 solution_set.push_back(ik_solutions);
1303 numsol = solve(frame, vfree, ik_solutions);
1304 solution_set.push_back(ik_solutions);
1307 RCLCPP_DEBUG_STREAM(
getLogger(),
"Found " << numsol <<
" solutions from IKFast");
1308 bool solutions_found =
false;
1314 for (
unsigned int r = 0; r < solution_set.size(); ++r)
1316 ik_solutions = solution_set[r];
1317 numsol = ik_solutions.GetNumSolutions();
1318 for (
int s = 0; s < numsol; ++s)
1320 std::vector<double> sol;
1321 getSolution(ik_solutions, ik_seed_state, s, sol);
1323 bool obeys_limits =
true;
1324 for (
unsigned int i = 0; i < sol.size(); ++i)
1327 if (joint_has_limits_vector_[i] && ((sol[i] < (joint_min_vector_[i] -
LIMIT_TOLERANCE)) ||
1331 obeys_limits =
false;
1332 RCLCPP_DEBUG_STREAM(
getLogger(),
"Not in limits! " << i <<
" value " << sol[i]
1333 <<
" has limit: " << joint_has_limits_vector_[i]
1334 <<
" being " << joint_min_vector_[i] <<
" to "
1335 << joint_max_vector_[i]);
1342 solutions_found =
true;
1343 solutions.push_back(sol);
1348 if (solutions_found)
1356 RCLCPP_DEBUG_STREAM(
getLogger(),
"No IK solution");
1364 std::vector<double>& sampled_joint_vals)
const
1368 double joint_min = joint_min_vector_[index];
1369 double joint_max = joint_max_vector_[index];
1375 size_t steps = std::ceil((joint_max - joint_min) / joint_dscrt);
1376 for (
size_t i = 0; i < steps; ++i)
1378 sampled_joint_vals.push_back(joint_min + joint_dscrt * i);
1380 sampled_joint_vals.push_back(joint_max);
1385 int steps = std::ceil((joint_max - joint_min) / joint_dscrt);
1386 steps = steps > 0 ? steps : 1;
1387 double diff = joint_max - joint_min;
1388 for (
int i = 0; i < steps; ++i)
1390 sampled_joint_vals.push_back(((diff * std::rand()) / (
static_cast<double>(RAND_MAX))) + joint_min);
1399 RCLCPP_ERROR_STREAM(
getLogger(),
"Discretization method " << method <<
" is not supported");
1406void IKFastKinematicsPlugin::transformToChainFrame(
const geometry_msgs::msg::Pose& ik_pose,
1407 KDL::Frame& ik_pose_chain)
const
1409 if (tip_transform_required_ || base_transform_required_)
1411 Eigen::Isometry3d ik_eigen_pose;
1412 tf2::fromMsg(ik_pose, ik_eigen_pose);
1413 if (tip_transform_required_)
1414 ik_eigen_pose = ik_eigen_pose * group_tip_to_chain_tip_;
1416 if (base_transform_required_)
1417 ik_eigen_pose = chain_base_to_group_base_ * ik_eigen_pose;
1419 tf2::fromMsg(tf2::toMsg(ik_eigen_pose), ik_pose_chain);
1423 tf2::fromMsg(ik_pose, ik_pose_chain);