srv_kinematics_plugin.cpp
Go to the documentation of this file.
1 /*********************************************************************
2  * Software License Agreement (BSD License)
3  *
4  * Copyright (c) 2014, JSK, The University of Tokyo.
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 JSK, The University of Tokyo 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: Dave Coleman, Masaki Murooka */
36 
37 #include <moveit_msgs/GetPositionIK.h>
41 
42 // Eigen
43 #include <Eigen/Core>
44 #include <Eigen/Geometry>
45 
46 // register SRVKinematics as a KinematicsBase implementation
48 
49 namespace srv_kinematics_plugin
50 {
52 {
53 }
54 
55 bool SrvKinematicsPlugin::initialize(const moveit::core::RobotModel& robot_model, const std::string& group_name,
56  const std::string& base_frame, const std::vector<std::string>& tip_frames,
57  double search_discretization)
58 {
59  bool debug = false;
60 
61  ROS_INFO_STREAM_NAMED("srv", "SrvKinematicsPlugin initializing");
62 
63  storeValues(robot_model, group_name, base_frame, tip_frames, search_discretization);
64  joint_model_group_ = robot_model_->getJointModelGroup(group_name);
65  if (!joint_model_group_)
66  return false;
67 
68  if (debug)
69  {
70  std::cout << std::endl << "Joint Model Variable Names: ------------------------------------------- " << std::endl;
71  const std::vector<std::string> jm_names = joint_model_group_->getVariableNames();
72  std::copy(jm_names.begin(), jm_names.end(), std::ostream_iterator<std::string>(std::cout, "\n"));
73  std::cout << std::endl;
74  }
75 
76  // Get the dimension of the planning group
77  dimension_ = joint_model_group_->getVariableCount();
78  ROS_INFO_STREAM_NAMED("srv", "Dimension planning group '"
79  << group_name << "': " << dimension_
80  << ". Active Joints Models: " << joint_model_group_->getActiveJointModels().size()
81  << ". Mimic Joint Models: " << joint_model_group_->getMimicJointModels().size());
82 
83  // Copy joint names
84  for (std::size_t i = 0; i < joint_model_group_->getJointModels().size(); ++i)
85  {
86  ik_group_info_.joint_names.push_back(joint_model_group_->getJointModelNames()[i]);
87  }
88 
89  if (debug)
90  {
91  ROS_ERROR_STREAM_NAMED("srv", "tip links available:");
92  std::copy(tip_frames_.begin(), tip_frames_.end(), std::ostream_iterator<std::string>(std::cout, "\n"));
93  }
94 
95  // Make sure all the tip links are in the link_names vector
96  for (const std::string& tip_frame : tip_frames_)
97  {
98  if (!joint_model_group_->hasLinkModel(tip_frame))
99  {
100  ROS_ERROR_NAMED("srv", "Could not find tip name '%s' in joint group '%s'", tip_frame.c_str(), group_name.c_str());
101  return false;
102  }
103  ik_group_info_.link_names.push_back(tip_frame);
104  }
105 
106  // Choose what ROS service to send IK requests to
107  ROS_DEBUG_STREAM_NAMED("srv", "Looking for ROS service name on rosparam server with param: "
108  << "/kinematics_solver_service_name");
109  std::string ik_service_name;
110  lookupParam("kinematics_solver_service_name", ik_service_name, std::string("solve_ik"));
111 
112  // Setup the joint state groups that we need
113  robot_state_ = std::make_shared<moveit::core::RobotState>(robot_model_);
114  robot_state_->setToDefaultValues();
115 
116  // Create the ROS service client
117  ros::NodeHandle nonprivate_handle("");
118  ik_service_client_ = std::make_shared<ros::ServiceClient>(
119  nonprivate_handle.serviceClient<moveit_msgs::GetPositionIK>(ik_service_name));
120  if (!ik_service_client_->waitForExistence(ros::Duration(0.1))) // wait 0.1 seconds, blocking
121  ROS_WARN_STREAM_NAMED("srv",
122  "Unable to connect to ROS service client with name: " << ik_service_client_->getService());
123  else
124  ROS_INFO_STREAM_NAMED("srv", "Service client started with ROS service name: " << ik_service_client_->getService());
125 
126  active_ = true;
127  ROS_DEBUG_NAMED("srv", "ROS service-based kinematics solver initialized");
128  return true;
129 }
130 
131 bool SrvKinematicsPlugin::setRedundantJoints(const std::vector<unsigned int>& redundant_joints)
132 {
133  if (num_possible_redundant_joints_ < 0)
134  {
135  ROS_ERROR_NAMED("srv", "This group cannot have redundant joints");
136  return false;
137  }
138  if (int(redundant_joints.size()) > num_possible_redundant_joints_)
139  {
140  ROS_ERROR_NAMED("srv", "This group can only have %d redundant joints", num_possible_redundant_joints_);
141  return false;
142  }
143 
144  return true;
145 }
146 
147 bool SrvKinematicsPlugin::isRedundantJoint(unsigned int index) const
148 {
149  for (const unsigned int& redundant_joint_indice : redundant_joint_indices_)
150  if (redundant_joint_indice == index)
151  return true;
152  return false;
153 }
154 
155 int SrvKinematicsPlugin::getJointIndex(const std::string& name) const
156 {
157  for (unsigned int i = 0; i < ik_group_info_.joint_names.size(); i++)
158  {
159  if (ik_group_info_.joint_names[i] == name)
160  return i;
161  }
162  return -1;
163 }
164 
165 bool SrvKinematicsPlugin::timedOut(const ros::WallTime& start_time, double duration) const
166 {
167  return ((ros::WallTime::now() - start_time).toSec() >= duration);
168 }
169 
170 bool SrvKinematicsPlugin::getPositionIK(const geometry_msgs::Pose& ik_pose, const std::vector<double>& ik_seed_state,
171  std::vector<double>& solution, moveit_msgs::MoveItErrorCodes& error_code,
172  const kinematics::KinematicsQueryOptions& options) const
173 {
174  std::vector<double> consistency_limits;
175 
176  return searchPositionIK(ik_pose, ik_seed_state, default_timeout_, consistency_limits, solution, IKCallbackFn(),
177  error_code, options);
178 }
179 
180 bool SrvKinematicsPlugin::searchPositionIK(const geometry_msgs::Pose& ik_pose, const std::vector<double>& ik_seed_state,
181  double timeout, std::vector<double>& solution,
182  moveit_msgs::MoveItErrorCodes& error_code,
183  const kinematics::KinematicsQueryOptions& options) const
184 {
185  std::vector<double> consistency_limits;
186 
187  return searchPositionIK(ik_pose, ik_seed_state, timeout, consistency_limits, solution, IKCallbackFn(), error_code,
188  options);
189 }
190 
191 bool SrvKinematicsPlugin::searchPositionIK(const geometry_msgs::Pose& ik_pose, const std::vector<double>& ik_seed_state,
192  double timeout, const std::vector<double>& consistency_limits,
193  std::vector<double>& solution, moveit_msgs::MoveItErrorCodes& error_code,
194  const kinematics::KinematicsQueryOptions& options) const
195 {
196  return searchPositionIK(ik_pose, ik_seed_state, timeout, consistency_limits, solution, IKCallbackFn(), error_code,
197  options);
198 }
199 
200 bool SrvKinematicsPlugin::searchPositionIK(const geometry_msgs::Pose& ik_pose, const std::vector<double>& ik_seed_state,
201  double timeout, std::vector<double>& solution,
202  const IKCallbackFn& solution_callback,
203  moveit_msgs::MoveItErrorCodes& error_code,
204  const kinematics::KinematicsQueryOptions& options) const
205 {
206  std::vector<double> consistency_limits;
207  return searchPositionIK(ik_pose, ik_seed_state, timeout, consistency_limits, solution, solution_callback, error_code,
208  options);
209 }
210 
211 bool SrvKinematicsPlugin::searchPositionIK(const geometry_msgs::Pose& ik_pose, const std::vector<double>& ik_seed_state,
212  double timeout, const std::vector<double>& consistency_limits,
213  std::vector<double>& solution, const IKCallbackFn& solution_callback,
214  moveit_msgs::MoveItErrorCodes& error_code,
215  const kinematics::KinematicsQueryOptions& options) const
216 {
217  // Convert single pose into a vector of one pose
218  std::vector<geometry_msgs::Pose> ik_poses;
219  ik_poses.push_back(ik_pose);
220 
221  return searchPositionIK(ik_poses, ik_seed_state, timeout, consistency_limits, solution, solution_callback, error_code,
222  options);
223 }
224 
225 bool SrvKinematicsPlugin::searchPositionIK(const std::vector<geometry_msgs::Pose>& ik_poses,
226  const std::vector<double>& ik_seed_state, double /*timeout*/,
227  const std::vector<double>& /*consistency_limits*/,
228  std::vector<double>& solution, const IKCallbackFn& solution_callback,
229  moveit_msgs::MoveItErrorCodes& error_code,
230  const kinematics::KinematicsQueryOptions& /*options*/,
231  const moveit::core::RobotState* /*context_state*/) const
232 {
233  // Check if active
234  if (!active_)
235  {
236  ROS_ERROR_NAMED("srv", "kinematics not active");
237  error_code.val = error_code.NO_IK_SOLUTION;
238  return false;
239  }
240 
241  // Check if seed state correct
242  if (ik_seed_state.size() != dimension_)
243  {
245  "Seed state must have size " << dimension_ << " instead of size " << ik_seed_state.size());
246  error_code.val = error_code.NO_IK_SOLUTION;
247  return false;
248  }
249 
250  // Check that we have the same number of poses as tips
251  if (tip_frames_.size() != ik_poses.size())
252  {
253  ROS_ERROR_STREAM_NAMED("srv", "Mismatched number of pose requests (" << ik_poses.size() << ") to tip frames ("
254  << tip_frames_.size()
255  << ") in searchPositionIK");
256  error_code.val = error_code.NO_IK_SOLUTION;
257  return false;
258  }
259 
260  // Create the service message
261  moveit_msgs::GetPositionIK ik_srv;
262  ik_srv.request.ik_request.avoid_collisions = true;
263  ik_srv.request.ik_request.group_name = getGroupName();
264 
265  // Copy seed state into virtual robot state and convert into moveit_msg
266  robot_state_->setJointGroupPositions(joint_model_group_, ik_seed_state);
267  moveit::core::robotStateToRobotStateMsg(*robot_state_, ik_srv.request.ik_request.robot_state);
268 
269  // Load the poses into the request in difference places depending if there is more than one or not
270  geometry_msgs::PoseStamped ik_pose_st;
271  ik_pose_st.header.frame_id = base_frame_;
272  if (tip_frames_.size() > 1)
273  {
274  // Load into vector of poses
275  for (std::size_t i = 0; i < tip_frames_.size(); ++i)
276  {
277  ik_pose_st.pose = ik_poses[i];
278  ik_srv.request.ik_request.pose_stamped_vector.push_back(ik_pose_st);
279  ik_srv.request.ik_request.ik_link_names.push_back(tip_frames_[i]);
280  }
281  }
282  else
283  {
284  ik_pose_st.pose = ik_poses[0];
285 
286  // Load into single pose value
287  ik_srv.request.ik_request.pose_stamped = ik_pose_st;
288  ik_srv.request.ik_request.ik_link_name = getTipFrames()[0];
289  }
290 
291  ROS_DEBUG_STREAM_NAMED("srv", "Calling service: " << ik_service_client_->getService());
292  if (ik_service_client_->call(ik_srv))
293  {
294  // Check error code
295  error_code.val = ik_srv.response.error_code.val;
296  if (error_code.val != error_code.SUCCESS)
297  {
298  ROS_DEBUG_STREAM_NAMED("srv", "An IK that satisifes the constraints and is collision free could not be found."
299  << "\nRequest was: \n"
300  << ik_srv.request.ik_request << "\nResponse was: \n"
301  << ik_srv.response.solution);
302  switch (error_code.val)
303  {
304  case moveit_msgs::MoveItErrorCodes::FAILURE:
305  ROS_ERROR_STREAM_NAMED("srv", "Service failed with with error code: FAILURE");
306  break;
307  case moveit_msgs::MoveItErrorCodes::NO_IK_SOLUTION:
308  ROS_ERROR_STREAM_NAMED("srv", "Service failed with with error code: NO IK SOLUTION");
309  break;
310  default:
311  ROS_ERROR_STREAM_NAMED("srv", "Service failed with with error code: " << error_code.val);
312  }
313  return false;
314  }
315  }
316  else
317  {
318  ROS_ERROR_STREAM("Service call failed to connect to service: " << ik_service_client_->getService());
319  error_code.val = error_code.FAILURE;
320  return false;
321  }
322 
323  // Convert the robot state message to our robot_state representation
324  if (!moveit::core::robotStateMsgToRobotState(ik_srv.response.solution, *robot_state_))
325  {
327  "An error occured converting received robot state message into internal robot state.");
328  error_code.val = error_code.FAILURE;
329  return false;
330  }
331 
332  // Get just the joints we are concerned about in our planning group
333  robot_state_->copyJointGroupPositions(joint_model_group_, solution);
334 
335  // Run the solution callback (i.e. collision checker) if available
336  if (!solution_callback.empty())
337  {
338  ROS_DEBUG_STREAM_NAMED("srv", "Calling solution callback on IK solution");
339 
340  // hack: should use all poses, not just the 0th
341  solution_callback(ik_poses[0], solution, error_code);
342 
343  if (error_code.val != error_code.SUCCESS)
344  {
345  switch (error_code.val)
346  {
347  case moveit_msgs::MoveItErrorCodes::FAILURE:
348  ROS_ERROR_STREAM_NAMED("srv", "IK solution callback failed with with error code: FAILURE");
349  break;
350  case moveit_msgs::MoveItErrorCodes::NO_IK_SOLUTION:
351  ROS_ERROR_STREAM_NAMED("srv", "IK solution callback failed with with error code: "
352  "NO IK SOLUTION");
353  break;
354  default:
355  ROS_ERROR_STREAM_NAMED("srv", "IK solution callback failed with with error code: " << error_code.val);
356  }
357  return false;
358  }
359  }
360 
361  ROS_INFO_STREAM_NAMED("srv", "IK Solver Succeeded!");
362  return true;
363 }
364 
365 bool SrvKinematicsPlugin::getPositionFK(const std::vector<std::string>& link_names,
366  const std::vector<double>& joint_angles,
367  std::vector<geometry_msgs::Pose>& poses) const
368 {
369  if (!active_)
370  {
371  ROS_ERROR_NAMED("srv", "kinematics not active");
372  return false;
373  }
374  poses.resize(link_names.size());
375  if (joint_angles.size() != dimension_)
376  {
377  ROS_ERROR_NAMED("srv", "Joint angles vector must have size: %d", dimension_);
378  return false;
379  }
380 
381  ROS_ERROR_STREAM_NAMED("srv", "Forward kinematics not implemented");
382 
383  return false;
384 }
385 
386 const std::vector<std::string>& SrvKinematicsPlugin::getJointNames() const
387 {
388  return ik_group_info_.joint_names;
389 }
390 
391 const std::vector<std::string>& SrvKinematicsPlugin::getLinkNames() const
392 {
393  return ik_group_info_.link_names;
394 }
395 
396 const std::vector<std::string>& SrvKinematicsPlugin::getVariableNames() const
397 {
398  return joint_model_group_->getVariableNames();
399 }
400 
401 } // namespace srv_kinematics_plugin
CLASS_LOADER_REGISTER_CLASS
#define CLASS_LOADER_REGISTER_CLASS(Derived, Base)
duration
std::chrono::system_clock::duration duration
ROS_ERROR_STREAM
#define ROS_ERROR_STREAM(args)
ROS_DEBUG_STREAM_NAMED
#define ROS_DEBUG_STREAM_NAMED(name, args)
moveit::core::RobotModel
ROS_ERROR_NAMED
#define ROS_ERROR_NAMED(name,...)
moveit::core::RobotState
kinematics::KinematicsBase::IKCallbackFn
boost::function< void(const geometry_msgs::Pose &, const std::vector< double > &, moveit_msgs::MoveItErrorCodes &)> IKCallbackFn
srv_kinematics_plugin
Definition: srv_kinematics_plugin.h:59
cached_ik_kinematics_plugin::NearestNeighborsGNAT::size
std::size_t size() const override
Get the number of elements in the datastructure.
Definition: NearestNeighborsGNAT.h:306
kinematics::KinematicsBase
ROS_DEBUG_NAMED
#define ROS_DEBUG_NAMED(name,...)
ros::WallTime::now
static WallTime now()
ROS_ERROR_STREAM_NAMED
#define ROS_ERROR_STREAM_NAMED(name, args)
srv_kinematics_plugin.h
class_loader.hpp
ros::WallTime
ROS_WARN_STREAM_NAMED
#define ROS_WARN_STREAM_NAMED(name, args)
srv_kinematics_plugin::SrvKinematicsPlugin
Specific implementation of kinematics using ROS service calls to communicate with external IK solvers...
Definition: srv_kinematics_plugin.h:97
kinematics::KinematicsQueryOptions
ROS_INFO_STREAM_NAMED
#define ROS_INFO_STREAM_NAMED(name, args)
conversions.h
srv_kinematics_plugin::SrvKinematicsPlugin::SrvKinematicsPlugin
SrvKinematicsPlugin()
Default constructor.
Definition: srv_kinematics_plugin.cpp:83
ros::Duration
moveit::core::robotStateToRobotStateMsg
void robotStateToRobotStateMsg(const RobotState &state, moveit_msgs::RobotState &robot_state, bool copy_attached_bodies=true)
ros::NodeHandle
moveit::core::robotStateMsgToRobotState
bool robotStateMsgToRobotState(const moveit_msgs::RobotState &robot_state, RobotState &state, bool copy_attached_bodies=true)


moveit_kinematics
Author(s): Dave Coleman , Ioan Sucan , Sachin Chitta
autogenerated on Fri May 3 2024 02:29:33