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.dev/sumo
3 // Copyright (C) 2005-2024 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::myLeftoverReminders;
55 std::vector<SUMOVehicleParameter*> MSCalibrator::myLeftoverVehicleParameters;
56 std::map<std::string, MSCalibrator*> MSCalibrator::myInstances;
57 
58 // ===========================================================================
59 // CalibratorCommand method definitions
60 // ===========================================================================
61 
64  UNUSED_PARAMETER(currentTime);
65  UNUSED_PARAMETER(execTime);
66  UNUSED_PARAMETER(newTime);
68  return 0;
69 }
70 
71 
72 // ===========================================================================
73 // method definitions
74 // ===========================================================================
75 MSCalibrator::MSCalibrator(const std::string& id,
76  const MSEdge* const edge,
77  MSLane* lane,
78  const double pos,
79  const std::string& aXMLFilename,
80  const std::string& outputFilename,
81  const SUMOTime freq, const double length,
82  const MSRouteProbe* probe,
83  const double invalidJamThreshold,
84  const std::string& vTypes,
85  bool addLaneMeanData) :
86  MSRouteHandler(aXMLFilename, true),
87  MSDetectorFileOutput(id, vTypes, "", (int)PersonMode::NONE), // detecting persons not yet supported
88  myEdge(const_cast<MSEdge*>(edge)),
89  myLane(lane),
90  myPos(pos), myProbe(probe),
91  myMeanDataParent(id + "_dummyMeanData", 0, 0, false, false, false, false, false, false, 1, 0, 0, vTypes, "",
92  std::vector<MSEdge*>(), false),
93  myEdgeMeanData(nullptr, length, false, &myMeanDataParent),
95  myOutput(nullptr), myFrequency(freq), myRemoved(0),
96  myInserted(0),
97  myClearedInJam(0),
98  mySpeedIsDefault(true), myDidSpeedAdaption(false), myDidInit(false),
99  myDefaultSpeed(myLane == nullptr ? myEdge->getSpeedLimit() : myLane->getSpeedLimit()),
101  myAmActive(false),
102  myInvalidJamThreshold(invalidJamThreshold),
103  myHaveInvalidJam(false) {
104  myInstances[id] = this;
105  if (outputFilename != "") {
106  myOutput = &OutputDevice::getDevice(outputFilename);
108  }
109  if (aXMLFilename != "") {
110  XMLSubSys::runParser(*this, aXMLFilename);
111  if (!myDidInit) {
112  init();
113  }
114  }
115  if (addLaneMeanData) {
116  // disabled for METriggeredCalibrator
117  for (MSLane* const eLane : myEdge->getLanes()) {
118  if (myLane == nullptr || myLane == eLane) {
119  //std::cout << " cali=" << getID() << " myLane=" << Named::getIDSecure(myLane) << " checkLane=" << i << "\n";
120  MSMeanData_Net::MSLaneMeanDataValues* laneData = new MSMeanData_Net::MSLaneMeanDataValues(eLane, eLane->getLength(), true, &myMeanDataParent);
121  laneData->setDescription("meandata_calibrator_" + eLane->getID());
122  myLeftoverReminders.push_back(laneData);
123  myLaneMeanData.push_back(laneData);
124  VehicleRemover* remover = new VehicleRemover(eLane, this);
125  myLeftoverReminders.push_back(remover);
126  myVehicleRemovers.push_back(remover);
127  }
128  }
129  }
130 }
131 
132 
133 void
135  if (myIntervals.size() > 0) {
136  if (myIntervals.back().end == -1) {
137  myIntervals.back().end = SUMOTime_MAX;
138  }
139  // calibration should happen after regular insertions have taken place
141  } else {
142  WRITE_WARNINGF(TL("No flow intervals in calibrator '%'."), getID());
143  }
144  myDidInit = true;
145 }
146 
147 
149  if (myCurrentStateInterval != myIntervals.end()) {
150  intervalEnd();
151  }
152  for (VehicleRemover* const remover : myVehicleRemovers) {
153  remover->disable();
154  }
155  myInstances.erase(getID());
156 }
157 
160  if (myCurrentStateInterval == myIntervals.end()) {
161  throw ProcessError(TLF("Calibrator '%' has no active or upcoming interval", getID()));
162  }
163  return *myCurrentStateInterval;
164 }
165 
166 void
168  const SUMOSAXAttributes& attrs) {
169  if (element == SUMO_TAG_FLOW) {
170  AspiredState state;
171  SUMOTime lastEnd = -1;
172  SUMOTime lastBegin = -1;
173  if (myIntervals.size() > 0) {
174  lastEnd = myIntervals.back().end;
175  lastBegin = myIntervals.back().begin;
176  if (lastEnd == -1) {
177  lastEnd = myIntervals.back().begin;
178  }
179  }
180  try {
181  bool ok = true;
182  state.q = attrs.getOpt<double>(SUMO_ATTR_VEHSPERHOUR, nullptr, ok, -1.);
183  state.v = attrs.getOpt<double>(SUMO_ATTR_SPEED, nullptr, ok, -1.);
184  state.begin = attrs.getSUMOTimeReporting(SUMO_ATTR_BEGIN, getID().c_str(), ok);
185  if (state.begin < lastEnd) {
186  WRITE_ERRORF("Overlapping or unsorted intervals in calibrator '%' (end=%, begin2=%).", getID(), time2string(lastEnd), time2string(state.begin));
187  } else if (state.begin <= lastBegin) {
188  WRITE_ERRORF("Overlapping or unsorted intervals in calibrator '%' (begin=%, begin2=%).", getID(), time2string(lastBegin), time2string(state.begin));
189  }
190  state.end = attrs.getOptSUMOTimeReporting(SUMO_ATTR_END, getID().c_str(), ok, -1);
191  state.vehicleParameter = SUMOVehicleParserHelper::parseVehicleAttributes(element, attrs, true, true, true);
194  // vehicles should be inserted with max speed unless stated otherwise
197  }
198  // vehicles should be inserted on any lane unless stated otherwise
200  if (myLane == nullptr) {
202  } else {
205  }
206  } else if (myLane != nullptr && (
208  || state.vehicleParameter->departLane != myLane->getIndex())) {
209  WRITE_WARNINGF(TL("Insertion lane may differ from calibrator lane for calibrator '%'."), getID());
210  }
211  if (state.vehicleParameter->vtypeid != DEFAULT_VTYPE_ID &&
213  WRITE_ERRORF(TL("Unknown vehicle type '%' in calibrator '%'."), state.vehicleParameter->vtypeid, getID());
214  }
215  } catch (EmptyData&) {
216  WRITE_ERRORF(TL("Mandatory attribute missing in definition of calibrator '%'."), getID());
217  } catch (NumberFormatException&) {
218  WRITE_ERRORF(TL("Non-numeric value for numeric attribute in definition of calibrator '%'."), getID());
219  }
220  if (state.q < 0 && state.v < 0 && state.vehicleParameter->vtypeid == DEFAULT_VTYPE_ID) {
221  WRITE_ERRORF(TL("Either 'vehsPerHour', 'speed' or 'type' has to be set in flow definition of calibrator '%'."), getID());
222  }
223  if (MSGlobals::gUseMesoSim && state.q < 0 && state.vehicleParameter->vtypeid != DEFAULT_VTYPE_ID) {
224  WRITE_ERRORF(TL("Type calibration is not supported in meso for calibrator '%'."), getID());
225  }
226  if (myIntervals.size() > 0 && myIntervals.back().end == -1) {
227  myIntervals.back().end = state.begin;
228  }
229  myIntervals.push_back(state);
231  } else {
232  MSRouteHandler::myStartElement(element, attrs);
233  }
234 }
235 
236 
237 void
239  if (element == SUMO_TAG_CALIBRATOR) {
240  if (!myDidInit) {
241  init();
242  }
243  // ensure correct state of SUMORouteHandler::myElementStack
244  callParentEnd(element);
245  } else if (element != SUMO_TAG_FLOW) {
247  }
248 }
249 
250 
251 void
253  if (myOutput != nullptr) {
255  }
256  myDidSpeedAdaption = false;
257  myInserted = 0;
258  myRemoved = 0;
259  myClearedInJam = 0;
261  reset();
262 }
263 
264 
265 bool
267  while (myCurrentStateInterval != myIntervals.end() && myCurrentStateInterval->end <= time) {
268  // XXX what about skipped intervals?
270  }
271  return myCurrentStateInterval != myIntervals.end() &&
272  myCurrentStateInterval->begin <= time && myCurrentStateInterval->end > time;
273 }
274 
275 
276 int
278  if (myCurrentStateInterval != myIntervals.end()) {
279  const double totalHourFraction = STEPS2TIME(myCurrentStateInterval->end - myCurrentStateInterval->begin) / (double) 3600.;
280  return (int)std::floor(myCurrentStateInterval->q * totalHourFraction + 0.5); // round to closest int
281  } else {
282  return -1;
283  }
284 }
285 
286 
287 double
289  const double totalHourFraction = STEPS2TIME(MSNet::getInstance()->getCurrentTimeStep() - myCurrentStateInterval->begin) / (double) 3600.;
290  return passed() / totalHourFraction;
291 }
292 
293 
294 double
296  if (myEdgeMeanData.getSamples() > 0) {
298  } else {
299  return -1;
300  }
301 }
302 
303 
304 bool
306  if (myToRemove.size() > 0) {
308  // it is not save to remove the vehicles inside
309  // VehicleRemover::notifyEnter so we do it here
310  for (std::set<std::string>::iterator it = myToRemove.begin(); it != myToRemove.end(); ++it) {
311  MSVehicle* vehicle = dynamic_cast<MSVehicle*>(vc.getVehicle(*it));
312  if (vehicle != nullptr) {
313  MSLane* lane = vehicle->getMutableLane();
316  vc.scheduleVehicleRemoval(vehicle, true);
317  } else {
318  WRITE_WARNINGF(TL("Calibrator '%' could not remove vehicle '%' time=%."), getID(), *it, time2string(MSNet::getInstance()->getCurrentTimeStep()));
319  }
320  }
321  myToRemove.clear();
322  return true;
323  }
324  return false;
325 }
326 
327 
328 SUMOTime
330  const bool calibrateFlow = myCurrentStateInterval->q >= 0;
331  const bool calibrateSpeed = myCurrentStateInterval->v >= 0;
332  // get current simulation values (valid for the last simulation second)
333  myHaveInvalidJam = (calibrateFlow || calibrateSpeed) && invalidJam(myLane == 0 ? -1 : myLane->getIndex());
334  // XXX could we miss vehicle movements if this is called less often than every DELTA_T (default) ?
335  updateMeanData();
336  const bool hadRemovals = removePending();
337  // check whether an adaptation value exists
338  if (isCurrentStateActive(currentTime)) {
339  myAmActive = true;
340  // all happens in isCurrentStateActive()
341  } else {
342  myAmActive = false;
343  reset();
344  if (!mySpeedIsDefault) {
345  // reset speed to default
346  if (myLane == nullptr) {
348  } else {
350  }
351  mySpeedIsDefault = true;
352  }
353  if (myCurrentStateInterval == myIntervals.end()) {
354  // keep calibrator alive for gui but do not call again
355  return TIME2STEPS(86400);
356  }
357  return myFrequency;
358  }
359  // we are active
360  if (!myDidSpeedAdaption && calibrateSpeed) {
361  if (myLane == nullptr) {
363  } else {
365  }
366  mySpeedIsDefault = false;
367  myDidSpeedAdaption = true;
368  }
369 
370  const int totalWishedNum = totalWished();
371  int adaptedNum = passed() + myClearedInJam;
372 #ifdef MSCalibrator_DEBUG
373  if (DEBUGCOND) {
374  std::cout << time2string(currentTime) << " " << getID()
375  << " q=" << myCurrentStateInterval->q
376  << " totalWished=" << totalWishedNum
377  << " adapted=" << adaptedNum
378  << " jam=" << myHaveInvalidJam
379  << " entered=" << myEdgeMeanData.nVehEntered
380  << " departed=" << myEdgeMeanData.nVehDeparted
381  << " arrived=" << myEdgeMeanData.nVehArrived
382  << " left=" << myEdgeMeanData.nVehLeft
383  << " waitSecs=" << myEdgeMeanData.waitSeconds
384  << " vaporized=" << myEdgeMeanData.nVehVaporized
385  << "\n";
386  }
387 #endif
388  if (calibrateFlow && adaptedNum < totalWishedNum && !hadRemovals) {
389  // we need to insert some vehicles
390  const double hourFraction = STEPS2TIME(currentTime - myCurrentStateInterval->begin + DELTA_T) / (double) 3600.;
391  const int wishedNum = (int)std::floor(myCurrentStateInterval->q * hourFraction + 0.5); // round to closest int
392  // only the difference between inflow and aspiredFlow should be added, thus
393  // we should not count vehicles vaporized from a jam here
394  // if we have enough time left we can add missing vehicles later
395  const int relaxedInsertion = (int)std::floor(STEPS2TIME(myCurrentStateInterval->end - currentTime) / 3);
396  const int insertionSlack = MAX2(0, adaptedNum + relaxedInsertion - totalWishedNum);
397  // increase number of vehicles
398 #ifdef MSCalibrator_DEBUG
399  if (DEBUGCOND) {
400  std::cout << " wished:" << wishedNum
401  << " slack:" << insertionSlack
402  << " before:" << adaptedNum
403  << "\n";
404  }
405 #endif
407  while (wishedNum > adaptedNum + insertionSlack) {
408  SUMOVehicleParameter* pars = myCurrentStateInterval->vehicleParameter;
409  ConstMSRoutePtr route = myProbe != nullptr ? myProbe->sampleRoute() : nullptr;
410  if (route == nullptr) {
411  route = MSRoute::dictionary(pars->routeid);
412  }
413  if (route == nullptr) {
414  WRITE_WARNINGF(TL("No valid routes in calibrator '%'."), getID());
415  break;
416  }
417  if (!route->contains(myEdge)) {
418  WRITE_WARNINGF(TL("Route '%' in calibrator '%' does not contain edge '%'."), route->getID(), getID(), myEdge->getID());
419  break;
420  }
421  const int routeIndex = (int)std::distance(route->begin(),
422  std::find(route->begin(), route->end(), myEdge));
423  MSVehicleType* vtype = vc.getVType(pars->vtypeid);
424  assert(route != 0 && vtype != 0);
425  // build the vehicle
426  const std::string newID = getNewVehicleID();
427  if (vc.getVehicle(newID) != nullptr) {
428  ;
429  // duplicate ids could come from loading state
430  myInserted++;
431  break;
432  }
433  SUMOVehicleParameter* newPars = new SUMOVehicleParameter(*pars);
434  newPars->id = newID;
435  newPars->depart = currentTime;
436  newPars->routeid = route->getID();
437  newPars->departLaneProcedure = DepartLaneDefinition::FIRST_ALLOWED; // ensure successful vehicle creation
438  MSVehicle* vehicle;
439  try {
440  vehicle = dynamic_cast<MSVehicle*>(vc.buildVehicle(newPars, route, vtype, true, false));
441  } catch (const ProcessError& e) {
443  WRITE_WARNING(e.what());
444  vehicle = nullptr;
445  break;
446  } else {
447  throw e;
448  }
449  }
450 #ifdef MSCalibrator_DEBUG
451  if (DEBUGCOND) {
452  std::cout << " resetting route pos: " << routeIndex << "\n";
453  }
454 #endif
455  vehicle->resetRoutePosition(routeIndex, pars->departLaneProcedure);
456  bool success = false;
457  try {
458  success = myEdge->insertVehicle(*vehicle, currentTime);
459  } catch (const ProcessError& e) {
461  throw e;
462  }
463  if (success) {
464  if (!MSNet::getInstance()->getVehicleControl().addVehicle(vehicle->getID(), vehicle)) {
465  throw ProcessError("Emission of vehicle '" + vehicle->getID() + "' in calibrator '" + getID() + "'failed!");
466  }
467  myInserted++;
468  adaptedNum++;
469 #ifdef MSCalibrator_DEBUG
470  if (DEBUGCOND) {
471  std::cout << "I ";
472  }
473 #endif
474  } else {
475  // could not insert vehicle
476 #ifdef MSCalibrator_DEBUG
477  if (DEBUGCOND) {
478  std::cout << "F ";
479  }
480 #endif
482  break;
483  }
484  }
485  }
486  if (myCurrentStateInterval->end <= currentTime + myFrequency) {
487  intervalEnd();
488  }
489  return myFrequency;
490 }
491 
492 void
496  val->reset();
497  }
498 }
499 
500 
501 bool
502 MSCalibrator::invalidJam(int laneIndex) const {
503  if (laneIndex < 0) {
504  const int numLanes = (int)myEdge->getLanes().size();
505  for (int i = 0; i < numLanes; ++i) {
506  if (invalidJam(i)) {
507  return true;
508  }
509  }
510  return false;
511  }
512  assert(laneIndex < (int)myEdge->getLanes().size());
513  const MSLane* const lane = myEdge->getLanes()[laneIndex];
514  if (lane->getVehicleNumber() < 4) {
515  // cannot reliably detect invalid jams
516  return false;
517  }
518  // maxSpeed reflects the calibration target
519  const bool toSlow = lane->getMeanSpeed() < myInvalidJamThreshold * myEdge->getSpeedLimit();
520  return toSlow && remainingVehicleCapacity(laneIndex) < 1;
521 }
522 
523 
524 int
526  if (laneIndex < 0) {
527  const int numLanes = (int)myEdge->getLanes().size();
528  int result = 0;
529  for (int i = 0; i < numLanes; ++i) {
530  result = MAX2(result, remainingVehicleCapacity(i));
531  }
532  return result;
533  }
534  assert(laneIndex < (int)myEdge->getLanes().size());
535  MSLane* lane = myEdge->getLanes()[laneIndex];
536  MSVehicle* last = lane->getLastFullVehicle();
537  const SUMOVehicleParameter* pars = myCurrentStateInterval->vehicleParameter;
539  const double spacePerVehicle = vtype->getLengthWithGap() + myEdge->getSpeedLimit() * vtype->getCarFollowModel().getHeadwayTime();
540  int overallSpaceLeft = (int)ceil(lane->getLength() / spacePerVehicle) - lane->getVehicleNumber();
541  if (last != nullptr) {
542  int entrySpaceLeft = (int)(last->getPositionOnLane() / spacePerVehicle);
543  return MAX2(overallSpaceLeft, entrySpaceLeft);
544  } else {
545  return overallSpaceLeft;
546  }
547 }
548 
549 
550 void
552  while (!myInstances.empty()) {
553  delete myInstances.begin()->second;
554  }
555  for (MSMoveReminder* rem : myLeftoverReminders) {
556  delete rem;
557  }
558  myLeftoverReminders.clear();
560  delete par;
561  }
563 }
564 
565 
566 void
569  for (std::vector<MSMeanData_Net::MSLaneMeanDataValues*>::iterator it = myLaneMeanData.begin();
570  it != myLaneMeanData.end(); ++it) {
571  (*it)->addTo(myEdgeMeanData);
572  }
573 }
574 
575 
576 bool
578  if (myParent == nullptr) {
579  return false;
580  }
581  if (!myParent->vehicleApplies(veh)) {
582  return false;
583  }
584  if (myParent->isActive()) {
586  const bool calibrateFlow = myParent->myCurrentStateInterval->q >= 0;
587  const int totalWishedNum = myParent->totalWished();
588  int adaptedNum = myParent->passed() + myParent->myClearedInJam;
589  if (calibrateFlow && adaptedNum > totalWishedNum) {
590 #ifdef MSCalibrator_DEBUG
591  if (DEBUGCOND2(myParent->getID())) std::cout << time2string(MSNet::getInstance()->getCurrentTimeStep()) << " " << myParent->getID()
592  << " vaporizing " << vehicle->getID() << " to reduce flow\n";
593 #endif
594  if (myParent->scheduleRemoval(&veh)) {
595  myParent->myRemoved++;
596  }
597  } else if (myParent->myHaveInvalidJam) {
598 #ifdef MSCalibrator_DEBUG
599  if (DEBUGCOND2(myParent->getID())) std::cout << time2string(MSNet::getInstance()->getCurrentTimeStep()) << " " << myParent->getID()
600  << " vaporizing " << vehicle->getID() << " to clear jam\n";
601 #endif
603  WRITE_WARNINGF(TL("Clearing jam at calibrator '%' at time=%."), myParent->getID(), time2string(SIMSTEP));
605  }
606  if (myParent->scheduleRemoval(&veh)) {
608  }
609  }
610  const std::string typeID = myParent->myCurrentStateInterval->vehicleParameter->vtypeid;
611  if (!calibrateFlow && typeID != DEFAULT_VTYPE_ID) {
612  // calibrate type
613  const std::string origType = veh.getParameter().vtypeid; // could by id of vTypeDistribution
615  const RandomDistributor<MSVehicleType*>* oldDist = vc.getVTypeDistribution(origType);
616  const RandomDistributor<MSVehicleType*>* newDist = vc.getVTypeDistribution(typeID);
617  bool matchDistribution = false;
618  if (oldDist != nullptr && newDist != nullptr && oldDist->getVals().size() == newDist->getVals().size()) {
619  auto it = std::find(oldDist->getVals().begin(), oldDist->getVals().end(), &veh.getVehicleType());
620  if (it != oldDist->getVals().end()) {
621  matchDistribution = true;
622  const int distIndex = (int)(it - oldDist->getVals().begin());
623  veh.replaceVehicleType(newDist->getVals()[distIndex]);
624  }
625  }
626  if (!matchDistribution) {
627  MSVehicleType* vehicleType = MSNet::getInstance()->getVehicleControl().getVType(typeID);
628  if (vehicleType == nullptr) {
629  throw ProcessError("Unknown vehicle type '" + typeID + "' in calibrator '" + myParent->getID() + "'");
630  }
631  veh.replaceVehicleType(vehicleType);
632  }
633  }
634  }
635  return true;
636 }
637 
638 
639 void
641  updateMeanData();
642  const int p = passed();
643  // meandata will be off if vehicles are removed on the next edge instead of this one
645  //assert(discrepancy >= 0); may go negative for lane calibrator when vehicles change lane before removal
646  const std::string ds = (discrepancy > 0 ? "\" vaporizedOnNextEdge=\"" + toString(discrepancy) : "");
647  const double durationSeconds = STEPS2TIME(stopTime - startTime);
649  dev.writeAttr(SUMO_ATTR_BEGIN, time2string(startTime));
650  dev.writeAttr(SUMO_ATTR_END, time2string(stopTime));
651  dev.writeAttr(SUMO_ATTR_ID, getID());
652  dev.writeAttr("nVehContrib", p);
653  dev.writeAttr("removed", myRemoved);
654  dev.writeAttr("inserted", myInserted);
655  dev.writeAttr("cleared", myClearedInJam);
656  dev.writeAttr("flow", p * 3600.0 / durationSeconds);
657  dev.writeAttr("aspiredFlow", myCurrentStateInterval->q);
660  dev.writeAttr("aspiredSpeed", myCurrentStateInterval->v);
661  if (discrepancy > 0) {
662  dev.writeAttr("vaporizedOnNextEdge", discrepancy);
663  }
664  dev.closeTag();
665 }
666 
667 void
669  dev.writeXMLHeader("calibratorstats", "calibratorstats_file.xsd");
670 }
671 
672 std::string
674  // avoid name clash for subsecond interval spacing
675  const double beginS = STEPS2TIME(myCurrentStateInterval->begin);
676  const int precision = beginS == int(beginS) ? 0 : 2;
677  return getID() + "." + toString(beginS, precision) + "." + toString(myInserted);
678 }
679 
680 void
681 MSCalibrator::setFlow(SUMOTime begin, SUMOTime end, double vehsPerHour, double speed, SUMOVehicleParameter vehicleParameter) {
682  auto it = myCurrentStateInterval;
683  while (it != myIntervals.end()) {
684  if (it->begin > begin) {
685  throw ProcessError("Cannot set flow for calibrator '" + getID() + "' with begin time=" + time2string(begin) + " in the past.");
686  } else if (it->begin == begin && it->end == end) {
687  // update current interval
688  AspiredState& state = const_cast<AspiredState&>(*it);
689  state.q = vehsPerHour;
690  state.v = speed;
691  state.vehicleParameter->vtypeid = vehicleParameter.vtypeid;
692  state.vehicleParameter->routeid = vehicleParameter.routeid;
693  state.vehicleParameter->departLane = vehicleParameter.departLane;
694  state.vehicleParameter->departLaneProcedure = vehicleParameter.departLaneProcedure;
695  state.vehicleParameter->departSpeed = vehicleParameter.departSpeed;
697  return;
698  } else if (begin < it->end) {
699  throw ProcessError(TLF("Cannot set flow for calibrator '%' with overlapping interval.", getID()));
700  } else if (begin >= end) {
701  throw ProcessError(TLF("Cannot set flow for calibrator '%' with negative interval.", getID()));
702  }
703  it++;
704  }
705  // add interval at the end of the known intervals
706  const int intervalIndex = (int)(myCurrentStateInterval - myIntervals.begin());
707  AspiredState state;
708  state.begin = begin;
709  state.end = end;
710  state.q = vehsPerHour;
711  state.v = speed;
712  state.vehicleParameter = new SUMOVehicleParameter(vehicleParameter);
713  myIntervals.push_back(state);
714  // fix iterator
715  myCurrentStateInterval = myIntervals.begin() + intervalIndex;
716 }
717 
718 /****************************************************************************/
long long int SUMOTime
Definition: GUI.h:35
#define DEBUGCOND
#define DEBUGCOND2(id)
#define WRITE_WARNINGF(...)
Definition: MsgHandler.h:296
#define WRITE_ERRORF(...)
Definition: MsgHandler.h:305
#define WRITE_WARNING(msg)
Definition: MsgHandler.h:295
#define TL(string)
Definition: MsgHandler.h:315
#define TLF(string,...)
Definition: MsgHandler.h:317
std::shared_ptr< const MSRoute > ConstMSRoutePtr
Definition: Route.h:31
SUMOTime DELTA_T
Definition: SUMOTime.cpp:38
std::string time2string(SUMOTime t, bool humanReadable)
convert SUMOTime to string (independently of global format setting)
Definition: SUMOTime.cpp:69
#define STEPS2TIME(x)
Definition: SUMOTime.h:55
#define SIMSTEP
Definition: SUMOTime.h:61
#define SUMOTime_MAX
Definition: SUMOTime.h:34
#define TIME2STEPS(x)
Definition: SUMOTime.h:57
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.
const int VEHPARS_CALIBRATORSPEED_SET
@ SUMO_TAG_INTERVAL
an aggreagated-output interval
@ SUMO_TAG_FLOW
a flow definition using from and to edges or a route
@ SUMO_TAG_CALIBRATOR
A calibrator placed over edge.
PersonMode
travel modes for persons
@ SUMO_ATTR_VEHSPERHOUR
@ SUMO_ATTR_SPEED
@ SUMO_ATTR_BEGIN
weights: time range begin
@ SUMO_ATTR_END
weights: time range end
@ SUMO_ATTR_ID
#define UNUSED_PARAMETER(x)
Definition: StdDefs.h:30
T MAX2(T a, T b)
Definition: StdDefs.h:82
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition: ToString.h:46
void callParentEnd(int element)
signal endElement to the parent handler (special case for MSCalibrator)
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:311
SUMOTime shiftTime(SUMOTime currentTime, SUMOTime execTime, SUMOTime newTime)
Reschedule or deschedule the command when quick-loading state.
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:349
OutputDevice * myOutput
The device for xml statistics.
Definition: MSCalibrator.h:315
double myInvalidJamThreshold
relative speed threshold for detecting and clearing invalid jam
Definition: MSCalibrator.h:340
double currentSpeed() const
measured speed in the current interval
MSMeanData_Net myMeanDataParent
dummy parent to retrieve vType filter
Definition: MSCalibrator.h:295
MSEdge *const myEdge
the edge on which this calibrator lies
Definition: MSCalibrator.h:287
static void cleanup()
cleanup remaining data structures
bool isActive() const
Definition: MSCalibrator.h:221
bool mySpeedIsDefault
The information whether the speed adaption has been reset.
Definition: MSCalibrator.h:326
virtual void updateMeanData()
aggregate lane values
int myRemoved
The number of vehicles that were removed in the current interval.
Definition: MSCalibrator.h:320
virtual int passed() const
Definition: MSCalibrator.h:119
const MSRouteProbe *const myProbe
the route probe to retrieve routes from
Definition: MSCalibrator.h:293
bool myAmActive
whether the calibrator was active when last checking
Definition: MSCalibrator.h:337
std::set< std::string > myToRemove
set of vehicle ids to remove
Definition: MSCalibrator.h:312
static std::vector< MSMoveReminder * > myLeftoverReminders
Definition: MSCalibrator.h:347
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:343
std::vector< MSMeanData_Net::MSLaneMeanDataValues * > myLaneMeanData
data collector for the calibrator
Definition: MSCalibrator.h:297
std::vector< AspiredState >::const_iterator myCurrentStateInterval
Iterator pointing to the current interval.
Definition: MSCalibrator.h:304
double currentFlow() const
flow in the current interval in veh/h
static std::vector< SUMOVehicleParameter * > myLeftoverVehicleParameters
Definition: MSCalibrator.h:348
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;.
int myInserted
The number of vehicles that were inserted in the current interval.
Definition: MSCalibrator.h:322
bool myHaveWarnedAboutClearingJam
The default (maximum) speed on the segment.
Definition: MSCalibrator.h:334
std::vector< AspiredState > myIntervals
List of adaptation intervals.
Definition: MSCalibrator.h:302
const double myPos
the position on the edge where this calibrator lies
Definition: MSCalibrator.h:291
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:306
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:299
friend class VehicleRemover
Definition: MSCalibrator.h:217
bool invalidJam(int laneIndex) const
int myClearedInJam
The number of vehicles that were removed when clearin a jam.
Definition: MSCalibrator.h:324
void writeXMLDetectorProlog(OutputDevice &dev) const
Open the XML-output.
virtual ~MSCalibrator()
double myDefaultSpeed
The default (maximum) speed on the segment.
Definition: MSCalibrator.h:332
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:289
bool scheduleRemoval(SUMOTrafficObject *veh)
try to schedule the given vehicle for removal. return true if it isn't already scheduled
Definition: MSCalibrator.h:273
bool myDidInit
The information whether init was called.
Definition: MSCalibrator.h:330
void intervalEnd()
AspiredState getCurrentStateInterval() const
bool isCurrentStateActive(SUMOTime time)
SUMOTime myFrequency
The frequeny with which to check for calibration.
Definition: MSCalibrator.h:318
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:328
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
void setMaxSpeed(double val, double jamThreshold=-1)
Sets a new maximum speed for all lanes (used by TraCI and MSCalibrator)
Definition: MSEdge.cpp:1113
const std::vector< MSLane * > & getLanes() const
Returns this edge's lanes.
Definition: MSEdge.h:168
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:1094
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:711
virtual void addEvent(Command *operation, SUMOTime execTimeStep=-1)
Adds an Event.
static bool gUseMesoSim
Definition: MSGlobals.h:103
static bool gCheckRoutes
Definition: MSGlobals.h:88
Representation of a lane in the micro simulation.
Definition: MSLane.h:84
virtual MSVehicle * removeVehicle(MSVehicle *remVehicle, MSMoveReminder::Notification notification, bool notify=true)
Definition: MSLane.cpp:2696
int getVehicleNumber() const
Returns the number of vehicles on this lane (for which this lane is responsible)
Definition: MSLane.h:448
MSVehicle * getLastFullVehicle() const
returns the last vehicle for which this lane is responsible or 0
Definition: MSLane.cpp:2509
double getLength() const
Returns the lane's length.
Definition: MSLane.h:598
int getIndex() const
Returns the lane's index.
Definition: MSLane.h:634
void setMaxSpeed(double val, bool byVSS=false, bool byTraCI=false, double jamThreshold=-1)
Sets a new maximum speed for the lane (used by TraCI and MSCalibrator)
Definition: MSLane.cpp:2649
double getMeanSpeed() const
Returns the mean speed on this lane.
Definition: MSLane.cpp:3288
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:280
Data structure for mean (aggregated) edge/lane values.
int nVehVaporized
The number of vehicles that left this lane via vaporization within the sample interval.
int nVehLeft
The number of vehicles that left this lane within the sample interval.
int nVehTeleported
The number of vehicles that left this lane via teleporting 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.
Something on a lane to be noticed about vehicle movement.
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:182
MSVehicleControl & getVehicleControl()
Returns the vehicle control.
Definition: MSNet.h:378
MSEventControl * getEndOfTimestepEvents()
Returns the event control for events executed at the end of a time step.
Definition: MSNet.h:481
Parser and container for routes during their loading.
virtual void myStartElement(int element, const SUMOSAXAttributes &attrs) override
Called on the opening of a tag;.
static bool dictionary(const std::string &id, ConstMSRoutePtr route)
Adds a route to the dictionary.
Definition: MSRoute.cpp:109
Writes routes of vehicles passing a certain edge.
Definition: MSRouteProbe.h:58
ConstMSRoutePtr sampleRoute(bool last=true) const
The class responsible for building and deletion of vehicles.
virtual SUMOVehicle * buildVehicle(SUMOVehicleParameter *defs, ConstMSRoutePtr route, MSVehicleType *type, const bool ignoreStopErrors, const bool fromRouteFile=true, bool addRouteStops=true)
Builds a vehicle, increases the number of built 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, SumoRNG *rng=nullptr, bool readOnly=false)
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.
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:592
void onRemovalFromNet(const MSMoveReminder::Notification reason)
Called when the vehicle is removed from the network.
Definition: MSVehicle.cpp:1043
double getPositionOnLane() const
Get the vehicle's position along the lane.
Definition: MSVehicle.h:377
The car-following model and parameter.
Definition: MSVehicleType.h:63
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:74
Static storage of an output device and its base (abstract) implementation.
Definition: OutputDevice.h:61
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:254
bool closeTag(const std::string &comment="")
Closes the most recently opened tag and optionally adds a comment.
static OutputDevice & getDevice(const std::string &name, bool usePrefix=true)
Returns the described OutputDevice.
bool writeXMLHeader(const std::string &rootElement, const std::string &schemaFile, std::map< SumoXMLAttr, std::string > attrs=std::map< SumoXMLAttr, std::string >(), bool includeConfig=true)
Writes an XML header with optional configuration.
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=T(), 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 parametersSet
Information for the router which parameter were set, TraCI may modify this (when changing color)
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, const bool allowInternalRoutes=false)
Parses a vehicle's attributes.
static bool runParser(GenericSAXHandler &handler, const std::string &file, const bool isNet=false, const bool isRoute=false, const bool isExternal=false, const bool catchExceptions=true)
Runs the given handler on the given file; returns if everything's ok.
Definition: XMLSubSys.cpp:157
Definition: json.hpp:4471
SUMOVehicleParameter * vehicleParameter
Definition: MSCalibrator.h:102