SUMO - Simulation of Urban MObility
METriggeredCalibrator.cpp
Go to the documentation of this file.
1 /****************************************************************************/
7 // Calibrates the flow on a segment to a specified one
8 /****************************************************************************/
9 // SUMO, Simulation of Urban MObility; see http://sumo.dlr.de/
10 // Copyright (C) 2001-2017 DLR (http://www.dlr.de/) and contributors
11 /****************************************************************************/
12 //
13 // This file is part of SUMO.
14 // SUMO is free software: you can redistribute it and/or modify
15 // it under the terms of the GNU General Public License as published by
16 // the Free Software Foundation, either version 3 of the License, or
17 // (at your option) any later version.
18 //
19 /****************************************************************************/
20 
21 
22 // ===========================================================================
23 // included modules
24 // ===========================================================================
25 #ifdef _MSC_VER
26 #include <windows_config.h>
27 #else
28 #include <config.h>
29 #endif
30 
31 #include <string>
32 #include <algorithm>
33 #include <cmath>
34 #include <microsim/MSGlobals.h>
35 #include <microsim/MSNet.h>
36 #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, pos, aXMLFilename, outputFilename, freq, length, probe, false),
65  mySegment(MSGlobals::gMesoNet->getSegmentForEdge(*edge, pos)) {
66  myEdgeMeanData.setDescription("meandata_calibrator_" + getID());
68 }
69 
70 
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 != 0) {
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 != 0) {
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 != 0 ? myProbe->getRoute() : 0;
167  if (route == 0) {
168  route = MSRoute::dictionary(pars->routeid);
169  }
170  if (route == 0) {
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();
187  newPars, route, vtype, false, false));
188  vehicle->setSegment(mySegment); // needed or vehicle will not be registered (XXX why?)
189  vehicle->setEventTime(currentTime); // XXX superfluous?
190  // move vehicle forward when the route does not begin at the calibrator's edge
191  const MSEdge* myedge = &mySegment->getEdge();
192  bool atDest = false;
193  while (vehicle->getEdge() != myedge) {
194  // let the vehicle move to the next edge
195  atDest = vehicle->moveRoutePointer();
196  }
197  // insert vehicle into the net
198  if (atDest || !tryEmit(mySegment, vehicle)) {
199  //std::cout << "F ";
201  break;
202  }
203  //std::cout << "I ";
204  myInserted++;
205  adaptedNum++;
206  }
207  }
208  //std::cout << " after:" << adaptedNum << "\n";
209  // we only remove vehicles once we really have to
210  while (totalWishedNum < adaptedNum) {
211  if (!mySegment->vaporizeAnyCar(currentTime)) {
212  // @bug: short edges may be jumped in a single step, giving us no chance to remove a vehicle
213  break;
214  }
215  myRemoved++;
216  adaptedNum--;
217  }
218  }
219  if (myCurrentStateInterval->end <= currentTime + myFrequency) {
220  writeXMLOutput();
221  }
222  assert(!invalidJam());
223  return myFrequency;
224 }
225 
226 
227 bool
229  if (mySegment->getBruttoOccupancy() == 0.) {
230  return false;
231  }
232  // maxSpeed reflects the calibration target
233  const bool toSlow = mySegment->getMeanSpeed() < 0.8 * mySegment->getEdge().getSpeedLimit();
234  return toSlow && remainingVehicleCapacity() < maximumInflow();
235 }
236 
237 
238 int
240  const SUMOVehicleParameter* pars = myCurrentStateInterval->vehicleParameter;
243 }
244 
245 
246 void
249 }
250 
251 
252 /****************************************************************************/
253 
MESegment * getNextSegment() const
Returns the following segment on the same edge (0 if it is the last).
Definition: MESegment.h:157
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:216
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:52
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:613
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:288
Writes routes of vehicles passing a certain edge.
Definition: MSRouteProbe.h:68
bool myDidSpeedAdaption
The information whether speed was adapted in the current interval.
Definition: MSCalibrator.h:247
const SUMOVehicleParameter & getParameter() const
Returns the vehicle&#39;s parameter (including departure definition)
std::string time2string(SUMOTime t)
Definition: SUMOTime.cpp:60
static MSNet * getInstance()
Returns the pointer to the unique instance of MSNet (singleton).
Definition: MSNet.cpp:158
T MAX2(T a, T b)
Definition: StdDefs.h:70
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:40
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:66
SUMOTime myFrequency
The frequeny with which to check for calibration.
Definition: MSCalibrator.h:237
#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:239
int myClearedInJam
The number of vehicles that were removed when clearin a jam.
Definition: MSCalibrator.h:243
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:824
const MSEdge *const myEdge
the edge on which this calibrator lies
Definition: MSCalibrator.h:211
#define WRITE_WARNING(msg)
Definition: MsgHandler.h:200
The car-following model and parameter.
Definition: MSVehicleType.h:74
static OptionsCont & getOptions()
Retrieves the options.
Definition: OptionsCont.cpp:65
A road/street connecting two junctions.
Definition: MSEdge.h:80
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition: ToString.h:56
std::vector< AspiredState >::const_iterator myCurrentStateInterval
Iterator pointing to the current interval.
Definition: MSCalibrator.h:223
std::string routeid
The vehicle&#39;s route id.
void writeXMLOutput()
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:310
virtual SUMOVehicle * buildVehicle(SUMOVehicleParameter *defs, const MSRoute *route, const MSVehicleType *type, const bool ignoreStopErrors, const bool fromRouteFile=true)
Builds a vehicle, increases the number of built vehicles.
SUMOTime depart
The vehicle&#39;s departure time.
#define STEPS2TIME(x)
Definition: SUMOTime.h:65
double myDefaultSpeed
The default (maximum) speed on the segment.
Definition: MSCalibrator.h:251
void addDetector(MSMoveReminder *data)
Adds a data collector for a detector to this segment.
Definition: MESegment.cpp:205
bool mySpeedIsDefault
The information whether the speed adaption has been reset.
Definition: MSCalibrator.h:245
std::vector< AspiredState > myIntervals
List of adaptation intervals.
Definition: MSCalibrator.h:221
double getBruttoOccupancy() const
Returns the occupany of the segment (the sum of the vehicle lengths + minGaps)
Definition: MESegment.h:173
bool vaporizeAnyCar(SUMOTime currentTime)
tries to remove any car from this segment
Definition: MESegment.cpp:567
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:253
void removeDetector(MSMoveReminder *data)
Removes a data collector for a detector from this segment.
Definition: MESegment.cpp:216
void setDescription(const std::string &description)
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:380
std::string myID
The name of the object.
Definition: Named.h:136
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:57
bool invalidJam() const
returns whether the segment is jammed although it should not be
static MELoop * gMesoNet
mesoscopic simulation infrastructure
Definition: MSGlobals.h:113
void setMaxSpeed(double val) const
Sets a new maximum speed for all lanes (used by TraCI and MSCalibrator)
Definition: MSEdge.cpp:843
const MSRouteProbe *const myProbe
the route probe to retrieve routes from
Definition: MSCalibrator.h:215
void setEventTime(SUMOTime t, bool hasDelay=true)
Sets the (planned) time at which the vehicle leaves his current cell.
Definition: MEVehicle.h:195
Calibrates the flow on a segment to a specified one.
Definition: MSCalibrator.h:57
long long int SUMOTime
Definition: TraCIDefs.h:52
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:219
void prepareDetectorForWriting(MSMoveReminder &data)
Updates data of a detector for all vehicle queues.
Definition: MESegment.cpp:247
bool isCurrentStateActive(SUMOTime time)
int remainingVehicleCapacity(const double vehLength) const
return the remaining physical space on this segment
Definition: MESegment.h:356
MSVehicleType * getVType(const std::string &id=DEFAULT_VTYPE_ID, MTRand *rng=0)
Returns the named vehicle type or a sample from the named distribution.
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:271
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:313
bool contains(const MSEdge *const edge) const
Definition: MSRoute.h:110
int myInserted
The number of vehicles that were inserted in the current interval.
Definition: MSCalibrator.h:241
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:118