SUMO - Simulation of Urban MObility
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
MSNet.cpp
Go to the documentation of this file.
1 /****************************************************************************/
13 // The simulated network and simulation perfomer
14 /****************************************************************************/
15 // SUMO, Simulation of Urban MObility; see http://sumo-sim.org/
16 // Copyright (C) 2001-2013 DLR (http://www.dlr.de/) and contributors
17 /****************************************************************************/
18 //
19 // This file is part of SUMO.
20 // SUMO is free software: you can redistribute it and/or modify
21 // it under the terms of the GNU General Public License as published by
22 // the Free Software Foundation, either version 3 of the License, or
23 // (at your option) any later version.
24 //
25 /****************************************************************************/
26 
27 
28 // ===========================================================================
29 // included modules
30 // ===========================================================================
31 #ifdef _MSC_VER
32 #include <windows_config.h>
33 #else
34 #include <config.h>
35 #endif
36 
37 #ifdef HAVE_VERSION_H
38 #include <version.h>
39 #endif
40 
41 #include <string>
42 #include <iostream>
43 #include <sstream>
44 #include <typeinfo>
45 #include <algorithm>
46 #include <cassert>
47 #include <vector>
49 #include "MSNet.h"
50 #include "MSPersonControl.h"
51 #include "MSEdgeControl.h"
52 #include "MSJunctionControl.h"
53 #include "MSInsertionControl.h"
54 #include "MSEventControl.h"
55 #include "MSEdge.h"
56 #include "MSJunction.h"
57 #include "MSJunctionLogic.h"
58 #include "MSLane.h"
59 #include "MSVehicleTransfer.h"
60 #include "MSRoute.h"
62 #include "trigger/MSTrigger.h"
63 #include "trigger/MSCalibrator.h"
65 #include "MSVehicleControl.h"
67 #include <utils/common/ToString.h>
73 #include <utils/shapes/Polygon.h>
75 
77 #include "output/MSFCDExport.h"
79 #include "output/MSFullExport.h"
80 #include "output/MSQueueExport.h"
81 #include "output/MSVTKExport.h"
82 #include "output/MSXMLRawOut.h"
84 #include <utils/common/SysUtils.h>
87 #include "MSGlobals.h"
89 #include <ctime>
90 #include "MSPerson.h"
91 #include "MSEdgeWeightsStorage.h"
92 #include "MSStateHandler.h"
93 
94 #ifdef HAVE_INTERNAL
95 #include <mesosim/MELoop.h>
97 #endif
98 
99 #ifndef NO_TRACI
101 #endif
102 
103 #ifdef CHECK_MEMORY_LEAKS
104 #include <foreign/nvwa/debug_new.h>
105 #endif // CHECK_MEMORY_LEAKS
106 
107 
108 // ===========================================================================
109 // static member definitions
110 // ===========================================================================
112 
113 
114 // ===========================================================================
115 // member method definitions
116 // ===========================================================================
117 SUMOReal
118 MSNet::getEffort(const MSEdge* const e, const SUMOVehicle* const v, SUMOReal t) {
119  SUMOReal value;
120  const MSVehicle* const veh = dynamic_cast<const MSVehicle* const>(v);
121  if (veh != 0 && veh->getWeightsStorage().retrieveExistingEffort(e, v, t, value)) {
122  return value;
123  }
124  if (getInstance()->getWeightsStorage().retrieveExistingEffort(e, v, t, value)) {
125  return value;
126  }
127  return 0;
128 }
129 
130 
131 SUMOReal
132 MSNet::getTravelTime(const MSEdge* const e, const SUMOVehicle* const v, SUMOReal t) {
133  SUMOReal value;
134  const MSVehicle* const veh = dynamic_cast<const MSVehicle* const>(v);
135  if (veh != 0 && veh->getWeightsStorage().retrieveExistingTravelTime(e, v, t, value)) {
136  return value;
137  }
138  if (getInstance()->getWeightsStorage().retrieveExistingTravelTime(e, v, t, value)) {
139  return value;
140  }
141  return e->getMinimumTravelTime(v);
142 }
143 
144 
145 
146 // ---------------------------------------------------------------------------
147 // MSNet - methods
148 // ---------------------------------------------------------------------------
149 MSNet*
151  if (myInstance != 0) {
152  return myInstance;
153  }
154  throw ProcessError("A network was not yet constructed.");
155 }
156 
157 
158 MSNet::MSNet(MSVehicleControl* vc, MSEventControl* beginOfTimestepEvents,
159  MSEventControl* endOfTimestepEvents, MSEventControl* insertionEvents,
160  ShapeContainer* shapeCont):
161  myVehiclesMoved(0),
162  myRouterTTInitialized(false),
163  myRouterTTDijkstra(0),
164  myRouterTTAStar(0),
165  myRouterEffort(0) {
166  if (myInstance != 0) {
167  throw ProcessError("A network was already constructed.");
168  }
170  myStep = string2time(oc.getString("begin"));
171  myLogExecutionTime = !oc.getBool("no-duration-log");
172  myLogStepNumber = !oc.getBool("no-step-log");
173  myTooManyVehicles = oc.getInt("max-num-vehicles");
174  myInserter = new MSInsertionControl(*vc, string2time(oc.getString("max-depart-delay")), !oc.getBool("eager-insert"));
175  myVehicleControl = vc;
177  myEdges = 0;
178  myJunctions = 0;
179  myRouteLoaders = 0;
180  myLogics = 0;
181  myPersonControl = 0;
182  myEdgeWeights = 0;
183  myShapeContainer = shapeCont == 0 ? new ShapeContainer() : shapeCont;
184 
185  myBeginOfTimestepEvents = beginOfTimestepEvents;
186  myEndOfTimestepEvents = endOfTimestepEvents;
187  myInsertionEvents = insertionEvents;
188  myLanesRTree.first = false;
189 
190 #ifdef HAVE_INTERNAL
192  MSGlobals::gMesoNet = new MELoop(string2time(oc.getString("meso-recheck")));
193  }
194 #endif
195  myInstance = this;
196 }
197 
198 
199 
200 
201 void
203  SUMORouteLoaderControl* routeLoaders,
204  MSTLLogicControl* tlc,
205  std::vector<SUMOTime> stateDumpTimes,
206  std::vector<std::string> stateDumpFiles) {
207  myEdges = edges;
208  myJunctions = junctions;
209  myRouteLoaders = routeLoaders;
210  myLogics = tlc;
211  // save the time the network state shall be saved at
212  myStateDumpTimes = stateDumpTimes;
213  myStateDumpFiles = stateDumpFiles;
214 
215  // set requests/responses
217 
218  // initialise performance computation
219  if (myLogExecutionTime) {
221  }
222 }
223 
224 
226  // delete events first maybe they do some cleanup
228  delete myEndOfTimestepEvents;
229  delete myInsertionEvents;
230  // delete controls
231  delete myJunctions;
232  delete myDetectorControl;
233  // delete mean data
234  delete myEdges;
235  delete myInserter;
236  delete myLogics;
237  delete myRouteLoaders;
238  delete myVehicleControl;
239  if (myPersonControl != 0) {
240  delete myPersonControl;
241  }
242  delete myShapeContainer;
243  delete myEdgeWeights;
244  delete myRouterTTDijkstra;
245  delete myRouterTTAStar;
246  delete myRouterEffort;
247  myLanesRTree.second.RemoveAll();
248  clearAll();
249 #ifdef HAVE_INTERNAL
251  delete MSGlobals::gMesoNet;
252  }
253 #endif
254  myInstance = 0;
255 }
256 
257 
258 int
260  // report the begin when wished
261  WRITE_MESSAGE("Simulation started with time: " + time2string(start));
262  // the simulation loop
264  myStep = start;
265  // preload the routes especially for TraCI
266  loadRoutes();
267 #ifndef NO_TRACI
268 #ifdef HAVE_PYTHON
269  if (OptionsCont::getOptions().isSet("python-script")) {
270  TraCIServer::runEmbedded(OptionsCont::getOptions().getString("python-script"));
271  closeSimulation(start);
272  WRITE_MESSAGE("Simulation ended at time: " + time2string(getCurrentTimeStep()));
273  WRITE_MESSAGE("Reason: Script ended");
274  return 0;
275  }
276 #endif
277 #endif
278  while (state == SIMSTATE_RUNNING) {
279  if (myLogStepNumber) {
281  }
282  simulationStep();
283  if (myLogStepNumber) {
285  }
286  state = simulationState(stop);
287 #ifndef NO_TRACI
288  if (state != SIMSTATE_RUNNING) {
289  if (OptionsCont::getOptions().getInt("remote-port") != 0 && !TraCIServer::wasClosed()) {
290  state = SIMSTATE_RUNNING;
291  }
292  }
293 #endif
294  }
295  // report the end when wished
296  WRITE_MESSAGE("Simulation ended at time: " + time2string(getCurrentTimeStep()));
297  WRITE_MESSAGE("Reason: " + getStateMessage(state));
298  // exit simulation loop
299  closeSimulation(start);
300  return 0;
301 }
302 
303 void
306 }
307 
308 
309 void
311  if (myLogExecutionTime) {
312  long duration = SysUtils::getCurrentMillis() - mySimBeginMillis;
313  std::ostringstream msg;
314  msg << "Performance: " << "\n" << " Duration: " << duration << " ms" << "\n";
315  if (duration != 0) {
316  msg << " Real time factor: " << (STEPS2TIME(myStep - start) * 1000. / (SUMOReal)duration) << "\n";
317  msg.setf(std::ios::fixed , std::ios::floatfield); // use decimal format
318  msg.setf(std::ios::showpoint); // print decimal point
319  msg << " UPS: " << ((SUMOReal)myVehiclesMoved / ((SUMOReal)duration / 1000)) << "\n";
320  }
321  // prepare optional statistics
322  const std::string discardNotice = ((myVehicleControl->getLoadedVehicleNo() != myVehicleControl->getDepartedVehicleNo()) ?
323  " (Loaded: " + toString(myVehicleControl->getLoadedVehicleNo()) + ")" : "");
324  const std::string collisionNotice = (
326  " (Collisions: " + toString(myVehicleControl->getCollisionCount()) + ")" : "");
327  const std::string teleportNotice = (
329  "Teleports: " + toString(myVehicleControl->getTeleportCount()) + collisionNotice + "\n" : "");
330  // print statistics
331  msg << "Vehicles: " << "\n"
332  << " Emitted: " << myVehicleControl->getDepartedVehicleNo() << discardNotice << "\n"
333  << " Running: " << myVehicleControl->getRunningVehicleNo() << "\n"
334  << " Waiting: " << myInserter->getWaitingVehicleNo() << "\n"
335  << teleportNotice;
336  WRITE_MESSAGE(msg.str());
337  }
339  if (OptionsCont::getOptions().getBool("vehroute-output.write-unfinished")) {
341  }
342 #ifndef NO_TRACI
344 #endif
345 }
346 
347 
348 void
350 #ifndef NO_TRACI
353  if (t != 0 && t->getTargetTime() != 0 && t->getTargetTime() < myStep) {
354  return;
355  }
356 #endif
357  // execute beginOfTimestepEvents
358  if (myLogExecutionTime) {
360  }
361  // simulation state output
362  std::vector<SUMOTime>::iterator timeIt = find(myStateDumpTimes.begin(), myStateDumpTimes.end(), myStep);
363  if (timeIt != myStateDumpTimes.end()) {
364  const int dist = (int)distance(myStateDumpTimes.begin(), timeIt);
366  }
370  }
371  // check whether the tls programs need to be switched
373 
374 #ifdef HAVE_INTERNAL
376  MSGlobals::gMesoNet->simulate(myStep);
377  } else {
378 #endif
379 
380  // assure all lanes with vehicles are 'active'
382 
383  // compute safe velocities for all vehicles for the next few lanes
384  // also register ApproachingVehicleInformation for all links
386 
387  // decide right-of-way and execute movements
391  }
392 
393  // Vehicles change Lanes (maybe)
395 
398  }
399 #ifdef HAVE_INTERNAL
400  }
401 #endif
402  loadRoutes();
403 
404  // persons
405  if (myPersonControl != 0) {
407  }
408  // emit Vehicles
413  }
415 
416  // execute endOfTimestepEvents
418 
419 #ifndef NO_TRACI
420  if (TraCIServer::getInstance() != 0) {
422  }
423 #endif
424  // update and write (if needed) detector values
425  writeOutput();
426 
427  if (myLogExecutionTime) {
431  }
432  myStep += DELTA_T;
433 }
434 
435 
440  }
441 #ifndef NO_TRACI
442  if (TraCIServer::wasClosed()) {
444  }
445  if (stopTime < 0 && OptionsCont::getOptions().getInt("remote-port") == 0) {
446 #else
447  if (stopTime < 0) {
448 #endif
451  && (myInserter->getPendingFlowCount() == 0)
452  && (myPersonControl == 0 || !myPersonControl->hasNonWaiting())) {
453  if (myPersonControl) {
455  }
458  }
459  }
460  if (stopTime >= 0 && myStep >= stopTime) {
462  }
463  return SIMSTATE_RUNNING;
464 }
465 
466 
467 std::string
469  switch (state) {
471  return "";
473  return "The final simulation step has been reached.";
475  return "All vehicles have left the simulation.";
477  return "TraCI requested termination.";
479  return "An error occured (see log).";
481  return "Too many vehicles.";
482  default:
483  return "Unknown reason.";
484  }
485 }
486 
487 
488 void
490  // clear container
491  MSEdge::clear();
492  MSLane::clear();
493  MSRoute::clear();
498 }
499 
500 
501 SUMOTime
503  return myStep;
504 }
505 
506 
507 void
509  // update detector values
511 
512  // check state dumps
513  if (OptionsCont::getOptions().isSet("netstate-dump")) {
515  }
516 
517  // check fcd dumps
518  if (OptionsCont::getOptions().isSet("fcd-output")) {
520  }
521 
522  // check emission dumps
523  if (OptionsCont::getOptions().isSet("emission-output")) {
525  }
526 
527  // check full dumps
528  if (OptionsCont::getOptions().isSet("full-output")) {
530  }
531 
532  // check queue dumps
533  if (OptionsCont::getOptions().isSet("queue-output")) {
535  }
536 
537  // check vtk dumps
538  if (OptionsCont::getOptions().isSet("vtk-output")) {
539 
540  if (MSNet::getInstance()->getVehicleControl().getRunningVehicleNo() > 0) {
541  std::string timestep = time2string(myStep);
542  timestep = timestep.substr(0, timestep.length() - 3);
543  std::string output = OptionsCont::getOptions().getString("vtk-output");
544  std::string filename = output + "_" + timestep + ".vtp";
545 
546  OutputDevice_File dev = OutputDevice_File(filename, false);
547 
548  //build a huge mass of xml files
550 
551  }
552 
553  }
554 
555  // summary output
556  if (OptionsCont::getOptions().isSet("summary-output")) {
557  OutputDevice& od = OutputDevice::getDeviceByOption("summary-output");
558  unsigned int departedVehiclesNumber = myVehicleControl->getDepartedVehicleNo();
559  const SUMOReal meanWaitingTime = departedVehiclesNumber != 0 ? myVehicleControl->getTotalDepartureDelay() / (SUMOReal) departedVehiclesNumber : -1.;
560  unsigned int endedVehicleNumber = myVehicleControl->getEndedVehicleNo();
561  const SUMOReal meanTravelTime = endedVehicleNumber != 0 ? myVehicleControl->getTotalTravelTime() / (SUMOReal) endedVehicleNumber : -1.;
563  .writeAttr("inserted", myVehicleControl->getDepartedVehicleNo()).writeAttr("running", myVehicleControl->getRunningVehicleNo())
564  .writeAttr("waiting", myInserter->getWaitingVehicleNo()).writeAttr("ended", myVehicleControl->getEndedVehicleNo())
565  .writeAttr("meanWaitingTime", meanWaitingTime).writeAttr("meanTravelTime", meanTravelTime);
566  if (myLogExecutionTime) {
567  od.writeAttr("duration", mySimStepDuration);
568  }
569  od.closeTag();
570  }
571 
572  // write detector values
574 
575  // write link states
576  if (OptionsCont::getOptions().isSet("link-output")) {
577  OutputDevice& od = OutputDevice::getDeviceByOption("link-output");
578  od.openTag("timestep");
580  const std::vector<MSEdge*>& edges = myEdges->getEdges();
581  for (std::vector<MSEdge*>::const_iterator i = edges.begin(); i != edges.end(); ++i) {
582  const std::vector<MSLane*>& lanes = (*i)->getLanes();
583  for (std::vector<MSLane*>::const_iterator j = lanes.begin(); j != lanes.end(); ++j) {
584  const std::vector<MSLink*>& links = (*j)->getLinkCont();
585  for (std::vector<MSLink*>::const_iterator k = links.begin(); k != links.end(); ++k) {
586  (*k)->writeApproaching(od, (*j)->getID());
587  }
588  }
589  }
590  od.closeTag();
591  }
592 }
593 
594 
595 bool
597  return myLogExecutionTime;
598 }
599 
600 
603  if (myPersonControl == 0) {
605  }
606  return *myPersonControl;
607 }
608 
609 
612  if (myEdgeWeights == 0) {
614  }
615  return *myEdgeWeights;
616 }
617 
618 
619 void
621  std::cout << "Step #" << time2string(myStep);
622 }
623 
624 
625 void
627  if (myLogExecutionTime) {
628  std::ostringstream oss;
629  oss.setf(std::ios::fixed , std::ios::floatfield); // use decimal format
630  oss.setf(std::ios::showpoint); // print decimal point
631  oss << std::setprecision(OUTPUT_ACCURACY);
632  if (mySimStepDuration != 0) {
633  oss << " (" << mySimStepDuration << "ms ~= "
634  << (1000. / (SUMOReal) mySimStepDuration) << "*RT, ~"
636  } else {
637  oss << " (0ms ?*RT. ?";
638  }
639  oss << "UPS, vehicles"
640  << " TOT " << myVehicleControl->getDepartedVehicleNo()
641  << " ACT " << myVehicleControl->getRunningVehicleNo()
642  << ") ";
643  std::string prev = "Step #" + time2string(myStep - DELTA_T);
644  std::cout << oss.str().substr(0, 78 - prev.length());
645  }
646  std::cout << '\r';
647 }
648 
649 
650 void
652  if (find(myVehicleStateListeners.begin(), myVehicleStateListeners.end(), listener) == myVehicleStateListeners.end()) {
653  myVehicleStateListeners.push_back(listener);
654  }
655 }
656 
657 
658 void
660  std::vector<VehicleStateListener*>::iterator i = find(myVehicleStateListeners.begin(), myVehicleStateListeners.end(), listener);
661  if (i != myVehicleStateListeners.end()) {
662  myVehicleStateListeners.erase(i);
663  }
664 }
665 
666 
667 void
669  for (std::vector<VehicleStateListener*>::iterator i = myVehicleStateListeners.begin(); i != myVehicleStateListeners.end(); ++i) {
670  (*i)->vehicleStateChanged(vehicle, to);
671  }
672 }
673 
674 
675 
676 // ------ Insertion and retrieval of bus stops ------
677 bool
679  return myBusStopDict.add(busStop->getID(), busStop);
680 }
681 
682 
683 MSBusStop*
684 MSNet::getBusStop(const std::string& id) const {
685  return myBusStopDict.get(id);
686 }
687 
688 
689 std::string
690 MSNet::getBusStopID(const MSLane* lane, const SUMOReal pos) const {
691  const std::map<std::string, MSBusStop*>& vals = myBusStopDict.getMyMap();
692  for (std::map<std::string, MSBusStop*>::const_iterator it = vals.begin(); it != vals.end(); ++it) {
693  MSBusStop* stop = it->second;
694  if (&stop->getLane() == lane && fabs(stop->getEndLanePosition() - pos) < POSITION_EPS) {
695  return stop->getID();
696  }
697  }
698  return "";
699 }
700 
701 
703 MSNet::getRouterTT(const std::vector<MSEdge*>& prohibited) const {
704  if (!myRouterTTInitialized) {
705  myRouterTTInitialized = true;
706  const std::string routingAlgorithm = OptionsCont::getOptions().getString("routing-algorithm");
707  if (routingAlgorithm == "dijkstra") {
710  } else {
711  if (routingAlgorithm != "astar") {
712  WRITE_WARNING("TraCI and Triggers cannot use routing algorithm '" + routingAlgorithm + "'. using 'astar' instead.");
713  }
716  }
717  }
718  if (myRouterTTDijkstra != 0) {
719  myRouterTTDijkstra->prohibit(prohibited);
720  return *myRouterTTDijkstra;
721  } else {
722  assert(myRouterTTAStar != 0);
723  myRouterTTAStar->prohibit(prohibited);
724  return *myRouterTTAStar;
725  }
726 }
727 
728 
730 MSNet::getRouterEffort(const std::vector<MSEdge*>& prohibited) const {
731  if (myRouterEffort == 0) {
734  }
735  myRouterEffort->prohibit(prohibited);
736  return *myRouterEffort;
737 }
738 
739 
740 const NamedRTree&
742  if (!myLanesRTree.first) {
743  MSLane::fill(myLanesRTree.second);
744  myLanesRTree.first = true;
745  }
746  return myLanesRTree.second;
747 }
748 
749 
750 /****************************************************************************/