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-2018 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  MSCalibrator(id, edge, (MSLane*)nullptr, pos, aXMLFilename, outputFilename, freq, length, probe, 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
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 '" + myID + "' 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 '" + myID + "' 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 '" + myID + "'.");
172  break;
173  }
174  if (!route->contains(myEdge)) {
175  WRITE_WARNING("Route '" + route->getID() + "' in calibrator '" + myID + "' 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 = myID + "." + toString(depart) + "." + toString(myInserted);
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  break;
225  }
226  myRemoved++;
227  adaptedNum--;
228  }
229  }
230  if (myCurrentStateInterval->end <= currentTime + myFrequency) {
231  writeXMLOutput();
232  }
233  assert(!invalidJam());
234  return myFrequency;
235 }
236 
237 
238 bool
240  if (mySegment->getBruttoOccupancy() == 0.) {
241  return false;
242  }
243  // maxSpeed reflects the calibration target
244  const bool toSlow = mySegment->getMeanSpeed() < 0.8 * mySegment->getEdge().getSpeedLimit();
245  return toSlow && remainingVehicleCapacity() < maximumInflow();
246 }
247 
248 
249 int
251  const SUMOVehicleParameter* pars = myCurrentStateInterval->vehicleParameter;
254 }
255 
256 
257 void
260 }
261 
262 
263 /****************************************************************************/
264 
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:228
virtual void deleteVehicle(SUMOVehicle *v, bool discard=false)
Deletes the vehicle.
long long int SUMOTime
Definition: SUMOTime.h:36
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:283
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:265
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:165
T MAX2(T a, T b)
Definition: StdDefs.h:76
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)
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:78
SUMOTime myFrequency
The frequeny with which to check for calibration.
Definition: MSCalibrator.h:255
#define TIME2STEPS(x)
Definition: SUMOTime.h:60
bool tryEmit(MESegment *s, MEVehicle *vehicle)
int myRemoved
The number of vehicles that were removed in the current interval.
Definition: MSCalibrator.h:257
int myClearedInJam
The number of vehicles that were removed when clearin a jam.
Definition: MSCalibrator.h:261
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:899
const MSEdge *const myEdge
the edge on which this calibrator lies
Definition: MSCalibrator.h:227
#define WRITE_WARNING(msg)
Definition: MsgHandler.h:241
The car-following model and parameter.
Definition: MSVehicleType.h:66
static OptionsCont & getOptions()
Retrieves the options.
Definition: OptionsCont.cpp:58
A road/street connecting two junctions.
Definition: MSEdge.h:75
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition: ToString.h:49
std::vector< AspiredState >::const_iterator myCurrentStateInterval
Iterator pointing to the current interval.
Definition: MSCalibrator.h:241
std::string routeid
The vehicle&#39;s route id.
void writeXMLOutput()
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:316
SUMOTime depart
The vehicle&#39;s departure time.
#define STEPS2TIME(x)
Definition: SUMOTime.h:58
double myDefaultSpeed
The default (maximum) speed on the segment.
Definition: MSCalibrator.h:269
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:263
std::vector< AspiredState > myIntervals
List of adaptation intervals.
Definition: MSCalibrator.h:239
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)
bool myHaveWarnedAboutClearingJam
The default (maximum) speed on the segment.
Definition: MSCalibrator.h:271
void removeDetector(MSMoveReminder *data)
Removes a data collector for a detector from this segment.
Definition: MESegment.cpp:223
void setDescription(const std::string &description)
MSVehicleType * getVType(const std::string &id=DEFAULT_VTYPE_ID, std::mt19937 *rng=0)
Returns the named vehicle type or a sample from the named distribution.
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
std::string myID
The name of the object.
Definition: Named.h:130
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:918
const MSRouteProbe *const myProbe
the route probe to retrieve routes from
Definition: MSCalibrator.h:233
void setEventTime(SUMOTime t, bool hasDelay=true)
Sets the (planned) time at which the vehicle leaves his current cell.
Definition: MEVehicle.h:207
Calibrates the flow on a segment to a specified one.
Definition: MSCalibrator.h:50
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:237
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:78
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:259
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