moveit2
The MoveIt Motion Planning Framework for ROS 2.
test_utils.hpp
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 #pragma once
36 
37 #include <gtest/gtest.h>
38 #ifndef INSTANTIATE_TEST_SUITE_P // prior to gtest 1.10
39 #define INSTANTIATE_TEST_SUITE_P(...) INSTANTIATE_TEST_CASE_P(__VA_ARGS__)
40 #endif
41 #ifndef TYPED_TEST_SUITE // prior to gtest 1.10
42 #define TYPED_TEST_SUITE(...) TYPED_TEST_CASE(__VA_ARGS__)
43 #endif
44 
45 #include <moveit_msgs/msg/motion_sequence_request.hpp>
50 #include <boost/core/demangle.hpp>
51 #include <math.h>
55 #include <moveit_msgs/msg/constraints.hpp>
56 #include <moveit_msgs/action/move_group.hpp>
57 #include <sensor_msgs/msg/joint_state.hpp>
58 #include <string>
59 // TODO: Remove conditional include swhen released to all active distros.
60 #if __has_include(<tf2/LinearMath/Quaternion.hpp>)
61 #include <tf2/LinearMath/Quaternion.hpp>
62 #else
63 #include <tf2/LinearMath/Quaternion.h>
64 #endif
65 #if __has_include(<tf2/convert.hpp>)
66 #include <tf2/convert.hpp>
67 #else
68 #include <tf2/convert.h>
69 #endif
70 #include <tf2_geometry_msgs/tf2_geometry_msgs.hpp>
71 #include <utility>
72 
73 namespace testutils
74 {
75 const std::string JOINT_NAME_PREFIX("prbt_joint_");
76 
77 static constexpr int32_t DEFAULT_SERVICE_TIMEOUT(10);
78 static constexpr double DEFAULT_ACCELERATION_EQUALITY_TOLERANCE{ 1e-6 };
79 static constexpr double DEFAULT_ROTATION_AXIS_EQUALITY_TOLERANCE{ 1e-8 };
80 
84 static inline constexpr double deg2Rad(double angle)
85 {
86  return (angle / 180.0) * M_PI;
87 }
88 
89 inline std::string getJointName(size_t joint_number, const std::string& joint_prefix)
90 {
91  return joint_prefix + std::to_string(joint_number);
92 }
93 
98 pilz_industrial_motion_planner::JointLimitsContainer createFakeLimits(const std::vector<std::string>& joint_names);
99 
100 inline std::string demangle(const char* name)
101 {
102  return boost::core::demangle(name);
103 }
104 
105 //********************************************
106 // Motion plan requests
107 //********************************************
108 
109 inline sensor_msgs::msg::JointState generateJointState(const std::vector<double>& pos, const std::vector<double>& vel,
110  const std::string& joint_prefix = testutils::JOINT_NAME_PREFIX)
111 {
112  sensor_msgs::msg::JointState state;
113  auto posit = pos.cbegin();
114  size_t i = 0;
115 
116  while (posit != pos.cend())
117  {
118  state.name.push_back(testutils::getJointName(i + 1, joint_prefix));
119  state.position.push_back(*posit);
120 
121  i++;
122  posit++;
123  }
124  for (const auto& one_vel : vel)
125  {
126  state.velocity.push_back(one_vel);
127  }
128  return state;
129 }
130 
131 inline sensor_msgs::msg::JointState generateJointState(const std::vector<double>& pos,
132  const std::string& joint_prefix = testutils::JOINT_NAME_PREFIX)
133 {
134  return generateJointState(pos, std::vector<double>(), joint_prefix);
135 }
136 
137 inline moveit_msgs::msg::Constraints
138 generateJointConstraint(const std::vector<double>& pos_list,
139  const std::string& joint_prefix = testutils::JOINT_NAME_PREFIX)
140 {
141  moveit_msgs::msg::Constraints gc;
142 
143  auto pos_it = pos_list.begin();
144 
145  for (size_t i = 0; i < pos_list.size(); ++i)
146  {
147  moveit_msgs::msg::JointConstraint jc;
148  jc.joint_name = testutils::getJointName(i + 1, joint_prefix);
149  jc.position = *pos_it;
150  gc.joint_constraints.push_back(jc);
151 
152  ++pos_it;
153  }
154 
155  return gc;
156 }
157 
162 bool getExpectedGoalPose(const moveit::core::RobotModelConstPtr& robot_model,
163  const planning_interface::MotionPlanRequest& req, std::string& link_name,
164  Eigen::Isometry3d& goal_pose_expect);
165 
173 void createDummyRequest(const moveit::core::RobotModelConstPtr& robot_model, const std::string& planning_group,
175 
176 void createPTPRequest(const std::string& planning_group, const moveit::core::RobotState& start_state,
178 
188 bool isGoalReached(const trajectory_msgs::msg::JointTrajectory& trajectory,
189  const std::vector<moveit_msgs::msg::JointConstraint>& goal, const double joint_position_tolerance,
190  const double joint_velocity_tolerance = 1.0e-6);
191 
202 bool isGoalReached(const moveit::core::RobotModelConstPtr& robot_model,
203  const trajectory_msgs::msg::JointTrajectory& trajectory,
204  const planning_interface::MotionPlanRequest& req, const double pos_tolerance,
205  const double orientation_tolerance);
206 
207 bool isGoalReached(const moveit::core::RobotModelConstPtr& robot_model,
208  const trajectory_msgs::msg::JointTrajectory& trajectory,
209  const planning_interface::MotionPlanRequest& req, const double tolerance);
210 
214 bool checkCartesianLinearity(const moveit::core::RobotModelConstPtr& robot_model,
215  const trajectory_msgs::msg::JointTrajectory& trajectory,
216  const planning_interface::MotionPlanRequest& req, const double translation_norm_tolerance,
217  const double rot_axis_norm_tolerance, const double rot_angle_tolerance = 10e-5);
218 
228 bool checkSLERP(const Eigen::Isometry3d& start_pose, const Eigen::Isometry3d& goal_pose,
229  const Eigen::Isometry3d& wp_pose, const double rot_axis_norm_tolerance,
230  const double rot_angle_tolerance = 10e-5);
231 
238 inline int getWayPointIndex(const robot_trajectory::RobotTrajectoryPtr& trajectory, const double time_from_start)
239 {
240  int index_before, index_after;
241  double blend;
242  trajectory->findWayPointIndicesForDurationAfterStart(time_from_start, index_before, index_after, blend);
243  return blend > 0.5 ? index_after : index_before;
244 }
245 
253 bool checkJointTrajectory(const trajectory_msgs::msg::JointTrajectory& trajectory,
255 
265 ::testing::AssertionResult hasStrictlyIncreasingTime(const robot_trajectory::RobotTrajectoryPtr& trajectory);
266 
273 bool isTrajectoryConsistent(const trajectory_msgs::msg::JointTrajectory& trajectory);
274 
281 bool isPositionBounded(const trajectory_msgs::msg::JointTrajectory& trajectory,
283 
290 bool isVelocityBounded(const trajectory_msgs::msg::JointTrajectory& trajectory,
292 
299 bool isAccelerationBounded(const trajectory_msgs::msg::JointTrajectory& trajectory,
301 
311 bool toTCPPose(const moveit::core::RobotModelConstPtr& robot_model, const std::string& link_name,
312  const std::vector<double>& joint_values, geometry_msgs::msg::Pose& pose,
313  const std::string& joint_prefix = testutils::JOINT_NAME_PREFIX);
314 
323 bool computeLinkFK(const moveit::core::RobotModelConstPtr& robot_model, const std::string& link_name,
324  const std::map<std::string, double>& joint_state, Eigen::Isometry3d& pose);
325 
336  const double time_tolerance);
337 
346  double joint_velocity_tolerance, double joint_accleration_tolerance);
347 
351 
356 bool checkThatPointsInRadius(const std::string& link_name, double r, Eigen::Isometry3d& circ_pose,
358 
367 void computeCartVelocity(const Eigen::Isometry3d& pose_1, const Eigen::Isometry3d& pose_2, double duration,
369 
379 void getLinLinPosesWithoutOriChange(const std::string& frame_id, sensor_msgs::msg::JointState& initialJointState,
380  geometry_msgs::msg::PoseStamped& p1, geometry_msgs::msg::PoseStamped& p2);
381 
382 void getOriChange(Eigen::Matrix3d& ori1, Eigen::Matrix3d& ori2);
383 
384 void createFakeCartTraj(const robot_trajectory::RobotTrajectoryPtr& traj, const std::string& link_name,
385  moveit_msgs::msg::RobotTrajectory& fake_traj);
386 
387 inline geometry_msgs::msg::Quaternion fromEuler(double a, double b, double c)
388 {
389  tf2::Vector3 qvz(0., 0., 1.);
390  tf2::Vector3 qvy(0., 1., 0.);
391  tf2::Quaternion q1(qvz, a);
392 
393  q1 = q1 * tf2::Quaternion(qvy, b);
394  q1 = q1 * tf2::Quaternion(qvz, c);
395 
396  return tf2::toMsg(q1);
397 }
398 
404 {
405  std::vector<double> start_position;
406  std::vector<double> mid_position;
407  std::vector<double> end_position;
408 };
409 
415 bool getBlendTestData(const rclcpp::Node::SharedPtr& node, const size_t& dataset_num, const std::string& name_prefix,
416  std::vector<BlendTestData>& datasets);
417 
428  const pilz_industrial_motion_planner::LimitsContainer& limits, double joint_velocity_tolerance,
429  double joint_acceleration_tolerance, double cartesian_velocity_tolerance,
430  double cartesian_angular_velocity_tolerance);
431 
443 bool generateTrajFromBlendTestData(const planning_scene::PlanningSceneConstPtr& scene,
444  const std::shared_ptr<pilz_industrial_motion_planner::TrajectoryGenerator>& tg,
445  const std::string& group_name, const std::string& link_name,
446  const BlendTestData& data, double sampling_time_1, double sampling_time_2,
448  planning_interface::MotionPlanResponse& res_lin_2, double& dis_lin_1,
449  double& dis_lin_2);
450 
451 void generateRequestMsgFromBlendTestData(const moveit::core::RobotModelConstPtr& robot_model, const BlendTestData& data,
452  const std::string& planner_id, const std::string& group_name,
453  const std::string& link_name,
454  moveit_msgs::msg::MotionSequenceRequest& req_list);
455 
456 void checkRobotModel(const moveit::core::RobotModelConstPtr& robot_model, const std::string& group_name,
457  const std::string& link_name);
458 
463 ::testing::AssertionResult hasTrapezoidVelocity(std::vector<double> accelerations, const double acc_tol);
464 
470 ::testing::AssertionResult
471 checkCartesianTranslationalPath(const robot_trajectory::RobotTrajectoryConstPtr& trajectory,
472  const std::string& link_name,
473  const double acc_tol = DEFAULT_ACCELERATION_EQUALITY_TOLERANCE);
474 
481 ::testing::AssertionResult
482 checkCartesianRotationalPath(const robot_trajectory::RobotTrajectoryConstPtr& trajectory, const std::string& link_name,
483  const double rot_axis_tol = DEFAULT_ROTATION_AXIS_EQUALITY_TOLERANCE,
484  const double acc_tol = DEFAULT_ACCELERATION_EQUALITY_TOLERANCE);
485 
486 inline bool isMonotonouslyDecreasing(const std::vector<double>& vec, double tol)
487 {
488  return std::is_sorted(vec.begin(), vec.end(), [tol](double a, double b) {
489  return std::abs(a - b) >= tol && a >= b; // true -> a is ordered before b -> list is not sorted
490  });
491 }
492 
493 } // namespace testutils
Representation of a robot's state. This includes position, velocity, acceleration and effort.
Definition: robot_state.hpp:90
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.
Vec3fX< details::Vec3Data< double > > Vector3d
Definition: fcl_compat.hpp:89
moveit_msgs::msg::MotionPlanRequest MotionPlanRequest
name
Definition: setup.py:7
bool checkBlendingCartSpaceContinuity(const pilz_industrial_motion_planner::TrajectoryBlendRequest &req, const pilz_industrial_motion_planner::TrajectoryBlendResponse &res, const pilz_industrial_motion_planner::LimitsContainer &planner_limits)
Definition: test_utils.cpp:775
std::string demangle(const char *name)
Definition: test_utils.hpp:100
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 verified.
Definition: test_utils.cpp:118
bool computeLinkFK(const moveit::core::RobotModelConstPtr &robot_model, const std::string &link_name, const std::map< std::string, double > &joint_state, Eigen::Isometry3d &pose)
computeLinkFK
Definition: test_utils.cpp:321
sensor_msgs::msg::JointState generateJointState(const std::vector< double > &pos, const std::vector< double > &vel, const std::string &joint_prefix=testutils::JOINT_NAME_PREFIX)
Definition: test_utils.hpp:109
::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 isVelocityBounded(const trajectory_msgs::msg::JointTrajectory &trajectory, const pilz_industrial_motion_planner::JointLimitsContainer &joint_limits)
is Velocity Bounded
Definition: test_utils.cpp:353
void createDummyRequest(const moveit::core::RobotModelConstPtr &robot_model, const std::string &planning_group, planning_interface::MotionPlanRequest &req)
create a dummy motion plan request with zero start state No goal constraint is given.
Definition: test_utils.cpp:504
int getWayPointIndex(const robot_trajectory::RobotTrajectoryPtr &trajectory, const double time_from_start)
get the waypoint index from time from start
Definition: test_utils.hpp:238
bool getExpectedGoalPose(const moveit::core::RobotModelConstPtr &robot_model, const planning_interface::MotionPlanRequest &req, std::string &link_name, Eigen::Isometry3d &goal_pose_expect)
Determines the goal position from the given request. TRUE if successful, FALSE otherwise.
Definition: test_utils.cpp:71
bool isAccelerationBounded(const trajectory_msgs::msg::JointTrajectory &trajectory, const pilz_industrial_motion_planner::JointLimitsContainer &joint_limits)
is Acceleration Bounded
Definition: test_utils.cpp:393
bool checkThatPointsInRadius(const std::string &link_name, double r, Eigen::Isometry3d &circ_pose, const pilz_industrial_motion_planner::TrajectoryBlendResponse &res)
Checks if all points of the blending trajectory lie within the blending radius.
Definition: test_utils.cpp:929
void generateRequestMsgFromBlendTestData(const moveit::core::RobotModelConstPtr &robot_model, const BlendTestData &data, const std::string &planner_id, const std::string &group_name, const std::string &link_name, moveit_msgs::msg::MotionSequenceRequest &req_list)
bool isMonotonouslyDecreasing(const std::vector< double > &vec, double tol)
Definition: test_utils.hpp:486
bool isTrajectoryConsistent(const trajectory_msgs::msg::JointTrajectory &trajectory)
check if the sizes of the joint position/veloicty/acceleration are correct
Definition: test_utils.cpp:376
void createFakeCartTraj(const robot_trajectory::RobotTrajectoryPtr &traj, const std::string &link_name, moveit_msgs::msg::RobotTrajectory &fake_traj)
Definition: test_utils.cpp:990
moveit_msgs::msg::Constraints generateJointConstraint(const std::vector< double > &pos_list, const std::string &joint_prefix=testutils::JOINT_NAME_PREFIX)
Definition: test_utils.hpp:138
bool checkBlendResult(const pilz_industrial_motion_planner::TrajectoryBlendRequest &blend_req, const pilz_industrial_motion_planner::TrajectoryBlendResponse &blend_res, const pilz_industrial_motion_planner::LimitsContainer &limits, double joint_velocity_tolerance, double joint_acceleration_tolerance, double cartesian_velocity_tolerance, double cartesian_angular_velocity_tolerance)
check the blending result of lin-lin
bool getBlendTestData(const rclcpp::Node::SharedPtr &node, const size_t &dataset_num, const std::string &name_prefix, std::vector< BlendTestData > &datasets)
fetch test datasets from node parameters
pilz_industrial_motion_planner::JointLimitsContainer createFakeLimits(const std::vector< std::string > &joint_names)
Create limits for tests to avoid the need to get the limits from the node parameter.
Definition: test_utils.cpp:48
bool checkSLERP(const Eigen::Isometry3d &start_pose, const Eigen::Isometry3d &goal_pose, const Eigen::Isometry3d &wp_pose, const double rot_axis_norm_tolerance, const double rot_angle_tolerance=10e-5)
check SLERP. The orientation should rotate around the same axis linearly.
Definition: test_utils.cpp:292
::testing::AssertionResult hasStrictlyIncreasingTime(const robot_trajectory::RobotTrajectoryPtr &trajectory)
Checks that every waypoint in the trajectory has a non-zero duration between itself and its predecess...
Definition: test_utils.cpp:487
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
std::string getJointName(size_t joint_number, const std::string &joint_prefix)
Definition: test_utils.hpp:89
void computeCartVelocity(const Eigen::Isometry3d &pose_1, const Eigen::Isometry3d &pose_2, double duration, Eigen::Vector3d &v, Eigen::Vector3d &w)
compute Cartesian velocity
Definition: test_utils.cpp:946
bool generateTrajFromBlendTestData(const planning_scene::PlanningSceneConstPtr &scene, const std::shared_ptr< pilz_industrial_motion_planner::TrajectoryGenerator > &tg, const std::string &group_name, const std::string &link_name, const BlendTestData &data, double sampling_time_1, double sampling_time_2, planning_interface::MotionPlanResponse &res_lin_1, planning_interface::MotionPlanResponse &res_lin_2, double &dis_lin_1, double &dis_lin_2)
generate two LIN trajectories from test data set
geometry_msgs::msg::Quaternion fromEuler(double a, double b, double c)
Definition: test_utils.hpp:387
void getOriChange(Eigen::Matrix3d &ori1, Eigen::Matrix3d &ori2)
Definition: test_utils.cpp:984
bool toTCPPose(const moveit::core::RobotModelConstPtr &robot_model, const std::string &link_name, const std::vector< double > &joint_values, geometry_msgs::msg::Pose &pose, const std::string &joint_prefix=testutils::JOINT_NAME_PREFIX)
compute the tcp pose from joint values
Definition: test_utils.cpp:531
void getLinLinPosesWithoutOriChange(const std::string &frame_id, sensor_msgs::msg::JointState &initialJointState, geometry_msgs::msg::PoseStamped &p1, geometry_msgs::msg::PoseStamped &p2)
Returns an initial joint state and two poses which can be used to perform a Lin-Lin movement.
Definition: test_utils.cpp:964
bool checkCartesianLinearity(const moveit::core::RobotModelConstPtr &robot_model, const trajectory_msgs::msg::JointTrajectory &trajectory, const planning_interface::MotionPlanRequest &req, const double translation_norm_tolerance, const double rot_axis_norm_tolerance, const double rot_angle_tolerance=10e-5)
Check that given trajectory is straight line.
Definition: test_utils.cpp:222
const std::string JOINT_NAME_PREFIX("prbt_joint_")
bool isPositionBounded(const trajectory_msgs::msg::JointTrajectory &trajectory, const pilz_industrial_motion_planner::JointLimitsContainer &joint_limits)
is Position Bounded
Definition: test_utils.cpp:435
::testing::AssertionResult hasTrapezoidVelocity(std::vector< double > accelerations, const double acc_tol)
Check that a given vector of accelerations represents a trapezoid velocity profile.
bool checkOriginalTrajectoryAfterBlending(const pilz_industrial_motion_planner::TrajectoryBlendRequest &req, const pilz_industrial_motion_planner::TrajectoryBlendResponse &res, const double time_tolerance)
checkOriginalTrajectoryAfterBlending
Definition: test_utils.cpp:561
bool checkBlendingJointSpaceContinuity(const pilz_industrial_motion_planner::TrajectoryBlendResponse &res, double joint_velocity_tolerance, double joint_accleration_tolerance)
check the blending result, if the joint space continuity is fulfilled
Definition: test_utils.cpp:671
void createPTPRequest(const std::string &planning_group, const moveit::core::RobotState &start_state, const moveit::core::RobotState &goal_state, planning_interface::MotionPlanRequest &req)
Definition: test_utils.cpp:516
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.
Test data for blending, which contains three joint position vectors of three robot state.
Definition: test_utils.hpp:404
std::vector< double > end_position
Definition: test_utils.hpp:407
std::vector< double > start_position
Definition: test_utils.hpp:405
std::vector< double > mid_position
Definition: test_utils.hpp:406