moveit2
The MoveIt Motion Planning Framework for ROS 2.
unittest_trajectory_generator_circ.cpp
Go to the documentation of this file.
1 /*********************************************************************
2  * Software License Agreement (BSD License)
3  *
4  * Copyright (c) 2018 Pilz GmbH & Co. KG
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 Pilz GmbH & Co. KG 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 #include <memory>
36 
37 #include <gtest/gtest.h>
38 
43 #include <tf2_eigen/tf2_eigen.hpp>
44 #include <tf2_geometry_msgs/tf2_geometry_msgs.hpp>
45 
50 #include "test_utils.h"
51 
52 #include <rclcpp/rclcpp.hpp>
53 
54 using namespace pilz_industrial_motion_planner;
56 
57 static const std::string PARAM_NAMESPACE_LIMITS = "robot_description_planning";
58 
59 class TrajectoryGeneratorCIRCTest : public testing::Test
60 {
61 protected:
66  void SetUp() override
67  {
68  rclcpp::NodeOptions node_options;
69  node_options.automatically_declare_parameters_from_overrides(true);
70  node_ = rclcpp::Node::make_shared("unittest_trajectory_generator_circ", node_options);
71 
72  // load robot model
73  rm_loader_ = std::make_unique<robot_model_loader::RobotModelLoader>(node_);
74  robot_model_ = rm_loader_->getModel();
75  ASSERT_TRUE(bool(robot_model_)) << "Failed to load robot model";
76  planning_scene_ = std::make_shared<planning_scene::PlanningScene>(robot_model_);
77 
78  // get parameters
79  ASSERT_TRUE(node_->has_parameter("testdata_file_name"));
80  node_->get_parameter<std::string>("testdata_file_name", test_data_file_name_);
81  ASSERT_TRUE(node_->has_parameter("planning_group"));
82  node_->get_parameter<std::string>("planning_group", planning_group_);
83  ASSERT_TRUE(node_->has_parameter("target_link"));
84  node_->get_parameter<std::string>("target_link", target_link_);
85  ASSERT_TRUE(node_->has_parameter("cartesian_position_tolerance"));
86  node_->get_parameter<double>("cartesian_position_tolerance", cartesian_position_tolerance_);
87  ASSERT_TRUE(node_->has_parameter("angular_acc_tolerance"));
88  node_->get_parameter<double>("angular_acc_tolerance", angular_acc_tolerance_);
89  ASSERT_TRUE(node_->has_parameter("rot_axis_norm_tolerance"));
90  node_->get_parameter<double>("rot_axis_norm_tolerance", rot_axis_norm_tolerance_);
91  ASSERT_TRUE(node_->has_parameter("acceleration_tolerance"));
92  node_->get_parameter<double>("acceleration_tolerance", acceleration_tolerance_);
93  ASSERT_TRUE(node_->has_parameter("other_tolerance"));
94  node_->get_parameter<double>("other_tolerance", other_tolerance_);
95 
96  // check robot model
97  testutils::checkRobotModel(robot_model_, planning_group_, target_link_);
98 
99  // load the test data provider
100  tdp_ = std::make_unique<pilz_industrial_motion_planner_testutils::XmlTestdataLoader>(test_data_file_name_);
101  ASSERT_NE(nullptr, tdp_) << "Failed to load test data by provider.";
102 
103  tdp_->setRobotModel(robot_model_);
104 
105  // create the limits container
108  node_, PARAM_NAMESPACE_LIMITS, robot_model_->getActiveJointModels());
109  CartesianLimit cart_limits;
110  // Cartesian limits are chose as such values to ease the manually compute the
111  // trajectory
112 
113  cart_limits.setMaxRotationalVelocity(1 * M_PI);
114  cart_limits.setMaxTranslationalAcceleration(1 * M_PI);
115  cart_limits.setMaxTranslationalDeceleration(1 * M_PI);
116  cart_limits.setMaxTranslationalVelocity(1 * M_PI);
117  planner_limits_.setJointLimits(joint_limits);
118  planner_limits_.setCartesianLimits(cart_limits);
119 
120  // initialize the LIN trajectory generator
121  circ_ = std::make_unique<TrajectoryGeneratorCIRC>(robot_model_, planner_limits_, planning_group_);
122  ASSERT_NE(nullptr, circ_) << "failed to create CIRC trajectory generator";
123  }
124 
127  {
128  moveit_msgs::msg::MotionPlanResponse res_msg;
129  res.getMessage(res_msg);
130  EXPECT_TRUE(testutils::isGoalReached(res.trajectory_->getFirstWayPointPtr()->getRobotModel(),
131  res_msg.trajectory.joint_trajectory, req, other_tolerance_));
132 
133  EXPECT_TRUE(
134  testutils::checkJointTrajectory(res_msg.trajectory.joint_trajectory, planner_limits_.getJointLimitContainer()));
135 
136  EXPECT_EQ(req.path_constraints.position_constraints.size(), 1u);
137  EXPECT_EQ(req.path_constraints.position_constraints.at(0).constraint_region.primitive_poses.size(), 1u);
138 
139  // Check that all point have the equal distance to the center
140  Eigen::Vector3d circ_center;
141  getCircCenter(req, res, circ_center);
142 
143  for (std::size_t i = 0; i < res.trajectory_->getWayPointCount(); ++i)
144  {
145  Eigen::Affine3d waypoint_pose = res.trajectory_->getWayPointPtr(i)->getFrameTransform(target_link_);
146  EXPECT_NEAR(
147  (res.trajectory_->getFirstWayPointPtr()->getFrameTransform(target_link_).translation() - circ_center).norm(),
148  (circ_center - waypoint_pose.translation()).norm(), cartesian_position_tolerance_);
149  }
150 
151  // check translational and rotational paths
152  ASSERT_TRUE(testutils::checkCartesianTranslationalPath(res.trajectory_, target_link_, acceleration_tolerance_));
153  ASSERT_TRUE(testutils::checkCartesianRotationalPath(res.trajectory_, target_link_, angular_acc_tolerance_,
154  rot_axis_norm_tolerance_));
155 
156  for (size_t idx = 0; idx < res.trajectory_->getLastWayPointPtr()->getVariableCount(); ++idx)
157  {
158  EXPECT_NEAR(0.0, res.trajectory_->getLastWayPointPtr()->getVariableVelocity(idx), other_tolerance_);
159  EXPECT_NEAR(0.0, res.trajectory_->getLastWayPointPtr()->getVariableAcceleration(idx), other_tolerance_);
160  }
161  }
162 
163  void TearDown() override
164  {
165  robot_model_.reset();
166  }
167 
170  {
171  if (req.path_constraints.name == "center")
172  {
173  tf2::fromMsg(req.path_constraints.position_constraints.at(0).constraint_region.primitive_poses.at(0).position,
174  circ_center);
175  }
176  else if (req.path_constraints.name == "interim")
177  {
178  Eigen::Vector3d interim;
179  tf2::fromMsg(req.path_constraints.position_constraints.at(0).constraint_region.primitive_poses.at(0).position,
180  interim);
181  Eigen::Vector3d start = res.trajectory_->getFirstWayPointPtr()->getFrameTransform(target_link_).translation();
182  Eigen::Vector3d goal = res.trajectory_->getLastWayPointPtr()->getFrameTransform(target_link_).translation();
183 
184  const Eigen::Vector3d t = interim - start;
185  const Eigen::Vector3d u = goal - start;
186  const Eigen::Vector3d v = goal - interim;
187 
188  const Eigen::Vector3d w = t.cross(u);
189 
190  ASSERT_GT(w.norm(), 1e-8) << "Circle center not well defined for given start, interim and goal.";
191 
192  circ_center = start + (u * t.dot(t) * u.dot(v) - t * u.dot(u) * t.dot(v)) * 0.5 / pow(w.norm(), 2);
193  }
194  }
195 
196 protected:
197  // ros stuff
198  rclcpp::Node::SharedPtr node_;
199  moveit::core::RobotModelConstPtr robot_model_;
200  std::unique_ptr<robot_model_loader::RobotModelLoader> rm_loader_;
201  planning_scene::PlanningSceneConstPtr planning_scene_;
202 
203  std::unique_ptr<TrajectoryGeneratorCIRC> circ_;
204  // test data provider
205  std::unique_ptr<pilz_industrial_motion_planner_testutils::TestdataLoader> tdp_;
206 
207  // test parameters from parameter server
208  std::string planning_group_, target_link_, test_data_file_name_;
210  double cartesian_position_tolerance_, angular_acc_tolerance_, rot_axis_norm_tolerance_, acceleration_tolerance_,
213 };
214 
219 TEST_F(TrajectoryGeneratorCIRCTest, TestExceptionErrorCodeMapping)
220 {
221  {
222  std::shared_ptr<CircleNoPlane> cnp_ex{ new CircleNoPlane("") };
223  EXPECT_EQ(cnp_ex->getErrorCode(), moveit_msgs::msg::MoveItErrorCodes::INVALID_MOTION_PLAN);
224  }
225 
226  {
227  std::shared_ptr<CircleToSmall> cts_ex{ new CircleToSmall("") };
228  EXPECT_EQ(cts_ex->getErrorCode(), moveit_msgs::msg::MoveItErrorCodes::INVALID_MOTION_PLAN);
229  }
230 
231  {
232  std::shared_ptr<CenterPointDifferentRadius> cpdr_ex{ new CenterPointDifferentRadius("") };
233  EXPECT_EQ(cpdr_ex->getErrorCode(), moveit_msgs::msg::MoveItErrorCodes::INVALID_MOTION_PLAN);
234  }
235 
236  {
237  std::shared_ptr<CircTrajectoryConversionFailure> ctcf_ex{ new CircTrajectoryConversionFailure("") };
238  EXPECT_EQ(ctcf_ex->getErrorCode(), moveit_msgs::msg::MoveItErrorCodes::INVALID_MOTION_PLAN);
239  }
240 
241  {
242  std::shared_ptr<UnknownPathConstraintName> upcn_ex{ new UnknownPathConstraintName("") };
243  EXPECT_EQ(upcn_ex->getErrorCode(), moveit_msgs::msg::MoveItErrorCodes::INVALID_MOTION_PLAN);
244  }
245 
246  {
247  std::shared_ptr<NoPositionConstraints> npc_ex{ new NoPositionConstraints("") };
248  EXPECT_EQ(npc_ex->getErrorCode(), moveit_msgs::msg::MoveItErrorCodes::INVALID_MOTION_PLAN);
249  }
250 
251  {
252  std::shared_ptr<NoPrimitivePose> npp_ex{ new NoPrimitivePose("") };
253  EXPECT_EQ(npp_ex->getErrorCode(), moveit_msgs::msg::MoveItErrorCodes::INVALID_MOTION_PLAN);
254  }
255 
256  {
257  std::shared_ptr<UnknownLinkNameOfAuxiliaryPoint> ulnoap_ex{ new UnknownLinkNameOfAuxiliaryPoint("") };
258  EXPECT_EQ(ulnoap_ex->getErrorCode(), moveit_msgs::msg::MoveItErrorCodes::INVALID_LINK_NAME);
259  }
260 
261  {
262  std::shared_ptr<NumberOfConstraintsMismatch> nocm_ex{ new NumberOfConstraintsMismatch("") };
263  EXPECT_EQ(nocm_ex->getErrorCode(), moveit_msgs::msg::MoveItErrorCodes::INVALID_GOAL_CONSTRAINTS);
264  }
265 
266  {
267  std::shared_ptr<CircInverseForGoalIncalculable> cifgi_ex{ new CircInverseForGoalIncalculable("") };
268  EXPECT_EQ(cifgi_ex->getErrorCode(), moveit_msgs::msg::MoveItErrorCodes::NO_IK_SOLUTION);
269  }
270 }
271 
276 {
277  LimitsContainer planner_limits;
278  EXPECT_THROW(TrajectoryGeneratorCIRC(this->robot_model_, planner_limits, planning_group_),
279  TrajectoryGeneratorInvalidLimitsException);
280 }
281 
285 TEST_F(TrajectoryGeneratorCIRCTest, nonZeroStartVelocity)
286 {
287  moveit_msgs::msg::MotionPlanRequest req{ tdp_->getCircJointCenterCart("circ1_center_2").toRequest() };
288 
289  // start state has non-zero velocity
290  req.start_state.joint_state.velocity.push_back(1.0);
292  EXPECT_FALSE(circ_->generate(planning_scene_, req, res));
293  EXPECT_EQ(res.error_code_.val, moveit_msgs::msg::MoveItErrorCodes::INVALID_ROBOT_STATE);
294  req.start_state.joint_state.velocity.clear();
295 }
296 
298 {
299  auto circ{ tdp_->getCircCartCenterCart("circ1_center_2") };
300 
302  EXPECT_TRUE(circ_->generate(planning_scene_, circ.toRequest(), res));
303  EXPECT_EQ(res.error_code_.val, moveit_msgs::msg::MoveItErrorCodes::SUCCESS);
304 }
305 
310 {
311  auto circ{ tdp_->getCircCartCenterCart("circ1_center_2") };
312 
313  circ.setVelocityScale(1.0);
315  EXPECT_FALSE(circ_->generate(planning_scene_, circ.toRequest(), res));
316  EXPECT_EQ(res.error_code_.val, moveit_msgs::msg::MoveItErrorCodes::PLANNING_FAILED);
317 }
318 
323 {
324  auto circ{ tdp_->getCircCartCenterCart("circ1_center_2") };
325 
326  circ.setAccelerationScale(1.0);
328  EXPECT_FALSE(circ_->generate(planning_scene_, circ.toRequest(), res));
329  EXPECT_EQ(res.error_code_.val, moveit_msgs::msg::MoveItErrorCodes::PLANNING_FAILED);
330 }
331 
336 TEST_F(TrajectoryGeneratorCIRCTest, samePointsWithCenter)
337 {
338  // Define auxiliary point and goal to be the same as the start
339  auto circ{ tdp_->getCircCartCenterCart("circ1_center_2") };
340  circ.getAuxiliaryConfiguration().getConfiguration().setPose(circ.getStartConfiguration().getPose());
341  circ.getAuxiliaryConfiguration().getConfiguration().getPose().position.x += 1e-8;
342  circ.getAuxiliaryConfiguration().getConfiguration().getPose().position.y += 1e-8;
343  circ.getAuxiliaryConfiguration().getConfiguration().getPose().position.z += 1e-8;
344  circ.getGoalConfiguration().setPose(circ.getStartConfiguration().getPose());
345  circ.getGoalConfiguration().getPose().position.x -= 1e-8;
346  circ.getGoalConfiguration().getPose().position.y -= 1e-8;
347  circ.getGoalConfiguration().getPose().position.z -= 1e-8;
348 
350  EXPECT_FALSE(circ_->generate(planning_scene_, circ.toRequest(), res));
351  EXPECT_EQ(res.error_code_.val, moveit_msgs::msg::MoveItErrorCodes::INVALID_MOTION_PLAN);
352 }
353 
359 TEST_F(TrajectoryGeneratorCIRCTest, samePointsWithInterim)
360 {
361  // Define auxiliary point and goal to be the same as the start
362  auto circ{ tdp_->getCircCartInterimCart("circ3_interim") };
363  circ.getAuxiliaryConfiguration().getConfiguration().setPose(circ.getStartConfiguration().getPose());
364  circ.getAuxiliaryConfiguration().getConfiguration().getPose().position.x += 1e-8;
365  circ.getAuxiliaryConfiguration().getConfiguration().getPose().position.y += 1e-8;
366  circ.getAuxiliaryConfiguration().getConfiguration().getPose().position.z += 1e-8;
367  circ.getGoalConfiguration().setPose(circ.getStartConfiguration().getPose());
368  circ.getGoalConfiguration().getPose().position.x -= 1e-8;
369  circ.getGoalConfiguration().getPose().position.y -= 1e-8;
370  circ.getGoalConfiguration().getPose().position.z -= 1e-8;
371 
373  EXPECT_FALSE(circ_->generate(planning_scene_, circ.toRequest(), res));
374  EXPECT_EQ(res.error_code_.val, moveit_msgs::msg::MoveItErrorCodes::INVALID_MOTION_PLAN);
375 }
376 
381 {
382  auto circ{ tdp_->getCircCartCenterCart("circ1_center_2") };
383 
384  planning_interface::MotionPlanRequest req = circ.toRequest();
385 
386  req.path_constraints.position_constraints.clear();
387 
389  EXPECT_FALSE(circ_->generate(planning_scene_, req, res));
390  EXPECT_EQ(res.error_code_.val, moveit_msgs::msg::MoveItErrorCodes::INVALID_MOTION_PLAN);
391 }
392 
397 {
398  auto circ{ tdp_->getCircCartCenterCart("circ1_center_2") };
399 
400  planning_interface::MotionPlanRequest req = circ.toRequest();
401 
402  req.path_constraints.name = "";
403 
405  EXPECT_FALSE(circ_->generate(planning_scene_, req, res));
406  EXPECT_EQ(res.error_code_.val, moveit_msgs::msg::MoveItErrorCodes::INVALID_MOTION_PLAN);
407 }
408 
414 {
415  auto circ{ tdp_->getCircJointInterimCart("circ3_interim") };
416 
417  planning_interface::MotionPlanRequest req = circ.toRequest();
418 
419  req.path_constraints.position_constraints.front().link_name = "INVALID";
420 
422  EXPECT_FALSE(circ_->generate(planning_scene_, req, res));
423  EXPECT_EQ(res.error_code_.val, moveit_msgs::msg::MoveItErrorCodes::INVALID_LINK_NAME);
424 }
425 
430 {
431  auto circ{ tdp_->getCircCartCenterCart("circ1_center_2") };
432  circ.getAuxiliaryConfiguration().getConfiguration().setPose(circ.getStartConfiguration().getPose());
433  circ.getAuxiliaryConfiguration().getConfiguration().getPose().position.y += 1;
434 
436  EXPECT_FALSE(circ_->generate(planning_scene_, circ.toRequest(), res));
437  EXPECT_EQ(res.error_code_.val, moveit_msgs::msg::MoveItErrorCodes::INVALID_MOTION_PLAN);
438 }
439 
446 {
447  auto circ{ tdp_->getCircCartCenterCart("circ1_center_2") };
448  circ.getAuxiliaryConfiguration().getConfiguration().setPose(circ.getStartConfiguration().getPose());
449  circ.getGoalConfiguration().setPose(circ.getStartConfiguration().getPose());
450 
451  // Stretch start and goal pose along line
452  circ.getStartConfiguration().getPose().position.x -= 0.1;
453  circ.getGoalConfiguration().getPose().position.x += 0.1;
454 
456  EXPECT_FALSE(circ_->generate(planning_scene_, circ.toRequest(), res));
457  EXPECT_EQ(res.error_code_.val, moveit_msgs::msg::MoveItErrorCodes::INVALID_MOTION_PLAN);
458 }
459 
467 {
468  auto circ{ tdp_->getCircCartInterimCart("circ3_interim") };
469  circ.getAuxiliaryConfiguration().getConfiguration().setPose(circ.getStartConfiguration().getPose());
470  circ.getGoalConfiguration().setPose(circ.getStartConfiguration().getPose());
471 
472  // Stretch start and goal pose along line
473  circ.getStartConfiguration().getPose().position.x -= 0.1;
474  circ.getGoalConfiguration().getPose().position.x += 0.1;
475 
477  EXPECT_FALSE(circ_->generate(planning_scene_, circ.toRequest(), res));
478  EXPECT_EQ(res.error_code_.val, moveit_msgs::msg::MoveItErrorCodes::INVALID_MOTION_PLAN);
479 }
480 
489 TEST_F(TrajectoryGeneratorCIRCTest, colinearCenterDueToInterim)
490 {
491  // get the test data from xml
492  auto circ{ tdp_->getCircCartInterimCart("circ3_interim") };
493 
495  ASSERT_TRUE(circ_->generate(planning_scene_, circ.toRequest(), res));
496  EXPECT_EQ(res.error_code_.val, moveit_msgs::msg::MoveItErrorCodes::SUCCESS);
497 }
498 
509 TEST_F(TrajectoryGeneratorCIRCTest, colinearCenterAndInterim)
510 {
511  auto circ{ tdp_->getCircCartInterimCart("circ3_interim") };
512 
513  // alter start, interim and goal such that start/center and interim are
514  // colinear
515  circ.getAuxiliaryConfiguration().getConfiguration().setPose(circ.getStartConfiguration().getPose());
516  circ.getGoalConfiguration().setPose(circ.getStartConfiguration().getPose());
517 
518  circ.getStartConfiguration().getPose().position.x -= 0.2;
519  circ.getAuxiliaryConfiguration().getConfiguration().getPose().position.x += 0.2;
520  circ.getGoalConfiguration().getPose().position.y -= 0.2;
521 
522  circ.setAccelerationScale(0.05);
523  circ.setVelocityScale(0.05);
524 
525  moveit_msgs::msg::MotionPlanRequest req = circ.toRequest();
526 
528  EXPECT_TRUE(circ_->generate(planning_scene_, req, res));
529  EXPECT_EQ(res.error_code_.val, moveit_msgs::msg::MoveItErrorCodes::SUCCESS);
530  checkCircResult(req, res);
531 }
532 
542 TEST_F(TrajectoryGeneratorCIRCTest, interimLarger180Degree)
543 {
544  auto circ{ tdp_->getCircCartInterimCart("circ3_interim") };
545 
546  // alter start, interim and goal such that start/center and interim are
547  // colinear
548  circ.getAuxiliaryConfiguration().getConfiguration().setPose(circ.getStartConfiguration().getPose());
549  circ.getGoalConfiguration().setPose(circ.getStartConfiguration().getPose());
550 
551  circ.getStartConfiguration().getPose().position.x -= 0.2;
552  circ.getAuxiliaryConfiguration().getConfiguration().getPose().position.x += 0.14142136;
553  circ.getAuxiliaryConfiguration().getConfiguration().getPose().position.y -= 0.14142136;
554  circ.getGoalConfiguration().getPose().position.y -= 0.2;
555 
556  circ.setAccelerationScale(0.05);
557  circ.setVelocityScale(0.05);
558 
559  moveit_msgs::msg::MotionPlanRequest req = circ.toRequest();
560 
562  EXPECT_TRUE(circ_->generate(planning_scene_, req, res));
563  EXPECT_EQ(res.error_code_.val, moveit_msgs::msg::MoveItErrorCodes::SUCCESS);
564  checkCircResult(req, res);
565 }
566 
570 TEST_F(TrajectoryGeneratorCIRCTest, centerPointJointGoal)
571 {
572  auto circ{ tdp_->getCircJointCenterCart("circ1_center_2") };
573  moveit_msgs::msg::MotionPlanRequest req = circ.toRequest();
574 
576  ASSERT_TRUE(circ_->generate(planning_scene_, req, res));
577  EXPECT_EQ(res.error_code_.val, moveit_msgs::msg::MoveItErrorCodes::SUCCESS);
578  checkCircResult(req, res);
579 }
580 
586 TEST_F(TrajectoryGeneratorCIRCTest, InvalidAdditionalPrimitivePose)
587 {
588  auto circ{ tdp_->getCircCartCenterCart("circ1_center_2") };
589 
590  moveit_msgs::msg::MotionPlanRequest req = circ.toRequest();
591 
592  // Contains one pose (interim / center)
593  ASSERT_EQ(req.path_constraints.position_constraints.back().constraint_region.primitive_poses.size(), 1u);
594 
595  // Define a additional pose here
596  geometry_msgs::msg::Pose center_position;
597  center_position.position.x = 0.0;
598  center_position.position.y = 0.0;
599  center_position.position.z = 0.65;
600  req.path_constraints.position_constraints.back().constraint_region.primitive_poses.push_back(center_position);
601 
603  ASSERT_FALSE(circ_->generate(planning_scene_, req, res));
604  EXPECT_EQ(res.error_code_.val, moveit_msgs::msg::MoveItErrorCodes::INVALID_MOTION_PLAN);
605 }
606 
613 TEST_F(TrajectoryGeneratorCIRCTest, InvalidExtraJointConstraint)
614 {
615  auto circ{ tdp_->getCircJointCenterCart("circ1_center_2") };
616 
617  moveit_msgs::msg::MotionPlanRequest req = circ.toRequest();
618 
619  // Define the additional joint constraint
620  moveit_msgs::msg::JointConstraint joint_constraint;
621  joint_constraint.joint_name = req.goal_constraints.front().joint_constraints.front().joint_name;
622  req.goal_constraints.front().joint_constraints.push_back(joint_constraint); //<-- Additional constraint
623 
625  EXPECT_FALSE(circ_->generate(planning_scene_, req, res));
626  EXPECT_EQ(res.error_code_.val, moveit_msgs::msg::MoveItErrorCodes::INVALID_GOAL_CONSTRAINTS);
627 }
628 
632 TEST_F(TrajectoryGeneratorCIRCTest, CenterPointPoseGoal)
633 {
634  auto circ{ tdp_->getCircCartCenterCart("circ1_center_2") };
635 
636  moveit_msgs::msg::MotionPlanRequest req = circ.toRequest();
637 
639  ASSERT_TRUE(circ_->generate(planning_scene_, req, res));
640  EXPECT_EQ(res.error_code_.val, moveit_msgs::msg::MoveItErrorCodes::SUCCESS);
641  checkCircResult(req, res);
642 }
643 
647 TEST_F(TrajectoryGeneratorCIRCTest, CenterPointPoseGoalFrameIdPositionConstraints)
648 {
649  auto circ{ tdp_->getCircCartCenterCart("circ1_center_2") };
650 
651  moveit_msgs::msg::MotionPlanRequest req = circ.toRequest();
652 
653  req.goal_constraints.front().position_constraints.front().header.frame_id = robot_model_->getModelFrame();
654 
656  ASSERT_TRUE(circ_->generate(planning_scene_, req, res));
657  EXPECT_EQ(res.error_code_.val, moveit_msgs::msg::MoveItErrorCodes::SUCCESS);
658  checkCircResult(req, res);
659 }
660 
664 TEST_F(TrajectoryGeneratorCIRCTest, CenterPointPoseGoalFrameIdOrientationConstraints)
665 {
666  auto circ{ tdp_->getCircCartCenterCart("circ1_center_2") };
667 
668  moveit_msgs::msg::MotionPlanRequest req = circ.toRequest();
669  req.goal_constraints.front().orientation_constraints.front().header.frame_id = robot_model_->getModelFrame();
670 
672  ASSERT_TRUE(circ_->generate(planning_scene_, req, res));
673  EXPECT_EQ(res.error_code_.val, moveit_msgs::msg::MoveItErrorCodes::SUCCESS);
674  checkCircResult(req, res);
675 }
676 
680 TEST_F(TrajectoryGeneratorCIRCTest, CenterPointPoseGoalFrameIdBothConstraints)
681 {
682  auto circ{ tdp_->getCircCartCenterCart("circ1_center_2") };
683 
684  moveit_msgs::msg::MotionPlanRequest req = circ.toRequest();
685 
686  // Both set
687  req.goal_constraints.front().position_constraints.front().header.frame_id = robot_model_->getModelFrame();
688  req.goal_constraints.front().orientation_constraints.front().header.frame_id = robot_model_->getModelFrame();
689 
691  ASSERT_TRUE(circ_->generate(planning_scene_, req, res));
692  EXPECT_EQ(res.error_code_.val, moveit_msgs::msg::MoveItErrorCodes::SUCCESS);
693  checkCircResult(req, res);
694 }
695 
699 TEST_F(TrajectoryGeneratorCIRCTest, InterimPointJointGoal)
700 {
701  auto circ{ tdp_->getCircJointInterimCart("circ3_interim") };
702 
703  moveit_msgs::msg::MotionPlanRequest req = circ.toRequest();
704 
706  ASSERT_TRUE(circ_->generate(planning_scene_, req, res));
707  EXPECT_EQ(res.error_code_.val, moveit_msgs::msg::MoveItErrorCodes::SUCCESS);
708  checkCircResult(req, res);
709 }
710 
717 TEST_F(TrajectoryGeneratorCIRCTest, InterimPointJointGoalStartVelNearZero)
718 {
719  auto circ{ tdp_->getCircJointInterimCart("circ3_interim") };
720 
721  moveit_msgs::msg::MotionPlanRequest req = circ.toRequest();
722 
723  // Set velocity near zero
724  req.start_state.joint_state.velocity = std::vector<double>(req.start_state.joint_state.position.size(), 1e-16);
725 
727  ASSERT_TRUE(circ_->generate(planning_scene_, req, res));
728  EXPECT_EQ(res.error_code_.val, moveit_msgs::msg::MoveItErrorCodes::SUCCESS);
729  checkCircResult(req, res);
730 }
731 
735 TEST_F(TrajectoryGeneratorCIRCTest, InterimPointPoseGoal)
736 {
737  auto circ{ tdp_->getCircJointInterimCart("circ3_interim") };
738  moveit_msgs::msg::MotionPlanRequest req = circ.toRequest();
739 
741  ASSERT_TRUE(circ_->generate(planning_scene_, req, res));
742  EXPECT_EQ(res.error_code_.val, moveit_msgs::msg::MoveItErrorCodes::SUCCESS);
743  checkCircResult(req, res);
744 }
745 
746 int main(int argc, char** argv)
747 {
748  rclcpp::init(argc, argv);
749  testing::InitGoogleTest(&argc, argv);
750  return RUN_ALL_TESTS();
751 }
void SetUp() override
Create test scenario for circ trajectory generator.
std::unique_ptr< TrajectoryGeneratorCIRC > circ_
std::unique_ptr< pilz_industrial_motion_planner_testutils::TestdataLoader > tdp_
void getCircCenter(const planning_interface::MotionPlanRequest &req, const planning_interface::MotionPlanResponse &res, Eigen::Vector3d &circ_center)
moveit::core::RobotModelConstPtr robot_model_
void checkCircResult(const planning_interface::MotionPlanRequest &req, const planning_interface::MotionPlanResponse &res)
planning_scene::PlanningSceneConstPtr planning_scene_
std::unique_ptr< robot_model_loader::RobotModelLoader > rm_loader_
Set of cartesian limits, has values for velocity, acceleration and deceleration of both the translati...
void setMaxRotationalVelocity(double max_rot_vel)
Set the maximum rotational velocity.
void setMaxTranslationalVelocity(double max_trans_vel)
Set the maximal translational velocity.
void setMaxTranslationalAcceleration(double max_trans_acc)
Set the maximum translational acceleration.
void setMaxTranslationalDeceleration(double max_trans_dec)
Set the maximum translational deceleration.
static JointLimitsContainer getAggregatedLimits(const rclcpp::Node::SharedPtr &node, const std::string &param_namespace, const std::vector< const moveit::core::JointModel * > &joint_models)
Aggregates(combines) the joint limits from joint model and node parameters. The rules for the combina...
Container for JointLimits, essentially a map with convenience functions. Adds the ability to as for l...
This class combines CartesianLimit and JointLimits into on single class.
This class implements a trajectory generator of arcs in Cartesian space. The arc is specified by a st...
Vec3fX< details::Vec3Data< double > > Vector3d
Definition: fcl_compat.h:89
w
Definition: pick.py:67
TEST_F(GetSolverTipFrameIntegrationTest, TestHasSolverManipulator)
Check if hasSolver() can be called successfully for the manipulator group.
moveit_msgs::msg::MotionPlanRequest MotionPlanRequest
bool isGoalReached(const trajectory_msgs::msg::JointTrajectory &trajectory, const std::vector< moveit_msgs::msg::JointConstraint > &goal, const double joint_position_tolerance, const double joint_velocity_tolerance=1.0e-6)
check if the goal given in joint space is reached Only the last point in the trajectory is veryfied.
Definition: test_utils.cpp:118
::testing::AssertionResult checkCartesianTranslationalPath(const robot_trajectory::RobotTrajectoryConstPtr &trajectory, const std::string &link_name, const double acc_tol=DEFAULT_ACCELERATION_EQUALITY_TOLERANCE)
Check that the translational path of a given trajectory has a trapezoid velocity profile.
bool checkJointTrajectory(const trajectory_msgs::msg::JointTrajectory &trajectory, const pilz_industrial_motion_planner::JointLimitsContainer &joint_limits)
check joint trajectory of consistency, position, velocity and acceleration limits
Definition: test_utils.cpp:460
void checkRobotModel(const moveit::core::RobotModelConstPtr &robot_model, const std::string &group_name, const std::string &link_name)
::testing::AssertionResult checkCartesianRotationalPath(const robot_trajectory::RobotTrajectoryConstPtr &trajectory, const std::string &link_name, const double rot_axis_tol=DEFAULT_ROTATION_AXIS_EQUALITY_TOLERANCE, const double acc_tol=DEFAULT_ACCELERATION_EQUALITY_TOLERANCE)
Check that the rotational path of a given trajectory is a quaternion slerp.
robot_trajectory::RobotTrajectoryPtr trajectory_
void getMessage(moveit_msgs::msg::MotionPlanResponse &msg) const
moveit_msgs::msg::MoveItErrorCodes error_code_
int main(int argc, char **argv)