39#include <tf2_eigen/tf2_eigen.hpp>
40#include <tf2_kdl/tf2_kdl.hpp>
41#include <boost/range/combine.hpp>
43#include <kdl/velocityprofile_trap.hpp>
59sensor_msgs::msg::JointState TrajectoryGenerator::filterGroupValues(
const sensor_msgs::msg::JointState& robot_state,
60 const std::string& group)
const
62 const std::vector<std::string>& group_joints{
robot_model_->getJointModelGroup(group)->getActiveJointModelNames() };
63 sensor_msgs::msg::JointState group_state;
64 group_state.name.reserve(group_joints.size());
65 group_state.position.reserve(group_joints.size());
66 group_state.velocity.reserve(group_joints.size());
68 for (
size_t i = 0; i < robot_state.name.size(); ++i)
70 if (std::find(group_joints.begin(), group_joints.end(), robot_state.name.at(i)) != group_joints.end())
72 group_state.name.push_back(robot_state.name.at(i));
73 group_state.position.push_back(robot_state.position.at(i));
74 if (i < robot_state.velocity.size())
76 group_state.velocity.push_back(robot_state.velocity.at(i));
89void TrajectoryGenerator::checkVelocityScaling(
double scaling_factor)
91 if (!isScalingFactorValid(scaling_factor))
93 std::ostringstream os;
95 <<
"actual value is: " << scaling_factor;
96 throw VelocityScalingIncorrect(os.str());
100void TrajectoryGenerator::checkAccelerationScaling(
double scaling_factor)
102 if (!isScalingFactorValid(scaling_factor))
104 std::ostringstream os;
106 <<
"actual value is: " << scaling_factor;
107 throw AccelerationScalingIncorrect(os.str());
111void TrajectoryGenerator::checkForValidGroupName(
const std::string& group_name)
const
115 std::ostringstream os;
116 os <<
"Unknown planning group: " << group_name;
117 throw UnknownPlanningGroup(os.str());
121void TrajectoryGenerator::checkStartState(
const moveit_msgs::msg::RobotState& start_state,
122 const std::string& group)
const
124 if (start_state.joint_state.name.size() != start_state.joint_state.position.size())
126 throw SizeMismatchInStartState(
"Joint state name and position do not match in start state");
129 sensor_msgs::msg::JointState group_start_state{ filterGroupValues(start_state.joint_state, group) };
133 std::string error_msg;
134 for (
auto joint : boost::combine(group_start_state.
name, group_start_state.position))
136 if (!limits.verifyPositionLimit(joint.get<0>(), joint.get<1>()))
138 error_msg.append(error_msg.empty() ?
"start state joints outside their position limits: " :
", ");
139 error_msg.append(joint.get<0>());
142 if (!error_msg.empty())
144 throw JointsOfStartStateOutOfRange(error_msg);
148 if (!std::all_of(group_start_state.velocity.begin(), group_start_state.velocity.end(),
149 [](
double v) { return std::fabs(v) < VELOCITY_TOLERANCE; }))
151 throw NonZeroVelocityInStartState(
"Trajectory Generator does not allow non-zero start velocity");
155void TrajectoryGenerator::checkJointGoalConstraint(
const moveit_msgs::msg::Constraints& constraint,
156 const std::string& group_name)
const
158 for (
const auto& joint_constraint : constraint.joint_constraints)
160 const std::string& curr_joint_name{ joint_constraint.joint_name };
162 if (!
robot_model_->getJointModelGroup(group_name)->hasJointModel(curr_joint_name))
164 std::ostringstream os;
165 os <<
"Joint \"" << curr_joint_name <<
"\" does not belong to group \"" << group_name <<
'\"';
166 throw JointConstraintDoesNotBelongToGroup(os.str());
171 std::ostringstream os;
172 os <<
"Joint \"" << curr_joint_name <<
"\" violates joint limits in goal constraints";
173 throw JointsOfGoalOutOfRange(os.str());
178void TrajectoryGenerator::checkCartesianGoalConstraint(
const moveit_msgs::msg::Constraints& constraint,
182 assert(constraint.position_constraints.size() == 1);
183 assert(constraint.orientation_constraints.size() == 1);
184 const moveit_msgs::msg::PositionConstraint& pos_constraint{ constraint.position_constraints.front() };
185 const moveit_msgs::msg::OrientationConstraint& ori_constraint{ constraint.orientation_constraints.front() };
187 if (pos_constraint.link_name.empty())
189 throw PositionConstraintNameMissing(
"Link name of position constraint missing");
192 if (ori_constraint.link_name.empty())
194 throw OrientationConstraintNameMissing(
"Link name of orientation constraint missing");
197 if (pos_constraint.link_name != ori_constraint.link_name)
199 std::ostringstream os;
200 os <<
"Position and orientation constraint name do not match"
201 <<
"(Position constraint name: \"" << pos_constraint.link_name <<
"\" | Orientation constraint name: \""
202 << ori_constraint.link_name <<
"\")";
203 throw PositionOrientationConstraintNameMismatch(os.str());
209 std::ostringstream os;
210 os <<
"No IK solver available for link: \"" << pos_constraint.link_name <<
'\"';
211 throw NoIKSolverAvailable(os.str());
214 if (pos_constraint.constraint_region.primitive_poses.empty())
216 throw NoPrimitivePoseGiven(
"Primitive pose in position constraints of goal missing");
220void TrajectoryGenerator::checkGoalConstraints(
221 const moveit_msgs::msg::MotionPlanRequest::_goal_constraints_type& goal_constraints,
const std::string& group_name,
224 if (goal_constraints.size() != 1)
226 std::ostringstream os;
227 os <<
"Exactly one goal constraint required, but " << goal_constraints.size() <<
" goal constraints given";
228 throw NotExactlyOneGoalConstraintGiven(os.str());
231 const moveit_msgs::msg::Constraints& goal_con{ goal_constraints.front() };
232 if (!isOnlyOneGoalTypeGiven(goal_con))
234 throw OnlyOneGoalTypeAllowed(
"Only cartesian XOR joint goal allowed");
237 if (isJointGoalGiven(goal_con))
239 checkJointGoalConstraint(goal_con, group_name);
243 checkCartesianGoalConstraint(goal_con, rstate,
robot_model_->getJointModelGroup(group_name));
250 checkVelocityScaling(req.max_velocity_scaling_factor);
251 checkAccelerationScaling(req.max_acceleration_scaling_factor);
252 checkForValidGroupName(req.group_name);
253 checkStartState(req.start_state, req.group_name);
254 checkGoalConstraints(req.goal_constraints, req.group_name, rstate);
257void TrajectoryGenerator::setSuccessResponse(
const moveit::core::RobotState& start_state,
const std::string& group_name,
258 const trajectory_msgs::msg::JointTrajectory& joint_trajectory,
259 const rclcpp::Time& planning_start,
262 auto rt = std::make_shared<robot_trajectory::RobotTrajectory>(
robot_model_, group_name);
263 rt->setRobotTrajectoryMsg(start_state, joint_trajectory);
266 res.
error_code.val = moveit_msgs::msg::MoveItErrorCodes::SUCCESS;
270void TrajectoryGenerator::setFailureResponse(
const rclcpp::Time& planning_start,
280std::unique_ptr<KDL::VelocityProfile>
282 double max_acceleration_scaling_factor,
283 const std::unique_ptr<KDL::Path>& path)
const
285 std::unique_ptr<KDL::VelocityProfile> vp_trans = std::make_unique<KDL::VelocityProfile_Trap>(
289 if (path->PathLength() > std::numeric_limits<double>::epsilon())
291 vp_trans->SetProfile(0, path->PathLength());
295 vp_trans->SetProfile(0, std::numeric_limits<double>::epsilon());
304 RCLCPP_INFO_STREAM(getLogger(),
"Generating " << req.planner_id <<
" trajectory...");
305 rclcpp::Time planning_begin =
clock_->now();
310 validateRequest(req, scene->getCurrentState());
314 RCLCPP_ERROR_STREAM(getLogger(), ex.what());
316 setFailureResponse(planning_begin, res);
322 cmdSpecificRequestValidation(req);
326 RCLCPP_ERROR_STREAM(getLogger(), ex.what());
328 setFailureResponse(planning_begin, res);
335 extractMotionPlanInfo(scene, req, plan_info);
339 RCLCPP_ERROR_STREAM(getLogger(), ex.what());
341 setFailureResponse(planning_begin, res);
345 trajectory_msgs::msg::JointTrajectory joint_trajectory;
348 plan(plan_info.
start_scene, req, plan_info, sampling_time, joint_trajectory);
352 RCLCPP_ERROR_STREAM(getLogger(), ex.what());
354 setFailureResponse(planning_begin, res);
358 setSuccessResponse(plan_info.
start_scene->getCurrentState(), req.group_name, joint_trajectory, planning_begin, res);
364 auto ps = scene->diff();
365 auto& start_state = ps->getCurrentStateNonConst();
373 for (
const auto* jm : start_state.
getRobotModel()->getJointModelGroup(req.group_name)->getActiveJointModels())
375 const auto& names = jm->getVariableNames();
376 for (std::size_t i = 0, j = jm->getFirstVariableIndex(); i < jm->getVariableCount(); ++i, ++j)
bool canSetStateFromIK(const std::string &tip) const
Representation of a robot's state. This includes position, velocity, acceleration and effort.
const RobotModelConstPtr & getRobotModel() const
Get the robot model this state is constructed for.
double * getVariablePositions()
Get a raw pointer to the positions of the variables stored in this state. Use carefully....
void update(bool force=false)
Update all transforms.
const moveit::core::LinkModel * getRigidlyConnectedParentLinkModel(const std::string &frame) const
Get the latest link upwards the kinematic tree which is only connected via fixed joints.
bool verifyPositionLimit(const std::string &joint_name, double joint_position) const
verify position limit of single joint
const cartesian_limits::Params & getCartesianLimits() const
Return the cartesian limits.
const JointLimitsContainer & getJointLimitContainer() const
Obtain the Joint Limits from the container.
Exception storing an moveit_msgs::msg::MoveItErrorCodes value.
virtual const moveit_msgs::msg::MoveItErrorCodes::_val_type & getErrorCode() const =0
This class is used to extract needed information from motion plan request.
MotionPlanInfo(const planning_scene::PlanningSceneConstPtr &scene, const planning_interface::MotionPlanRequest &req)
planning_scene::PlanningSceneConstPtr start_scene
std::map< std::string, double > start_joint_position
const moveit::core::RobotModelConstPtr robot_model_
static constexpr double MIN_SCALING_FACTOR
const pilz_industrial_motion_planner::LimitsContainer planner_limits_
const std::unique_ptr< rclcpp::Clock > clock_
void generate(const planning_scene::PlanningSceneConstPtr &scene, const planning_interface::MotionPlanRequest &req, planning_interface::MotionPlanResponse &res, double sampling_time=0.1)
generate robot trajectory with given sampling time
static constexpr double MAX_SCALING_FACTOR
std::unique_ptr< KDL::VelocityProfile > cartesianTrapVelocityProfile(double max_velocity_scaling_factor, double max_acceleration_scaling_factor, const std::unique_ptr< KDL::Path > &path) const
build cartesian velocity profile for the path
rclcpp::Logger getLogger()
bool robotStateMsgToRobotState(const Transforms &tf, const moveit_msgs::msg::RobotState &robot_state, RobotState &state, bool copy_attached_bodies=true)
Convert a robot state msg (with accompanying extra transforms) to a MoveIt robot state.
rclcpp::Logger getLogger(const std::string &name)
Creates a namespaced logger.
moveit_msgs::msg::MotionPlanRequest MotionPlanRequest
Response to a planning query.
moveit::core::MoveItErrorCode error_code
robot_trajectory::RobotTrajectoryPtr trajectory