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-2017 German Aerospace Center (DLR) and others.
4 /****************************************************************************/
5 //
6 // This program and the accompanying materials
7 // are made available under the terms of the Eclipse Public License v2.0
8 // which accompanies this distribution, and is available at
9 // http://www.eclipse.org/legal/epl-v20.html
10 //
11 /****************************************************************************/
17 // Calibrates the flow on a segment to a specified one
18 /****************************************************************************/
19 
20 
21 // ===========================================================================
22 // included modules
23 // ===========================================================================
24 #ifdef _MSC_VER
25 #include <windows_config.h>
26 #else
27 #include <config.h>
28 #endif
29 
30 #include <string>
31 #include <algorithm>
32 #include <cmath>
33 #include <microsim/MSGlobals.h>
34 #include <microsim/MSNet.h>
35 #include <microsim/MSEdge.h>
40 #include <utils/common/ToString.h>
43 #include <utils/xml/XMLSubSys.h>
49 #include "MELoop.h"
50 #include "MESegment.h"
51 #include "MEVehicle.h"
52 #include "METriggeredCalibrator.h"
53 
54 
55 // ===========================================================================
56 // method definitions
57 // ===========================================================================
59  const MSEdge* const edge, const double pos,
60  const std::string& aXMLFilename,
61  const std::string& outputFilename,
62  const SUMOTime freq, const double length,
63  const MSRouteProbe* probe) :
64  MSCalibrator(id, edge, (MSLane*)0, pos, aXMLFilename, outputFilename, freq, length, probe, false),
65  mySegment(MSGlobals::gMesoNet->getSegmentForEdge(*edge, pos)) {
66  myEdgeMeanData.setDescription("meandata_calibrator_" + getID());
68 }
69 
70 
72  if (myCurrentStateInterval != myIntervals.end()) {
73  // need to do it here and not in MSCalibrator because otherwise meandata is gone
75  // but avoid to call it again in MSCalibrator
77  }
79 }
80 
81 
82 bool
84  if (s->initialise(vehicle, vehicle->getParameter().depart)) {
85  if (!MSNet::getInstance()->getVehicleControl().addVehicle(vehicle->getID(), vehicle)) {
86  throw ProcessError("Emission of vehicle '" + vehicle->getID() + "' in calibrator '" + getID() + "'failed!");
87  }
88  return true;
89  }
90  return false;
91 }
92 
93 
96  // get current simulation values (valid for the last simulation second)
97  // XXX could we miss vehicle movements if this is called less often than every DELTA_T (default) ?
99 
100  // check whether an adaptation value exists
101  if (isCurrentStateActive(currentTime)) {
102  // all happens in isCurrentStateActive()
103  } else {
104  myEdgeMeanData.reset(); // discard collected values
105  if (!mySpeedIsDefault) {
106  // if not, reset adaptation values
109  const double jamThresh = OptionsCont::getOptions().getFloat("meso-jam-threshold");
110  while (first != 0) {
111  first->setSpeed(myDefaultSpeed, currentTime, jamThresh);
112  first = first->getNextSegment();
113  }
114  mySpeedIsDefault = true;
115  }
116  if (myCurrentStateInterval == myIntervals.end()) {
117  // keep calibrator alive but do not call again
118  return TIME2STEPS(86400);
119  }
120  return myFrequency;
121  }
122  // we are active
126  while (first != 0) {
127  first->setSpeed(myCurrentStateInterval->v, currentTime, -1);
128  first = first->getNextSegment();
129  }
130  mySpeedIsDefault = false;
131  myDidSpeedAdaption = true;
132  }
133  // clear invalid jams
134  bool hadInvalidJam = false;
135  while (invalidJam()) {
136  hadInvalidJam = true;
138  WRITE_WARNING("Clearing jam at calibrator '" + myID + "' at time " + time2string(currentTime));
139  }
140  // remove one vehicle currently on the segment
141  if (mySegment->vaporizeAnyCar(currentTime)) {
142  myClearedInJam++;
143  } else {
145  // this frequenly happens for very short edges
146  WRITE_WARNING("Could not clear jam at calibrator '" + myID + "' at time " + time2string(currentTime));
147  }
148  break;
149  }
151  }
152  if (myCurrentStateInterval->q >= 0) {
153  // flow calibration starts here ...
154  // compute the number of vehicles that should have passed the calibrator within the time
155  // rom begin of the interval
156  const double totalHourFraction = STEPS2TIME(myCurrentStateInterval->end - myCurrentStateInterval->begin) / (double) 3600.;
157  const int totalWishedNum = (int)std::floor(myCurrentStateInterval->q * totalHourFraction + 0.5); // round to closest int
158  int adaptedNum = passed() + myClearedInJam;
159  if (!hadInvalidJam) {
160  // only add vehicles if we do not have an invalid upstream jam to prevent spill-back
161  const double hourFraction = STEPS2TIME(currentTime - myCurrentStateInterval->begin + DELTA_T) / (double) 3600.;
162  const int wishedNum = (int)std::floor(myCurrentStateInterval->q * hourFraction + 0.5); // round to closest int
163  // only the difference between inflow and aspiredFlow should be added, thus
164  // we should not count vehicles vaporized from a jam here
165  // if we have enough time left we can add missing vehicles later
166  const int relaxedInsertion = (int)std::floor(STEPS2TIME(myCurrentStateInterval->end - currentTime) / 3);
167  const int insertionSlack = MAX2(0, adaptedNum + relaxedInsertion - totalWishedNum);
168  // increase number of vehicles
169  //std::cout << "time:" << STEPS2TIME(currentTime) << " w:" << wishedNum << " s:" << insertionSlack << " before:" << adaptedNum;
170  while (wishedNum > adaptedNum + insertionSlack && remainingVehicleCapacity() > maximumInflow()) {
171  SUMOVehicleParameter* pars = myCurrentStateInterval->vehicleParameter;
172  const MSRoute* route = myProbe != 0 ? myProbe->getRoute() : 0;
173  if (route == 0) {
174  route = MSRoute::dictionary(pars->routeid);
175  }
176  if (route == 0) {
177  WRITE_WARNING("No valid routes in calibrator '" + myID + "'.");
178  break;
179  }
180  if (!route->contains(myEdge)) {
181  WRITE_WARNING("Route '" + route->getID() + "' in calibrator '" + myID + "' does not contain edge '" + myEdge->getID() + "'.");
182  break;
183  }
185  assert(route != 0 && vtype != 0);
186  // build the vehicle
187  const SUMOTime depart = mySegment->getNextInsertionTime(currentTime);
188  SUMOVehicleParameter* newPars = new SUMOVehicleParameter(*pars);
189  newPars->id = myID + "." + toString(depart) + "." + toString(myInserted);
190  newPars->depart = depart;
191  newPars->routeid = route->getID();
192  MEVehicle* vehicle;
193  try {
194  vehicle = static_cast<MEVehicle*>(MSNet::getInstance()->getVehicleControl().buildVehicle(
195  newPars, route, vtype, false, false));
196  } catch (const ProcessError& e) {
198  WRITE_WARNING(e.what());
199  vehicle = 0;
200  break;
201  } else {
202  throw e;
203  }
204  }
205  vehicle->setSegment(mySegment); // needed or vehicle will not be registered (XXX why?)
206  vehicle->setEventTime(currentTime); // XXX superfluous?
207  // move vehicle forward when the route does not begin at the calibrator's edge
208  const MSEdge* myedge = &mySegment->getEdge();
209  bool atDest = false;
210  while (vehicle->getEdge() != myedge) {
211  // let the vehicle move to the next edge
212  atDest = vehicle->moveRoutePointer();
213  }
214  // insert vehicle into the net
215  if (atDest || !tryEmit(mySegment, vehicle)) {
216  //std::cout << "F ";
218  break;
219  }
220  //std::cout << "I ";
221  myInserted++;
222  adaptedNum++;
223  }
224  }
225  //std::cout << " after:" << adaptedNum << "\n";
226  // we only remove vehicles once we really have to
227  while (totalWishedNum < adaptedNum) {
228  if (!mySegment->vaporizeAnyCar(currentTime)) {
229  // @bug: short edges may be jumped in a single step, giving us no chance to remove a vehicle
230  break;
231  }
232  myRemoved++;
233  adaptedNum--;
234  }
235  }
236  if (myCurrentStateInterval->end <= currentTime + myFrequency) {
237  writeXMLOutput();
238  }
239  assert(!invalidJam());
240  return myFrequency;
241 }
242 
243 
244 bool
246  if (mySegment->getBruttoOccupancy() == 0.) {
247  return false;
248  }
249  // maxSpeed reflects the calibration target
250  const bool toSlow = mySegment->getMeanSpeed() < 0.8 * mySegment->getEdge().getSpeedLimit();
251  return toSlow && remainingVehicleCapacity() < maximumInflow();
252 }
253 
254 
255 int
257  const SUMOVehicleParameter* pars = myCurrentStateInterval->vehicleParameter;
260 }
261 
262 
263 void
266 }
267 
268 
269 /****************************************************************************/
270 
MESegment * getNextSegment() const
Returns the following segment on the same edge (0 if it is the last).
Definition: MESegment.h:156
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:220
virtual void deleteVehicle(SUMOVehicle *v, bool discard=false)
Deletes the vehicle.
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:51
MESegment * getSegmentForEdge(const MSEdge &e, double pos=0)
Get the segment for a given edge at a given position.
Definition: MELoop.cpp:289
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:612
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:287
Writes routes of vehicles passing a certain edge.
Definition: MSRouteProbe.h:67
bool myDidSpeedAdaption
The information whether speed was adapted in the current interval.
Definition: MSCalibrator.h:271
const SUMOVehicleParameter & getParameter() const
Returns the vehicle&#39;s parameter (including departure definition)
std::string time2string(SUMOTime t)
Definition: SUMOTime.cpp:59
static MSNet * getInstance()
Returns the pointer to the unique instance of MSNet (singleton).
Definition: MSNet.cpp:167
T MAX2(T a, T b)
Definition: StdDefs.h:73
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:39
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:65
SUMOTime myFrequency
The frequeny with which to check for calibration.
Definition: MSCalibrator.h:261
#define TIME2STEPS(x)
Definition: SUMOTime.h:66
bool tryEmit(MESegment *s, MEVehicle *vehicle)
int myRemoved
The number of vehicles that were removed in the current interval.
Definition: MSCalibrator.h:263
int myClearedInJam
The number of vehicles that were removed when clearin a jam.
Definition: MSCalibrator.h:267
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:846
const MSEdge *const myEdge
the edge on which this calibrator lies
Definition: MSCalibrator.h:233
#define WRITE_WARNING(msg)
Definition: MsgHandler.h:199
The car-following model and parameter.
Definition: MSVehicleType.h:72
static OptionsCont & getOptions()
Retrieves the options.
Definition: OptionsCont.cpp:64
A road/street connecting two junctions.
Definition: MSEdge.h:80
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition: ToString.h:55
std::vector< AspiredState >::const_iterator myCurrentStateInterval
Iterator pointing to the current interval.
Definition: MSCalibrator.h:247
std::string routeid
The vehicle&#39;s route id.
void writeXMLOutput()
static bool gCheckRoutes
Definition: MSGlobals.h:85
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:306
SUMOTime depart
The vehicle&#39;s departure time.
#define STEPS2TIME(x)
Definition: SUMOTime.h:64
double myDefaultSpeed
The default (maximum) speed on the segment.
Definition: MSCalibrator.h:275
void addDetector(MSMoveReminder *data)
Adds a data collector for a detector to this segment.
Definition: MESegment.cpp:204
bool mySpeedIsDefault
The information whether the speed adaption has been reset.
Definition: MSCalibrator.h:269
std::vector< AspiredState > myIntervals
List of adaptation intervals.
Definition: MSCalibrator.h:245
double getBruttoOccupancy() const
Returns the occupany of the segment (the sum of the vehicle lengths + minGaps)
Definition: MESegment.h:172
bool vaporizeAnyCar(SUMOTime currentTime)
tries to remove any car from this segment
Definition: MESegment.cpp:566
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:277
void removeDetector(MSMoveReminder *data)
Removes a data collector for a detector from this segment.
Definition: MESegment.cpp:215
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:141
SUMOTime getNextInsertionTime(SUMOTime earliestEntry) const
return a time after earliestEntry at which a vehicle may be inserted at full speed ...
Definition: MESegment.cpp:379
std::string myID
The name of the object.
Definition: Named.h:135
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:56
bool invalidJam() const
returns whether the segment is jammed although it should not be
static MELoop * gMesoNet
mesoscopic simulation infrastructure
Definition: MSGlobals.h:112
void setMaxSpeed(double val) const
Sets a new maximum speed for all lanes (used by TraCI and MSCalibrator)
Definition: MSEdge.cpp:865
const MSRouteProbe *const myProbe
the route probe to retrieve routes from
Definition: MSCalibrator.h:239
void setEventTime(SUMOTime t, bool hasDelay=true)
Sets the (planned) time at which the vehicle leaves his current cell.
Definition: MEVehicle.h:199
Calibrates the flow on a segment to a specified one.
Definition: MSCalibrator.h:56
long long int SUMOTime
Definition: TraCIDefs.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:243
void prepareDetectorForWriting(MSMoveReminder &data)
Updates data of a detector for all vehicle queues.
Definition: MESegment.cpp:246
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:355
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:270
Representation of a lane in the micro simulation.
Definition: MSLane.h:77
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:312
bool contains(const MSEdge *const edge) const
Definition: MSRoute.h:109
int myInserted
The number of vehicles that were inserted in the current interval.
Definition: MSCalibrator.h:265
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:117