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 
189 #ifdef HAVE_INTERNAL
191  MSGlobals::gMesoNet = new MELoop(string2time(oc.getString("meso-recheck")));
192  }
193 #endif
194  myInstance = this;
195 }
196 
197 
198 
199 
200 void
202  SUMORouteLoaderControl* routeLoaders,
203  MSTLLogicControl* tlc,
204  std::vector<SUMOTime> stateDumpTimes,
205  std::vector<std::string> stateDumpFiles) {
206  myEdges = edges;
207  myJunctions = junctions;
208  myRouteLoaders = routeLoaders;
209  myLogics = tlc;
210  // save the time the network state shall be saved at
211  myStateDumpTimes = stateDumpTimes;
212  myStateDumpFiles = stateDumpFiles;
213 
214  // set requests/responses
216 
217  // initialise performance computation
218  if (myLogExecutionTime) {
220  }
221 }
222 
223 
225  // delete events first maybe they do some cleanup
227  delete myEndOfTimestepEvents;
228  delete myInsertionEvents;
229  // delete controls
230  delete myJunctions;
231  delete myDetectorControl;
232  // delete mean data
233  delete myEdges;
234  delete myInserter;
235  delete myLogics;
236  delete myRouteLoaders;
237  delete myVehicleControl;
238  if (myPersonControl != 0) {
239  delete myPersonControl;
240  }
241  delete myShapeContainer;
242  delete myEdgeWeights;
243  delete myRouterTTDijkstra;
244  delete myRouterTTAStar;
245  delete myRouterEffort;
246 #ifdef HAVE_INTERNAL
248  delete MSGlobals::gMesoNet;
249  }
250 #endif
251  clearAll();
252  myInstance = 0;
253 }
254 
255 
256 int
258  // report the begin when wished
259  WRITE_MESSAGE("Simulation started with time: " + time2string(start));
260  // the simulation loop
262  myStep = start;
263  // preload the routes especially for TraCI
264  loadRoutes();
265 #ifndef NO_TRACI
266 #ifdef HAVE_PYTHON
267  if (OptionsCont::getOptions().isSet("python-script")) {
268  traci::TraCIServer::runEmbedded(OptionsCont::getOptions().getString("python-script"));
269  closeSimulation(start);
270  WRITE_MESSAGE("Simulation ended at time: " + time2string(getCurrentTimeStep()));
271  WRITE_MESSAGE("Reason: Script ended");
272  return 0;
273  }
274 #endif
275 #endif
276  while (state == SIMSTATE_RUNNING) {
277  if (myLogStepNumber) {
279  }
280  simulationStep();
281  if (myLogStepNumber) {
283  }
284  state = simulationState(stop);
285 #ifndef NO_TRACI
286  if (state != SIMSTATE_RUNNING) {
287  if (OptionsCont::getOptions().getInt("remote-port") != 0 && !traci::TraCIServer::wasClosed()) {
288  state = SIMSTATE_RUNNING;
289  }
290  }
291 #endif
292  }
293  // report the end when wished
294  WRITE_MESSAGE("Simulation ended at time: " + time2string(getCurrentTimeStep()));
295  WRITE_MESSAGE("Reason: " + getStateMessage(state));
296  // exit simulation loop
297  closeSimulation(start);
298  return 0;
299 }
300 
301 void
304 }
305 
306 
307 void
309  if (myLogExecutionTime) {
310  long duration = SysUtils::getCurrentMillis() - mySimBeginMillis;
311  std::ostringstream msg;
312  msg << "Performance: " << "\n" << " Duration: " << duration << " ms" << "\n";
313  if (duration != 0) {
314  msg << " Real time factor: " << (STEPS2TIME(myStep - start) * 1000. / (SUMOReal)duration) << "\n";
315  msg.setf(std::ios::fixed , std::ios::floatfield); // use decimal format
316  msg.setf(std::ios::showpoint); // print decimal point
317  msg << " UPS: " << ((SUMOReal)myVehiclesMoved / ((SUMOReal)duration / 1000)) << "\n";
318  }
319  // prepare optional statistics
320  const std::string discardNotice = ((myVehicleControl->getLoadedVehicleNo() != myVehicleControl->getDepartedVehicleNo()) ?
321  " (Loaded: " + toString(myVehicleControl->getLoadedVehicleNo()) + ")" : "");
322  const std::string collisionNotice = (
324  " (Collisions: " + toString(myVehicleControl->getCollisionCount()) + ")" : "");
325  const std::string teleportNotice = (
327  "Teleports: " + toString(myVehicleControl->getTeleportCount()) + collisionNotice + "\n" : "");
328  // print statistics
329  msg << "Vehicles: " << "\n"
330  << " Emitted: " << myVehicleControl->getDepartedVehicleNo() << discardNotice << "\n"
331  << " Running: " << myVehicleControl->getRunningVehicleNo() << "\n"
332  << " Waiting: " << myInserter->getWaitingVehicleNo() << "\n"
333  << teleportNotice;
334  WRITE_MESSAGE(msg.str());
335  }
337  if (OptionsCont::getOptions().getBool("vehroute-output.write-unfinished")) {
339  }
340 #ifndef NO_TRACI
342 #endif
343 }
344 
345 
346 void
348 #ifndef NO_TRACI
351  if (t != 0 && t->getTargetTime() != 0 && t->getTargetTime() < myStep) {
352  return;
353  }
354 #endif
355  // execute beginOfTimestepEvents
356  if (myLogExecutionTime) {
358  }
359  // simulation state output
360  std::vector<SUMOTime>::iterator timeIt = find(myStateDumpTimes.begin(), myStateDumpTimes.end(), myStep);
361  if (timeIt != myStateDumpTimes.end()) {
362  const int dist = (int)distance(myStateDumpTimes.begin(), timeIt);
364  }
368  }
369  // check whether the tls programs need to be switched
371 
372 #ifdef HAVE_INTERNAL
374  MSGlobals::gMesoNet->simulate(myStep);
375  } else {
376 #endif
377 
378  // assure all lanes with vehicles are 'active'
380 
381  // compute safe velocities for all vehicles for the next few lanes
382  // also register ApproachingVehicleInformation for all links
384 
385  // decide right-of-way and execute movements
389  }
390 
391  // Vehicles change Lanes (maybe)
393 
396  }
397 #ifdef HAVE_INTERNAL
398  }
399 #endif
400  loadRoutes();
401 
402  // persons
403  if (myPersonControl != 0) {
405  }
406  // emit Vehicles
411  }
413 
414  // execute endOfTimestepEvents
416 
417 #ifndef NO_TRACI
418  if (traci::TraCIServer::getInstance() != 0) {
420  }
421 #endif
422  // update and write (if needed) detector values
423  writeOutput();
424 
425  if (myLogExecutionTime) {
429  }
430  myStep += DELTA_T;
431 }
432 
433 
438  }
439 #ifndef NO_TRACI
442  }
443  if (stopTime < 0 && OptionsCont::getOptions().getInt("remote-port") == 0) {
444 #else
445  if (stopTime < 0) {
446 #endif
449  && (myInserter->getPendingFlowCount() == 0)
450  && (myPersonControl == 0 || !myPersonControl->hasNonWaiting())) {
451  if (myPersonControl) {
453  }
456  }
457  }
458  if (stopTime >= 0 && myStep >= stopTime) {
460  }
461  return SIMSTATE_RUNNING;
462 }
463 
464 
465 std::string
467  switch (state) {
469  return "";
471  return "The final simulation step has been reached.";
473  return "All vehicles have left the simulation.";
475  return "TraCI requested termination.";
477  return "An error occured (see log).";
479  return "Too many vehicles.";
480  default:
481  return "Unknown reason.";
482  }
483 }
484 
485 
486 void
488  // clear container
489  MSEdge::clear();
490  MSLane::clear();
491  MSRoute::clear();
496 }
497 
498 
499 SUMOTime
501  return myStep;
502 }
503 
504 
505 void
507  // update detector values
509 
510  // check state dumps
511  if (OptionsCont::getOptions().isSet("netstate-dump")) {
513  }
514 
515  // check fcd dumps
516  if (OptionsCont::getOptions().isSet("fcd-output")) {
518  }
519 
520  // check emission dumps
521  if (OptionsCont::getOptions().isSet("emission-output")) {
523  }
524 
525  // check full dumps
526  if (OptionsCont::getOptions().isSet("full-output")) {
528  }
529 
530  // check queue dumps
531  if (OptionsCont::getOptions().isSet("queue-output")) {
533  }
534 
535  // check vtk dumps
536  if (OptionsCont::getOptions().isSet("vtk-output")) {
537 
538  if (MSNet::getInstance()->getVehicleControl().getRunningVehicleNo() > 0) {
539  std::string timestep = time2string(myStep);
540  timestep = timestep.substr(0, timestep.length() - 3);
541  std::string output = OptionsCont::getOptions().getString("vtk-output");
542  std::string filename = output + "_" + timestep + ".vtp";
543 
544  OutputDevice_File dev = OutputDevice_File(filename, false);
545 
546  //build a huge mass of xml files
548 
549  }
550 
551  }
552 
553  // emission output
554  if (OptionsCont::getOptions().isSet("summary-output")) {
555  OutputDevice& od = OutputDevice::getDeviceByOption("summary-output");
556  od << " <step time=\"" << time2string(myStep) << "\" "
557  << "loaded=\"" << myVehicleControl->getLoadedVehicleNo() << "\" "
558  << "emitted=\"" << myVehicleControl->getDepartedVehicleNo() << "\" "
559  << "running=\"" << myVehicleControl->getRunningVehicleNo() << "\" "
560  << "waiting=\"" << myInserter->getWaitingVehicleNo() << "\" "
561  << "ended=\"" << myVehicleControl->getEndedVehicleNo() << "\" "
562  << "meanWaitingTime=\"";
564  od << "\" meanTravelTime=\"";
566  od << "\" ";
567  if (myLogExecutionTime) {
568  od << "duration=\"" << mySimStepDuration << "\" ";
569  }
570  od << "/>\n";
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 /****************************************************************************/