fk_ik_tests.cpp
Go to the documentation of this file.
1 // Author: Jeroen De Maeyer (JeroenDM @ Github)
2 // With edits by Jonathan Meyer
3 
4 #include <array>
5 #include <chrono>
6 #include <gtest/gtest.h>
7 #include <random>
8 
13 
14 
15 // Structure used for setting sampler parameters based on floating point type
16 template <typename T>
18 
19 template<>
20 struct TestTolerance<float> {
21  static constexpr float TOLERANCE = 5e-4f;
22  static constexpr const char* const NAME = "float";
23 };
24 
25 template<>
26 struct TestTolerance<double> {
27  static constexpr double TOLERANCE = 1e-10;
28  static constexpr const char* const NAME = "double";
29 };
30 
31 // Helper Functions for generating and testing random poses in cartesian/joint space
33 
34 template <typename T>
35 void comparePoses(const Transform<T>& Ta, const Transform<T>& Tb, double tolerance)
36 {
37  using Matrix = Eigen::Matrix<T, 3, 3>;
38  using Vector = Eigen::Matrix<T, 3, 1>;
39 
40  Matrix Ra = Ta.rotation(), Rb = Tb.rotation();
41  for (int i = 0; i < Ra.rows(); ++i)
42  {
43  for (int j = 0; j < Ra.cols(); ++j)
44  {
45  EXPECT_NEAR(Ra(i, j), Rb(i, j), tolerance);
46  }
47  }
48 
49  Vector pa = Ta.translation(), pb = Tb.translation();
50  EXPECT_NEAR(pa[0], pb[0], tolerance);
51  EXPECT_NEAR(pa[1], pb[1], tolerance);
52  EXPECT_NEAR(pa[2], pb[2], tolerance);
53 }
54 
55 template <typename T>
57 {
58  static std::default_random_engine en{ 42 }; // random engine
59  static std::uniform_real_distribution<T> rg{ T(-M_PI), T(M_PI) }; // random generator
60 
61  q[0] = rg(en);
62  q[1] = rg(en);
63  q[2] = rg(en);
64  q[3] = rg(en);
65  q[4] = rg(en);
66  q[5] = rg(en);
67 }
68 
69 // Generate random joint pose -> Solve FK -> Solve IK -> Verify that new FK matches
70 // the original.
71 template <typename T>
73 {
74  const static unsigned int number_of_tests = 1000;
75 
76  Transform<T> pose, forward_pose;
77  T q_rand[6];
78  std::array<T, 6 * 8> sols;
79 
80  for (unsigned j = 0; j < number_of_tests; ++j)
81  {
82  // create a reachable pose based on a random robot position
83  getRandomJointValues(q_rand);
84  pose = opw_kinematics::forward(params, q_rand);
85 
86  // Solve Inverse kinematics
87  opw_kinematics::inverse(params, pose, sols.data());
88 
89  // check all valid solutions using forward kinematics
90  for (unsigned i = 0; i < 8; ++i)
91  {
92  if (opw_kinematics::isValid(&sols[6 * i]))
93  {
94  // Forward kinematics of a solution should result in the same pose
95  forward_pose = opw_kinematics::forward(params, &sols[6 * i]);
96  comparePoses(forward_pose, pose, TestTolerance<T>::TOLERANCE);
97  }
98  }
99  }
100 }
101 
102 // Generate random joint poses, time how long it takes to solve FK for all of them
103 // Then time how long it takes to solve IK for all of them
104 template <typename T>
106 {
107  const static unsigned int number_of_tests = 10000;
108 
109  std::vector<Transform<T>, Eigen::aligned_allocator<Transform<T>>> poses;
110  poses.resize(number_of_tests);
111 
112  {
113  // Generate N random joint poses
114  std::vector<std::array<T, 6>> random_joint_values;
115  random_joint_values.resize(number_of_tests);
116 
117  for (std::size_t i = 0; i < number_of_tests; ++i)
118  {
119  getRandomJointValues(random_joint_values[i].data());
120  }
121 
122  // Time the solving of FK
123  const auto fk_start_tm = std::chrono::steady_clock::now();
124  for (std::size_t i = 0; i < number_of_tests; ++i)
125  {
126  poses[i] = opw_kinematics::forward(params, random_joint_values[i].data());
127  }
128  const auto fk_end_tm = std::chrono::steady_clock::now();
129 
130  // Report FK timing
131  const auto fk_dt_us = std::chrono::duration_cast<std::chrono::microseconds>(fk_end_tm - fk_start_tm).count();
132  std::cout << "Forward Kinematics " << TestTolerance<T>::NAME << " generated " << number_of_tests
133  << " poses in " << fk_dt_us << " us\n";
134  std::cout << "Average us per fk solve: " << static_cast<double>(fk_dt_us) / number_of_tests << "\n";
135  }
136 
137  std::array<T, 6*8> ik_sol_space;
138  const auto ik_start_tm = std::chrono::steady_clock::now();
139  for (std::size_t i = 0; i < number_of_tests; ++i)
140  {
141  opw_kinematics::inverse(params, poses[i], ik_sol_space.data());
142  }
143  const auto ik_end_tm = std::chrono::steady_clock::now();
144  // Report FK timing
145  const auto ik_dt_us = std::chrono::duration_cast<std::chrono::microseconds>(ik_end_tm - ik_start_tm).count();
146  std::cout << "Inverse Kinematics " << TestTolerance<T>::NAME << " generated " << number_of_tests
147  << " poses in " << ik_dt_us << " us\n";
148  std::cout << "Average us per ik solve: " << static_cast<double>(ik_dt_us) / number_of_tests << "\n";
149 }
150 
151 TEST(kuka_kr6, random_reachable_poses_double)
152 {
153  const auto kukaKR6_R700_sixx = opw_kinematics::makeKukaKR6_R700_sixx<double>();
154  runRandomReachablePosesTest(kukaKR6_R700_sixx);
155 }
156 
157 TEST(kuka_kr6, random_reachable_poses_float)
158 {
159  const auto kukaKR6_R700_sixx = opw_kinematics::makeKukaKR6_R700_sixx<float>();
160  runRandomReachablePosesTest(kukaKR6_R700_sixx);
161 }
162 
163 TEST(kuka_kr6, throughput_tests_float)
164 {
165  const auto params = opw_kinematics::makeKukaKR6_R700_sixx<float>();
166  runThroughputTests(params);
167 }
168 
169 TEST(kuka_kr6, throughput_tests_double)
170 {
171  const auto params = opw_kinematics::makeKukaKR6_R700_sixx<double>();
172  runThroughputTests(params);
173 }
174 
175 TEST(abb_2400, throughput_tests_float)
176 {
177  const auto params = opw_kinematics::makeIrb2400_10<float>();
178  runThroughputTests(params);
179 }
180 TEST(abb_2400, random_reachable_poses_double)
181 {
182  const auto params = opw_kinematics::makeIrb2400_10<double>();
184 }
185 
186 TEST(abb_2400, random_reachable_poses_float)
187 {
188  const auto params= opw_kinematics::makeIrb2400_10<float>();
190 }
191 
192 TEST(abb_2400, throughput_tests_double)
193 {
194  const auto params = opw_kinematics::makeIrb2400_10<double>();
195  runThroughputTests(params);
196 }
197 
198 OPW_IGNORE_WARNINGS_PUSH
199 TEST(fanuc_r2000, random_reachable_poses_double)
200 {
201  const auto params = opw_kinematics::makeFanucR2000iB_200R<double>();
203 }
204 
205 TEST(fanuc_r2000, random_reachable_poses_float)
206 {
207  const auto params= opw_kinematics::makeFanucR2000iB_200R<float>();
209 }
210 
211 TEST(fanuc_r2000, throughput_tests_float)
212 {
213  const auto params = opw_kinematics::makeFanucR2000iB_200R<float>();
214  runThroughputTests(params);
215 }
216 
217 TEST(fanuc_r2000, throughput_tests_double)
218 {
219  const auto params = opw_kinematics::makeFanucR2000iB_200R<double>();
220  runThroughputTests(params);
221 }
222 OPW_IGNORE_WARNINGS_POP
223 
224 int main(int argc, char** argv)
225 {
226  testing::InitGoogleTest(&argc, argv);
227  return RUN_ALL_TESTS();
228 }
void runThroughputTests(const opw_kinematics::Parameters< T > &params)
f
const double TOLERANCE
#define M_PI
#define EXPECT_NEAR(a, b, prec)
bool isValid(const T *qs)
Definition: opw_utilities.h:10
void comparePoses(const Transform< T > &Ta, const Transform< T > &Tb, double tolerance)
Definition: fk_ik_tests.cpp:35
void runRandomReachablePosesTest(const opw_kinematics::Parameters< T > &params)
Definition: fk_ik_tests.cpp:72
void getRandomJointValues(T *q)
Definition: fk_ik_tests.cpp:56
string NAME
Eigen::Transform< T, 3, Eigen::Isometry > Transform
TEST(kuka_kr6, random_reachable_poses_double)
OPW_IGNORE_WARNINGS_POP int main(int argc, char **argv)
void inverse(const Parameters< T > &params, const Transform< T > &pose, T *out) noexcept
Computes up to 8 kinematically unique joint solutions that put the tool flange of the robot described...
opw_kinematics::Transform< double > Transform
Transform< T > forward(const Parameters< T > &p, const T *qs) noexcept
Computes the tool pose of the robot described by when said robot has the joint positions given by qs...


moveit_opw_kinematics_plugin
Author(s): Jeroen De Maeyer, Simon Schmeisser (isys vision)
autogenerated on Wed Jun 3 2020 03:17:14