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.dev/sumo
3 // Copyright (C) 2001-2024 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>
26 #include <microsim/MSGlobals.h>
27 #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 Parameterised::Map& 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  myExtendMaxDur = StringUtils::toBool(getParameter("extendMaxDur", "false"));
62 #ifdef DEBUG_TIMELOSS_CONTROL
63  std::cout << "show-detectors: " << myShowDetectors
64  << " detectorRange: " << myDetectionRange
65  << " minTimeLoss: " << myTimeLossThreshold
66  << " file: " << myFile
67  << " freq: " << myFreq
68  << " vTypes: " << myVehicleTypes
69  << std::endl;
70 #endif
71 }
72 
73 
74 void
77  assert(myLanes.size() > 0);
78  LaneVectorVector::const_iterator i2;
79  LaneVector::const_iterator i;
80  // build the E2 detectors
81  for (i2 = myLanes.begin(); i2 != myLanes.end(); ++i2) {
82  const LaneVector& lanes = *i2;
83  for (i = lanes.begin(); i != lanes.end(); i++) {
84  MSLane* lane = (*i);
85  if (noVehicles(lane->getPermissions())) {
86  // do not build detectors on green verges or sidewalks
87  continue;
88  }
89  // Build the detectors and register them at the detector control
90  if (myLaneDetectors.find(lane) == myLaneDetectors.end()) {
91  MSE2Collector* det = nullptr;
92  const std::string customID = getParameter(lane->getID());
93  if (customID != "") {
95  if (det == nullptr) {
96  WRITE_ERRORF(TL("Unknown laneAreaDetector '%' given as custom detector for delay_based tlLogic '%', program '%."), customID, getID(), getProgramID());
97  continue;
98  }
100  } else {
101  // check whether the lane (or unamibiguous lane sequence) is long enough and avoid overlapping detectors
102  double length = lane->getLength();
103  MSLane* firstLane = lane;
104  while (length < myDetectionRange && firstLane->getIncomingLanes().size() == 1
105  && firstLane->getIncomingLanes().front().viaLink->getCorrespondingEntryLink()->getTLLogic() == nullptr) {
106  firstLane = firstLane->getLogicalPredecessorLane();
107  if (firstLane->getLinkCont().size() > 1) {
108  break;
109  }
110  length += firstLane->getLength();
111  }
112  length = MIN2(length, myDetectionRange);
113 
114  std::string id = "TLS" + myID + "_" + myProgramID + "_E2CollectorOn_" + lane->getID();
115  det = nb.createE2Detector(id, DU_TL_CONTROL, lane, INVALID_POSITION, lane->getLength(), length, TIME2STEPS(1.0), 5.0/3.6, 10.0, "", myVehicleTypes, "", (int)PersonMode::NONE, myShowDetectors);
117  }
118  myLaneDetectors[lane] = det;
119  }
120  }
121  }
122 }
123 
124 
125 
127 
128 // ------------ Switching and setting current rows
129 
130 
131 SUMOTime
132 MSDelayBasedTrafficLightLogic::proposeProlongation(const SUMOTime actDuration, const SUMOTime maxDuration, bool& othersEmpty) {
133 #ifdef DEBUG_TIMELOSS_CONTROL
134  std::cout << "\n" << SIMTIME << " MSDelayBasedTrafficLightLogic::proposeProlongation() for TLS '" << this->getID() << "' (current phase = " << myStep << ")" << std::endl;
135 #endif
136  SUMOTime prolongation = 0;
137  const std::string& state = getCurrentPhaseDef().getState();
138  // iterate over green lanes, eventually increase the proposed prolongationTime to the estimated passing time for each lane.
139  for (int i = 0; i < (int) state.size(); i++) {
140  // this lane index corresponds to a non-green time
141  bool igreen = state[i] == LINKSTATE_TL_GREEN_MAJOR || state[i] == LINKSTATE_TL_GREEN_MINOR;
142  for (const MSLane* const lane : getLanesAt(i)) {
143  std::map<const MSLane*, MSE2Collector*>::iterator it = myLaneDetectors.find(lane);
144  if (it == myLaneDetectors.end()) {
145 #ifdef DEBUG_TIMELOSS_CONTROL
146  // no detector for this lane!? maybe noVehicles allowed
147  std::cout << "no detector on lane '" << lane->getID() << std::endl;
148 #endif
149  continue;
150  }
151  const std::vector<MSE2Collector::VehicleInfo*> vehInfos = it->second->getCurrentVehicles();
152 #ifdef DEBUG_TIMELOSS_CONTROL
153  int nrVehs = 0; // count vehicles on detector
154 #endif
155  if (igreen) {
156  // green phase
157  for (const MSE2Collector::VehicleInfo* const iv : vehInfos) {
158  if (iv->accumulatedTimeLoss > myTimeLossThreshold && iv->distToDetectorEnd > 0) {
159  const SUMOTime estimatedTimeToJunction = TIME2STEPS((iv->distToDetectorEnd) / lane->getSpeedLimit());
160  if (actDuration + estimatedTimeToJunction <= maxDuration && getLatest() > 0) {
161  // only prolong if vehicle has a chance to pass until max duration is reached
162  prolongation = MAX2(prolongation, estimatedTimeToJunction);
163  }
164 #ifdef DEBUG_TIMELOSS_CONTROL
165  nrVehs++;
166 #endif
167 
168 #ifdef DEBUG_TIMELOSS_CONTROL
169  std::cout << "vehicle '" << iv->id << "' with accumulated timeloss: " << iv->accumulatedTimeLoss
170  << "\nestimated passing time: " << estimatedTimeToJunction << std::endl;
171  } else {
172  std::string reason = iv->accumulatedTimeLoss <= myTimeLossThreshold ? " (time loss below threshold)" : " (front already left detector)";
173  std::cout << "disregarded: (vehicle '" << iv->id << "' with accumulated timeloss " << iv->accumulatedTimeLoss << ")" << reason << std::endl;
174 #endif
175  }
176  }
177  } else {
178  // non-green phase
179  if (vehInfos.size() > 0) {
180  // here is a car on a non-green approach
181  othersEmpty = false;
182  if (actDuration >= getCurrentPhaseDef().maxDuration) {
183 #ifdef DEBUG_TIMELOSS_CONTROL
184  std::cout << "Actual duration exceeds maxDuration and a vehicle is on concurrent approach: " << nrVehs << std::endl;
185 #endif
186  // don't prolong
187  return 0;
188  }
189  break;
190  }
191 #ifdef DEBUG_TIMELOSS_CONTROL
192  std::cout << "Number of current vehicles on detector: " << nrVehs << std::endl;
193 #endif
194  }
195  }
196  }
197 #ifdef DEBUG_TIMELOSS_CONTROL
198  std::cout << "Proposed prolongation (maximal estimated passing time): " << prolongation << std::endl; // debug
199 #endif
200  return prolongation;
201 }
202 
203 
204 SUMOTime
206  /* check if the actual phase should be prolonged */
207  const MSPhaseDefinition& currentPhase = getCurrentPhaseDef();
208  // time since last switch
209  const SUMOTime actDuration = MSNet::getInstance()->getCurrentTimeStep() - currentPhase.myLastSwitch;
210 
211 #ifdef DEBUG_TIMELOSS_CONTROL
212  std::cout << "last switch = " << currentPhase.myLastSwitch
213  << "\nactDuration = " << actDuration
214  << "\nmaxDuration = " << currentPhase.maxDuration
215  << std::endl;
216 #endif
217 
218  // flag whether to prolong or not
219  if (currentPhase.isGreenPhase() && !MSGlobals::gUseMesoSim) {
220  bool othersEmpty = true; // whether no vehicles are present on concurrent approaches
221  SUMOTime proposedProlongation = proposeProlongation(actDuration, currentPhase.maxDuration, othersEmpty);
222 
223 #ifdef DEBUG_TIMELOSS_CONTROL
224  std::cout << "othersEmpty = " << othersEmpty
225  << std::endl;
226 #endif
227 
228  // assure minimal duration
229  proposedProlongation = MAX3(SUMOTime(0), proposedProlongation, currentPhase.minDuration - actDuration);
230  if (othersEmpty) {
231  // prolong by one second if no vehicles on other approaches
232  proposedProlongation = MAX2(proposedProlongation, TIME2STEPS(1.));
233  } else {
234  // vehicles are present on other approaches -> prolong no further than the max green time
235  proposedProlongation = MIN2(proposedProlongation, MAX2(SUMOTime(0), currentPhase.maxDuration - actDuration));
236  }
237  if (!myExtendMaxDur) {
238  proposedProlongation = MIN2(proposedProlongation, MAX2(SUMOTime(0), currentPhase.maxDuration - actDuration));
239  }
240 
241 #ifdef DEBUG_TIMELOSS_CONTROL
242  std::cout << "Proposed prolongation = " << proposedProlongation << std::endl;
243 #endif
244 
245  if (proposedProlongation > 0) {
246  // check again after the prolonged period (must be positive...)
247  // XXX: Can it be harmful not to return a duration of integer seconds?
248  return proposedProlongation;
249  }
250  }
251  // Don't prolong... switch to the next phase
252  const SUMOTime prevStart = myPhases[myStep]->myLastSwitch;
253  myStep = (myStep + 1) % (int)myPhases.size();
254  myPhases[myStep]->myLastSwitch = SIMSTEP;
255  MSPhaseDefinition* newPhase = myPhases[myStep];
256  //stores the time the phase started
258  // set the next event
259  return MAX2(newPhase->minDuration, getEarliest(prevStart));
260 }
261 
262 void
264  myShowDetectors = show;
265  for (auto& item : myLaneDetectors) {
266  item.second->setVisible(myShowDetectors);
267  }
268 }
269 
270 std::map<std::string, double>
272  std::map<std::string, double> result;
273  for (auto item : myLaneDetectors) {
274  result[item.second->getID()] = item.second->getCurrentVehicleNumber();
275  }
276  return result;
277 }
278 
279 double
281  double result = 0.0;
282  for (auto item : myLaneDetectors) {
283  if (item.first->getID() == laneID) {
284  result = item.second->getCurrentVehicleNumber();
285  break;
286  }
287  }
288  return result;
289 }
290 
291 double
293  double result = 0.0;
294  for (auto item : myLaneDetectors) {
295  if (item.first->getID() == laneID) {
296  result = item.second->getEstimateQueueLength();
297  break;
298  }
299  }
300  return result;
301 }
302 
303 /****************************************************************************/
long long int SUMOTime
Definition: GUI.h:35
#define INVALID_POSITION
@ DU_TL_CONTROL
#define WRITE_ERRORF(...)
Definition: MsgHandler.h:305
#define TL(string)
Definition: MsgHandler.h:315
#define SIMSTEP
Definition: SUMOTime.h:61
#define SIMTIME
Definition: SUMOTime.h:62
#define TIME2STEPS(x)
Definition: SUMOTime.h:57
bool noVehicles(SVCPermissions permissions)
Returns whether an edge with the given permissions 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:76
T MAX2(T a, T b)
Definition: StdDefs.h:82
T MAX3(T a, T b, T c)
Definition: StdDefs.h:96
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.
double getDetectorState(const std::string laneID) const override
retrieve a specific detector used by this program
bool myExtendMaxDur
Whether phases may be extended beyond maxDur in the absence of traffic.
std::string myVehicleTypes
Whether detector output separates by vType.
SUMOTime myFreq
The frequency for aggregating detector output.
std::map< std::string, double > getDetectorStates() const override
retrieve all detectors used by this program
std::map< const MSLane *, MSE2Collector * > myLaneDetectors
A map from lanes to the corresponding lane detectors.
void init(NLDetectorBuilder &nb) override
Initializes the tls with information about incoming lanes.
bool myShowDetectors
Whether the detectors shall be shown in the GUI.
std::string myFile
The output file for generated detectors.
MSDelayBasedTrafficLightLogic(MSTLLogicControl &tlcontrol, const std::string &id, const std::string &programID, const SUMOTime offset, const MSSimpleTrafficLightLogic::Phases &phases, int step, SUMOTime delay, const Parameterised::Map &parameter, const std::string &basePath)
Constructor.
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() override
Switches to the next phase, if possible.
double getTLQueueLength(const std::string laneID) const override
return the estimated queue length at the upcoming traffic light
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:103
Representation of a lane in the micro simulation.
Definition: MSLane.h:84
const std::vector< MSLink * > & getLinkCont() const
returns the container with all links !!!
Definition: MSLane.h:716
SVCPermissions getPermissions() const
Returns the vehicle class permissions for this lane.
Definition: MSLane.h:606
double getLength() const
Returns the lane's length.
Definition: MSLane.h:598
const std::vector< IncomingLaneInfo > & getIncomingLanes() const
Definition: MSLane.h:942
MSLane * getLogicalPredecessorLane() const
get the most likely precedecessor lane (sorted using by_connections_to_sorter). The result is cached ...
Definition: MSLane.cpp:3116
static MSNet * getInstance()
Returns the pointer to the unique instance of MSNet (singleton).
Definition: MSNet.cpp:184
MSDetectorControl & getDetectorControl()
Returns the detector control.
Definition: MSNet.h:441
SUMOTime getCurrentTimeStep() const
Returns the current simulation step.
Definition: MSNet.h:320
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 duration 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'
virtual const std::string getParameter(const std::string &key, const std::string defaultValue="") const override
gets a parameter
const MSPhaseDefinition & getCurrentPhaseDef() const override
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 name, const std::string &vTypes, const std::string &nextEdges, int detectPersons, bool showDetector)
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:60
std::map< std::string, std::string > Map
parameters map
Definition: Parameterised.h:45
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