45 #include <Eigen/Geometry>
46 #include <tf2_eigen_kdl/tf2_eigen_kdl.hpp>
47 #include <rclcpp/logger.hpp>
48 #include <rclcpp/logging.hpp>
49 #include <rclcpp/node.hpp>
50 #include <rclcpp/parameter_value.hpp>
51 #include <tf2_eigen/tf2_eigen.hpp>
52 #include <tf2_kdl/tf2_kdl.hpp>
70 #define IKFAST_NO_MAIN
152 return dist_from_seed <
a.dist_from_seed;
156 static const rclcpp::Logger LOGGER = rclcpp::get_logger(
"ikfast");
164 std::vector<std::string> joint_names_;
165 std::vector<double> joint_min_vector_;
166 std::vector<double> joint_max_vector_;
167 std::vector<bool> joint_has_limits_vector_;
168 std::vector<std::string> link_names_;
169 const size_t num_joints_;
170 std::vector<int> free_params_;
174 const std::string IKFAST_TIP_FRAME_ =
"flange";
175 const std::string IKFAST_BASE_FRAME_ =
"base_link";
178 std::string link_prefix_;
184 bool tip_transform_required_;
185 bool base_transform_required_;
189 Eigen::Isometry3d chain_base_to_group_base_;
190 Eigen::Isometry3d group_tip_to_chain_tip_;
194 const std::vector<std::string>& getJointNames()
const override
198 const std::vector<std::string>& getLinkNames()
const override
209 srand(time(
nullptr));
226 const geometry_msgs::msg::Pose& ik_pose,
const std::vector<double>& ik_seed_state, std::vector<double>& solution,
227 moveit_msgs::msg::MoveItErrorCodes& error_code,
245 bool getPositionIK(
const std::vector<geometry_msgs::msg::Pose>& ik_poses,
const std::vector<double>& ik_seed_state,
257 bool searchPositionIK(
258 const geometry_msgs::msg::Pose& ik_pose,
const std::vector<double>& ik_seed_state,
double timeout,
259 std::vector<double>& solution, moveit_msgs::msg::MoveItErrorCodes& error_code,
271 bool searchPositionIK(
272 const geometry_msgs::msg::Pose& ik_pose,
const std::vector<double>& ik_seed_state,
double timeout,
273 const std::vector<double>& consistency_limits, std::vector<double>& solution,
274 moveit_msgs::msg::MoveItErrorCodes& error_code,
285 bool searchPositionIK(
286 const geometry_msgs::msg::Pose& ik_pose,
const std::vector<double>& ik_seed_state,
double timeout,
287 std::vector<double>& solution,
const IKCallbackFn& solution_callback, moveit_msgs::msg::MoveItErrorCodes& error_code,
300 bool searchPositionIK(
301 const geometry_msgs::msg::Pose& ik_pose,
const std::vector<double>& ik_seed_state,
double timeout,
302 const std::vector<double>& consistency_limits, std::vector<double>& solution,
303 const IKCallbackFn& solution_callback, moveit_msgs::msg::MoveItErrorCodes& error_code,
314 bool getPositionFK(
const std::vector<std::string>& link_names,
const std::vector<double>& joint_angles,
315 std::vector<geometry_msgs::msg::Pose>& poses)
const override;
326 void setSearchDiscretization(
const std::map<unsigned int, double>& discretization);
331 bool setRedundantJoints(
const std::vector<unsigned int>& redundant_joint_indices)
override;
334 bool initialize(
const rclcpp::Node::SharedPtr& node,
const moveit::core::RobotModel& robot_model,
const std::string& group_name,
335 const std::string& base_frame,
const std::vector<std::string>& tip_frames,
336 double search_discretization)
override;
342 size_t solve(KDL::Frame& pose_frame,
const std::vector<double>& vfree,
IkSolutionList<IkReal>& solutions)
const;
352 void getSolution(
const IkSolutionList<IkReal>& solutions,
const std::vector<double>& ik_seed_state,
int i,
353 std::vector<double>& solution)
const;
358 double enforceLimits(
double val,
double min,
double max)
const;
360 void fillFreeParams(
int count,
int* array);
361 bool getCount(
int& count,
const int& max_count,
const int& min_count)
const;
372 bool computeRelativeTransform(
const std::string& from,
const std::string& to, Eigen::Isometry3d& transform,
373 bool& differs_from_identity);
380 void transformToChainFrame(
const geometry_msgs::msg::Pose& ik_pose, KDL::Frame& ik_pose_chain)
const;
383 bool IKFastKinematicsPlugin::computeRelativeTransform(
const std::string& from,
const std::string& to,
384 Eigen::Isometry3d& transform,
bool& differs_from_identity)
386 RobotStatePtr robot_state = std::make_shared<RobotState>(robot_model_);
387 robot_state->setToDefaultValues();
389 auto* from_link = robot_model_->getLinkModel(from);
390 auto* to_link = robot_model_->getLinkModel(to);
391 if (!from_link || !to_link)
394 if (robot_model_->getRigidlyConnectedParentLinkModel(from_link) !=
395 robot_model_->getRigidlyConnectedParentLinkModel(to_link))
397 RCLCPP_ERROR_STREAM(LOGGER,
"Link frames " << from <<
" and " << to <<
" are not rigidly connected.");
401 transform = robot_state->getGlobalLinkTransform(from_link).inverse() * robot_state->getGlobalLinkTransform(to_link);
402 differs_from_identity = !transform.matrix().isIdentity();
406 bool IKFastKinematicsPlugin::initialize(
const rclcpp::Node::SharedPtr& node,
const moveit::core::RobotModel& robot_model,
const std::string& group_name,
407 const std::string& base_frame,
const std::vector<std::string>& tip_frames,
408 double search_discretization)
410 if (tip_frames.size() != 1)
412 RCLCPP_ERROR(LOGGER,
"Expecting exactly one tip frame.");
416 storeValues(robot_model, group_name, base_frame, tip_frames, search_discretization);
417 if (!lookupParam(node,
"link_prefix", link_prefix_, std::string(
"")))
419 RCLCPP_INFO(LOGGER,
"Using empty link_prefix.");
423 RCLCPP_INFO_STREAM(LOGGER,
"Using link_prefix: '" << link_prefix_ <<
"'");
428 RCLCPP_ERROR_STREAM(LOGGER,
"tip frame '" << tip_frames_[0] <<
"' does not exist.");
430 RCLCPP_ERROR_STREAM(LOGGER,
"base_frame '" << base_frame_ <<
"' does not exist.");
432 if (!robot_model.
hasLinkModel(link_prefix_ + IKFAST_TIP_FRAME_))
433 RCLCPP_ERROR_STREAM(LOGGER,
"prefixed tip frame '" << link_prefix_ + IKFAST_TIP_FRAME_
434 <<
"' does not exist. "
435 "Please check your link_prefix parameter.");
436 if (!robot_model.
hasLinkModel(link_prefix_ + IKFAST_BASE_FRAME_))
437 RCLCPP_ERROR_STREAM(LOGGER,
"prefixed base frame '" << link_prefix_ + IKFAST_BASE_FRAME_
438 <<
"' does not exist. "
439 "Please check your link_prefix parameter.");
445 if (!computeRelativeTransform(tip_frames_[0], link_prefix_ + IKFAST_TIP_FRAME_, group_tip_to_chain_tip_,
446 tip_transform_required_) ||
447 !computeRelativeTransform(link_prefix_ + IKFAST_BASE_FRAME_, base_frame_, chain_base_to_group_base_,
448 base_transform_required_))
456 if (free_params_.size() > 1)
458 RCLCPP_ERROR(LOGGER,
"Only one free joint parameter supported!");
461 else if (free_params_.size() == 1)
463 redundant_joint_indices_.clear();
464 redundant_joint_indices_.push_back(free_params_[0]);
465 KinematicsBase::setSearchDiscretization(search_discretization);
471 RCLCPP_ERROR_STREAM(LOGGER,
"Unknown planning group: " << group_name);
475 RCLCPP_DEBUG_STREAM(LOGGER,
"Registering joints and links");
478 while (link && link != base_link)
480 RCLCPP_DEBUG_STREAM(LOGGER,
"Link " << link->
getName());
481 link_names_.push_back(link->
getName());
485 RCLCPP_DEBUG_STREAM(LOGGER,
"Adding joint " << joint->
getName());
487 joint_names_.push_back(joint->
getName());
496 if (joint_names_.size() != num_joints_)
498 RCLCPP_FATAL(LOGGER,
"Joint numbers of RobotModel (%zd) and IKFast solver (%zd) do not match", joint_names_.size(),
503 std::reverse(link_names_.begin(), link_names_.end());
504 std::reverse(joint_names_.begin(), joint_names_.end());
505 std::reverse(joint_min_vector_.begin(), joint_min_vector_.end());
506 std::reverse(joint_max_vector_.begin(), joint_max_vector_.end());
507 std::reverse(joint_has_limits_vector_.begin(), joint_has_limits_vector_.end());
509 for (
size_t joint_id = 0; joint_id < num_joints_; ++joint_id)
510 RCLCPP_DEBUG_STREAM(LOGGER, joint_names_[joint_id] <<
" " << joint_min_vector_[joint_id] <<
" "
511 << joint_max_vector_[joint_id] <<
" "
512 << joint_has_limits_vector_[joint_id]);
518 void IKFastKinematicsPlugin::setSearchDiscretization(
const std::map<unsigned int, double>& discretization)
520 if (discretization.empty())
522 RCLCPP_ERROR(LOGGER,
"The 'discretization' map is empty");
526 if (redundant_joint_indices_.empty())
528 RCLCPP_ERROR_STREAM(LOGGER,
"This group's solver doesn't support redundant joints");
532 if (discretization.begin()->first != redundant_joint_indices_[0])
534 std::string redundant_joint = joint_names_[free_params_[0]];
535 RCLCPP_ERROR_STREAM(LOGGER,
"Attempted to discretize a non-redundant joint "
536 << discretization.begin()->first <<
", only joint '" << redundant_joint
537 <<
"' with index " << redundant_joint_indices_[0] <<
" is redundant.");
541 if (discretization.begin()->second <= 0.0)
543 RCLCPP_ERROR_STREAM(LOGGER,
"Discretization can not takes values that are <= 0");
547 redundant_joint_discretization_.clear();
548 redundant_joint_discretization_[redundant_joint_indices_[0]] = discretization.begin()->second;
551 bool IKFastKinematicsPlugin::setRedundantJoints(
const std::vector<unsigned int>& )
553 RCLCPP_ERROR_STREAM(LOGGER,
"Changing the redundant joints isn't permitted by this group's solver ");
557 size_t IKFastKinematicsPlugin::solve(KDL::Frame& pose_frame,
const std::vector<double>& vfree,
564 trans[0] = pose_frame.p[0];
565 trans[1] = pose_frame.p[1];
566 trans[2] = pose_frame.p[2];
569 KDL::Vector direction;
580 vals[0] = mult(0, 0);
581 vals[1] = mult(0, 1);
582 vals[2] = mult(0, 2);
583 vals[3] = mult(1, 0);
584 vals[4] = mult(1, 1);
585 vals[5] = mult(1, 2);
586 vals[6] = mult(2, 0);
587 vals[7] = mult(2, 1);
588 vals[8] = mult(2, 2);
591 ComputeIk(trans, vals, vfree.size() > 0 ? &vfree[0] :
nullptr, solutions);
600 direction = pose_frame.M * KDL::Vector(0, 0, 1);
601 ComputeIk(trans, direction.data, vfree.size() > 0 ? &vfree[0] :
nullptr, solutions);
610 RCLCPP_ERROR(LOGGER,
"IK for this IkParameterizationType not implemented yet.");
616 RCLCPP_ERROR(LOGGER,
"IK for this IkParameterizationType not implemented yet.");
623 RCLCPP_ERROR(LOGGER,
"IK for this IkParameterizationType not implemented yet.");
627 double roll, pitch, yaw;
631 pose_frame.M.GetRPY(roll, pitch, yaw);
632 ComputeIk(trans, &yaw, vfree.size() > 0 ? &vfree[0] :
nullptr, solutions);
639 pose_frame.M.GetRPY(roll, pitch, yaw);
640 ComputeIk(trans, &roll, vfree.size() > 0 ? &vfree[0] :
nullptr, solutions);
647 pose_frame.M.GetRPY(roll, pitch, yaw);
648 ComputeIk(trans, &pitch, vfree.size() > 0 ? &vfree[0] :
nullptr, solutions);
652 RCLCPP_ERROR(LOGGER,
"Unknown IkParameterizationType! "
653 "Was the solver generated with an incompatible version of Openrave?");
659 std::vector<double>& solution)
const
662 solution.resize(num_joints_);
666 std::vector<IkReal> vsolfree(sol.
GetFree().size());
667 sol.
GetSolution(&solution[0], vsolfree.size() > 0 ? &vsolfree[0] :
nullptr);
669 for (std::size_t joint_id = 0; joint_id < num_joints_; ++joint_id)
671 if (joint_has_limits_vector_[joint_id])
673 solution[joint_id] = enforceLimits(solution[joint_id], joint_min_vector_[joint_id], joint_max_vector_[joint_id]);
679 const std::vector<double>& ik_seed_state,
int i,
680 std::vector<double>& solution)
const
683 solution.resize(num_joints_);
687 std::vector<IkReal> vsolfree(sol.
GetFree().size());
688 sol.
GetSolution(&solution[0], vsolfree.size() > 0 ? &vsolfree[0] :
nullptr);
691 for (std::size_t i = 0; i < num_joints_; ++i)
693 if (joint_has_limits_vector_[i])
695 solution[i] = enforceLimits(solution[i], joint_min_vector_[i], joint_max_vector_[i]);
696 double signed_distance = solution[i] - ik_seed_state[i];
697 while (signed_distance > M_PI && solution[i] - 2 * M_PI > (joint_min_vector_[i] -
LIMIT_TOLERANCE))
699 signed_distance -= 2 * M_PI;
700 solution[i] -= 2 * M_PI;
702 while (signed_distance < -M_PI && solution[i] + 2 * M_PI < (joint_max_vector_[i] +
LIMIT_TOLERANCE))
704 signed_distance += 2 * M_PI;
705 solution[i] += 2 * M_PI;
711 double IKFastKinematicsPlugin::enforceLimits(
double joint_value,
double min,
double max)
const
714 while (joint_value > max)
716 joint_value -= 2 * M_PI;
720 while (joint_value < min)
722 joint_value += 2 * M_PI;
727 void IKFastKinematicsPlugin::fillFreeParams(
int count,
int* array)
729 free_params_.clear();
730 for (
int i = 0; i < count; ++i)
731 free_params_.push_back(array[i]);
734 bool IKFastKinematicsPlugin::getCount(
int& count,
const int& max_count,
const int& min_count)
const
738 if (-count >= min_count)
743 else if (count + 1 <= max_count)
755 if (1 - count <= max_count)
760 else if (count - 1 >= min_count)
770 bool IKFastKinematicsPlugin::getPositionFK(
const std::vector<std::string>& link_names,
771 const std::vector<double>& joint_angles,
772 std::vector<geometry_msgs::msg::Pose>& poses)
const
780 RCLCPP_ERROR(LOGGER,
"Can only compute FK for Transform6D IK type!");
785 if (link_names.size() == 0)
787 RCLCPP_WARN_STREAM(LOGGER,
"Link names with nothing");
791 if (link_names.size() != 1 || link_names[0] != getTipFrame())
793 RCLCPP_ERROR(LOGGER,
"Can compute FK for %s only", getTipFrame().c_str());
799 IkReal eerot[9], eetrans[3];
801 if (joint_angles.size() != num_joints_)
803 RCLCPP_ERROR(LOGGER,
"Unexpected number of joint angles");
807 std::vector<IkReal> angles(num_joints_, 0);
808 for (
unsigned char i = 0; i < num_joints_; i++)
809 angles[i] = joint_angles[i];
812 ComputeFk(angles.data(), eetrans, eerot);
814 for (
int i = 0; i < 3; ++i)
815 p_out.p.data[i] = eetrans[i];
817 for (
int i = 0; i < 9; ++i)
818 p_out.M.data[i] = eerot[i];
821 poses[0] = tf2::toMsg(p_out);
826 bool IKFastKinematicsPlugin::searchPositionIK(
const geometry_msgs::msg::Pose& ik_pose,
827 const std::vector<double>& ik_seed_state,
double timeout,
828 std::vector<double>& solution, moveit_msgs::msg::MoveItErrorCodes& error_code,
831 std::vector<double> consistency_limits;
832 return searchPositionIK(ik_pose, ik_seed_state, timeout, consistency_limits, solution,
IKCallbackFn(), error_code,
836 bool IKFastKinematicsPlugin::searchPositionIK(
const geometry_msgs::msg::Pose& ik_pose,
837 const std::vector<double>& ik_seed_state,
double timeout,
838 const std::vector<double>& consistency_limits,
839 std::vector<double>& solution, moveit_msgs::msg::MoveItErrorCodes& error_code,
842 return searchPositionIK(ik_pose, ik_seed_state, timeout, consistency_limits, solution,
IKCallbackFn(), error_code,
846 bool IKFastKinematicsPlugin::searchPositionIK(
const geometry_msgs::msg::Pose& ik_pose,
847 const std::vector<double>& ik_seed_state,
double timeout,
848 std::vector<double>& solution,
const IKCallbackFn& solution_callback,
849 moveit_msgs::msg::MoveItErrorCodes& error_code,
852 std::vector<double> consistency_limits;
853 return searchPositionIK(ik_pose, ik_seed_state, timeout, consistency_limits, solution, solution_callback, error_code,
857 bool IKFastKinematicsPlugin::searchPositionIK(
const geometry_msgs::msg::Pose& ik_pose,
858 const std::vector<double>& ik_seed_state,
double ,
859 const std::vector<double>& consistency_limits,
860 std::vector<double>& solution,
const IKCallbackFn& solution_callback,
861 moveit_msgs::msg::MoveItErrorCodes& error_code,
868 if (free_params_.size() == 0)
870 RCLCPP_DEBUG_STREAM(LOGGER,
"No need to search since no free params/redundant joints");
872 std::vector<geometry_msgs::msg::Pose> ik_poses(1, ik_pose);
873 std::vector<std::vector<double>> solutions;
876 if (!getPositionIK(ik_poses, ik_seed_state, solutions, kinematic_result,
options))
878 RCLCPP_DEBUG_STREAM(LOGGER,
"No solution whatsoever");
879 error_code.val = moveit_msgs::msg::MoveItErrorCodes::NO_IK_SOLUTION;
884 std::vector<LimitObeyingSol> solutions_obey_limits;
885 for (std::size_t i = 0; i < solutions.size(); ++i)
887 double dist_from_seed = 0.0;
888 for (std::size_t j = 0; j < ik_seed_state.size(); ++j)
890 dist_from_seed += fabs(ik_seed_state[j] - solutions[i][j]);
893 solutions_obey_limits.push_back({ solutions[i], dist_from_seed });
895 std::sort(solutions_obey_limits.begin(), solutions_obey_limits.end());
898 if (solution_callback)
900 for (std::size_t i = 0; i < solutions_obey_limits.size(); ++i)
902 solution_callback(ik_pose, solutions_obey_limits[i].value, error_code);
903 if (error_code.val == moveit_msgs::msg::MoveItErrorCodes::SUCCESS)
905 solution = solutions_obey_limits[i].value;
906 RCLCPP_DEBUG_STREAM(LOGGER,
"Solution passes callback");
911 RCLCPP_DEBUG_STREAM(LOGGER,
"Solution has error code " << error_code.val);
916 solution = solutions_obey_limits[0].value;
917 error_code.val = moveit_msgs::msg::MoveItErrorCodes::SUCCESS;
926 RCLCPP_ERROR_STREAM(LOGGER,
"Kinematics not active");
927 error_code.val = error_code.NO_IK_SOLUTION;
931 if (ik_seed_state.size() != num_joints_)
933 RCLCPP_ERROR_STREAM(LOGGER,
934 "Seed state must have size " << num_joints_ <<
" instead of size " << ik_seed_state.size());
935 error_code.val = error_code.NO_IK_SOLUTION;
939 if (!consistency_limits.empty() && consistency_limits.size() != num_joints_)
941 RCLCPP_ERROR_STREAM(LOGGER,
"Consistency limits be empty or must have size " << num_joints_ <<
" instead of size "
942 << consistency_limits.size());
943 error_code.val = error_code.NO_IK_SOLUTION;
951 transformToChainFrame(ik_pose, frame);
953 std::vector<double> vfree(free_params_.size());
957 double initial_guess = ik_seed_state[free_params_[0]];
958 vfree[0] = initial_guess;
962 int num_positive_increments;
963 int num_negative_increments;
964 double search_discretization = redundant_joint_discretization_.at(free_params_[0]);
966 if (!consistency_limits.empty())
970 double max_limit = fmin(joint_max_vector_[free_params_[0]], initial_guess + consistency_limits[free_params_[0]]);
971 double min_limit = fmax(joint_min_vector_[free_params_[0]], initial_guess - consistency_limits[free_params_[0]]);
973 num_positive_increments =
static_cast<int>((max_limit - initial_guess) / search_discretization);
974 num_negative_increments =
static_cast<int>((initial_guess - min_limit) / search_discretization);
978 num_positive_increments = (joint_max_vector_[free_params_[0]] - initial_guess) / search_discretization;
979 num_negative_increments = (initial_guess - joint_min_vector_[free_params_[0]]) / search_discretization;
985 RCLCPP_DEBUG_STREAM(LOGGER,
"Free param is " << free_params_[0] <<
" initial guess is " << initial_guess
986 <<
", # positive increments: " << num_positive_increments
987 <<
", # negative increments: " << num_negative_increments);
988 if ((search_mode &
OPTIMIZE_MAX_JOINT) && (num_positive_increments + num_negative_increments) > 1000)
989 RCLCPP_WARN_STREAM_ONCE(LOGGER,
"Large search space, consider increasing the search discretization");
991 double best_costs = -1.0;
992 std::vector<double> best_solution;
993 int nattempts = 0, nvalid = 0;
998 size_t numsol = solve(frame, vfree, solutions);
1000 RCLCPP_DEBUG_STREAM(LOGGER,
"Found " << numsol <<
" solutions from IKFast");
1004 for (
size_t s = 0; s < numsol; ++s)
1007 std::vector<double> sol;
1008 getSolution(solutions, ik_seed_state, s, sol);
1010 bool obeys_limits =
true;
1011 for (
size_t i = 0; i < sol.size(); i++)
1013 if (joint_has_limits_vector_[i] && (sol[i] < joint_min_vector_[i] || sol[i] > joint_max_vector_[i]))
1015 obeys_limits =
false;
1023 getSolution(solutions, ik_seed_state, s, solution);
1026 if (solution_callback)
1028 solution_callback(ik_pose, solution, error_code);
1032 error_code.val = error_code.SUCCESS;
1035 if (error_code.val == error_code.SUCCESS)
1042 for (
unsigned int i = 0; i < solution.size(); i++)
1044 double d = fabs(ik_seed_state[i] - solution[i]);
1048 if (costs < best_costs || best_costs == -1.0)
1051 best_solution = solution;
1062 if (!getCount(counter, num_positive_increments, -num_negative_increments))
1065 error_code.val = moveit_msgs::msg::MoveItErrorCodes::NO_IK_SOLUTION;
1069 vfree[0] = initial_guess + search_discretization * counter;
1073 RCLCPP_DEBUG_STREAM(LOGGER,
"Valid solutions: " << nvalid <<
"/" << nattempts);
1077 solution = best_solution;
1078 error_code.val = error_code.SUCCESS;
1083 error_code.val = moveit_msgs::msg::MoveItErrorCodes::NO_IK_SOLUTION;
1088 bool IKFastKinematicsPlugin::getPositionIK(
const geometry_msgs::msg::Pose& ik_pose,
const std::vector<double>& ik_seed_state,
1089 std::vector<double>& solution, moveit_msgs::msg::MoveItErrorCodes& error_code,
1092 RCLCPP_DEBUG_STREAM(LOGGER,
"getPositionIK");
1096 RCLCPP_ERROR(LOGGER,
"kinematics not active");
1100 if (ik_seed_state.size() < num_joints_)
1102 RCLCPP_ERROR_STREAM(LOGGER,
"ik_seed_state only has " << ik_seed_state.size()
1103 <<
" entries, this ikfast solver requires " << num_joints_);
1108 for (std::size_t i = 0; i < ik_seed_state.size(); i++)
1111 if (joint_has_limits_vector_[i] && ((ik_seed_state[i] < (joint_min_vector_[i] -
LIMIT_TOLERANCE)) ||
1114 RCLCPP_DEBUG_STREAM(LOGGER,
"IK seed not in limits! " <<
static_cast<int>(i) <<
" value " << ik_seed_state[i]
1115 <<
" has limit: " << joint_has_limits_vector_[i] <<
" being "
1116 << joint_min_vector_[i] <<
" to " << joint_max_vector_[i]);
1121 std::vector<double> vfree(free_params_.size());
1122 for (std::size_t i = 0; i < free_params_.size(); ++i)
1124 int p = free_params_[i];
1125 RCLCPP_ERROR(LOGGER,
"%u is %f",
p, ik_seed_state[
p]);
1126 vfree[i] = ik_seed_state[
p];
1130 transformToChainFrame(ik_pose, frame);
1133 size_t numsol = solve(frame, vfree, solutions);
1134 RCLCPP_DEBUG_STREAM(LOGGER,
"Found " << numsol <<
" solutions from IKFast");
1136 std::vector<LimitObeyingSol> solutions_obey_limits;
1140 std::vector<double> solution_obey_limits;
1141 for (std::size_t s = 0; s < numsol; ++s)
1143 std::vector<double> sol;
1144 getSolution(solutions, ik_seed_state, s, sol);
1145 RCLCPP_DEBUG(LOGGER,
"Sol %d: %e %e %e %e %e %e",
static_cast<int>(s), sol[0], sol[1], sol[2], sol[3],
1148 bool obeys_limits =
true;
1149 for (std::size_t i = 0; i < sol.size(); i++)
1152 if (joint_has_limits_vector_[i] && ((sol[i] < (joint_min_vector_[i] -
LIMIT_TOLERANCE)) ||
1156 obeys_limits =
false;
1157 RCLCPP_DEBUG_STREAM(LOGGER,
"Not in limits! " <<
static_cast<int>(i) <<
" value " << sol[i]
1158 <<
" has limit: " << joint_has_limits_vector_[i] <<
" being "
1159 << joint_min_vector_[i] <<
" to " << joint_max_vector_[i]);
1166 getSolution(solutions, ik_seed_state, s, solution_obey_limits);
1167 double dist_from_seed = 0.0;
1168 for (std::size_t i = 0; i < ik_seed_state.size(); ++i)
1170 dist_from_seed += fabs(ik_seed_state[i] - solution_obey_limits[i]);
1173 solutions_obey_limits.push_back({ solution_obey_limits, dist_from_seed });
1179 RCLCPP_DEBUG_STREAM(LOGGER,
"No IK solution");
1183 if (!solutions_obey_limits.empty())
1185 std::sort(solutions_obey_limits.begin(), solutions_obey_limits.end());
1186 solution = solutions_obey_limits[0].value;
1187 error_code.val = moveit_msgs::msg::MoveItErrorCodes::SUCCESS;
1191 error_code.val = moveit_msgs::msg::MoveItErrorCodes::NO_IK_SOLUTION;
1195 bool IKFastKinematicsPlugin::getPositionIK(
const std::vector<geometry_msgs::msg::Pose>& ik_poses,
1196 const std::vector<double>& ik_seed_state,
1197 std::vector<std::vector<double>>& solutions,
1201 RCLCPP_DEBUG_STREAM(LOGGER,
"getPositionIK with multiple solutions");
1205 RCLCPP_ERROR(LOGGER,
"kinematics not active");
1210 if (ik_poses.empty())
1212 RCLCPP_ERROR(LOGGER,
"ik_poses is empty");
1217 if (ik_poses.size() > 1)
1219 RCLCPP_ERROR(LOGGER,
"ik_poses contains multiple entries, only one is allowed");
1224 if (ik_seed_state.size() < num_joints_)
1226 RCLCPP_ERROR_STREAM(LOGGER,
"ik_seed_state only has " << ik_seed_state.size()
1227 <<
" entries, this ikfast solver requires " << num_joints_);
1232 transformToChainFrame(ik_poses[0], frame);
1235 std::vector<IkSolutionList<IkReal>> solution_set;
1237 std::vector<double> vfree;
1239 std::vector<double> sampled_joint_vals;
1240 if (!redundant_joint_indices_.empty())
1243 sampled_joint_vals.push_back(ik_seed_state[redundant_joint_indices_[0]]);
1247 joint_has_limits_vector_[redundant_joint_indices_.front()])
1249 double joint_min = joint_min_vector_[redundant_joint_indices_.front()];
1250 double joint_max = joint_max_vector_[redundant_joint_indices_.front()];
1252 double jv = sampled_joint_vals[0];
1256 RCLCPP_ERROR_STREAM(LOGGER,
"ik seed is out of bounds");
1262 if (!sampleRedundantJoint(
options.discretization_method, sampled_joint_vals))
1268 for (
unsigned int i = 0; i < sampled_joint_vals.size(); i++)
1271 vfree.push_back(sampled_joint_vals[i]);
1272 numsol += solve(frame, vfree, ik_solutions);
1273 solution_set.push_back(ik_solutions);
1279 numsol = solve(frame, vfree, ik_solutions);
1280 solution_set.push_back(ik_solutions);
1283 RCLCPP_DEBUG_STREAM(LOGGER,
"Found " << numsol <<
" solutions from IKFast");
1284 bool solutions_found =
false;
1290 for (
unsigned int r = 0;
r < solution_set.size();
r++)
1292 ik_solutions = solution_set[
r];
1294 for (
int s = 0; s < numsol; ++s)
1296 std::vector<double> sol;
1297 getSolution(ik_solutions, ik_seed_state, s, sol);
1299 bool obeys_limits =
true;
1300 for (
unsigned int i = 0; i < sol.size(); i++)
1303 if (joint_has_limits_vector_[i] && ((sol[i] < (joint_min_vector_[i] -
LIMIT_TOLERANCE)) ||
1307 obeys_limits =
false;
1308 RCLCPP_DEBUG_STREAM(LOGGER,
"Not in limits! " << i <<
" value " << sol[i]
1309 <<
" has limit: " << joint_has_limits_vector_[i] <<
" being "
1310 << joint_min_vector_[i] <<
" to " << joint_max_vector_[i]);
1317 solutions_found =
true;
1318 solutions.push_back(sol);
1323 if (solutions_found)
1331 RCLCPP_DEBUG_STREAM(LOGGER,
"No IK solution");
1339 std::vector<double>& sampled_joint_vals)
const
1341 int index = redundant_joint_indices_.front();
1342 double joint_dscrt = redundant_joint_discretization_.at(index);
1343 double joint_min = joint_min_vector_[index];
1344 double joint_max = joint_max_vector_[index];
1350 size_t steps = std::ceil((joint_max - joint_min) / joint_dscrt);
1351 for (
size_t i = 0; i < steps; i++)
1353 sampled_joint_vals.push_back(joint_min + joint_dscrt * i);
1355 sampled_joint_vals.push_back(joint_max);
1360 int steps = std::ceil((joint_max - joint_min) / joint_dscrt);
1361 steps = steps > 0 ? steps : 1;
1362 double diff = joint_max - joint_min;
1363 for (
int i = 0; i < steps; i++)
1365 sampled_joint_vals.push_back(((diff * std::rand()) / (
static_cast<double>(RAND_MAX))) + joint_min);
1374 RCLCPP_ERROR_STREAM(LOGGER,
"Discretization method " << method <<
" is not supported");
1381 void IKFastKinematicsPlugin::transformToChainFrame(
const geometry_msgs::msg::Pose& ik_pose, KDL::Frame& ik_pose_chain)
const
1383 if (tip_transform_required_ || base_transform_required_)
1385 Eigen::Isometry3d ik_eigen_pose;
1386 tf2::fromMsg(ik_pose, ik_eigen_pose);
1387 if (tip_transform_required_)
1388 ik_eigen_pose = ik_eigen_pose * group_tip_to_chain_tip_;
1390 if (base_transform_required_)
1391 ik_eigen_pose = chain_base_to_group_base_ * ik_eigen_pose;
1393 tf2::transformEigenToKDL(ik_eigen_pose, ik_pose_chain);
1397 tf2::fromMsg(ik_pose, ik_pose_chain);
1404 #include <pluginlib/class_list_macros.hpp>
The discrete solutions are returned in this structure.
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...
virtual void GetSolution(T *solution, const T *freevalues) const =0
gets a concrete solution
Default implementation of IkSolutionListBase.
virtual const IkSolutionBase< T > & GetSolution(size_t index) const
returns the solution pointer
virtual size_t GetNumSolutions() const
returns the number of solutions stored
virtual void Clear()
clears all current solutions, note that any memory addresses returned from GetSolution will be invali...
Provides an interface for kinematics solvers.
std::function< void(const geometry_msgs::msg::Pose &, const std::vector< double > &, moveit_msgs::msg::MoveItErrorCodes &)> IKCallbackFn
Signature for a callback to validate an IK solution. Typically used for collision checking.
A joint from the robot. Models the transform that this joint applies in the kinematic chain....
std::size_t getVariableCount() const
Get the number of variables that describe this joint.
const std::string & getName() const
Get the name of the joint.
const VariableBounds & getVariableBounds(const std::string &variable) const
Get the bounds for a variable. Throw an exception if the variable was not found.
JointType getType() const
Get the type of joint.
A link from the robot. Contains the constant transform applied to the link and its geometry.
const JointModel * getParentJointModel() const
Get the joint model whose child this link is. There will always be a parent joint.
const std::string & getName() const
The name of this link.
const LinkModel * getParentLinkModel() const
Get the link model whose child this link is (through some joint). There may not always be a parent li...
Definition of a kinematic model. This class is not thread safe, however multiple instances can be cre...
bool hasLinkModel(const std::string &name) const
Check if a link exists. Return true if it does.
SEARCH_MODE
Search modes for searchPositionIK(), see there.
@ MULTIPLE_TIPS_NOT_SUPPORTED
@ UNSUPORTED_DISCRETIZATION_REQUESTED
Core components of MoveIt.
IkParameterizationType
The types of inverse kinematics parameterizations supported.
@ IKP_Direction3D
direction on end effector coordinate system reaches desired direction
@ IKP_TranslationZAxisAngle4DVelocity
@ IKP_TranslationXAxisAngleZNorm4DVelocity
@ IKP_UniqueIdMask
the mask for the unique ids
@ IKP_TranslationDirection5DVelocity
@ IKP_TranslationXY2D
2D translation along XY plane
@ IKP_Transform6DVelocity
@ IKP_NumberOfParameterizations
number of parameterizations (does not count IKP_None)
@ IKP_TranslationLocalGlobal6D
local point on end effector origin reaches desired 3D global point
@ IKP_Ray4D
ray on end effector coordinate system reaches desired global ray
@ IKP_Translation3DVelocity
@ IKP_TranslationYAxisAngleXNorm4D
@ IKP_TranslationLocalGlobal6DVelocity
@ IKP_TranslationDirection5D
@ IKP_TranslationXAxisAngle4D
@ IKP_TranslationZAxisAngleYNorm4DVelocity
@ IKP_TranslationYAxisAngle4DVelocity
@ IKP_TranslationXAxisAngle4DVelocity
@ IKP_Translation3D
end effector origin reaches desired 3D translation
@ IKP_Rotation3D
end effector reaches desired 3D rotation
@ IKP_VelocityDataBit
bit is set if the data represents the time-derivate velocity of an IkParameterization
@ IKP_TranslationZAxisAngle4D
@ IKP_Transform6D
end effector reaches desired 6D transformation
@ IKP_TranslationXAxisAngleZNorm4D
@ IKP_TranslationXYOrientation3DVelocity
@ IKP_TranslationXYOrientation3D
@ IKP_Lookat3D
direction on end effector coordinate system points to desired 3D position
@ IKP_TranslationYAxisAngleXNorm4DVelocity
@ IKP_TranslationXY2DVelocity
@ IKP_TranslationYAxisAngle4D
@ IKP_TranslationZAxisAngleYNorm4D
@ IKP_Direction3DVelocity
PLUGINLIB_EXPORT_CLASS(prbt_manipulator::IKFastKinematicsPlugin, kinematics::KinematicsBase)
const double LIMIT_TOLERANCE
IKFAST_API int * GetFreeParameters()
IKFAST_API int GetNumJoints()
IKFAST_API int GetIkType()
IKFAST_API void ComputeFk(const IkReal *j, IkReal *eetrans, IkReal *eerot)
IKFAST_API bool ComputeIk(const IkReal *eetrans, const IkReal *eerot, const IkReal *pfree, IkSolutionListBase< IkReal > &solutions)
IKFAST_API int GetNumFreeParameters()
A set of options for the kinematics solver.
KinematicError kinematic_error
std::vector< double > value
bool operator<(const LimitObeyingSol &a) const