Eclipse SUMO - Simulation of Urban MObility
MSEdgeControl.cpp
Go to the documentation of this file.
1 /****************************************************************************/
2 // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
3 // Copyright (C) 2001-2019 German Aerospace Center (DLR) and others.
4 // This program and the accompanying materials
5 // are made available under the terms of the Eclipse Public License v2.0
6 // which accompanies this distribution, and is available at
7 // http://www.eclipse.org/legal/epl-v20.html
8 // SPDX-License-Identifier: EPL-2.0
9 /****************************************************************************/
18 // Stores edges and lanes, performs moving of vehicle
19 /****************************************************************************/
20 
21 
22 // ===========================================================================
23 // included modules
24 // ===========================================================================
25 #include <config.h>
26 
27 #include <iostream>
28 #include <queue>
29 #include <vector>
30 #include "MSEdgeControl.h"
31 #include "MSVehicleControl.h"
32 #include "MSGlobals.h"
33 #include "MSEdge.h"
34 #include "MSLane.h"
35 #include "MSVehicle.h"
36 
37 #define PARALLEL_PLAN_MOVE
38 //#define PARALLEL_EXEC_MOVE
39 //#define PARALLEL_CHANGE_LANES
40 //#define LOAD_BALANCING
41 
42 // ===========================================================================
43 // member method definitions
44 // ===========================================================================
45 MSEdgeControl::MSEdgeControl(const std::vector< MSEdge* >& edges)
46  : myEdges(edges),
47  myLanes(MSLane::dictSize()),
48  myWithVehicles2Integrate(MSGlobals::gNumSimThreads > 1),
49  myLastLaneChange(MSEdge::dictSize()) {
50  // build the usage definitions for lanes
51  for (std::vector< MSEdge* >::const_iterator i = myEdges.begin(); i != myEdges.end(); ++i) {
52  const std::vector<MSLane*>& lanes = (*i)->getLanes();
53  if (!(*i)->hasLaneChanger()) {
54  int pos = (*lanes.begin())->getNumericalID();
55  myLanes[pos].lane = *(lanes.begin());
56  myLanes[pos].amActive = false;
57  myLanes[pos].haveNeighbors = false;
58  } else {
59  for (std::vector<MSLane*>::const_iterator j = lanes.begin(); j != lanes.end(); ++j) {
60  int pos = (*j)->getNumericalID();
61  myLanes[pos].lane = *j;
62  myLanes[pos].amActive = false;
63  myLanes[pos].haveNeighbors = true;
64  }
65  myLastLaneChange[(*i)->getNumericalID()] = -1;
66  }
67  }
68 }
69 
70 
72 }
73 
74 
75 void
77  for (std::set<MSLane*, ComparatorNumericalIdLess>::iterator i = myChangedStateLanes.begin(); i != myChangedStateLanes.end(); ++i) {
78  LaneUsage& lu = myLanes[(*i)->getNumericalID()];
79  // if the lane was inactive but is now...
80  if (!lu.amActive && (*i)->getVehicleNumber() > 0) {
81  // ... add to active lanes and mark as such
82  if (lu.haveNeighbors) {
83  myActiveLanes.push_front(*i);
84  } else {
85  myActiveLanes.push_back(*i);
86  }
87  lu.amActive = true;
88  }
89  }
90  myChangedStateLanes.clear();
91 }
92 
93 
94 void
96 #ifdef HAVE_FOX
97  if (MSGlobals::gNumSimThreads > 1) {
98  while (myThreadPool.size() < MSGlobals::gNumSimThreads) {
99  new FXWorkerThread(myThreadPool);
100  }
101  }
102 #endif
103 #ifdef LOAD_BALANCING
104  myRNGLoad = std::priority_queue<std::pair<int, int> >();
105  for (int i = 0; i < MSLane::getNumRNGs(); i++) {
106  myRNGLoad.emplace(0, i);
107  }
108 #endif
109  for (std::list<MSLane*>::iterator i = myActiveLanes.begin(); i != myActiveLanes.end();) {
110  const int vehNum = (*i)->getVehicleNumber();
111  if (vehNum == 0) {
112  myLanes[(*i)->getNumericalID()].amActive = false;
113  i = myActiveLanes.erase(i);
114  } else {
115 #ifdef LOAD_BALANCING
116  std::pair<int, int> minRNG = myRNGLoad.top();
117  (*i)->setRNGIndex(minRNG.second);
118  myRNGLoad.pop();
119  minRNG.first -= vehNum;
120  myRNGLoad.push(minRNG);
121 #endif
122 #ifdef HAVE_FOX
123  if (MSGlobals::gNumSimThreads > 1) {
124  myThreadPool.add((*i)->getPlanMoveTask(t), (*i)->getRNGIndex() % myThreadPool.size());
125  ++i;
126  continue;
127  }
128 #endif
129  (*i)->planMovements(t);
130  ++i;
131  }
132  }
133 #ifdef HAVE_FOX
134  if (MSGlobals::gNumSimThreads > 1) {
135  myThreadPool.waitAll(false);
136  }
137 #endif
138 }
139 
140 
141 void
143  for (MSLane* const lane : myActiveLanes) {
144  lane->setJunctionApproaches(t);
145  }
146 }
147 
148 
149 void
151  std::vector<MSLane*> wasActive(myActiveLanes.begin(), myActiveLanes.end());
153 #ifdef HAVE_FOX
154 #ifdef PARALLEL_EXEC_MOVE
155  if (MSGlobals::gNumSimThreads > 1) {
156 #ifdef LOAD_BALANCING
157  myRNGLoad = std::priority_queue<std::pair<int, int> >();
158  for (int i = 0; i < MSLane::getNumRNGs(); i++) {
159  myRNGLoad.emplace(0, i);
160  }
161 #endif
162  for (MSLane* const lane : myActiveLanes) {
163 #ifdef LOAD_BALANCING
164  std::pair<int, int> minRNG = myRNGLoad.top();
165  lane->setRNGIndex(minRNG.second);
166  myRNGLoad.pop();
167  minRNG.first -= lane->getVehicleNumber();
168  myRNGLoad.push(minRNG);
169 #endif
170  myThreadPool.add(lane->getExecuteMoveTask(t), lane->getRNGIndex() % myThreadPool.size());
171  }
172  myThreadPool.waitAll(false);
173  }
174 #endif
175 #endif
176  for (std::list<MSLane*>::iterator i = myActiveLanes.begin(); i != myActiveLanes.end();) {
177  if (
178 #ifdef PARALLEL_EXEC_MOVE
180 #endif
181  (*i)->getVehicleNumber() > 0) {
182  (*i)->executeMovements(t);
183  }
184  if ((*i)->getVehicleNumber() == 0) {
185  myLanes[(*i)->getNumericalID()].amActive = false;
186  i = myActiveLanes.erase(i);
187  } else {
188  ++i;
189  }
190  }
191  for (MSLane* lane : wasActive) {
192  lane->updateLengthSum();
193  }
195  std::vector<MSLane*>& toIntegrate = myWithVehicles2Integrate.getContainer();
196  std::sort(toIntegrate.begin(), toIntegrate.end(), ComparatorIdLess());
198  for (MSLane* const lane : toIntegrate) {
199  const bool wasInactive = lane->getVehicleNumber() == 0;
200  lane->integrateNewVehicles();
201  if (wasInactive && lane->getVehicleNumber() > 0) {
202  LaneUsage& lu = myLanes[lane->getNumericalID()];
203  if (!lu.amActive) {
204  if (lu.haveNeighbors) {
205  myActiveLanes.push_front(lane);
206  } else {
207  myActiveLanes.push_back(lane);
208  }
209  lu.amActive = true;
210  }
211  }
212  }
213 }
214 
215 
216 void
218  std::vector<MSLane*> toAdd;
219 #ifdef PARALLEL_CHANGE_LANES
220  std::vector<MSEdge*> recheckLaneUsage;
221 #endif
222  MSGlobals::gComputeLC = true;
223  for (std::list<MSLane*>::iterator i = myActiveLanes.begin(); i != myActiveLanes.end();) {
224  LaneUsage& lu = myLanes[(*i)->getNumericalID()];
225  if (lu.haveNeighbors) {
226  MSEdge& edge = (*i)->getEdge();
227  if (myLastLaneChange[edge.getNumericalID()] != t) {
228  myLastLaneChange[edge.getNumericalID()] = t;
229 #ifdef PARALLEL_CHANGE_LANES
230  if (MSGlobals::gNumSimThreads > 1) {
231  MSLane* lane = edge.getLanes()[0];
232  myThreadPool.add(lane->getLaneChangeTask(t), lane->getRNGIndex() % myThreadPool.size());
233  recheckLaneUsage.push_back(&edge);
234  } else {
235 #endif
236  edge.changeLanes(t);
237  const std::vector<MSLane*>& lanes = edge.getLanes();
238  for (std::vector<MSLane*>::const_iterator i = lanes.begin(); i != lanes.end(); ++i) {
239  LaneUsage& lu = myLanes[(*i)->getNumericalID()];
240  //if ((*i)->getID() == "disabled") {
241  // std::cout << SIMTIME << " vehicles=" << toString((*i)->getVehiclesSecure()) << "\n";
242  // (*i)->releaseVehicles();
243  //}
244  if ((*i)->getVehicleNumber() > 0 && !lu.amActive) {
245  toAdd.push_back(*i);
246  lu.amActive = true;
247  }
248  }
249 #ifdef PARALLEL_CHANGE_LANES
250  }
251 #endif
252  }
253  ++i;
254  } else {
255  i = myActiveLanes.end();
256  }
257  }
258 
259 #ifdef PARALLEL_CHANGE_LANES
260  if (MSGlobals::gNumSimThreads > 1) {
261  myThreadPool.waitAll(false);
262  for (MSEdge* e : recheckLaneUsage) {
263  const std::vector<MSLane*>& lanes = e->getLanes();
264  for (std::vector<MSLane*>::const_iterator i = lanes.begin(); i != lanes.end(); ++i) {
265  LaneUsage& lu = myLanes[(*i)->getNumericalID()];
266  if ((*i)->getVehicleNumber() > 0 && !lu.amActive) {
267  toAdd.push_back(*i);
268  lu.amActive = true;
269  }
270  }
271  }
272  }
273 #endif
274 
275  MSGlobals::gComputeLC = false;
276  for (std::vector<MSLane*>::iterator i = toAdd.begin(); i != toAdd.end(); ++i) {
277  myActiveLanes.push_front(*i);
278  }
280  // sort maneuver reservations
281  for (LaneUsageVector::iterator it = myLanes.begin(); it != myLanes.end(); ++it) {
282  (*it).lane->sortManeuverReservations();
283  }
284  }
285 }
286 
287 
288 void
289 MSEdgeControl::detectCollisions(SUMOTime timestep, const std::string& stage) {
290  // Detections is made by the edge's lanes, therefore hand over.
291  for (MSLane* lane : myActiveLanes) {
292  if (lane->needsCollisionCheck()) {
293  lane->detectCollisions(timestep, stage);
294  }
295  }
296  if (myInactiveCheckCollisions.size() > 0) {
297  for (MSLane* lane : myInactiveCheckCollisions) {
298  lane->detectCollisions(timestep, stage);
299  }
300  myInactiveCheckCollisions.clear();
301  }
302 }
303 
304 
305 void
307  myChangedStateLanes.insert(l);
308 }
309 
310 void
312  myInactiveCheckCollisions.insert(l);
313 }
314 
315 void
317  for (MSEdgeVector::const_iterator i = myEdges.begin(); i != myEdges.end(); ++i) {
318  const std::vector<MSLane*>& lanes = (*i)->getLanes();
319  for (std::vector<MSLane*>::const_iterator j = lanes.begin(); j != lanes.end(); ++j) {
320  (*j)->initRestrictions();
321  }
322  }
323 }
324 
325 
326 /****************************************************************************/
327 
std::list< MSLane * > myActiveLanes
The list of active (not empty) lanes.
static double gLateralResolution
Definition: MSGlobals.h:85
long long int SUMOTime
Definition: SUMOTime.h:35
static int getNumRNGs()
return the number of RNGs
Definition: MSLane.h:228
int getRNGIndex() const
returns the associated RNG index
Definition: MSLane.h:218
~MSEdgeControl()
Destructor.
std::set< MSLane *, ComparatorNumericalIdLess > myChangedStateLanes
Lanes which changed the state without informing the control.
void checkCollisionForInactive(MSLane *l)
trigger collision checking for inactive lane
void patchActiveLanes()
Resets information whether a lane is active for all lanes.
static bool gComputeLC
whether the simulationLoop is in the lane changing phase
Definition: MSGlobals.h:121
std::set< MSLane *, ComparatorNumericalIdLess > myInactiveCheckCollisions
Additional lanes for which collision checking must be performed.
LaneUsageVector myLanes
Information about lanes&#39; number of vehicles and neighbors.
const std::vector< MSLane * > & getLanes() const
Returns this edge&#39;s lanes.
Definition: MSEdge.h:165
static MSNet * getInstance()
Returns the pointer to the unique instance of MSNet (singleton).
Definition: MSNet.cpp:168
bool amActive
Information whether this lane is active.
A structure holding some basic information about a simulated lane.
void gotActive(MSLane *l)
Informs the control that the given lane got active.
void detectCollisions(SUMOTime timestep, const std::string &stage)
Detect collisions.
int getNumericalID() const
Returns the numerical id of the edge.
Definition: MSEdge.h:263
void setAdditionalRestrictions()
apply additional restrictions
FXSynchQue< MSLane *, std::vector< MSLane * > > myWithVehicles2Integrate
A storage for lanes which shall be integrated because vehicles have moved onto them.
Container & getContainer()
Definition: FXSynchQue.h:74
void setJunctionApproaches(SUMOTime t)
Register junction approaches for all vehicles after velocities have been planned. This is a prerequis...
A road/street connecting two junctions.
Definition: MSEdge.h:76
std::priority_queue< std::pair< int, int > > myRNGLoad
static int gNumSimThreads
how many threads to use for simulation
Definition: MSGlobals.h:124
MSVehicleControl & getVehicleControl()
Returns the vehicle control.
Definition: MSNet.h:337
std::vector< SUMOTime > myLastLaneChange
The list of active (not empty) lanes.
void changeLanes(const SUMOTime t)
Moves (precomputes) critical vehicles.
MSEdgeVector myEdges
Loaded edges.
void planMovements(SUMOTime t)
Compute safe velocities for all vehicles based on positions and speeds from the last time step...
void executeMovements(SUMOTime t)
Executes planned vehicle movements with regards to right-of-way.
void unlock()
Definition: FXSynchQue.h:83
void clear()
Definition: FXSynchQue.h:120
virtual void changeLanes(SUMOTime t)
Performs lane changing on this edge.
Definition: MSEdge.cpp:699
void removePending()
Removes a vehicle after it has ended.
bool haveNeighbors
Information whether this lane belongs to a multi-lane edge.
A thread repeatingly calculating incoming tasks.
Function-object for stable sorting of objects acting like Named without being derived (SUMOVehicle) ...
Definition: Named.h:33
MSEdgeControl(const std::vector< MSEdge * > &edges)
Constructor.
Representation of a lane in the micro simulation.
Definition: MSLane.h:83