Go to the documentation of this file.00001
00027 #include <stomp_moveit/cost_functions/obstacle_distance_gradient.h>
00028 #include <ros/console.h>
00029 #include <pluginlib/class_list_macros.h>
00030 #include <moveit/robot_state/conversions.h>
00031
00032 PLUGINLIB_EXPORT_CLASS(stomp_moveit::cost_functions::ObstacleDistanceGradient,stomp_moveit::cost_functions::StompCostFunction)
00033 static const double LONGEST_VALID_JOINT_MOVE = 0.01;
00034
00035 namespace stomp_moveit
00036 {
00037 namespace cost_functions
00038 {
00039
00040 ObstacleDistanceGradient::ObstacleDistanceGradient() :
00041 name_("ObstacleDistanceGradient"),
00042 robot_state_()
00043 {
00044
00045 }
00046
00047 ObstacleDistanceGradient::~ObstacleDistanceGradient()
00048 {
00049
00050 }
00051
00052 bool ObstacleDistanceGradient::initialize(moveit::core::RobotModelConstPtr robot_model_ptr,
00053 const std::string& group_name, XmlRpc::XmlRpcValue& config)
00054 {
00055 robot_model_ptr_ = robot_model_ptr;
00056 group_name_ = group_name;
00057 collision_request_.distance = true;
00058 collision_request_.group_name = group_name;
00059 collision_request_.cost = false;
00060 collision_request_.max_contacts = 1;
00061 collision_request_.max_contacts_per_pair = 1;
00062 collision_request_.contacts = false;
00063 collision_request_.verbose = false;
00064 return configure(config);
00065 }
00066
00067 bool ObstacleDistanceGradient::configure(const XmlRpc::XmlRpcValue& config)
00068 {
00069
00070 try
00071 {
00072
00073 auto members = {"cost_weight" ,"max_distance"};
00074 for(auto& m : members)
00075 {
00076 if(!config.hasMember(m))
00077 {
00078 ROS_ERROR("%s failed to find the '%s' parameter",getName().c_str(),m);
00079 return false;
00080 }
00081 }
00082
00083 XmlRpc::XmlRpcValue c = config;
00084 max_distance_ = static_cast<double>(c["max_distance"]);
00085 cost_weight_ = static_cast<double>(c["cost_weight"]);
00086 longest_valid_joint_move_ = c.hasMember("longest_valid_joint_move") ? static_cast<double>(c["longest_valid_joint_move"]):LONGEST_VALID_JOINT_MOVE;
00087
00088 if(!c.hasMember("longest_valid_joint_move"))
00089 {
00090 ROS_WARN("%s using default value for 'longest_valid_joint_move' of %f",getName().c_str(),longest_valid_joint_move_);
00091 }
00092 }
00093 catch(XmlRpc::XmlRpcException& e)
00094 {
00095 ROS_ERROR("%s failed to parse configuration parameters",name_.c_str());
00096 return false;
00097 }
00098
00099 return true;
00100 }
00101
00102 bool ObstacleDistanceGradient::setMotionPlanRequest(const planning_scene::PlanningSceneConstPtr& planning_scene,
00103 const moveit_msgs::MotionPlanRequest &req,
00104 const stomp_core::StompConfiguration &config,
00105 moveit_msgs::MoveItErrorCodes& error_code)
00106 {
00107 using namespace moveit::core;
00108
00109 planning_scene_ = planning_scene;
00110 plan_request_ = req;
00111 error_code.val = moveit_msgs::MoveItErrorCodes::SUCCESS;
00112
00113
00114 robot_state_.reset(new RobotState(robot_model_ptr_));
00115
00116 if(!robotStateMsgToRobotState(req.start_state,*robot_state_,true))
00117 {
00118 ROS_ERROR("%s Failed to get current robot state from request",getName().c_str());
00119 return false;
00120 }
00121
00122
00123 for(auto& rs : intermediate_coll_states_)
00124 {
00125 rs.reset(new RobotState(*robot_state_));
00126 }
00127
00128 return true;
00129 }
00130
00131 bool ObstacleDistanceGradient::computeCosts(const Eigen::MatrixXd& parameters, std::size_t start_timestep,
00132 std::size_t num_timesteps, int iteration_number, int rollout_number,
00133 Eigen::VectorXd& costs, bool& validity)
00134 {
00135
00136 if(!robot_state_)
00137 {
00138 ROS_ERROR("%s Robot State has not been updated",getName().c_str());
00139 return false;
00140 }
00141
00142
00143
00144
00145 costs = Eigen::VectorXd::Zero(num_timesteps);
00146 const moveit::core::JointModelGroup* joint_group = robot_model_ptr_->getJointModelGroup(group_name_);
00147
00148 if(parameters.cols()<start_timestep + num_timesteps)
00149 {
00150 ROS_ERROR_STREAM("Size in the 'parameters' matrix is less than required");
00151 return false;
00152 }
00153
00154
00155 double dist;
00156 bool skip_next_check = false;
00157 validity = true;
00158 for (auto t=start_timestep; t<start_timestep + num_timesteps; ++t)
00159 {
00160
00161 if(!skip_next_check)
00162 {
00163 collision_result_.clear();
00164 robot_state_->setJointGroupPositions(joint_group,parameters.col(t));
00165 robot_state_->update();
00166 collision_result_.distance = max_distance_;
00167
00168 planning_scene_->checkSelfCollision(collision_request_,collision_result_,*robot_state_,planning_scene_->getAllowedCollisionMatrix());
00169 dist = collision_result_.collision ? -1.0 :collision_result_.distance ;
00170
00171 if(dist >= max_distance_)
00172 {
00173 costs(t) = 0;
00174 }
00175 else if(dist < 0)
00176 {
00177 costs(t) = 1.0;
00178 validity = false;
00179 }
00180 else
00181 {
00182 costs(t) = (max_distance_ - dist)/max_distance_;
00183 }
00184 }
00185
00186 skip_next_check = false;
00187
00188
00189 if(t < start_timestep + num_timesteps - 1)
00190 {
00191 if(!checkIntermediateCollisions(parameters.col(t),parameters.col(t+1),longest_valid_joint_move_))
00192 {
00193 costs(t) = 1.0;
00194 costs(t+1) = 1.0;
00195 validity = false;
00196 skip_next_check = true;
00197 }
00198 else
00199 {
00200 skip_next_check = false;
00201 }
00202 }
00203
00204 }
00205
00206 return true;
00207 }
00208
00209 bool ObstacleDistanceGradient::checkIntermediateCollisions(const Eigen::VectorXd& start,
00210 const Eigen::VectorXd& end,double longest_valid_joint_move)
00211 {
00212 Eigen::VectorXd diff = end - start;
00213 int num_intermediate = std::ceil(((diff.cwiseAbs())/longest_valid_joint_move).maxCoeff()) - 1;
00214 if(num_intermediate < 1.0)
00215 {
00216
00217 return true;
00218 }
00219
00220
00221 auto& start_state = intermediate_coll_states_[0];
00222 auto& mid_state = intermediate_coll_states_[1];
00223 auto& end_state = intermediate_coll_states_[2];
00224
00225 if(!start_state || !mid_state || !end_state)
00226 {
00227 ROS_ERROR("%s intermediate states not initialized",getName().c_str());
00228 return false;
00229 }
00230
00231
00232 auto req = collision_request_;
00233 req.distance = false;
00234 collision_detection::CollisionResult res;
00235 const moveit::core::JointModelGroup* joint_group = robot_model_ptr_->getJointModelGroup(group_name_);
00236 start_state->setJointGroupPositions(joint_group,start);
00237 end_state->setJointGroupPositions(joint_group,end);
00238
00239
00240 double dt = 1.0/static_cast<double>(num_intermediate);
00241 double interval = 0.0;
00242 for(std::size_t i = 1; i < num_intermediate;i++)
00243 {
00244 interval = i*dt;
00245 start_state->interpolate(*end_state,interval,*mid_state) ;
00246 if(planning_scene_->isStateColliding(*mid_state))
00247 {
00248 return false;
00249 }
00250 }
00251
00252 return true;
00253 }
00254
00255 void ObstacleDistanceGradient::done(bool success,int total_iterations,double final_cost,const Eigen::MatrixXd& parameters)
00256 {
00257 robot_state_.reset();
00258 }
00259
00260 }
00261 }