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 
MESegment * getNextSegment() const
Returns the following segment on the same edge (0 if it is the last).
Definition: MESegment.h:152
double getLengthWithGap() const
Get vehicle&#39;s length including the minimum gap [m].
virtual void setSegment(MESegment *s, int idx=0)
Sets the current segment the vehicle is at together with its que.
Definition: MEVehicle.h:235
virtual void deleteVehicle(SUMOVehicle *v, bool discard=false)
Deletes the vehicle.
long long int SUMOTime
Definition: SUMOTime.h:35
SUMOTime execute(SUMOTime currentTime)
int maximumInflow() const
returns the maximum number of vehicles that could enter from upstream until the calibrator is activat...
A vehicle from the mesoscopic point of view.
Definition: MEVehicle.h:45
MESegment * getSegmentForEdge(const MSEdge &e, double pos=0)
Get the segment for a given edge at a given position.
Definition: MELoop.cpp:293
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
std::string vtypeid
The vehicle&#39;s type id.
const MSRoute * getRoute() const
bool initialise(MEVehicle *veh, SUMOTime time)
Inserts (emits) vehicle into the segment.
Definition: MESegment.cpp:279
Writes routes of vehicles passing a certain edge.
Definition: MSRouteProbe.h:61
bool myDidSpeedAdaption
The information whether speed was adapted in the current interval.
Definition: MSCalibrator.h:293
MSVehicleType * getVType(const std::string &id=DEFAULT_VTYPE_ID, std::mt19937 *rng=nullptr)
Returns the named vehicle type or a sample from the named distribution.
const SUMOVehicleParameter & getParameter() const
Returns the vehicle&#39;s parameter (including departure definition)
std::string time2string(SUMOTime t)
Definition: SUMOTime.cpp:65
static MSNet * getInstance()
Returns the pointer to the unique instance of MSNet (singleton).
Definition: MSNet.cpp:168
T MAX2(T a, T b)
Definition: StdDefs.h:80
SUMOTime DELTA_T
Definition: SUMOTime.cpp:35
virtual bool addVehicle(const std::string &id, SUMOVehicle *v)
Tries to insert the vehicle into the internal vehicle container.
const std::string & getID() const
Returns the id.
Definition: Named.h:77
SUMOTime myFrequency
The frequeny with which to check for calibration.
Definition: MSCalibrator.h:283
#define TIME2STEPS(x)
Definition: SUMOTime.h:59
bool tryEmit(MESegment *s, MEVehicle *vehicle)
int myRemoved
The number of vehicles that were removed in the current interval.
Definition: MSCalibrator.h:285
int myClearedInJam
The number of vehicles that were removed when clearin a jam.
Definition: MSCalibrator.h:289
double getSpeedLimit() const
Returns the speed limit of the edge The speed limit of the first lane is retured; should probably be...
Definition: MSEdge.cpp:916
const MSEdge *const myEdge
the edge on which this calibrator lies
Definition: MSCalibrator.h:252
#define WRITE_WARNING(msg)
Definition: MsgHandler.h:239
The car-following model and parameter.
Definition: MSVehicleType.h:66
const std::string & getID() const
Definition: MSCalibrator.h:91
static OptionsCont & getOptions()
Retrieves the options.
Definition: OptionsCont.cpp:58
A road/street connecting two junctions.
Definition: MSEdge.h:76
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition: ToString.h:48
std::vector< AspiredState >::const_iterator myCurrentStateInterval
Iterator pointing to the current interval.
Definition: MSCalibrator.h:269
std::string routeid
The vehicle&#39;s route id.
static bool gCheckRoutes
Definition: MSGlobals.h:79
MESegment * mySegment
mesoscopic edge segment the calibrator lies on
const MSEdge * getEdge() const
Returns the edge the vehicle is currently at.
MSVehicleControl & getVehicleControl()
Returns the vehicle control.
Definition: MSNet.h:337
#define STEPS2TIME(x)
Definition: SUMOTime.h:57
double myDefaultSpeed
The default (maximum) speed on the segment.
Definition: MSCalibrator.h:297
void addDetector(MSMoveReminder *data)
Adds a data collector for a detector to this segment.
Definition: MESegment.cpp:212
bool mySpeedIsDefault
The information whether the speed adaption has been reset.
Definition: MSCalibrator.h:291
std::vector< AspiredState > myIntervals
List of adaptation intervals.
Definition: MSCalibrator.h:267
double getBruttoOccupancy() const
Returns the occupany of the segment (the sum of the vehicle lengths + minGaps)
Definition: MESegment.h:168
bool vaporizeAnyCar(SUMOTime currentTime)
tries to remove any car from this segment
Definition: MESegment.cpp:578
double getFloat(const std::string &name) const
Returns the double-value of the named option (only for Option_Float)
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)
bool myHaveWarnedAboutClearingJam
The default (maximum) speed on the segment.
Definition: MSCalibrator.h:299
void removeDetector(MSMoveReminder *data)
Removes a data collector for a detector from this segment.
Definition: MESegment.cpp:223
void setDescription(const std::string &description)
bool moveRoutePointer()
Update when the vehicle enters a new edge in the move step.
Definition: MEVehicle.cpp:139
SUMOTime getNextInsertionTime(SUMOTime earliestEntry) const
return a time after earliestEntry at which a vehicle may be inserted at full speed ...
Definition: MESegment.cpp:362
void intervalEnd()
int remainingVehicleCapacity() const
returns the number of vehicles (of the current type) that still fit onto the segment ...
Structure representing possible vehicle parameter.
A single mesoscopic segment (cell)
Definition: MESegment.h:50
bool invalidJam() const
returns whether the segment is jammed although it should not be
static MELoop * gMesoNet
mesoscopic simulation infrastructure
Definition: MSGlobals.h:106
void setMaxSpeed(double val) const
Sets a new maximum speed for all lanes (used by TraCI and MSCalibrator)
Definition: MSEdge.cpp:935
const MSRouteProbe *const myProbe
the route probe to retrieve routes from
Definition: MSCalibrator.h:258
void setEventTime(SUMOTime t, bool hasDelay=true)
Sets the (planned) time at which the vehicle leaves his current cell.
Definition: MEVehicle.h:214
Calibrates the flow on a segment to a specified one.
Definition: MSCalibrator.h:51
void reset(bool afterWrite=false)
Resets values so they may be used for the next interval.
MSMeanData_Net::MSLaneMeanDataValues myEdgeMeanData
accumlated data for the whole edge
Definition: MSCalibrator.h:262
void prepareDetectorForWriting(MSMoveReminder &data)
Updates data of a detector for all vehicle queues.
Definition: MESegment.cpp:238
bool isCurrentStateActive(SUMOTime time)
virtual SUMOVehicle * buildVehicle(SUMOVehicleParameter *defs, const MSRoute *route, MSVehicleType *type, const bool ignoreStopErrors, const bool fromRouteFile=true)
Builds a vehicle, increases the number of built vehicles.
int remainingVehicleCapacity(const double vehLength) const
return the remaining physical space on this segment
Definition: MESegment.h:356
const std::string & getID() const
Returns the name of the vehicle.
const MSEdge & getEdge() const
Returns the edge this segment belongs to.
Definition: MESegment.h:266
Representation of a lane in the micro simulation.
Definition: MSLane.h:83
void reset()
reset collected vehicle data
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
bool contains(const MSEdge *const edge) const
Definition: MSRoute.h:103
int myInserted
The number of vehicles that were inserted in the current interval.
Definition: MSCalibrator.h:287
std::string id
The vehicle&#39;s id.
static bool dictionary(const std::string &id, const MSRoute *route)
Adds a route to the dictionary.
Definition: MSRoute.cpp:114