37 #include <gtest/gtest.h>
43 #include <tf2_eigen/tf2_eigen.hpp>
44 #include <tf2_geometry_msgs/tf2_geometry_msgs.hpp>
57 #include <rclcpp/rclcpp.hpp>
72 rclcpp::NodeOptions node_options;
73 node_options.automatically_declare_parameters_from_overrides(
true);
74 node_ = rclcpp::Node::make_shared(
"unittest_trajectory_blender_transition_window", node_options);
77 rm_loader_ = std::make_unique<robot_model_loader::RobotModelLoader>(node_);
78 robot_model_ = rm_loader_->getModel();
79 ASSERT_TRUE(
bool(robot_model_)) <<
"Failed to load robot model";
80 planning_scene_ = std::make_shared<planning_scene::PlanningScene>(robot_model_);
83 ASSERT_TRUE(node_->has_parameter(
"planning_group"));
84 node_->get_parameter<std::string>(
"planning_group", planning_group_);
85 ASSERT_TRUE(node_->has_parameter(
"target_link"));
86 node_->get_parameter<std::string>(
"target_link", target_link_);
87 ASSERT_TRUE(node_->has_parameter(
"cartesian_velocity_tolerance"));
88 node_->get_parameter<
double>(
"cartesian_velocity_tolerance", cartesian_velocity_tolerance_);
89 ASSERT_TRUE(node_->has_parameter(
"cartesian_angular_velocity_tolerance"));
90 node_->get_parameter<
double>(
"cartesian_angular_velocity_tolerance", cartesian_angular_velocity_tolerance_);
91 ASSERT_TRUE(node_->has_parameter(
"joint_velocity_tolerance"));
92 node_->get_parameter<
double>(
"joint_velocity_tolerance", joint_velocity_tolerance_);
93 ASSERT_TRUE(node_->has_parameter(
"joint_acceleration_tolerance"));
94 node_->get_parameter<
double>(
"joint_acceleration_tolerance", joint_acceleration_tolerance_);
95 ASSERT_TRUE(node_->has_parameter(
"sampling_time"));
96 node_->get_parameter<
double>(
"sampling_time", sampling_time_);
97 ASSERT_TRUE(node_->has_parameter(
"testdata_file_name"));
98 node_->get_parameter<std::string>(
"testdata_file_name", test_data_file_name_);
101 data_loader_ = std::make_unique<XmlTestdataLoader>(test_data_file_name_, robot_model_);
102 ASSERT_NE(
nullptr, data_loader_) <<
"Failed to load test data by provider.";
112 cartesian_limits::Params cart_limits;
113 cart_limits.max_trans_vel = 1 * M_PI;
114 cart_limits.max_trans_acc = 2;
115 cart_limits.max_trans_dec = 2;
116 cart_limits.max_rot_vel = 1;
119 planner_limits_.setCartesianLimits(cart_limits);
122 lin_generator_ = std::make_unique<TrajectoryGeneratorLIN>(robot_model_, planner_limits_, planning_group_);
123 ASSERT_NE(
nullptr, lin_generator_) <<
"failed to create LIN trajectory generator";
124 blender_ = std::make_unique<TrajectoryBlenderTransitionWindow>(planner_limits_);
125 ASSERT_NE(
nullptr, blender_) <<
"failed to create trajectory blender";
130 robot_model_.reset();
138 std::vector<planning_interface::MotionPlanResponse> responses(num_cmds);
139 for (
size_t index = 0; index < num_cmds; ++index)
150 lin_generator_->generate(planning_scene_, req, resp, sampling_time_);
151 if (resp.
error_code.val != moveit_msgs::msg::MoveItErrorCodes::SUCCESS)
153 std::runtime_error(
"Failed to generate trajectory.");
155 responses.at(index) = resp;
164 std::unique_ptr<robot_model_loader::RobotModelLoader>
rm_loader_;
168 std::unique_ptr<TrajectoryBlenderTransitionWindow>
blender_;
193 Sequence seq{ data_loader_->getSequence(
"SimpleSequence") };
195 std::vector<planning_interface::MotionPlanResponse> res{ generateLinTrajs(seq, 2) };
206 EXPECT_FALSE(blender_->blend(planning_scene_, blend_req, blend_res));
222 Sequence seq{ data_loader_->getSequence(
"SimpleSequence") };
224 std::vector<planning_interface::MotionPlanResponse> res{ generateLinTrajs(seq, 2) };
230 blend_req.
link_name =
"invalid_target_link";
235 EXPECT_FALSE(blender_->blend(planning_scene_, blend_req, blend_res));
252 Sequence seq{ data_loader_->getSequence(
"SimpleSequence") };
254 std::vector<planning_interface::MotionPlanResponse> res{ generateLinTrajs(seq, 2) };
265 EXPECT_FALSE(blender_->blend(planning_scene_, blend_req, blend_res));
281 Sequence seq{ data_loader_->getSequence(
"SimpleSequence") };
283 std::vector<planning_interface::MotionPlanResponse> res{ generateLinTrajs(seq, 2) };
294 EXPECT_FALSE(blender_->blend(planning_scene_, blend_req, blend_res));
311 Sequence seq{ data_loader_->getSequence(
"SimpleSequence") };
314 std::size_t num_cmds{ 2 };
315 std::vector<planning_interface::MotionPlanResponse> responses(num_cmds);
317 for (
size_t index = 0; index < num_cmds; ++index)
329 lin_generator_->generate(planning_scene_, req, resp, sampling_time_);
330 if (resp.
error_code.val != moveit_msgs::msg::MoveItErrorCodes::SUCCESS)
332 std::runtime_error(
"Failed to generate trajectory.");
334 responses.at(index) = resp;
345 EXPECT_FALSE(blender_->blend(planning_scene_, blend_req, blend_res));
364 Sequence seq{ data_loader_->getSequence(
"SimpleSequence") };
366 std::vector<planning_interface::MotionPlanResponse> res{ generateLinTrajs(seq, 2) };
369 EXPECT_GT(res[0].trajectory->getWayPointCount(), 2u);
370 res[0].trajectory->setWayPointDurationFromPrevious(1, 2 * sampling_time_);
380 EXPECT_FALSE(blender_->blend(planning_scene_, blend_req, blend_res));
398 Sequence seq{ data_loader_->getSequence(
"SimpleSequence") };
400 std::vector<planning_interface::MotionPlanResponse> res{ generateLinTrajs(seq, 1) };
412 EXPECT_FALSE(blender_->blend(planning_scene_, blend_req, blend_res));
429 Sequence seq{ data_loader_->getSequence(
"SimpleSequence") };
431 std::vector<planning_interface::MotionPlanResponse> res{ generateLinTrajs(seq, 2) };
445 blend_req.
first_trajectory->getLastWayPointPtr()->setVariableVelocity(0, 1.0);
448 EXPECT_FALSE(blender_->blend(planning_scene_, blend_req, blend_res));
466 Sequence seq{ data_loader_->getSequence(
"SimpleSequence") };
468 std::vector<planning_interface::MotionPlanResponse> res{ generateLinTrajs(seq, 2) };
470 double lin1_distance;
471 lin1_distance = (res[0].trajectory->getFirstWayPoint().getFrameTransform(target_link_).translation() -
472 res[0].trajectory->getLastWayPoint().getFrameTransform(target_link_).translation())
485 EXPECT_FALSE(blender_->blend(planning_scene_, blend_req, blend_res));
503 Sequence seq{ data_loader_->getSequence(
"NoIntersectionTraj2") };
505 std::vector<planning_interface::MotionPlanResponse> res{ generateLinTrajs(seq, 2) };
517 EXPECT_FALSE(blender_->blend(planning_scene_, blend_req, blend_res));
540 Sequence seq{ data_loader_->getSequence(
"SimpleSequence") };
542 std::vector<planning_interface::MotionPlanResponse> res{ generateLinTrajs(seq, 2) };
554 EXPECT_TRUE(blender_->blend(planning_scene_, blend_req, blend_res));
557 joint_acceleration_tolerance_, cartesian_velocity_tolerance_,
558 cartesian_angular_velocity_tolerance_));
583 Sequence seq{ data_loader_->getSequence(
"SimpleSequence") };
587 std::vector<planning_interface::MotionPlanResponse> res{ generateLinTrajs(seq, 2) };
597 EXPECT_TRUE(blender_->blend(planning_scene_, blend_req, blend_res));
600 joint_acceleration_tolerance_, cartesian_velocity_tolerance_,
601 cartesian_angular_velocity_tolerance_));
629 const double sine_scaling_factor{ 0.01 };
630 const double time_scaling_factor{ 10 };
632 Sequence seq{ data_loader_->getSequence(
"SimpleSequence") };
634 std::vector<planning_interface::MotionPlanResponse> res{ generateLinTrajs(seq, 2) };
637 std::vector<robot_trajectory::RobotTrajectoryPtr> sine_trajs(2);
639 for (
size_t traj_index = 0; traj_index < 2; ++traj_index)
641 auto lin_traj{ res.at(traj_index).trajectory };
644 trajectory_msgs::msg::JointTrajectory joint_traj;
645 const double duration{ lin_traj->getWayPointDurationFromStart(lin_traj->getWayPointCount()) };
647 const double time_from_start_offset{ time_scaling_factor * lin_traj->getWayPointDurations().back() };
650 for (
size_t i = 0; i < lin_traj->getWayPointCount(); ++i)
653 const double sine_arg{ 4 * M_PI * lin_traj->getWayPointDurationFromStart(i) / duration };
657 const Eigen::Isometry3d eigen_pose{ lin_traj->getWayPointPtr(i)->getFrameTransform(target_link_) };
658 geometry_msgs::msg::Pose waypoint_pose = tf2::toMsg(eigen_pose);
661 waypoint_pose.position.x += sine_scaling_factor * sin(sine_arg);
662 waypoint_pose.position.y += sine_scaling_factor * sin(sine_arg);
663 waypoint_pose.position.z += sine_scaling_factor * sin(sine_arg);
666 waypoint.
pose = waypoint_pose;
668 time_from_start_offset + time_scaling_factor * lin_traj->getWayPointDurationFromStart(i));
669 cart_traj.
points.push_back(waypoint);
673 std::map<std::string, double> initial_joint_position, initial_joint_velocity;
674 for (
const std::string& joint_name :
675 lin_traj->getFirstWayPointPtr()->getJointModelGroup(planning_group_)->getActiveJointModelNames())
679 initial_joint_position[joint_name] = lin_traj->getFirstWayPoint().getVariablePosition(joint_name);
680 initial_joint_velocity[joint_name] = lin_traj->getFirstWayPoint().getVariableVelocity(joint_name);
684 initial_joint_position[joint_name] =
685 sine_trajs[traj_index - 1]->getLastWayPoint().getVariablePosition(joint_name);
686 initial_joint_velocity[joint_name] =
687 sine_trajs[traj_index - 1]->getLastWayPoint().getVariableVelocity(joint_name);
691 moveit_msgs::msg::MoveItErrorCodes error_code;
692 if (!
generateJointTrajectory(planning_scene_, planner_limits_.getJointLimitContainer(), cart_traj, planning_group_,
693 target_link_, initial_joint_position, initial_joint_velocity, joint_traj, error_code,
696 std::runtime_error(
"Failed to generate trajectory.");
699 joint_traj.points.back().velocities.assign(joint_traj.points.back().velocities.size(), 0.0);
700 joint_traj.points.back().accelerations.assign(joint_traj.points.back().accelerations.size(), 0.0);
703 sine_trajs[traj_index] = std::make_shared<robot_trajectory::RobotTrajectory>(robot_model_, planning_group_);
704 sine_trajs.at(traj_index)->setRobotTrajectoryMsg(lin_traj->getFirstWayPoint(), joint_traj);
717 EXPECT_TRUE(blender_->blend(planning_scene_, blend_req, blend_res));
720 joint_acceleration_tolerance_, cartesian_velocity_tolerance_,
721 cartesian_angular_velocity_tolerance_));
724 int main(
int argc,
char** argv)
726 rclcpp::init(argc, argv);
727 testing::InitGoogleTest(&argc, argv);
728 return RUN_ALL_TESTS();
void SetUp() override
Create test scenario for trajectory blender.
std::string planning_group_
moveit::core::RobotModelConstPtr robot_model_
std::string test_data_file_name_
std::unique_ptr< TrajectoryGenerator > lin_generator_
double joint_acceleration_tolerance_
double cartesian_angular_velocity_tolerance_
std::unique_ptr< TrajectoryBlenderTransitionWindow > blender_
std::unique_ptr< robot_model_loader::RobotModelLoader > rm_loader_
std::vector< planning_interface::MotionPlanResponse > generateLinTrajs(const Sequence &seq, size_t num_cmds)
Generate lin trajectories for blend sequences.
XmlTestDataLoaderUPtr data_loader_
planning_scene::PlanningSceneConstPtr planning_scene_
LimitsContainer planner_limits_
rclcpp::Node::SharedPtr node_
static JointLimitsContainer getAggregatedLimits(const rclcpp::Node::SharedPtr &node, const std::string ¶m_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.
StartType & getStartConfiguration()
Data class storing all information regarding a linear command.
Data class storing all information regarding a Sequence command.
T & getCmd(const size_t index_cmd)
void robotStateToRobotStateMsg(const RobotState &state, moveit_msgs::msg::RobotState &robot_state, bool copy_attached_bodies=true)
Convert a MoveIt robot state to a robot state message.
std::unique_ptr< TestdataLoader > XmlTestDataLoaderUPtr
bool generateJointTrajectory(const planning_scene::PlanningSceneConstPtr &scene, const JointLimitsContainer &joint_limits, const KDL::Trajectory &trajectory, const std::string &group_name, const std::string &link_name, const std::map< std::string, double > &initial_joint_position, double sampling_time, trajectory_msgs::msg::JointTrajectory &joint_trajectory, moveit_msgs::msg::MoveItErrorCodes &error_code, bool check_self_collision=false)
Generate joint trajectory from a KDL Cartesian trajectory.
TEST_F(GetSolverTipFrameIntegrationTest, TestHasSolverManipulator)
Check if hasSolver() can be called successfully for the manipulator group.
moveit_msgs::msg::MotionPlanRequest MotionPlanRequest
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
void checkRobotModel(const moveit::core::RobotModelConstPtr &robot_model, const std::string &group_name, const std::string &link_name)
geometry_msgs::msg::Pose pose
rclcpp::Duration time_from_start
std::vector< CartesianTrajectoryPoint > points
robot_trajectory::RobotTrajectoryPtr second_trajectory
robot_trajectory::RobotTrajectoryPtr first_trajectory
Response to a planning query.
moveit::core::MoveItErrorCode error_code
int main(int argc, char **argv)
const std::string PARAM_NAMESPACE_LIMITS