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