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 /****************************************************************************/
12 // The simulated network and simulation perfomer
13 /****************************************************************************/
14 // SUMO, Simulation of Urban MObility; see http://sumo.sourceforge.net/
15 // Copyright (C) 2001-2012 DLR (http://www.dlr.de/) and contributors
16 /****************************************************************************/
17 //
18 // This file is part of SUMO.
19 // SUMO is free software: you can redistribute it and/or modify
20 // it under the terms of the GNU General Public License as published by
21 // the Free Software Foundation, either version 3 of the License, or
22 // (at your option) any later version.
23 //
24 /****************************************************************************/
25 
26 
27 // ===========================================================================
28 // included modules
29 // ===========================================================================
30 #ifdef _MSC_VER
31 #include <windows_config.h>
32 #else
33 #include <config.h>
34 #endif
35 
36 #ifdef HAVE_VERSION_H
37 #include <version.h>
38 #endif
39 
40 #include <iostream>
41 #include <sstream>
42 #include <typeinfo>
43 #include <algorithm>
44 #include <cassert>
45 #include <vector>
46 #include <sstream>
48 #include "MSNet.h"
49 #include "MSPersonControl.h"
50 #include "MSEdgeControl.h"
51 #include "MSJunctionControl.h"
52 #include "MSInsertionControl.h"
53 #include "MSEventControl.h"
54 #include "MSEdge.h"
55 #include "MSJunction.h"
56 #include "MSJunctionLogic.h"
57 #include "MSLane.h"
58 #include "MSVehicleTransfer.h"
59 #include "MSRoute.h"
60 #include "MSRouteLoaderControl.h"
62 #include "MSVehicleControl.h"
64 #include <utils/common/ToString.h>
68 #include <utils/shapes/Polygon.h>
70 #include "output/MSXMLRawOut.h"
72 #include <utils/common/SysUtils.h>
75 #include "MSGlobals.h"
77 #include <ctime>
78 #include "MSPerson.h"
79 #include "MSEdgeWeightsStorage.h"
80 
81 
82 #ifdef _MESSAGES
83 #include "MSMessageEmitter.h"
84 #endif
85 
86 #ifdef HAVE_MESOSIM
87 #include <mesosim/MELoop.h>
89 #endif
90 
91 #ifndef NO_TRACI
93 #endif
94 
95 #ifdef CHECK_MEMORY_LEAKS
96 #include <foreign/nvwa/debug_new.h>
97 #endif // CHECK_MEMORY_LEAKS
98 
99 
100 // ===========================================================================
101 // static member definitions
102 // ===========================================================================
104 
105 
106 // ===========================================================================
107 // member method definitions
108 // ===========================================================================
109 // ---------------------------------------------------------------------------
110 // MSNet::EdgeWeightsProxi - methods
111 // ---------------------------------------------------------------------------
112 SUMOReal
114  const SUMOVehicle* const v,
115  SUMOReal t) const {
116  SUMOReal value;
117  if (myVehicleKnowledge.retrieveExistingEffort(e, v, t, value)) {
118  return value;
119  }
120  if (myNetKnowledge.retrieveExistingEffort(e, v, t, value)) {
121  return value;
122  }
123  return 0;
124 }
125 
126 
127 SUMOReal
129  const SUMOVehicle* const v,
130  SUMOReal t) const {
131  SUMOReal value;
132  if (myVehicleKnowledge.retrieveExistingTravelTime(e, v, t, value)) {
133  return value;
134  }
135  if (myNetKnowledge.retrieveExistingTravelTime(e, v, t, value)) {
136  return value;
137  }
138  const MSLane* const l = e->getLanes()[0];
139  return l->getLength() / l->getMaxSpeed();
140 }
141 
142 
143 
144 // ---------------------------------------------------------------------------
145 // MSNet - methods
146 // ---------------------------------------------------------------------------
147 MSNet*
149  if (myInstance != 0) {
150  return myInstance;
151  }
152  throw ProcessError("A network was not yet constructed.");
153 }
154 
155 
156 MSNet::MSNet(MSVehicleControl* vc, MSEventControl* beginOfTimestepEvents,
157  MSEventControl* endOfTimestepEvents, MSEventControl* insertionEvents,
158  ShapeContainer* shapeCont) {
159  if (myInstance != 0) {
160  throw ProcessError("A network was already constructed.");
161  }
163  myStep = string2time(oc.getString("begin"));
164  myLogExecutionTime = !oc.getBool("no-duration-log");
165  myLogStepNumber = !oc.getBool("no-step-log");
166  myTooManyVehicles = oc.getInt("max-num-vehicles");
167  myInserter = new MSInsertionControl(*vc, string2time(oc.getString("max-depart-delay")), oc.getBool("sloppy-insert"));
168  myVehicleControl = vc;
170  myEdges = 0;
171  myJunctions = 0;
172  myRouteLoaders = 0;
173  myLogics = 0;
174  myPersonControl = 0;
175  myEdgeWeights = 0;
176  myShapeContainer = shapeCont == 0 ? new ShapeContainer() : shapeCont;
177 
178  myBeginOfTimestepEvents = beginOfTimestepEvents;
179  myEndOfTimestepEvents = endOfTimestepEvents;
180  myInsertionEvents = insertionEvents;
181 
182 #ifdef HAVE_MESOSIM
184  MSGlobals::gMesoNet = new MELoop(string2time(oc.getString("meso-recheck")));
185  }
186 #endif
187  myInstance = this;
188 }
189 
190 
191 
192 
193 void
195  MSRouteLoaderControl* routeLoaders,
196  MSTLLogicControl* tlc,
197  std::vector<SUMOTime> stateDumpTimes,
198  std::vector<std::string> stateDumpFiles) {
199  myEdges = edges;
200  myJunctions = junctions;
201  myRouteLoaders = routeLoaders;
202  myLogics = tlc;
203  // save the time the network state shall be saved at
204  myStateDumpTimes = stateDumpTimes;
205  myStateDumpFiles = stateDumpFiles;
206 
207  // set requests/responses
209 
210  // initialise performance computation
211  if (myLogExecutionTime) {
213  }
214 }
215 
216 
218  // delete events first maybe they do some cleanup
220  delete myEndOfTimestepEvents;
221  delete myInsertionEvents;
222  // delete controls
223  delete myJunctions;
224  delete myDetectorControl;
225  // delete mean data
226  delete myEdges;
227  delete myInserter;
228  delete myLogics;
229  delete myRouteLoaders;
230  delete myVehicleControl;
231  if (myPersonControl != 0) {
232  delete myPersonControl;
233  }
234  delete myShapeContainer;
235 #ifdef _MESSAGES
236  myMsgEmitter.clear();
237  msgEmitVec.clear();
238 #endif
239  delete myEdgeWeights;
240 #ifdef HAVE_MESOSIM
242  delete MSGlobals::gMesoNet;
243  }
244 #endif
245  clearAll();
246  myInstance = 0;
247 }
248 
249 
250 int
252  // report the begin when wished
253  WRITE_MESSAGE("Simulation started with time: " + time2string(start));
254  // the simulation loop
256  myStep = start;
257 #ifndef NO_TRACI
258 #ifdef HAVE_PYTHON
259  if (OptionsCont::getOptions().isSet("python-script")) {
260  traci::TraCIServer::runEmbedded(OptionsCont::getOptions().getString("python-script"));
261  closeSimulation(start);
262  WRITE_MESSAGE("Simulation ended at time: " + time2string(getCurrentTimeStep()));
263  WRITE_MESSAGE("Reason: Script ended");
264  return 0;
265  }
266 #endif
267 #endif
268  while (state == SIMSTATE_RUNNING) {
269  if (myLogStepNumber) {
271  }
272  simulationStep();
273  if (myLogStepNumber) {
275  }
276  state = simulationState(stop);
277 #ifndef NO_TRACI
278  if (state != SIMSTATE_RUNNING) {
279  if (OptionsCont::getOptions().getInt("remote-port") != 0 && !traci::TraCIServer::wasClosed()) {
280  state = SIMSTATE_RUNNING;
281  }
282  }
283 #endif
284  }
285  // report the end when wished
286  WRITE_MESSAGE("Simulation ended at time: " + time2string(getCurrentTimeStep()));
287  WRITE_MESSAGE("Reason: " + getStateMessage(state));
288  // exit simulation loop
289  closeSimulation(start);
290  return 0;
291 }
292 
293 
294 void
296  if (myLogExecutionTime) {
297  long duration = SysUtils::getCurrentMillis() - mySimBeginMillis;
298  std::ostringstream msg;
299  msg << "Performance: " << "\n" << " Duration: " << duration << " ms" << "\n";
300  if (duration != 0) {
301  msg << " Real time factor: " << (STEPS2TIME(myStep - start) * 1000. / (SUMOReal)duration) << "\n";
302  msg.setf(std::ios::fixed , std::ios::floatfield); // use decimal format
303  msg.setf(std::ios::showpoint); // print decimal point
304  msg << " UPS: " << ((SUMOReal) myVehiclesMoved * 1000. / (SUMOReal) duration) << "\n";
305  }
306  const std::string scaleNotice = ((myVehicleControl->getLoadedVehicleNo() != myVehicleControl->getDepartedVehicleNo()) ?
307  " (Loaded: " + toString(myVehicleControl->getLoadedVehicleNo()) + ")" : "");
308  msg << "Vehicles: " << "\n"
309  << " Emitted: " << myVehicleControl->getDepartedVehicleNo() << scaleNotice << "\n"
310  << " Running: " << myVehicleControl->getRunningVehicleNo() << "\n"
311  << " Waiting: " << myInserter->getWaitingVehicleNo() << "\n";
312  WRITE_MESSAGE(msg.str());
313  }
315 #ifndef NO_TRACI
317 #endif
318 }
319 
320 
321 void
323 #ifndef NO_TRACI
325 #endif
326  // execute beginOfTimestepEvents
327  if (myLogExecutionTime) {
329  }
330 #ifdef HAVE_MESOSIM
331  // netstate output
332  std::vector<SUMOTime>::iterator timeIt = find(myStateDumpTimes.begin(), myStateDumpTimes.end(), myStep);
333  if (timeIt != myStateDumpTimes.end()) {
334  const int dist = distance(myStateDumpTimes.begin(), timeIt);
335  std::ofstream strm(myStateDumpFiles[dist].c_str(), std::fstream::out | std::fstream::binary);
336  saveState(strm);
337  }
338 #endif
342  }
343  // check whether the tls programs need to be switched
345  // set the signals
347 
348 #ifdef HAVE_MESOSIM
350  MSGlobals::gMesoNet->simulate(myStep);
351  } else {
352 #endif
353 
354  // assure all lanes with vehicles are 'active'
356 
357  // move vehicles
358  // precompute possible positions for vehicles that do interact with
359  // their lane's end
361 
362  // move vehicles which do interact with their lane's end
363  // (it is now known whether they may drive
367  }
368 
369  // Vehicles change Lanes (maybe)
371 
374  }
375 #ifdef HAVE_MESOSIM
376  }
377 #endif
378  // load routes
380 
381  // persons
382  if (myPersonControl != 0) {
384  }
385  // emit Vehicles
390  }
391  MSVehicleTransfer::getInstance()->checkInsertions(myStep);
392 
393  // execute endOfTimestepEvents
395 
396  // update and write (if needed) detector values
397  writeOutput();
398 
399  if (myLogExecutionTime) {
403  }
404  myStep += DELTA_T;
405 }
406 
407 
412  }
413 #ifndef NO_TRACI
416  }
417  if (stopTime < 0 && OptionsCont::getOptions().getInt("remote-port") == 0) {
418 #else
419  if (stopTime < 0) {
420 #endif
423  && (myInserter->getPendingFlowCount() == 0)
425  if (myPersonControl) {
427  }
430  }
431  }
432  if (stopTime >= 0 && myStep >= stopTime) {
434  }
435  return SIMSTATE_RUNNING;
436 }
437 
438 
439 std::string
441  switch (state) {
443  return "";
445  return "The final simulation step has been reached.";
447  return "All vehicles have left the simulation.";
449  return "TraCI requested termination.";
451  return "An error occured (see log).";
453  return "Too many vehicles.";
454  default:
455  return "Unknown reason.";
456  }
457 }
458 
459 
460 void
462  // clear container
463  MSEdge::clear();
464  MSLane::clear();
465  MSRoute::clear();
467 }
468 
469 
470 SUMOTime
472  return myStep;
473 }
474 
475 
476 void
478  // update detector values
480  // check state dumps
481  if (OptionsCont::getOptions().isSet("netstate-dump")) {
483  }
484  // emission output
485  if (OptionsCont::getOptions().isSet("summary-output")) {
487  od << " <step time=\"" << time2string(myStep) << "\" "
488  << "loaded=\"" << myVehicleControl->getLoadedVehicleNo() << "\" "
489  << "emitted=\"" << myVehicleControl->getDepartedVehicleNo() << "\" "
490  << "running=\"" << myVehicleControl->getRunningVehicleNo() << "\" "
491  << "waiting=\"" << myInserter->getWaitingVehicleNo() << "\" "
492  << "ended=\"" << myVehicleControl->getEndedVehicleNo() << "\" "
493  << "meanWaitingTime=\"";
495  od << "\" meanTravelTime=\"";
497  od << "\" ";
498  if (myLogExecutionTime) {
499  od << "duration=\"" << mySimStepDuration << "\" ";
500  }
501  od << "/>\n";
502  }
503  // write detector values
505 }
506 
507 
508 bool
510  return myLogExecutionTime;
511 }
512 
513 
514 #ifdef HAVE_MESOSIM
515 void
516 MSNet::saveState(std::ostream& os) {
518  FileHelpers::writeUInt(os, sizeof(size_t));
519  FileHelpers::writeUInt(os, sizeof(SUMOReal));
522  MSRoute::dict_saveState(os);
525  MSGlobals::gMesoNet->saveState(os);
526  }
527 }
528 
529 
530 unsigned int
531 MSNet::loadState(BinaryInputDevice& bis) {
532  std::string version;
533  unsigned int sizeT, fpSize, numEdges, step;
534  bis >> version;
535  bis >> sizeT;
536  bis >> fpSize;
537  bis >> numEdges;
538  bis >> step;
539  if (version != VERSION_STRING) {
540  WRITE_WARNING("State was written with sumo version " + version + " (present: " + VERSION_STRING + ")!");
541  }
542  if (sizeT != sizeof(size_t)) {
543  WRITE_WARNING("State was written on a different platform (32bit vs. 64bit)!");
544  }
545  if (fpSize != sizeof(SUMOReal)) {
546  WRITE_WARNING("State was written with a different precision for SUMOReal!");
547  }
548  if (numEdges != MSEdge::dictSize()) {
549  WRITE_WARNING("State was written for a different net!");
550  }
551  const SUMOTime offset = string2time(OptionsCont::getOptions().getString("load-state.offset"));
552  MSRoute::dict_loadState(bis);
553  myVehicleControl->loadState(bis, offset);
555  MSGlobals::gMesoNet->loadState(bis, *myVehicleControl, offset);
556  }
557  return step;
558 }
559 #endif
560 
561 
564  if (myPersonControl == 0) {
566  }
567  return *myPersonControl;
568 }
569 
570 
573  if (myEdgeWeights == 0) {
575  }
576  return *myEdgeWeights;
577 }
578 
579 
580 void
582  std::cout << "Step #" << time2string(myStep);
583 }
584 
585 
586 void
588  if (myLogExecutionTime) {
589  std::ostringstream oss;
590  oss.setf(std::ios::fixed , std::ios::floatfield); // use decimal format
591  oss.setf(std::ios::showpoint); // print decimal point
592  oss << std::setprecision(OUTPUT_ACCURACY);
593  if (mySimStepDuration != 0) {
594  oss << " (" << mySimStepDuration << "ms ~= "
595  << (1000. / (SUMOReal) mySimStepDuration) << "*RT, ~"
597  } else {
598  oss << " (0ms ?*RT. ?";
599  }
600  oss << "UPS, vehicles"
601  << " TOT " << myVehicleControl->getDepartedVehicleNo()
602  << " ACT " << myVehicleControl->getRunningVehicleNo()
603  << ") ";
604  std::string prev = "Step #" + time2string(myStep - DELTA_T);
605  std::cout << oss.str().substr(0, 78 - prev.length());
606  }
607  std::cout << '\r';
608 }
609 
610 
611 void
613  if (find(myVehicleStateListeners.begin(), myVehicleStateListeners.end(), listener) == myVehicleStateListeners.end()) {
614  myVehicleStateListeners.push_back(listener);
615  }
616 }
617 
618 
619 void
621  std::vector<VehicleStateListener*>::iterator i = find(myVehicleStateListeners.begin(), myVehicleStateListeners.end(), listener);
622  if (i != myVehicleStateListeners.end()) {
623  myVehicleStateListeners.erase(i);
624  }
625 }
626 
627 
628 void
630  for (std::vector<VehicleStateListener*>::iterator i = myVehicleStateListeners.begin(); i != myVehicleStateListeners.end(); ++i) {
631  (*i)->vehicleStateChanged(vehicle, to);
632  }
633 }
634 
635 
636 
637 // ------ Insertion and retrieval of bus stops ------
638 bool
640  return myBusStopDict.add(busStop->getID(), busStop);
641 }
642 
643 
644 MSBusStop*
645 MSNet::getBusStop(const std::string& id) const {
646  return myBusStopDict.get(id);
647 }
648 
649 
650 std::string
651 MSNet::getBusStopID(const MSLane* lane, const SUMOReal pos) const {
652  const std::map<std::string, MSBusStop*> &vals = myBusStopDict.getMyMap();
653  for (std::map<std::string, MSBusStop*>::const_iterator it = vals.begin(); it != vals.end(); ++it) {
654  MSBusStop* stop = it->second;
655  if (&stop->getLane() == lane && fabs(stop->getEndLanePosition() - pos) < POSITION_EPS) {
656  return stop->getID();
657  }
658  }
659  return "";
660 }
661 
662 
663 #ifdef _MESSAGES
664 MSMessageEmitter*
665 MSNet::getMsgEmitter(const std::string& whatemit) {
666  msgEmitVec.clear();
667  msgEmitVec = myMsgEmitter.buildAndGetStaticVector();
668  MSMessageEmitter* msgEmitter = 0;
669  for (int i = 0; i < msgEmitVec.size(); ++i) {
670  if (msgEmitVec.at(i)->getEventsEnabled(whatemit)) {
671  msgEmitter = msgEmitVec.at(i);
672  break;
673  }
674  }
675  // returns 0 if the requested MessageEmitter is not in the map
676  return msgEmitter;
677 }
678 
679 
680 void
681 MSNet::createMsgEmitter(std::string& id,
682  std::string& file,
683  const std::string& base,
684  std::string& whatemit,
685  bool reverse,
686  bool table,
687  bool xy,
688  SUMOReal step) {
689  MSMessageEmitter* msgEmitter = new MSMessageEmitter(file, base, whatemit, reverse, table, xy, step);
690  myMsgEmitter.add(id, msgEmitter);
691 }
692 #endif
693 
694 
695 /****************************************************************************/
696