30 #include <stomp_core/utils.h> 35 static const std::string DEBUG_NS =
"stomp_planner";
36 static const std::string DESCRIPTION =
"STOMP";
37 static const double TIMEOUT_INTERVAL = 0.5;
38 static int const IK_ATTEMPTS = 4;
39 static int const IK_TIMEOUT = 0.005;
40 const static double MAX_START_DISTANCE_THRESH = 0.5;
64 if (config.
hasMember(
"control_cost_weight"))
67 if (config.
hasMember(
"initialization_method"))
71 stomp_config.
num_timesteps = static_cast<int>(config[
"num_timesteps"]);
74 stomp_config.
delta_t = static_cast<double>(config[
"delta_t"]);
77 stomp_config.
num_iterations = static_cast<int>(config[
"num_iterations"]);
79 if (config.
hasMember(
"num_iterations_after_valid"))
83 stomp_config.
max_rollouts = static_cast<int>(config[
"max_rollouts"]);
86 stomp_config.
num_rollouts = static_cast<int>(config[
"num_rollouts"]);
88 if (config.
hasMember(
"exponentiated_cost_sensitivity"))
95 ROS_ERROR(
"Planning Group %s has no active joints",group->
getName().c_str());
106 const moveit::core::RobotModelConstPtr& model):
107 PlanningContext(DESCRIPTION,group),
111 ph_(new
ros::NodeHandle(
"~"))
116 StompPlanner::~StompPlanner()
132 task_config = config_[
"task"];
135 if(!robot_model_->hasJointModelGroup(
group_))
137 std::string msg =
"Stomp Planning Group '" +
group_ +
"' was not found";
139 throw std::logic_error(msg);
143 if(!config_.
hasMember(
"optimization") || !
parseConfig(config_[
"optimization" ],robot_model_->getJointModelGroup(
group_),stomp_config_))
145 std::string msg =
"Stomp 'optimization' parameter for group '" +
group_ +
"' failed to load";
147 throw std::logic_error(msg);
154 throw std::logic_error(
"Stomp Planner failed to load configuration for group '" +
group_+
"'; " + e.
getMessage());
163 bool success =
solve(detailed_res);
183 res.
error_code_.val = moveit_msgs::MoveItErrorCodes::SUCCESS;
186 bool success =
false;
189 Eigen::MatrixXd parameters;
190 bool planning_success;
193 auto config_copy = stomp_config_;
196 Eigen::MatrixXd initial_parameters;
203 "%s allowed planning time %f is less than the minimum planning time value of %f",
205 std::atomic<bool> terminating(
false);
220 ROS_INFO(
"%s Seeding trajectory from MotionPlanRequest",
getName().c_str());
223 config_copy.num_timesteps = initial_parameters.cols();
228 res.
error_code_.val = moveit_msgs::MoveItErrorCodes::FAILURE;
232 stomp_->setConfig(config_copy);
233 planning_success = stomp_->solve(initial_parameters, parameters);
239 Eigen::VectorXd start, goal;
242 res.
error_code_.val = moveit_msgs::MoveItErrorCodes::INVALID_MOTION_PLAN;
249 res.
error_code_.val = moveit_msgs::MoveItErrorCodes::FAILURE;
253 stomp_->setConfig(config_copy);
254 planning_success = stomp_->solve(start,goal,parameters);
258 timeout_timer.
stop();
265 res.
error_code_.val = moveit_msgs::MoveItErrorCodes::PLANNING_FAILED;
274 res.
trajectory_.back()->setRobotTrajectoryMsg( robot_state,trajectory);
278 res.
error_code_.val = moveit_msgs::MoveItErrorCodes::PLANNING_FAILED;
285 res.
error_code_.val = moveit_msgs::MoveItErrorCodes::PLANNING_FAILED;
299 using namespace utils::kinematics;
300 using namespace utils::polynomial;
302 auto within_tolerance = [&](
const Eigen::VectorXd& a,
const Eigen::VectorXd& b,
double tol) ->
bool 304 double dist = (a - b).cwiseAbs().sum();
308 trajectory_msgs::JointTrajectory traj;
317 ROS_ERROR(
"%s Failed to created seed parameters from joint trajectory",
getName().c_str());
321 if(parameters.cols()<= 2)
323 ROS_ERROR(
"%s Found less than 3 points in seed trajectory",
getName().c_str());
334 const auto& tool_link = group->getLinkModelNames().back();
335 Eigen::VectorXd start, goal;
343 ROS_ERROR(
"Start state is out of bounds");
348 start.resize(joint_names.size());
349 for(
auto j = 0u; j < joint_names.size(); j++)
354 if(within_tolerance(parameters.leftCols(1),start,MAX_START_DISTANCE_THRESH))
356 parameters.leftCols(1) = start;
360 ROS_ERROR(
"%s Start State is in discrepancy with the seed trajectory",
getName().c_str());
371 bool found_goal =
false;
372 goal = parameters.rightCols(1);
373 for(
auto& gc :
request_.goal_constraints)
375 if(!gc.joint_constraints.empty())
378 for(
auto j = 0u; j < gc.joint_constraints.size() ; j++)
380 auto jc = gc.joint_constraints[j];
387 ROS_ERROR(
"%s Requested Goal joint pose is out of bounds",
getName().c_str());
391 for(
auto j = 0u; j < joint_names.size(); j++)
404 if(!tool_constraints.is_initialized())
406 ROS_WARN(
"Cartesian Goal could not be created from provided constraints");
411 Eigen::VectorXd solution;
412 ik_solver_->setKinematicState(state);
413 if(ik_solver_->solve(goal,tool_constraints.get(),solution))
421 ROS_ERROR(
"A valid ik solution for the given Cartesian constraints was not found ");
430 if(within_tolerance(parameters.rightCols(1),goal,MAX_START_DISTANCE_THRESH))
432 parameters.rightCols(1) = goal;
436 ROS_ERROR(
"%s Goal in seed is too far away from requested goal constraints",
getName().c_str());
442 ROS_ERROR(
"%s requested goal constraint was invalid or unreachable, comparison with goal in seed isn't possible",
getName().c_str());
446 if(!applyPolynomialSmoothing(robot_model_,
group_,parameters,5,1e-5))
455 trajectory_msgs::JointTrajectory& trajectory)
458 trajectory.joint_names = robot_model_->getJointModelGroup(
group_)->getActiveJointModelNames();
459 trajectory.points.clear();
460 trajectory.points.resize(parameters.cols());
461 std::vector<double> vals(parameters.rows());
462 std::vector<double> zeros(parameters.rows(),0.0);
463 for(
auto t = 0u; t < parameters.cols() ; t++)
465 Eigen::VectorXd::Map(&vals[0],vals.size()) = parameters.col(t);
466 trajectory.points[t].positions = vals;
467 trajectory.points[t].velocities = zeros;
468 trajectory.points[t].accelerations = zeros;
483 moveit_msgs::RobotTrajectory robot_traj_msgs;
487 trajectory = robot_traj_msgs.joint_trajectory;
499 const auto dof = traj.joint_names.size();
500 const auto timesteps = traj.points.size();
502 Eigen::MatrixXd mat (dof, timesteps);
506 for (
size_t joint = 0; joint < dof; ++joint)
508 mat(joint,
step) = traj.points[
step].positions[joint];
518 if (req.trajectory_constraints.constraints.empty())
521 const auto* joint_group = robot_model_->getJointModelGroup(
group_);
522 const auto& names = joint_group->getActiveJointModelNames();
523 const auto dof = names.size();
525 const auto& constraints = req.trajectory_constraints.constraints;
527 for (
size_t i = 0; i < constraints.size(); ++i)
529 auto n = constraints[i].joint_constraints.size();
532 ROS_WARN(
"Seed trajectory index %lu does not have %lu constraints (has %lu instead).", i, dof, n);
536 trajectory_msgs::JointTrajectoryPoint joint_pt;
538 for (
size_t j = 0; j < constraints[i].joint_constraints.size(); ++j)
540 const auto& c = constraints[i].joint_constraints[j];
541 if (c.joint_name != names[j])
543 ROS_WARN(
"Seed trajectory (index %lu, joint %lu) joint name '%s' does not match expected name '%s'",
544 i, j, c.joint_name.c_str(), names[j].c_str());
547 joint_pt.positions.push_back(c.position);
550 seed.points.push_back(joint_pt);
553 seed.joint_names = names;
559 moveit_msgs::TrajectoryConstraints res;
561 const auto dof = seed.joint_names.size();
563 for (
size_t i = 0; i < seed.points.size(); ++i)
565 moveit_msgs::Constraints c;
567 if (seed.points[i].positions.size() != dof)
568 throw std::runtime_error(
"All trajectory position fields must have same dimensions as joint_names");
570 for (
size_t j = 0; j < dof; ++j)
572 moveit_msgs::JointConstraint jc;
573 jc.joint_name = seed.joint_names[j];
574 jc.position = seed.points[i].positions[j];
576 c.joint_constraints.push_back(jc);
579 res.constraints.push_back(std::move(c));
588 using namespace utils::kinematics;
590 RobotStatePtr state(
new RobotState(robot_model_));
593 bool found_goal =
false;
598 state->setToDefaultValues();
601 ROS_ERROR(
"%s Failed to extract start state from MotionPlanRequest",
getName().c_str());
606 const std::vector<std::string> joint_names= state->getJointModelGroup(
group_)->getActiveJointModelNames();
607 start.resize(joint_names.size());
608 goal.resize(joint_names.size());
610 if(!state->satisfiesBounds(state->getJointModelGroup(
group_)))
616 for(
auto j = 0u; j < joint_names.size(); j++)
618 start(j) = state->getVariablePosition(joint_names[j]);
622 if(
request_.goal_constraints.empty())
629 for(
const auto& gc :
request_.goal_constraints)
633 if(!gc.joint_constraints.empty())
637 for(
auto j = 0u; j < gc.joint_constraints.size() ; j++)
639 auto jc = gc.joint_constraints[j];
640 state->setVariablePosition(jc.joint_name,jc.position);
644 if(!state->satisfiesBounds(state->getJointModelGroup(
group_)))
646 ROS_ERROR(
"%s Requested Goal joint pose is out of bounds",
getName().c_str());
653 for(
auto j = 0u; j < joint_names.size(); j++)
655 goal(j) = state->getVariablePosition(joint_names[j]);
664 state->updateLinkTransforms();
665 Eigen::Affine3d start_tool_pose = state->getGlobalLinkTransform(tool_link);
667 if(!tool_constraints.is_initialized())
669 ROS_WARN(
"Cartesian Goal could not be created from provided constraints");
675 Eigen::VectorXd solution;
676 Eigen::VectorXd seed = start;
677 ik_solver_->setKinematicState(*state);
678 if(ik_solver_->solve(seed,tool_constraints.get(),solution))
686 ROS_ERROR(
"A valid ik solution for the given Cartesian constraints was not found ");
692 ROS_ERROR_COND(!found_goal,
"%s was unable to retrieve the goal from the MotionPlanRequest",
getName().c_str());
697 ROS_ERROR(
"Failure retrieving start or goal state joint values from request %s", e.what());
710 ROS_ERROR(
"STOMP: Unsupported planning group '%s' requested", req.group_name.c_str());
715 if (req.goal_constraints.size() != 1)
717 ROS_ERROR(
"STOMP: Can only handle a single goal region.");
722 const auto& gc = req.goal_constraints[0];
723 if ((gc.joint_constraints.size() == 0) &&
726 ROS_ERROR(
"STOMP couldn't find either a joint or cartesian goal.");
737 if(!stomp_->cancel())
755 if(!nh.
getParam(param, stomp_config))
757 ROS_ERROR(
"The 'stomp' configuration parameter was not found");
762 std::string group_name;
767 group_name =
static_cast<std::string
>(v->second[
"group_name"]);
768 config.insert(std::make_pair(group_name, v->second));
774 ROS_ERROR(
"Unable to parse ROS parameter:\n %s",stomp_config.
toXml().c_str());
const std::string & getMessage() const
robot_trajectory::RobotTrajectoryPtr trajectory_
#define ROS_DEBUG_STREAM_NAMED(name, args)
ValueStruct::iterator iterator
std::vector< std::string > description_
const Eigen::Affine3d & getGlobalLinkTransform(const std::string &link_name)
virtual bool solve(planning_interface::MotionPlanResponse &res) override
Solve the motion planning problem as defined in the motion request passed before hand.
This defines the stomp planner for MoveIt.
const JointModelGroup * getJointModelGroup(const std::string &group) const
const std::vector< std::string > & getLinkModelNames() const
const std::string & getName() const
double control_cost_weight
void setup()
planner setup
virtual void clear() override
Clears results from previous plan.
double exponentiated_cost_sensitivity
#define ROS_ERROR_COND(cond,...)
const planning_scene::PlanningSceneConstPtr & getPlanningScene() const
moveit_msgs::MoveItErrorCodes error_code_
static moveit_msgs::TrajectoryConstraints encodeSeedTrajectory(const trajectory_msgs::JointTrajectory &seed)
From a trajectory_msgs::JointTrajectory create a set of trajectory constraints that stomp can use lat...
bool parseConfig(XmlRpc::XmlRpcValue config, const moveit::core::JointModelGroup *group, stomp_core::StompConfiguration &stomp_config)
Parses a XmlRpcValue and populates a StompComfiguration structure.
virtual bool terminate() override
Thread-safe method that request early termination, if a solve() function is currently computing plans...
void getRobotTrajectoryMsg(moveit_msgs::RobotTrajectory &trajectory) const
boost::optional< moveit_msgs::Constraints > curateCartesianConstraints(const moveit_msgs::Constraints &c, const Eigen::Affine3d &ref_pose, double default_pos_tol=0.0005, double default_rot_tol=M_PI)
Populates the missing parts of a Cartesian constraints in order to provide a constraint that can be u...
double dist(const T &p1, const T &p2)
std::string toXml() const
planning_scene::PlanningSceneConstPtr planning_scene_
moveit_msgs::MoveItErrorCodes error_code_
bool getSeedParameters(Eigen::MatrixXd ¶meters) const
This function 1) gets the seed trajectory from the active motion plan request, 2) checks to see if th...
robot_trajectory::RobotTrajectory trajectory(rmodel,"right_arm")
bool canServiceRequest(const moveit_msgs::MotionPlanRequest &req) const
Checks some conditions to determine whether it is able to plan given for this planning request...
const std::vector< std::string > & getActiveJointModelNames() const
This defines kinematic related utilities.
std::vector< double > processing_time_
bool robotStateMsgToRobotState(const Transforms &tf, const moveit_msgs::RobotState &robot_state, RobotState &state, bool copy_attached_bodies=true)
bool jointTrajectorytoParameters(const trajectory_msgs::JointTrajectory &traj, Eigen::MatrixXd ¶meters) const
Converts from a joint trajectory to an Eigen Matrix.
void setPlanningScene(const planning_scene::PlanningSceneConstPtr &planning_scene)
Loads and manages the STOMP plugins during the planning process.
bool extractSeedTrajectory(const moveit_msgs::MotionPlanRequest &req, trajectory_msgs::JointTrajectory &seed) const
Populates a seed joint trajectory from the 'trajectory_constraints' moveit_msgs::Constraints[] array...
bool satisfiesBounds(double margin=0.0) const
const std::string & getGroupName() const
bool isCartesianConstraints(const moveit_msgs::Constraints &c)
Checks if the constraint structured contains valid data from which a proper cartesian constraint can ...
bool hasMember(const std::string &name) const
int initialization_method
#define ROS_INFO_STREAM(args)
std::vector< robot_trajectory::RobotTrajectoryPtr > trajectory_
static bool getConfigData(ros::NodeHandle &nh, std::map< std::string, XmlRpc::XmlRpcValue > &config, std::string param=std::string("stomp"))
Convenience method to load extract the parameters for each supported planning group.
const std::string & getName() const
bool computeTimeStamps(robot_trajectory::RobotTrajectory &trajectory, const double max_velocity_scaling_factor=1.0, const double max_acceleration_scaling_factor=1.0) const
bool getParam(const std::string &key, std::string &s) const
bool parametersToJointTrajectory(const Eigen::MatrixXd ¶meters, trajectory_msgs::JointTrajectory &traj)
Converts from an Eigen Matrix to to a joint trajectory.
#define ROS_WARN_COND(cond,...)
bool getStartAndGoal(Eigen::VectorXd &start, Eigen::VectorXd &goal)
Gets the start and goal joint values from the motion plan request passed.
const std::vector< const JointModel * > & getActiveJointModels() const
void updateLinkTransforms()
double getVariablePosition(const std::string &variable) const
#define ROS_ERROR_STREAM(args)
void setVariablePosition(const std::string &variable, double value)
MotionPlanRequest request_
void setRobotTrajectoryMsg(const robot_state::RobotState &reference_state, const trajectory_msgs::JointTrajectory &trajectory)
int num_iterations_after_valid