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