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-2023 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>
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// ===========================================================================
54std::vector<MSMoveReminder*> MSCalibrator::myLeftoverReminders;
55std::vector<SUMOVehicleParameter*> MSCalibrator::myLeftoverVehicleParameters;
56std::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// ===========================================================================
75MSCalibrator::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(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),
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
133void
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 }
164}
165
166void
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);
192 state.vehicleParameter->parametersSet &= ~VEHPARS_CALIBRATORSPEED_SET;
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 }
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
237void
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
251void
253 if (myOutput != nullptr) {
255 }
256 myDidSpeedAdaption = false;
257 myInserted = 0;
258 myRemoved = 0;
259 myClearedInJam = 0;
261 reset();
262}
263
264
265bool
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
276int
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
287double
289 const double totalHourFraction = STEPS2TIME(MSNet::getInstance()->getCurrentTimeStep() - myCurrentStateInterval->begin) / (double) 3600.;
290 return passed() / totalHourFraction;
291}
292
293
294double
296 if (myEdgeMeanData.getSamples() > 0) {
298 } else {
299 return -1;
300 }
301}
302
303
304bool
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
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) ?
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
492void
496 val->reset();
497 }
498}
499
500
501bool
502MSCalibrator::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
524int
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
550void
552 while (!myInstances.empty()) {
553 delete myInstances.begin()->second;
554 }
556 delete rem;
557 }
558 myLeftoverReminders.clear();
560 delete par;
561 }
563}
564
565
566void
569 for (std::vector<MSMeanData_Net::MSLaneMeanDataValues*>::iterator it = myLaneMeanData.begin();
570 it != myLaneMeanData.end(); ++it) {
571 (*it)->addTo(myEdgeMeanData);
572 }
573}
574
575
576bool
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)) {
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);
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) {
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
639void
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));
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
667void
669 dev.writeXMLHeader("calibratorstats", "calibratorstats_file.xsd");
670}
671
672std::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
680void
681MSCalibrator::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;
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:36
#define DEBUGCOND
#define DEBUGCOND2(id)
#define WRITE_WARNINGF(...)
Definition: MsgHandler.h:271
#define WRITE_ERRORF(...)
Definition: MsgHandler.h:280
#define WRITE_WARNING(msg)
Definition: MsgHandler.h:270
#define TL(string)
Definition: MsgHandler.h:287
#define TLF(string,...)
Definition: MsgHandler.h:288
std::shared_ptr< const MSRoute > ConstMSRoutePtr
Definition: Route.h:32
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.
@ 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
const MSEdge *const myEdge
the edge on which this calibrator lies
Definition: MSCalibrator.h:287
MSMeanData_Net myMeanDataParent
dummy parent to retrieve vType filter
Definition: MSCalibrator.h:295
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
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:1056
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:675
void setMaxSpeed(double val) const
Sets a new maximum speed for all lanes (used by TraCI and MSCalibrator)
Definition: MSEdge.cpp:1075
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:2635
int getVehicleNumber() const
Returns the number of vehicles on this lane (for which this lane is responsible)
Definition: MSLane.h:447
MSVehicle * getLastFullVehicle() const
returns the last vehicle for which this lane is responsible or 0
Definition: MSLane.cpp:2474
double getLength() const
Returns the lane's length.
Definition: MSLane.h:593
int getIndex() const
Returns the lane's index.
Definition: MSLane.h:629
void setMaxSpeed(double val)
Sets a new maximum speed for the lane (used by TraCI and MSCalibrator)
Definition: MSLane.cpp:2600
double getMeanSpeed() const
Returns the mean speed on this lane.
Definition: MSLane.cpp:3222
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:183
MSEventControl * getEndOfTimestepEvents()
Returns the event control for events executed at the end of a time step.
Definition: MSNet.h:483
MSVehicleControl & getVehicleControl()
Returns the vehicle control.
Definition: MSNet.h:380
Parser and container for routes during their loading.
virtual void myStartElement(int element, const SUMOSAXAttributes &attrs)
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
void onRemovalFromNet(const MSMoveReminder::Notification reason)
Called when the vehicle is removed from the network.
Definition: MSVehicle.cpp:1024
MSLane * getMutableLane() const
Returns the lane the vehicle is on Non const version indicates that something volatile is going on.
Definition: MSVehicle.h:592
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 & writeAttr(const SumoXMLAttr attr, const T &val)
writes a named attribute
Definition: OutputDevice.h:254
OutputDevice & openTag(const std::string &xmlElement)
Opens an XML tag.
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)
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