tst_prbt_ikfast_manipulator_plugin.cpp
Go to the documentation of this file.
1 #include <ros/ros.h>
2 #include <gtest/gtest.h>
4 
6 
7 typedef std::vector<double> Vec1D;
8 typedef std::vector<Vec1D> Vec2D;
10 
11 static const std::string MOVEIT_CORE_PACKAGE {"moveit_core"};
12 static const std::string KINEMATICS_BASE_CLASS {"kinematics::KinematicsBase"};
13 
14 static const std::string PLUGIN_NAME_PARAM {"ik_plugin_name"};
15 static const std::string GROUP_PARAM {"group"};
16 static const std::string TIP_LINK_PARAM {"tip_link"};
17 static const std::string ROOT_LINK_PARAM {"root_link"};
18 static const std::string JOINT_NAMES_PARAM {"joint_names"};
19 static const std::string ROBOT_DESCRIPTION_PARAM {"robot_description"};
20 
21 static constexpr double DEFAULT_SEARCH_DISCRETIZATION {0.01};
22 static constexpr unsigned int NUM_JOINTS {6};
23 static constexpr double IKFAST_TOLERANCE {0.001};
24 
25 static constexpr double L1 {0.3500}; // Height of first connector
26 static constexpr double L2 {0.3070}; // Height of second connector
27 
31 std::ostream& operator<< (std::ostream &os, const Vec1D &vec)
32 {
33  os << "(";
34  if (!vec.empty())
35  {
36  auto it = vec.begin();
37  os << *it;
38  for (++it; it < vec.end(); ++it)
39  {
40  os << ", " << *it;
41  }
42  }
43  os << ")";
44  return os;
45 }
46 
50 std::ostream& operator<< (std::ostream &os, const geometry_msgs::Pose &pose)
51 {
52  os << "position: x=" << double(pose.position.x)
53  << ", y=" << double(pose.position.y)
54  << ", z=" << double(pose.position.z)
55  << ", orientation: x=" << double(pose.orientation.x)
56  << ", y=" << double(pose.orientation.y)
57  << ", z=" << double(pose.orientation.z)
58  << ", w=" << double(pose.orientation.w);
59  return os;
60 }
61 
65 double singularPoseJointFormula(double joint1)
66 {
67  return ( asin( L1 / L2 * sin(joint1) ) + joint1 );
68 }
69 
73 class PrbtIKFastPluginTest : public ::testing::Test
74 {
75 protected:
77  void SetUp();
78 
80  void TearDown();
81 
82 protected:
83  std::string root_link_;
84  std::string tip_link_;
85  std::string group_name_;
86  std::vector<std::string> joint_names_;
87 
89 
90 private:
93 };
94 
96 {
97  // load plugin
98  std::string plugin_name;
100  << "The parameter " << PLUGIN_NAME_PARAM << " was not found.";
101 
102  try
103  {
104  solver_ = loader_.createInstance(plugin_name);
105  }
107  {
108  FAIL() << "Failed to load plugin: " << e.what();
109  }
110 
111  // initialize plugin
113  << "The parameter " << GROUP_PARAM << " was not found.";
115  << "The parameter " << TIP_LINK_PARAM << " was not found.";
117  << "The parameter " << ROOT_LINK_PARAM << " was not round.";
119  << "The parameter " << JOINT_NAMES_PARAM << " was not found.";
120 
121  std::vector<std::string> tip_links {tip_link_};
122 
123  ASSERT_TRUE( solver_->initialize(ROBOT_DESCRIPTION_PARAM, group_name_, root_link_, tip_links,
124  DEFAULT_SEARCH_DISCRETIZATION) ) << "Failed to initialize plugin.";
125 }
126 
128 {
129  solver_.reset();
130 }
131 
147 TEST_F(PrbtIKFastPluginTest, testSingularities)
148 {
149  // ++++++++++
150  // + Step 1 +
151  // ++++++++++
152 
153  std::vector<std::string> link_names { {solver_->getTipFrame()} };
154  Vec1D seed;
155  seed.resize(NUM_JOINTS, 0.);
156 
157  Vec2D joints_test_set;
158  joints_test_set.push_back(Vec1D { {0.0, 0.0, 0.0, 0.0, 0.0, 0.0} });
159  joints_test_set.push_back(Vec1D { {0.0, 0.0, 0.0, 1.0, 0.0, 0.0} });
160  joints_test_set.push_back(Vec1D { {0.0, 0.0, 0.0, 0.0, -1.0, 0.0} });
161  joints_test_set.push_back(Vec1D { {0.0, 0.0, 0.0, 0.0, 1.0, 1.0} });
162 
163  double j1 { 1.0 };
164  double j2 { singularPoseJointFormula(j1) };
165  joints_test_set.push_back(Vec1D { {0.0, j1, j2, 0.0, 0.0, 0.0} });
166  joints_test_set.push_back(Vec1D { {0.0, j1, j2, -1.0, 0.0, 0.0} });
167  joints_test_set.push_back(Vec1D { {0.0, j1, j2, 0.0, 1.0, 0.0} });
168  joints_test_set.push_back(Vec1D { {0.0, j1, j2, 0.0, 1.0, -1.0} });
169 
170  // Same procedure for all joint vectors
171  for (Vec1D joints : joints_test_set)
172  {
173  ROS_INFO_STREAM("Using joint angles: " << joints);
174 
175  // ++++++++++
176  // + Step 2 +
177  // ++++++++++
178 
179  std::vector<geometry_msgs::Pose> poses;
180  ASSERT_TRUE( solver_->getPositionFK(link_names, joints, poses) )
181  << "Failed to compute forward kinematics.";
182  EXPECT_EQ(1u, poses.size());
183  ROS_INFO_STREAM("Obtain pose: " << poses.at(0));
184 
185  // ++++++++++
186  // + Step 3 +
187  // ++++++++++
188 
189  Vec2D solutions;
192 
193  ros::Time generation_begin = ros::Time::now();
194  EXPECT_TRUE( solver_->getPositionIK(poses, seed, solutions, result, options) )
195  << "Failed to solve inverse kinematics.";
196  double duration_ms = (ros::Time::now() - generation_begin).toSec() * 1000;
197  ROS_DEBUG_STREAM("Ik solve took " << duration_ms << " ms");
198 
199 
200  ROS_INFO_STREAM("Received " << solutions.size() << " solutions to IK problem.");
201  EXPECT_GT(solutions.size(), 0u);
202 
203  // ++++++++++
204  // + Step 4 +
205  // ++++++++++
206 
207  bool found_expected_solution {false};
208  for (Vec1D sol : solutions)
209  {
210  EXPECT_EQ(sol.size(), NUM_JOINTS);
211 
212  double diff {0.0};
213  for (unsigned int j = 0; j < NUM_JOINTS; j++)
214  {
215  diff += pow(sol[j] - joints[j], 2);
216  }
217 
218  found_expected_solution = (sqrt(diff) < IKFAST_TOLERANCE);
219  if (found_expected_solution)
220  {
221  break;
222  }
223  }
224 
225  if (!found_expected_solution)
226  {
227  ADD_FAILURE() << "No solution is near the expected values.";
228  // print all solutions in case of failure
229  for (Vec1D sol : solutions)
230  {
231  ROS_INFO_STREAM("Solution: " << sol);
232  }
233  }
234  }
235 }
236 
237 int main(int argc, char** argv)
238 {
239  ros::init(argc, argv, "unittest_prbt_ikfast_manipulator_plugin");
240  ros::NodeHandle nh;
241 
242  testing::InitGoogleTest(&argc, argv);
243  return RUN_ALL_TESTS();
244 }
static const std::string MOVEIT_CORE_PACKAGE
static const std::string GROUP_PARAM
std::ostream & operator<<(std::ostream &os, const Vec1D &vec)
Overload ostream operator for double vectors.
static constexpr double IKFAST_TOLERANCE
static constexpr double L1
static const std::string ROOT_LINK_PARAM
ROSCPP_DECL void init(int &argc, char **argv, const std::string &name, uint32_t options=0)
IMETHOD Vector diff(const Vector &p_w_a, const Vector &p_w_b, double dt=1)
int main(int argc, char **argv)
void TearDown()
Ensures that the solver is destroyed before the ClassLoader.
static const std::string JOINT_NAMES_PARAM
#define EXPECT_EQ(a, b)
std::vector< Vec1D > Vec2D
static constexpr unsigned int NUM_JOINTS
options
INLINE Rall1d< T, V, S > asin(const Rall1d< T, V, S > &x)
TEST_F(PrbtIKFastPluginTest, testSingularities)
Tests if the IKFast plugin can solve the IK problem for specific singular poses.
void SetUp()
Loads and initializes the IKFast plugin.
INLINE Rall1d< T, V, S > sqrt(const Rall1d< T, V, S > &arg)
#define ROS_DEBUG_STREAM(args)
INLINE Rall1d< T, V, S > pow(const Rall1d< T, V, S > &arg, double m)
std::vector< std::string > joint_names_
#define ROS_INFO_STREAM(args)
static const std::string ROBOT_DESCRIPTION_PARAM
bool getParam(const std::string &key, std::string &s) const
static Time now()
double singularPoseJointFormula(double joint1)
Computes joint2 from joint1 such that singular position with px,py=0 is reached.
static const std::string TIP_LINK_PARAM
static const std::string PLUGIN_NAME_PARAM
static constexpr double L2
static constexpr double DEFAULT_SEARCH_DISCRETIZATION
pluginlib::ClassLoader< kinematics::KinematicsBase > KinematicsLoader
#define EXPECT_TRUE(args)
INLINE Rall1d< T, V, S > sin(const Rall1d< T, V, S > &arg)
std::vector< double > Vec1D
Initializes the test of the IKFast plugin.
static const std::string KINEMATICS_BASE_CLASS
boost::shared_ptr< kinematics::KinematicsBase > solver_


prbt_ikfast_manipulator_plugin
Author(s):
autogenerated on Tue Feb 2 2021 03:50:30