step_plan.cpp
Go to the documentation of this file.
2 
3 
4 
6 {
7 StepPlan::StepPlan(const msgs::StepPlan& step_plan)
8 {
9  fromMsg(step_plan);
10 }
11 
13  : mode(0)
14 {
15 }
16 
17 StepPlan& StepPlan::operator=(const msgs::StepPlan& step_plan)
18 {
19  fromMsg(step_plan);
20  return *this;
21 }
22 
23 StepPlan& StepPlan::operator+(const msgs::StepPlan& step_plan)
24 {
25  appendStepPlan(step_plan);
26  return *this;
27 }
28 
29 StepPlan& StepPlan::operator|(const msgs::StepPlan& step_plan)
30 {
31  updateStepPlan(step_plan);
32  return *this;
33 }
34 
35 StepPlan& StepPlan::operator+(const msgs::Step& step)
36 {
37  insertStep(step);
38  return *this;
39 }
40 
41 StepPlan& StepPlan::operator|(const msgs::Step& step)
42 {
43  updateStep(step);
44  return *this;
45 }
46 
47 StepPlan& StepPlan::operator-(const msgs::Step& step)
48 {
49  removeStep(step.step_index);
50  return *this;
51 }
52 
54 {
55  boost::shared_lock<boost::shared_mutex> lock(step_plan_mutex);
56 
57  if (steps.empty())
58  return -1;
59  else
60  return steps.begin()->second.step_index;
61 }
62 
64 {
65  boost::shared_lock<boost::shared_mutex> lock(step_plan_mutex);
66 
67  if (steps.empty())
68  return -1;
69  else
70  return steps.rbegin()->second.step_index;
71 }
72 
73 msgs::ErrorStatus StepPlan::insertStep(const msgs::Step& step)
74 {
75  boost::unique_lock<boost::shared_mutex> lock(step_plan_mutex);
76  return _insertStep(step);
77 }
78 
79 msgs::ErrorStatus StepPlan::updateStep(const msgs::Step& step)
80 {
81  boost::unique_lock<boost::shared_mutex> lock(step_plan_mutex);
82  return _updateStep(step);
83 }
84 
85 bool StepPlan::getStep(msgs::Step& step, const msgs::StepPlan& step_plan, unsigned int step_index)
86 {
87  for (std::vector<msgs::Step>::const_iterator itr = step_plan.steps.begin(); itr != step_plan.steps.end(); itr++)
88  {
89  const msgs::Step& s = *itr;
90  if (s.step_index == step_index)
91  {
92  step = s;
93  return true;
94  }
95  }
96  return false;
97 }
98 
99 bool StepPlan::getStepAt(msgs::Step& step, unsigned int position) const
100 {
101  boost::shared_lock<boost::shared_mutex> lock(step_plan_mutex);
102 
103  if (steps.empty())
104  return false;
105  else
106  {
107  std::map<unsigned int, msgs::Step>::const_iterator itr = steps.begin();
108  std::advance(itr, position);
109  step = itr->second;
110  return true;
111  }
112 }
113 
114 bool StepPlan::getfirstStep(msgs::Step& step) const
115 {
116  boost::shared_lock<boost::shared_mutex> lock(step_plan_mutex);
117 
118  if (steps.empty())
119  return false;
120  else
121  {
122  step = steps.begin()->second;
123  return true;
124  }
125 }
126 
127 bool StepPlan::getLastStep(msgs::Step& step) const
128 {
129  boost::shared_lock<boost::shared_mutex> lock(step_plan_mutex);
130 
131  if (steps.empty())
132  return false;
133  else
134  {
135  step = steps.rbegin()->second;
136  return true;
137  }
138 }
139 
140 bool StepPlan::popStep(msgs::Step& step)
141 {
142  boost::unique_lock<boost::shared_mutex> lock(step_plan_mutex);
143 
144  if (steps.empty())
145  return false;
146  else
147  {
148  step = steps.begin()->second;
149  steps.erase(steps.begin());
150  return true;
151  }
152 }
153 
155 {
156  msgs::Step step;
157  popStep(step);
158 }
159 
160 void StepPlan::removeStep(unsigned int step_index)
161 {
162  boost::unique_lock<boost::shared_mutex> lock(step_plan_mutex);
163  steps.erase(step_index);
164 }
165 
166 void StepPlan::removeStepAt(unsigned int position)
167 {
168  boost::unique_lock<boost::shared_mutex> lock(step_plan_mutex);
169  steps.erase(steps.find(position));
170 }
171 
172 void StepPlan::removeSteps(unsigned int from_step_index, int to_step_index)
173 {
174  boost::unique_lock<boost::shared_mutex> lock(step_plan_mutex);
175 
176  if (steps.empty())
177  return;
178 
179  from_step_index = std::max(from_step_index, steps.begin()->first);
180  if (from_step_index > to_step_index)
181  return;
182 
183  std::map<unsigned int, msgs::Step>::iterator start_itr = steps.find(from_step_index);
184  std::map<unsigned int, msgs::Step>::iterator end_itr = to_step_index >= 0 ? steps.find(to_step_index+1) : steps.end();
185  steps.erase(start_itr, end_itr);
186 }
187 
188 msgs::ErrorStatus StepPlan::appendStepPlan(const msgs::StepPlan& step_plan)
189 {
190  boost::unique_lock<boost::shared_mutex> lock(step_plan_mutex);
191 
192  // check for errors
193  msgs::ErrorStatus status = isConsistent(step_plan);
194  if (status.error != msgs::ErrorStatus::NO_ERROR)
195  return status;
196  else if (step_plan.steps.empty())
197  return ErrorStatusWarning(msgs::ErrorStatus::WARN_INVALID_STEP_PLAN, "appendStepPlan", "Got empty plan!");
198 
199  if (!_empty())
200  {
201  if (step_plan.header.frame_id != header.frame_id)
202  return ErrorStatusError(msgs::ErrorStatus::ERR_UNKNOWN, "appendStepPlan", "Frame id mismatch of plans: " + header.frame_id + " vs. " + step_plan.header.frame_id);
203  else if (mode != step_plan.mode)
204  return ErrorStatusError(msgs::ErrorStatus::ERR_UNKNOWN, "appendStepPlan", "Plans have different modes!");
205  }
206  // append plan
207  return _appendStepPlan(step_plan);
208 }
209 
210 msgs::ErrorStatus StepPlan::updateStepPlan(const msgs::StepPlan& step_plan)
211 {
212  boost::unique_lock<boost::shared_mutex> lock(step_plan_mutex);
213 
214  // check for errors
215  if (step_plan.steps.empty())
216  return ErrorStatusWarning(msgs::ErrorStatus::WARN_INVALID_STEP_PLAN, "updateStepPlan", "Got empty plan!");
217 
218  if (!_empty())
219  {
220  if (step_plan.header.frame_id != header.frame_id)
221  return ErrorStatusError(msgs::ErrorStatus::ERR_UNKNOWN, "updateStepPlan", "Frame id mismatch of plans: " + header.frame_id + " vs. " + step_plan.header.frame_id);
222  else if (mode != step_plan.mode)
223  return ErrorStatusError(msgs::ErrorStatus::ERR_UNKNOWN, "updateStepPlan", "Plans have different modes!");
224  }
225 
226  // update plan
227  return _updateStepPlan(step_plan);
228 }
229 
230 msgs::ErrorStatus StepPlan::stitchStepPlan(const msgs::StepPlan& step_plan, int step_index)
231 {
232  boost::unique_lock<boost::shared_mutex> lock(step_plan_mutex);
233 
234  // check for errors
235  msgs::ErrorStatus status = isConsistent(step_plan);
236  if (status.error != msgs::ErrorStatus::NO_ERROR)
237  return status;
238  else if (step_plan.steps.empty())
239  return ErrorStatusWarning(msgs::ErrorStatus::WARN_INVALID_STEP_PLAN, "stitchStepPlan", "Got empty plan!");
240 
241  if (!_empty())
242  {
243  if (step_plan.header.frame_id != header.frame_id)
244  return ErrorStatusError(msgs::ErrorStatus::ERR_UNKNOWN, "stitchStepPlan", "Frame id mismatch of plans: " + header.frame_id + " vs. " + step_plan.header.frame_id);
245  else if (mode != step_plan.mode)
246  return ErrorStatusError(msgs::ErrorStatus::ERR_UNKNOWN, "stitchStepPlan", "Plans have different modes!");
247  else if (step_index > 0 && (steps.empty() || step_index > steps.rbegin()->second.step_index))
248  return ErrorStatusError(msgs::ErrorStatus::ERR_UNKNOWN, "stitchStepPlan", "Can't stitch as requested step index is not in current step plan!");
250  }
251 
252  // stitch plan
253  return _stitchStepPlan(step_plan, step_index);
254 }
255 
256 tf::Transform StepPlan::getTransform(const geometry_msgs::Pose& current, const geometry_msgs::Pose& target)
257 {
258  tf::Pose ref_current;
259  tf::poseMsgToTF(current, ref_current);
260 
261  tf::Pose ref_target;
262  tf::poseMsgToTF(target, ref_target);
263  //ref_target.setRotation(tf::createQuaternionFromYaw(tf::getYaw(ref_target.getRotation()))); /// HACK to clamp everything to flat ground
264 
265  // determine transformation
266  return ref_target * ref_current.inverse();
267 }
268 
269 void StepPlan::transformStepPlan(msgs::StepPlan& step_plan, const tf::Transform& transform)
270 {
271  tf::Pose pose;
272 
273  // start pose
274  tf::poseMsgToTF(step_plan.start.left.pose, pose);
275  pose = transform * pose;
276  tf::poseTFToMsg(pose, step_plan.start.left.pose);
277 
278  tf::poseMsgToTF(step_plan.start.right.pose, pose);
279  pose = transform * pose;
280  tf::poseTFToMsg(pose, step_plan.start.right.pose);
281 
282  // goal pose
283  tf::poseMsgToTF(step_plan.goal.left.pose, pose);
284  pose = transform * pose;
285  tf::poseTFToMsg(pose, step_plan.goal.left.pose);
286 
287  tf::poseMsgToTF(step_plan.goal.right.pose, pose);
288  pose = transform * pose;
289  tf::poseTFToMsg(pose, step_plan.goal.right.pose);
290 
291  // entire plan
292  for (std::vector<msgs::Step>::iterator itr = step_plan.steps.begin(); itr != step_plan.steps.end(); itr++)
293  {
294  msgs::Step& step = *itr;
295 
296  tf::poseMsgToTF(step.foot.pose, pose);
297  pose = transform * pose;
298  tf::poseTFToMsg(pose, step.foot.pose);
299  }
300 }
301 
303 {
304  header = std_msgs::Header();
305  start = msgs::Feet();
306  goal = msgs::Feet();
307  steps.clear();
308  mode = 0;
309  data.clear();
310 }
311 
312 bool StepPlan::_empty() const
313 {
314  return steps.empty();
315 }
316 
317 size_t StepPlan::_size() const
318 {
319  return steps.size();
320 }
321 
322 bool StepPlan::_hasStep(unsigned int step_index) const
323 {
324  return steps.find(step_index) != steps.end();
325 }
326 
327 bool StepPlan::_getStep(msgs::Step& step, unsigned int step_index) const
328 {
329  std::map<unsigned int, msgs::Step>::const_iterator itr = steps.find(step_index);
330  if (itr != steps.end())
331  {
332  step = itr->second;
333  return true;
334  }
335  return false;
336 }
337 
338 msgs::ErrorStatus StepPlan::_insertStep(const msgs::Step& step)
339 {
340  // check for errors
341  if (steps.empty())
342  header = step.header;
343  else if (step.header.frame_id != header.frame_id)
344  return ErrorStatusError(msgs::ErrorStatus::ERR_UNKNOWN, "insertStep", "Frame id mismatch! Plan: " + header.frame_id + " vs. step: " + step.header.frame_id);
345 
346  // insert step
347  steps[step.step_index] = step;
348 
349  return msgs::ErrorStatus();
350 }
351 
352 msgs::ErrorStatus StepPlan::_updateStep(const msgs::Step& step)
353 {
354  // check for errors
355  if (steps.empty())
356  header = step.header;
357  else if (step.header.frame_id != header.frame_id)
358  return ErrorStatusError(msgs::ErrorStatus::ERR_UNKNOWN, "updateStep", "Frame id mismatch! Plan: " + header.frame_id + " vs. step: " + step.header.frame_id);
359 
360  // check if step has already existed
361  bool modified(_hasStep(step.step_index));
362 
363  // insert/update step
364  steps[step.step_index] = step;
365  steps[step.step_index].modified = modified;
366 
367  return msgs::ErrorStatus();
368 }
369 
370 msgs::ErrorStatus StepPlan::_appendStepPlan(const msgs::StepPlan& step_plan)
371 {
372  int step_index = 0;
373 
374  // init header
375  if (steps.empty())
376  {
377  header = step_plan.header;
378  mode = step_plan.mode;
379  data = step_plan.data;
380  }
381  else
382  step_index = steps.rbegin()->second.step_index + 1;
383 
384  // append plan
385  msgs::ErrorStatus status;
386  for (msgs::Step step : step_plan.steps)
387  {
388  step.step_index = step_index++;
389  status += _insertStep(step);
390 
391  if (status.error != msgs::ErrorStatus::NO_ERROR)
392  break;
393  }
394 
395  return status;
396 }
397 
398 msgs::ErrorStatus StepPlan::_updateStepPlan(const msgs::StepPlan& step_plan)
399 {
400  // init header
401  if (steps.empty())
402  {
403  header = step_plan.header;
404  mode = step_plan.mode;
405  data = step_plan.data;
406  }
407 
408  // update plan
409  msgs::ErrorStatus status;
410  for (std::vector<msgs::Step>::const_iterator itr = step_plan.steps.begin(); itr != step_plan.steps.end(); itr++)
411  {
412  status += _updateStep(*itr);
413 
414  if (status.error != msgs::ErrorStatus::NO_ERROR)
415  break;
416  }
417 
418  return status;
419 }
420 
421 msgs::ErrorStatus StepPlan::_stitchStepPlan(const msgs::StepPlan& step_plan, int step_index)
422 {
423  if (step_plan.steps.empty())
424  return msgs::ErrorStatus();
425 
426  // simple case: current step plan is still empty
427  if (steps.empty())
428  return _updateStepPlan(step_plan);
429 
430  msgs::Step last_current_step;
431  msgs::Step first_new_step;
432 
433  if (step_index == 0)
434  {
435  last_current_step = steps.rbegin()->second;
436  first_new_step = step_plan.steps.front();
437  }
438  else
439  {
440  if (!_getStep(last_current_step, step_index))
441  return ErrorStatusError(msgs::ErrorStatus::ERR_INVALID_STEP, "stitchStepPlan", "Current step plan doesn't contain step index " + boost::lexical_cast<std::string>(step_index) + "!");
442 
443  if (!getStep(first_new_step, step_plan, step_index))
444  return ErrorStatusError(msgs::ErrorStatus::ERR_INVALID_STEP, "stitchStepPlan", "Input step plan doesn't contain step index " + boost::lexical_cast<std::string>(step_index) + "!");
445  }
446 
447  // ensure overlapping first step
448  if (last_current_step.foot.foot_index != first_new_step.foot.foot_index)
449  return ErrorStatusError(msgs::ErrorStatus::ERR_INCONSISTENT_STEP_PLAN, "stitchStepPlan", std::string("First foot ") +
450  (first_new_step.foot.foot_index == msgs::Foot::RIGHT ? std::string("(RIGHT)") : std::string("(LEFT)")) + std::string(" of input step plan doesn't match ") +
451  (last_current_step.foot.foot_index == msgs::Foot::RIGHT ? std::string("(RIGHT)") : std::string("(LEFT)")) + std::string(" last foot of current step plan."));
452 
453  // transform input plan to be relative to current plan's reference foot pose
454  msgs::StepPlan step_plan_transformed = step_plan;
455  step_plan_transformed.steps.clear();
456 
457  for (msgs::Step step : step_plan.steps)
458  {
459  if (step.step_index >= step_index)
460  step_plan_transformed.steps.push_back(step);
461  }
462 
463  // determine transformation 'input plan first step' -> 'current plan last step'
464  tf::Transform transform = getTransform(first_new_step.foot.pose, last_current_step.foot.pose);
465  transformStepPlan(step_plan_transformed, transform);
466 
467  // remove remaining tail of old step plan
468  unsigned int max_step_index = step_plan_transformed.steps.back().step_index;
469  for (std::map<unsigned int, msgs::Step>::iterator itr = steps.begin(); itr != steps.end();)
470  {
471  if (itr->second.step_index > max_step_index)
472  steps.erase(itr++);
473  else
474  itr++;
475  }
476 
477  // remove pivot step as we won't change it
478  step_plan_transformed.steps.erase(step_plan_transformed.steps.begin());
479 
480  // update plan using the transformed step plan
481  return _updateStepPlan(step_plan_transformed);
482 }
483 
484 msgs::ErrorStatus StepPlan::fromMsg(const msgs::StepPlan& step_plan)
485 {
486  clear();
487  msgs::ErrorStatus status = isConsistent(step_plan);
488 
489  // check for errors
490  if (status.error != msgs::ErrorStatus::NO_ERROR)
491  return status;
492 
493  boost::unique_lock<boost::shared_mutex> lock(step_plan_mutex);
494 
495  // convert step plan
496  header = step_plan.header;
497 
498  start = step_plan.start;
499  goal = step_plan.goal;
500 
501  mode = step_plan.mode;
502  data = step_plan.data;
503 
504  steps.clear();
505 
506  for (unsigned int i = 0u; i < step_plan.steps.size(); i++)
507  {
508  status += _insertStep(step_plan.steps[i]);
509 
510  if (status.error != msgs::ErrorStatus::NO_ERROR)
511  break;
512  }
513 
514  return status;
515 }
516 
517 msgs::ErrorStatus StepPlan::toMsg(msgs::StepPlan& step_plan) const
518 {
519  boost::shared_lock<boost::shared_mutex> lock(step_plan_mutex);
520 
521  msgs::ErrorStatus status;
522 
523  // convert step plan
524  step_plan.header = header;
525 
526  step_plan.start = start;
527  step_plan.goal = goal;
528 
529  step_plan.steps.clear();
530  for (std::map<unsigned int, msgs::Step>::const_iterator itr = steps.begin(); itr != steps.end(); itr++)
531  step_plan.steps.push_back(itr->second);
532 
533  step_plan.mode = mode;
534  step_plan.data = data;
535 
536  status += isConsistent(step_plan);
537 
538  return status;
539 }
540 }
static bool getStep(msgs::Step &step, const msgs::StepPlan &step_plan, unsigned int step_index)
Definition: step_plan.cpp:85
msgs::ErrorStatus ErrorStatusWarning(unsigned int warning, const std::string &context, const std::string &warning_msg, bool output=true, double throttle_rate=0.0)
static void poseMsgToTF(const geometry_msgs::Pose &msg, Pose &bt)
msgs::ErrorStatus updateStep(const msgs::Step &step)
Definition: step_plan.cpp:79
std::map< unsigned int, msgs::Step > steps
Definition: step_plan.h:212
XmlRpcServer s
bool getfirstStep(msgs::Step &step) const
Definition: step_plan.cpp:114
void removeSteps(unsigned int from_step_index, int to_step_index=-1)
Definition: step_plan.cpp:172
bool getLastStep(msgs::Step &step) const
Definition: step_plan.cpp:127
msgs::ErrorStatus insertStep(const msgs::Step &step)
Definition: step_plan.cpp:73
std::vector< uint8_t > data
Definition: step_plan.h:214
StepPlan & operator|(const msgs::StepPlan &step_plan)
Definition: step_plan.cpp:29
StepPlan & operator-(const msgs::Step &step)
Definition: step_plan.cpp:47
msgs::ErrorStatus toMsg(msgs::StepPlan &step_plan) const
Definition: step_plan.cpp:517
msgs::ErrorStatus _updateStepPlan(const msgs::StepPlan &step_plan)
Merges the given step plan to current step plan. Already exisiting steps will be tagged as modified...
Definition: step_plan.cpp:398
msgs::ErrorStatus _stitchStepPlan(const msgs::StepPlan &step_plan, int step_index=0)
Stitches the given step plan into the current step plan starting at step_index. Hereby the all in ran...
Definition: step_plan.cpp:421
StepPlan & operator=(const msgs::StepPlan &step_plan)
Definition: step_plan.cpp:17
msgs::ErrorStatus appendStepPlan(const msgs::StepPlan &step_plan)
Appends a step plan to current step plan. No transformation will be done!
Definition: step_plan.cpp:188
msgs::ErrorStatus fromMsg(const msgs::StepPlan &step_plan)
Definition: step_plan.cpp:484
Transform inverse() const
msgs::ErrorStatus isConsistent(const msgs::StepPlan &result)
bool _hasStep(unsigned int step_index) const
Definition: step_plan.cpp:322
unsigned int step
void removeStep(unsigned int step_index)
Definition: step_plan.cpp:160
static void poseTFToMsg(const Pose &bt, geometry_msgs::Pose &msg)
msgs::ErrorStatus _updateStep(const msgs::Step &step)
Inserts step into step plan. If the step does already exists it will be overwritten and tagged as mod...
Definition: step_plan.cpp:352
bool getStepAt(msgs::Step &step, unsigned int position) const
Definition: step_plan.cpp:99
msgs::ErrorStatus ErrorStatusError(unsigned int error, const std::string &context, const std::string &error_msg, bool output=true, double throttle_rate=0.0)
static tf::Transform getTransform(const geometry_msgs::Pose &current, const geometry_msgs::Pose &target)
Determines transformation T from current to target coordinate system represented by the given poses i...
Definition: step_plan.cpp:256
StepPlan & operator+(const msgs::StepPlan &step_plan)
Definition: step_plan.cpp:23
static void transformStepPlan(msgs::StepPlan &step_plan, const tf::Transform &transform)
Definition: step_plan.cpp:269
boost::shared_mutex step_plan_mutex
Definition: step_plan.h:207
void removeStepAt(unsigned int position)
Definition: step_plan.cpp:166
msgs::ErrorStatus updateStepPlan(const msgs::StepPlan &step_plan)
Merges the given step plan to current step plan. Already exisiting steps will be tagged as modified...
Definition: step_plan.cpp:210
bool _getStep(msgs::Step &step, unsigned int step_index) const
Definition: step_plan.cpp:327
msgs::ErrorStatus stitchStepPlan(const msgs::StepPlan &step_plan, int step_index=0)
Stitches the given step plan into the current step plan starting at step_index. Hereby the all in ran...
Definition: step_plan.cpp:230
msgs::ErrorStatus _appendStepPlan(const msgs::StepPlan &step_plan)
Appends a step plan to current step plan. No transformation will be done!
Definition: step_plan.cpp:370
msgs::ErrorStatus _insertStep(const msgs::Step &step)
Inserts step into step plan. If the step does already exists it will be overwritten and not tagged as...
Definition: step_plan.cpp:338


vigir_footstep_planning_msgs
Author(s): Alexander Stumpf
autogenerated on Mon Jun 10 2019 15:45:25