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 /****************************************************************************/
15 // The simulated network and simulation perfomer
16 /****************************************************************************/
17 // SUMO, Simulation of Urban MObility; see http://sumo-sim.org/
18 // Copyright (C) 2001-2014 DLR (http://www.dlr.de/) and contributors
19 /****************************************************************************/
20 //
21 // This file is part of SUMO.
22 // SUMO is free software: you can redistribute it and/or modify
23 // it under the terms of the GNU General Public License as published by
24 // the Free Software Foundation, either version 3 of the License, or
25 // (at your option) any later version.
26 //
27 /****************************************************************************/
28 
29 
30 // ===========================================================================
31 // included modules
32 // ===========================================================================
33 #ifdef _MSC_VER
34 #include <windows_config.h>
35 #else
36 #include <config.h>
37 #endif
38 
39 #ifdef HAVE_VERSION_H
40 #include <version.h>
41 #endif
42 
43 #include <string>
44 #include <iostream>
45 #include <sstream>
46 #include <typeinfo>
47 #include <algorithm>
48 #include <cassert>
49 #include <vector>
50 #include <ctime>
52 #include "MSNet.h"
53 #include "MSPersonControl.h"
54 #include "MSEdgeControl.h"
55 #include "MSJunctionControl.h"
56 #include "MSInsertionControl.h"
57 #include "MSEventControl.h"
58 #include "MSEdge.h"
59 #include "MSJunction.h"
60 #include "MSJunctionLogic.h"
61 #include "MSLane.h"
62 #include "MSVehicleTransfer.h"
63 #include "MSRoute.h"
65 #include "trigger/MSTrigger.h"
66 #include "trigger/MSCalibrator.h"
68 #include "MSVehicleControl.h"
70 #include <utils/common/ToString.h>
76 #include <utils/shapes/Polygon.h>
78 
80 #include "output/MSFCDExport.h"
82 #include "output/MSFullExport.h"
83 #include "output/MSQueueExport.h"
84 #include "output/MSVTKExport.h"
85 #include "output/MSXMLRawOut.h"
88 #include <utils/common/SysUtils.h>
92 #include "MSGlobals.h"
93 #include "MSPModel.h"
95 #include "MSPerson.h"
96 #include "MSEdgeWeightsStorage.h"
97 #include "MSStateHandler.h"
98 
99 #ifdef HAVE_INTERNAL
100 #include <mesosim/MELoop.h>
102 #endif
103 
104 #ifndef NO_TRACI
106 #endif
107 
108 #ifdef CHECK_MEMORY_LEAKS
109 #include <foreign/nvwa/debug_new.h>
110 #endif // CHECK_MEMORY_LEAKS
111 
112 
113 // ===========================================================================
114 // static member definitions
115 // ===========================================================================
117 
118 const std::string MSNet::STAGE_EVENTS("events");
119 const std::string MSNet::STAGE_MOVEMENTS("move");
120 const std::string MSNet::STAGE_LANECHANGE("laneChange");
121 const std::string MSNet::STAGE_INSERTIONS("insertion");
122 
123 // ===========================================================================
124 // member method definitions
125 // ===========================================================================
126 SUMOReal
127 MSNet::getEffort(const MSEdge* const e, const SUMOVehicle* const v, SUMOReal t) {
128  SUMOReal value;
129  const MSVehicle* const veh = dynamic_cast<const MSVehicle* const>(v);
130  if (veh != 0 && veh->getWeightsStorage().retrieveExistingEffort(e, t, value)) {
131  return value;
132  }
133  if (getInstance()->getWeightsStorage().retrieveExistingEffort(e, t, value)) {
134  return value;
135  }
136  return 0;
137 }
138 
139 
140 SUMOReal
141 MSNet::getTravelTime(const MSEdge* const e, const SUMOVehicle* const v, SUMOReal t) {
142  SUMOReal value;
143  const MSVehicle* const veh = dynamic_cast<const MSVehicle* const>(v);
144  if (veh != 0 && veh->getWeightsStorage().retrieveExistingTravelTime(e, t, value)) {
145  return value;
146  }
148  return value;
149  }
150  return e->getMinimumTravelTime(v);
151 }
152 
153 
154 
155 // ---------------------------------------------------------------------------
156 // MSNet - methods
157 // ---------------------------------------------------------------------------
158 MSNet*
160  if (myInstance != 0) {
161  return myInstance;
162  }
163  throw ProcessError("A network was not yet constructed.");
164 }
165 
166 
167 MSNet::MSNet(MSVehicleControl* vc, MSEventControl* beginOfTimestepEvents,
168  MSEventControl* endOfTimestepEvents, MSEventControl* insertionEvents,
169  ShapeContainer* shapeCont):
170  myVehiclesMoved(0),
171  myRouterTTInitialized(false),
172  myRouterTTDijkstra(0),
173  myRouterTTAStar(0),
174  myRouterEffort(0),
175  myPedestrianRouter(0) {
176  if (myInstance != 0) {
177  throw ProcessError("A network was already constructed.");
178  }
180  myStep = string2time(oc.getString("begin"));
181  myLogExecutionTime = !oc.getBool("no-duration-log");
182  myLogStepNumber = !oc.getBool("no-step-log");
183  myTooManyVehicles = oc.getInt("max-num-vehicles");
184  myInserter = new MSInsertionControl(*vc, string2time(oc.getString("max-depart-delay")), !oc.getBool("eager-insert"));
185  myVehicleControl = vc;
187  myEdges = 0;
188  myJunctions = 0;
189  myRouteLoaders = 0;
190  myLogics = 0;
191  myPersonControl = 0;
192  myEdgeWeights = 0;
193  myShapeContainer = shapeCont == 0 ? new ShapeContainer() : shapeCont;
194 
195  myBeginOfTimestepEvents = beginOfTimestepEvents;
196  myEndOfTimestepEvents = endOfTimestepEvents;
197  myInsertionEvents = insertionEvents;
198  myLanesRTree.first = false;
199 
200 #ifdef HAVE_INTERNAL
202  MSGlobals::gMesoNet = new MELoop(string2time(oc.getString("meso-recheck")));
203  }
204 #endif
205  myInstance = this;
206 }
207 
208 
209 
210 
211 void
213  SUMORouteLoaderControl* routeLoaders,
214  MSTLLogicControl* tlc,
215  std::vector<SUMOTime> stateDumpTimes,
216  std::vector<std::string> stateDumpFiles) {
217  myEdges = edges;
218  myJunctions = junctions;
219  myRouteLoaders = routeLoaders;
220  myLogics = tlc;
221  // save the time the network state shall be saved at
222  myStateDumpTimes = stateDumpTimes;
223  myStateDumpFiles = stateDumpFiles;
224 
225  // set requests/responses
227 
228  // initialise performance computation
229  if (myLogExecutionTime) {
231  }
232 }
233 
234 
236  // delete events first maybe they do some cleanup
238  delete myEndOfTimestepEvents;
239  delete myInsertionEvents;
240  // delete controls
241  delete myJunctions;
242  delete myDetectorControl;
243  // delete mean data
244  delete myEdges;
245  delete myInserter;
246  delete myLogics;
247  delete myRouteLoaders;
248  delete myVehicleControl;
249  if (myPersonControl != 0) {
250  delete myPersonControl;
251  }
252  delete myShapeContainer;
253  delete myEdgeWeights;
254  delete myRouterTTDijkstra;
255  delete myRouterTTAStar;
256  delete myRouterEffort;
257  myLanesRTree.second.RemoveAll();
258  clearAll();
259 #ifdef HAVE_INTERNAL
261  delete MSGlobals::gMesoNet;
262  }
263 #endif
264  myInstance = 0;
265 }
266 
267 
268 int
270  // report the begin when wished
271  WRITE_MESSAGE("Simulation started with time: " + time2string(start));
272  // the simulation loop
274  myStep = start;
275  // preload the routes especially for TraCI
276  loadRoutes();
277 #ifndef NO_TRACI
278 #ifdef HAVE_PYTHON
279  if (OptionsCont::getOptions().isSet("python-script")) {
280  TraCIServer::runEmbedded(OptionsCont::getOptions().getString("python-script"));
281  closeSimulation(start);
282  WRITE_MESSAGE("Simulation ended at time: " + time2string(getCurrentTimeStep()));
283  WRITE_MESSAGE("Reason: Script ended");
284  return 0;
285  }
286 #endif
287 #endif
288  while (state == SIMSTATE_RUNNING) {
289  if (myLogStepNumber) {
291  }
292  simulationStep();
293  if (myLogStepNumber) {
295  }
296  state = simulationState(stop);
297 #ifndef NO_TRACI
298  if (state != SIMSTATE_RUNNING) {
299  if (OptionsCont::getOptions().getInt("remote-port") != 0 && !TraCIServer::wasClosed()) {
300  state = SIMSTATE_RUNNING;
301  }
302  }
303 #endif
304  }
305  // report the end when wished
306  WRITE_MESSAGE("Simulation ended at time: " + time2string(getCurrentTimeStep()));
307  WRITE_MESSAGE("Reason: " + getStateMessage(state));
308  // exit simulation loop
309  closeSimulation(start);
310  return 0;
311 }
312 
313 void
316 }
317 
318 
319 void
321  if (myLogExecutionTime) {
322  long duration = SysUtils::getCurrentMillis() - mySimBeginMillis;
323  std::ostringstream msg;
324  // print performance notice
325  msg << "Performance: " << "\n" << " Duration: " << duration << " ms" << "\n";
326  if (duration != 0) {
327  msg << " Real time factor: " << (STEPS2TIME(myStep - start) * 1000. / (SUMOReal)duration) << "\n";
328  msg.setf(std::ios::fixed , std::ios::floatfield); // use decimal format
329  msg.setf(std::ios::showpoint); // print decimal point
330  msg << " UPS: " << ((SUMOReal)myVehiclesMoved / ((SUMOReal)duration / 1000)) << "\n";
331  }
332  // print vehicle statistics
333  const std::string discardNotice = ((myVehicleControl->getLoadedVehicleNo() != myVehicleControl->getDepartedVehicleNo()) ?
334  " (Loaded: " + toString(myVehicleControl->getLoadedVehicleNo()) + ")" : "");
335  msg << "Vehicles: " << "\n"
336  << " Inserted: " << myVehicleControl->getDepartedVehicleNo() << discardNotice << "\n"
337  << " Running: " << myVehicleControl->getRunningVehicleNo() << "\n"
338  << " Waiting: " << myInserter->getWaitingVehicleNo() << "\n";
339 
340  if (myVehicleControl->getTeleportCount() > 0) {
341  // print optional teleport statistics
342  std::vector<std::string> reasons;
343  if (myVehicleControl->getCollisionCount() > 0) {
344  reasons.push_back("Collisions: " + toString(myVehicleControl->getCollisionCount()));
345  }
346  if (myVehicleControl->getTeleportsJam() > 0) {
347  reasons.push_back("Jam: " + toString(myVehicleControl->getTeleportsJam()));
348  }
349  if (myVehicleControl->getTeleportsYield() > 0) {
350  reasons.push_back("Yield: " + toString(myVehicleControl->getTeleportsYield()));
351  }
353  reasons.push_back("Wrong Lane: " + toString(myVehicleControl->getTeleportsWrongLane()));
354  }
355  msg << "Teleports: " << myVehicleControl->getTeleportCount() << " (" << joinToString(reasons, ", ") << ")\n";
356  }
357  if (myVehicleControl->getEmergencyStops() > 0) {
358  msg << "Emergency Stops: " << myVehicleControl->getEmergencyStops() << "\n";
359  }
360  WRITE_MESSAGE(msg.str());
361  }
363  if (OptionsCont::getOptions().getBool("vehroute-output.write-unfinished")) {
365  }
366 #ifndef NO_TRACI
368 #endif
369 }
370 
371 
372 void
374 #ifndef NO_TRACI
377  if (t != 0 && t->getTargetTime() != 0 && t->getTargetTime() < myStep) {
378  return;
379  }
380 #endif
381  // execute beginOfTimestepEvents
382  if (myLogExecutionTime) {
384  }
385  // simulation state output
386  std::vector<SUMOTime>::iterator timeIt = find(myStateDumpTimes.begin(), myStateDumpTimes.end(), myStep);
387  if (timeIt != myStateDumpTimes.end()) {
388  const int dist = (int)distance(myStateDumpTimes.begin(), timeIt);
390  }
394  }
395  // check whether the tls programs need to be switched
397 
398 #ifdef HAVE_INTERNAL
400  MSGlobals::gMesoNet->simulate(myStep);
401  } else {
402 #endif
403 
404  // assure all lanes with vehicles are 'active'
406 
407  // compute safe velocities for all vehicles for the next few lanes
408  // also register ApproachingVehicleInformation for all links
410 
411  // decide right-of-way and execute movements
415  }
416 
417  // Vehicles change Lanes (maybe)
419 
422  }
423 #ifdef HAVE_INTERNAL
424  }
425 #endif
426  loadRoutes();
427 
428  // persons
429  if (myPersonControl != 0) {
431  }
432  // insert Vehicles
437  }
438  MSVehicleTransfer::getInstance()->checkInsertions(myStep);
439 
440  // execute endOfTimestepEvents
442 
443 #ifndef NO_TRACI
444  if (TraCIServer::getInstance() != 0) {
445  TraCIServer::getInstance()->postProcessVTD();
446  }
447 #endif
448  // update and write (if needed) detector values
449  writeOutput();
450 
451  if (myLogExecutionTime) {
455  }
456  myStep += DELTA_T;
457 }
458 
459 
464  }
465 #ifndef NO_TRACI
466  if (TraCIServer::wasClosed()) {
468  }
469  if (stopTime < 0 && OptionsCont::getOptions().getInt("remote-port") == 0) {
470 #else
471  if (stopTime < 0) {
472 #endif
475  && (myInserter->getPendingFlowCount() == 0)
476  && (myPersonControl == 0 || !myPersonControl->hasNonWaiting())) {
477  if (myPersonControl) {
479  }
482  }
483  }
484  if (stopTime >= 0 && myStep >= stopTime) {
486  }
487  return SIMSTATE_RUNNING;
488 }
489 
490 
491 std::string
493  switch (state) {
495  return "";
497  return "The final simulation step has been reached.";
499  return "All vehicles have left the simulation.";
501  return "TraCI requested termination.";
503  return "An error occured (see log).";
505  return "Too many vehicles.";
506  default:
507  return "Unknown reason.";
508  }
509 }
510 
511 
512 void
514  // clear container
515  MSEdge::clear();
516  MSLane::clear();
517  MSRoute::clear();
524 }
525 
526 
527 void
529  // update detector values
531 
532  // check state dumps
533  if (OptionsCont::getOptions().isSet("netstate-dump")) {
535  }
536 
537  // check fcd dumps
538  if (OptionsCont::getOptions().isSet("fcd-output")) {
540  }
541 
542  // check emission dumps
543  if (OptionsCont::getOptions().isSet("emission-output")) {
545  }
546 
547  // check full dumps
548  if (OptionsCont::getOptions().isSet("full-output")) {
550  }
551 
552  // check queue dumps
553  if (OptionsCont::getOptions().isSet("queue-output")) {
555  }
556 
557  // check amitran dumps
558  if (OptionsCont::getOptions().isSet("amitran-output")) {
560  }
561 
562  // check vtk dumps
563  if (OptionsCont::getOptions().isSet("vtk-output")) {
564 
565  if (MSNet::getInstance()->getVehicleControl().getRunningVehicleNo() > 0) {
566  std::string timestep = time2string(myStep);
567  timestep = timestep.substr(0, timestep.length() - 3);
568  std::string output = OptionsCont::getOptions().getString("vtk-output");
569  std::string filename = output + "_" + timestep + ".vtp";
570 
571  OutputDevice_File dev = OutputDevice_File(filename, false);
572 
573  //build a huge mass of xml files
575 
576  }
577 
578  }
579 
580  // summary output
581  if (OptionsCont::getOptions().isSet("summary-output")) {
582  OutputDevice& od = OutputDevice::getDeviceByOption("summary-output");
583  unsigned int departedVehiclesNumber = myVehicleControl->getDepartedVehicleNo();
584  const SUMOReal meanWaitingTime = departedVehiclesNumber != 0 ? myVehicleControl->getTotalDepartureDelay() / (SUMOReal) departedVehiclesNumber : -1.;
585  unsigned int endedVehicleNumber = myVehicleControl->getEndedVehicleNo();
586  const SUMOReal meanTravelTime = endedVehicleNumber != 0 ? myVehicleControl->getTotalTravelTime() / (SUMOReal) endedVehicleNumber : -1.;
588  .writeAttr("inserted", myVehicleControl->getDepartedVehicleNo()).writeAttr("running", myVehicleControl->getRunningVehicleNo())
589  .writeAttr("waiting", myInserter->getWaitingVehicleNo()).writeAttr("ended", myVehicleControl->getEndedVehicleNo())
590  .writeAttr("meanWaitingTime", meanWaitingTime).writeAttr("meanTravelTime", meanTravelTime);
591  if (myLogExecutionTime) {
592  od.writeAttr("duration", mySimStepDuration);
593  }
594  od.closeTag();
595  }
596 
597  // write detector values
599 
600  // write link states
601  if (OptionsCont::getOptions().isSet("link-output")) {
602  OutputDevice& od = OutputDevice::getDeviceByOption("link-output");
603  od.openTag("timestep");
605  const std::vector<MSEdge*>& edges = myEdges->getEdges();
606  for (std::vector<MSEdge*>::const_iterator i = edges.begin(); i != edges.end(); ++i) {
607  const std::vector<MSLane*>& lanes = (*i)->getLanes();
608  for (std::vector<MSLane*>::const_iterator j = lanes.begin(); j != lanes.end(); ++j) {
609  const std::vector<MSLink*>& links = (*j)->getLinkCont();
610  for (std::vector<MSLink*>::const_iterator k = links.begin(); k != links.end(); ++k) {
611  (*k)->writeApproaching(od, (*j)->getID());
612  }
613  }
614  }
615  od.closeTag();
616  }
617 }
618 
619 
620 bool
622  return myLogExecutionTime;
623 }
624 
625 
628  if (myPersonControl == 0) {
630  }
631  return *myPersonControl;
632 }
633 
634 
637  if (myEdgeWeights == 0) {
639  }
640  return *myEdgeWeights;
641 }
642 
643 
644 void
646  std::cout << "Step #" << time2string(myStep);
647 }
648 
649 
650 void
652  if (myLogExecutionTime) {
653  std::ostringstream oss;
654  oss.setf(std::ios::fixed , std::ios::floatfield); // use decimal format
655  oss.setf(std::ios::showpoint); // print decimal point
656  oss << std::setprecision(OUTPUT_ACCURACY);
657  if (mySimStepDuration != 0) {
658  oss << " (" << mySimStepDuration << "ms ~= "
659  << (1000. / (SUMOReal) mySimStepDuration) << "*RT, ~"
661  } else {
662  oss << " (0ms ?*RT. ?";
663  }
664  oss << "UPS, vehicles"
665  << " TOT " << myVehicleControl->getDepartedVehicleNo()
666  << " ACT " << myVehicleControl->getRunningVehicleNo()
667  << ") ";
668  std::string prev = "Step #" + time2string(myStep - DELTA_T);
669  std::cout << oss.str().substr(0, 78 - prev.length());
670  }
671  std::cout << '\r';
672 }
673 
674 
675 void
677  if (find(myVehicleStateListeners.begin(), myVehicleStateListeners.end(), listener) == myVehicleStateListeners.end()) {
678  myVehicleStateListeners.push_back(listener);
679  }
680 }
681 
682 
683 void
685  std::vector<VehicleStateListener*>::iterator i = find(myVehicleStateListeners.begin(), myVehicleStateListeners.end(), listener);
686  if (i != myVehicleStateListeners.end()) {
687  myVehicleStateListeners.erase(i);
688  }
689 }
690 
691 
692 void
694  for (std::vector<VehicleStateListener*>::iterator i = myVehicleStateListeners.begin(); i != myVehicleStateListeners.end(); ++i) {
695  (*i)->vehicleStateChanged(vehicle, to);
696  }
697 }
698 
699 
700 
701 // ------ Insertion and retrieval of bus stops ------
702 bool
704  return myBusStopDict.add(busStop->getID(), busStop);
705 }
706 
707 
708 MSBusStop*
709 MSNet::getBusStop(const std::string& id) const {
710  return myBusStopDict.get(id);
711 }
712 
713 
714 std::string
715 MSNet::getBusStopID(const MSLane* lane, const SUMOReal pos) const {
716  const std::map<std::string, MSBusStop*>& vals = myBusStopDict.getMyMap();
717  for (std::map<std::string, MSBusStop*>::const_iterator it = vals.begin(); it != vals.end(); ++it) {
718  MSBusStop* stop = it->second;
719  if (&stop->getLane() == lane && fabs(stop->getEndLanePosition() - pos) < POSITION_EPS) {
720  return stop->getID();
721  }
722  }
723  return "";
724 }
725 
726 
728 MSNet::getRouterTT(const std::vector<MSEdge*>& prohibited) const {
729  if (!myRouterTTInitialized) {
730  myRouterTTInitialized = true;
731  const std::string routingAlgorithm = OptionsCont::getOptions().getString("routing-algorithm");
732  if (routingAlgorithm == "dijkstra") {
735  } else {
736  if (routingAlgorithm != "astar") {
737  WRITE_WARNING("TraCI and Triggers cannot use routing algorithm '" + routingAlgorithm + "'. using 'astar' instead.");
738  }
741  }
742  }
743  if (myRouterTTDijkstra != 0) {
744  myRouterTTDijkstra->prohibit(prohibited);
745  return *myRouterTTDijkstra;
746  } else {
747  assert(myRouterTTAStar != 0);
748  myRouterTTAStar->prohibit(prohibited);
749  return *myRouterTTAStar;
750  }
751 }
752 
753 
755 MSNet::getRouterEffort(const std::vector<MSEdge*>& prohibited) const {
756  if (myRouterEffort == 0) {
759  }
760  myRouterEffort->prohibit(prohibited);
761  return *myRouterEffort;
762 }
763 
764 
766 MSNet::getPedestrianRouter(const std::vector<MSEdge*>& prohibited) const {
767  if (myPedestrianRouter == 0) {
769  }
770  myPedestrianRouter->prohibit(prohibited);
771  return *myPedestrianRouter;
772 }
773 
774 
775 const NamedRTree&
777  if (!myLanesRTree.first) {
778  MSLane::fill(myLanesRTree.second);
779  myLanesRTree.first = true;
780  }
781  return myLanesRTree.second;
782 }
783 
784 
785 /****************************************************************************/