collision_check.cpp
Go to the documentation of this file.
1 
26 #include <ros/console.h>
30 
32 
33 static const int MIN_KERNEL_WINDOW_SIZE = 3;
34 
41 static void applyKernelSmoothing(std::size_t window_size, const Eigen::VectorXd& data, Eigen::VectorXd& smoothed)
42 {
43  using namespace Eigen;
44 
45  // allocation
46  window_size = 2*(window_size/2) + 1;// forcing it into an odd number
47  smoothed.setZero(data.size());
48  VectorXd x_nneighbors = VectorXd::Zero(window_size);
49  VectorXd y_nneighbors = VectorXd::Zero(window_size);
50  VectorXd kernel_weights = VectorXd::Zero(window_size);
51 
52 
53  // indexing
54  int index_left, index_right;
55  std::size_t window_index_middle = window_size/2;
56 
57  // kernel function
58  //Epanechnikov(x,neighbors,lambda)
59  auto epanechnikov_function = [](double x_m,const VectorXd& neighbors,double lambda, VectorXd& weights )
60  {
61 
62  double t = 0;
63  for(int i = 0; i < neighbors.size(); i++)
64  {
65  t = std::abs(x_m - neighbors(i))/lambda;
66  if(t < 1)
67  {
68  weights(i) = 0.75f*(1 - std::pow(t,2));
69  }
70  else
71  {
72  weights(i) = 0;
73  }
74  }
75 
76  };
77 
78  for(int i = 0; i < data.size(); i++)
79  {
80  // middle term
81  x_nneighbors(window_index_middle) = i;
82  y_nneighbors(window_index_middle) = data(i);
83 
84  // grabbing neighbors
85  for(int j = 1; j <= window_size/2; j++)
86  {
87  index_left = i - j;
88  index_right = i + j;
89 
90  if(index_left < 0)
91  {
92  x_nneighbors(window_index_middle - j) = 0;
93  y_nneighbors(window_index_middle - j) = data(0);
94  }
95  else
96  {
97  x_nneighbors(window_index_middle - j) = index_left;
98  y_nneighbors(window_index_middle - j) = data(index_left);
99  }
100 
101  if(index_right > data.rows()-1)
102  {
103  x_nneighbors(window_index_middle + j) = data.rows()-1;
104  y_nneighbors(window_index_middle + j) = data(data.rows() - 1);
105  }
106  else
107  {
108  x_nneighbors(window_index_middle + j) = index_right;
109  y_nneighbors(window_index_middle + j) = data(index_right);
110  }
111 
112  }
113 
114  epanechnikov_function(i,x_nneighbors,window_size,kernel_weights);
115  smoothed(i) = (y_nneighbors.array()*kernel_weights.array()).sum()/kernel_weights.sum();
116  }
117 
118 
119 }
120 
121 namespace stomp_moveit
122 {
123 namespace cost_functions
124 {
125 
126 CollisionCheck::CollisionCheck():
127  name_("CollisionCheckPlugin"),
128  robot_state_(),
129  collision_penalty_(0.0)
130 {
131  // TODO Auto-generated constructor stub
132 
133 }
134 
135 CollisionCheck::~CollisionCheck()
136 {
137  // TODO Auto-generated destructor stub
138 }
139 
140 bool CollisionCheck::initialize(moveit::core::RobotModelConstPtr robot_model_ptr,
141  const std::string& group_name,XmlRpc::XmlRpcValue& config)
142 {
143  robot_model_ptr_ = robot_model_ptr;
144  group_name_ = group_name;
145  return configure(config);
146 }
147 
148 bool CollisionCheck::setMotionPlanRequest(const planning_scene::PlanningSceneConstPtr& planning_scene,
149  const moveit_msgs::MotionPlanRequest &req,
150  const stomp_core::StompConfiguration &config,
151  moveit_msgs::MoveItErrorCodes& error_code)
152 {
153  using namespace moveit::core;
154 
155  planning_scene_ = planning_scene;
156  plan_request_ = req;
157  error_code.val = moveit_msgs::MoveItErrorCodes::SUCCESS;
158 
159  // storing robot state
160  robot_state_.reset(new RobotState(robot_model_ptr_));
161  if(!robotStateMsgToRobotState(req.start_state,*robot_state_,true))
162  {
163  ROS_ERROR("%s Failed to get current robot state from request",getName().c_str());
164  return false;
165  }
166 
167  // copying into intermediate robot states
168  for(auto& rs : intermediate_coll_states_)
169  {
170  rs.reset(new RobotState(*robot_state_));
171  }
172 
173  // allocating arrays
174  raw_costs_ = Eigen::VectorXd::Zero(config.num_timesteps);
175 
176 
177  return true;
178 }
179 
180 bool CollisionCheck::computeCosts(const Eigen::MatrixXd& parameters,
181  std::size_t start_timestep,
182  std::size_t num_timesteps,
183  int iteration_number,
184  int rollout_number,
185  Eigen::VectorXd& costs,
186  bool& validity)
187 {
188 
189  using namespace moveit::core;
190  using namespace Eigen;
191 
192  if(!robot_state_)
193  {
194  ROS_ERROR("%s Robot State has not been updated",getName().c_str());
195  return false;
196  }
197 
199  typedef ContactMap::iterator ContactMapIterator;
200  typedef std::vector<collision_detection::Contact> ContactArray;
201 
202  // initializing result array
203  costs = Eigen::VectorXd::Zero(num_timesteps);
204 
205  // resetting array
206  raw_costs_.setZero();
207 
208  // collision
209  validity = true;
210 
211  // planning groups
212  const JointModelGroup* joint_group = robot_model_ptr_->getJointModelGroup(group_name_);
213 
214  if(parameters.cols()< (start_timestep + num_timesteps))
215  {
216  ROS_ERROR_STREAM("Size in the 'parameters' matrix is less than required");
217  return false;
218  }
219 
220  // check for collisions at each state
221  bool skip_next_check = false;
222  for (auto t=start_timestep; t<start_timestep + num_timesteps; ++t)
223  {
224  if(!skip_next_check)
225  {
226  robot_state_->setJointGroupPositions(joint_group,parameters.col(t));
227  robot_state_->update();
228 
229  if (planning_scene_->isStateColliding(*robot_state_, group_name_))
230  {
231  raw_costs_(t) = collision_penalty_;
232  validity = false;
233  }
234  }
235 
236  // check intermediate poses to the next position (skip the last one)
237  if(t < start_timestep + num_timesteps - 1)
238  {
239  if(!checkIntermediateCollisions(parameters.col(t),parameters.col(t+1),longest_valid_joint_move_))
240  {
241  raw_costs_(t) = collision_penalty_;
242  raw_costs_(t+1) = collision_penalty_;
243  validity = false;
244  skip_next_check = true;
245  }
246  else
247  {
248  skip_next_check = false;
249  }
250  }
251  }
252 
253  // applying kernel smoothing
254  if(!validity)
255  {
256 
257  if(kernel_window_percentage_> 1e-6)
258  {
259  int window_size = num_timesteps*kernel_window_percentage_;
260  window_size = window_size < MIN_KERNEL_WINDOW_SIZE ? MIN_KERNEL_WINDOW_SIZE : window_size;
261 
262  // adding minimum cost
263  intermediate_costs_slots_ = (raw_costs_.array() < collision_penalty_).cast<double>();
264  raw_costs_ += (raw_costs_.sum()/raw_costs_.size())*(intermediate_costs_slots_.matrix());
265 
266  // smoothing
267  applyKernelSmoothing(window_size,raw_costs_,costs);
268  }
269  else
270  {
271  costs = raw_costs_;
272  }
273 
274  }
275 
276  return true;
277 }
278 
279 bool CollisionCheck::checkIntermediateCollisions(const Eigen::VectorXd& start,
280  const Eigen::VectorXd& end,double longest_valid_joint_move)
281 {
282  Eigen::VectorXd diff = end - start;
283  int num_intermediate = std::ceil(((diff.cwiseAbs())/longest_valid_joint_move).maxCoeff()) - 1;
284  if(num_intermediate < 1.0)
285  {
286  // no interpolation needed
287  return true;
288  }
289 
290  // grabbing states
291  auto& start_state = intermediate_coll_states_[0];
292  auto& mid_state = intermediate_coll_states_[1];
293  auto& end_state = intermediate_coll_states_[2];
294 
295  if(!start_state || !mid_state || !end_state)
296  {
297  ROS_ERROR("%s intermediate states not initialized",getName().c_str());
298  return false;
299  }
300 
301  // setting up collision
302  const moveit::core::JointModelGroup* joint_group = robot_model_ptr_->getJointModelGroup(group_name_);
303  start_state->setJointGroupPositions(joint_group,start);
304  end_state->setJointGroupPositions(joint_group,end);
305 
306  // checking intermediate states
307  double dt = 1.0/static_cast<double>(num_intermediate);
308  double interval = 0.0;
309  for(std::size_t i = 1; i < num_intermediate;i++)
310  {
311  interval = i*dt;
312  start_state->interpolate(*end_state,interval,*mid_state) ;
313  if(planning_scene_->isStateColliding(*mid_state, group_name_))
314  {
315  return false;
316  }
317  }
318 
319  return true;
320 }
321 
322 bool CollisionCheck::configure(const XmlRpc::XmlRpcValue& config)
323 {
324 
325  // check parameter presence
326  auto members = {"cost_weight","collision_penalty","kernel_window_percentage"};
327  for(auto& m : members)
328  {
329  if(!config.hasMember(m))
330  {
331  ROS_ERROR("%s failed to find one or more required parameters",getName().c_str());
332  return false;
333  }
334  }
335 
336  try
337  {
338  // check parameter presence
339  auto members = {"cost_weight","collision_penalty","kernel_window_percentage", "longest_valid_joint_move"};
340  for(auto& m : members)
341  {
342  if(!config.hasMember(m))
343  {
344  ROS_ERROR("%s failed to find '%s' parameter",getName().c_str(),m);
345  return false;
346  }
347  }
348 
349  XmlRpc::XmlRpcValue c = config;
350  cost_weight_ = static_cast<double>(c["cost_weight"]);
351  collision_penalty_ = static_cast<double>(c["collision_penalty"]);
352  kernel_window_percentage_ = static_cast<double>(c["kernel_window_percentage"]);
353  longest_valid_joint_move_ = static_cast<double>(c["longest_valid_joint_move"]);
354  }
355  catch(XmlRpc::XmlRpcException& e)
356  {
357  ROS_ERROR("%s failed to parse configuration parameters",name_.c_str());
358  return false;
359  }
360 
361  return true;
362 }
363 
364 void CollisionCheck::done(bool success,int total_iterations,double final_cost,const Eigen::MatrixXd& parameters)
365 {
366  robot_state_.reset();
367 }
368 
369 } /* namespace cost_functions */
370 } /* namespace stomp_moveit */
This defines a cost function for collision checking.
IMETHOD Vector diff(const Vector &p_w_a, const Vector &p_w_b, double dt=1)
std::string getName(void *handle)
std::map< std::pair< std::string, std::string >, std::vector< Contact > > ContactMap
PLUGINLIB_EXPORT_CLASS(test_moveit_controller_manager::TestMoveItControllerManager, moveit_controller_manager::MoveItControllerManager)
bool robotStateMsgToRobotState(const Transforms &tf, const moveit_msgs::RobotState &robot_state, RobotState &state, bool copy_attached_bodies=true)
static void applyKernelSmoothing(std::size_t window_size, const Eigen::VectorXd &data, Eigen::VectorXd &smoothed)
Convenience method that propagates the cost value at center to the window to the adjacent points...
Assigns a cost value to each robot state by evaluating if the robot is in collision.
bool hasMember(const std::string &name) const
Assigns a cost value to each robot state by evaluating the minimum distance between the robot and the...
#define ROS_ERROR_STREAM(args)
#define ROS_ERROR(...)


stomp_moveit
Author(s): Jorge Nicho
autogenerated on Fri May 8 2020 03:35:47