test_kinematics_as_plugin.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 /* Modified by Guillaume WALCK for Shadow Hands*/
37 
38 #include <ros/ros.h>
39 #include <gtest/gtest.h>
40 #include <pluginlib/class_loader.h>
41 #include <string>
42 #include <vector>
43 
44 // HandKinematics
46 // MoveIt!
51 #include <urdf/model.h>
52 #include <srdfdom/model.h>
53 
54 #define IK_NEAR 3e-3
55 #define IK_NEAR_TRANSLATE 1e-5
56 
57 class MyTest
58 {
59 public:
60  bool initialize()
61  {
62  double search_discretization;
63  ros::NodeHandle nh("~");
64  kinematics_loader_.reset(
65  new pluginlib::ClassLoader<kinematics::KinematicsBase>("moveit_core", "kinematics::KinematicsBase"));
66 
67  std::string plugin_name;
68  if (!nh.getParam("plugin_name", plugin_name))
69  {
70  ROS_ERROR("No plugin name found on parameter server");
71  EXPECT_TRUE(0);
72  return false;
73  }
74  ROS_INFO("Plugin name: %s", plugin_name.c_str());
75  try
76  {
77  kinematics_solver_ = kinematics_loader_->createUniqueInstance(plugin_name);
78  }
79  catch (pluginlib::PluginlibException &ex) // handle the class failing to load
80  {
81  ROS_ERROR("The plugin failed to load. Error: %s", ex.what());
82  EXPECT_TRUE(0);
83  return false;
84  }
85  std::string root_name, tip_name, finger_group_name;
86  ros::WallTime start_time = ros::WallTime::now();
87  bool done = true;
88  while ((ros::WallTime::now() - start_time).toSec() <= 5.0)
89  {
90  if (!nh.getParam("root_name", root_name))
91  {
92  ROS_ERROR("No root name found on parameter server");
93  done = false;
94  EXPECT_TRUE(0);
95  continue;
96  }
97  if (!nh.getParam("tip_name", tip_name))
98  {
99  ROS_ERROR("No tip name found on parameter server");
100  done = false;
101  EXPECT_TRUE(0);
102  continue;
103  }
104  if (!nh.getParam("search_discretization", search_discretization))
105  {
106  ROS_ERROR("No search discretization found on parameter server");
107  done = false;
108  EXPECT_TRUE(0);
109  continue;
110  }
111  if (!nh.getParam("group_name", finger_group_name))
112  {
113  ROS_ERROR("No group name given, using fingers");
114  finger_group_name = "fingers";
115  continue;
116  }
117 
118 
119  done = true;
120  }
121 
122  if (!done)
123  {
124  return false;
125  }
126 
127  if (kinematics_solver_->initialize("robot_description", finger_group_name, root_name, tip_name,
128  search_discretization))
129  {
130  return true;
131  }
132  else
133  {
134  EXPECT_TRUE(0);
135  return false;
136  }
137  };
138 
139  void joint_state_callback(const geometry_msgs::Pose &ik_pose,
140  const std::vector<double> &joint_state,
141  moveit_msgs::MoveItErrorCodes &error_code)
142  {
143  std::vector<std::string> link_names;
144  link_names.push_back(kinematics_solver_->getTipFrame());
145  std::vector<geometry_msgs::Pose> solutions;
146  solutions.resize(1);
147  if (!kinematics_solver_->getPositionFK(link_names, joint_state, solutions))
148  {
149  error_code.val = error_code.PLANNING_FAILED;
150  }
151  if (solutions[0].position.z > 0.0)
152  {
153  error_code.val = error_code.SUCCESS;
154  }
155  else
156  {
157  error_code.val = error_code.PLANNING_FAILED;
158  }
159  };
160 
161  kinematics::KinematicsBasePtr kinematics_solver_;
163 };
164 
166 
167 TEST(HandIKPlugin, initialize)
168 {
169  ASSERT_TRUE(my_test.initialize());
170  // Test getting chain information
171  std::string root_name = my_test.kinematics_solver_->getBaseFrame();
172  EXPECT_TRUE(root_name == std::string("rh_palm"));
173  std::string tool_name = my_test.kinematics_solver_->getTipFrame();
174  EXPECT_TRUE(tool_name.find("tip") != std::string::npos);
175  std::vector<std::string> joint_names = my_test.kinematics_solver_->getJointNames();
176 
177  if (tool_name.find("fftip") != std::string::npos)
178  {
179  EXPECT_EQ(static_cast<int>(joint_names.size()), 4);
180  EXPECT_TRUE(joint_names[0].find("FFJ4") != std::string::npos);
181  EXPECT_TRUE(joint_names[1].find("FFJ3") != std::string::npos);
182  EXPECT_TRUE(joint_names[2].find("FFJ2") != std::string::npos);
183  EXPECT_TRUE(joint_names[3].find("FFJ1") != std::string::npos);
184  }
185  if (tool_name.find("mftip") != std::string::npos)
186  {
187  EXPECT_EQ(static_cast<int>(joint_names.size()), 4);
188  EXPECT_TRUE(joint_names[0].find("MFJ4") != std::string::npos);
189  EXPECT_TRUE(joint_names[1].find("MFJ3") != std::string::npos);
190  EXPECT_TRUE(joint_names[2].find("MFJ2") != std::string::npos);
191  EXPECT_TRUE(joint_names[3].find("MFJ1") != std::string::npos);
192  }
193  if (tool_name.find("rftip") != std::string::npos)
194  {
195  EXPECT_EQ(static_cast<int>(joint_names.size()), 4);
196  EXPECT_TRUE(joint_names[0].find("RFJ4") != std::string::npos);
197  EXPECT_TRUE(joint_names[1].find("RFJ3") != std::string::npos);
198  EXPECT_TRUE(joint_names[2].find("RFJ2") != std::string::npos);
199  EXPECT_TRUE(joint_names[3].find("RFJ1") != std::string::npos);
200  }
201  if (tool_name.find("lftip") != std::string::npos)
202  {
203  EXPECT_EQ(static_cast<int>(joint_names.size()), 5);
204  EXPECT_TRUE(joint_names[0].find("LFJ5") != std::string::npos);
205  EXPECT_TRUE(joint_names[1].find("LFJ4") != std::string::npos);
206  EXPECT_TRUE(joint_names[2].find("LFJ3") != std::string::npos);
207  EXPECT_TRUE(joint_names[3].find("LFJ2") != std::string::npos);
208  EXPECT_TRUE(joint_names[4].find("LFJ1") != std::string::npos);
209  }
210  if (tool_name.find("thtip") != std::string::npos)
211  {
212  EXPECT_EQ(static_cast<int>(joint_names.size()), 5);
213  EXPECT_TRUE(joint_names[0].find("THJ5") != std::string::npos);
214  EXPECT_TRUE(joint_names[1].find("THJ4") != std::string::npos);
215  EXPECT_TRUE(joint_names[2].find("THJ3") != std::string::npos);
216  EXPECT_TRUE(joint_names[3].find("THJ2") != std::string::npos);
217  EXPECT_TRUE(joint_names[4].find("THJ1") != std::string::npos);
218  }
219 }
220 
221 TEST(HandIKPlugin, getFK)
222 {
223  rdf_loader::RDFLoader rdf_loader_;
224  robot_model::RobotModelPtr kinematic_model;
225  const boost::shared_ptr<srdf::Model> &srdf = rdf_loader_.getSRDF();
226  const boost::shared_ptr<urdf::ModelInterface> &urdf_model = rdf_loader_.getURDF();
227  kinematic_model.reset(new robot_model::RobotModel(urdf_model, srdf));
228  robot_model::JointModelGroup *joint_model_group = kinematic_model->getJointModelGroup(
229  my_test.kinematics_solver_->getGroupName());
230 
231  std::vector<double> seed, fk_values, solution;
232  moveit_msgs::MoveItErrorCodes error_code;
233  solution.resize(my_test.kinematics_solver_->getJointNames().size(), 0.0);
234 
235  std::vector<std::string> fk_names;
236  fk_names.push_back(my_test.kinematics_solver_->getTipFrame());
237 
238  robot_state::RobotState kinematic_state(kinematic_model);
239 
240  ros::NodeHandle nh("~");
241  int number_fk_tests;
242  nh.param("number_fk_tests", number_fk_tests, 100);
243 
244  for (unsigned int i = 0; i < (unsigned int) number_fk_tests; ++i)
245  {
246  seed.resize(my_test.kinematics_solver_->getJointNames().size(), 0.0);
247  fk_values.resize(my_test.kinematics_solver_->getJointNames().size(), 0.0);
248 
249  kinematic_state.setToRandomPositions(joint_model_group);
250  kinematic_state.copyJointGroupPositions(joint_model_group, fk_values);
251 
252  std::vector<geometry_msgs::Pose> poses;
253  poses.resize(1);
254  bool result_fk = my_test.kinematics_solver_->getPositionFK(fk_names, fk_values, poses);
255  ASSERT_TRUE(result_fk);
256  }
257 }
258 
259 TEST(HandIKPlugin, searchIK)
260 {
261  rdf_loader::RDFLoader rdf_loader_;
262  robot_model::RobotModelPtr kinematic_model;
263  const boost::shared_ptr<srdf::Model> &srdf_model = rdf_loader_.getSRDF();
264  const boost::shared_ptr<urdf::ModelInterface> &urdf_model = rdf_loader_.getURDF();
265  kinematic_model.reset(new robot_model::RobotModel(urdf_model, srdf_model));
266  robot_model::JointModelGroup *joint_model_group = kinematic_model->getJointModelGroup(
267  my_test.kinematics_solver_->getGroupName());
268 
269  // Test inverse kinematics
270  std::vector<double> seed, fk_values, solution;
271  double timeout = 5.0;
272  moveit_msgs::MoveItErrorCodes error_code;
273  solution.resize(my_test.kinematics_solver_->getJointNames().size(), 0.0);
274 
275  std::vector<std::string> fk_names;
276  fk_names.push_back(my_test.kinematics_solver_->getTipFrame());
277 
278  robot_state::RobotState kinematic_state(kinematic_model);
279 
280  ros::NodeHandle nh("~");
281  int number_ik_tests;
282  nh.param("number_ik_tests", number_ik_tests, 10);
283  unsigned int success = 0;
284 
285  std::vector<std::string> joint_names = my_test.kinematics_solver_->getJointNames();
286 
287  ros::WallTime start_time = ros::WallTime::now();
288  for (unsigned int i = 0; i < (unsigned int) number_ik_tests; ++i)
289  {
290  seed.resize(my_test.kinematics_solver_->getJointNames().size(), 0.0);
291  fk_values.resize(my_test.kinematics_solver_->getJointNames().size(), 0.0);
292  kinematic_state.setToRandomPositions(joint_model_group);
293  kinematic_state.copyJointGroupPositions(joint_model_group, fk_values);
294 
295  // make the coupling 1:1 in random values
296  if (joint_names[0].find("TH") == std::string::npos && joint_names[0].find("LF") == std::string::npos)
297  {
298  fk_values[3] = fk_values[2];
299  }
300  else if (joint_names[0].find("LF") != std::string::npos)
301  {
302  fk_values[4] = fk_values[3];
303  }
304 
305  std::vector<geometry_msgs::Pose> poses;
306  poses.resize(1);
307  bool result_fk = my_test.kinematics_solver_->getPositionFK(fk_names, fk_values, poses);
308  ASSERT_TRUE(result_fk);
309 
310  bool result = my_test.kinematics_solver_->searchPositionIK(poses[0], seed, timeout, solution, error_code);
311  ROS_DEBUG("Pose: %f %f %f", poses[0].position.x, poses[0].position.y, poses[0].position.z);
312  ROS_DEBUG("Orient: %f %f %f %f", poses[0].orientation.x, poses[0].orientation.y, poses[0].orientation.z,
313  poses[0].orientation.w);
314  if (result)
315  {
316  success++;
317  result = my_test.kinematics_solver_->getPositionIK(poses[0], solution, solution, error_code);
318  EXPECT_TRUE(result);
319  }
320  else
321  {
322  if (fk_names[0].find("TH") != std::string::npos)
323  ROS_DEBUG("fk values: %f %f %f %f %f", fk_values[0], fk_values[1], fk_values[2], fk_values[3], fk_values[4]);
324  }
325 
326  std::vector<geometry_msgs::Pose> new_poses;
327  new_poses.resize(1);
328  result_fk = my_test.kinematics_solver_->getPositionFK(fk_names, solution, new_poses);
329 
330  EXPECT_NEAR(poses[0].position.x, new_poses[0].position.x, IK_NEAR);
331  EXPECT_NEAR(poses[0].position.y, new_poses[0].position.y, IK_NEAR);
332  EXPECT_NEAR(poses[0].position.z, new_poses[0].position.z, IK_NEAR);
333  }
334  ROS_INFO("Success Rate: %f", static_cast<double>(success / number_ik_tests));
335  bool success_count = (success > 0.99 * number_ik_tests);
336  EXPECT_TRUE(success_count);
337  ROS_INFO("Elapsed time: %f", (ros::WallTime::now() - start_time).toSec());
338 }
339 
340 TEST(HandIKPlugin, searchIKWithCallbacks)
341 {
342  rdf_loader::RDFLoader rdf_loader_;
343  robot_model::RobotModelPtr kinematic_model;
344  const boost::shared_ptr<srdf::Model> &srdf = rdf_loader_.getSRDF();
345  const boost::shared_ptr<urdf::ModelInterface> &urdf_model = rdf_loader_.getURDF();
346  kinematic_model.reset(new robot_model::RobotModel(urdf_model, srdf));
347  robot_model::JointModelGroup *joint_model_group = kinematic_model->getJointModelGroup(
348  my_test.kinematics_solver_->getGroupName());
349 
350  // Test inverse kinematics
351  std::vector<double> seed, fk_values, solution;
352  double timeout = 5.0;
353  moveit_msgs::MoveItErrorCodes error_code;
354  solution.resize(my_test.kinematics_solver_->getJointNames().size(), 0.0);
355 
356  std::vector<std::string> fk_names;
357  fk_names.push_back(my_test.kinematics_solver_->getTipFrame());
358 
359  robot_state::RobotState kinematic_state(kinematic_model);
360 
361  ros::NodeHandle nh("~");
362  int number_ik_tests;
363  nh.param("number_ik_tests_with_callbacks", number_ik_tests, 10);
364  unsigned int success = 0;
365  unsigned int num_actual_tests = 0;
366  std::vector<std::string> joint_names = my_test.kinematics_solver_->getJointNames();
367  for (unsigned int i = 0; i < (unsigned int) number_ik_tests; ++i)
368  {
369  seed.resize(my_test.kinematics_solver_->getJointNames().size(), 0.0);
370  fk_values.resize(my_test.kinematics_solver_->getJointNames().size(), 0.0);
371 
372  kinematic_state.setToRandomPositions(joint_model_group);
373  kinematic_state.copyJointGroupPositions(joint_model_group, fk_values);
374 
375  // make the coupling 1:1 in random values
376  if (joint_names[0].find("TH") == std::string::npos && joint_names[0].find("LF") == std::string::npos)
377  {
378  fk_values[3] = fk_values[2];
379  }
380  else if (joint_names[0].find("LF") != std::string::npos)
381  {
382  fk_values[4] = fk_values[3];
383  }
384 
385  std::vector<geometry_msgs::Pose> poses;
386  poses.resize(1);
387  bool result_fk = my_test.kinematics_solver_->getPositionFK(fk_names, fk_values, poses);
388  ASSERT_TRUE(result_fk);
389  if (poses[0].position.z < 0.0)
390  {
391  continue;
392  }
393 
394  num_actual_tests++;
395  bool result = my_test.kinematics_solver_->searchPositionIK(poses[0], seed, timeout, solution,
396  boost::bind(&MyTest::joint_state_callback, &my_test, _1,
397  _2, _3), error_code);
398 
399  if (result)
400  {
401  success++;
402  std::vector<geometry_msgs::Pose> new_poses;
403  new_poses.resize(1);
404  result_fk = my_test.kinematics_solver_->getPositionFK(fk_names, solution, new_poses);
405 
406  EXPECT_NEAR(poses[0].position.x, new_poses[0].position.x, IK_NEAR);
407  EXPECT_NEAR(poses[0].position.y, new_poses[0].position.y, IK_NEAR);
408  EXPECT_NEAR(poses[0].position.z, new_poses[0].position.z, IK_NEAR);
409  }
410 
411  if (!ros::ok())
412  {
413  break;
414  }
415  }
416  ROS_INFO("Success with callbacks (%%): %f", static_cast<double>(success / num_actual_tests) * 100.0);
417 }
418 
419 
420 int main(int argc, char **argv)
421 {
422  testing::InitGoogleTest(&argc, argv);
423  ros::init(argc, argv, "right_hand_kinematics");
424  return RUN_ALL_TESTS();
425 }
const srdf::ModelSharedPtr & getSRDF() const
ROSCPP_DECL void init(int &argc, char **argv, const std::string &name, uint32_t options=0)
boost::shared_ptr< pluginlib::ClassLoader< kinematics::KinematicsBase > > kinematics_loader_
#define EXPECT_NEAR(a, b, prec)
#define IK_NEAR
void joint_state_callback(const geometry_msgs::Pose &ik_pose, const std::vector< double > &joint_state, moveit_msgs::MoveItErrorCodes &error_code)
#define EXPECT_EQ(a, b)
TEST(HandIKPlugin, initialize)
#define ROS_INFO(...)
bool param(const std::string &param_name, T &param_val, const T &default_val) const
ROSCPP_DECL bool ok()
ros::NodeHandle * nh
int main(int argc, char **argv)
static WallTime now()
bool getParam(const std::string &key, std::string &s) const
#define EXPECT_TRUE(args)
#define ROS_ERROR(...)
kinematics::KinematicsBasePtr kinematics_solver_
const urdf::ModelInterfaceSharedPtr & getURDF() const
#define ROS_DEBUG(...)


hand_kinematics
Author(s): Juan Antonio Corrales Ramon (UPMC),, Guillaume Walck (CITEC)
autogenerated on Wed Oct 14 2020 04:05:07