route_coordinator_timed.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 
30 #include <iostream>
31 
32 #define TIME_INFINITY (-1)
33 //#define DEBUG
34 
35 namespace multi_robot_router
36 {
37 
39 {
40 }
41 
42 bool RouteCoordinatorTimed::addRoute(const std::vector<RouteVertex> &_path, const uint32_t _diameterPixel, const uint32_t _robotId)
43 {
44  for (uint32_t i = 0; i < _path.size(); i++)
45  {
46  uint32_t begin = 0;
47  int32_t end = TIME_INFINITY;
48 
49  if (i != 0)
50  {
51  begin = _path[i - 1].potential;
52  }
53 
54  if (i != _path.size() - 1)
55  {
56  end = _path[i].potential;
57  }
58 
59  if (!timeline_.addSegment(begin, end, _path[i].getSegment().getSegmentId(), _robotId, _diameterPixel, true))
60  {
61  removeRobot(_robotId);
62  return false;
63  }
64 
65  std::vector<uint32_t> pred = _path[i].getSegment().getPredecessors();
66 
67  if (_path[i].overlapPredecessor)
68  {
69  for (const uint32_t idx : pred)
70  {
71  if (!timeline_.addCrossingSegment(begin, end, idx, _robotId, _diameterPixel, false))
72  {
73  removeRobot(_robotId);
74  return false;
75  }
76  }
77  }
78 
79  std::vector<uint32_t> succ = _path[i].getSegment().getSuccessors();
80 
81  if (_path[i].overlapSuccessor)
82  {
83  for (const uint32_t idx : succ)
84  {
85  if (!timeline_.addCrossingSegment(begin, end, idx, _robotId, _diameterPixel, false))
86  {
87  removeRobot(_robotId);
88  return false;
89  }
90  }
91  }
92  }
93 
94  return true;
95 }
96 
97 bool RouteCoordinatorTimed::isGoal(const Vertex &_seg, const uint32_t _robotId) const
98 {
99  return _seg.getSegment().getSegmentId() == goalSegments_[_robotId];
100 }
101 
102 const uint32_t RouteCoordinatorTimed::getEnd(const uint32_t _robotId) const
103 {
104  return goalSegments_[_robotId];
105 }
106 
107 const uint32_t RouteCoordinatorTimed::getStart(const uint32_t _robotId) const
108 {
109  return startSegments_[_robotId];
110 }
111 
112 bool RouteCoordinatorTimed::checkSegment(const Vertex &_next, const uint32_t _startTime, const int32_t _endTime, const uint32_t _diameterPixel, int32_t &_collisionRobot, const uint32_t _robotId, bool _ignoreGoal) const
113 {
114 
115  //Bug fix check all neighbour edges for infinity
116  int32_t endTime = _endTime;
117 
118  if (isGoal(_next, _robotId) && !_ignoreGoal)
119  {
120  endTime = TIME_INFINITY;
121  }
122 
123  if (!checkSegmentSingle(_next, _startTime, endTime, _diameterPixel, _collisionRobot, _robotId, _ignoreGoal))
124  {
125  return false;
126  }
127 
128  std::vector<uint32_t> pred = _next.getSegment().getPredecessors();
129 
130  if (_next.crossingPredecessor)
131  {
132  for (const uint32_t idx : pred)
133  {
134  if (!timeline_.checkCrossingSegment(_startTime, endTime, idx, _robotId, _diameterPixel, _collisionRobot))
135  {
136  return false;
137  }
138  }
139  }
140 
141  std::vector<uint32_t> succ = _next.getSegment().getSuccessors();
142 
143  if (_next.crossingSuccessor)
144  {
145  for (const uint32_t idx : succ)
146  {
147  if (!timeline_.checkCrossingSegment(_startTime, endTime, idx, _robotId, _diameterPixel, _collisionRobot))
148  {
149  return false;
150  }
151  }
152  }
153 
154  return true;
155 }
156 
157 bool RouteCoordinatorTimed::checkSegmentSingle(const Vertex &_next, const uint32_t _startTime, const int32_t _endTime, const uint32_t _diameterPixel, int32_t &_collisionRobot, const uint32_t _robotId, const bool &_ignoreGoal) const
158 {
159  if (isGoal(_next, _robotId) && !_ignoreGoal)
160  {
161  return timeline_.checkSegment(_startTime, TIME_INFINITY, _next.getSegment().getSegmentId(), _robotId, _diameterPixel, _collisionRobot);
162  }
163  else
164  {
165  return timeline_.checkSegment(_startTime, _endTime, _next.getSegment().getSegmentId(), _robotId, _diameterPixel, _collisionRobot);
166  }
167 }
168 
169 void RouteCoordinatorTimed::reset(const std::vector<Segment> &_graph, const uint32_t _nrRobots)
170 {
171  timeline_.reset(_graph, _nrRobots);
172 
173  goalSegments_.clear();
174  startSegments_.clear();
175 }
176 
177 bool RouteCoordinatorTimed::setGoalSegments(const std::vector<uint32_t> &_goalSegments)
178 {
179  goalSegments_.clear();
180 
181  for (int i = 0; i < _goalSegments.size(); i++)
182  {
183  goalSegments_.emplace_back(_goalSegments[i]);
184  }
185 
186  return true;
187 }
188 
189 bool RouteCoordinatorTimed::setStartSegments(const std::vector<uint32_t> &_startSegments)
190 {
191  startSegments_.clear();
192 
193  for (int i = 0; i < _startSegments.size(); i++)
194  {
195  startSegments_.emplace_back(_startSegments[i]);
196  }
197 
198  return true;
199 }
200 
201 int32_t RouteCoordinatorTimed::findSegNr(const uint32_t _robot, const uint32_t _potential) const
202 {
203  int32_t segId = timeline_.findSegId(_robot, _potential);
204 
205  return segId;
206 }
207 
208 int32_t RouteCoordinatorTimed::findPotentialUntilRobotOnSegment(const uint32_t _robot, const uint32_t _segId) const
209 {
210  return timeline_.getTimeUntilRobotOnSegment(_robot, _segId);
211 }
212 
213 std::vector<std::pair<uint32_t, float>> RouteCoordinatorTimed::getListOfRobotsHigherPrioritizedRobots(const uint32_t _robot, const uint32_t _segId, const int32_t _potential) const
214 {
215  return timeline_.getListOfRobotsHigherPrioritizedRobots(_robot, _segId, _potential);
216 }
217 
218 void RouteCoordinatorTimed::removeRobot(const uint32_t _robot)
219 {
220  timeline_.removeRobot(_robot);
221 }
222 
224 {
225 }
226 
227 void RouteCoordinatorTimed::Timeline::reset(const std::vector<Segment> &_graph, const uint32_t _nrRobots)
228 {
229  nrRobots_ = _nrRobots;
230  timeline_.clear();
231  segmentSpace_.clear();
232  maxTime_ = 0;
233 
234  for (int i = 0; i < _graph.size(); i++)
235  {
236  timeline_.emplace_back();
237  segmentSpace_.push_back(_graph[i].width());
238  }
239 }
240 
241 bool RouteCoordinatorTimed::Timeline::addSegment(const uint32_t _startTime, const int32_t _endTime, const uint32_t _segId, const uint32_t _robotNr, const uint32_t _robotSize, bool _mainSeg)
242 {
243  int collision;
244 
245  if (!checkSegment(_startTime, _endTime, _segId, _robotNr, _robotSize, collision))
246  {
247  return false;
248  }
249 
250  int freeSpace = segmentSpace_[_segId];
251 
252  if (_endTime > maxTime_)
253  {
254  maxTime_ = _endTime;
255  }
256 
257  //Vertex has enough space
258  if (robotSegments_.size() <= _robotNr)
259  {
260  robotSegments_.resize(_robotNr + 1);
261  }
262 
263  robotSegments_[_robotNr].push_back(_segId);
264  timeline_[_segId].emplace_back(_robotNr, (float)_robotSize, _startTime, _endTime, _mainSeg);
265 
266  return true;
267 }
268 
269 bool RouteCoordinatorTimed::Timeline::addCrossingSegment(const uint32_t _startTime, const int32_t _endTime, const uint32_t _segId, const uint32_t _robotNr, const uint32_t _robotSize, const bool &_mainSeg)
270 {
271  if (_robotSize > segmentSpace_[_segId])
272  {
273  return addSegment(_startTime, _endTime, _segId, _robotNr, segmentSpace_[_segId], _mainSeg);
274  }
275 
276  return addSegment(_startTime, _endTime, _segId, _robotNr, _robotSize, _mainSeg);
277 }
278 
279 bool RouteCoordinatorTimed::Timeline::checkCrossingSegment(const uint32_t _startTime, const int32_t _endTime, const uint32_t _segId, const uint32_t _robotNr, const uint32_t _robotSize, int32_t &_lastCollisionRobot) const
280 {
281  if (_robotSize > segmentSpace_[_segId])
282  {
283  return checkSegment(_startTime, _endTime, _segId, _robotNr, segmentSpace_[_segId], _lastCollisionRobot);
284  }
285 
286  return checkSegment(_startTime, _endTime, _segId, _robotNr, _robotSize, _lastCollisionRobot);
287 }
288 
289 bool RouteCoordinatorTimed::Timeline::checkSegment(const uint32_t _startTime, const int32_t _endTime, const uint32_t _segId, const uint32_t _robotNr, const uint32_t _robotSize, int32_t &_lastCollisionRobot) const
290 {
291  _lastCollisionRobot = -1;
292 
293  //Return if to less space
294  int freeSpace = segmentSpace_[_segId];
295 
296  if (freeSpace < _robotSize)
297  {
298  return false;
299  }
300 
301  std::vector<bool> checkedRobots_(nrRobots_, false);
302 
303  for (const seg_occupation &occupation : timeline_[_segId])
304  {
305  if (occupation.robot != _robotNr && !checkedRobots_[occupation.robot])
306  {
307  if (_endTime == TIME_INFINITY || occupation.endTime == TIME_INFINITY)
308  {
309  if (_endTime == TIME_INFINITY && occupation.endTime == TIME_INFINITY)
310  {
311  freeSpace -= occupation.spaceOccupied;
312  _lastCollisionRobot = occupation.robot;
313  checkedRobots_[occupation.robot] = true;
314 
315  if (freeSpace < _robotSize)
316  {
317  return false;
318  }
319  }
320  else if (_endTime == TIME_INFINITY && _startTime <= occupation.endTime)
321  {
322  freeSpace -= occupation.spaceOccupied;
323  _lastCollisionRobot = occupation.robot;
324  checkedRobots_[occupation.robot] = true;
325 
326  if (freeSpace < _robotSize)
327  {
328  return false;
329  }
330  }
331  else if (occupation.endTime == TIME_INFINITY && _endTime >= occupation.startTime)
332  {
333  freeSpace -= occupation.spaceOccupied;
334  _lastCollisionRobot = occupation.robot;
335  checkedRobots_[occupation.robot] = true;
336 
337  if (freeSpace < _robotSize)
338  {
339  return false;
340  }
341  }
342  }
343  else
344  {
345 
346  if ((_startTime <= occupation.startTime && _endTime >= occupation.startTime) || (_startTime <= occupation.endTime && _endTime >= occupation.endTime))
347  {
348  freeSpace -= occupation.spaceOccupied;
349  _lastCollisionRobot = occupation.robot;
350  checkedRobots_[occupation.robot] = true;
351 
352  if (freeSpace < _robotSize)
353  {
354  return false;
355  }
356  }
357  else if ((_startTime >= occupation.startTime && _endTime <= occupation.endTime))
358  {
359  freeSpace -= occupation.spaceOccupied;
360  _lastCollisionRobot = occupation.robot;
361  checkedRobots_[occupation.robot] = true;
362 
363  if (freeSpace < _robotSize)
364  {
365  return false;
366  }
367  }
368  }
369  }
370  }
371 
372  //No collision
373  _lastCollisionRobot = -1;
374  return true;
375 }
376 
378 {
379  return maxTime_;
380 }
381 
382 int32_t RouteCoordinatorTimed::Timeline::findSegId(const int32_t _robot, const uint32_t _timestep) const
383 {
384  if (_robot < 0)
385  {
386  return -1;
387  }
388 
389  for (const int &s : robotSegments_[_robot])
390  {
391  for (const seg_occupation &occupation : timeline_[s])
392  {
393  if (occupation.robot == _robot && _timestep >= occupation.startTime && _timestep <= occupation.endTime && occupation.mainSeg)
394  {
395  return s;
396  }
397  }
398  }
399 
400  return -1;
401 }
402 
403 int32_t RouteCoordinatorTimed::Timeline::getTimeUntilRobotOnSegment(const int32_t _robotNr, const uint32_t _segId) const
404 {
405  int32_t ret = -2;
406 
407  for (const auto &occupation : timeline_[_segId])
408  {
409  if (occupation.robot == _robotNr)
410  {
411  ret = occupation.endTime;
412  }
413  }
414 
415  return ret;
416 }
417 
418 std::vector<std::pair<uint32_t, float>> RouteCoordinatorTimed::Timeline::getListOfRobotsHigherPrioritizedRobots(const uint32_t _robot, const uint32_t _segId, const int32_t _potential) const
419 {
420  std::vector<std::pair<uint32_t, float>> robots;
421 
422  seg_occupation occupationRobot(-1, -1, -1, -1);
423 
424  for (const auto &occupation : timeline_[_segId])
425  {
426  if (occupation.robot == _robot)
427  {
428  occupationRobot = occupation;
429  break;
430  }
431  }
432 
433  if (occupationRobot.robot != _robot)
434  return robots;
435 
436  for (const auto &occupation : timeline_[_segId])
437  {
438  if (occupation.robot != _robot && occupation.startTime < _potential)
439  {
440  if (segmentSpace_[_segId] - occupation.spaceOccupied < occupationRobot.spaceOccupied)
441  {
442  //Sort only if they would block each other
443  robots.push_back({occupation.robot, occupation.endTime});
444  }
445  }
446  }
447 
448  return robots;
449 }
450 
452 {
453  tmpRobot_ = _robot;
454 
455  for (std::vector<seg_occupation> &occ : timeline_)
456  {
457  occ.erase(std::remove_if(occ.begin(), occ.end(), [_robot](seg_occupation x) { return x.robot == _robot; }), occ.end());
458  }
459 
460  maxTime_ = 0;
461 
462  for (std::vector<seg_occupation> &occ : timeline_)
463  {
464  for (seg_occupation &o : occ)
465  {
466  if (o.endTime > maxTime_)
467  maxTime_ = o.endTime;
468  }
469  }
470 
471  if (robotSegments_.size() > _robot)
472  robotSegments_[_robot].clear();
473 }
474 
475 } // namespace multi_robot_router
uint32_t getSegmentId() const
Definition: srr_utils.cpp:60
void reset(const std::vector< Segment > &_graph, const uint32_t _nrRobots)
resets the planning session of multiple robots
void removeRobot(const uint32_t _robot)
removes a Robot from the Routing Table
uint32_t getSize() const
returns the length of the timeline (max Time)
const uint32_t getEnd(const uint32_t _robotId) const
returns the Goal of a robot
XmlRpcServer s
std::vector< std::pair< uint32_t, float > > getListOfRobotsHigherPrioritizedRobots(const uint32_t _robot, const uint32_t _segId, const int32_t _potential) const
returns all robots which pass the segment before the given robot and a given time ...
bool setStartSegments(const std::vector< uint32_t > &_startSegments)
updates the start segments of the planning attempt
int32_t findSegId(const int32_t _robot, const uint32_t _timestep) const
returns the segment id at which the robot is at timepoint _potential
int32_t findSegNr(const uint32_t _robot, const uint32_t _potential) const
returns the segment id at which the robot is at timepoint _potential
std::vector< std::pair< uint32_t, float > > getListOfRobotsHigherPrioritizedRobots(const uint32_t _robot, const uint32_t _segId, const int32_t _potential) const
returns all robots which pass the segment before the given robot and a given time ...
void removeRobot(const uint32_t _robot)
removes a Robot from the Routing Table
bool checkSegmentSingle(const Vertex &_next, const uint32_t _startTime, const int32_t _endTime, const uint32_t _diameterPixel, int32_t &_collisionRobot, const uint32_t _robotId, const bool &_ignoreGoal) const
bool checkCrossingSegment(const uint32_t _startTime, const int32_t _endTime, const uint32_t _segId, const uint32_t _robotNr, const uint32_t _robotSize, int32_t &_lastCollisionRobot) const
checks if a robot can enter a segment at a specific time if located in a crossing (neighbours > 1) ...
bool checkSegment(const uint32_t _startTime, const int32_t _endTime, const uint32_t _segId, const uint32_t _robotNr, const uint32_t _robotSize, int32_t &_lastCollisionRobot) const
checks if a robot can enter a segment at a specific time
bool addCrossingSegment(const uint32_t _startTime, const int32_t _endTime, const uint32_t _segId, const uint32_t _robotNr, const uint32_t _robotSize, const bool &_mainSeg)
adds a segment in a crossing (neighbours > 1) to the timeline and checks if the occupation is valid ...
bool isGoal(const Vertex &_seg, const uint32_t _robotId) const
returns if a Vertex is the goal vertex for a robot
TFSIMD_FORCE_INLINE const tfScalar & x() const
const std::vector< uint32_t > & getSuccessors() const
Definition: srr_utils.cpp:69
#define TIME_INFINITY
int32_t findPotentialUntilRobotOnSegment(const uint32_t _robot, const uint32_t _segId) const
returns the time point, when a robot leaves a vertex
bool addSegment(const uint32_t _startTime, const int32_t _endTime, const uint32_t _segId, const uint32_t _robotNr, const uint32_t _robotSize, bool _mainSeg)
adds a segment to the timeline and checks if the occupation is valid
const Segment & getSegment() const
Definition: srr_utils.cpp:88
bool addRoute(const std::vector< RouteVertex > &_path, const uint32_t _diameterPixel, const uint32_t _robotId)
adds a new route to the Routing table and checks if the Routing Table is valid
const uint32_t getStart(const uint32_t _robotId) const
returns the start of a robot
const std::vector< uint32_t > & getPredecessors() const
Definition: srr_utils.cpp:55
bool checkSegment(const Vertex &_next, const uint32_t _startTime, const int32_t _endTime, const uint32_t _diameterPixel, int32_t &_collisionRobot, const uint32_t _robotId, bool _ignoreGoal=false) const
checks if a robot can enter a segment at a specific time
int32_t getTimeUntilRobotOnSegment(const int32_t _robotNr, const uint32_t _segId) const
returns the time point, when a robot leaves a vertex
bool setGoalSegments(const std::vector< uint32_t > &_goalSegments)
updates the goal segments of the planning attempt
void reset(const std::vector< Segment > &_graph, const uint32_t _nrRobots)
resets the planning session of multiple robots


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