multi_robot_router.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 
34 namespace multi_robot_router
35 {
36 //TODO Multithreaded
37 
38  MultiRobotRouter::MultiRobotRouter(const uint32_t _nr_robots, const std::vector<uint32_t> &_robotDiameter) : RouteGenerator(), priority_scheduler_(_nr_robots), speed_scheduler_(_nr_robots)
39  {
40  setRobotNr(_nr_robots);
41  robotDiameter_ = _robotDiameter;
43  }
44 
45  MultiRobotRouter::MultiRobotRouter(const uint32_t _nr_robots) : RouteGenerator(), priority_scheduler_(_nr_robots), speed_scheduler_(_nr_robots)
46  {
47  setRobotNr(_nr_robots);
48  std::vector<uint32_t> robotDiameter(_nr_robots, 0);
49  robotDiameter_ = robotDiameter;
51  }
52 
53 
55  {
56  cResType_ = cRes;
57  }
58 
59 
60  void MultiRobotRouter::setRobotNr(const uint32_t _nr_robots)
61  {
62  nr_robots_ = _nr_robots;
63  priority_scheduler_.reset(_nr_robots);
64  }
65 
66  void MultiRobotRouter::setRobotDiameter(const std::vector< uint32_t > &_diameter)
67  {
68  robotDiameter_.clear();
69  robotDiameter_ = _diameter;
70  min_diameter_ = std::numeric_limits<uint32_t>::max();
71 
72  for(const uint32_t d : robotDiameter_)
73  {
74  min_diameter_ = std::min(min_diameter_, d);
75  }
76  }
77 
78  void MultiRobotRouter::resetAttempt(const std::vector< Segment > &_graph)
79  {
83  robotCollisions_.clear();
87  }
88 
90  {
92  }
93 
95  {
97  }
98 
99  bool MultiRobotRouter::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)
100  {
101  std::chrono::time_point<std::chrono::high_resolution_clock> tstart = std::chrono::high_resolution_clock::now();
102 
103  resetAttempt(_graph);
104  route_coordinator_->setStartSegments(_startSegments);
105  route_coordinator_->setGoalSegments(_goalSegments);
106 
107  maxIterationsSingleRobot_ = _graph.size();
108 
111 
112  std::vector<std::vector<RouteVertex>> routeCandidates;
113  routeCandidates.resize(nr_robots_);
114 
115  std::vector<uint32_t> priorityList = priority_scheduler_.getActualSchedule();
116  std::vector<float> speedList = speed_scheduler_.getActualSpeeds();
117  uint32_t firstSchedule = 0;
118  bool found = false;
119  uint32_t lastPlannedRobot;
120  float duration = 0;
121 
122  do
123  {
124  int32_t firstRobot = -1;
125  do
126  {
127  //Find first schedule to replan if speed rescheduling was active
128  //(used for removing from path coordinator)
129  if(firstRobot != -1)
130  {
131  for(uint32_t i = 0; i < priorityList.size(); i++)
132  {
133  if(priorityList[i] == firstRobot)
134  firstSchedule = i;
135  }
136  }
137  found = planPaths(priorityList, speedList, _startSegments, _goalSegments, firstSchedule, routeCandidates, lastPlannedRobot);
138 
140  std::chrono::time_point<std::chrono::high_resolution_clock> tgoal = std::chrono::high_resolution_clock::now();
141  duration = std::chrono::duration_cast<std::chrono::milliseconds>(tgoal - tstart).count();
142  duration /= 1000;
143  }
144  while(useSpeedRescheduler_ && duration < _timeLimit && !found && speed_scheduler_.rescheduleSpeeds(lastPlannedRobot, srr.getRobotCollisions(), speedList, firstRobot) );
145 
147  }
148  while(usePriorityRescheduler_ && duration < _timeLimit && !found && priority_scheduler_.reschedulePriorities(lastPlannedRobot, srr.getRobotCollisions(), priorityList, firstSchedule));
149  routingTable = generatePath(routeCandidates, *route_coordinator_);
150 
151  return found;
152  }
153 
154  bool MultiRobotRouter::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)
155  {
156  bool found = false;
157 
158  //Remove only schedules (robots) which have to be replanned
159  for(uint32_t i = _firstSchedule; i < nr_robots_; i++)
160  {
161  _robot = _priorityList[i];
163  }
164 
165  //Find a plan for each robot with no plan
166  for(uint32_t i = _firstSchedule; i < nr_robots_; i++)
167  {
168  found = false;
169  _robot = _priorityList[i];
170 
171  //route_coordinator_->setActive(_robot);
172 
173  RouteCoordinatorWrapper rcWrapper(_robot, *route_coordinator_);
174  //Worst case scenario: Search whole graph once + n * (move through whole graph to avoid other robot) -> graph.size() * (i+1) iterations
175  if(!srr.getRouteCandidate(_startSegments[_robot], _goalSegments[_robot], rcWrapper, robotDiameter_[_robot], _speedList[_robot], _routeCandidates[_robot], maxIterationsSingleRobot_ * (i + 1)))
176  {
177  //ROS_INFO("Failed Robot");
179  robotCollisions_[_robot].resize(nr_robots_, 0);
180  break;
181  }
182 
184  robotCollisions_[_robot].resize(nr_robots_, 0);
185 
186  if(!route_coordinator_->addRoute(_routeCandidates[_robot], robotDiameter_[_robot], _robot))
187  {
188  ROS_INFO("Failed coordinator");
189  break;
190  }
191 
192  found = true;
193  }
194 
195  return found;
196  }
197 
199  {
200  usePriorityRescheduler_ = _status;
201  }
202 
203  void MultiRobotRouter::setSpeedRescheduling(const bool _status)
204  {
205  useSpeedRescheduler_ = _status;
206  }
207 
208 
209 }
210 
211 
d
void reset(const uint32_t _nrRobots)
resets the Priority schedule with an initial priority schedule
virtual void removeRobot(const uint32_t _robot)=0
removes a Robot from the Routing Table
virtual const uint32_t getPriorityScheduleAttempts() const
returns the number of attemps to reschedul the priorities taken
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)
MultiRobotRouter(const uint32_t _nr_robots, const std::vector< uint32_t > &_robotDiameter)
constructor
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 void setSpeedRescheduling(const bool _status)
enables or disables speed rescheduling
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 setCollisionResolver(const SegmentExpander::CollisionResolverType cRes)
sets the CollisionResolverType used to resolve occured robot collisions
SegmentExpander::CollisionResolverType cResType_
virtual bool setStartSegments(const std::vector< uint32_t > &_startSegments)=0
updates the start segments of the planning attempt
void reset(const uint32_t _nrRobots)
resets the speed rescheduler (all speeds to max)
std::vector< std::vector< uint32_t > > robotCollisions_
virtual void setRobotDiameter(const std::vector< uint32_t > &_diameter)
sets the robot diameter for every robot
const std::vector< uint32_t > & getRobotCollisions() const
returns the found robot collisions while planning
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 ...
#define ROS_INFO(...)
void resetAttempt(const std::vector< Segment > &_graph)
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
void initSearchGraph(const std::vector< Segment > &_graph, const uint32_t minSegmentWidth_=0)
generates the search graph out of the given graph (and optimizes it)
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 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
virtual void setPriorityRescheduling(const bool _status)
enables or disables priority rescheduling
virtual const uint32_t getSpeedScheduleAttempts() const
returns the number of attemps to limit the maximum speed of a robot taken
void setCollisionResolver(const SegmentExpander::CollisionResolverType cRes)
sets the collisionResolver used
virtual void reset(const std::vector< Segment > &_graph, const uint32_t _nrRobots)=0
resets the planning session of multiple robots
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 setRobotNr(const uint32_t _nr_robots)
sets the number of robots used


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