pr2_arm_kinematics.cpp
Go to the documentation of this file.
1 /*********************************************************************
2  * Software License Agreement (BSD License)
3  *
4  * Copyright (c) 2008, Willow Garage, Inc.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  * * Redistributions of source code must retain the above copyright
12  * notice, this list of conditions and the following disclaimer.
13  * * Redistributions in binary form must reproduce the above
14  * copyright notice, this list of conditions and the following
15  * disclaimer in the documentation and/or other materials provided
16  * with the distribution.
17  * * Neither the name of Willow Garage nor the names of its
18  * contributors may be used to endorse or promote products derived
19  * from this software without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32  * POSSIBILITY OF SUCH DAMAGE.
33  *********************************************************************/
34 
35 /* Author: Sachin Chitta */
36 
38 #include <geometry_msgs/PoseStamped.h>
40 #include <tf_conversions/tf_kdl.h>
41 #include "ros/ros.h"
42 #include <algorithm>
43 #include <numeric>
44 
45 using namespace KDL;
46 using namespace tf;
47 using namespace std;
48 using namespace ros;
49 
50 namespace pr2_arm_kinematics
51 {
52 static const std::string IK_SERVICE = "get_ik";
53 static const std::string FK_SERVICE = "get_fk";
54 static const std::string IK_INFO_SERVICE = "get_ik_solver_info";
55 static const std::string FK_INFO_SERVICE = "get_fk_solver_info";
56 
57 PR2ArmKinematics::PR2ArmKinematics(bool create_tf_listener) : node_handle_("~"), dimension_(7)
58 {
59  urdf::Model robot_model;
60  std::string tip_name, xml_string;
61 
62  while (!loadRobotModel(node_handle_, robot_model, xml_string) && node_handle_.ok())
63  {
64  ROS_ERROR("Could not load robot model. Are you sure the robot model is on the parameter server?");
65  ros::Duration(0.5).sleep();
66  }
67 
68  if (!node_handle_.getParam("root_name", root_name_))
69  {
70  ROS_FATAL("PR2IK: No root name found on parameter server");
71  exit(-1);
72  }
73  if (!node_handle_.getParam("tip_name", tip_name))
74  {
75  ROS_FATAL("PR2IK: No tip name found on parameter server");
76  exit(-1);
77  }
78 
79  ROS_DEBUG("Loading KDL Tree");
80  if (!getKDLChain(xml_string, root_name_, tip_name, kdl_chain_))
81  {
82  active_ = false;
83  ROS_ERROR("Could not load kdl tree");
84  }
85  if (create_tf_listener)
86  {
87  tf_ = new TransformListener();
88  }
89  else
90  {
91  tf_ = NULL;
92  }
93 
94  ROS_DEBUG("Advertising services");
96  node_handle_.param<int>("free_angle", free_angle_, 2);
97 
98  node_handle_.param<double>("search_discretization", search_discretization_, 0.01);
99  pr2_arm_ik_solver_.reset(
100  new pr2_arm_kinematics::PR2ArmIKSolver(robot_model, root_name_, tip_name, search_discretization_, free_angle_));
101  if (!pr2_arm_ik_solver_->active_)
102  {
103  ROS_ERROR("Could not load ik");
104  active_ = false;
105  }
106  else
107  {
108  pr2_arm_ik_solver_->getSolverInfo(ik_solver_info_);
110  fk_solver_info_.joint_names = ik_solver_info_.joint_names;
111 
112  for (unsigned int i = 0; i < ik_solver_info_.joint_names.size(); i++)
113  {
114  ROS_DEBUG("PR2Kinematics:: joint name: %s", ik_solver_info_.joint_names[i].c_str());
115  }
116  for (unsigned int i = 0; i < ik_solver_info_.link_names.size(); i++)
117  {
118  ROS_DEBUG("PR2Kinematics can solve IK for %s", ik_solver_info_.link_names[i].c_str());
119  }
120  for (unsigned int i = 0; i < fk_solver_info_.link_names.size(); i++)
121  {
122  ROS_DEBUG("PR2Kinematics can solve FK for %s", fk_solver_info_.link_names[i].c_str());
123  }
124  ROS_DEBUG("PR2Kinematics::active");
125  active_ = true;
128 
131  }
132 }
133 
135 {
136  if (tf_ != NULL)
137  {
138  delete tf_;
139  }
140 }
141 
143 {
144  if (active_)
145  return true;
146  return false;
147 }
148 
149 bool PR2ArmKinematics::getPositionIK(kinematics_msgs::GetPositionIK::Request& request,
150  kinematics_msgs::GetPositionIK::Response& response)
151 {
152  if (!active_)
153  {
154  ROS_ERROR("IK service not active");
155  return false;
156  }
157 
158  if (!checkIKService(request, response, ik_solver_info_))
159  return false;
160 
161  geometry_msgs::PoseStamped pose_msg_in = request.ik_request.pose_stamped;
162  geometry_msgs::PoseStamped pose_msg_out;
163 
164  if (tf_ != NULL)
165  {
166  if (!convertPoseToRootFrame(pose_msg_in, pose_msg_out, root_name_, *tf_))
167  {
168  response.error_code.val = response.error_code.FRAME_TRANSFORM_FAILURE;
169  return true;
170  }
171  }
172  else
173  {
174  ROS_WARN_STREAM("No tf listener. Can't transform anything");
175  response.error_code.val = response.error_code.FRAME_TRANSFORM_FAILURE;
176  return false;
177  }
178  request.ik_request.pose_stamped = pose_msg_out;
179  return getPositionIKHelper(request, response);
180 }
181 
182 // this assumes that everything has been checked and is in the correct frame
183 bool PR2ArmKinematics::getPositionIKHelper(kinematics_msgs::GetPositionIK::Request& request,
184  kinematics_msgs::GetPositionIK::Response& response)
185 {
186  KDL::Frame pose_desired;
187  tf::PoseMsgToKDL(request.ik_request.pose_stamped.pose, pose_desired);
188 
189  // Do the IK
190  KDL::JntArray jnt_pos_in;
191  KDL::JntArray jnt_pos_out;
192  jnt_pos_in.resize(dimension_);
193  for (int i = 0; i < dimension_; i++)
194  {
195  int tmp_index = getJointIndex(request.ik_request.ik_seed_state.joint_state.name[i], ik_solver_info_);
196  if (tmp_index >= 0)
197  {
198  jnt_pos_in(tmp_index) = request.ik_request.ik_seed_state.joint_state.position[i];
199  }
200  else
201  {
202  ROS_ERROR("i: %d, No joint index for %s", i, request.ik_request.ik_seed_state.joint_state.name[i].c_str());
203  }
204  }
205 
206  int ik_valid = pr2_arm_ik_solver_->CartToJntSearch(jnt_pos_in, pose_desired, jnt_pos_out, request.timeout.toSec());
207  if (ik_valid == pr2_arm_kinematics::TIMED_OUT)
208  response.error_code.val = response.error_code.TIMED_OUT;
209  if (ik_valid == pr2_arm_kinematics::NO_IK_SOLUTION)
210  response.error_code.val = response.error_code.NO_IK_SOLUTION;
211 
212  response.solution.joint_state.header = request.ik_request.pose_stamped.header;
213 
214  if (ik_valid >= 0)
215  {
216  response.solution.joint_state.name = ik_solver_info_.joint_names;
217  response.solution.joint_state.position.resize(dimension_);
218  for (int i = 0; i < dimension_; i++)
219  {
220  response.solution.joint_state.position[i] = jnt_pos_out(i);
221  ROS_DEBUG("IK Solution: %s %d: %f", response.solution.joint_state.name[i].c_str(), i, jnt_pos_out(i));
222  }
223  response.error_code.val = response.error_code.SUCCESS;
224  return true;
225  }
226  else
227  {
228  ROS_DEBUG("An IK solution could not be found");
229  return false;
230  }
231 }
232 
233 bool PR2ArmKinematics::getIKSolverInfo(kinematics_msgs::GetKinematicSolverInfo::Request& request,
234  kinematics_msgs::GetKinematicSolverInfo::Response& response)
235 {
236  if (active_)
237  {
238  response.kinematic_solver_info = ik_solver_info_;
239  return true;
240  }
241  ROS_ERROR("IK node not active");
242  return false;
243 }
244 
245 bool PR2ArmKinematics::getFKSolverInfo(kinematics_msgs::GetKinematicSolverInfo::Request& request,
246  kinematics_msgs::GetKinematicSolverInfo::Response& response)
247 {
248  if (active_)
249  {
250  response.kinematic_solver_info = fk_solver_info_;
251  return true;
252  }
253  ROS_ERROR("IK node not active");
254  return false;
255 }
256 
257 bool PR2ArmKinematics::getPositionFK(kinematics_msgs::GetPositionFK::Request& request,
258  kinematics_msgs::GetPositionFK::Response& response)
259 {
260  if (!active_)
261  {
262  ROS_ERROR("FK service not active");
263  return false;
264  }
265 
266  if (!checkFKService(request, response, fk_solver_info_))
267  return false;
268 
269  KDL::Frame p_out;
270  KDL::JntArray jnt_pos_in;
271  geometry_msgs::PoseStamped pose;
272  tf::Stamped<tf::Pose> tf_pose;
273 
274  jnt_pos_in.resize(dimension_);
275  for (int i = 0; i < (int)request.robot_state.joint_state.position.size(); i++)
276  {
277  int tmp_index = getJointIndex(request.robot_state.joint_state.name[i], fk_solver_info_);
278  if (tmp_index >= 0)
279  jnt_pos_in(tmp_index) = request.robot_state.joint_state.position[i];
280  }
281 
282  response.pose_stamped.resize(request.fk_link_names.size());
283  response.fk_link_names.resize(request.fk_link_names.size());
284 
285  for (unsigned int i = 0; i < request.fk_link_names.size(); i++)
286  {
287  ROS_DEBUG("End effector index: %d", pr2_arm_kinematics::getKDLSegmentIndex(kdl_chain_, request.fk_link_names[i]));
288  ROS_DEBUG("Chain indices: %d", kdl_chain_.getNrOfSegments());
289  if (jnt_to_pose_solver_->JntToCart(
290  jnt_pos_in, p_out, pr2_arm_kinematics::getKDLSegmentIndex(kdl_chain_, request.fk_link_names[i])) >= 0)
291  {
292  tf_pose.frame_id_ = root_name_;
293  tf_pose.stamp_ = ros::Time();
294  tf::PoseKDLToTF(p_out, tf_pose);
295  tf::poseStampedTFToMsg(tf_pose, pose);
296  if (!transformPose(request.header.frame_id, pose, response.pose_stamped[i]))
297  {
298  response.error_code.val = response.error_code.FRAME_TRANSFORM_FAILURE;
299  return false;
300  }
301  response.fk_link_names[i] = request.fk_link_names[i];
302  response.error_code.val = response.error_code.SUCCESS;
303  }
304  else
305  {
306  ROS_ERROR("Could not compute FK for %s", request.fk_link_names[i].c_str());
307  response.error_code.val = response.error_code.NO_FK_SOLUTION;
308  return false;
309  }
310  }
311  return true;
312 }
313 bool PR2ArmKinematics::transformPose(const std::string& des_frame, const geometry_msgs::PoseStamped& pose_in,
314  geometry_msgs::PoseStamped& pose_out)
315 {
316  if (tf_ != NULL)
317  {
318  try
319  {
320  tf_->transformPose(des_frame, pose_in, pose_out);
321  }
322  catch (...)
323  {
324  ROS_ERROR("Could not transform FK pose to frame: %s", des_frame.c_str());
325  return false;
326  }
327  }
328  else if (des_frame != root_name_)
329  {
330  ROS_WARN_STREAM("No tf listener, can't transform to frame " << des_frame);
331  return false;
332  }
333  return true;
334 }
335 } // namespace
ROS_DEPRECATED void PoseKDLToTF(const KDL::Frame &k, tf::Pose &t)
boost::shared_ptr< pr2_arm_kinematics::PR2ArmIKSolver > pr2_arm_ik_solver_
#define ROS_FATAL(...)
bool getPositionFK(kinematics_msgs::GetPositionFK::Request &request, kinematics_msgs::GetPositionFK::Response &response)
This is the basic forward kinematics service that will return information about the kinematics node...
void transformPose(const std::string &target_frame, const geometry_msgs::PoseStamped &stamped_in, geometry_msgs::PoseStamped &stamped_out) const
static void poseStampedTFToMsg(const Stamped< Pose > &bt, geometry_msgs::PoseStamped &msg)
Namespace for the PR2ArmKinematics.
unsigned int getNrOfSegments() const
bool getKDLChain(const urdf::ModelInterface &model, const std::string &root_name, const std::string &tip_name, KDL::Chain &kdl_chain)
ROS_DEPRECATED void PoseMsgToKDL(const geometry_msgs::Pose &m, KDL::Frame &k)
bool getIKSolverInfo(kinematics_msgs::GetKinematicSolverInfo::Request &request, kinematics_msgs::GetKinematicSolverInfo::Response &response)
This is the basic kinematics info service that will return information about the kinematics node...
#define ROS_ERROR(...)
boost::shared_ptr< KDL::ChainFkSolverPos_recursive > jnt_to_pose_solver_
ServiceServer advertiseService(const std::string &service, bool(T::*srv_func)(MReq &, MRes &), T *obj)
static const int NO_IK_SOLUTION
kinematics_msgs::KinematicSolverInfo fk_solver_info_
void getKDLChainInfo(const KDL::Chain &chain, moveit_msgs::KinematicSolverInfo &chain_info)
#define ROS_DEBUG(...)
bool getFKSolverInfo(kinematics_msgs::GetKinematicSolverInfo::Request &request, kinematics_msgs::GetKinematicSolverInfo::Response &response)
This is the basic kinematics info service that will return information about the kinematics node...
bool param(const std::string &param_name, T &param_val, const T &default_val) const
bool convertPoseToRootFrame(const geometry_msgs::PoseStamped &pose_msg, KDL::Frame &pose_kdl, const std::string &root_frame, tf::TransformListener &tf)
bool checkIKService(moveit_msgs::GetPositionIK::Request &request, moveit_msgs::GetPositionIK::Response &response, const moveit_msgs::KinematicSolverInfo &chain_info)
bool getParam(const std::string &key, std::string &s) const
int getJointIndex(const std::string &name, const moveit_msgs::KinematicSolverInfo &chain_info)
def xml_string(rootXml, addHeader=True)
bool getPositionIKHelper(kinematics_msgs::GetPositionIK::Request &request, kinematics_msgs::GetPositionIK::Response &response)
#define ROS_WARN_STREAM(args)
static const std::string IK_SERVICE
static const std::string FK_INFO_SERVICE
void resize(unsigned int newSize)
ros::Time stamp_
static const std::string IK_INFO_SERVICE
std::string frame_id_
kinematics_msgs::KinematicSolverInfo ik_solver_info_
virtual bool transformPose(const std::string &des_frame, const geometry_msgs::PoseStamped &pose_in, geometry_msgs::PoseStamped &pose_out)
static const int TIMED_OUT
bool checkFKService(moveit_msgs::GetPositionFK::Request &request, moveit_msgs::GetPositionFK::Response &response, const moveit_msgs::KinematicSolverInfo &chain_info)
virtual bool getPositionIK(kinematics_msgs::GetPositionIK::Request &request, kinematics_msgs::GetPositionIK::Response &response)
This is the basic IK service method that will compute and return an IK solution.
bool sleep() const
bool isActive()
Specifies if the node is active or not.
static const std::string FK_SERVICE
bool ok() const
bool loadRobotModel(ros::NodeHandle node_handle, urdf::Model &robot_model, std::string &xml_string)
int getKDLSegmentIndex(const KDL::Chain &chain, const std::string &name)


pr2_moveit_plugins
Author(s): Ioan Sucan , Sachin Chitta
autogenerated on Mon Feb 28 2022 22:51:25