segment_expander.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2017, <copyright holder> <email>
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  * * Redistributions of source code must retain the above copyright
8  * notice, this list of conditions and the following disclaimer.
9  * * Redistributions in binary form must reproduce the above copyright
10  * notice, this list of conditions and the following disclaimer in the
11  * documentation and/or other materials provided with the distribution.
12  * * Neither the name of the <organization> nor the
13  * names of its contributors may be used to endorse or promote products
14  * derived from this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY <copyright holder> <email> ''AS IS'' AND ANY
17  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19  * DISCLAIMED. IN NO EVENT SHALL <copyright holder> <email> BE LIABLE FOR ANY
20  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  *
27  */
28 
31 #include <iostream>
32 #define TIME_OVERLAP (1)
33 
34 namespace multi_robot_router
35 {
37 {
38  setCollisionResolver(_cRes);
39 }
40 
42 {
43  crType_ = _cRes;
45  {
47  }
48  else if (_cRes == CollisionResolverType::avoidance)
49  {
51  }
52  else //if(_cRes == CollisionResolverType::none)
53  {
55  }
56 }
57 
59 {
60  return crType_;
61 }
62 
64 {
65  collisions_robots_.clear();
66  startSegments_.clear();
67 }
68 
70 {
71  if (_current.potential == -1)
72  return;
73 
74  if (_next.potential >= 0)
75  return;
76 
77  int32_t collision = -1;
78 
79  if (route_querry_->checkSegment(_next, _current.potential - TIME_OVERLAP, _current.potential + pCalc_.CalculatePotential(_next) + TIME_OVERLAP, diameter_, collision))
80  {
81  float pot = _current.potential + pCalc_.CalculatePotential(_next);
82  float h = hx_.calcHeuristic(_next, _end);
83  float weight = pot + h;
84 
85  _next.weight = weight;
86  _next.potential = pot;
87  _next.predecessor_ = &_current;
88  _next.successor_ = &_start;
89  _next.collision = -1;
90 
91  seg_queue_.push(&_next);
92  }
93 }
94 
96 {
97  if (_current.potential == -1)
98  return;
99 
100  if (_next.potential >= 0)
101  return;
102 
103  int32_t collision;
104 
105  if (!route_querry_->checkSegment(_next, _current.potential - TIME_OVERLAP, _current.potential + pCalc_.CalculatePotential(_next) + TIME_OVERLAP, diameter_, collision))
106  {
107  if (collision != -1)
108  {
109  std::vector<std::reference_wrapper<Vertex>> resolutions = collision_resolution_->resolve(_current, _next, collision);
110 
111  for (Vertex &res : resolutions)
112  {
113  float h = hx_.calcHeuristic(res, _end);
114  res.weight = res.potential + h;
115 
116  if (res.getSegment().getSegmentId() == _end.getSegment().getSegmentId()) //Should not happen but safety first :D
117  {
118  res.weight = 0;
119  }
120 
121  seg_queue_.push(&res);
122  }
123  }
124 
125  return;
126  }
127 
128  float pot = _current.potential + pCalc_.CalculatePotential(_next);
129  float h = hx_.calcHeuristic(_next, _end);
130  float weight = pot + h;
131 
132  _next.weight = weight;
133  _next.potential = pot;
134 
135  if (_next.getSegment().getSegmentId() == _end.getSegment().getSegmentId())
136  _next.weight = 0;
137 
138  _next.predecessor_ = &_current;
139  _next.collision = -1;
140 
141  seg_queue_.push(&_next);
142 }
143 
144 bool SegmentExpander::calculatePotentials(const RouteCoordinatorWrapper *_p, Vertex &_start, Vertex &_end, const uint32_t _maxIterations, const uint32_t _diameter)
145 {
146  route_querry_ = _p;
147 
148  collisions_robots_.clear();
149  collision_resolution_->resetSession(_p, &pCalc_, _diameter);
150  diameter_ = _diameter;
151 
152  Vertex *foundEnd = expandVoronoi(_start, _end, _maxIterations);
153 
154  if (foundEnd == NULL)
155  return false;
156 
157  //Save actual planning status from parallel ends :D
158  if (&_end != foundEnd)
159  _end.updateVertex(*foundEnd);
160 
161  return (foundEnd->getSegment().getSegmentId() == _end.getSegment().getSegmentId());
162 }
163 
165 {
166  int collision = -1;
167  _start.collision = -1;
168  _start.predecessor_ = NULL;
169  _start.potential = -1;
170 
172 
173  //If the robot wants to stay on its pose we have to add a additional segment to enable avoiding higher prioritized robots
174  if (_start.getSegment().getSegmentId() == _end.getSegment().getSegmentId() && !route_querry_->checkSegment(_start, 0, -1, diameter_, collision) && collision != -1)
175  {
176  // Force the robot to move away from the segment
177  startSegments_.emplace_back(std::make_unique<Vertex>(_start));
178  Vertex &start = *(startSegments_.back().get());
179  start.predecessor_ = NULL;
180  start.potential = pCalc_.CalculatePotential(start);
181  start.collision = -1;
182 
183  const std::vector<std::reference_wrapper<Vertex>> &n_succ = start.getPlanningSuccessors();
184 
185  for (Vertex &v : n_succ)
186  {
187  //One to move back to start
188  startSegments_.emplace_back(std::make_unique<Vertex>(v));
189  addStartExpansionCandidate(_start, start, *(startSegments_.back().get()), _end);
190 
191  //One to expand Normal (Not working because we are blocking our own path) //TODO find fix
192  //All adjacent vertices to start are allready expanded. Hence there is no way back to start
193  //addExpansoionCandidate(start, v, _end);
194  }
195 
196  const std::vector<std::reference_wrapper<Vertex>> &n_pred = start.getPlanningPredecessors();
197 
198  for (Vertex &v : n_pred)
199  {
200  //One to move back to start
201  startSegments_.emplace_back(std::make_unique<Vertex>(v));
202  addStartExpansionCandidate(_start, start, *(startSegments_.back().get()), _end);
203 
204  //One to expand Normal (Not working well because we are blocking our own path) //TODO find fix
205  //All adjacent vertices to start are allready expanded. Hence there is no way back to start
206  //addExpansoionCandidate(start, v, _end);
207  }
208  }
209  else
210  {
211  _start.collision = -1;
212  _start.predecessor_ = NULL;
213  _start.potential = pCalc_.CalculatePotential(_start);
215  int32_t collision = -1;
216 
217  if (route_querry_->checkSegment(_start, 0, _start.potential + TIME_OVERLAP, diameter_, collision))
218  {
219  seg_queue_.push(&_start);
220  }
221  else if (collision != -1)
222  {
224  }
225  }
226 }
227 
228 bool SegmentExpander::containsVertex(const Vertex &_v, const std::vector<std::reference_wrapper<Vertex>> &_list) const
229 {
230  for (const Vertex &v : _list)
231  {
232  if (_v.getSegment().getSegmentId() == v.getSegment().getSegmentId())
233  return true;
234  }
235 
236  return false;
237 }
238 
239 void SegmentExpander::setSpeed(const float &_speed)
240 {
241  pCalc_.SetMultiplier(_speed);
242 }
243 
244 Vertex *SegmentExpander::expandVoronoi(Vertex &_start, Vertex &_end, const uint32_t _cycles)
245 {
246  startSegments_.clear();
247 
248  uint32_t cycle = 0; //For having a high startpotential
249  resolveStartCollision(_start, _end);
250 
251  Vertex *current = NULL;
252 
253  while (!(seg_queue_.empty()) && (cycle < _cycles) && (current == NULL || _end.getSegment().getSegmentId() != current->getSegment().getSegmentId()))
254  {
255  if (seg_queue_.empty())
256  return NULL;
257 
258  current = seg_queue_.top();
259  seg_queue_.pop();
260 
261  //The segment expander is forced to expand to the successor (generated by the collision resolution)
262  if (current->successor_ != NULL)
263  {
264  addExpansoionCandidate(*current, *(current->successor_), _end);
265  }
266  else
267  {
268  const std::vector<std::reference_wrapper<Vertex>> &n_succ = current->getPlanningSuccessors();
269 
270  if (current->predecessor_ == NULL || !containsVertex(*(current->predecessor_), n_succ))
271  {
272  for (Vertex &v : n_succ)
273  {
274  addExpansoionCandidate(*current, v, _end);
275  }
276  }
277 
278  const std::vector<std::reference_wrapper<Vertex>> &n_pred = current->getPlanningPredecessors();
279 
280  if (current->predecessor_ == NULL || !containsVertex(*(current->predecessor_), n_pred))
281  {
282  for (Vertex &v : n_pred)
283  {
284  addExpansoionCandidate(*current, v, _end);
285  }
286  }
287  }
288 
289  cycle++;
290  }
291 
292  if (current == NULL || current->getSegment().getSegmentId() != _end.getSegment().getSegmentId())
293  return NULL;
294 
295  return current;
296 }
297 
298 const std::vector<uint32_t> &SegmentExpander::getRobotCollisions() const
299 {
301 }
302 
303 } // namespace multi_robot_router
uint32_t getSegmentId() const
Definition: srr_utils.cpp:60
void addExpansoionCandidate(Vertex &_current, Vertex &_next, Vertex &_end)
float calcHeuristic(const Vertex &_next, const Vertex &_end) const
calculates the euclidean distance to the end vertex
Definition: heuristic.h:45
std::vector< std::unique_ptr< Vertex > > startSegments_
CollisionResolution * collision_resolution_
Vertex * expandVoronoi(Vertex &_start, Vertex &_end, const uint32_t _cycles)
const std::vector< std::reference_wrapper< Vertex > > & getPlanningPredecessors() const
Definition: srr_utils.cpp:93
const std::vector< uint32_t > & getRobotCollisions() const
returns the found robotCollisions while planning
bool checkSegment(const Vertex &_next, const uint32_t _startTime, const int32_t _endTime, const uint32_t _diameterPixel, int32_t &_collisionRobot, bool _ignoreGoal=false) const
calls checkSegment of the routeCoordinator using robot
std::vector< uint32_t > collisions_robots_
std::priority_queue< Vertex *, std::vector< Vertex * >, greaterSegmentWrapper > seg_queue_
const std::vector< std::reference_wrapper< Vertex > > & getPlanningSuccessors() const
Definition: srr_utils.cpp:98
void updateVertex(const Vertex &_v)
Definition: srr_utils.cpp:136
virtual std::vector< std::reference_wrapper< Vertex > > resolve(Vertex &_current, Vertex &_next, int32_t _collision)=0
resolves a found collision between two robots.
virtual const std::vector< uint32_t > & getRobotCollisions() const =0
returns amount of robot collisions found in each resolve try after resetSession
float CalculatePotential(const Vertex &_vertex) const
calculates the potential for a vertex
#define TIME_OVERLAP
void setCollisionResolver(const CollisionResolverType cRes)
sets the desired collision resolver
virtual void saveCollision(const uint32_t _coll)=0
increases the collision count of one robot
bool containsVertex(const Vertex &_v, const std::vector< std::reference_wrapper< Vertex >> &_list) const
CollisionResolverType getCollisionResolver() const
gets the currently used collision resolver
const Segment & getSegment() const
Definition: srr_utils.cpp:88
void SetMultiplier(const float &_multiplier)
sets the Potential multiplier
void resolveStartCollision(Vertex &_start, Vertex &_end)
void setSpeed(const float &_speed)
Sets the multiplier to reduce a robots speed (pCalc...)
void clearpq(std::priority_queue< T, S, C > &q)
void addStartExpansionCandidate(Vertex &_start, Vertex &_current, Vertex &_next, Vertex &_end)
SegmentExpander(const CollisionResolverType _cRes)
constructor
virtual void resetSession(const RouteCoordinatorWrapper *_route_querry, const PotentialCalculator *_pCalc, const uint32_t _robot_radius)=0
resets the session (setting the new route querry and potential calculator)
bool calculatePotentials(const RouteCoordinatorWrapper *_p, Vertex &_start, Vertex &_end, const uint32_t _maxIterations, const uint32_t _radius)
assigns all Vertices in the Search graph with a potential according to the distance to the start ...
const RouteCoordinatorWrapper * route_querry_


tuw_multi_robot_router
Author(s): Benjamin Binder
autogenerated on Mon Jun 10 2019 15:42:49