Eclipse SUMO - Simulation of Urban MObility
METriggeredCalibrator.cpp
Go to the documentation of this file.
1 /****************************************************************************/
2 // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
3 // Copyright (C) 2001-2019 German Aerospace Center (DLR) and others.
4 // This program and the accompanying materials
5 // are made available under the terms of the Eclipse Public License v2.0
6 // which accompanies this distribution, and is available at
7 // http://www.eclipse.org/legal/epl-v20.html
8 // SPDX-License-Identifier: EPL-2.0
9 /****************************************************************************/
14 // Calibrates the flow on a segment to a specified one
15 /****************************************************************************/
16 
17 
18 // ===========================================================================
19 // included modules
20 // ===========================================================================
21 #include <config.h>
22 
23 #include <string>
24 #include <algorithm>
25 #include <cmath>
26 #include <microsim/MSGlobals.h>
27 #include <microsim/MSNet.h>
28 #include <microsim/MSEdge.h>
33 #include <utils/common/ToString.h>
36 #include <utils/xml/XMLSubSys.h>
42 #include "MELoop.h"
43 #include "MESegment.h"
44 #include "MEVehicle.h"
45 #include "METriggeredCalibrator.h"
46 
47 
48 // ===========================================================================
49 // method definitions
50 // ===========================================================================
52  const MSEdge* const edge, const double pos,
53  const std::string& aXMLFilename,
54  const std::string& outputFilename,
55  const SUMOTime freq, const double length,
56  const MSRouteProbe* probe,
57  const std::string& vTypes) :
58  MSCalibrator(id, edge, (MSLane*)nullptr, pos, aXMLFilename, outputFilename, freq, length, probe, vTypes, false),
59  mySegment(MSGlobals::gMesoNet->getSegmentForEdge(*edge, pos)) {
60  myEdgeMeanData.setDescription("meandata_calibrator_" + getID());
62 }
63 
64 
66  if (myCurrentStateInterval != myIntervals.end()) {
67  // need to do it here and not in MSCalibrator because otherwise meandata is gone
68  intervalEnd();
69  // but avoid to call it again in MSCalibrator
71  }
73 }
74 
75 
76 bool
78  if (s->initialise(vehicle, vehicle->getParameter().depart)) {
79  if (!MSNet::getInstance()->getVehicleControl().addVehicle(vehicle->getID(), vehicle)) {
80  throw ProcessError("Emission of vehicle '" + vehicle->getID() + "' in calibrator '" + getID() + "'failed!");
81  }
82  return true;
83  }
84  return false;
85 }
86 
87 
90  // get current simulation values (valid for the last simulation second)
91  // XXX could we miss vehicle movements if this is called less often than every DELTA_T (default) ?
93 
94  // check whether an adaptation value exists
95  if (isCurrentStateActive(currentTime)) {
96  // all happens in isCurrentStateActive()
97  } else {
98  myEdgeMeanData.reset(); // discard collected values
99  if (!mySpeedIsDefault) {
100  // if not, reset adaptation values
103  const double jamThresh = OptionsCont::getOptions().getFloat("meso-jam-threshold");
104  while (first != nullptr) {
105  first->setSpeed(myDefaultSpeed, currentTime, jamThresh);
106  first = first->getNextSegment();
107  }
108  mySpeedIsDefault = true;
109  }
110  if (myCurrentStateInterval == myIntervals.end()) {
111  // keep calibrator alive but do not call again
112  return TIME2STEPS(86400);
113  }
114  return myFrequency;
115  }
116  // we are active
120  while (first != nullptr) {
121  first->setSpeed(myCurrentStateInterval->v, currentTime, -1);
122  first = first->getNextSegment();
123  }
124  mySpeedIsDefault = false;
125  myDidSpeedAdaption = true;
126  }
127  // clear invalid jams
128  bool hadInvalidJam = false;
129  while (invalidJam()) {
130  hadInvalidJam = true;
132  WRITE_WARNING("Clearing jam at calibrator '" + getID() + "' at time " + time2string(currentTime));
133  }
134  // remove one vehicle currently on the segment
135  if (mySegment->vaporizeAnyCar(currentTime)) {
136  myClearedInJam++;
137  } else {
139  // this frequenly happens for very short edges
140  WRITE_WARNING("Could not clear jam at calibrator '" + getID() + "' at time " + time2string(currentTime));
141  }
142  break;
143  }
145  }
146  if (myCurrentStateInterval->q >= 0) {
147  // flow calibration starts here ...
148  // compute the number of vehicles that should have passed the calibrator within the time
149  // rom begin of the interval
150  const double totalHourFraction = STEPS2TIME(myCurrentStateInterval->end - myCurrentStateInterval->begin) / (double) 3600.;
151  const int totalWishedNum = (int)std::floor(myCurrentStateInterval->q * totalHourFraction + 0.5); // round to closest int
152  int adaptedNum = passed() + myClearedInJam;
153  if (!hadInvalidJam) {
154  // only add vehicles if we do not have an invalid upstream jam to prevent spill-back
155  const double hourFraction = STEPS2TIME(currentTime - myCurrentStateInterval->begin + DELTA_T) / (double) 3600.;
156  const int wishedNum = (int)std::floor(myCurrentStateInterval->q * hourFraction + 0.5); // round to closest int
157  // only the difference between inflow and aspiredFlow should be added, thus
158  // we should not count vehicles vaporized from a jam here
159  // if we have enough time left we can add missing vehicles later
160  const int relaxedInsertion = (int)std::floor(STEPS2TIME(myCurrentStateInterval->end - currentTime) / 3);
161  const int insertionSlack = MAX2(0, adaptedNum + relaxedInsertion - totalWishedNum);
162  // increase number of vehicles
163  //std::cout << "time:" << STEPS2TIME(currentTime) << " w:" << wishedNum << " s:" << insertionSlack << " before:" << adaptedNum;
164  while (wishedNum > adaptedNum + insertionSlack && remainingVehicleCapacity() > maximumInflow()) {
165  SUMOVehicleParameter* pars = myCurrentStateInterval->vehicleParameter;
166  const MSRoute* route = myProbe != nullptr ? myProbe->getRoute() : nullptr;
167  if (route == nullptr) {
168  route = MSRoute::dictionary(pars->routeid);
169  }
170  if (route == nullptr) {
171  WRITE_WARNING("No valid routes in calibrator '" + getID() + "'.");
172  break;
173  }
174  if (!route->contains(myEdge)) {
175  WRITE_WARNING("Route '" + route->getID() + "' in calibrator '" + getID() + "' does not contain edge '" + myEdge->getID() + "'.");
176  break;
177  }
179  assert(route != 0 && vtype != 0);
180  // build the vehicle
181  const SUMOTime depart = mySegment->getNextInsertionTime(currentTime);
182  SUMOVehicleParameter* newPars = new SUMOVehicleParameter(*pars);
183  newPars->id = getNewVehicleID();
184  newPars->depart = depart;
185  newPars->routeid = route->getID();
186  MEVehicle* vehicle;
187  try {
188  vehicle = static_cast<MEVehicle*>(MSNet::getInstance()->getVehicleControl().buildVehicle(
189  newPars, route, vtype, false, false));
190  } catch (const ProcessError& e) {
192  WRITE_WARNING(e.what());
193  vehicle = nullptr;
194  break;
195  } else {
196  throw e;
197  }
198  }
199  vehicle->setSegment(mySegment); // needed or vehicle will not be registered (XXX why?)
200  vehicle->setEventTime(currentTime); // XXX superfluous?
201  // move vehicle forward when the route does not begin at the calibrator's edge
202  const MSEdge* myedge = &mySegment->getEdge();
203  bool atDest = false;
204  while (vehicle->getEdge() != myedge) {
205  // let the vehicle move to the next edge
206  atDest = vehicle->moveRoutePointer();
207  }
208  // insert vehicle into the net
209  if (atDest || !tryEmit(mySegment, vehicle)) {
210  //std::cout << "F ";
212  break;
213  }
214  //std::cout << "I ";
215  myInserted++;
216  adaptedNum++;
217  }
218  }
219  //std::cout << " after:" << adaptedNum << "\n";
220  // we only remove vehicles once we really have to
221  while (totalWishedNum < adaptedNum) {
222  if (!mySegment->vaporizeAnyCar(currentTime)) {
223  // @bug: short edges may be jumped in a single step, giving us no chance to remove a vehicle
224  // @bug2: vehicleApplies() must be considered (#3082)
225  break;
226  }
227  myRemoved++;
228  adaptedNum--;
229  }
230  }
231  if (myCurrentStateInterval->end <= currentTime + myFrequency) {
232  intervalEnd();
233  }
234  //assert(!invalidJam());
235  if (invalidJam()) {
236  WRITE_WARNING("DEBUG: Could not clear jam at calibrator '" + getID() + "' at time " + time2string(currentTime));
237  }
238  return myFrequency;
239 }
240 
241 
242 bool
244  if (mySegment->getBruttoOccupancy() == 0.) {
245  return false;
246  }
247  // maxSpeed reflects the calibration target
248  const bool toSlow = mySegment->getMeanSpeed() < 0.8 * mySegment->getEdge().getSpeedLimit();
249  return toSlow && remainingVehicleCapacity() < maximumInflow();
250 }
251 
252 
253 int
255  const SUMOVehicleParameter* pars = myCurrentStateInterval->vehicleParameter;
258 }
259 
260 
261 void
264 }
265 
266 
267 /****************************************************************************/
268 
MSCalibrator::myRemoved
int myRemoved
The number of vehicles that were removed in the current interval.
Definition: MSCalibrator.h:287
MSCalibrator::myClearedInJam
int myClearedInJam
The number of vehicles that were removed when clearin a jam.
Definition: MSCalibrator.h:291
MSVehicleType
The car-following model and parameter.
Definition: MSVehicleType.h:65
MEVehicle
A vehicle from the mesoscopic point of view.
Definition: MEVehicle.h:44
MESegment::remainingVehicleCapacity
int remainingVehicleCapacity(const double vehLength) const
return the remaining physical space on this segment
Definition: MESegment.h:355
MSCalibrator::getID
const std::string & getID() const
Definition: MSCalibrator.h:90
ToString.h
MSBaseVehicle::getParameter
const SUMOVehicleParameter & getParameter() const
Returns the vehicle's parameter (including departure definition)
Definition: MSBaseVehicle.cpp:144
METriggeredCalibrator.h
MSCalibrator::myHaveWarnedAboutClearingJam
bool myHaveWarnedAboutClearingJam
The default (maximum) speed on the segment.
Definition: MSCalibrator.h:301
MSEdge::getSpeedLimit
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:877
MESegment::getMeanSpeed
double getMeanSpeed(bool useCache) const
Returns the average speed of vehicles on the segment in meters per second. If there is no vehicle on ...
Definition: MESegment.cpp:293
WRITE_WARNING
#define WRITE_WARNING(msg)
Definition: MsgHandler.h:275
METriggeredCalibrator::tryEmit
bool tryEmit(MESegment *s, MEVehicle *vehicle)
Definition: METriggeredCalibrator.cpp:77
METriggeredCalibrator::execute
SUMOTime execute(SUMOTime currentTime)
Definition: METriggeredCalibrator.cpp:89
MSNet.h
MSLane
Representation of a lane in the micro simulation.
Definition: MSLane.h:82
MSVehicleControl::getVType
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.
Definition: MSVehicleControl.cpp:353
MESegment
A single mesoscopic segment (cell)
Definition: MESegment.h:49
MSCalibrator::myInserted
int myInserted
The number of vehicles that were inserted in the current interval.
Definition: MSCalibrator.h:289
DELTA_T
SUMOTime DELTA_T
Definition: SUMOTime.cpp:36
SUMOVehicleParserHelper.h
MSCalibrator::myFrequency
SUMOTime myFrequency
The frequeny with which to check for calibration.
Definition: MSCalibrator.h:285
OptionsCont.h
MSRouteProbe
Writes routes of vehicles passing a certain edge.
Definition: MSRouteProbe.h:60
MESegment::addDetector
void addDetector(MSMoveReminder *data)
Adds a data collector for a detector to this segment.
Definition: MESegment.cpp:211
SUMOVehicleParameter::vtypeid
std::string vtypeid
The vehicle's type id.
Definition: SUMOVehicleParameter.h:474
MSCalibrator::myCurrentStateInterval
std::vector< AspiredState >::const_iterator myCurrentStateInterval
Iterator pointing to the current interval.
Definition: MSCalibrator.h:271
MESegment::getEdge
const MSEdge & getEdge() const
Returns the edge this segment belongs to.
Definition: MESegment.h:265
MESegment::initialise
bool initialise(MEVehicle *veh, SUMOTime time)
Inserts (emits) vehicle into the segment.
Definition: MESegment.cpp:278
SUMOTime
long long int SUMOTime
Definition: SUMOTime.h:34
OptionsCont::getOptions
static OptionsCont & getOptions()
Retrieves the options.
Definition: OptionsCont.cpp:57
METriggeredCalibrator::remainingVehicleCapacity
int remainingVehicleCapacity() const
returns the number of vehicles (of the current type) that still fit onto the segment
Definition: METriggeredCalibrator.cpp:254
MSGlobals
Definition: MSGlobals.h:48
MSCalibrator::mySpeedIsDefault
bool mySpeedIsDefault
The information whether the speed adaption has been reset.
Definition: MSCalibrator.h:293
SUMOVehicleParameter
Structure representing possible vehicle parameter.
Definition: SUMOVehicleParameter.h:297
MSEdge.h
MEVehicle::setEventTime
void setEventTime(SUMOTime t, bool hasDelay=true)
Sets the (planned) time at which the vehicle leaves his current cell.
Definition: MEVehicle.h:217
MESegment::removeDetector
void removeDetector(MSMoveReminder *data)
Removes a data collector for a detector from this segment.
Definition: MESegment.cpp:222
MSRoute
Definition: MSRoute.h:66
SUMOVehicleParameter::depart
SUMOTime depart
Definition: SUMOVehicleParameter.h:482
MSMeanData_Net::MSLaneMeanDataValues::reset
void reset(bool afterWrite=false)
Resets values so they may be used for the next interval.
Definition: MSMeanData_Net.cpp:73
MSCalibrator::myDefaultSpeed
double myDefaultSpeed
The default (maximum) speed on the segment.
Definition: MSCalibrator.h:299
MEVehicle::moveRoutePointer
bool moveRoutePointer()
Update when the vehicle enters a new edge in the move step.
Definition: MEVehicle.cpp:138
SUMOVehicleParameter.h
METriggeredCalibrator::passed
int passed() const
Definition: METriggeredCalibrator.h:61
MESegment.h
MSBaseVehicle::getEdge
const MSEdge * getEdge() const
Returns the edge the vehicle is currently at.
Definition: MSBaseVehicle.cpp:181
MAX2
T MAX2(T a, T b)
Definition: StdDefs.h:79
METriggeredCalibrator::mySegment
MESegment * mySegment
mesoscopic edge segment the calibrator lies on
Definition: METriggeredCalibrator.h:85
METriggeredCalibrator::~METriggeredCalibrator
virtual ~METriggeredCalibrator()
Definition: METriggeredCalibrator.cpp:65
MSVehicleControl::addVehicle
virtual bool addVehicle(const std::string &id, SUMOVehicle *v)
Tries to insert the vehicle into the internal vehicle container.
Definition: MSVehicleControl.cpp:215
METriggeredCalibrator::reset
void reset()
reset collected vehicle data
Definition: METriggeredCalibrator.cpp:262
RandomDistributor.h
MESegment::prepareDetectorForWriting
void prepareDetectorForWriting(MSMoveReminder &data)
Updates data of a detector for all vehicle queues.
Definition: MESegment.cpp:237
TIME2STEPS
#define TIME2STEPS(x)
Definition: SUMOTime.h:58
MSVehicleType::getLengthWithGap
double getLengthWithGap() const
Get vehicle's length including the minimum gap [m].
Definition: MSVehicleType.h:117
MSCalibrator::myDidSpeedAdaption
bool myDidSpeedAdaption
The information whether speed was adapted in the current interval.
Definition: MSCalibrator.h:295
STEPS2TIME
#define STEPS2TIME(x)
Definition: SUMOTime.h:56
SUMOVehicleParameter::id
std::string id
The vehicle's id.
Definition: SUMOVehicleParameter.h:468
MELoop::getSegmentForEdge
MESegment * getSegmentForEdge(const MSEdge &e, double pos=0)
Get the segment for a given edge at a given position.
Definition: MELoop.cpp:292
MSVehicleControl::deleteVehicle
virtual void deleteVehicle(SUMOVehicle *v, bool discard=false)
Deletes the vehicle.
Definition: MSVehicleControl.cpp:250
ProcessError
Definition: UtilExceptions.h:39
time2string
std::string time2string(SUMOTime t)
Definition: SUMOTime.cpp:67
MSGlobals.h
UtilExceptions.h
MESegment::getNextSegment
MESegment * getNextSegment() const
Returns the following segment on the same edge (0 if it is the last).
Definition: MESegment.h:151
MSEdge
A road/street connecting two junctions.
Definition: MSEdge.h:78
MSGlobals::gCheckRoutes
static bool gCheckRoutes
Definition: MSGlobals.h:78
MSCalibrator::myEdgeMeanData
MSMeanData_Net::MSLaneMeanDataValues myEdgeMeanData
accumlated data for the whole edge
Definition: MSCalibrator.h:264
MSRouteProbe::getRoute
const MSRoute * getRoute() const
Definition: MSRouteProbe.cpp:124
MSCalibrator::myProbe
const MSRouteProbe *const myProbe
the route probe to retrieve routes from
Definition: MSCalibrator.h:260
SUMOVehicleParameter::routeid
std::string routeid
The vehicle's route id.
Definition: SUMOVehicleParameter.h:471
MESegment::vaporizeAnyCar
bool vaporizeAnyCar(SUMOTime currentTime)
tries to remove any car from this segment
Definition: MESegment.cpp:575
METriggeredCalibrator::invalidJam
bool invalidJam() const
returns whether the segment is jammed although it should not be
Definition: METriggeredCalibrator.cpp:243
OptionsCont::getFloat
double getFloat(const std::string &name) const
Returns the double-value of the named option (only for Option_Float)
Definition: OptionsCont.cpp:208
StringUtils.h
MESegment::getBruttoOccupancy
double getBruttoOccupancy() const
Returns the occupany of the segment (the sum of the vehicle lengths + minGaps)
Definition: MESegment.h:167
MSNet::getInstance
static MSNet * getInstance()
Returns the pointer to the unique instance of MSNet (singleton).
Definition: MSNet.cpp:167
MSGlobals::gMesoNet
static MELoop * gMesoNet
mesoscopic simulation infrastructure
Definition: MSGlobals.h:105
METriggeredCalibrator::maximumInflow
int maximumInflow() const
returns the maximum number of vehicles that could enter from upstream until the calibrator is activat...
Definition: METriggeredCalibrator.h:79
MSEdge::setMaxSpeed
void setMaxSpeed(double val) const
Sets a new maximum speed for all lanes (used by TraCI and MSCalibrator)
Definition: MSEdge.cpp:896
MSCalibrator::getNewVehicleID
std::string getNewVehicleID()
determine id of new vehicle from calibrator state
Definition: MSCalibrator.cpp:579
MSCalibrator::isCurrentStateActive
bool isCurrentStateActive(SUMOTime time)
Definition: MSCalibrator.cpp:227
MSRouteProbe.h
MEVehicle::setSegment
virtual void setSegment(MESegment *s, int idx=0)
Sets the current segment the vehicle is at together with its que.
Definition: MEVehicle.h:238
MSMoveReminder::setDescription
void setDescription(const std::string &description)
Definition: MSMoveReminder.h:226
MESegment::getNextInsertionTime
SUMOTime getNextInsertionTime(SUMOTime earliestEntry) const
return a time after earliestEntry at which a vehicle may be inserted at full speed
Definition: MESegment.cpp:361
MSBaseVehicle::getID
const std::string & getID() const
Returns the name of the vehicle.
Definition: MSBaseVehicle.cpp:138
MEVehicle.h
MSRoute::dictionary
static bool dictionary(const std::string &id, const MSRoute *route)
Adds a route to the dictionary.
Definition: MSRoute.cpp:113
config.h
StringTokenizer.h
MELoop.h
MSEventControl.h
MESegment::setSpeed
void setSpeed(double newSpeed, SUMOTime currentTime, double jamThresh=DO_NOT_PATCH_JAM_THRESHOLD)
reset mySpeed and patch the speed of all vehicles in it. Also set/recompute myJamThreshold
Definition: MESegment.cpp:621
MSCalibrator
Calibrates the flow on a segment to a specified one.
Definition: MSCalibrator.h:50
MSCalibrator::intervalEnd
void intervalEnd()
Definition: MSCalibrator.cpp:213
MSCalibrator::myIntervals
std::vector< AspiredState > myIntervals
List of adaptation intervals.
Definition: MSCalibrator.h:269
MSRoute::contains
bool contains(const MSEdge *const edge) const
Definition: MSRoute.h:102
METriggeredCalibrator::METriggeredCalibrator
METriggeredCalibrator(const std::string &id, const MSEdge *const edge, const double pos, const std::string &aXMLFilename, const std::string &outputFilename, const SUMOTime freq, const double length, const MSRouteProbe *probe, const std::string &vTypes)
Definition: METriggeredCalibrator.cpp:51
MSCalibrator::myEdge
const MSEdge *const myEdge
the edge on which this calibrator lies
Definition: MSCalibrator.h:254
MSVehicleControl.h
Named::getID
const std::string & getID() const
Returns the id.
Definition: Named.h:76
SUMOXMLDefinitions.h
MSNet::getVehicleControl
MSVehicleControl & getVehicleControl()
Returns the vehicle control.
Definition: MSNet.h:336
XMLSubSys.h