Eclipse SUMO - Simulation of Urban MObility
MSDelayBasedTrafficLightLogic.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-2022 German Aerospace Center (DLR) and others.
4 // This program and the accompanying materials are made available under the
5 // terms of the Eclipse Public License 2.0 which is available at
6 // https://www.eclipse.org/legal/epl-2.0/
7 // This Source Code may also be made available under the following Secondary
8 // Licenses when the conditions for such availability set forth in the Eclipse
9 // Public License 2.0 are satisfied: GNU General Public License, version 2
10 // or later which is available at
11 // https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
12 // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
13 /****************************************************************************/
18 // An actuated traffic light logic based on time delay of approaching vehicles
19 /****************************************************************************/
20 #include <config.h>
21 
22 #include <cassert>
23 #include <vector>
24 #include <microsim/MSGlobals.h>
25 #include <microsim/MSNet.h>
29 #include <microsim/MSLane.h>
32 
33 #define INVALID_POSITION std::numeric_limits<double>::max()
34 
35 // ===========================================================================
36 // parameter defaults definitions
37 // ===========================================================================
38 
39 //#define DEBUG_TIMELOSS_CONTROL
40 
41 // ===========================================================================
42 // method definitions
43 // ===========================================================================
45  const std::string& id, const std::string& programID,
46  const SUMOTime offset,
47  const Phases& phases,
48  int step, SUMOTime delay,
49  const std::map<std::string, std::string>& parameter,
50  const std::string& basePath) :
51  MSSimpleTrafficLightLogic(tlcontrol, id, programID, offset, TrafficLightType::DELAYBASED, phases, step, delay, parameter) {
52 #ifdef DEBUG_TIMELOSS_CONTROL
53  std::cout << "Building delay based tls logic '" << id << "'" << std::endl;
54 #endif
55  myShowDetectors = StringUtils::toBool(getParameter("show-detectors", "false"));
56  myDetectionRange = StringUtils::toDouble(getParameter("detectorRange", toString(OptionsCont::getOptions().getFloat("tls.delay_based.detector-range"))));
58  myFile = FileHelpers::checkForRelativity(getParameter("file", "NUL"), basePath);
60  myVehicleTypes = getParameter("vTypes", "");
61 #ifdef DEBUG_TIMELOSS_CONTROL
62  std::cout << "show-detectors: " << myShowDetectors
63  << " detectorRange: " << myDetectionRange
64  << " minTimeLoss: " << myTimeLossThreshold
65  << " file: " << myFile
66  << " freq: " << myFreq
67  << " vTypes: " << myVehicleTypes
68  << std::endl;
69 #endif
70 }
71 
72 
73 void
76  assert(myLanes.size() > 0);
77  LaneVectorVector::const_iterator i2;
78  LaneVector::const_iterator i;
79  // build the E2 detectors
80  for (i2 = myLanes.begin(); i2 != myLanes.end(); ++i2) {
81  const LaneVector& lanes = *i2;
82  for (i = lanes.begin(); i != lanes.end(); i++) {
83  MSLane* lane = (*i);
84  if (noVehicles(lane->getPermissions())) {
85  // do not build detectors on green verges or sidewalks
86  continue;
87  }
88  // Build the detectors and register them at the detector control
89  if (myLaneDetectors.find(lane) == myLaneDetectors.end()) {
90  MSE2Collector* det = nullptr;
91  const std::string customID = getParameter(lane->getID());
92  if (customID != "") {
94  if (det == nullptr) {
95  WRITE_ERROR("Unknown laneAreaDetector '" + customID + "' given as custom detector for delay_based tlLogic '" + getID() + "', program '" + getProgramID() + ".");
96  continue;
97  }
99  } else {
100  std::string id = "TLS" + myID + "_" + myProgramID + "_E2CollectorOn_" + lane->getID();
103  }
104  myLaneDetectors[lane] = det;
105  }
106  }
107  }
108 }
109 
110 
111 
113 
114 // ------------ Switching and setting current rows
115 
116 
117 SUMOTime
118 MSDelayBasedTrafficLightLogic::proposeProlongation(const SUMOTime actDuration, const SUMOTime maxDuration, bool& othersEmpty) {
119 #ifdef DEBUG_TIMELOSS_CONTROL
120  std::cout << "\n" << SIMTIME << " MSDelayBasedTrafficLightLogic::proposeProlongation() for TLS '" << this->getID() << "' (current phase = " << myStep << ")" << std::endl;
121 #endif
122  SUMOTime prolongation = 0;
123  const std::string& state = getCurrentPhaseDef().getState();
124  // iterate over green lanes, eventually increase the proposed prolongationTime to the estimated passing time for each lane.
125  for (int i = 0; i < (int) state.size(); i++) {
126  // this lane index corresponds to a non-green time
127  bool igreen = state[i] == LINKSTATE_TL_GREEN_MAJOR || state[i] == LINKSTATE_TL_GREEN_MINOR;
128  for (const MSLane* const lane : getLanesAt(i)) {
129  std::map<const MSLane*, MSE2Collector*>::iterator it = myLaneDetectors.find(lane);
130  if (it == myLaneDetectors.end()) {
131 #ifdef DEBUG_TIMELOSS_CONTROL
132  // no detector for this lane!? maybe noVehicles allowed
133  std::cout << "no detector on lane '" << lane->getID() << std::endl;
134 #endif
135  continue;
136  }
137  const std::vector<MSE2Collector::VehicleInfo*> vehInfos = it->second->getCurrentVehicles();
138 #ifdef DEBUG_TIMELOSS_CONTROL
139  int nrVehs = 0; // count vehicles on detector
140 #endif
141  if (igreen) {
142  // green phase
143  for (const MSE2Collector::VehicleInfo* const iv : vehInfos) {
144  if (iv->accumulatedTimeLoss > myTimeLossThreshold && iv->distToDetectorEnd > 0) {
145  const SUMOTime estimatedTimeToJunction = TIME2STEPS((iv->distToDetectorEnd) / lane->getSpeedLimit());
146  if (actDuration + estimatedTimeToJunction <= maxDuration && getLatest() > 0) {
147  // only prolong if vehicle has a chance to pass until max duration is reached
148  prolongation = MAX2(prolongation, estimatedTimeToJunction);
149  }
150 #ifdef DEBUG_TIMELOSS_CONTROL
151  nrVehs++;
152 #endif
153 
154 #ifdef DEBUG_TIMELOSS_CONTROL
155  std::cout << "vehicle '" << iv->id << "' with accumulated timeloss: " << iv->accumulatedTimeLoss
156  << "\nestimated passing time: " << estimatedTimeToJunction << std::endl;
157  } else {
158  std::string reason = iv->accumulatedTimeLoss <= myTimeLossThreshold ? " (time loss below threshold)" : " (front already left detector)";
159  std::cout << "disregarded: (vehicle '" << iv->id << "' with accumulated timeloss " << iv->accumulatedTimeLoss << ")" << reason << std::endl;
160 #endif
161  }
162  }
163  } else {
164  // non-green phase
165  if (vehInfos.size() > 0) {
166  // here is a car on a non-green approach
167  othersEmpty = false;
168  if (actDuration >= getCurrentPhaseDef().maxDuration) {
169 #ifdef DEBUG_TIMELOSS_CONTROL
170  std::cout << "Actual duration exceeds maxDuration and a vehicle is on concurrent approach: " << nrVehs << std::endl;
171 #endif
172  // don't prolong
173  return 0;
174  }
175  break;
176  }
177 #ifdef DEBUG_TIMELOSS_CONTROL
178  std::cout << "Number of current vehicles on detector: " << nrVehs << std::endl;
179 #endif
180  }
181  }
182  }
183 #ifdef DEBUG_TIMELOSS_CONTROL
184  std::cout << "Proposed prolongation (maximal estimated passing time): " << prolongation << std::endl; // debug
185 #endif
186  return prolongation;
187 }
188 
189 
190 SUMOTime
192  /* check if the actual phase should be prolonged */
193  const MSPhaseDefinition& currentPhase = getCurrentPhaseDef();
194  // time since last switch
195  const SUMOTime actDuration = MSNet::getInstance()->getCurrentTimeStep() - currentPhase.myLastSwitch;
196 
197 #ifdef DEBUG_TIMELOSS_CONTROL
198  std::cout << "last switch = " << currentPhase.myLastSwitch
199  << "\nactDuration = " << actDuration
200  << "\nmaxDuration = " << currentPhase.maxDuration
201  << std::endl;
202 #endif
203 
204  // flag whether to prolong or not
205  if (currentPhase.isGreenPhase() && !MSGlobals::gUseMesoSim) {
206  bool othersEmpty = true; // whether no vehicles are present on concurrent approaches
207  SUMOTime proposedProlongation = proposeProlongation(actDuration, currentPhase.maxDuration, othersEmpty);
208 
209 #ifdef DEBUG_TIMELOSS_CONTROL
210  std::cout << "othersEmpty = " << othersEmpty
211  << std::endl;
212 #endif
213 
214  // keep this phase a little longer?
215  bool prolong = othersEmpty || actDuration < currentPhase.maxDuration;
216  // assure minimal duration
217  proposedProlongation = MAX3(SUMOTime(0), proposedProlongation, currentPhase.minDuration - actDuration);
218  if (othersEmpty) {
219  // prolong by one second if no vehicles on other approaches
220  proposedProlongation = MAX2(proposedProlongation, TIME2STEPS(1.));
221  } else {
222  // vehicles are present on other approaches -> prolong no further than the max green time
223  proposedProlongation = MIN2(proposedProlongation, MAX2(SUMOTime(0), currentPhase.maxDuration - actDuration));
224  }
225 
226 #ifdef DEBUG_TIMELOSS_CONTROL
227  std::cout << "Proposed prolongation = " << proposedProlongation << std::endl;
228 #endif
229 
230  prolong = proposedProlongation > 0;
231  if (prolong) {
232  // check again after the prolonged period (must be positive...)
233  // XXX: Can it be harmful not to return a duration of integer seconds?
234  return proposedProlongation;
235  }
236  }
237  // Don't prolong... switch to the next phase
238  const SUMOTime prevStart = myPhases[myStep]->myLastSwitch;
239  myStep = (myStep + 1) % (int)myPhases.size();
240  myPhases[myStep]->myLastSwitch = SIMSTEP;
241  MSPhaseDefinition* newPhase = myPhases[myStep];
242  //stores the time the phase started
244  // set the next event
245  return MAX2(newPhase->minDuration, getEarliest(prevStart));
246 }
247 
248 void
250  myShowDetectors = show;
251  for (auto& item : myLaneDetectors) {
252  item.second->setVisible(myShowDetectors);
253  }
254 }
255 
256 
257 
258 /****************************************************************************/
#define INVALID_POSITION
@ DU_TL_CONTROL
#define WRITE_ERROR(msg)
Definition: MsgHandler.h:288
#define SIMSTEP
Definition: SUMOTime.h:59
#define SIMTIME
Definition: SUMOTime.h:60
#define TIME2STEPS(x)
Definition: SUMOTime.h:55
long long int SUMOTime
Definition: SUMOTime.h:32
bool noVehicles(SVCPermissions permissions)
Returns whether an edge with the given permission forbids vehicles.
TrafficLightType
@ SUMO_TAG_LANE_AREA_DETECTOR
alternative tag for e2 detector
@ LINKSTATE_TL_GREEN_MAJOR
The link has green light, may pass.
@ LINKSTATE_TL_GREEN_MINOR
The link has green light, has to brake.
T MIN2(T a, T b)
Definition: StdDefs.h:74
T MAX2(T a, T b)
Definition: StdDefs.h:80
T MAX3(T a, T b, T c)
Definition: StdDefs.h:94
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition: ToString.h:46
static std::string checkForRelativity(const std::string &filename, const std::string &basePath)
Returns the path from a configuration so that it is accessable from the current working directory.
double myDetectionRange
Range of the connected detector, which provides the information on approaching vehicles.
MSDelayBasedTrafficLightLogic(MSTLLogicControl &tlcontrol, const std::string &id, const std::string &programID, const SUMOTime offset, const MSSimpleTrafficLightLogic::Phases &phases, int step, SUMOTime delay, const std::map< std::string, std::string > &parameter, const std::string &basePath)
Constructor.
std::string myVehicleTypes
Whether detector output separates by vType.
void init(NLDetectorBuilder &nb)
Initializes the tls with information about incoming lanes.
SUMOTime myFreq
The frequency for aggregating detector output.
std::map< const MSLane *, MSE2Collector * > myLaneDetectors
A map from lanes to the corresponding lane detectors.
bool myShowDetectors
Whether the detectors shall be shown in the GUI.
std::string myFile
The output file for generated detectors.
SUMOTime proposeProlongation(const SUMOTime actDuration, const SUMOTime maxDuration, bool &othersEmpty)
The returned, proposed prolongation for the green phase is oriented on the largest estimated passing ...
SUMOTime trySwitch()
Switches to the next phase, if possible.
const NamedObjectCont< MSDetectorFileOutput * > & getTypedDetectors(SumoXMLTag type) const
Returns the list of detectors of the given type.
void add(SumoXMLTag type, MSDetectorFileOutput *d, const std::string &device, SUMOTime interval, SUMOTime begin=-1)
Adds a detector/output combination into the containers.
An areal detector corresponding to a sequence of consecutive lanes.
Definition: MSE2Collector.h:79
virtual void setVisible(bool)
static bool gUseMesoSim
Definition: MSGlobals.h:94
Representation of a lane in the micro simulation.
Definition: MSLane.h:82
SVCPermissions getPermissions() const
Returns the vehicle class permissions for this lane.
Definition: MSLane.h:549
double getLength() const
Returns the lane's length.
Definition: MSLane.h:541
static MSNet * getInstance()
Returns the pointer to the unique instance of MSNet (singleton).
Definition: MSNet.cpp:174
MSDetectorControl & getDetectorControl()
Returns the detector control.
Definition: MSNet.h:439
SUMOTime getCurrentTimeStep() const
Returns the current simulation step.
Definition: MSNet.h:318
The definition of a single phase of a tls logic.
const std::string & getState() const
Returns the state within this phase.
SUMOTime maxDuration
The maximum duration of the phase.
SUMOTime minDuration
The minimum duration of the phase.
SUMOTime myLastSwitch
Stores the timestep of the last on-switched of the phase.
bool isGreenPhase() const
Returns whether this phase is a pure "green" phase.
A fixed traffic light logic.
SUMOTime getLatest() const
the maximum duratin for keeping the current phase when considering 'latestEnd'
Phases myPhases
The list of phases this logic uses.
SUMOTime getEarliest(SUMOTime prevStart) const
the minimum duration for keeping the current phase when considering 'earliestEnd'
const MSPhaseDefinition & getCurrentPhaseDef() const
Returns the definition of the current phase.
A class that stores and controls tls and switching of their programs.
std::vector< MSLane * > LaneVector
Definition of the list of arrival lanes subjected to this tls.
const std::string myProgramID
The id of the logic.
LaneVectorVector myLanes
The list of LaneVectors; each vector contains the incoming lanes that belong to the same link index.
const LaneVector & getLanesAt(int i) const
Returns the list of lanes that are controlled by the signals at the given position.
std::vector< MSPhaseDefinition * > Phases
Definition of a list of phases, being the junction logic.
virtual void init(NLDetectorBuilder &nb)
Initialises the tls with information about incoming lanes.
const std::string & getProgramID() const
Returns this tl-logic's id.
Builds detectors for microsim.
virtual MSE2Collector * createE2Detector(const std::string &id, DetectorUsage usage, MSLane *lane, double pos, double endPos, double length, SUMOTime haltingTimeThreshold, double haltingSpeedThreshold, double jamDistThreshold, const std::string &vTypes, int detectPersons, bool showDetector=true)
Creates a MSE2Collector instance, overridden by GUIE2Collector::createE2Detector()
std::string myID
The name of the object.
Definition: Named.h:125
const std::string & getID() const
Returns the id.
Definition: Named.h:74
T get(const std::string &id) const
Retrieves an item.
static OptionsCont & getOptions()
Retrieves the options.
Definition: OptionsCont.cpp:58
virtual const std::string getParameter(const std::string &key, const std::string defaultValue="") const
Returns the value for a given key.
static double toDouble(const std::string &sData)
converts a string into the double value described by it by calling the char-type converter
static bool toBool(const std::string &sData)
converts a string into the bool value described by it by calling the char-type converter
A VehicleInfo stores values that are tracked for the individual vehicles on the detector,...
Definition: MSE2Collector.h:85