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-2012 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"
61 #include "MSRouteLoaderControl.h"
62 #include "trigger/MSTrigger.h"
64 #include "MSVehicleControl.h"
66 #include <utils/common/ToString.h>
72 #include <utils/shapes/Polygon.h>
74 
76 #include "output/MSFCDExport.h"
78 #include "output/MSFullExport.h"
79 #include "output/MSQueueExport.h"
80 #include "output/MSVTKExport.h"
81 #include "output/MSXMLRawOut.h"
83 #include <utils/common/SysUtils.h>
86 #include "MSGlobals.h"
88 #include <ctime>
89 #include "MSPerson.h"
90 #include "MSEdgeWeightsStorage.h"
91 
92 
93 #ifdef _MESSAGES
94 #include "MSMessageEmitter.h"
95 #endif
96 
97 #ifdef HAVE_INTERNAL
98 #include <mesosim/MELoop.h>
100 #endif
101 
102 #ifndef NO_TRACI
104 #endif
105 
106 #ifdef CHECK_MEMORY_LEAKS
107 #include <foreign/nvwa/debug_new.h>
108 #endif // CHECK_MEMORY_LEAKS
109 
110 
111 // ===========================================================================
112 // static member definitions
113 // ===========================================================================
115 
116 
117 // ===========================================================================
118 // member method definitions
119 // ===========================================================================
120 SUMOReal
121 MSNet::getEffort(const MSEdge* const e, const SUMOVehicle* const v, SUMOReal t) {
122  SUMOReal value;
123  const MSVehicle* const veh = dynamic_cast<const MSVehicle* const>(v);
124  if (veh != 0 && veh->getWeightsStorage().retrieveExistingEffort(e, v, t, value)) {
125  return value;
126  }
127  if (getInstance()->getWeightsStorage().retrieveExistingEffort(e, v, t, value)) {
128  return value;
129  }
130  return 0;
131 }
132 
133 
134 SUMOReal
135 MSNet::getTravelTime(const MSEdge* const e, const SUMOVehicle* const v, SUMOReal t) {
136  SUMOReal value;
137  const MSVehicle* const veh = dynamic_cast<const MSVehicle* const>(v);
138  if (veh != 0 && veh->getWeightsStorage().retrieveExistingTravelTime(e, v, t, value)) {
139  return value;
140  }
141  if (getInstance()->getWeightsStorage().retrieveExistingTravelTime(e, v, t, value)) {
142  return value;
143  }
144  return e->getMinimumTravelTime(v);
145 }
146 
147 
148 
149 // ---------------------------------------------------------------------------
150 // MSNet - methods
151 // ---------------------------------------------------------------------------
152 MSNet*
154  if (myInstance != 0) {
155  return myInstance;
156  }
157  throw ProcessError("A network was not yet constructed.");
158 }
159 
160 
161 MSNet::MSNet(MSVehicleControl* vc, MSEventControl* beginOfTimestepEvents,
162  MSEventControl* endOfTimestepEvents, MSEventControl* insertionEvents,
163  ShapeContainer* shapeCont):
164  myVehiclesMoved(0),
165  myRouterTTInitialized(false),
166  myRouterTTDijkstra(0),
167  myRouterTTAStar(0),
168  myRouterEffort(0) {
169  if (myInstance != 0) {
170  throw ProcessError("A network was already constructed.");
171  }
173  myStep = string2time(oc.getString("begin"));
174  myLogExecutionTime = !oc.getBool("no-duration-log");
175  myLogStepNumber = !oc.getBool("no-step-log");
176  myTooManyVehicles = oc.getInt("max-num-vehicles");
177  myInserter = new MSInsertionControl(*vc, string2time(oc.getString("max-depart-delay")), oc.getBool("sloppy-insert"));
178  myVehicleControl = vc;
180  myEdges = 0;
181  myJunctions = 0;
182  myRouteLoaders = 0;
183  myLogics = 0;
184  myPersonControl = 0;
185  myEdgeWeights = 0;
186  myShapeContainer = shapeCont == 0 ? new ShapeContainer() : shapeCont;
187 
188  myBeginOfTimestepEvents = beginOfTimestepEvents;
189  myEndOfTimestepEvents = endOfTimestepEvents;
190  myInsertionEvents = insertionEvents;
191 
192 #ifdef HAVE_INTERNAL
194  MSGlobals::gMesoNet = new MELoop(string2time(oc.getString("meso-recheck")));
195  }
196 #endif
197  myInstance = this;
198 }
199 
200 
201 
202 
203 void
205  MSRouteLoaderControl* routeLoaders,
206  MSTLLogicControl* tlc,
207  std::vector<SUMOTime> stateDumpTimes,
208  std::vector<std::string> stateDumpFiles) {
209  myEdges = edges;
210  myJunctions = junctions;
211  myRouteLoaders = routeLoaders;
212  myLogics = tlc;
213  // save the time the network state shall be saved at
214  myStateDumpTimes = stateDumpTimes;
215  myStateDumpFiles = stateDumpFiles;
216 
217  // set requests/responses
219 
220  // initialise performance computation
221  if (myLogExecutionTime) {
223  }
224 }
225 
226 
228  // delete events first maybe they do some cleanup
230  delete myEndOfTimestepEvents;
231  delete myInsertionEvents;
232  // delete controls
233  delete myJunctions;
234  delete myDetectorControl;
235  // delete mean data
236  delete myEdges;
237  delete myInserter;
238  delete myLogics;
239  delete myRouteLoaders;
240  delete myVehicleControl;
241  if (myPersonControl != 0) {
242  delete myPersonControl;
243  }
244  delete myShapeContainer;
245 #ifdef _MESSAGES
246  myMsgEmitter.clear();
247  msgEmitVec.clear();
248 #endif
249  delete myEdgeWeights;
250  delete myRouterTTDijkstra;
251  delete myRouterTTAStar;
252  delete myRouterEffort;
253 #ifdef HAVE_INTERNAL
255  delete MSGlobals::gMesoNet;
256  }
257 #endif
258  clearAll();
259  myInstance = 0;
260 }
261 
262 
263 int
265  // report the begin when wished
266  WRITE_MESSAGE("Simulation started with time: " + time2string(start));
267  // the simulation loop
269  myStep = start;
270 #ifndef NO_TRACI
271 #ifdef HAVE_PYTHON
272  if (OptionsCont::getOptions().isSet("python-script")) {
273  traci::TraCIServer::runEmbedded(OptionsCont::getOptions().getString("python-script"));
274  closeSimulation(start);
275  WRITE_MESSAGE("Simulation ended at time: " + time2string(getCurrentTimeStep()));
276  WRITE_MESSAGE("Reason: Script ended");
277  return 0;
278  }
279 #endif
280 #endif
281  while (state == SIMSTATE_RUNNING) {
282  if (myLogStepNumber) {
284  }
285  simulationStep();
286  if (myLogStepNumber) {
288  }
289  state = simulationState(stop);
290 #ifndef NO_TRACI
291  if (state != SIMSTATE_RUNNING) {
292  if (OptionsCont::getOptions().getInt("remote-port") != 0 && !traci::TraCIServer::wasClosed()) {
293  state = SIMSTATE_RUNNING;
294  }
295  }
296 #endif
297  }
298  // report the end when wished
299  WRITE_MESSAGE("Simulation ended at time: " + time2string(getCurrentTimeStep()));
300  WRITE_MESSAGE("Reason: " + getStateMessage(state));
301  // exit simulation loop
302  closeSimulation(start);
303  return 0;
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
350 #endif
351  // execute beginOfTimestepEvents
352  if (myLogExecutionTime) {
354  }
355 #ifdef HAVE_INTERNAL
356  // netstate output
357  std::vector<SUMOTime>::iterator timeIt = find(myStateDumpTimes.begin(), myStateDumpTimes.end(), myStep);
358  if (timeIt != myStateDumpTimes.end()) {
359  const int dist = distance(myStateDumpTimes.begin(), timeIt);
360  std::ofstream strm(myStateDumpFiles[dist].c_str(), std::fstream::out | std::fstream::binary);
361  saveState(strm);
362  }
363 #endif
367  }
368  // check whether the tls programs need to be switched
370  // set the signals
372 
373 #ifdef HAVE_INTERNAL
375  MSGlobals::gMesoNet->simulate(myStep);
376  } else {
377 #endif
378 
379  // assure all lanes with vehicles are 'active'
381 
382  // move vehicles
383  // precompute possible positions for vehicles that do interact with
384  // their lane's end
386 
387  // move vehicles which do interact with their lane's end
388  // (it is now known whether they may drive
392  }
393 
394  // Vehicles change Lanes (maybe)
396 
399  }
400 #ifdef HAVE_INTERNAL
401  }
402 #endif
403  // load routes
405 
406  // persons
407  if (myPersonControl != 0) {
409  }
410  // emit Vehicles
415  }
417 
418  // execute endOfTimestepEvents
420 
421  // update and write (if needed) detector values
422  writeOutput();
423 
424  if (myLogExecutionTime) {
428  }
429  myStep += DELTA_T;
430 }
431 
432 
437  }
438 #ifndef NO_TRACI
441  }
442  if (stopTime < 0 && OptionsCont::getOptions().getInt("remote-port") == 0) {
443 #else
444  if (stopTime < 0) {
445 #endif
448  && (myInserter->getPendingFlowCount() == 0)
449  && (myPersonControl == 0 || !myPersonControl->hasNonWaiting())) {
450  if (myPersonControl) {
452  }
455  }
456  }
457  if (stopTime >= 0 && myStep >= stopTime) {
459  }
460  return SIMSTATE_RUNNING;
461 }
462 
463 
464 std::string
466  switch (state) {
468  return "";
470  return "The final simulation step has been reached.";
472  return "All vehicles have left the simulation.";
474  return "TraCI requested termination.";
476  return "An error occured (see log).";
478  return "Too many vehicles.";
479  default:
480  return "Unknown reason.";
481  }
482 }
483 
484 
485 void
487  // clear container
488  MSEdge::clear();
489  MSLane::clear();
490  MSRoute::clear();
494 }
495 
496 
497 SUMOTime
499  return myStep;
500 }
501 
502 
503 void
505  // update detector values
507 
508  // check state dumps
509  if (OptionsCont::getOptions().isSet("netstate-dump")) {
511  }
512 
513  // check fcd dumps
514  if (OptionsCont::getOptions().isSet("fcd-output")) {
516  }
517 
518  // check emission dumps
519  if (OptionsCont::getOptions().isSet("emission-output")) {
521  }
522 
523  // check full dumps
524  if (OptionsCont::getOptions().isSet("full-output")) {
526  }
527 
528  // check queue dumps
529  if (OptionsCont::getOptions().isSet("queue-output")) {
531  }
532 
533  // check vtk dumps
534  if (OptionsCont::getOptions().isSet("vtk-output")) {
535 
536  if (MSNet::getInstance()->getVehicleControl().getRunningVehicleNo() > 0) {
537  std::string timestep = time2string(myStep);
538  timestep = timestep.substr(0, timestep.length() - 3);
539  std::string output = OptionsCont::getOptions().getString("vtk-output");
540  std::string filename = output + "_" + timestep + ".vtp";
541 
542  OutputDevice_File dev = OutputDevice_File(filename, false);
543 
544  //build a huge mass of xml files
546 
547  }
548 
549  }
550 
551  // emission output
552  if (OptionsCont::getOptions().isSet("summary-output")) {
553  OutputDevice& od = OutputDevice::getDeviceByOption("summary-output");
554  od << " <step time=\"" << time2string(myStep) << "\" "
555  << "loaded=\"" << myVehicleControl->getLoadedVehicleNo() << "\" "
556  << "emitted=\"" << myVehicleControl->getDepartedVehicleNo() << "\" "
557  << "running=\"" << myVehicleControl->getRunningVehicleNo() << "\" "
558  << "waiting=\"" << myInserter->getWaitingVehicleNo() << "\" "
559  << "ended=\"" << myVehicleControl->getEndedVehicleNo() << "\" "
560  << "meanWaitingTime=\"";
562  od << "\" meanTravelTime=\"";
564  od << "\" ";
565  if (myLogExecutionTime) {
566  od << "duration=\"" << mySimStepDuration << "\" ";
567  }
568  od << "/>\n";
569  }
570  // write detector values
572 }
573 
574 
575 bool
577  return myLogExecutionTime;
578 }
579 
580 
581 #ifdef HAVE_INTERNAL
582 void
583 MSNet::saveState(std::ostream& os) {
585  FileHelpers::writeUInt(os, sizeof(size_t));
586  FileHelpers::writeUInt(os, sizeof(SUMOReal));
589  MSRoute::dict_saveState(os);
592  MSGlobals::gMesoNet->saveState(os);
593  }
594 }
595 
596 
597 SUMOTime
598 MSNet::loadState(BinaryInputDevice& bis) {
599  std::string version;
600  unsigned int sizeT, fpSize, numEdges;
601  SUMOTime step;
602  bis >> version;
603  bis >> sizeT;
604  bis >> fpSize;
605  bis >> numEdges;
606  bis >> step;
607  if (version != VERSION_STRING) {
608  WRITE_WARNING("State was written with sumo version " + version + " (present: " + VERSION_STRING + ")!");
609  }
610  if (sizeT != sizeof(size_t)) {
611  WRITE_WARNING("State was written on a different platform (32bit vs. 64bit)!");
612  }
613  if (fpSize != sizeof(SUMOReal)) {
614  WRITE_WARNING("State was written with a different precision for SUMOReal!");
615  }
616  if (numEdges != MSEdge::dictSize()) {
617  WRITE_WARNING("State was written for a different net!");
618  }
619  const SUMOTime offset = string2time(OptionsCont::getOptions().getString("load-state.offset"));
620  MSRoute::dict_loadState(bis);
621  myVehicleControl->loadState(bis, offset);
623  MSGlobals::gMesoNet->loadState(bis, *myVehicleControl, offset);
624  }
625  return step;
626 }
627 #endif
628 
629 
632  if (myPersonControl == 0) {
634  }
635  return *myPersonControl;
636 }
637 
638 
641  if (myEdgeWeights == 0) {
643  }
644  return *myEdgeWeights;
645 }
646 
647 
648 void
650  std::cout << "Step #" << time2string(myStep);
651 }
652 
653 
654 void
656  if (myLogExecutionTime) {
657  std::ostringstream oss;
658  oss.setf(std::ios::fixed , std::ios::floatfield); // use decimal format
659  oss.setf(std::ios::showpoint); // print decimal point
660  oss << std::setprecision(OUTPUT_ACCURACY);
661  if (mySimStepDuration != 0) {
662  oss << " (" << mySimStepDuration << "ms ~= "
663  << (1000. / (SUMOReal) mySimStepDuration) << "*RT, ~"
665  } else {
666  oss << " (0ms ?*RT. ?";
667  }
668  oss << "UPS, vehicles"
669  << " TOT " << myVehicleControl->getDepartedVehicleNo()
670  << " ACT " << myVehicleControl->getRunningVehicleNo()
671  << ") ";
672  std::string prev = "Step #" + time2string(myStep - DELTA_T);
673  std::cout << oss.str().substr(0, 78 - prev.length());
674  }
675  std::cout << '\r';
676 }
677 
678 
679 void
681  if (find(myVehicleStateListeners.begin(), myVehicleStateListeners.end(), listener) == myVehicleStateListeners.end()) {
682  myVehicleStateListeners.push_back(listener);
683  }
684 }
685 
686 
687 void
689  std::vector<VehicleStateListener*>::iterator i = find(myVehicleStateListeners.begin(), myVehicleStateListeners.end(), listener);
690  if (i != myVehicleStateListeners.end()) {
691  myVehicleStateListeners.erase(i);
692  }
693 }
694 
695 
696 void
698  for (std::vector<VehicleStateListener*>::iterator i = myVehicleStateListeners.begin(); i != myVehicleStateListeners.end(); ++i) {
699  (*i)->vehicleStateChanged(vehicle, to);
700  }
701 }
702 
703 
704 
705 // ------ Insertion and retrieval of bus stops ------
706 bool
708  return myBusStopDict.add(busStop->getID(), busStop);
709 }
710 
711 
712 MSBusStop*
713 MSNet::getBusStop(const std::string& id) const {
714  return myBusStopDict.get(id);
715 }
716 
717 
718 std::string
719 MSNet::getBusStopID(const MSLane* lane, const SUMOReal pos) const {
720  const std::map<std::string, MSBusStop*>& vals = myBusStopDict.getMyMap();
721  for (std::map<std::string, MSBusStop*>::const_iterator it = vals.begin(); it != vals.end(); ++it) {
722  MSBusStop* stop = it->second;
723  if (&stop->getLane() == lane && fabs(stop->getEndLanePosition() - pos) < POSITION_EPS) {
724  return stop->getID();
725  }
726  }
727  return "";
728 }
729 
730 
732 MSNet::getRouterTT(const std::vector<MSEdge*>& prohibited) const {
733  if (!myRouterTTInitialized) {
734  myRouterTTInitialized = true;
735  const std::string routingAlgorithm = OptionsCont::getOptions().getString("routing-algorithm");
736  if (routingAlgorithm == "dijkstra") {
739  } else {
740  if (routingAlgorithm != "astar") {
741  WRITE_WARNING("TraCI and Triggers cannot use routing algorithm '" + routingAlgorithm + "'. using 'astar' instead.");
742  }
745  }
746  }
747  if (myRouterTTDijkstra != 0) {
748  myRouterTTDijkstra->prohibit(prohibited);
749  return *myRouterTTDijkstra;
750  } else {
751  assert(myRouterTTAStar != 0);
752  myRouterTTAStar->prohibit(prohibited);
753  return *myRouterTTAStar;
754  }
755 }
756 
757 
759 MSNet::getRouterEffort(const std::vector<MSEdge*>& prohibited) const {
760  if (myRouterEffort == 0) {
763  }
764  myRouterEffort->prohibit(prohibited);
765  return *myRouterEffort;
766 }
767 
768 
769 
770 #ifdef _MESSAGES
771 MSMessageEmitter*
772 MSNet::getMsgEmitter(const std::string& whatemit) {
773  msgEmitVec.clear();
774  msgEmitVec = myMsgEmitter.buildAndGetStaticVector();
775  for (std::vector<MSMessageEmitter*>::iterator it = msgEmitVec.begin(); it != msgEmitVec.end(); ++it) {
776  if ((*it)->getEventsEnabled(whatemit)) {
777  return *it;
778  }
779  }
780  return 0;
781 }
782 
783 
784 void
785 MSNet::createMsgEmitter(std::string& id,
786  std::string& file,
787  const std::string& base,
788  std::string& whatemit,
789  bool reverse,
790  bool table,
791  bool xy,
792  SUMOReal step) {
793  MSMessageEmitter* msgEmitter = new MSMessageEmitter(file, base, whatemit, reverse, table, xy, step);
794  myMsgEmitter.add(id, msgEmitter);
795 }
796 #endif
797 
798 
799 /****************************************************************************/
800