footstep_planner_environment.cpp
Go to the documentation of this file.
2 
3 #include <vigir_footstep_planning_plugins/plugin_aggregators/state_generator.h>
4 
5 
6 
8 {
9 FootstepPlannerEnvironment::FootstepPlannerEnvironment(const EnvironmentParameters& params, const FootPoseTransformer& foot_pose_transformer, boost::function<void (msgs::PlanningFeedback)>& feedback_cb)
10  : DiscreteSpaceInformation()
11  , foot_pose_transformer(foot_pose_transformer)
12  , feedback_cb(feedback_cb)
13  , params(params)
14  , ivNumExpandedStates(0)
15  , frame_id("/world")
16  , last_feedback_flush(ros::Time::now())
17 {
18  state_space.reset(new StateSpace(params, StateID2IndexMapping));
19 }
20 
22 {
23 }
24 
26 {
27  this->frame_id = frame_id;
28 }
29 
31 {
32  // check if start and goal have been set
33  assert(state_space->ivIdGoalFootLeft != -1 && state_space->ivIdGoalFootRight != -1);
34  assert(state_space->ivIdStartFootLeft != -1 && state_space->ivIdStartFootRight != -1);
35 
36  if (!state_space->ivHeuristicExpired)
37  return;
38 
39  ROS_INFO("Updating the heuristic values.");
40 
41 // if (state_space->ivHeuristicPtr->getHeuristicType() == Heuristic::PATH_STEP_COST_HEURISTIC)
42 // {
43 // boost::shared_ptr<PathCostHeuristic> h =
44 // boost::dynamic_pointer_cast<PathCostHeuristic>(
45 // state_space->ivHeuristicPtr);
46 // MDPConfig MDPCfg;
47 // InitializeMDPCfg(&MDPCfg);
48 // const PlanningState* start = state_space->ivStateId2State[MDPCfg.startstateid];
49 // const PlanningState* goal = state_space->ivStateId2State[MDPCfg.goalstateid];
50 
51 // // NOTE: start/goal state are set to left leg
52 // bool success;
53 // if (params.forward_search)
54 // success = h->calculateDistances(*start, *goal);
55 // else
56 // success = h->calculateDistances(*goal, *start);
57 // if (!success)
58 // {
59 // ROS_ERROR("Failed to calculate path cost heuristic.");
60 // exit(1);
61 // }
62 // }
63 
64  ROS_DEBUG("Finished updating the heuristic values.");
65  state_space->ivHeuristicExpired = false;
66 }
67 
69 {
70  state_space->reset();
71 
72  ivExpandedStates.clear();
74 
75  visited_steps.clear();
77 }
78 
79 void FootstepPlannerEnvironment::stateExpanded(const PlanningState& s)
80 {
81  ivExpandedStates.insert(std::pair<int,int>(s.getX(), s.getY()));
83 
84  if (!feedback_cb.empty())
85  {
86  if (((ros::Time::now() - last_feedback_flush).toSec()) > 1.0/params.feedback_rate)
87  {
88  // send recent visited states
89  msgs::PlanningFeedback feedback;
90  feedback.header.stamp = ros::Time::now();
91  feedback.header.frame_id = frame_id;
92  feedback.visited_steps = visited_steps;
93 
94  // build current plan
95  const PlanningState* state = &s;
96  msgs::Step step;
97  step.header = feedback.header;
98  step.foot.header = feedback.header;
99 
100  feedback.current_step_plan.header = feedback.header;
101 
102  while (state)
103  {
104  state->getState().getStep(step);
105  feedback.current_step_plan.steps.push_back(step);
106 
107  if (params.forward_search)
108  {
109  if (!state->getPredState())
110  break;
111  state = state->getPredState();
112  }
113  else
114  {
115  if (!state->getSuccState())
116  break;
117  state = state->getSuccState();
118  }
119  }
120 
121  // transform step plan
122  foot_pose_transformer.transformToRobotFrame(feedback.current_step_plan);
123 
124  // publish feedback
125  feedback_cb(feedback);
126 
127  visited_steps.clear();
129  }
130  }
131 }
132 
133 void FootstepPlannerEnvironment::stateVisited(const PlanningState& s)
134 {
135  if (!feedback_cb.empty())
136  {
137  msgs::Step step;
138  s.getState().getStep(step);
139  step.header.stamp = ros::Time::now();
140  step.header.frame_id = frame_id;
141  step.foot.header = step.header;
142  visited_steps.push_back(step);
143  }
144 }
145 
146 int FootstepPlannerEnvironment::GetFromToHeuristic(int FromStateID, int ToStateID)
147 {
148  assert(FromStateID >= 0 && (unsigned int) FromStateID < state_space->ivStateId2State.size());
149  assert(ToStateID >= 0 && (unsigned int) ToStateID < state_space->ivStateId2State.size());
150 
151  if ((FromStateID == state_space->ivIdGoalFootLeft && ToStateID == state_space->ivIdGoalFootRight)
152  || (FromStateID == state_space->ivIdGoalFootRight && ToStateID == state_space->ivIdGoalFootLeft)){
153  return 0;
154  }
155 
156  return GetFromToHeuristic(*(state_space->ivStateId2State[FromStateID]), *(state_space->ivStateId2State[ToStateID]),
157  *(state_space->ivStateId2State[state_space->ivIdPlanningStart]), *(state_space->ivStateId2State[state_space->ivIdPlanningGoal]));
158 }
159 
160 int FootstepPlannerEnvironment::GetFromToHeuristic(const PlanningState& from, const PlanningState& to, const PlanningState& start, const PlanningState& goal)
161 {
162  return cvMmScale * params.heuristic_scale * Heuristic::instance().getHeuristicValue(from.getState(), to.getState(), start.getState(), goal.getState());
163 }
164 
166 {
167  const PlanningState* current = state_space->ivStateId2State[stateID];
168  if (current->getLeg() == LEFT)
169  return GetFromToHeuristic(stateID, state_space->ivIdGoalFootLeft);
170  else
171  return GetFromToHeuristic(stateID, state_space->ivIdGoalFootRight);
172  //return GetFromToHeuristic(stateID, state_space->ivIdPlanningGoal);
173 }
174 
175 void FootstepPlannerEnvironment::GetPreds(int TargetStateID, std::vector<int> *PredIDV, std::vector<int> *CostV)
176 {
177  boost::this_thread::interruption_point();
178 
179  PredIDV->clear();
180  CostV->clear();
181 
182  assert(TargetStateID >= 0 && (unsigned int) TargetStateID < state_space->ivStateId2State.size());
183 
184  // make start states always absorbing
185  if (TargetStateID == state_space->ivIdStartFootLeft || TargetStateID == state_space->ivIdStartFootRight)
186  return;
187 
188  const PlanningState* current = state_space->ivStateId2State[TargetStateID];
189 
190  if (!current->getSuccState())
191  {
192  ROS_WARN("Step cost should be evaluated but current state has no successor!");
193  return;
194  }
195 
196  // make sure goal state transitions are consistent with
197  // GetSuccs(some_state, goal_state) where goal_state is reachable by an
198  // arbitrary step from some_state
199  if (params.forward_search)
200  {
201  if (state_space->ivStateArea.empty())
202  ROS_WARN("This should not happen! Reactivate setStateArea");
203  if (TargetStateID == state_space->ivIdGoalFootLeft || TargetStateID == state_space->ivIdGoalFootRight)
204  {
205  const PlanningState* s;
206  int cost;
207  std::vector<int>::const_iterator state_id_iter;
208  for(state_id_iter = state_space->ivStateArea.begin(); state_id_iter != state_space->ivStateArea.end(); ++state_id_iter)
209  {
210  s = state_space->ivStateId2State[*state_id_iter];
211  if (s->getLeg() == current->getLeg())
212  continue;
213  if (*(current->getSuccState()) == *s)
214  continue;
215 
216  if (!state_space->getStepCost(current->getState(), s->getState(), current->getSuccState()->getState(), cost))
217  continue;
218 
219  PredIDV->push_back(s->getId());
220  CostV->push_back(cost);
221  stateVisited(*s);
222  }
223  return;
224  }
225  }
226 
227  stateExpanded(*current);
228 
229  // check if start is reachable
230  if (state_space->closeToStart(*current))
231  {
232  const PlanningState* start = state_space->ivStateId2State[state_space->ivIdPlanningStart];
233  if (*(current->getSuccState()) == *start)
234  return;
235 
236  if (WorldModel::instance().isAccessible(start->getState(), current->getState()))
237  {
238  int cost;
239  if (state_space->getStepCost(current->getState(), start->getState(), current->getSuccState()->getState(), cost))
240  {
241  PredIDV->push_back(start->getId());
242  CostV->push_back(cost);
243  stateVisited(*start);
244  return;
245  }
246  }
247  }
248 
249  // explorate all states
250  std::list<PlanningState::Ptr> visited_states = StateGenerator::instance().generatePredecessors(*current);
251 
252  PredIDV->reserve(visited_states.size());
253  CostV->reserve(visited_states.size());
254 
255  for (const PlanningState::Ptr& visited_state : visited_states)
256  {
257  const PlanningState* successor_hash = state_space->createHashEntryIfNotExists(*visited_state);
258 
259  PredIDV->push_back(successor_hash->getId());
260  CostV->push_back(static_cast<int>(cvMmScale * visited_state->getState().getCost() + 0.5));
261  stateVisited(*successor_hash);
262  }
263 }
264 
266 {
267  const PlanningState* current = state_space->ivStateId2State[stateID];
268  if (current->getLeg() == LEFT)
269  return GetFromToHeuristic(stateID, state_space->ivIdStartFootLeft);
270  else
271  return GetFromToHeuristic(stateID, state_space->ivIdStartFootRight);
272  //return GetFromToHeuristic(stateID, state_space->ivIdPlanningStart);
273 }
274 
275 
276 void FootstepPlannerEnvironment::GetSuccs(int SourceStateID, std::vector<int> *SuccIDV, std::vector<int> *CostV)
277 {
278  boost::this_thread::interruption_point();
279 
280  SuccIDV->clear();
281  CostV->clear();
282 
283  assert(SourceStateID >= 0 && unsigned(SourceStateID) < state_space->ivStateId2State.size());
284 
285  // make goal states always absorbing
286  if (SourceStateID == state_space->ivIdGoalFootLeft || SourceStateID == state_space->ivIdGoalFootRight)
287  return;
288 
289  const PlanningState* current = state_space->ivStateId2State[SourceStateID];
290 
291  if (!current->getPredState())
292  {
293  ROS_WARN("Step cost should be evaluated but current state has no predecessor!");
294  return;
295  }
296 
297  // make sure start state transitions are consistent with
298  // GetPreds(some_state, start_state) where some_state is reachable by an
299  // arbitrary step from start_state
300  if (!params.forward_search)
301  {
302  if (state_space->ivStateArea.empty())
303  ROS_WARN("This should not happen! Reactivate setStateArea");
304  if (SourceStateID == state_space->ivIdStartFootLeft || SourceStateID == state_space->ivIdStartFootRight)
305  {
306  const PlanningState* s;
307  int cost;
308  std::vector<int>::const_iterator state_id_iter;
309  for(state_id_iter = state_space->ivStateArea.begin(); state_id_iter != state_space->ivStateArea.end(); ++state_id_iter)
310  {
311  s = state_space->ivStateId2State[*state_id_iter];
312  if (s->getLeg() == current->getLeg())
313  continue;
314  if (*(current->getPredState()) == *s)
315  continue;
316 
317  if (!state_space->getStepCost(current->getState(), current->getPredState()->getState(), s->getState(), cost))
318  continue;
319 
320  SuccIDV->push_back(s->getId());
321  CostV->push_back(cost);
322  stateVisited(*s);
323  }
324  return;
325  }
326  }
327 
328  stateExpanded(*current);
329 
330  // check if goal is reachable
331  if (state_space->closeToGoal(*current))
332  {
333  const PlanningState* goal = state_space->ivStateId2State[state_space->ivIdPlanningGoal];
334  if (*(current->getPredState()) == *goal)
335  return;
336 
337  if (WorldModel::instance().isAccessible(goal->getState(), current->getState()))
338  {
339  int cost;
340  if (state_space->getStepCost(current->getState(), current->getPredState()->getState(), goal->getState(), cost))
341  {
342  SuccIDV->push_back(goal->getId());
343  CostV->push_back(cost);
344  stateVisited(*goal);
345  return;
346  }
347  }
348  }
349 
350  // explorate all states
351  std::list<PlanningState::Ptr> visited_states = StateGenerator::instance().generateSuccessors(*current);
352 
353  SuccIDV->reserve(visited_states.size());
354  CostV->reserve(visited_states.size());
355 
356  for (const PlanningState::Ptr& visited_state : visited_states)
357  {
358  const PlanningState* successor_hash = state_space->createHashEntryIfNotExists(*visited_state);
359 
360  SuccIDV->push_back(successor_hash->getId());
361  CostV->push_back(static_cast<int>(cvMmScale * visited_state->getState().getCost() + 0.5));
362  stateVisited(*successor_hash);
363  }
364 }
365 
366 void FootstepPlannerEnvironment::GetRandomSuccsatDistance(int SourceStateID, std::vector<int>* SuccIDV, std::vector<int>* CLowV)
367 {
368  boost::this_thread::interruption_point();
369 
370  assert(SourceStateID >= 0 && unsigned(SourceStateID) < state_space->ivStateId2State.size());
371  //goal state should be absorbing
372  if (SourceStateID == state_space->ivIdGoalFootLeft || SourceStateID == state_space->ivIdGoalFootRight )
373  return;
374 
375 
376  //const PlanningState* currentState = state_space->ivStateId2State[SourceStateID];
377  // TODO: state_space->closeToGoal?
378  //
379  // if (state_space->closeToGoal(currentState->getState()))
380  // return;
381 
382  //get the successors
383  //GetRandomNeighs(currentState, SuccIDV, CLowV, params.num_random_nodes, state_space->ivRandomNodeDist, true);
384 }
385 
386 void FootstepPlannerEnvironment::GetRandomPredsatDistance(int TargetStateID, std::vector<int>* PredIDV, std::vector<int>* CLowV)
387 {
388  boost::this_thread::interruption_point();
389 
390  assert(TargetStateID >= 0 && unsigned(TargetStateID) < state_space->ivStateId2State.size());
391 
392  // start state should be absorbing
393  if (TargetStateID == state_space->ivIdStartFootLeft || TargetStateID == state_space->ivIdStartFootRight)
394  return;
395 
396  //const PlanningState* currentState = state_space->ivStateId2State[TargetStateID];
397 
398  // TODO: ???
399  // if(state_space->closeToStart(currentState->getState()))
400  // return;
401 
402  //get the predecessors
403  //GetRandomNeighs(currentState, PredIDV, CLowV, params.num_random_nodes, state_space->ivRandomNodeDist, false);
404 }
405 
406 bool FootstepPlannerEnvironment::AreEquivalent(int StateID1, int StateID2)
407 {
408  assert(StateID1 >= 0 && StateID2 >= 0 && unsigned(StateID1) < state_space->ivStateId2State.size() && unsigned(StateID2) < state_space->ivStateId2State.size());
409 
410  if (StateID1 == StateID2)
411  return true;
412 
413  const PlanningState* s1 = state_space->ivStateId2State[StateID1];
414  const PlanningState* s2 = state_space->ivStateId2State[StateID2];
415 
416  return *s1 == *s2;
417 }
418 
420 {
421  // ROS_ERROR("FootstepPlanerEnvironment::InitializeEnv: Hit unimplemented "
422  // "function. Check this!");
423  return true;
424 }
425 
427 {
428  // NOTE: The internal start and goal ids are set here to the left foot
429  // (this affects the calculation of the heuristic values)
430  MDPCfg->startstateid = state_space->ivIdPlanningStart;
431  MDPCfg->goalstateid = state_space->ivIdPlanningGoal;
432 
433  assert(state_space->ivIdPlanningStart != -1);
434  assert(state_space->ivIdPlanningGoal != -1);
435 
436  return true;
437 }
438 
440 {
441  // NOTE: implement this if the planner needs to print out configurations
442  ROS_ERROR("FootstepPlanerEnvironment::PrintEnv_Config: Hit "
443  "unimplemented function. Check this!");
444 }
445 
446 void FootstepPlannerEnvironment::PrintState(int stateID, bool bVerbose, FILE *fOut)
447 {
448  if(fOut == NULL)
449  {
450  fOut = stdout;
451  }
452 
453  if(stateID == state_space->ivIdGoalFootLeft && bVerbose)
454  {
455  SBPL_FPRINTF(fOut, "the state is a goal state\n");
456  }
457 
458  const PlanningState* s = state_space->ivStateId2State[stateID];
459 
460  if(bVerbose)
461  {
462  SBPL_FPRINTF(fOut, "X=%i Y=%i THETA=%i FOOT=%i\n",
463  s->getX(), s->getY(), s->getYaw(), s->getLeg());
464  }
465  else
466  {
467  SBPL_FPRINTF(fOut, "%i %i %i %i\n",
468  s->getX(), s->getY(), s->getYaw(), s->getLeg());
469  }
470 }
471 
473 {
474  // NOTE: not implemented so far
475  // Description: Some searches may also use SetAllActionsandAllOutcomes
476  // or SetAllPreds functions if they keep the pointers to successors
477  // (predecessors) but most searches do not require this, so it is not
478  // necessary to support this
479 
480  ROS_ERROR("FootstepPlannerEnvironment::SetAllActionsandAllOutcomes: Hit"
481  " unimplemented function. Check this!");
482 }
483 
485 {
486  // NOTE: not implemented so far
487  // Description: Some searches may also use SetAllActionsandAllOutcomes
488  // or SetAllPreds functions if they keep the pointers to successors
489  // (predecessors) but most searches do not require this, so it is not
490  // necessary to support this
491 
492  ROS_ERROR("FootstepPlannerEnvironment::SetAllPreds: Hit unimplemented "
493  "function. Check this!");
494 }
495 
497 {
498  return state_space->ivStateId2State.size();
499 }
500 
501 bool FootstepPlannerEnvironment::less::operator()(const PlanningState* a, const PlanningState* b) const
502 {
503  if (a->getX() < b->getX())
504  return true;
505  else if (a->getY() < b->getY())
506  return true;
507  else if (a->getYaw() < b->getYaw())
508  return true;
509  else
510  return false;
511 }
512 }
void updateHeuristicValues()
Update the heuristic values (e.g. after the map has changed). The environment takes care that the upd...
void reset()
Resets the current planning task (i.e. the start and goal poses).
void GetSuccs(int SourceStateID, std::vector< int > *SuccIDV, std::vector< int > *CostV)
Calculates the successor states and the corresponding costs when performing the footstep set on the p...
XmlRpcServer s
#define ROS_WARN(...)
bool operator()(const PlanningState *a, const PlanningState *b) const
msgs::ErrorStatus transformToRobotFrame(T &p) const
virtual void GetRandomPredsatDistance(int TargetStateID, std::vector< int > *PredIDV, std::vector< int > *CLowV)
Used for RStar: generate succs/preds at some domain-dependent distance. The number of generated succs...
boost::function< void(msgs::PlanningFeedback)> & feedback_cb
#define ROS_INFO(...)
unsigned int step
static Time now()
void GetPreds(int TargetStateID, std::vector< int > *PredIDV, std::vector< int > *CostV)
Calculates the predecessor states and the corresponding costs when reversing the footstep set on the ...
virtual void GetRandomSuccsatDistance(int SourceStateID, std::vector< int > *SuccIDV, std::vector< int > *CLowV)
Used for RStar: generate succs/preds at some domain-dependent distance. The number of generated succs...
void PrintState(int stateID, bool bVerbose, FILE *fOut)
#define ROS_ERROR(...)
FootstepPlannerEnvironment(const EnvironmentParameters &params, const FootPoseTransformer &foot_pose_transformer, boost::function< void(msgs::PlanningFeedback)> &feedback_cb)
#define ROS_DEBUG(...)


vigir_footstep_planner
Author(s): Alexander Stumpf
autogenerated on Sun Nov 17 2019 03:29:59