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.sourceforge.net/
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 
93 
94 #ifdef _MESSAGES
95 #include "MSMessageEmitter.h"
96 #endif
97 
98 #ifdef HAVE_INTERNAL
99 #include <mesosim/MELoop.h>
100 #include <mesosim/StateHandler.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 
119 // ===========================================================================
120 // member method definitions
121 // ===========================================================================
122 SUMOReal
123 MSNet::getEffort(const MSEdge* const e, const SUMOVehicle* const v, SUMOReal t) {
124  SUMOReal value;
125  const MSVehicle* const veh = dynamic_cast<const MSVehicle* const>(v);
126  if (veh != 0 && veh->getWeightsStorage().retrieveExistingEffort(e, v, t, value)) {
127  return value;
128  }
129  if (getInstance()->getWeightsStorage().retrieveExistingEffort(e, v, t, value)) {
130  return value;
131  }
132  return 0;
133 }
134 
135 
136 SUMOReal
137 MSNet::getTravelTime(const MSEdge* const e, const SUMOVehicle* const v, SUMOReal t) {
138  SUMOReal value;
139  const MSVehicle* const veh = dynamic_cast<const MSVehicle* const>(v);
140  if (veh != 0 && veh->getWeightsStorage().retrieveExistingTravelTime(e, v, t, value)) {
141  return value;
142  }
143  if (getInstance()->getWeightsStorage().retrieveExistingTravelTime(e, v, t, value)) {
144  return value;
145  }
146  return e->getMinimumTravelTime(v);
147 }
148 
149 
150 
151 // ---------------------------------------------------------------------------
152 // MSNet - methods
153 // ---------------------------------------------------------------------------
154 MSNet*
156  if (myInstance != 0) {
157  return myInstance;
158  }
159  throw ProcessError("A network was not yet constructed.");
160 }
161 
162 
163 MSNet::MSNet(MSVehicleControl* vc, MSEventControl* beginOfTimestepEvents,
164  MSEventControl* endOfTimestepEvents, MSEventControl* insertionEvents,
165  ShapeContainer* shapeCont):
166  myVehiclesMoved(0),
167  myRouterTTInitialized(false),
168  myRouterTTDijkstra(0),
169  myRouterTTAStar(0),
170  myRouterEffort(0) {
171  if (myInstance != 0) {
172  throw ProcessError("A network was already constructed.");
173  }
175  myStep = string2time(oc.getString("begin"));
176  myLogExecutionTime = !oc.getBool("no-duration-log");
177  myLogStepNumber = !oc.getBool("no-step-log");
178  myTooManyVehicles = oc.getInt("max-num-vehicles");
179  myInserter = new MSInsertionControl(*vc, string2time(oc.getString("max-depart-delay")), oc.getBool("sloppy-insert"));
180  myVehicleControl = vc;
182  myEdges = 0;
183  myJunctions = 0;
184  myRouteLoaders = 0;
185  myLogics = 0;
186  myPersonControl = 0;
187  myEdgeWeights = 0;
188  myShapeContainer = shapeCont == 0 ? new ShapeContainer() : shapeCont;
189 
190  myBeginOfTimestepEvents = beginOfTimestepEvents;
191  myEndOfTimestepEvents = endOfTimestepEvents;
192  myInsertionEvents = insertionEvents;
193 
194 #ifdef HAVE_INTERNAL
196  MSGlobals::gMesoNet = new MELoop(string2time(oc.getString("meso-recheck")));
197  }
198 #endif
199  myInstance = this;
200 }
201 
202 
203 
204 
205 void
207  SUMORouteLoaderControl* routeLoaders,
208  MSTLLogicControl* tlc,
209  std::vector<SUMOTime> stateDumpTimes,
210  std::vector<std::string> stateDumpFiles) {
211  myEdges = edges;
212  myJunctions = junctions;
213  myRouteLoaders = routeLoaders;
214  myLogics = tlc;
215  // save the time the network state shall be saved at
216  myStateDumpTimes = stateDumpTimes;
217  myStateDumpFiles = stateDumpFiles;
218 
219  // set requests/responses
221 
222  // initialise performance computation
223  if (myLogExecutionTime) {
225  }
226 }
227 
228 
230  // delete events first maybe they do some cleanup
232  delete myEndOfTimestepEvents;
233  delete myInsertionEvents;
234  // delete controls
235  delete myJunctions;
236  delete myDetectorControl;
237  // delete mean data
238  delete myEdges;
239  delete myInserter;
240  delete myLogics;
241  delete myRouteLoaders;
242  delete myVehicleControl;
243  if (myPersonControl != 0) {
244  delete myPersonControl;
245  }
246  delete myShapeContainer;
247 #ifdef _MESSAGES
248  myMsgEmitter.clear();
249  msgEmitVec.clear();
250 #endif
251  delete myEdgeWeights;
252  delete myRouterTTDijkstra;
253  delete myRouterTTAStar;
254  delete myRouterEffort;
255 #ifdef HAVE_INTERNAL
257  delete MSGlobals::gMesoNet;
258  }
259 #endif
260  clearAll();
261  myInstance = 0;
262 }
263 
264 
265 int
267  // report the begin when wished
268  WRITE_MESSAGE("Simulation started with time: " + time2string(start));
269  // the simulation loop
271  myStep = start;
272 #ifndef NO_TRACI
273 #ifdef HAVE_PYTHON
274  if (OptionsCont::getOptions().isSet("python-script")) {
275  traci::TraCIServer::runEmbedded(OptionsCont::getOptions().getString("python-script"));
276  closeSimulation(start);
277  WRITE_MESSAGE("Simulation ended at time: " + time2string(getCurrentTimeStep()));
278  WRITE_MESSAGE("Reason: Script ended");
279  return 0;
280  }
281 #endif
282 #endif
283  while (state == SIMSTATE_RUNNING) {
284  if (myLogStepNumber) {
286  }
287  simulationStep();
288  if (myLogStepNumber) {
290  }
291  state = simulationState(stop);
292 #ifndef NO_TRACI
293  if (state != SIMSTATE_RUNNING) {
294  if (OptionsCont::getOptions().getInt("remote-port") != 0 && !traci::TraCIServer::wasClosed()) {
295  state = SIMSTATE_RUNNING;
296  }
297  }
298 #endif
299  }
300  // report the end when wished
301  WRITE_MESSAGE("Simulation ended at time: " + time2string(getCurrentTimeStep()));
302  WRITE_MESSAGE("Reason: " + getStateMessage(state));
303  // exit simulation loop
304  closeSimulation(start);
305  return 0;
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 #ifdef HAVE_INTERNAL
362  // netstate output
363  std::vector<SUMOTime>::iterator timeIt = find(myStateDumpTimes.begin(), myStateDumpTimes.end(), myStep);
364  if (timeIt != myStateDumpTimes.end()) {
365  const int dist = distance(myStateDumpTimes.begin(), timeIt);
366  StateHandler::saveState(myStateDumpFiles[dist], myStep);
367  }
368 #endif
372  }
373  // check whether the tls programs need to be switched
375 
376 #ifdef HAVE_INTERNAL
378  MSGlobals::gMesoNet->simulate(myStep);
379  } else {
380 #endif
381 
382  // assure all lanes with vehicles are 'active'
384 
385  // compute safe velocities for all vehicles for the next few lanes
386  // also register ApproachingVehicleInformation for all links
388 
389  // decide right-of-way and execute movements
393  }
394 
395  // Vehicles change Lanes (maybe)
397 
400  }
401 #ifdef HAVE_INTERNAL
402  }
403 #endif
404  // load routes
406 
407  // persons
408  if (myPersonControl != 0) {
410  }
411  // emit Vehicles
416  }
418 
419  // execute endOfTimestepEvents
421 
422 #ifndef NO_TRACI
423  if (traci::TraCIServer::getInstance() != 0) {
425  }
426 #endif
427  // update and write (if needed) detector values
428  writeOutput();
429 
430  if (myLogExecutionTime) {
434  }
435  myStep += DELTA_T;
436 }
437 
438 
443  }
444 #ifndef NO_TRACI
447  }
448  if (stopTime < 0 && OptionsCont::getOptions().getInt("remote-port") == 0) {
449 #else
450  if (stopTime < 0) {
451 #endif
454  && (myInserter->getPendingFlowCount() == 0)
455  && (myPersonControl == 0 || !myPersonControl->hasNonWaiting())) {
456  if (myPersonControl) {
458  }
461  }
462  }
463  if (stopTime >= 0 && myStep >= stopTime) {
465  }
466  return SIMSTATE_RUNNING;
467 }
468 
469 
470 std::string
472  switch (state) {
474  return "";
476  return "The final simulation step has been reached.";
478  return "All vehicles have left the simulation.";
480  return "TraCI requested termination.";
482  return "An error occured (see log).";
484  return "Too many vehicles.";
485  default:
486  return "Unknown reason.";
487  }
488 }
489 
490 
491 void
493  // clear container
494  MSEdge::clear();
495  MSLane::clear();
496  MSRoute::clear();
501 }
502 
503 
504 SUMOTime
506  return myStep;
507 }
508 
509 
510 void
512  // update detector values
514 
515  // check state dumps
516  if (OptionsCont::getOptions().isSet("netstate-dump")) {
518  }
519 
520  // check fcd dumps
521  if (OptionsCont::getOptions().isSet("fcd-output")) {
523  }
524 
525  // check emission dumps
526  if (OptionsCont::getOptions().isSet("emission-output")) {
528  }
529 
530  // check full dumps
531  if (OptionsCont::getOptions().isSet("full-output")) {
533  }
534 
535  // check queue dumps
536  if (OptionsCont::getOptions().isSet("queue-output")) {
538  }
539 
540  // check vtk dumps
541  if (OptionsCont::getOptions().isSet("vtk-output")) {
542 
543  if (MSNet::getInstance()->getVehicleControl().getRunningVehicleNo() > 0) {
544  std::string timestep = time2string(myStep);
545  timestep = timestep.substr(0, timestep.length() - 3);
546  std::string output = OptionsCont::getOptions().getString("vtk-output");
547  std::string filename = output + "_" + timestep + ".vtp";
548 
549  OutputDevice_File dev = OutputDevice_File(filename, false);
550 
551  //build a huge mass of xml files
553 
554  }
555 
556  }
557 
558  // emission output
559  if (OptionsCont::getOptions().isSet("summary-output")) {
560  OutputDevice& od = OutputDevice::getDeviceByOption("summary-output");
561  od << " <step time=\"" << time2string(myStep) << "\" "
562  << "loaded=\"" << myVehicleControl->getLoadedVehicleNo() << "\" "
563  << "emitted=\"" << myVehicleControl->getDepartedVehicleNo() << "\" "
564  << "running=\"" << myVehicleControl->getRunningVehicleNo() << "\" "
565  << "waiting=\"" << myInserter->getWaitingVehicleNo() << "\" "
566  << "ended=\"" << myVehicleControl->getEndedVehicleNo() << "\" "
567  << "meanWaitingTime=\"";
569  od << "\" meanTravelTime=\"";
571  od << "\" ";
572  if (myLogExecutionTime) {
573  od << "duration=\"" << mySimStepDuration << "\" ";
574  }
575  od << "/>\n";
576  }
577  // write detector values
579 }
580 
581 
582 bool
584  return myLogExecutionTime;
585 }
586 
587 
590  if (myPersonControl == 0) {
592  }
593  return *myPersonControl;
594 }
595 
596 
599  if (myEdgeWeights == 0) {
601  }
602  return *myEdgeWeights;
603 }
604 
605 
606 void
608  std::cout << "Step #" << time2string(myStep);
609 }
610 
611 
612 void
614  if (myLogExecutionTime) {
615  std::ostringstream oss;
616  oss.setf(std::ios::fixed , std::ios::floatfield); // use decimal format
617  oss.setf(std::ios::showpoint); // print decimal point
618  oss << std::setprecision(OUTPUT_ACCURACY);
619  if (mySimStepDuration != 0) {
620  oss << " (" << mySimStepDuration << "ms ~= "
621  << (1000. / (SUMOReal) mySimStepDuration) << "*RT, ~"
623  } else {
624  oss << " (0ms ?*RT. ?";
625  }
626  oss << "UPS, vehicles"
627  << " TOT " << myVehicleControl->getDepartedVehicleNo()
628  << " ACT " << myVehicleControl->getRunningVehicleNo()
629  << ") ";
630  std::string prev = "Step #" + time2string(myStep - DELTA_T);
631  std::cout << oss.str().substr(0, 78 - prev.length());
632  }
633  std::cout << '\r';
634 }
635 
636 
637 void
639  if (find(myVehicleStateListeners.begin(), myVehicleStateListeners.end(), listener) == myVehicleStateListeners.end()) {
640  myVehicleStateListeners.push_back(listener);
641  }
642 }
643 
644 
645 void
647  std::vector<VehicleStateListener*>::iterator i = find(myVehicleStateListeners.begin(), myVehicleStateListeners.end(), listener);
648  if (i != myVehicleStateListeners.end()) {
649  myVehicleStateListeners.erase(i);
650  }
651 }
652 
653 
654 void
656  for (std::vector<VehicleStateListener*>::iterator i = myVehicleStateListeners.begin(); i != myVehicleStateListeners.end(); ++i) {
657  (*i)->vehicleStateChanged(vehicle, to);
658  }
659 }
660 
661 
662 
663 // ------ Insertion and retrieval of bus stops ------
664 bool
666  return myBusStopDict.add(busStop->getID(), busStop);
667 }
668 
669 
670 MSBusStop*
671 MSNet::getBusStop(const std::string& id) const {
672  return myBusStopDict.get(id);
673 }
674 
675 
676 std::string
677 MSNet::getBusStopID(const MSLane* lane, const SUMOReal pos) const {
678  const std::map<std::string, MSBusStop*>& vals = myBusStopDict.getMyMap();
679  for (std::map<std::string, MSBusStop*>::const_iterator it = vals.begin(); it != vals.end(); ++it) {
680  MSBusStop* stop = it->second;
681  if (&stop->getLane() == lane && fabs(stop->getEndLanePosition() - pos) < POSITION_EPS) {
682  return stop->getID();
683  }
684  }
685  return "";
686 }
687 
688 
690 MSNet::getRouterTT(const std::vector<MSEdge*>& prohibited) const {
691  if (!myRouterTTInitialized) {
692  myRouterTTInitialized = true;
693  const std::string routingAlgorithm = OptionsCont::getOptions().getString("routing-algorithm");
694  if (routingAlgorithm == "dijkstra") {
697  } else {
698  if (routingAlgorithm != "astar") {
699  WRITE_WARNING("TraCI and Triggers cannot use routing algorithm '" + routingAlgorithm + "'. using 'astar' instead.");
700  }
703  }
704  }
705  if (myRouterTTDijkstra != 0) {
706  myRouterTTDijkstra->prohibit(prohibited);
707  return *myRouterTTDijkstra;
708  } else {
709  assert(myRouterTTAStar != 0);
710  myRouterTTAStar->prohibit(prohibited);
711  return *myRouterTTAStar;
712  }
713 }
714 
715 
717 MSNet::getRouterEffort(const std::vector<MSEdge*>& prohibited) const {
718  if (myRouterEffort == 0) {
721  }
722  myRouterEffort->prohibit(prohibited);
723  return *myRouterEffort;
724 }
725 
726 
727 
728 #ifdef _MESSAGES
729 MSMessageEmitter*
730 MSNet::getMsgEmitter(const std::string& whatemit) {
731  msgEmitVec.clear();
732  msgEmitVec = myMsgEmitter.buildAndGetStaticVector();
733  for (std::vector<MSMessageEmitter*>::iterator it = msgEmitVec.begin(); it != msgEmitVec.end(); ++it) {
734  if ((*it)->getEventsEnabled(whatemit)) {
735  return *it;
736  }
737  }
738  return 0;
739 }
740 
741 
742 void
743 MSNet::createMsgEmitter(std::string& id,
744  std::string& file,
745  const std::string& base,
746  std::string& whatemit,
747  bool reverse,
748  bool table,
749  bool xy,
750  SUMOReal step) {
751  MSMessageEmitter* msgEmitter = new MSMessageEmitter(file, base, whatemit, reverse, table, xy, step);
752  myMsgEmitter.add(id, msgEmitter);
753 }
754 #endif
755 
756 
757 /****************************************************************************/
758