38 #include <gtest/gtest.h>
47 #include <moveit_msgs/DisplayTrajectory.h>
48 #include <moveit_msgs/MotionPlanResponse.h>
50 #include <tf2_eigen/tf2_eigen.hpp>
71 static std::string createManipulatorJointName(
const size_t& joint_number)
73 return std::string(
"prbt_joint_") + std::to_string(joint_number + 1);
76 static std::string createGripperJointName(
const size_t& joint_number)
81 return "prbt_gripper_finger_left_joint";
85 throw std::runtime_error(
"Could not create gripper joint name");
91 void SetUp()
override;
95 ros::NodeHandle ph_{
"~" };
97 std::shared_ptr<pilz_industrial_motion_planner::CommandListManager>
manager_;
98 planning_scene::PlanningScenePtr
scene_;
101 std::unique_ptr<pilz_industrial_motion_planner_testutils::TestdataLoader>
data_loader_;
109 FAIL() <<
"Robot model could not be loaded.";
112 std::string test_data_file_name;
117 std::make_unique<pilz_industrial_motion_planner_testutils::XmlTestdataLoader>(test_data_file_name, robot_model_);
118 ASSERT_NE(
nullptr, data_loader_) <<
"Failed to load test data by provider.";
121 manager_ = std::make_shared<pilz_industrial_motion_planner::CommandListManager>(ph_, robot_model_);
122 scene_ = std::make_shared<planning_scene::PlanningScene>(robot_model_);
123 pipeline_ = std::make_shared<planning_pipeline::PlanningPipeline>(robot_model_, ph_);
133 std::shared_ptr<NegativeBlendRadiusException> nbr_ex{
new NegativeBlendRadiusException(
"") };
134 EXPECT_EQ(nbr_ex->getErrorCode(), moveit_msgs::msg::MoveItErrorCodes::INVALID_MOTION_PLAN);
136 std::shared_ptr<LastBlendRadiusNotZeroException> lbrnz_ex{
new LastBlendRadiusNotZeroException(
"") };
137 EXPECT_EQ(lbrnz_ex->getErrorCode(), moveit_msgs::msg::MoveItErrorCodes::INVALID_MOTION_PLAN);
139 std::shared_ptr<StartStateSetException> sss_ex{
new StartStateSetException(
"") };
140 EXPECT_EQ(sss_ex->getErrorCode(), moveit_msgs::msg::MoveItErrorCodes::INVALID_ROBOT_STATE);
142 std::shared_ptr<OverlappingBlendRadiiException> obr_ex{
new OverlappingBlendRadiiException(
"") };
143 EXPECT_EQ(obr_ex->getErrorCode(), moveit_msgs::msg::MoveItErrorCodes::INVALID_MOTION_PLAN);
145 std::shared_ptr<PlanningPipelineException> pp_ex{
new PlanningPipelineException(
"") };
146 EXPECT_EQ(pp_ex->getErrorCode(), moveit_msgs::msg::MoveItErrorCodes::FAILURE);
171 Sequence seq{ data_loader_->getSequence(
"ComplexSequence") };
172 ASSERT_GE(seq.size(), 3u);
173 seq.erase(3, seq.size());
174 seq.setAllBlendRadiiToZero();
176 RobotTrajCont res123_vec{ manager_->solve(scene_, pipeline_, seq.toRequest()) };
177 EXPECT_EQ(res123_vec.size(), 1u);
178 EXPECT_GT(res123_vec.front()->getWayPointCount(), 0u);
181 ROS_INFO(
"step 2: only first segment");
182 moveit_msgs::msg::MotionSequenceRequest req_1;
183 req_1.items.resize(1);
184 req_1.items.at(0).req = seq.getCmd(0).toRequest();
185 req_1.items.at(0).blend_radius = 0.;
186 RobotTrajCont res1_vec{ manager_->solve(scene_, pipeline_, req_1) };
187 EXPECT_EQ(res1_vec.size(), 1u);
188 EXPECT_GT(res1_vec.front()->getWayPointCount(), 0u);
189 EXPECT_EQ(res1_vec.front()->getFirstWayPoint().getVariableCount(),
190 req_1.items.at(0).req.start_state.joint_state.name.size());
192 ROS_INFO(
"step 3: only second segment");
193 moveit_msgs::msg::MotionSequenceRequest req_2;
194 req_2.items.resize(1);
195 req_2.items.at(0).req = seq.getCmd(1).toRequest();
196 req_2.items.at(0).blend_radius = 0.;
197 RobotTrajCont res2_vec{ manager_->solve(scene_, pipeline_, req_2) };
198 EXPECT_EQ(res2_vec.size(), 1u);
199 EXPECT_GT(res2_vec.front()->getWayPointCount(), 0u);
200 EXPECT_EQ(res2_vec.front()->getFirstWayPoint().getVariableCount(),
201 req_2.items.at(0).req.start_state.joint_state.name.size());
203 ROS_INFO(
"step 4: only third segment");
204 moveit_msgs::msg::MotionSequenceRequest req_3;
205 req_3.items.resize(1);
206 req_3.items.at(0).req = seq.getCmd(2).toRequest();
207 req_3.items.at(0).blend_radius = 0.;
208 RobotTrajCont res3_vec{ manager_->solve(scene_, pipeline_, req_3) };
209 EXPECT_EQ(res3_vec.size(), 1u);
210 EXPECT_GT(res3_vec.front()->getWayPointCount(), 0u);
211 EXPECT_EQ(res3_vec.front()->getFirstWayPoint().getVariableCount(),
212 req_3.items.at(0).req.start_state.joint_state.name.size());
215 auto t1_2_3 = res123_vec.front()->getWayPointDurationFromStart(res123_vec.front()->getWayPointCount() - 1);
216 auto t1 = res1_vec.front()->getWayPointDurationFromStart(res123_vec.front()->getWayPointCount() - 1);
217 auto t2 = res2_vec.front()->getWayPointDurationFromStart(res123_vec.front()->getWayPointCount() - 1);
218 auto t3 = res3_vec.front()->getWayPointDurationFromStart(res123_vec.front()->getWayPointCount() - 1);
219 ROS_DEBUG_STREAM(
"total time: " << t1_2_3 <<
" t1:" << t1 <<
" t2:" << t2 <<
" t3:" << t3);
220 EXPECT_LT(fabs((t1_2_3 - t1 - t2 - t3)), 0.4);
240 Sequence seq{ data_loader_->getSequence(
"ComplexSequence") };
241 ASSERT_GE(seq.size(), 3u);
242 seq.erase(3, seq.size());
243 seq.setAllBlendRadiiToZero();
244 seq.setBlendRadius(0, 0.1);
245 RobotTrajCont res1{ manager_->solve(scene_, pipeline_, seq.toRequest()) };
246 EXPECT_EQ(res1.size(), 1u);
247 EXPECT_GT(res1.front()->getWayPointCount(), 0u);
250 seq.setAllBlendRadiiToZero();
251 seq.setBlendRadius(1, 0.1);
252 RobotTrajCont res2{ manager_->solve(scene_, pipeline_, seq.toRequest()) };
253 EXPECT_EQ(res2.size(), 1u);
254 EXPECT_GT(res2.front()->getWayPointCount(), 0u);
270 Sequence seq{ data_loader_->getSequence(
"PtpPtpSequence") };
271 ASSERT_GE(seq.size(), 2u);
272 seq.setAllBlendRadiiToZero();
274 RobotTrajCont res_vec{ manager_->solve(scene_, pipeline_, seq.toRequest()) };
275 EXPECT_EQ(res_vec.size(), 1u);
276 EXPECT_GT(res_vec.front()->getWayPointCount(), 0u);
292 Sequence seq{ data_loader_->getSequence(
"PtpLinSequence") };
293 ASSERT_GE(seq.size(), 2u);
294 seq.setAllBlendRadiiToZero();
296 RobotTrajCont res_vec{ manager_->solve(scene_, pipeline_, seq.toRequest()) };
297 EXPECT_EQ(res_vec.size(), 1u);
298 EXPECT_GT(res_vec.front()->getWayPointCount(), 0u);
314 Sequence seq{ data_loader_->getSequence(
"LinPtpSequence") };
315 ASSERT_GE(seq.size(), 2u);
316 seq.setAllBlendRadiiToZero();
318 RobotTrajCont res_vec{ manager_->solve(scene_, pipeline_, seq.toRequest()) };
319 EXPECT_EQ(res_vec.size(), 1u);
320 EXPECT_GT(res_vec.front()->getWayPointCount(), 0u);
335 Sequence seq{ data_loader_->getSequence(
"SimpleSequence") };
336 ASSERT_EQ(seq.size(), 2u);
337 moveit_msgs::msg::MotionSequenceRequest req{ seq.toRequest() };
338 RobotTrajCont res_vec{ manager_->solve(scene_, pipeline_, req) };
339 EXPECT_EQ(res_vec.size(), 1u);
340 EXPECT_GT(res_vec.front()->getWayPointCount(), 0u);
341 EXPECT_EQ(res_vec.front()->getFirstWayPoint().getVariableCount(),
342 req.items.at(0).req.start_state.joint_state.name.size());
345 ros::Publisher pub = nh.advertise<moveit_msgs::msg::DisplayTrajectory>(
"my_planned_path", 1);
346 ros::Duration duration(1.0);
349 moveit_msgs::msg::DisplayTrajectory display_trajectory;
350 moveit_msgs::msg::RobotTrajectory rob_traj_msg;
351 res_vec.front()->getRobotTrajectoryMsg(rob_traj_msg);
352 display_trajectory.trajectory.push_back(rob_traj_msg);
353 pub.publish(display_trajectory);
371 moveit_msgs::msg::MotionSequenceRequest empty_list;
372 RobotTrajCont res_vec{ manager_->solve(scene_, pipeline_, empty_list) };
373 EXPECT_TRUE(res_vec.empty());
387 Sequence seq{ data_loader_->getSequence(
"SimpleSequence") };
388 ASSERT_GE(seq.size(), 2u);
391 EXPECT_THROW(manager_->solve(scene_, pipeline_, seq.toRequest()), PlanningPipelineException);
405 Sequence seq{ data_loader_->getSequence(
"SimpleSequence") };
406 ASSERT_GE(seq.size(), 2u);
408 moveit_msgs::msg::MotionSequenceRequest req{ seq.
toRequest() };
409 req.items.at(1).req.start_state = lin.getGoalConfiguration().toMoveitMsgsRobotState();
410 EXPECT_THROW(manager_->solve(scene_, pipeline_, req), StartStateSetException);
425 Sequence seq{ data_loader_->getSequence(
"SimpleSequence") };
426 ASSERT_GE(seq.size(), 2u);
427 seq.setBlendRadius(0, -0.3);
428 EXPECT_THROW(manager_->solve(scene_, pipeline_, seq.toRequest()), NegativeBlendRadiusException);
443 Sequence seq{ data_loader_->getSequence(
"SimpleSequence") };
444 ASSERT_EQ(seq.size(), 2u);
445 seq.setBlendRadius(1, 0.03);
446 EXPECT_THROW(manager_->solve(scene_, pipeline_, seq.toRequest()), LastBlendRadiusNotZeroException);
462 Sequence seq{ data_loader_->getSequence(
"SimpleSequence") };
463 ASSERT_GE(seq.size(), 2u);
464 seq.setBlendRadius(0, 42.0);
465 EXPECT_THROW(manager_->solve(scene_, pipeline_, seq.toRequest()), BlendingFailedException);
482 Sequence seq{ data_loader_->getSequence(
"ComplexSequence") };
483 ASSERT_GE(seq.size(), 3u);
484 seq.erase(3, seq.size());
486 RobotTrajCont res_valid_vec{ manager_->solve(scene_, pipeline_, seq.toRequest()) };
487 EXPECT_EQ(res_valid_vec.size(), 1u);
488 EXPECT_GT(res_valid_vec.front()->getWayPointCount(), 0u);
493 Eigen::Isometry3d p1, p2;
494 tf2::fromMsg(ptp.getGoalConfiguration().getPose(), p1);
495 tf2::fromMsg(circ.getGoalConfiguration().getPose(), p2);
496 auto distance = (p2.translation() - p1.translation()).norm();
498 seq.setBlendRadius(1, (
distance - seq.getBlendRadius(0) + 0.01));
499 EXPECT_THROW(manager_->solve(scene_, pipeline_, seq.toRequest()), OverlappingBlendRadiiException);
518 Sequence seq{ data_loader_->getSequence(
"ComplexSequence") };
519 ASSERT_GE(seq.size(), 2u);
520 RobotTrajCont res_single_vec{ manager_->solve(scene_, pipeline_, seq.toRequest()) };
521 EXPECT_EQ(res_single_vec.size(), 1u);
522 EXPECT_GT(res_single_vec.front()->getWayPointCount(), 0u);
524 moveit_msgs::msg::MotionSequenceRequest req{ seq.toRequest() };
527 const size_t n{ req.items.size() };
528 for (
size_t i = 0; i < n; ++i)
530 moveit_msgs::msg::MotionSequenceItem item{ req.items.at(i) };
535 item.req.start_state = moveit_msgs::msg::RobotState();
537 req.items.push_back(item);
540 RobotTrajCont res_n_vec{ manager_->solve(scene_, pipeline_, req) };
541 EXPECT_EQ(res_n_vec.size(), 1u);
542 EXPECT_GT(res_n_vec.front()->getWayPointCount(), 0u);
544 const double trajectory_time_1 =
545 res_single_vec.front()->getWayPointDurationFromStart(res_single_vec.front()->getWayPointCount() - 1);
546 const double trajectory_time_n =
547 res_n_vec.front()->getWayPointDurationFromStart(res_n_vec.front()->getWayPointCount() - 1);
548 double multiplicator = req.items.size() / n;
549 EXPECT_LE(trajectory_time_n, trajectory_time_1 * multiplicator);
550 EXPECT_GE(trajectory_time_n, trajectory_time_1 * multiplicator * 0.5);
564 Sequence seq{ data_loader_->getSequence(
"ComplexSequenceWithGripper") };
565 ASSERT_GE(seq.size(), 1u);
567 unsigned int num_groups{ 1 };
568 std::string last_group_name{ seq.getCmd(0).getPlanningGroup() };
569 for (
size_t i = 1; i < seq.size(); ++i)
571 if (seq.getCmd(i).getPlanningGroup() != last_group_name)
574 last_group_name = seq.getCmd(i).getPlanningGroup();
578 RobotTrajCont res_single_vec{ manager_->solve(scene_, pipeline_, seq.toRequest()) };
579 EXPECT_EQ(res_single_vec.size(), num_groups);
581 for (
const auto& res : res_single_vec)
583 EXPECT_GT(res->getWayPointCount(), 0u);
594 Sequence seq{ data_loader_->getSequence(
"PureGripperSequence") };
595 ASSERT_GE(seq.size(), 2u);
596 ASSERT_TRUE(seq.cmdIsOfType<
Gripper>(0));
597 ASSERT_TRUE(seq.cmdIsOfType<
Gripper>(1));
600 seq.setBlendRadius(0, 1.0);
601 RobotTrajCont res_vec{ manager_->solve(scene_, pipeline_, seq.toRequest()) };
602 EXPECT_EQ(res_vec.size(), 1u);
620 using std::placeholders::_1;
622 Sequence seq{ data_loader_->getSequence(
"ComplexSequenceWithGripper") };
623 ASSERT_GE(seq.size(), 4u);
624 seq.erase(4, seq.size());
627 gripper.
getStartConfiguration().setCreateJointNameFunc([](
size_t n) {
return createGripperJointName(n); });
630 gripper.getStartConfiguration().clearModel();
633 ptp.
getStartConfiguration().setCreateJointNameFunc([](
size_t n) {
return createManipulatorJointName(n); });
636 ptp.getStartConfiguration().clearModel();
638 RobotTrajCont res_vec{ manager_->solve(scene_, pipeline_, seq.toRequest()) };
639 EXPECT_GE(res_vec.size(), 1u);
640 EXPECT_GT(res_vec.front()->getWayPointCount(), 0u);
649 Gripper gripper_cmd{ data_loader_->getGripper(
"open_gripper") };
650 EXPECT_THROW(getSolverTipFrame(robot_model_->getJointModelGroup(gripper_cmd.getPlanningGroup())), NoSolverException);
653 int main(
int argc,
char** argv)
655 ros::init(argc, argv,
"integrationtest_command_list_manager");
656 testing::InitGoogleTest(&argc, argv);
660 return RUN_ALL_TESTS();
planning_scene::PlanningScenePtr scene_
std::shared_ptr< pilz_industrial_motion_planner::CommandListManager > manager_
planning_pipeline::PlanningPipelinePtr pipeline_
std::unique_ptr< pilz_industrial_motion_planner_testutils::TestdataLoader > data_loader_
StartType & getStartConfiguration()
planning_interface::MotionPlanRequest toRequest() const override
GoalType & getGoalConfiguration()
Data class storing all information regarding a Circ command.
Data class storing all information regarding a linear command.
Data class storing all information regarding a Ptp command.
Data class storing all information regarding a Sequence command.
const moveit::core::RobotModelPtr & getModel() const
Get the constructed planning_models::RobotModel.
const std::string ROBOT_DESCRIPTION_STR
int main(int argc, char **argv)
const std::string TEST_DATA_FILE_NAME("testdata_file_name")
const std::string EMPTY_VALUE
std::vector< robot_trajectory::RobotTrajectoryPtr > RobotTrajCont
TEST_F(GetSolverTipFrameIntegrationTest, TestHasSolverManipulator)
Check if hasSolver() can be called successfully for the manipulator group.
double distance(const urdf::Pose &transform)
::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...