37#include <moveit_msgs/srv/get_position_ik.hpp>
39#include <class_loader/class_loader.hpp>
46#include <Eigen/Geometry>
66 const std::string& group_name,
const std::string& base_frame,
67 const std::vector<std::string>& tip_frames,
double search_discretization)
72 RCLCPP_INFO(getLogger(),
"SrvKinematicsPlugin initializing");
75 std::string kinematics_param_prefix =
"robot_description_kinematics." + group_name;
76 param_listener_ = std::make_shared<srv_kinematics::ParamListener>(node, kinematics_param_prefix);
77 params_ = param_listener_->get_params();
79 storeValues(robot_model, group_name, base_frame, tip_frames, search_discretization);
80 joint_model_group_ =
robot_model_->getJointModelGroup(group_name);
81 if (!joint_model_group_)
86 std::cout <<
"Joint Model Variable Names: ------------------------------------------- \n ";
87 const std::vector<std::string> jm_names = joint_model_group_->
getVariableNames();
88 std::copy(jm_names.begin(), jm_names.end(), std::ostream_iterator<std::string>(std::cout,
"\n"));
94 RCLCPP_INFO_STREAM(getLogger(),
"Dimension planning group '"
95 << group_name <<
"': " << dimension_
100 for (std::size_t i = 0; i < joint_model_group_->
getJointModels().size(); ++i)
107 RCLCPP_ERROR(getLogger(),
"tip links available:");
116 RCLCPP_ERROR(getLogger(),
"Could not find tip name '%s' in joint group '%s'", tip_frame.c_str(),
120 ik_group_info_.link_names.push_back(tip_frame);
124 robot_state_ = std::make_shared<moveit::core::RobotState>(
robot_model_);
125 robot_state_->setToDefaultValues();
128 RCLCPP_DEBUG(getLogger(),
"IK Service client topic : %s", params_.kinematics_solver_service_name.c_str());
129 ik_service_client_ = node_->create_client<moveit_msgs::srv::GetPositionIK>(params_.kinematics_solver_service_name);
131 if (!ik_service_client_->wait_for_service(std::chrono::seconds(1)))
133 RCLCPP_WARN_STREAM(getLogger(),
134 "Unable to connect to ROS service client with name: " << ik_service_client_->get_service_name());
138 RCLCPP_INFO_STREAM(getLogger(),
139 "Service client started with ROS service name: " << ik_service_client_->get_service_name());
143 RCLCPP_DEBUG(getLogger(),
"ROS service-based kinematics solver initialized");
149 if (num_possible_redundant_joints_ < 0)
151 RCLCPP_ERROR(getLogger(),
"This group cannot have redundant joints");
154 if (
int(redundant_joints.size()) > num_possible_redundant_joints_)
156 RCLCPP_ERROR(getLogger(),
"This group can only have %d redundant joints", num_possible_redundant_joints_);
163bool SrvKinematicsPlugin::isRedundantJoint(
unsigned int index)
const
167 if (redundant_joint_indice == index)
173int SrvKinematicsPlugin::getJointIndex(
const std::string& name)
const
175 for (
unsigned int i = 0; i < ik_group_info_.joint_names.size(); ++i)
177 if (ik_group_info_.joint_names[i] == name)
183bool SrvKinematicsPlugin::timedOut(
const rclcpp::Time& start_time,
double duration)
const
185 return ((node_->now() - start_time).seconds() >= duration);
189 const std::vector<double>& ik_seed_state, std::vector<double>& solution,
190 moveit_msgs::msg::MoveItErrorCodes& error_code,
193 std::vector<double> consistency_limits;
196 error_code, options);
200 const std::vector<double>& ik_seed_state,
double timeout,
201 std::vector<double>& solution,
202 moveit_msgs::msg::MoveItErrorCodes& error_code,
205 std::vector<double> consistency_limits;
212 const std::vector<double>& ik_seed_state,
double timeout,
213 const std::vector<double>& consistency_limits, std::vector<double>& solution,
214 moveit_msgs::msg::MoveItErrorCodes& error_code,
222 const std::vector<double>& ik_seed_state,
double timeout,
223 std::vector<double>& solution,
const IKCallbackFn& solution_callback,
224 moveit_msgs::msg::MoveItErrorCodes& error_code,
227 std::vector<double> consistency_limits;
228 return searchPositionIK(ik_pose, ik_seed_state, timeout, consistency_limits, solution, solution_callback, error_code,
233 const std::vector<double>& ik_seed_state,
double timeout,
234 const std::vector<double>& consistency_limits, std::vector<double>& solution,
236 moveit_msgs::msg::MoveItErrorCodes& error_code,
240 std::vector<geometry_msgs::msg::Pose> ik_poses;
241 ik_poses.push_back(ik_pose);
243 return searchPositionIK(ik_poses, ik_seed_state, timeout, consistency_limits, solution, solution_callback, error_code,
248 const std::vector<double>& ik_seed_state,
double ,
249 const std::vector<double>& ,
250 std::vector<double>& solution,
const IKCallbackFn& solution_callback,
251 moveit_msgs::msg::MoveItErrorCodes& error_code,
258 RCLCPP_ERROR(getLogger(),
"kinematics not active");
259 error_code.val = error_code.NO_IK_SOLUTION;
264 if (ik_seed_state.size() != dimension_)
266 RCLCPP_ERROR_STREAM(getLogger(),
267 "Seed state must have size " << dimension_ <<
" instead of size " << ik_seed_state.size());
268 error_code.val = error_code.NO_IK_SOLUTION;
275 RCLCPP_ERROR_STREAM(getLogger(),
"Mismatched number of pose requests (" << ik_poses.size() <<
") to tip frames ("
277 <<
") in searchPositionIK");
278 error_code.val = error_code.NO_IK_SOLUTION;
283 auto ik_srv = std::make_shared<moveit_msgs::srv::GetPositionIK::Request>();
284 ik_srv->ik_request.avoid_collisions =
true;
288 robot_state_->setJointGroupPositions(joint_model_group_, ik_seed_state);
292 geometry_msgs::msg::PoseStamped ik_pose_st;
297 for (std::size_t i = 0; i <
tip_frames_.size(); ++i)
299 ik_pose_st.pose = ik_poses[i];
300 ik_srv->ik_request.pose_stamped_vector.push_back(ik_pose_st);
301 ik_srv->ik_request.ik_link_names.push_back(
tip_frames_[i]);
306 ik_pose_st.pose = ik_poses[0];
309 ik_srv->ik_request.pose_stamped = ik_pose_st;
313 RCLCPP_DEBUG(getLogger(),
"Calling service: %s", ik_service_client_->get_service_name());
314 auto result_future = ik_service_client_->async_send_request(ik_srv);
315 const auto& response = result_future.get();
316 if (rclcpp::spin_until_future_complete(node_, result_future) == rclcpp::FutureReturnCode::SUCCESS)
319 error_code.val = response->error_code.val;
320 if (error_code.val != error_code.SUCCESS)
327 switch (error_code.val)
329 case moveit_msgs::msg::MoveItErrorCodes::FAILURE:
330 RCLCPP_ERROR(getLogger(),
"Service failed with with error code: FAILURE");
332 case moveit_msgs::msg::MoveItErrorCodes::NO_IK_SOLUTION:
333 RCLCPP_DEBUG(getLogger(),
"Service failed with with error code: NO IK SOLUTION");
336 RCLCPP_DEBUG_STREAM(getLogger(),
"Service failed with with error code: " << error_code.val);
343 RCLCPP_DEBUG_STREAM(getLogger(),
344 "Service call failed to connect to service: " << ik_service_client_->get_service_name());
345 error_code.val = error_code.FAILURE;
351 RCLCPP_ERROR(getLogger(),
"An error occurred converting received robot state message into internal robot state.");
352 error_code.val = error_code.FAILURE;
357 robot_state_->copyJointGroupPositions(joint_model_group_, solution);
360 if (solution_callback)
362 RCLCPP_DEBUG(getLogger(),
"Calling solution callback on IK solution");
365 solution_callback(ik_poses[0], solution, error_code);
367 if (error_code.val != error_code.SUCCESS)
369 switch (error_code.val)
371 case moveit_msgs::msg::MoveItErrorCodes::FAILURE:
372 RCLCPP_ERROR(getLogger(),
"IK solution callback failed with with error code: FAILURE");
374 case moveit_msgs::msg::MoveItErrorCodes::NO_IK_SOLUTION:
375 RCLCPP_ERROR(getLogger(),
"IK solution callback failed with with error code: "
379 RCLCPP_ERROR_STREAM(getLogger(),
"IK solution callback failed with with error code: " << error_code.val);
385 RCLCPP_INFO(getLogger(),
"IK Solver Succeeded!");
390 const std::vector<double>& joint_angles,
391 std::vector<geometry_msgs::msg::Pose>& poses)
const
395 RCLCPP_ERROR(getLogger(),
"kinematics not active");
398 poses.resize(link_names.size());
399 if (joint_angles.size() != dimension_)
401 RCLCPP_ERROR(getLogger(),
"Joint angles vector must have size: %d", dimension_);
405 RCLCPP_ERROR(getLogger(),
"Forward kinematics not implemented");
412 return ik_group_info_.joint_names;
417 return ik_group_info_.link_names;
Provides an interface for kinematics solvers.
void storeValues(const moveit::core::RobotModel &robot_model, const std::string &group_name, const std::string &base_frame, const std::vector< std::string > &tip_frames, double search_discretization)
std::vector< unsigned int > redundant_joint_indices_
virtual const std::string & getGroupName() const
Return the name of the group that the solver is operating on.
std::vector< std::string > tip_frames_
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.
virtual const std::vector< std::string > & getTipFrames() const
Return the names of the tip frames of the kinematic tree on which the solver is operating....
moveit::core::RobotModelConstPtr robot_model_
const std::vector< const JointModel * > & getMimicJointModels() const
Get the mimic joints that are part of this group.
const std::vector< std::string > & getJointModelNames() const
Get the names of the joints in this group. These are the names of the joints returned by getJointMode...
const std::vector< std::string > & getVariableNames() const
Get the names of the variables that make up the joints included in this group. The number of returned...
const std::vector< const JointModel * > & getActiveJointModels() const
Get the active joints in this group (that have controllable DOF). This does not include mimic joints.
bool hasLinkModel(const std::string &link) const
Check if a link is part of this group.
unsigned int getVariableCount() const
Get the number of variables that describe this joint group. This includes variables necessary for mim...
const std::vector< const JointModel * > & getJointModels() const
Get all the joints in this group (including fixed and mimic joints).
Definition of a kinematic model. This class is not thread safe, however multiple instances can be cre...
Representation of a robot's state. This includes position, velocity, acceleration and effort.
Specific implementation of kinematics using ROS service calls to communicate with external IK solvers...
bool setRedundantJoints(const std::vector< unsigned int > &redundant_joint_indices) override
Set a set of redundant joints for the kinematics solver to use. This can fail, depending on the IK so...
const std::vector< std::string > & getJointNames() const override
Return all the joint names in the order they are used internally.
bool searchPositionIK(const geometry_msgs::msg::Pose &ik_pose, const std::vector< double > &ik_seed_state, double timeout, std::vector< double > &solution, moveit_msgs::msg::MoveItErrorCodes &error_code, const kinematics::KinematicsQueryOptions &options=kinematics::KinematicsQueryOptions()) const override
Given a desired pose of the end-effector, search for the joint angles required to reach it....
bool getPositionIK(const geometry_msgs::msg::Pose &ik_pose, const std::vector< double > &ik_seed_state, std::vector< double > &solution, moveit_msgs::msg::MoveItErrorCodes &error_code, const kinematics::KinematicsQueryOptions &options=kinematics::KinematicsQueryOptions()) const override
Given a desired pose of the end-effector, compute the joint angles to reach it.
const std::vector< std::string > & getVariableNames() const
Return all the variable names in the order they are represented internally.
const std::vector< std::string > & getLinkNames() const override
Return all the link names in the order they are represented internally.
bool getPositionFK(const std::vector< std::string > &link_names, const std::vector< double > &joint_angles, std::vector< geometry_msgs::msg::Pose > &poses) const override
Given a set of joint angles and a set of links, compute their pose.
bool initialize(const rclcpp::Node::SharedPtr &node, const moveit::core::RobotModel &robot_model, const std::string &group_name, const std::string &base_name, const std::vector< std::string > &tip_frames, double search_discretization) override
Initialization function for the kinematics, for use with kinematic chain IK solvers.
SrvKinematicsPlugin()
Default constructor.
rclcpp::Logger getLogger()
void robotStateToRobotStateMsg(const RobotState &state, moveit_msgs::msg::RobotState &robot_state, bool copy_attached_bodies=true)
Convert a MoveIt robot state to a robot state message.
bool robotStateMsgToRobotState(const Transforms &tf, const moveit_msgs::msg::RobotState &robot_state, RobotState &state, bool copy_attached_bodies=true)
Convert a robot state msg (with accompanying extra transforms) to a MoveIt robot state.
rclcpp::Logger getLogger(const std::string &name)
Creates a namespaced logger.
CLASS_LOADER_REGISTER_CLASS(default_planning_request_adapters::ResolveConstraintFrames, planning_interface::PlanningRequestAdapter)
A set of options for the kinematics solver.