moveit2
The MoveIt Motion Planning Framework for ROS 2.
test_time_optimal_trajectory_generation.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2011, Georgia Tech Research Corporation
3  * All rights reserved.
4  *
5  * Author: Tobias Kunz <[email protected]>
6  * Date: 05/2012
7  *
8  * Humanoid Robotics Lab Georgia Institute of Technology
9  * Director: Mike Stilman http://www.golems.org
10  *
11  * Algorithm details and publications:
12  * http://www.golems.org/node/1570
13  *
14  * This file is provided under the following "BSD-style" License:
15  * Redistribution and use in source and binary forms, with or
16  * without modification, are permitted provided that the following
17  * conditions are met:
18  * * Redistributions of source code must retain the above copyright
19  * notice, this list of conditions and the following disclaimer.
20  * * Redistributions in binary form must reproduce the above
21  * copyright notice, this list of conditions and the following
22  * disclaimer in the documentation and/or other materials provided
23  * with the distribution.
24  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
25  * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
26  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
27  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
28  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
29  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
30  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
31  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
32  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
33  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
35  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36  * POSSIBILITY OF SUCH DAMAGE.
37  */
38 
39 #include <gtest/gtest.h>
42 
46 
47 TEST(time_optimal_trajectory_generation, test1)
48 {
49  Eigen::VectorXd waypoint(4);
50  std::list<Eigen::VectorXd> waypoints;
51 
52  waypoint << 1424.0, 984.999694824219, 2126.0, 0.0;
53  waypoints.push_back(waypoint);
54  waypoint << 1423.0, 985.000244140625, 2126.0, 0.0;
55  waypoints.push_back(waypoint);
56 
57  Eigen::VectorXd max_velocities(4);
58  max_velocities << 1.3, 0.67, 0.67, 0.5;
59  Eigen::VectorXd max_accelerations(4);
60  max_accelerations << 0.00249, 0.00249, 0.00249, 0.00249;
61 
62  Trajectory trajectory(Path(waypoints, 100.0), max_velocities, max_accelerations, 10.0);
63  EXPECT_TRUE(trajectory.isValid());
64  EXPECT_DOUBLE_EQ(40.080256821829849, trajectory.getDuration());
65 
66  // Test start matches
67  EXPECT_DOUBLE_EQ(1424.0, trajectory.getPosition(0.0)[0]);
68  EXPECT_DOUBLE_EQ(984.999694824219, trajectory.getPosition(0.0)[1]);
69  EXPECT_DOUBLE_EQ(2126.0, trajectory.getPosition(0.0)[2]);
70  EXPECT_DOUBLE_EQ(0.0, trajectory.getPosition(0.0)[3]);
71 
72  // Test end matches
73  EXPECT_DOUBLE_EQ(1423.0, trajectory.getPosition(trajectory.getDuration())[0]);
74  EXPECT_DOUBLE_EQ(985.000244140625, trajectory.getPosition(trajectory.getDuration())[1]);
75  EXPECT_DOUBLE_EQ(2126.0, trajectory.getPosition(trajectory.getDuration())[2]);
76  EXPECT_DOUBLE_EQ(0.0, trajectory.getPosition(trajectory.getDuration())[3]);
77 }
78 
79 TEST(time_optimal_trajectory_generation, test2)
80 {
81  Eigen::VectorXd waypoint(4);
82  std::list<Eigen::VectorXd> waypoints;
83 
84  waypoint << 1427.0, 368.0, 690.0, 90.0;
85  waypoints.push_back(waypoint);
86  waypoint << 1427.0, 368.0, 790.0, 90.0;
87  waypoints.push_back(waypoint);
88  waypoint << 952.499938964844, 433.0, 1051.0, 90.0;
89  waypoints.push_back(waypoint);
90  waypoint << 452.5, 533.0, 1051.0, 90.0;
91  waypoints.push_back(waypoint);
92  waypoint << 452.5, 533.0, 951.0, 90.0;
93  waypoints.push_back(waypoint);
94 
95  Eigen::VectorXd max_velocities(4);
96  max_velocities << 1.3, 0.67, 0.67, 0.5;
97  Eigen::VectorXd max_accelerations(4);
98  max_accelerations << 0.002, 0.002, 0.002, 0.002;
99 
100  Trajectory trajectory(Path(waypoints, 100.0), max_velocities, max_accelerations, 10.0);
101  EXPECT_TRUE(trajectory.isValid());
102  EXPECT_DOUBLE_EQ(1922.1418427445944, trajectory.getDuration());
103 
104  // Test start matches
105  EXPECT_DOUBLE_EQ(1427.0, trajectory.getPosition(0.0)[0]);
106  EXPECT_DOUBLE_EQ(368.0, trajectory.getPosition(0.0)[1]);
107  EXPECT_DOUBLE_EQ(690.0, trajectory.getPosition(0.0)[2]);
108  EXPECT_DOUBLE_EQ(90.0, trajectory.getPosition(0.0)[3]);
109 
110  // Test end matches
111  EXPECT_DOUBLE_EQ(452.5, trajectory.getPosition(trajectory.getDuration())[0]);
112  EXPECT_DOUBLE_EQ(533.0, trajectory.getPosition(trajectory.getDuration())[1]);
113  EXPECT_DOUBLE_EQ(951.0, trajectory.getPosition(trajectory.getDuration())[2]);
114  EXPECT_DOUBLE_EQ(90.0, trajectory.getPosition(trajectory.getDuration())[3]);
115 }
116 
117 TEST(time_optimal_trajectory_generation, test3)
118 {
119  Eigen::VectorXd waypoint(4);
120  std::list<Eigen::VectorXd> waypoints;
121 
122  waypoint << 1427.0, 368.0, 690.0, 90.0;
123  waypoints.push_back(waypoint);
124  waypoint << 1427.0, 368.0, 790.0, 90.0;
125  waypoints.push_back(waypoint);
126  waypoint << 952.499938964844, 433.0, 1051.0, 90.0;
127  waypoints.push_back(waypoint);
128  waypoint << 452.5, 533.0, 1051.0, 90.0;
129  waypoints.push_back(waypoint);
130  waypoint << 452.5, 533.0, 951.0, 90.0;
131  waypoints.push_back(waypoint);
132 
133  Eigen::VectorXd max_velocities(4);
134  max_velocities << 1.3, 0.67, 0.67, 0.5;
135  Eigen::VectorXd max_accelerations(4);
136  max_accelerations << 0.002, 0.002, 0.002, 0.002;
137 
138  Trajectory trajectory(Path(waypoints, 100.0), max_velocities, max_accelerations);
139  EXPECT_TRUE(trajectory.isValid());
140  EXPECT_DOUBLE_EQ(1919.5597888812974, trajectory.getDuration());
141 
142  // Test start matches
143  EXPECT_DOUBLE_EQ(1427.0, trajectory.getPosition(0.0)[0]);
144  EXPECT_DOUBLE_EQ(368.0, trajectory.getPosition(0.0)[1]);
145  EXPECT_DOUBLE_EQ(690.0, trajectory.getPosition(0.0)[2]);
146  EXPECT_DOUBLE_EQ(90.0, trajectory.getPosition(0.0)[3]);
147 
148  // Test end matches
149  EXPECT_DOUBLE_EQ(452.5, trajectory.getPosition(trajectory.getDuration())[0]);
150  EXPECT_DOUBLE_EQ(533.0, trajectory.getPosition(trajectory.getDuration())[1]);
151  EXPECT_DOUBLE_EQ(951.0, trajectory.getPosition(trajectory.getDuration())[2]);
152  EXPECT_DOUBLE_EQ(90.0, trajectory.getPosition(trajectory.getDuration())[3]);
153 }
154 
155 // Test the version of computeTimeStamps that takes custom velocity/acceleration limits
156 TEST(time_optimal_trajectory_generation, test_custom_limits)
157 {
158  constexpr auto robot_name{ "panda" };
159  constexpr auto group_name{ "panda_arm" };
160 
161  auto robot_model = moveit::core::loadTestingRobotModel(robot_name);
162  ASSERT_TRUE((bool)robot_model) << "Failed to load robot model" << robot_name;
163  auto group = robot_model->getJointModelGroup(group_name);
164  ASSERT_TRUE((bool)group) << "Failed to load joint model group " << group_name;
165  moveit::core::RobotState waypoint_state(robot_model);
166  waypoint_state.setToDefaultValues();
167 
168  const double delta_t = 0.1;
169  robot_trajectory::RobotTrajectory trajectory(robot_model, group);
170  waypoint_state.setJointGroupPositions(group, std::vector<double>{ -0.5, -3.52, 1.35, -2.51, -0.88, 0.63, 0.0 });
171  trajectory.addSuffixWayPoint(waypoint_state, delta_t);
172  waypoint_state.setJointGroupPositions(group, std::vector<double>{ -0.45, -3.2, 1.2, -2.4, -0.8, 0.6, 0.0 });
173  trajectory.addSuffixWayPoint(waypoint_state, delta_t);
174 
176  // Custom velocity & acceleration limits for some joints
177  std::unordered_map<std::string, double> vel_limits{ { "panda_joint1", 1.3 } };
178  std::unordered_map<std::string, double> accel_limits{ { "panda_joint2", 2.3 }, { "panda_joint3", 3.3 } };
179  ASSERT_TRUE(totg.computeTimeStamps(trajectory, vel_limits, accel_limits)) << "Failed to compute time stamps";
180 }
181 
182 // Test that totg algorithm doesn't give large acceleration
183 TEST(time_optimal_trajectory_generation, testLargeAccel)
184 {
185  double path_tolerance = 0.1;
186  double resample_dt = 0.1;
187  Eigen::VectorXd waypoint(6);
188  std::list<Eigen::VectorXd> waypoints;
189  Eigen::VectorXd max_velocities(6);
190  Eigen::VectorXd max_accelerations(6);
191 
192  // Waypoints
193  // clang-format off
194  waypoint << 1.6113056281076339,
195  -0.21400163389235427,
196  -1.974502599739185,
197  9.9653618690354051e-12,
198  -1.3810916877429624,
199  1.5293902838041467;
200  waypoints.push_back(waypoint);
201 
202  waypoint << 1.6088016187976597,
203  -0.21792862470933924,
204  -1.9758628799742952,
205  0.00010424017303217738,
206  -1.3835690515335755,
207  1.5279972853269816;
208  waypoints.push_back(waypoint);
209 
210  waypoint << 1.5887695443178671,
211  -0.24934455124521923,
212  -1.9867451218551782,
213  0.00093816147756670078,
214  -1.4033879618584812,
215  1.5168532975096607;
216  waypoints.push_back(waypoint);
217 
218  waypoint << 1.1647412393815282,
219  -0.91434018564402375,
220  -2.2170946337498498,
221  0.018590164397622583,
222  -1.8229041212673529,
223  1.2809632867583278;
224  waypoints.push_back(waypoint);
225 
226  // Max velocities
227  max_velocities << 0.89535390627300004,
228  0.89535390627300004,
229  0.79587013890930003,
230  0.92022484811399996,
231  0.82074108075029995,
232  1.3927727430915;
233  // Max accelerations
234  max_accelerations << 0.82673490883799994,
235  0.78539816339699997,
236  0.60883578557700002,
237  3.2074759432319997,
238  1.4398966328939999,
239  4.7292792634680003;
240  // clang-format on
241 
242  Trajectory parameterized(Path(waypoints, path_tolerance), max_velocities, max_accelerations, 0.001);
243 
244  ASSERT_TRUE(parameterized.isValid());
245 
246  size_t sample_count = std::ceil(parameterized.getDuration() / resample_dt);
247  for (size_t sample = 0; sample <= sample_count; ++sample)
248  {
249  // always sample the end of the trajectory as well
250  double t = std::min(parameterized.getDuration(), sample * resample_dt);
251  Eigen::VectorXd acceleration = parameterized.getAcceleration(t);
252 
253  ASSERT_EQ(acceleration.size(), 6);
254  for (std::size_t i = 0; i < 6; ++i)
255  EXPECT_NEAR(acceleration(i), 0.0, 100.0) << "Invalid acceleration at position " << sample_count << "\n";
256  }
257 }
258 
259 // Test parameterizing a trajectory would always produce a trajectory with output end waypoint same as the input end waypoint
260 TEST(time_optimal_trajectory_generation, testLastWaypoint)
261 {
262  constexpr auto robot_name{ "panda" };
263  constexpr auto group_name{ "hand" };
264 
265  auto robot_model = moveit::core::loadTestingRobotModel(robot_name);
266  ASSERT_TRUE((bool)robot_model) << "Failed to load robot model" << robot_name;
267  auto group = robot_model->getJointModelGroup(group_name);
268  ASSERT_TRUE((bool)group) << "Failed to load joint model group " << group_name;
269  moveit::core::RobotState waypoint_state(robot_model);
270  waypoint_state.setToDefaultValues();
271 
272  robot_trajectory::RobotTrajectory trajectory(robot_model, group);
273  auto add_waypoint = [&](const std::vector<double>& waypoint) {
274  waypoint_state.setJointGroupPositions(group, waypoint);
275  trajectory.addSuffixWayPoint(waypoint_state, 0.1);
276  };
277  add_waypoint({ 0.000000000, 0.000000000 });
278  add_waypoint({ 0.000396742, 0.000396742 });
279  add_waypoint({ 0.000793484, 0.000793484 });
280  add_waypoint({ 0.001190226, 0.001190226 });
281  add_waypoint({ 0.001586968, 0.001586968 });
282  add_waypoint({ 0.001983710, 0.001983710 });
283  add_waypoint({ 0.002380452, 0.002380452 });
284  add_waypoint({ 0.002777194, 0.002777194 });
285  add_waypoint({ 0.003173936, 0.003173936 });
286  add_waypoint({ 0.003570678, 0.003570678 });
287  add_waypoint({ 0.003967420, 0.003967420 });
288  add_waypoint({ 0.004364162, 0.004364162 });
289  add_waypoint({ 0.004760904, 0.004760904 });
290  add_waypoint({ 0.005157646, 0.005157646 });
291  add_waypoint({ 0.005554388, 0.005554388 });
292  add_waypoint({ 0.005951130, 0.005951130 });
293  add_waypoint({ 0.006347872, 0.006347872 });
294  add_waypoint({ 0.006744614, 0.006744614 });
295  add_waypoint({ 0.007141356, 0.007141356 });
296  add_waypoint({ 0.007538098, 0.007538098 });
297  add_waypoint({ 0.007934840, 0.007934840 });
298  add_waypoint({ 0.008331582, 0.008331582 });
299  add_waypoint({ 0.008728324, 0.008728324 });
300  add_waypoint({ 0.009125066, 0.009125066 });
301  add_waypoint({ 0.009521808, 0.009521808 });
302  add_waypoint({ 0.009918550, 0.009918550 });
303  add_waypoint({ 0.010315292, 0.010315292 });
304  add_waypoint({ 0.010712034, 0.010712034 });
305  add_waypoint({ 0.011108776, 0.011108776 });
306  add_waypoint({ 0.011505518, 0.011505518 });
307  add_waypoint({ 0.011902261, 0.011902261 });
308  add_waypoint({ 0.012299003, 0.012299003 });
309  add_waypoint({ 0.012695745, 0.012695745 });
310  add_waypoint({ 0.013092487, 0.013092487 });
311  add_waypoint({ 0.013489229, 0.013489229 });
312  add_waypoint({ 0.013885971, 0.013885971 });
313  add_waypoint({ 0.014282713, 0.014282713 });
314  add_waypoint({ 0.014679455, 0.014679455 });
315  add_waypoint({ 0.015076197, 0.015076197 });
316  add_waypoint({ 0.015472939, 0.015472939 });
317  add_waypoint({ 0.015869681, 0.015869681 });
318  add_waypoint({ 0.016266423, 0.016266423 });
319  add_waypoint({ 0.016663165, 0.016663165 });
320  add_waypoint({ 0.017059907, 0.017059907 });
321  add_waypoint({ 0.017456649, 0.017456649 });
322  add_waypoint({ 0.017853391, 0.017853391 });
323  add_waypoint({ 0.018250133, 0.018250133 });
324  add_waypoint({ 0.018646875, 0.018646875 });
325  add_waypoint({ 0.019043617, 0.019043617 });
326  add_waypoint({ 0.019440359, 0.019440359 });
327  add_waypoint({ 0.019837101, 0.019837101 });
328  add_waypoint({ 0.020233843, 0.020233843 });
329  add_waypoint({ 0.020630585, 0.020630585 });
330  add_waypoint({ 0.021027327, 0.021027327 });
331  add_waypoint({ 0.021424069, 0.021424069 });
332  add_waypoint({ 0.021820811, 0.021820811 });
333  add_waypoint({ 0.022217553, 0.022217553 });
334  add_waypoint({ 0.022614295, 0.022614295 });
335  add_waypoint({ 0.023011037, 0.023011037 });
336  add_waypoint({ 0.023407779, 0.023407779 });
337  add_waypoint({ 0.023804521, 0.023804521 });
338  add_waypoint({ 0.024201263, 0.024201263 });
339  add_waypoint({ 0.024598005, 0.024598005 });
340  add_waypoint({ 0.024994747, 0.024994747 });
341  add_waypoint({ 0.025391489, 0.025391489 });
342  add_waypoint({ 0.025788231, 0.025788231 });
343  add_waypoint({ 0.026184973, 0.026184973 });
344  add_waypoint({ 0.026581715, 0.026581715 });
345  add_waypoint({ 0.026978457, 0.026978457 });
346  add_waypoint({ 0.027375199, 0.027375199 });
347  add_waypoint({ 0.027771941, 0.027771941 });
348  add_waypoint({ 0.028168683, 0.028168683 });
349  add_waypoint({ 0.028565425, 0.028565425 });
350  add_waypoint({ 0.028962167, 0.028962167 });
351  add_waypoint({ 0.029358909, 0.029358909 });
352  add_waypoint({ 0.029755651, 0.029755651 });
353  add_waypoint({ 0.030152393, 0.030152393 });
354  add_waypoint({ 0.030549135, 0.030549135 });
355  add_waypoint({ 0.030945877, 0.030945877 });
356  add_waypoint({ 0.031342619, 0.031342619 });
357  add_waypoint({ 0.031739361, 0.031739361 });
358  add_waypoint({ 0.032136103, 0.032136103 });
359  add_waypoint({ 0.032532845, 0.032532845 });
360  add_waypoint({ 0.032929587, 0.032929587 });
361  add_waypoint({ 0.033326329, 0.033326329 });
362  add_waypoint({ 0.033723071, 0.033723071 });
363  add_waypoint({ 0.034119813, 0.034119813 });
364  add_waypoint({ 0.034516555, 0.034516555 });
365 
366  const std::vector<double> expected_last_waypoint = { 0.034913297, 0.034913297 };
367  add_waypoint(expected_last_waypoint);
368 
370  ASSERT_TRUE(totg.computeTimeStamps(trajectory)) << "Failed to compute time stamps";
371  const auto robot_state = trajectory.getLastWayPoint();
372  std::vector<double> actual_last_waypoint;
373  robot_state.copyJointGroupPositions(group, actual_last_waypoint);
374  EXPECT_TRUE(std::equal(actual_last_waypoint.cbegin(), actual_last_waypoint.cend(), expected_last_waypoint.cbegin(),
375  expected_last_waypoint.cend(), [](const double rhs, const double lhs) {
376  return std::abs(rhs - lhs) < std::numeric_limits<double>::epsilon();
377  }));
378 }
379 
380 TEST(time_optimal_trajectory_generation, testPluginAPI)
381 {
382  constexpr auto robot_name{ "panda" };
383  constexpr auto group_name{ "panda_arm" };
384 
385  auto robot_model = moveit::core::loadTestingRobotModel(robot_name);
386  ASSERT_TRUE((bool)robot_model) << "Failed to load robot model" << robot_name;
387  auto group = robot_model->getJointModelGroup(group_name);
388  ASSERT_TRUE((bool)group) << "Failed to load joint model group " << group_name;
389  moveit::core::RobotState waypoint_state(robot_model);
390  waypoint_state.setToDefaultValues();
391 
392  robot_trajectory::RobotTrajectory trajectory(robot_model, group);
393  waypoint_state.setJointGroupPositions(group, std::vector<double>{ -0.5, -3.52, 1.35, -2.51, -0.88, 0.63, 0.0 });
394  trajectory.addSuffixWayPoint(waypoint_state, 0.1);
395  waypoint_state.setJointGroupPositions(group, std::vector<double>{ -0.5, -3.52, 1.35, -2.51, -0.88, 0.63, 0.0 });
396  trajectory.addSuffixWayPoint(waypoint_state, 0.1);
397  waypoint_state.setJointGroupPositions(group, std::vector<double>{ 0.0, -3.5, 1.4, -1.2, -1.0, -0.2, 0.0 });
398  trajectory.addSuffixWayPoint(waypoint_state, 0.1);
399  waypoint_state.setJointGroupPositions(group, std::vector<double>{ -0.5, -3.52, 1.35, -2.51, -0.88, 0.63, 0.0 });
400  trajectory.addSuffixWayPoint(waypoint_state, 0.1);
401  waypoint_state.setJointGroupPositions(group, std::vector<double>{ 0.0, -3.5, 1.4, -1.2, -1.0, -0.2, 0.0 });
402  trajectory.addSuffixWayPoint(waypoint_state, 0.1);
403  waypoint_state.setJointGroupPositions(group, std::vector<double>{ -0.5, -3.52, 1.35, -2.51, -0.88, 0.63, 0.0 });
404  trajectory.addSuffixWayPoint(waypoint_state, 0.1);
405 
406  // Number TOTG iterations
407  constexpr size_t totg_iterations = 10;
408 
409  // Test computing the dynamics repeatedly with the same totg instance
410  moveit_msgs::msg::RobotTrajectory first_trajectory_msg_start, first_trajectory_msg_end;
411  {
412  robot_trajectory::RobotTrajectory test_trajectory(trajectory, true /* deep copy */);
413 
414  // Test if the trajectory was copied correctly
415  ASSERT_EQ(test_trajectory.getDuration(), trajectory.getDuration());
416  moveit::core::JointBoundsVector test_bounds = test_trajectory.getRobotModel()->getActiveJointModelsBounds();
417  moveit::core::JointBoundsVector original_bounds = trajectory.getRobotModel()->getActiveJointModelsBounds();
418  ASSERT_EQ(test_bounds.size(), original_bounds.size());
419  for (size_t bound_idx = 0; bound_idx < test_bounds.at(0)->size(); ++bound_idx)
420  {
421  ASSERT_EQ(test_bounds.at(0)->at(bound_idx).max_velocity_, original_bounds.at(0)->at(bound_idx).max_velocity_);
422  ASSERT_EQ(test_bounds.at(0)->at(bound_idx).min_velocity_, original_bounds.at(0)->at(bound_idx).min_velocity_);
423  ASSERT_EQ(test_bounds.at(0)->at(bound_idx).velocity_bounded_,
424  original_bounds.at(0)->at(bound_idx).velocity_bounded_);
425 
426  ASSERT_EQ(test_bounds.at(0)->at(bound_idx).max_acceleration_,
427  original_bounds.at(0)->at(bound_idx).max_acceleration_);
428  ASSERT_EQ(test_bounds.at(0)->at(bound_idx).min_acceleration_,
429  original_bounds.at(0)->at(bound_idx).min_acceleration_);
430  ASSERT_EQ(test_bounds.at(0)->at(bound_idx).acceleration_bounded_,
431  original_bounds.at(0)->at(bound_idx).acceleration_bounded_);
432  }
433  ASSERT_EQ(test_trajectory.getWayPointDurationFromPrevious(1), trajectory.getWayPointDurationFromPrevious(1));
434 
436  ASSERT_TRUE(totg.computeTimeStamps(test_trajectory)) << "Failed to compute time stamps";
437 
438  test_trajectory.getRobotTrajectoryMsg(first_trajectory_msg_start);
439 
440  // Iteratively recompute timestamps with same totg instance
441  for (size_t i = 0; i < totg_iterations; ++i)
442  {
443  bool totg_success = totg.computeTimeStamps(test_trajectory);
444  EXPECT_TRUE(totg_success) << "Failed to compute time stamps with a same TOTG instance in iteration " << i;
445  }
446 
447  test_trajectory.getRobotTrajectoryMsg(first_trajectory_msg_end);
448  }
449 
450  // Test computing the dynamics repeatedly with one TOTG instance per call
451  moveit_msgs::msg::RobotTrajectory second_trajectory_msg_start, second_trajectory_msg_end;
452  {
453  robot_trajectory::RobotTrajectory test_trajectory(trajectory, true /* deep copy */);
454 
455  {
457  ASSERT_TRUE(totg.computeTimeStamps(test_trajectory)) << "Failed to compute time stamps";
458  }
459 
460  test_trajectory.getRobotTrajectoryMsg(second_trajectory_msg_start);
461 
462  // Iteratively recompute timestamps with new totg instances
463  for (size_t i = 0; i < totg_iterations; ++i)
464  {
466  bool totg_success = totg.computeTimeStamps(test_trajectory);
467  EXPECT_TRUE(totg_success) << "Failed to compute time stamps with a new TOTG instance in iteration " << i;
468  }
469 
470  test_trajectory.getRobotTrajectoryMsg(second_trajectory_msg_end);
471  }
472 
473  // Make sure trajectories produce equal waypoints independent of TOTG instances
474  ASSERT_EQ(first_trajectory_msg_start, second_trajectory_msg_start);
475  ASSERT_EQ(first_trajectory_msg_end, second_trajectory_msg_end);
476 
477  // Iterate on the original trajectory again
478  moveit_msgs::msg::RobotTrajectory third_trajectory_msg_end;
479 
480  {
482  ASSERT_TRUE(totg.computeTimeStamps(trajectory)) << "Failed to compute time stamps";
483  }
484 
485  for (size_t i = 0; i < totg_iterations; ++i)
486  {
488  bool totg_success = totg.computeTimeStamps(trajectory);
489  ASSERT_TRUE(totg_success) << "Failed to compute timestamps on a new TOTG instance in iteration " << i;
490  }
491 
492  // Compare with previous work
493  trajectory.getRobotTrajectoryMsg(third_trajectory_msg_end);
494 
495  // Make sure trajectories produce equal waypoints independent of TOTG instances
496  ASSERT_EQ(first_trajectory_msg_end, third_trajectory_msg_end);
497 }
498 
499 TEST(time_optimal_trajectory_generation, testRelevantZeroMaxAccelerationsInvalidateTrajectory)
500 {
501  const Eigen::Vector2d max_velocity(1, 1);
502  const Path path(std::list<Eigen::VectorXd>{ Eigen::Vector2d(0, 0), Eigen::Vector2d(1, 1) });
503 
504  EXPECT_FALSE(Trajectory(path, max_velocity, /*max_acceleration=*/Eigen::Vector2d(0, 1)).isValid());
505  EXPECT_FALSE(Trajectory(path, max_velocity, /*max_acceleration=*/Eigen::Vector2d(1, 0)).isValid());
506  EXPECT_FALSE(Trajectory(path, max_velocity, /*max_acceleration=*/Eigen::Vector2d(0, 0)).isValid());
507 }
508 
509 TEST(time_optimal_trajectory_generation, testIrrelevantZeroMaxAccelerationsDontInvalidateTrajectory)
510 {
511  const Eigen::Vector2d max_velocity(1, 1);
512 
513  EXPECT_TRUE(Trajectory(Path(std::list<Eigen::VectorXd>{ Eigen::Vector2d(0, 0), Eigen::Vector2d(0, 1) }), max_velocity,
514  /*max_acceleration=*/Eigen::Vector2d(0, 1))
515  .isValid());
516  EXPECT_TRUE(Trajectory(Path(std::list<Eigen::VectorXd>{ Eigen::Vector2d(0, 0), Eigen::Vector2d(1, 0) }), max_velocity,
517  /*max_acceleration=*/Eigen::Vector2d(1, 0))
518  .isValid());
519 }
520 
521 TEST(time_optimal_trajectory_generation, testTimeStepZeroMakesTrajectoryInvalid)
522 {
523  EXPECT_FALSE(Trajectory(Path(std::list<Eigen::VectorXd>{ Eigen::Vector2d(0, 0), Eigen::Vector2d(1, 1) }),
524  /*max_velocity=*/Eigen::Vector2d(1, 1), /*max_acceleration=*/Eigen::Vector2d(1, 1),
525  /*time_step=*/0)
526  .isValid());
527 }
528 
529 int main(int argc, char** argv)
530 {
531  testing::InitGoogleTest(&argc, argv);
532  return RUN_ALL_TESTS();
533 }
Representation of a robot's state. This includes position, velocity, acceleration and effort.
Definition: robot_state.h:90
void setJointGroupPositions(const std::string &joint_group_name, const double *gstate)
Given positions for the variables that make up a group, in the order found in the group (including va...
Definition: robot_state.h:605
void copyJointGroupPositions(const std::string &joint_group_name, std::vector< double > &gstate) const
For a given group, copy the position values of the variables that make up the group into another loca...
Definition: robot_state.h:691
void setToDefaultValues()
Set all joints to their default positions. The default position is 0, or if that is not within bounds...
Maintain a sequence of waypoints and the time durations between these waypoints.
const moveit::core::RobotModelConstPtr & getRobotModel() const
void getRobotTrajectoryMsg(moveit_msgs::msg::RobotTrajectory &trajectory, const std::vector< std::string > &joint_filter=std::vector< std::string >()) const
RobotTrajectory & addSuffixWayPoint(const moveit::core::RobotState &state, double dt)
Add a point to the trajectory.
double getWayPointDurationFromPrevious(std::size_t index) const
const moveit::core::RobotState & getLastWayPoint() const
bool computeTimeStamps(robot_trajectory::RobotTrajectory &trajectory, const double max_velocity_scaling_factor=1.0, const double max_acceleration_scaling_factor=1.0) const override
Eigen::VectorXd getAcceleration(double time) const
Return the acceleration vector for a given point in time.
bool isValid() const
Call this method after constructing the object to make sure the trajectory generation succeeded witho...
Eigen::VectorXd getPosition(double time) const
Return the position/configuration vector for a given point in time.
double getDuration() const
Returns the optimal duration of the trajectory.
moveit::core::RobotModelPtr loadTestingRobotModel(const std::string &robot_name)
Loads a robot from moveit_resources.
std::vector< const JointModel::Bounds * > JointBoundsVector
int main(int argc, char **argv)
TEST(time_optimal_trajectory_generation, test1)