multi_robot_router_threaded_srr.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 <chrono>
31 #include <iostream>
32 #include <ros/ros.h>
33 #include <thread>
34 
35 namespace multi_robot_router
36 {
37  MultiRobotRouterThreadedSrr::MultiRobotRouterThreadedSrr(const uint32_t _nr_robots, const std::vector<uint32_t> &_robotDiameter, const uint32_t _threads) : MultiRobotRouter(_nr_robots, _robotDiameter), priority_scheduler_(_nr_robots), speed_scheduler_(_nr_robots)
38  {
39  setThreads(_threads);
40  setRobotNr(_nr_robots);
41  robotDiameter_ = _robotDiameter;
43 
44  for(uint32_t i = 0; i < threads_; i++)
45  {
47  srr.push_back(sr);
48  }
49 
50  }
51 
52  MultiRobotRouterThreadedSrr::MultiRobotRouterThreadedSrr(const uint32_t _nr_robots, const uint32_t _threads) : MultiRobotRouter(_nr_robots), priority_scheduler_(_nr_robots), speed_scheduler_(_nr_robots)
53  {
54  setThreads(_threads);
55  setRobotNr(_nr_robots);
56  std::vector<uint32_t> robotRadius(_nr_robots, 0);
57  robotDiameter_ = robotRadius;
59 
60  for(uint32_t i = 0; i < threads_; i++)
61  {
63  srr.push_back(sr);
64  }
65  }
66 
67 
68  void MultiRobotRouterThreadedSrr::setThreads(const uint32_t _threads)
69  {
70  threads_ = _threads;
71  }
72 
73 
75  {
76  cResType_ = cRes;
77  }
78 
79 
80  void MultiRobotRouterThreadedSrr::setRobotNr(const uint32_t _nr_robots)
81  {
82  nr_robots_ = _nr_robots;
83  priority_scheduler_.reset(_nr_robots);
84  }
85 
86  void MultiRobotRouterThreadedSrr::setRobotDiameter(const std::vector< uint32_t > &_diameter)
87  {
88  robotDiameter_.clear();
89  robotDiameter_ = _diameter;
90  min_diameter_ = std::numeric_limits<uint32_t>::max();
91 
92  for(const uint32_t d : robotDiameter_)
93  {
94  min_diameter_ = std::min(min_diameter_, d);
95  }
96  }
97 
98  void MultiRobotRouterThreadedSrr::resetAttempt(const std::vector< Segment > &_graph)
99  {
103  robotCollisions_.clear();
107  }
108 
110  {
112  }
113 
115  {
116  return speedScheduleAttempts_;
117  }
118 
119  bool MultiRobotRouterThreadedSrr::getRoutingTable(const std::vector<Segment> &_graph, const std::vector<uint32_t> &_startSegments, const std::vector<uint32_t> &_goalSegments, std::vector<std::vector< Checkpoint>> &routingTable, const float &_timeLimit)
120  {
121  std::chrono::time_point<std::chrono::high_resolution_clock> tstart = std::chrono::high_resolution_clock::now();
122 
123  resetAttempt(_graph);
124  route_coordinator_->setStartSegments(_startSegments);
125  route_coordinator_->setGoalSegments(_goalSegments);
126 
127  maxIterationsSingleRobot_ = _graph.size();
128 
129  for(SingleRobotRouter & sr : srr)
130  {
131  sr.setCollisionResolver(cResType_);
132  sr.initSearchGraph(_graph, min_diameter_);
133  }
134 
135  std::vector<std::vector<RouteVertex>> routeCandidates;
136  routeCandidates.resize(nr_robots_);
137 
138  std::vector<uint32_t> priorityList = priority_scheduler_.getActualSchedule();
139  std::vector<float> speedList = speed_scheduler_.getActualSpeeds();
140  uint32_t firstSchedule = 0;
141  bool found = false;
142  uint32_t lastPlannedRobot;
143  float duration = 0;
144 
145  do
146  {
147  int32_t firstRobot = -1;
148 
149  do
150  {
151  //Find first schedule to replan if speed rescheduling was active
152  //(used for removing from path coordinator)
153  if(firstRobot != -1)
154  {
155  for(uint32_t i = 0; i < priorityList.size(); i++)
156  {
157  if(priorityList[i] == firstRobot)
158  firstSchedule = i;
159  }
160  }
161 
162  found = planPaths(priorityList, speedList, _startSegments, _goalSegments, firstSchedule, routeCandidates, lastPlannedRobot);
163 
165  std::chrono::time_point<std::chrono::high_resolution_clock> tgoal = std::chrono::high_resolution_clock::now();
166  duration = std::chrono::duration_cast<std::chrono::milliseconds>(tgoal - tstart).count();
167  duration /= 1000;
168  }
169  while(useSpeedRescheduler_ && duration < _timeLimit && !found && speed_scheduler_.rescheduleSpeeds(lastPlannedRobot, robotCollisions_[lastPlannedRobot], speedList, firstRobot));
170 
172  }
173  while(usePriorityRescheduler_ && duration < _timeLimit && !found && priority_scheduler_.reschedulePriorities(lastPlannedRobot, robotCollisions_[lastPlannedRobot], priorityList, firstSchedule));
174 
175  routingTable = generatePath(routeCandidates, *route_coordinator_);
176 
177  return found;
178  }
179 
180  //TODO Optimize
181  bool MultiRobotRouterThreadedSrr::planPaths(const std::vector<uint32_t> &_priorityList, const std::vector<float> &_speedList, const std::vector<uint32_t> &_startSegments, const std::vector<uint32_t> &_goalSegments, const uint32_t _firstSchedule, std::vector<std::vector<RouteVertex>> &_routeCandidates, uint32_t &_lastRobot)
182  {
183  //Remove only schedules (robots) which have to be replanned
184  for(uint32_t i = _firstSchedule; i < nr_robots_; i++)
185  {
186  uint32_t robot = _priorityList[i];
188  }
189 
190 
191  uint32_t plannedRobots = _firstSchedule;
192 
193  while(plannedRobots < nr_robots_)
194  {
195  uint32_t maxCount = std::min(plannedRobots + threads_, nr_robots_);
196  uint32_t startCount = plannedRobots;
197  int32_t currentFailedI = -1;
198 
199 
200 
201  std::vector<std::thread> s;
202  s.resize(maxCount - startCount);
203 
204  std::vector<RouteCoordinatorWrapper> rcWrappers;
205  for(int i = startCount; i < maxCount; i++)
206  {
207  uint32_t robot = _priorityList[i];
209  rcWrappers.push_back(rcW);
210  }
211 
212  for(int i = startCount; i < maxCount; i++)
213  {
214  uint32_t robot = _priorityList[i];
215  uint32_t start = _startSegments[robot];
216  uint32_t goal = _goalSegments[robot];
217  uint32_t diameter = robotDiameter_[robot];
218  float speed = _speedList[robot];
219  std::vector<RouteVertex> &routeCandidate = _routeCandidates[robot];
220  uint32_t iter = maxIterationsSingleRobot_ * (i + 1);
221  uint32_t index = i - startCount;
222  SingleRobotRouter &sr = srr[index];
223  RouteCoordinatorWrapper &wr = rcWrappers[index];
224  s[index] = std::thread( //TODO not working multi threaded
225  [wr, robot, start, goal, diameter, speed, &routeCandidate, iter, &sr]()
226  {
227  sr.getRouteCandidate(start, goal, wr, diameter, speed, routeCandidate, iter);
228 
229  });
230 
231  // s[index].join();
232 
233  //Worst case scenario: Search whole graph once + n * (move through whole graph to avoid other robot) -> graph.size() * (i+1) iterations
234  //srr[i - startCount].getRouteCandidate(_startSegments[robot], _goalSegments[robot], rcWrapper, robotDiameter_[robot], _speedList[robot], _routeCandidates[robot], maxIterationsSingleRobot_ * (i + 1));
235 
236  }
237 
238 
239  for(std::thread & t : s)
240  {
241  if(t.joinable())
242  t.join();
243  }
244 
245  for(uint32_t i = startCount; i < maxCount; i++)
246  {
247  uint32_t robot = _priorityList[i];
248  uint32_t planner = i - startCount;
249  _lastRobot = robot;
250 
251  robotCollisions_[robot] = srr[planner].getRobotCollisions();
252  robotCollisions_[robot].resize(nr_robots_, 0);
253 
254  if(!srr[planner].getLastResult())
255  {
256 // //std::cout << "srr " << i << planner << std::endl;
257  return false;
258  }
259 
260  if(!route_coordinator_->addRoute(_routeCandidates[robot], robotDiameter_[robot], robot))
261  {
262  if(i == startCount)
263  {
264  ROS_INFO("Failed coordinator");
265  return false;
266  }
267 
268  //Replan from plannedRobots
269  break;
270  }
271  else
272  {
273  plannedRobots++;
274  }
275 
276  }
277 
278  }
279 
280  return true;
281  }
282 
284  {
285  usePriorityRescheduler_ = _status;
286  }
287 
289  {
290  useSpeedRescheduler_ = _status;
291  }
292 
293 
294 }
295 
296 
d
void reset(const uint32_t _nrRobots)
resets the Priority schedule with an initial priority schedule
MultiRobotRouterThreadedSrr(const uint32_t _nr_robots, const std::vector< uint32_t > &_robotDiameter, const uint32_t _threads)
constructor
standard multi robot router without multi threading (Works best in practice)
virtual void removeRobot(const uint32_t _robot)=0
removes a Robot from the Routing Table
bool planPaths(const std::vector< uint32_t > &_priorityList, const std::vector< float > &_speedList, const std::vector< uint32_t > &_startSegments, const std::vector< uint32_t > &_goalSegments, const uint32_t _firstSchedule, std::vector< std::vector< RouteVertex >> &_routeCandidates, uint32_t &_robot)
XmlRpcServer s
bool getRouteCandidate(const uint32_t _start, const uint32_t _goal, const RouteCoordinatorWrapper &path_coordinator, const uint32_t _robotDiameter, const float &_robotSpeed, std::vector< RouteVertex > &path, const uint32_t _maxIterations)
calculates a route candidate coordinated with other robots by the given route Coordinated ...
virtual bool setGoalSegments(const std::vector< uint32_t > &_goalSegments)=0
updates the goal segments of the planning attempt
virtual bool addRoute(const std::vector< RouteVertex > &_path, const uint32_t _diameterPixel, const uint32_t _robotId)=0
checks if a robot can enter a segment at a specific time
virtual void setRobotDiameter(const std::vector< uint32_t > &_diameter)
sets the robot diameter for every robot
virtual bool setStartSegments(const std::vector< uint32_t > &_startSegments)=0
updates the start segments of the planning attempt
virtual void setThreads(const uint32_t _threads)
sets the number of threads
void reset(const uint32_t _nrRobots)
resets the speed rescheduler (all speeds to max)
std::vector< std::vector< Checkpoint > > generatePath(const std::vector< std::vector< RouteVertex >> &_paths, const RouteCoordinator &routeQuerry_) const
generates a final Routing Table containing Segment List and Preconditions to other robots ...
virtual bool getRoutingTable(const std::vector< Segment > &_graph, const std::vector< uint32_t > &_startSegments, const std::vector< uint32_t > &_goalSegments, std::vector< std::vector< Checkpoint >> &_routingTable, const float &_timeLimit)
computes the routing table according to the given start and goal _goalSegments
#define ROS_INFO(...)
bool rescheduleSpeeds(const uint32_t _collidingRobot, const std::vector< uint32_t > &_collsisions, std::vector< float > &_newSchedule, int32_t &_firstRobotToReplan)
reduces a selected robots maximum speed
virtual void setCollisionResolver(const SegmentExpander::CollisionResolverType cRes)
sets the CollisionResolverType used to resolve occured robot collisions
bool reschedulePriorities(const uint32_t _collidingRobot, std::vector< uint32_t > _collsisions, std::vector< uint32_t > &_newSchedule, uint32_t &_firstRobotToReplan)
rescedules priorities depending on the ound collisions and allready tried schedules ...
virtual void setRobotNr(const uint32_t _nr_robots)
sets the number of robots used
virtual const uint32_t getPriorityScheduleAttempts() const
returns the number of attemps to reschedul the priorities taken
virtual void setSpeedRescheduling(const bool _status)
enables or disables speed rescheduling
virtual void reset(const std::vector< Segment > &_graph, const uint32_t _nrRobots)=0
resets the planning session of multiple robots
virtual const uint32_t getSpeedScheduleAttempts() const
returns the number of attemps to limit the maximum speed of a robot taken
void resetAttempt(const std::vector< Segment > &_graph)
const std::vector< float > & getActualSpeeds()
returns the computed speed schedule
const std::vector< uint32_t > & getActualSchedule() const
returns the currently produced speed schedule
virtual void setPriorityRescheduling(const bool _status)
enables or disables priority rescheduling


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