Eclipse SUMO - Simulation of Urban MObility
MSCalibrator.cpp
Go to the documentation of this file.
1 /****************************************************************************/
2 // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
3 // Copyright (C) 2005-2020 German Aerospace Center (DLR) and others.
4 // This program and the accompanying materials are made available under the
5 // terms of the Eclipse Public License 2.0 which is available at
6 // https://www.eclipse.org/legal/epl-2.0/
7 // This Source Code may also be made available under the following Secondary
8 // Licenses when the conditions for such availability set forth in the Eclipse
9 // Public License 2.0 are satisfied: GNU General Public License, version 2
10 // or later which is available at
11 // https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
12 // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
13 /****************************************************************************/
20 // Calibrates the flow on an edge by removing an inserting vehicles
21 /****************************************************************************/
22 #include <config.h>
23 
24 #include <string>
25 #include <algorithm>
26 #include <cmath>
27 #include <microsim/MSNet.h>
28 #include <microsim/MSEdge.h>
29 #include <microsim/MSLane.h>
34 #include <utils/common/ToString.h>
37 #include <utils/xml/XMLSubSys.h>
43 #include "MSCalibrator.h"
44 
45 //#define MSCalibrator_DEBUG
46 
47 #define DEBUGID ""
48 #define DEBUGCOND (getID() == DEBUGID)
49 #define DEBUGCOND2(id) ((id) == DEBUGID)
50 
51 // ===========================================================================
52 // static members
53 // ===========================================================================
54 std::vector<MSMoveReminder*> MSCalibrator::LeftoverReminders;
55 std::vector<SUMOVehicleParameter*> MSCalibrator::LeftoverVehicleParameters;
56 std::map<std::string, MSCalibrator*> MSCalibrator::myInstances;
57 
58 // ===========================================================================
59 // method definitions
60 // ===========================================================================
61 MSCalibrator::MSCalibrator(const std::string& id,
62  const MSEdge* const edge,
63  MSLane* lane,
64  const double pos,
65  const std::string& aXMLFilename,
66  const std::string& outputFilename,
67  const SUMOTime freq, const double length,
68  const MSRouteProbe* probe,
69  const double invalidJamThreshold,
70  const std::string& vTypes,
71  bool addLaneMeanData) :
72  MSTrigger(id),
73  MSRouteHandler(aXMLFilename, true),
74  MSDetectorFileOutput(id, vTypes, false), // detecting persons not yet supported
75  myEdge(edge),
76  myLane(lane),
77  myPos(pos), myProbe(probe),
78  myMeanDataParent(id + "_dummyMeanData", 0, 0, false, false, false, false, false, false, 1, 0, 0, vTypes, ""),
79  myEdgeMeanData(nullptr, length, false, &myMeanDataParent),
80  myCurrentStateInterval(myIntervals.begin()),
81  myOutput(nullptr), myFrequency(freq), myRemoved(0),
82  myInserted(0), myClearedInJam(0),
83  mySpeedIsDefault(true), myDidSpeedAdaption(false), myDidInit(false),
84  myDefaultSpeed(myLane == nullptr ? myEdge->getSpeedLimit() : myLane->getSpeedLimit()),
85  myHaveWarnedAboutClearingJam(false),
86  myAmActive(false),
87  myInvalidJamThreshold(invalidJamThreshold),
88  myHaveInvalidJam(false) {
89  myInstances[id] = this;
90  if (outputFilename != "") {
91  myOutput = &OutputDevice::getDevice(outputFilename);
93  }
94  if (aXMLFilename != "") {
95  XMLSubSys::runParser(*this, aXMLFilename);
96  if (!myDidInit) {
97  init();
98  }
99  }
100  if (addLaneMeanData) {
101  // disabled for METriggeredCalibrator
102  for (MSLane* const eLane : myEdge->getLanes()) {
103  if (myLane == nullptr || myLane == eLane) {
104  //std::cout << " cali=" << getID() << " myLane=" << Named::getIDSecure(myLane) << " checkLane=" << i << "\n";
105  MSMeanData_Net::MSLaneMeanDataValues* laneData = new MSMeanData_Net::MSLaneMeanDataValues(eLane, eLane->getLength(), true, &myMeanDataParent);
106  laneData->setDescription("meandata_calibrator_" + eLane->getID());
107  LeftoverReminders.push_back(laneData);
108  myLaneMeanData.push_back(laneData);
109  VehicleRemover* remover = new VehicleRemover(eLane, this);
110  LeftoverReminders.push_back(remover);
111  myVehicleRemovers.push_back(remover);
112  }
113  }
114  }
115 }
116 
117 
118 void
120  if (myIntervals.size() > 0) {
121  if (myIntervals.back().end == -1) {
122  myIntervals.back().end = SUMOTime_MAX;
123  }
124  // calibration should happen after regular insertions have taken place
126  } else {
127  WRITE_WARNING("No flow intervals in calibrator '" + getID() + "'.");
128  }
129  myDidInit = true;
130 }
131 
132 
134  if (myCurrentStateInterval != myIntervals.end()) {
135  intervalEnd();
136  }
137  for (VehicleRemover* const remover : myVehicleRemovers) {
138  remover->disable();
139  }
140  myInstances.erase(getID());
141 }
142 
145  if (myCurrentStateInterval == myIntervals.end()) {
146  throw ProcessError("Calibrator '" + getID() + "' has no active or upcoming interval");
147  }
148  return *myCurrentStateInterval;
149 }
150 
151 void
153  const SUMOSAXAttributes& attrs) {
154  if (element == SUMO_TAG_FLOW) {
155  AspiredState state;
156  SUMOTime lastEnd = -1;
157  if (myIntervals.size() > 0) {
158  lastEnd = myIntervals.back().end;
159  if (lastEnd == -1) {
160  lastEnd = myIntervals.back().begin;
161  }
162  }
163  try {
164  bool ok = true;
165  state.q = attrs.getOpt<double>(SUMO_ATTR_VEHSPERHOUR, nullptr, ok, -1.);
166  state.v = attrs.getOpt<double>(SUMO_ATTR_SPEED, nullptr, ok, -1.);
167  state.begin = attrs.getSUMOTimeReporting(SUMO_ATTR_BEGIN, getID().c_str(), ok);
168  if (state.begin < lastEnd) {
169  WRITE_ERROR("Overlapping or unsorted intervals in calibrator '" + getID() + "'.");
170  }
171  state.end = attrs.getOptSUMOTimeReporting(SUMO_ATTR_END, getID().c_str(), ok, -1);
172  state.vehicleParameter = SUMOVehicleParserHelper::parseVehicleAttributes(element, attrs, true, true, true);
174  // vehicles should be inserted with max speed unless stated otherwise
177  }
178  // vehicles should be inserted on any lane unless stated otherwise
180  if (myLane == nullptr) {
182  } else {
185  }
186  } else if (myLane != nullptr && (
188  || state.vehicleParameter->departLane != myLane->getIndex())) {
189  WRITE_WARNING("Insertion lane may differ from calibrator lane for calibrator '" + getID() + "'.");
190  }
191  if (state.vehicleParameter->vtypeid != DEFAULT_VTYPE_ID &&
193  WRITE_ERROR("Unknown vehicle type '" + state.vehicleParameter->vtypeid + "' in calibrator '" + getID() + "'.");
194  }
195  } catch (EmptyData&) {
196  WRITE_ERROR("Mandatory attribute missing in definition of calibrator '" + getID() + "'.");
197  } catch (NumberFormatException&) {
198  WRITE_ERROR("Non-numeric value for numeric attribute in definition of calibrator '" + getID() + "'.");
199  }
200  if (state.q < 0 && state.v < 0 && state.vehicleParameter->vtypeid == DEFAULT_VTYPE_ID) {
201  WRITE_ERROR("Either 'vehsPerHour', 'speed' or 'type' has to be set in flow definition of calibrator '" + getID() + "'.");
202  }
203  if (MSGlobals::gUseMesoSim && state.q < 0 && state.vehicleParameter->vtypeid != DEFAULT_VTYPE_ID) {
204  WRITE_ERROR("Type calibration is not supported in meso for calibrator '" + getID() + "'.");
205  }
206  if (myIntervals.size() > 0 && myIntervals.back().end == -1) {
207  myIntervals.back().end = state.begin;
208  }
209  myIntervals.push_back(state);
211  } else {
212  MSRouteHandler::myStartElement(element, attrs);
213  }
214 }
215 
216 
217 void
219  if (element == SUMO_TAG_CALIBRATOR) {
220  if (!myDidInit) {
221  init();
222  }
223  } else if (element != SUMO_TAG_FLOW) {
225  }
226 }
227 
228 
229 void
231  if (myOutput != nullptr) {
233  }
234  myDidSpeedAdaption = false;
235  myInserted = 0;
236  myRemoved = 0;
237  myClearedInJam = 0;
239  reset();
240 }
241 
242 
243 bool
245  while (myCurrentStateInterval != myIntervals.end() && myCurrentStateInterval->end <= time) {
246  // XXX what about skipped intervals?
248  }
249  return myCurrentStateInterval != myIntervals.end() &&
250  myCurrentStateInterval->begin <= time && myCurrentStateInterval->end > time;
251 }
252 
253 int
255  if (myCurrentStateInterval != myIntervals.end()) {
256  const double totalHourFraction = STEPS2TIME(myCurrentStateInterval->end - myCurrentStateInterval->begin) / (double) 3600.;
257  return (int)std::floor(myCurrentStateInterval->q * totalHourFraction + 0.5); // round to closest int
258  } else {
259  return -1;
260  }
261 }
262 
263 
264 double
266  const double totalHourFraction = STEPS2TIME(MSNet::getInstance()->getCurrentTimeStep() - myCurrentStateInterval->begin) / (double) 3600.;
267  return passed() / totalHourFraction;
268 }
269 
270 double
272  if (myEdgeMeanData.getSamples() > 0) {
274  } else {
275  return -1;
276  }
277 }
278 
279 
280 bool
282  if (myToRemove.size() > 0) {
284  // it is not save to remove the vehicles inside
285  // VehicleRemover::notifyEnter so we do it here
286  for (std::set<std::string>::iterator it = myToRemove.begin(); it != myToRemove.end(); ++it) {
287  MSVehicle* vehicle = dynamic_cast<MSVehicle*>(vc.getVehicle(*it));
288  if (vehicle != nullptr) {
289  MSLane* lane = vehicle->getMutableLane();
292  vc.scheduleVehicleRemoval(vehicle, true);
293  } else {
294  WRITE_WARNING("Calibrator '" + getID() + "' could not remove vehicle '" + *it + "' time=" + time2string(MSNet::getInstance()->getCurrentTimeStep()) + ".");
295  }
296  }
297  myToRemove.clear();
298  return true;
299  }
300  return false;
301 }
302 
303 
304 SUMOTime
306  const bool calibrateFlow = myCurrentStateInterval->q >= 0;
307  const bool calibrateSpeed = myCurrentStateInterval->v >= 0;
308  // get current simulation values (valid for the last simulation second)
309  myHaveInvalidJam = (calibrateFlow || calibrateSpeed) && invalidJam(myLane == 0 ? -1 : myLane->getIndex());
310  // XXX could we miss vehicle movements if this is called less often than every DELTA_T (default) ?
311  updateMeanData();
312  const bool hadRemovals = removePending();
313  // check whether an adaptation value exists
314  if (isCurrentStateActive(currentTime)) {
315  myAmActive = true;
316  // all happens in isCurrentStateActive()
317  } else {
318  myAmActive = false;
319  reset();
320  if (!mySpeedIsDefault) {
321  // reset speed to default
322  if (myLane == nullptr) {
324  } else {
326  }
327  mySpeedIsDefault = true;
328  }
329  if (myCurrentStateInterval == myIntervals.end()) {
330  // keep calibrator alive for gui but do not call again
331  return TIME2STEPS(86400);
332  }
333  return myFrequency;
334  }
335  // we are active
336  if (!myDidSpeedAdaption && calibrateSpeed) {
337  if (myLane == nullptr) {
339  } else {
341  }
342  mySpeedIsDefault = false;
343  myDidSpeedAdaption = true;
344  }
345 
346  const int totalWishedNum = totalWished();
347  int adaptedNum = passed() + myClearedInJam;
348 #ifdef MSCalibrator_DEBUG
349  if (DEBUGCOND) {
350  std::cout << time2string(currentTime) << " " << getID()
351  << " q=" << myCurrentStateInterval->q
352  << " totalWished=" << totalWishedNum
353  << " adapted=" << adaptedNum
354  << " jam=" << myHaveInvalidJam
355  << " entered=" << myEdgeMeanData.nVehEntered
356  << " departed=" << myEdgeMeanData.nVehDeparted
357  << " arrived=" << myEdgeMeanData.nVehArrived
358  << " left=" << myEdgeMeanData.nVehLeft
359  << " waitSecs=" << myEdgeMeanData.waitSeconds
360  << " vaporized=" << myEdgeMeanData.nVehVaporized
361  << "\n";
362  }
363 #endif
364  if (calibrateFlow && adaptedNum < totalWishedNum && !hadRemovals) {
365  // we need to insert some vehicles
366  const double hourFraction = STEPS2TIME(currentTime - myCurrentStateInterval->begin + DELTA_T) / (double) 3600.;
367  const int wishedNum = (int)std::floor(myCurrentStateInterval->q * hourFraction + 0.5); // round to closest int
368  // only the difference between inflow and aspiredFlow should be added, thus
369  // we should not count vehicles vaporized from a jam here
370  // if we have enough time left we can add missing vehicles later
371  const int relaxedInsertion = (int)std::floor(STEPS2TIME(myCurrentStateInterval->end - currentTime) / 3);
372  const int insertionSlack = MAX2(0, adaptedNum + relaxedInsertion - totalWishedNum);
373  // increase number of vehicles
374 #ifdef MSCalibrator_DEBUG
375  if (DEBUGCOND) {
376  std::cout << " wished:" << wishedNum
377  << " slack:" << insertionSlack
378  << " before:" << adaptedNum
379  << "\n";
380  }
381 #endif
382  while (wishedNum > adaptedNum + insertionSlack) {
383  SUMOVehicleParameter* pars = myCurrentStateInterval->vehicleParameter;
384  const MSRoute* route = myProbe != nullptr ? myProbe->sampleRoute() : nullptr;
385  if (route == nullptr) {
386  route = MSRoute::dictionary(pars->routeid);
387  }
388  if (route == nullptr) {
389  WRITE_WARNING("No valid routes in calibrator '" + getID() + "'.");
390  break;
391  }
392  if (!route->contains(myEdge)) {
393  WRITE_WARNING("Route '" + route->getID() + "' in calibrator '" + getID() + "' does not contain edge '" + myEdge->getID() + "'.");
394  break;
395  }
396  const int routeIndex = (int)std::distance(route->begin(),
397  std::find(route->begin(), route->end(), myEdge));
399  assert(route != 0 && vtype != 0);
400  // build the vehicle
401  SUMOVehicleParameter* newPars = new SUMOVehicleParameter(*pars);
402  newPars->id = getNewVehicleID();
403  newPars->depart = currentTime;
404  newPars->routeid = route->getID();
405  newPars->departLaneProcedure = DepartLaneDefinition::FIRST_ALLOWED; // ensure successful vehicle creation
406  MSVehicle* vehicle;
407  try {
408  vehicle = dynamic_cast<MSVehicle*>(MSNet::getInstance()->getVehicleControl().buildVehicle(
409  newPars, route, vtype, true, false));
410  } catch (const ProcessError& e) {
412  WRITE_WARNING(e.what());
413  vehicle = nullptr;
414  break;
415  } else {
416  throw e;
417  }
418  }
419 #ifdef MSCalibrator_DEBUG
420  if (DEBUGCOND) {
421  std::cout << " resetting route pos: " << routeIndex << "\n";
422  }
423 #endif
424  vehicle->resetRoutePosition(routeIndex, pars->departLaneProcedure);
425  if (myEdge->insertVehicle(*vehicle, currentTime)) {
426  if (!MSNet::getInstance()->getVehicleControl().addVehicle(vehicle->getID(), vehicle)) {
427  throw ProcessError("Emission of vehicle '" + vehicle->getID() + "' in calibrator '" + getID() + "'failed!");
428  }
429  myInserted++;
430  adaptedNum++;
431 #ifdef MSCalibrator_DEBUG
432  if (DEBUGCOND) {
433  std::cout << "I ";
434  }
435 #endif
436  } else {
437  // could not insert vehicle
438 #ifdef MSCalibrator_DEBUG
439  if (DEBUGCOND) {
440  std::cout << "F ";
441  }
442 #endif
444  break;
445  }
446  }
447  }
448  if (myCurrentStateInterval->end <= currentTime + myFrequency) {
449  intervalEnd();
450  }
451  return myFrequency;
452 }
453 
454 void
457  for (std::vector<MSMeanData_Net::MSLaneMeanDataValues*>::iterator it = myLaneMeanData.begin(); it != myLaneMeanData.end(); ++it) {
458  (*it)->reset();
459  }
460 }
461 
462 
463 bool
464 MSCalibrator::invalidJam(int laneIndex) const {
465  if (laneIndex < 0) {
466  const int numLanes = (int)myEdge->getLanes().size();
467  for (int i = 0; i < numLanes; ++i) {
468  if (invalidJam(i)) {
469  return true;
470  }
471  }
472  return false;
473  }
474  assert(laneIndex < (int)myEdge->getLanes().size());
475  const MSLane* const lane = myEdge->getLanes()[laneIndex];
476  if (lane->getVehicleNumber() < 4) {
477  // cannot reliably detect invalid jams
478  return false;
479  }
480  // maxSpeed reflects the calibration target
481  const bool toSlow = lane->getMeanSpeed() < myInvalidJamThreshold * myEdge->getSpeedLimit();
482  return toSlow && remainingVehicleCapacity(laneIndex) < 1;
483 }
484 
485 
486 int
488  if (laneIndex < 0) {
489  const int numLanes = (int)myEdge->getLanes().size();
490  int result = 0;
491  for (int i = 0; i < numLanes; ++i) {
492  result = MAX2(result, remainingVehicleCapacity(i));
493  }
494  return result;
495  }
496  assert(laneIndex < (int)myEdge->getLanes().size());
497  MSLane* lane = myEdge->getLanes()[laneIndex];
498  MSVehicle* last = lane->getLastFullVehicle();
499  const SUMOVehicleParameter* pars = myCurrentStateInterval->vehicleParameter;
501  const double spacePerVehicle = vtype->getLengthWithGap() + myEdge->getSpeedLimit() * vtype->getCarFollowModel().getHeadwayTime();
502  int overallSpaceLeft = (int)ceil(lane->getLength() / spacePerVehicle) - lane->getVehicleNumber();
503  if (last != nullptr) {
504  int entrySpaceLeft = (int)(last->getPositionOnLane() / spacePerVehicle);
505  return MAX2(overallSpaceLeft, entrySpaceLeft);
506  } else {
507  return overallSpaceLeft;
508  }
509 }
510 
511 
512 void
514  for (std::vector<MSMoveReminder*>::iterator it = LeftoverReminders.begin(); it != LeftoverReminders.end(); ++it) {
515  delete *it;
516  }
517  LeftoverReminders.clear();
518  for (std::vector<SUMOVehicleParameter*>::iterator it = LeftoverVehicleParameters.begin();
519  it != LeftoverVehicleParameters.end(); ++it) {
520  delete *it;
521  }
523  myInstances.clear(); // deletion is performed in MSTrigger::cleanup()
524 }
525 
526 
527 void
530  for (std::vector<MSMeanData_Net::MSLaneMeanDataValues*>::iterator it = myLaneMeanData.begin();
531  it != myLaneMeanData.end(); ++it) {
532  (*it)->addTo(myEdgeMeanData);
533  }
534 }
535 
536 
537 bool
539  if (myParent == nullptr) {
540  return false;
541  }
542  if (!myParent->vehicleApplies(veh)) {
543  return false;
544  }
545  if (myParent->isActive()) {
547  const bool calibrateFlow = myParent->myCurrentStateInterval->q >= 0;
548  const int totalWishedNum = myParent->totalWished();
549  int adaptedNum = myParent->passed() + myParent->myClearedInJam;
550  if (calibrateFlow && adaptedNum > totalWishedNum) {
551 #ifdef MSCalibrator_DEBUG
552  if (DEBUGCOND2(myParent->getID())) std::cout << time2string(MSNet::getInstance()->getCurrentTimeStep()) << " " << myParent->getID()
553  << " vaporizing " << vehicle->getID() << " to reduce flow\n";
554 #endif
555  if (myParent->scheduleRemoval(&veh)) {
556  myParent->myRemoved++;
557  }
558  } else if (myParent->myHaveInvalidJam) {
559 #ifdef MSCalibrator_DEBUG
560  if (DEBUGCOND2(myParent->getID())) std::cout << time2string(MSNet::getInstance()->getCurrentTimeStep()) << " " << myParent->getID()
561  << " vaporizing " << vehicle->getID() << " to clear jam\n";
562 #endif
564  WRITE_WARNING("Clearing jam at calibrator '" + myParent->getID() + "' at time "
565  + time2string(MSNet::getInstance()->getCurrentTimeStep()));
567  }
568  if (myParent->scheduleRemoval(&veh)) {
570  }
571  }
572  const std::string typeID = myParent->myCurrentStateInterval->vehicleParameter->vtypeid;
573  if (!calibrateFlow && typeID != DEFAULT_VTYPE_ID) {
574  // calibrate type
575  const std::string origType = veh.getParameter().vtypeid; // could by id of vTypeDistribution
577  const RandomDistributor<MSVehicleType*>* oldDist = vc.getVTypeDistribution(origType);
578  const RandomDistributor<MSVehicleType*>* newDist = vc.getVTypeDistribution(typeID);
579  bool matchDistribution = false;
580  if (oldDist != nullptr && newDist != nullptr && oldDist->getVals().size() == newDist->getVals().size()) {
581  auto it = std::find(oldDist->getVals().begin(), oldDist->getVals().end(), &veh.getVehicleType());
582  if (it != oldDist->getVals().end()) {
583  matchDistribution = true;
584  const int distIndex = (int)(it - oldDist->getVals().begin());
585  veh.replaceVehicleType(newDist->getVals()[distIndex]);
586  }
587  }
588  if (!matchDistribution) {
589  MSVehicleType* vehicleType = MSNet::getInstance()->getVehicleControl().getVType(typeID);
590  if (vehicleType == nullptr) {
591  throw ProcessError("Unknown vehicle type '" + typeID + "' in calibrator '" + myParent->getID() + "'");
592  }
593  veh.replaceVehicleType(vehicleType);
594  }
595  }
596  }
597  return true;
598 }
599 
600 
601 void
603  updateMeanData();
604  const int p = passed();
605  // meandata will be off if vehicles are removed on the next edge instead of this one
607  //assert(discrepancy >= 0); may go negative for lane calibrator when vehicles change lane before removal
608  const std::string ds = (discrepancy > 0 ? "\" vaporizedOnNextEdge=\"" + toString(discrepancy) : "");
609  const double durationSeconds = STEPS2TIME(stopTime - startTime);
611  dev.writeAttr(SUMO_ATTR_BEGIN, time2string(startTime));
612  dev.writeAttr(SUMO_ATTR_END, time2string(stopTime));
613  dev.writeAttr(SUMO_ATTR_ID, getID());
614  dev.writeAttr("nVehContrib", p);
615  dev.writeAttr("removed", myRemoved);
616  dev.writeAttr("inserted", myInserted);
617  dev.writeAttr("cleared", myClearedInJam);
618  dev.writeAttr("flow", p * 3600.0 / durationSeconds);
619  dev.writeAttr("aspiredFlow", myCurrentStateInterval->q);
622  dev.writeAttr("aspiredSpeed", myCurrentStateInterval->v);
623  if (discrepancy > 0) {
624  dev.writeAttr("vaporizedOnNextEdge", discrepancy);
625  }
626  dev.closeTag();
627 }
628 
629 void
631  dev.writeXMLHeader("calibratorstats", "calibratorstats_file.xsd");
632 }
633 
634 std::string
636  // avoid name clash for subsecond interval spacing
637  const double beginS = STEPS2TIME(myCurrentStateInterval->begin);
638  const int precision = beginS == int(beginS) ? 0 : 2;
639  return getID() + "." + toString(beginS, precision) + "." + toString(myInserted);
640 }
641 
642 void
643 MSCalibrator::setFlow(SUMOTime begin, SUMOTime end, double vehsPerHour, double speed, SUMOVehicleParameter vehicleParameter) {
644  auto it = myCurrentStateInterval;
645  while (it != myIntervals.end()) {
646  if (it->begin > begin) {
647  throw ProcessError("Cannot set flow for calibrator '" + getID() + "' with begin time " + time2string(begin) + " in the past.");
648  } else if (it->begin == begin && it->end == end) {
649  // update current interval
650  AspiredState& state = const_cast<AspiredState&>(*it);
651  state.q = vehsPerHour;
652  state.v = speed;
653  state.vehicleParameter->vtypeid = vehicleParameter.vtypeid;
654  state.vehicleParameter->routeid = vehicleParameter.routeid;
655  state.vehicleParameter->departLane = vehicleParameter.departLane;
656  state.vehicleParameter->departLaneProcedure = vehicleParameter.departLaneProcedure;
657  state.vehicleParameter->departSpeed = vehicleParameter.departSpeed;
659  return;
660  } else if (begin < it->end) {
661  throw ProcessError("Cannot set flow for calibrator '" + getID() + "' with overlapping interval.");
662  } else if (begin >= end) {
663  throw ProcessError("Cannot set flow for calibrator '" + getID() + "' with negative interval.");
664  }
665  it++;
666  }
667  // add interval at the end of the known intervals
668  const int intervalIndex = (int)(myCurrentStateInterval - myIntervals.begin());
669  AspiredState state;
670  state.begin = begin;
671  state.end = end;
672  state.q = vehsPerHour;
673  state.v = speed;
674  state.vehicleParameter = new SUMOVehicleParameter(vehicleParameter);
675  myIntervals.push_back(state);
676  // fix iterator
677  myCurrentStateInterval = myIntervals.begin() + intervalIndex;
678 }
679 
680 /****************************************************************************/
#define DEBUGCOND
#define DEBUGCOND2(id)
#define WRITE_ERROR(msg)
Definition: MsgHandler.h:284
#define WRITE_WARNING(msg)
Definition: MsgHandler.h:276
SUMOTime DELTA_T
Definition: SUMOTime.cpp:37
std::string time2string(SUMOTime t)
convert SUMOTime to string
Definition: SUMOTime.cpp:68
#define STEPS2TIME(x)
Definition: SUMOTime.h:53
#define SUMOTime_MAX
Definition: SUMOTime.h:32
#define TIME2STEPS(x)
Definition: SUMOTime.h:55
long long int SUMOTime
Definition: SUMOTime.h:31
const std::string DEFAULT_VTYPE_ID
@ GIVEN
The lane is given.
@ ALLOWED_FREE
The least occupied lane from lanes which allow the continuation.
@ DEFAULT
No information given; use default.
@ FIRST_ALLOWED
The rightmost lane the vehicle may use.
@ MAX
The maximum safe speed is used.
@ DEFAULT
No information given; use default.
@ SUMO_TAG_INTERVAL
an aggreagated-output interval
@ SUMO_TAG_FLOW
a flow definitio nusing a from-to edges instead of a route (used by router)
@ SUMO_TAG_CALIBRATOR
A calibrator placed over edge.
@ SUMO_ATTR_VEHSPERHOUR
@ SUMO_ATTR_SPEED
@ SUMO_ATTR_BEGIN
weights: time range begin
@ SUMO_ATTR_END
weights: time range end
@ SUMO_ATTR_ID
T MAX2(T a, T b)
Definition: StdDefs.h:79
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition: ToString.h:44
void resetRoutePosition(int index, DepartLaneDefinition departLaneProcedure)
reset index of edge within route
virtual double getHeadwayTime() const
Get the driver's desired headway [s].
Definition: MSCFModel.h:257
virtual bool notifyEnter(SUMOTrafficObject &veh, MSMoveReminder::Notification reason, const MSLane *enteredLane=0)
Checks whether the reminder is activated by a vehicle entering the lane.
static std::map< std::string, MSCalibrator * > myInstances
Definition: MSCalibrator.h:342
OutputDevice * myOutput
The device for xml statistics.
Definition: MSCalibrator.h:308
double myInvalidJamThreshold
relative speed threshold for detecting and clearing invalid jam
Definition: MSCalibrator.h:333
double currentSpeed() const
measured speed in the current interval
const MSEdge *const myEdge
the edge on which this calibrator lies
Definition: MSCalibrator.h:280
MSMeanData_Net myMeanDataParent
dummy parent to retrieve vType filter
Definition: MSCalibrator.h:288
static void cleanup()
cleanup remaining data structures
bool isActive() const
Definition: MSCalibrator.h:214
static std::vector< SUMOVehicleParameter * > LeftoverVehicleParameters
Definition: MSCalibrator.h:341
bool mySpeedIsDefault
The information whether the speed adaption has been reset.
Definition: MSCalibrator.h:319
virtual void updateMeanData()
aggregate lane values
int myRemoved
The number of vehicles that were removed in the current interval.
Definition: MSCalibrator.h:313
virtual int passed() const
Definition: MSCalibrator.h:125
const MSRouteProbe *const myProbe
the route probe to retrieve routes from
Definition: MSCalibrator.h:286
bool myAmActive
whether the calibrator was active when last checking
Definition: MSCalibrator.h:330
std::set< std::string > myToRemove
set of vehicle ids to remove
Definition: MSCalibrator.h:305
void setFlow(SUMOTime begin, SUMOTime end, double vehsPerHour, double speed, SUMOVehicleParameter vehicleParameter)
bool myHaveInvalidJam
whether the calibrator has registered an invalid jam in the last execution step
Definition: MSCalibrator.h:336
std::vector< MSMeanData_Net::MSLaneMeanDataValues * > myLaneMeanData
data collector for the calibrator
Definition: MSCalibrator.h:290
std::vector< AspiredState >::const_iterator myCurrentStateInterval
Iterator pointing to the current interval.
Definition: MSCalibrator.h:297
double currentFlow() const
flow in the current interval in veh/h
bool removePending()
remove any vehicles which are scheduled for removal. return true if removals took place
virtual void myStartElement(int element, const SUMOSAXAttributes &attrs)
Called on the opening of a tag;.
const std::string & getID() const
Definition: MSCalibrator.h:89
int myInserted
The number of vehicles that were inserted in the current interval.
Definition: MSCalibrator.h:315
bool myHaveWarnedAboutClearingJam
The default (maximum) speed on the segment.
Definition: MSCalibrator.h:327
std::vector< AspiredState > myIntervals
List of adaptation intervals.
Definition: MSCalibrator.h:295
virtual void myEndElement(int element)
Called on the closing of a tag;.
int totalWished() const
number of vehicles expected to pass this interval
std::vector< VehicleRemover * > myVehicleRemovers
Definition: MSCalibrator.h:299
void writeXMLOutput(OutputDevice &dev, SUMOTime startTime, SUMOTime stopTime)
Write the generated output to the given device.
std::string getNewVehicleID()
determine id of new vehicle from calibrator state
MSMeanData_Net::MSLaneMeanDataValues myEdgeMeanData
accumlated data for the whole edge
Definition: MSCalibrator.h:292
static std::vector< MSMoveReminder * > LeftoverReminders
Definition: MSCalibrator.h:340
friend class VehicleRemover
Definition: MSCalibrator.h:210
bool invalidJam(int laneIndex) const
int myClearedInJam
The number of vehicles that were removed when clearin a jam.
Definition: MSCalibrator.h:317
void writeXMLDetectorProlog(OutputDevice &dev) const
Open the XML-output.
virtual ~MSCalibrator()
double myDefaultSpeed
The default (maximum) speed on the segment.
Definition: MSCalibrator.h:325
virtual SUMOTime execute(SUMOTime currentTime)
MSLane *const myLane
the lane on which this calibrator lies (0 if the whole edge is covered at once)
Definition: MSCalibrator.h:282
bool scheduleRemoval(SUMOTrafficObject *veh)
try to schedule the given vehicle for removal. return true if it isn't already scheduled
Definition: MSCalibrator.h:266
bool myDidInit
The information whether init was called.
Definition: MSCalibrator.h:323
void intervalEnd()
AspiredState getCurrentStateInterval() const
bool isCurrentStateActive(SUMOTime time)
SUMOTime myFrequency
The frequeny with which to check for calibration.
Definition: MSCalibrator.h:311
MSCalibrator(const std::string &id, const MSEdge *const edge, MSLane *lane, const double pos, const std::string &aXMLFilename, const std::string &outputFilename, const SUMOTime freq, const double length, const MSRouteProbe *probe, const double invalidJamThreshold, const std::string &vTypes, bool addLaneMeanData=true)
virtual void reset()
reset collected vehicle data
int remainingVehicleCapacity(int laneIndex) const
bool myDidSpeedAdaption
The information whether speed was adapted in the current interval.
Definition: MSCalibrator.h:321
Base of value-generating classes (detectors)
bool vehicleApplies(const SUMOTrafficObject &veh) const
Checks whether the detector measures vehicles of the given type.
A road/street connecting two junctions.
Definition: MSEdge.h:77
const std::vector< MSLane * > & getLanes() const
Returns this edge's lanes.
Definition: MSEdge.h:166
double getSpeedLimit() const
Returns the speed limit of the edge @caution The speed limit of the first lane is retured; should pro...
Definition: MSEdge.cpp:919
bool insertVehicle(SUMOVehicle &v, SUMOTime time, const bool checkOnly=false, const bool forceCheck=false) const
Tries to insert the given vehicle into the network.
Definition: MSEdge.cpp:570
void setMaxSpeed(double val) const
Sets a new maximum speed for all lanes (used by TraCI and MSCalibrator)
Definition: MSEdge.cpp:938
virtual void addEvent(Command *operation, SUMOTime execTimeStep=-1)
Adds an Event.
static bool gUseMesoSim
Definition: MSGlobals.h:88
static bool gCheckRoutes
Definition: MSGlobals.h:76
Representation of a lane in the micro simulation.
Definition: MSLane.h:82
virtual MSVehicle * removeVehicle(MSVehicle *remVehicle, MSMoveReminder::Notification notification, bool notify=true)
Definition: MSLane.cpp:2193
int getVehicleNumber() const
Returns the number of vehicles on this lane (for which this lane is responsible)
Definition: MSLane.h:399
MSVehicle * getLastFullVehicle() const
returns the last vehicle for which this lane is responsible or 0
Definition: MSLane.cpp:2042
double getLength() const
Returns the lane's length.
Definition: MSLane.h:539
int getIndex() const
Returns the lane's index.
Definition: MSLane.h:562
void setMaxSpeed(double val)
Sets a new maximum speed for the lane (used by TraCI and MSCalibrator)
Definition: MSLane.cpp:2168
double getMeanSpeed() const
Returns the mean speed on this lane.
Definition: MSLane.cpp:2736
double getTravelledDistance() const
Returns the total travelled distance.
Definition: MSMeanData.h:156
virtual double getSamples() const
Returns the number of collected sample seconds.
Definition: MSMeanData.cpp:277
Data structure for mean (aggregated) edge/lane values.
int nVehVaporized
The number of vehicles that left this lane within the sample interval.
int nVehLeft
The number of vehicles that left this lane within the sample interval.
int nVehArrived
The number of vehicles that finished on the lane.
double waitSeconds
The number of vehicle probes with small speed.
int nVehEntered
The number of vehicles that entered this lane within the sample interval.
void reset(bool afterWrite=false)
Resets values so they may be used for the next interval.
void setDescription(const std::string &description)
Notification
Definition of a vehicle state.
@ NOTIFICATION_VAPORIZED_CALIBRATOR
The vehicle got removed by a calibrator.
static MSNet * getInstance()
Returns the pointer to the unique instance of MSNet (singleton).
Definition: MSNet.cpp:171
MSVehicleControl & getVehicleControl()
Returns the vehicle control.
Definition: MSNet.h:371
MSEventControl * getEndOfTimestepEvents()
Returns the event control for events executed at the end of a time step.
Definition: MSNet.h:474
Parser and container for routes during their loading.
virtual void myStartElement(int element, const SUMOSAXAttributes &attrs)
Called on the opening of a tag;.
MSRouteIterator end() const
Returns the end of the list of edges to pass.
Definition: MSRoute.cpp:75
static bool dictionary(const std::string &id, const MSRoute *route)
Adds a route to the dictionary.
Definition: MSRoute.cpp:113
bool contains(const MSEdge *const edge) const
Definition: MSRoute.h:99
MSRouteIterator begin() const
Returns the begin of the list of edges to pass.
Definition: MSRoute.cpp:69
Writes routes of vehicles passing a certain edge.
Definition: MSRouteProbe.h:58
const MSRoute * sampleRoute(bool last=true) const
An abstract device that changes the state of the micro simulation.
Definition: MSTrigger.h:38
The class responsible for building and deletion of vehicles.
virtual void deleteVehicle(SUMOVehicle *v, bool discard=false)
Deletes the vehicle.
SUMOVehicle * getVehicle(const std::string &id) const
Returns the vehicle with the given id.
MSVehicleType * getVType(const std::string &id=DEFAULT_VTYPE_ID, std::mt19937 *rng=nullptr)
Returns the named vehicle type or a sample from the named distribution.
const RandomDistributor< MSVehicleType * > * getVTypeDistribution(const std::string &typeDistID) const
return the vehicle type distribution with the given id
void scheduleVehicleRemoval(SUMOVehicle *veh, bool checkDuplicate=false)
Removes a vehicle after it has ended.
virtual SUMOVehicle * buildVehicle(SUMOVehicleParameter *defs, const MSRoute *route, MSVehicleType *type, const bool ignoreStopErrors, const bool fromRouteFile=true)
Builds a vehicle, increases the number of built vehicles.
Representation of a vehicle in the micro simulation.
Definition: MSVehicle.h:77
MSLane * getMutableLane() const
Returns the lane the vehicle is on Non const version indicates that something volatile is going on.
Definition: MSVehicle.h:558
void onRemovalFromNet(const MSMoveReminder::Notification reason)
Called when the vehicle is removed from the network.
Definition: MSVehicle.cpp:967
double getPositionOnLane() const
Get the vehicle's position along the lane.
Definition: MSVehicle.h:374
The car-following model and parameter.
Definition: MSVehicleType.h:62
double getLengthWithGap() const
Get vehicle's length including the minimum gap [m].
const MSCFModel & getCarFollowModel() const
Returns the vehicle type's car following model definition (const version)
const std::string & getID() const
Returns the id.
Definition: Named.h:73
Static storage of an output device and its base (abstract) implementation.
Definition: OutputDevice.h:60
bool writeXMLHeader(const std::string &rootElement, const std::string &schemaFile, std::map< SumoXMLAttr, std::string > attrs=std::map< SumoXMLAttr, std::string >())
Writes an XML header with optional configuration.
OutputDevice & openTag(const std::string &xmlElement)
Opens an XML tag.
OutputDevice & writeAttr(const SumoXMLAttr attr, const T &val)
writes a named attribute
Definition: OutputDevice.h:239
bool closeTag(const std::string &comment="")
Closes the most recently opened tag and optionally adds a comment.
static OutputDevice & getDevice(const std::string &name)
Returns the described OutputDevice.
const std::vector< T > & getVals() const
Returns the members of the distribution.
virtual void myEndElement(int element)
Called when a closing tag occurs.
Encapsulated SAX-Attributes.
T getOpt(int attr, const char *objectid, bool &ok, T defaultValue, bool report=true) const
Tries to read given attribute assuming it is an int.
SUMOTime getOptSUMOTimeReporting(int attr, const char *objectid, bool &ok, SUMOTime defaultValue, bool report=true) const
Tries to read given attribute assuming it is a SUMOTime.
SUMOTime getSUMOTimeReporting(int attr, const char *objectid, bool &ok, bool report=true) const
Tries to read given attribute assuming it is a SUMOTime.
Representation of a vehicle, person, or container.
virtual const MSVehicleType & getVehicleType() const =0
Returns the object's "vehicle" type.
virtual const SUMOVehicleParameter & getParameter() const =0
Returns the vehicle's parameter (including departure definition)
virtual void replaceVehicleType(MSVehicleType *type)=0
Replaces the current vehicle type by the one given.
Structure representing possible vehicle parameter.
int departLane
(optional) The lane the vehicle shall depart from (index in edge)
double departSpeed
(optional) The initial speed of the vehicle
std::string vtypeid
The vehicle's type id.
DepartLaneDefinition departLaneProcedure
Information how the vehicle shall choose the lane to depart from.
DepartSpeedDefinition departSpeedProcedure
Information how the vehicle's initial speed shall be chosen.
std::string routeid
The vehicle's route id.
std::string id
The vehicle's id.
static SUMOVehicleParameter * parseVehicleAttributes(int element, const SUMOSAXAttributes &attrs, const bool hardFail, const bool optionalID=false, const bool skipDepart=false)
Parses a vehicle's attributes.
static bool runParser(GenericSAXHandler &handler, const std::string &file, const bool isNet=false, const bool isRoute=false)
Runs the given handler on the given file; returns if everything's ok.
Definition: XMLSubSys.cpp:148
SUMOVehicleParameter * vehicleParameter
Definition: MSCalibrator.h:108