39#include <rclcpp/duration.hpp>
40#include <rclcpp/logger.hpp>
41#include <rclcpp/logging.hpp>
45#include <tf2_eigen/tf2_eigen.hpp>
46#include <tf2_geometry_msgs/tf2_geometry_msgs.hpp>
63 throw TrajectoryGeneratorInvalidLimitsException(
"joint limit not set");
69 const auto* jmg = robot_model->getJointModelGroup(group_name);
71 throw TrajectoryGeneratorInvalidLimitsException(
"invalid group: " + group_name);
73 const auto& active_joints = jmg->getActiveJointModelNames();
76 if (!active_joints.empty())
78 most_strict_limit_ = joint_limits_.getCommonLimit(active_joints);
80 if (!most_strict_limit_.has_velocity_limits)
82 throw TrajectoryGeneratorInvalidLimitsException(
"velocity limit not set for group " + group_name);
84 if (!most_strict_limit_.has_acceleration_limits)
86 throw TrajectoryGeneratorInvalidLimitsException(
"acceleration limit not set for group " + group_name);
88 if (!most_strict_limit_.has_deceleration_limits)
90 throw TrajectoryGeneratorInvalidLimitsException(
"deceleration limit not set for group " + group_name);
94 RCLCPP_INFO(
getLogger(),
"Initialized Point-to-Point Trajectory Generator.");
97void TrajectoryGeneratorPTP::planPTP(
const std::map<std::string, double>& start_pos,
98 const std::map<std::string, double>& goal_pos,
99 trajectory_msgs::msg::JointTrajectory& joint_trajectory,
100 double velocity_scaling_factor,
double acceleration_scaling_factor,
101 double sampling_time)
104 for (
const auto& item : goal_pos)
106 joint_trajectory.joint_names.push_back(item.first);
110 bool goal_reached =
true;
111 for (
const auto& goal : goal_pos)
113 if (fabs(start_pos.at(goal.first) - goal.second) >= MIN_MOVEMENT)
115 goal_reached =
false;
121 RCLCPP_INFO_STREAM(
getLogger(),
"Goal already reached, set one goal point explicitly.");
122 if (joint_trajectory.points.empty())
124 trajectory_msgs::msg::JointTrajectoryPoint point;
125 point.time_from_start = rclcpp::Duration::from_seconds(sampling_time);
126 for (
const std::string& joint_name : joint_trajectory.joint_names)
128 point.positions.push_back(start_pos.at(joint_name));
129 point.velocities.push_back(0);
130 point.accelerations.push_back(0);
132 joint_trajectory.points.push_back(point);
138 std::string leading_axis = joint_trajectory.joint_names.front();
139 double max_duration = -1.0;
141 std::map<std::string, VelocityProfileATrap> velocity_profile;
142 for (
const auto& joint_name : joint_trajectory.joint_names)
145 velocity_profile.insert(std::make_pair(
146 joint_name, VelocityProfileATrap(velocity_scaling_factor * most_strict_limit_.max_velocity,
147 acceleration_scaling_factor * most_strict_limit_.max_acceleration,
148 acceleration_scaling_factor * most_strict_limit_.max_deceleration)));
150 velocity_profile.at(joint_name).SetProfile(start_pos.at(joint_name), goal_pos.at(joint_name));
151 if (velocity_profile.at(joint_name).Duration() > max_duration)
153 max_duration = velocity_profile.at(joint_name).Duration();
154 leading_axis = joint_name;
162 double acc_time = velocity_profile.at(leading_axis).firstPhaseDuration();
163 double const_time = velocity_profile.at(leading_axis).secondPhaseDuration();
164 double dec_time = velocity_profile.at(leading_axis).thirdPhaseDuration();
166 for (
const auto& joint_name : joint_trajectory.joint_names)
168 if (joint_name != leading_axis)
174 if (!velocity_profile.at(joint_name)
175 .setProfileAllDurations(start_pos.at(joint_name), goal_pos.at(joint_name), acc_time, const_time,
179 std::stringstream error_str;
180 error_str <<
"TrajectoryGeneratorPTP::planPTP(): Can not synchronize "
181 "velocity profile of axis "
182 << joint_name <<
" with leading axis " << leading_axis;
183 throw PtpVelocityProfileSyncFailed(error_str.str());
190 std::vector<double> time_samples;
191 for (
double t_sample = 0.0; t_sample < max_duration; t_sample += sampling_time)
193 time_samples.push_back(t_sample);
196 time_samples.push_back(max_duration);
199 for (
double time_stamp : time_samples)
201 trajectory_msgs::msg::JointTrajectoryPoint point;
202 point.time_from_start = rclcpp::Duration::from_seconds(time_stamp);
203 for (std::string& joint_name : joint_trajectory.joint_names)
205 point.positions.push_back(velocity_profile.at(joint_name).Pos(time_stamp));
206 point.velocities.push_back(velocity_profile.at(joint_name).Vel(time_stamp));
207 point.accelerations.push_back(velocity_profile.at(joint_name).Acc(time_stamp));
209 joint_trajectory.points.push_back(point);
213 std::fill(joint_trajectory.points.back().velocities.begin(), joint_trajectory.points.back().velocities.end(), 0.0);
214 std::fill(joint_trajectory.points.back().accelerations.begin(), joint_trajectory.points.back().accelerations.end(),
218void TrajectoryGeneratorPTP::extractMotionPlanInfo(
const planning_scene::PlanningSceneConstPtr& scene,
220 MotionPlanInfo& info)
const
222 info.group_name = req.group_name;
225 info.goal_joint_position.clear();
226 if (!req.goal_constraints.at(0).joint_constraints.empty())
228 for (
const auto& joint_constraint : req.goal_constraints.at(0).joint_constraints)
230 info.goal_joint_position[joint_constraint.joint_name] = joint_constraint.position;
236 std::string frame_id;
238 info.link_name = req.goal_constraints.front().position_constraints.front().link_name;
239 if (req.goal_constraints.front().position_constraints.front().header.frame_id.empty() ||
240 req.goal_constraints.front().orientation_constraints.front().header.frame_id.empty())
242 RCLCPP_WARN(
getLogger(),
"Frame id is not set in position/orientation constraints of "
243 "goal. Use model frame as default");
244 frame_id = robot_model_->getModelFrame();
248 frame_id = req.goal_constraints.front().position_constraints.front().header.frame_id;
252 info.goal_pose = scene->getFrameTransform(frame_id) *
getConstraintPose(req.goal_constraints.front());
253 frame_id = robot_model_->getModelFrame();
256 if (!
computePoseIK(scene, info.group_name, info.link_name, info.goal_pose, frame_id, info.start_joint_position,
257 info.goal_joint_position))
259 std::ostringstream os;
260 os <<
"Failed to compute inverse kinematics for link: " << info.link_name <<
" of goal pose";
261 throw PtpNoIkSolutionForGoalPose(os.str());
266void TrajectoryGeneratorPTP::plan(
const planning_scene::PlanningSceneConstPtr& ,
268 double sampling_time, trajectory_msgs::msg::JointTrajectory& joint_trajectory)
271 planPTP(plan_info.start_joint_position, plan_info.goal_joint_position, joint_trajectory,
272 req.max_velocity_scaling_factor, req.max_acceleration_scaling_factor, sampling_time);
This class combines CartesianLimit and JointLimits into on single class.
TrajectoryGeneratorPTP(const moveit::core::RobotModelConstPtr &robot_model, const pilz_industrial_motion_planner::LimitsContainer &planner_limits, const std::string &group_name)
Constructor of PTP Trajectory Generator.
TrajectoryGenerator(const moveit::core::RobotModelConstPtr &robot_model, const pilz_industrial_motion_planner::LimitsContainer &planner_limits)
const pilz_industrial_motion_planner::LimitsContainer planner_limits_
rclcpp::Logger getLogger(const std::string &name)
Creates a namespaced logger.
bool computePoseIK(const planning_scene::PlanningSceneConstPtr &scene, const std::string &group_name, const std::string &link_name, const Eigen::Isometry3d &pose, const std::string &frame_id, const std::map< std::string, double > &seed, std::map< std::string, double > &solution, bool check_self_collision=true, const double timeout=0.0)
compute the inverse kinematics of a given pose, also check robot self collision
moveit_msgs::msg::MotionPlanRequest MotionPlanRequest
rclcpp::Logger getLogger()
Eigen::Isometry3d getConstraintPose(const geometry_msgs::msg::Point &position, const geometry_msgs::msg::Quaternion &orientation, const geometry_msgs::msg::Vector3 &offset)
Adapt goal pose, defined by position+orientation, to consider offset.