trajectory_generator_lin.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2018 Pilz GmbH & Co. KG
3  *
4  * This program is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU Lesser General Public License as published by
6  * the Free Software Foundation, either version 3 of the License, or
7  * (at your option) any later version.
8 
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU Lesser General Public License for more details.
13 
14  * You should have received a copy of the GNU Lesser General Public License
15  * along with this program. If not, see <http://www.gnu.org/licenses/>.
16  */
17 
19 
20 #include <ros/ros.h>
21 #include <time.h>
22 #include <cassert>
23 #include <sstream>
24 
27 
29 
30 #include <kdl/path_line.hpp>
31 #include <kdl/utilities/error.h>
32 #include <kdl/trajectory_segment.hpp>
33 
34 namespace pilz {
35 
36 TrajectoryGeneratorLIN::TrajectoryGeneratorLIN(const moveit::core::RobotModelConstPtr &robot_model,
37  const LimitsContainer &planner_limits)
38  :TrajectoryGenerator::TrajectoryGenerator(robot_model, planner_limits)
39 {
41  {
42  ROS_ERROR("Cartesian limits not set for LIN trajectory generator.");
43  throw TrajectoryGeneratorInvalidLimitsException("Cartesian limits are not fully set for LIN trajectory generator.");
44  }
45 }
46 
48 {
49  ROS_DEBUG("Extract necessary information from motion plan request.");
50 
51  info.group_name = req.group_name;
52  std::string frame_id {robot_model_->getModelFrame()};
53 
54  // goal given in joint space
55  if(!req.goal_constraints.front().joint_constraints.empty())
56  {
57  info.link_name = robot_model_->getJointModelGroup(req.group_name)->getSolverInstance()->getTipFrame();
58 
59  if(req.goal_constraints.front().joint_constraints.size() !=
60  robot_model_->getJointModelGroup(req.group_name)->getActiveJointModelNames().size())
61  {
62  std::ostringstream os;
63  os << "Number of joints in goal does not match number of joints of group (Number joints goal: "
64  << req.goal_constraints.front().joint_constraints.size() << " | Number of joints of group: "
65  << robot_model_->getJointModelGroup(req.group_name)->getActiveJointModelNames().size() << ")";
66  throw JointNumberMismatch(os.str());
67  }
68 
69  for(const auto &joint_item : req.goal_constraints.front().joint_constraints)
70  {
71  info.goal_joint_position[joint_item.joint_name] = joint_item.position;
72  }
73 
74  // Ignored return value because at this point the function should always return 'true'.
76  }
77  // goal given in Cartesian space
78  else
79  {
80  info.link_name = req.goal_constraints.front().position_constraints.front().link_name;
81  if(req.goal_constraints.front().position_constraints.front().header.frame_id.empty() ||
82  req.goal_constraints.front().orientation_constraints.front().header.frame_id.empty())
83  {
84  ROS_WARN("Frame id is not set in position/orientation constraints of goal. Use model frame as default");
85  frame_id = robot_model_->getModelFrame();
86  }
87  else
88  {
89  frame_id = req.goal_constraints.front().position_constraints.front().header.frame_id;
90  }
91  geometry_msgs::Pose goal_pose_msg;
92  goal_pose_msg.position = req.goal_constraints.front().position_constraints.front()
93  .constraint_region.primitive_poses.front().position;
94  goal_pose_msg.orientation = req.goal_constraints.front().orientation_constraints.front().orientation;
95  normalizeQuaternion(goal_pose_msg.orientation);
96  tf::poseMsgToEigen(goal_pose_msg, info.goal_pose);
97  }
98 
99  assert(req.start_state.joint_state.name.size() == req.start_state.joint_state.position.size());
100  for(const auto& joint_name : robot_model_->getJointModelGroup(req.group_name)->getActiveJointModelNames())
101  {
102  auto it {std::find(req.start_state.joint_state.name.cbegin(), req.start_state.joint_state.name.cend(), joint_name)};
103  if (it == req.start_state.joint_state.name.cend())
104  {
105  std::ostringstream os;
106  os << "Could not find joint \"" << joint_name << "\" of group \"" << req.group_name << "\" in start state of request";
107  throw LinJointMissingInStartState(os.str());
108  }
109  size_t index = it - req.start_state.joint_state.name.cbegin();
110  info.start_joint_position[joint_name] = req.start_state.joint_state.position[index];
111  }
112 
113  // Ignored return value because at this point the function should always return 'true'.
115 
116  //check goal pose ik before Cartesian motion plan starts
117  std::map<std::string, double> ik_solution;
119  info.group_name,
120  info.link_name,
121  info.goal_pose,
122  frame_id,
124  ik_solution))
125  {
126  std::ostringstream os;
127  os << "Failed to compute inverse kinematics for link: " << info.link_name << " of goal pose";
128  throw LinInverseForGoalIncalculable(os.str());
129  }
130 }
131 
133  const MotionPlanInfo& plan_info,
134  const double& sampling_time,
135  trajectory_msgs::JointTrajectory& joint_trajectory)
136 {
137  // create Cartesian path for lin
138  std::unique_ptr<KDL::Path> path( setPathLIN(plan_info.start_pose, plan_info.goal_pose) );
139 
140  // create velocity profile
141  std::unique_ptr<KDL::VelocityProfile> vp(cartesianTrapVelocityProfile(req.max_velocity_scaling_factor, req.max_acceleration_scaling_factor, path));
142 
143  // combine path and velocity profile into Cartesian trajectory
144  // with the third parameter set to false, KDL::Trajectory_Segment does not take
145  // the ownship of Path and Velocity Profile
146  KDL::Trajectory_Segment cart_trajectory(path.get(), vp.get(), false);
147 
148  moveit_msgs::MoveItErrorCodes error_code;
149  // sample the Cartesian trajectory and compute joint trajectory using inverse kinematics
152  cart_trajectory,
153  plan_info.group_name,
154  plan_info.link_name,
155  plan_info.start_joint_position,
156  sampling_time,
157  joint_trajectory,
158  error_code))
159  {
160  std::ostringstream os;
161  os << "Failed to generate valid joint trajectory from the Cartesian path";
162  throw LinTrajectoryConversionFailure(os.str(), error_code.val);
163  }
164 }
165 
166 std::unique_ptr<KDL::Path> TrajectoryGeneratorLIN::setPathLIN(const Eigen::Affine3d& start_pose,
167  const Eigen::Affine3d& goal_pose) const
168 {
169  ROS_DEBUG("Set Cartesian path for LIN command.");
170 
171  KDL::Frame kdl_start_pose, kdl_goal_pose;
172  tf::transformEigenToKDL(start_pose, kdl_start_pose);
173  tf::transformEigenToKDL(goal_pose, kdl_goal_pose);
177 
178  return std::unique_ptr<KDL::Path>(new KDL::Path_Line(kdl_start_pose,
179  kdl_goal_pose,
180  rot_interpo,
181  eqradius,
182  true));
183 
184 }
185 
186 } // namespace pilz
187 
std::map< std::string, double > start_joint_position
TrajectoryGeneratorLIN(const robot_model::RobotModelConstPtr &robot_model, const pilz::LimitsContainer &planner_limits)
Constructor of LIN Trajectory Generator.
std::map< std::string, double > goal_joint_position
Base class of trajectory generators.
bool computePoseIK(const robot_model::RobotModelConstPtr &robot_model, const std::string &group_name, const std::string &link_name, const Eigen::Affine3d &pose, const std::string &frame_id, const std::map< std::string, double > &seed, std::map< std::string, double > &solution, bool check_self_collision=true, int max_attempt=10, const double timeout=0.1)
compute the inverse kinematics of a given pose, also check robot self collision
double getMaxTranslationalVelocity() const
Return the maximal translational velocity [m/s], 0 if nothing was set.
void poseMsgToEigen(const geometry_msgs::Pose &m, Eigen::Affine3d &e)
const CartesianLimit & getCartesianLimits() const
Return the cartesian limits.
#define ROS_WARN(...)
void transformEigenToKDL(const Eigen::Affine3d &e, KDL::Frame &k)
const robot_model::RobotModelConstPtr robot_model_
virtual void plan(const planning_interface::MotionPlanRequest &req, const MotionPlanInfo &plan_info, const double &sampling_time, trajectory_msgs::JointTrajectory &joint_trajectory) override
unsigned int index
std::unique_ptr< KDL::Path > setPathLIN(const Eigen::Affine3d &start_pose, const Eigen::Affine3d &goal_pose) const
construct a KDL::Path object for a Cartesian straight line
const pilz::LimitsContainer planner_limits_
bool computeLinkFK(const robot_model::RobotModelConstPtr &robot_model, const std::string &link_name, const std::map< std::string, double > &joint_state, Eigen::Affine3d &pose)
compute the pose of a link at give robot state
const JointLimitsContainer & getJointLimitContainer() const
Obtain the Joint Limits from the container.
double getMaxRotationalVelocity() const
Return the maximal rotational velocity [rad/s], 0 if nothing was set.
This class combines CartesianLimit and JointLimits into on single class.
moveit_msgs::MotionPlanRequest MotionPlanRequest
std::unique_ptr< KDL::VelocityProfile > cartesianTrapVelocityProfile(const double &max_velocity_scaling_factor, const double &max_acceleration_scaling_factor, const std::unique_ptr< KDL::Path > &path) const
build cartesian velocity profile for the path
This class is used to extract needed information from motion plan request.
void normalizeQuaternion(geometry_msgs::Quaternion &quat)
bool generateJointTrajectory(const robot_model::RobotModelConstPtr &robot_model, 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, const double &sampling_time, trajectory_msgs::JointTrajectory &joint_trajectory, moveit_msgs::MoveItErrorCodes &error_code, bool check_self_collision=false)
Generate joint trajectory from a KDL Cartesian trajectory.
#define ROS_ERROR(...)
virtual void extractMotionPlanInfo(const planning_interface::MotionPlanRequest &req, MotionPlanInfo &info) const finaloverride
Extract needed information from a motion plan request in order to simplify further usages...
bool hasFullCartesianLimits() const
Return if this LimitsContainer has defined cartesian limits.
#define ROS_DEBUG(...)


pilz_trajectory_generation
Author(s):
autogenerated on Mon Apr 6 2020 03:17:33