cartesian_trajectory_segment_test.cpp
Go to the documentation of this file.
1 // -- BEGIN LICENSE BLOCK ----------------------------------------------
2 // Copyright 2021 FZI Forschungszentrum Informatik
3 // Created on behalf of Universal Robots A/S
4 //
5 // Licensed under the Apache License, Version 2.0 (the "License");
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
8 //
9 // http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 // -- END LICENSE BLOCK ------------------------------------------------
17 
18 //-----------------------------------------------------------------------------
25 //-----------------------------------------------------------------------------
26 
27 #include <gtest/gtest.h>
28 
30 
31 using namespace ros_controllers_cartesian;
32 
33 TEST(TestCartesianTrajectorySegment, SamplingBeyondBoundariesIsSafe)
34 {
36  start.p.x() = 1.0;
37  start.v.x() = 1.0;
38  start.w.x() = 1.0;
39  start.v_dot.x() = 1.0;
40  start.w_dot.x() = 1.0;
41  double start_time = 0;
42 
43  CartesianState end;
44  end.p.x() = 2.0;
45  end.v.x() = 2.0;
46  end.w.x() = 2.0;
47  end.v_dot.x() = 2.0;
48  end.w_dot.x() = 2.0;
49  double end_time = 5.0;
50 
51  CartesianTrajectorySegment seg{ start_time, start, end_time, end };
52 
53  // Sampling beyond the time boundaries should yield the boundary states with
54  // zero velocities and zero accelerations.
55 
56  CartesianState sample_lower;
57  seg.sample(-1.0, sample_lower);
58 
59  EXPECT_DOUBLE_EQ(start.p.x(), sample_lower.p.x());
60  EXPECT_DOUBLE_EQ(0, sample_lower.v.x());
61  EXPECT_DOUBLE_EQ(0, sample_lower.w.x());
62  EXPECT_DOUBLE_EQ(0, sample_lower.v_dot.x());
63  EXPECT_DOUBLE_EQ(0, sample_lower.w_dot.x());
64 
65  CartesianState sample_upper;
66  seg.sample(6.0, sample_lower);
67 
68  EXPECT_DOUBLE_EQ(end.p.x(), sample_lower.p.x());
69  EXPECT_DOUBLE_EQ(0, sample_lower.v.x());
70  EXPECT_DOUBLE_EQ(0, sample_lower.w.x());
71  EXPECT_DOUBLE_EQ(0, sample_lower.v_dot.x());
72  EXPECT_DOUBLE_EQ(0, sample_lower.w_dot.x());
73 }
74 
75 TEST(TestCartesianTrajectorySegment, DoubleConversionIsIdentity)
76 {
77  //--------------------------------------------------------------------------------
78  // Cartesian -> Spline -> Cartesian
79  //--------------------------------------------------------------------------------
81 
82  c.v.x() = 1.1;
83  c.v.y() = 1.2;
84  c.v.z() = 1.3;
85 
86  c.w.x() = 2.1;
87  c.w.y() = 2.2;
88  c.w.z() = 2.3;
89 
90  c.v_dot.x() = 3.1;
91  c.v_dot.y() = 3.2;
92  c.v_dot.z() = 3.3;
93 
94  c.w_dot.x() = 4.1;
95  c.w_dot.y() = 4.2;
96  c.w_dot.z() = 4.3;
97 
98  std::stringstream before;
99  std::stringstream after;
100  before << c;
101  after << convert(convert(c));
102 
103  // Compact check if both `read` the same.
104  EXPECT_EQ(before.str(), after.str());
105 
106  // The non-initialized case
108  before.clear();
109  after.clear();
110  before << d;
111  after << convert(convert(d));
112  EXPECT_EQ(before.str(), after.str());
113 }
114 
115 TEST(TestCartesianTrajectorySegment, NansYieldEmptySplineVelocities)
116 {
117  CartesianState c;
118  c.p.x() = 1.0;
119  c.p.y() = 2.0;
120  c.p.z() = 3.0;
121  c.q.w() = 4.0;
122  c.q.x() = 5.0;
123  c.q.y() = 6.0;
124  c.q.z() = 7.0;
125 
126  c.v.x() = std::nan("0");
127 
129  s.position.push_back(1.0);
130  s.position.push_back(2.0);
131  s.position.push_back(3.0);
132  s.position.push_back(4.0);
133  s.position.push_back(5.0);
134  s.position.push_back(6.0);
135  s.position.push_back(7.0);
136  std::stringstream expected;
137  expected << s;
138 
139  s = convert(c);
140  std::stringstream actual;
141  actual << s;
142  EXPECT_EQ(expected.str(), actual.str());
143 }
144 
145 TEST(TestCartesianTrajectorySegment, ConvertToSplineState)
146 {
147  CartesianState cartesian_state;
148  // Position
149  cartesian_state.p.x() = 0.1;
150  cartesian_state.p.y() = 0.2;
151  cartesian_state.p.z() = 0.3;
152  cartesian_state.q.w() = 0.0;
153  cartesian_state.q.x() = -0.707107;
154  cartesian_state.q.y() = -0.707107;
155  cartesian_state.q.z() = 0.0;
156  // Velocity
157  cartesian_state.v[0] = 0.1;
158  cartesian_state.v[1] = 0.1;
159  cartesian_state.v[2] = 0.1;
160  cartesian_state.w[0] = 0.1;
161  cartesian_state.w[1] = 0.1;
162  cartesian_state.w[2] = 0.1;
163  // Acceleration
164  cartesian_state.v_dot[0] = 0.1;
165  cartesian_state.v_dot[1] = 0.1;
166  cartesian_state.v_dot[2] = 0.1;
167  cartesian_state.w_dot[0] = 0.1;
168  cartesian_state.w_dot[1] = 0.1;
169  cartesian_state.w_dot[2] = 0.1;
170 
171  CartesianTrajectorySegment::SplineState expected_spline_state;
172  // Position
173  expected_spline_state.position.push_back(0.1);
174  expected_spline_state.position.push_back(0.2);
175  expected_spline_state.position.push_back(0.3);
176  expected_spline_state.position.push_back(0.0);
177  expected_spline_state.position.push_back(-0.707107);
178  expected_spline_state.position.push_back(-0.707107);
179  expected_spline_state.position.push_back(0.0);
180  // Velocity
181  expected_spline_state.velocity.push_back(0.1);
182  expected_spline_state.velocity.push_back(0.1);
183  expected_spline_state.velocity.push_back(-0.0999999);
184  expected_spline_state.velocity.push_back(0.0707107);
185  expected_spline_state.velocity.push_back(0.0353553);
186  expected_spline_state.velocity.push_back(-0.0353553);
187  expected_spline_state.velocity.push_back(0.0);
188  // Acceleration
189  expected_spline_state.acceleration.push_back(0.1);
190  expected_spline_state.acceleration.push_back(0.1);
191  expected_spline_state.acceleration.push_back(-0.0999999);
192  expected_spline_state.acceleration.push_back(0.0707107);
193  expected_spline_state.acceleration.push_back(0.0406586);
194  expected_spline_state.acceleration.push_back(-0.030052);
195  expected_spline_state.acceleration.push_back(0.0);
196 
197  std::stringstream expected;
198  expected << expected_spline_state;
199 
200  CartesianTrajectorySegment::SplineState actual_spline_state = convert(cartesian_state);
201  std::stringstream actual;
202  actual << actual_spline_state;
203 
204  EXPECT_EQ(expected.str(), actual.str());
205 }
206 
207 TEST(TestCartesianTrajectorySegment, ConvertToCartesianState)
208 {
210  // Position
211  spline_state.position.push_back(0.1);
212  spline_state.position.push_back(0.2);
213  spline_state.position.push_back(0.3);
214  spline_state.position.push_back(0.0);
215  spline_state.position.push_back(-0.707107);
216  spline_state.position.push_back(-0.707107);
217  spline_state.position.push_back(0.0);
218  // Velocity
219  spline_state.velocity.push_back(0.1);
220  spline_state.velocity.push_back(0.1);
221  spline_state.velocity.push_back(0.1);
222  spline_state.velocity.push_back(0);
223  spline_state.velocity.push_back(0.05);
224  spline_state.velocity.push_back(0.05);
225  spline_state.velocity.push_back(0.05);
226  // Acceleration
227  spline_state.acceleration.push_back(0.1);
228  spline_state.acceleration.push_back(0.1);
229  spline_state.acceleration.push_back(0.1);
230  spline_state.acceleration.push_back(-0.0075);
231  spline_state.acceleration.push_back(0.05);
232  spline_state.acceleration.push_back(0.05);
233  spline_state.acceleration.push_back(0.05);
234 
235  CartesianState expected_cartesian_state;
236  // Position
237  expected_cartesian_state.p.x() = 0.1;
238  expected_cartesian_state.p.y() = 0.2;
239  expected_cartesian_state.p.z() = 0.3;
240  expected_cartesian_state.q.w() = 0;
241  expected_cartesian_state.q.x() = -0.707107;
242  expected_cartesian_state.q.y() = -0.707107;
243  expected_cartesian_state.q.z() = 0.0;
244  // Velocity
245  expected_cartesian_state.v[0] = 0.1;
246  expected_cartesian_state.v[1] = 0.1;
247  expected_cartesian_state.v[2] = -0.1;
248  expected_cartesian_state.w[0] = -0.0707107;
249  expected_cartesian_state.w[1] = 0.0707107;
250  expected_cartesian_state.w[2] = 0.0;
251  // Acceleration
252  expected_cartesian_state.v_dot[0] = 0.1;
253  expected_cartesian_state.v_dot[1] = 0.1;
254  expected_cartesian_state.v_dot[2] = -0.1;
255  expected_cartesian_state.w_dot[0] = -0.0913173;
256  expected_cartesian_state.w_dot[1] = 0.0701041;
257  expected_cartesian_state.w_dot[2] = 0.0;
258 
259  std::stringstream expected;
260  expected << expected_cartesian_state;
261 
262  CartesianState actual_cartesian_state = convert(spline_state);
263  std::stringstream actual;
264  actual << actual_cartesian_state;
265 
266  EXPECT_EQ(expected.str(), actual.str());
267 }
268 
269 TEST(TestCartesianTrajectorySegment, interpolationOfOrientation)
270 {
271  // This will test that the orientation is interpolated correctly. The trajectory is based on a sine wave, such that
272  // the first and second derivatives are known. The sine wave will produce an angle that is rotated around the z-axis
273  // of an "artificial" robot's TCP. This orientation is then rotated to the base of the "artificial" robot. This will
274  // make sure that we catch that the interpolation of the orientation is done correctly.
275 
276  // Convenience method
277  auto compute_cartesian_state = [](auto& cartesian_state, const auto& time) {
278  double omega = 0.2;
279  double angle = sin(omega * time);
280 
281  // Rotation around the "artificial" robot's TCP z-axis
282  Eigen::Matrix3d rot_z = Eigen::Matrix3d::Zero();
283  rot_z(0, 0) = cos(angle);
284  rot_z(0, 1) = -sin(angle);
285  rot_z(1, 0) = sin(angle);
286  rot_z(1, 1) = cos(angle);
287  rot_z(2, 2) = 1;
288 
289  // Rotate the z-axis rotation to the base of the "artificial" robot
290  Eigen::Matrix3d rot_base = Eigen::Matrix3d::Zero();
291  rot_base(0, 1) = 1.0;
292  rot_base(1, 0) = 1.0;
293  rot_base(2, 2) = -1.0;
294  rot_z = rot_base * rot_z;
295 
296  // Create cartesian state
297  Eigen::Quaterniond q(rot_z);
298 
299  cartesian_state.p.x() = 0.0;
300  cartesian_state.p.y() = 0.0;
301  cartesian_state.p.z() = 0.0;
302 
303  cartesian_state.q.w() = q.w();
304  cartesian_state.q.x() = q.x();
305  cartesian_state.q.y() = q.y();
306  cartesian_state.q.z() = q.z();
307 
308  cartesian_state.v[0] = 0.0;
309  cartesian_state.v[1] = 0.0;
310  cartesian_state.v[2] = 0.0;
311 
312  cartesian_state.w[0] = 0.0;
313  cartesian_state.w[1] = 0.0;
314  cartesian_state.w[2] = omega * cos(omega * time);
315  // Rotate the velocity to the base of the "artificial" robot
316  cartesian_state.w = rot_base * cartesian_state.w;
317 
318  cartesian_state.v_dot[0] = 0.0;
319  cartesian_state.v_dot[0] = 0.0;
320  cartesian_state.v_dot[0] = 0.0;
321 
322  cartesian_state.w_dot[0] = 0.0;
323  cartesian_state.w_dot[1] = 0.0;
324  cartesian_state.w_dot[2] = (-omega * omega) * sin(omega * time);
325  // Rotate the acceleration to the base of the "artificial" robot
326  cartesian_state.w_dot = rot_base * cartesian_state.w_dot;
327  };
328 
329  double start_time = 0.0;
330  double end_time = 1.0;
331 
332  // Setup states
333  CartesianState start_state;
334  compute_cartesian_state(start_state, start_time);
335 
336  CartesianState end_state;
337  compute_cartesian_state(end_state, end_time);
338 
339  // Create segment
340  CartesianTrajectorySegment segment{ start_time, start_state, end_time, end_state };
341 
342  CartesianState sampled_state;
343  segment.sample(0.3, sampled_state);
344 
345  CartesianState expected_state;
346  compute_cartesian_state(expected_state, 0.3);
347 
348  // Orientation
349  double eps = 1e-3;
350  EXPECT_NEAR(expected_state.q.x(), sampled_state.q.x(), eps);
351  EXPECT_NEAR(expected_state.q.y(), sampled_state.q.y(), eps);
352  EXPECT_NEAR(expected_state.q.z(), sampled_state.q.z(), eps);
353  EXPECT_NEAR(expected_state.q.w(), sampled_state.q.w(), eps);
354 
355  // Velocity
356  EXPECT_NEAR(expected_state.w[0], sampled_state.w[0], eps);
357  EXPECT_NEAR(expected_state.w[1], sampled_state.w[1], eps);
358  EXPECT_NEAR(expected_state.w[2], sampled_state.w[2], eps);
359 
360  // Acceleration
361  EXPECT_NEAR(expected_state.w_dot[0], sampled_state.w_dot[0], eps);
362  EXPECT_NEAR(expected_state.w_dot[1], sampled_state.w_dot[1], eps);
363  EXPECT_NEAR(expected_state.w_dot[2], sampled_state.w_dot[2], eps);
364 }
365 
366 int main(int argc, char** argv)
367 {
368  testing::InitGoogleTest(&argc, argv);
369  return RUN_ALL_TESTS();
370 }
main
int main(int argc, char **argv)
Definition: cartesian_trajectory_segment_test.cpp:366
ros_controllers_cartesian
Definition: cartesian_state.h:29
s
XmlRpcServer s
ros_controllers_cartesian::CartesianState::v
Eigen::Vector3d v
linear velocity,
Definition: cartesian_state.h:101
cartesian_trajectory_segment.h
ros_controllers_cartesian::CartesianState::v_dot
Eigen::Vector3d v_dot
linear acceleration,
Definition: cartesian_state.h:105
trajectory_interface::PosVelAccState::position
std::vector< Scalar > position
ros_controllers_cartesian::CartesianState::q
Eigen::Quaterniond q
rotation
Definition: cartesian_state.h:98
ros_controllers_cartesian::CartesianState::w_dot
Eigen::Vector3d w_dot
angular acceleration,
Definition: cartesian_state.h:106
ros_controllers_cartesian::CartesianState
Cartesian state with pose, velocity and acceleration.
Definition: cartesian_state.h:38
trajectory_interface::PosVelAccState::velocity
std::vector< Scalar > velocity
ros_controllers_cartesian::convert
CartesianTrajectorySegment::SplineState convert(const CartesianState &state)
Convert a CartesianState into a ros_controllers_cartesian::SplineState.
Definition: cartesian_trajectory_segment.cpp:67
d
d
ros_controllers_cartesian::CartesianState::p
Eigen::Vector3d p
position
Definition: cartesian_state.h:97
ros_controllers_cartesian::CartesianState::w
Eigen::Vector3d w
angular velocity,
Definition: cartesian_state.h:102
start
ROSCPP_DECL void start()
ros_controllers_cartesian::CartesianTrajectorySegment
Cartesian segment between two trajectory waypoints.
Definition: cartesian_trajectory_segment.h:63
trajectory_interface::PosVelAccState
TEST
TEST(TestCartesianTrajectorySegment, SamplingBeyondBoundariesIsSafe)
Definition: cartesian_trajectory_segment_test.cpp:33
trajectory_interface::PosVelAccState::acceleration
std::vector< Scalar > acceleration
angle
TF2SIMD_FORCE_INLINE tf2Scalar angle(const Quaternion &q1, const Quaternion &q2)


cartesian_trajectory_interpolation
Author(s):
autogenerated on Tue Oct 15 2024 02:09:14