Eclipse SUMO - Simulation of Urban MObility
Loading...
Searching...
No Matches
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-2026 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
74void
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->getLogicalPredecessorLane() != nullptr
106 && firstLane->getIncomingLanes().front().viaLink->getCorrespondingEntryLink()->getTLLogic() == nullptr) {
107 firstLane = firstLane->getLogicalPredecessorLane();
108 if (firstLane->getLinkCont().size() > 1) {
109 break;
110 }
111 length += firstLane->getLength();
112 }
113 length = MIN2(length, myDetectionRange);
114
115 std::string id = "TLS" + myID + "_" + myProgramID + "_E2CollectorOn_" + lane->getID();
116 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);
118 }
119 myLaneDetectors[lane] = det;
120 }
121 }
122 }
123}
124
125
126
128
129// ------------ Switching and setting current rows
130
131
133MSDelayBasedTrafficLightLogic::proposeProlongation(const SUMOTime actDuration, const SUMOTime maxDuration, bool& othersEmpty) {
134#ifdef DEBUG_TIMELOSS_CONTROL
135 std::cout << "\n" << SIMTIME << " MSDelayBasedTrafficLightLogic::proposeProlongation() for TLS '" << this->getID() << "' (current phase = " << myStep << ")" << std::endl;
136#endif
137 SUMOTime prolongation = 0;
138 const std::string& state = getCurrentPhaseDef().getState();
139 // iterate over green lanes, eventually increase the proposed prolongationTime to the estimated passing time for each lane.
140 for (int i = 0; i < (int) state.size(); i++) {
141 // this lane index corresponds to a non-green time
142 bool igreen = state[i] == LINKSTATE_TL_GREEN_MAJOR || state[i] == LINKSTATE_TL_GREEN_MINOR;
143 for (const MSLane* const lane : getLanesAt(i)) {
144 std::map<const MSLane*, MSE2Collector*>::iterator it = myLaneDetectors.find(lane);
145 if (it == myLaneDetectors.end()) {
146#ifdef DEBUG_TIMELOSS_CONTROL
147 // no detector for this lane!? maybe noVehicles allowed
148 std::cout << "no detector on lane '" << lane->getID() << std::endl;
149#endif
150 continue;
151 }
152 const std::vector<MSE2Collector::VehicleInfo*> vehInfos = it->second->getCurrentVehicles();
153#ifdef DEBUG_TIMELOSS_CONTROL
154 int nrVehs = 0; // count vehicles on detector
155#endif
156 if (igreen) {
157 // green phase
158 for (const MSE2Collector::VehicleInfo* const iv : vehInfos) {
159 if (iv->accumulatedTimeLoss > myTimeLossThreshold && iv->distToDetectorEnd > 0) {
160 const SUMOTime estimatedTimeToJunction = TIME2STEPS((iv->distToDetectorEnd) / lane->getSpeedLimit());
161 if (actDuration + estimatedTimeToJunction <= maxDuration && getLatest() > 0) {
162 // only prolong if vehicle has a chance to pass until max duration is reached
163 prolongation = MAX2(prolongation, estimatedTimeToJunction);
164 }
165#ifdef DEBUG_TIMELOSS_CONTROL
166 nrVehs++;
167#endif
168
169#ifdef DEBUG_TIMELOSS_CONTROL
170 std::cout << "vehicle '" << iv->id << "' with accumulated timeloss: " << iv->accumulatedTimeLoss
171 << "\nestimated passing time: " << estimatedTimeToJunction << std::endl;
172 } else {
173 std::string reason = iv->accumulatedTimeLoss <= myTimeLossThreshold ? " (time loss below threshold)" : " (front already left detector)";
174 std::cout << "disregarded: (vehicle '" << iv->id << "' with accumulated timeloss " << iv->accumulatedTimeLoss << ")" << reason << std::endl;
175#endif
176 }
177 }
178 } else {
179 // non-green phase
180 if (vehInfos.size() > 0) {
181 // here is a car on a non-green approach
182 othersEmpty = false;
183 if (actDuration >= getCurrentPhaseDef().maxDuration) {
184#ifdef DEBUG_TIMELOSS_CONTROL
185 std::cout << "Actual duration exceeds maxDuration and a vehicle is on concurrent approach: " << nrVehs << std::endl;
186#endif
187 // don't prolong
188 return 0;
189 }
190 break;
191 }
192#ifdef DEBUG_TIMELOSS_CONTROL
193 std::cout << "Number of current vehicles on detector: " << nrVehs << std::endl;
194#endif
195 }
196 }
197 }
198#ifdef DEBUG_TIMELOSS_CONTROL
199 std::cout << "Proposed prolongation (maximal estimated passing time): " << prolongation << std::endl; // debug
200#endif
201 return prolongation;
202}
203
204
207 /* check if the actual phase should be prolonged */
208 const MSPhaseDefinition& currentPhase = getCurrentPhaseDef();
209 // time since last switch
210 const SUMOTime actDuration = MSNet::getInstance()->getCurrentTimeStep() - currentPhase.myLastSwitch;
211
212#ifdef DEBUG_TIMELOSS_CONTROL
213 std::cout << "last switch = " << currentPhase.myLastSwitch
214 << "\nactDuration = " << actDuration
215 << "\nmaxDuration = " << currentPhase.maxDuration
216 << std::endl;
217#endif
218
219 // flag whether to prolong or not
220 if (currentPhase.isGreenPhase() && !MSGlobals::gUseMesoSim) {
221 bool othersEmpty = true; // whether no vehicles are present on concurrent approaches
222 SUMOTime proposedProlongation = proposeProlongation(actDuration, currentPhase.maxDuration, othersEmpty);
223
224#ifdef DEBUG_TIMELOSS_CONTROL
225 std::cout << "othersEmpty = " << othersEmpty
226 << std::endl;
227#endif
228
229 // assure minimal duration
230 proposedProlongation = MAX3(SUMOTime(0), proposedProlongation, currentPhase.minDuration - actDuration);
231 if (othersEmpty) {
232 // prolong by one second if no vehicles on other approaches
233 proposedProlongation = MAX2(proposedProlongation, TIME2STEPS(1.));
234 } else {
235 // vehicles are present on other approaches -> prolong no further than the max green time
236 proposedProlongation = MIN2(proposedProlongation, MAX2(SUMOTime(0), currentPhase.maxDuration - actDuration));
237 }
238 if (!myExtendMaxDur) {
239 proposedProlongation = MIN2(proposedProlongation, MAX2(SUMOTime(0), currentPhase.maxDuration - actDuration));
240 }
241
242#ifdef DEBUG_TIMELOSS_CONTROL
243 std::cout << "Proposed prolongation = " << proposedProlongation << std::endl;
244#endif
245
246 if (proposedProlongation > 0) {
247 // check again after the prolonged period (must be positive...)
248 // XXX: Can it be harmful not to return a duration of integer seconds?
249 return proposedProlongation;
250 }
251 }
252 // Don't prolong... switch to the next phase
253 const SUMOTime prevStart = myPhases[myStep]->myLastSwitch;
254 myStep = (myStep + 1) % (int)myPhases.size();
255 myPhases[myStep]->myLastSwitch = SIMSTEP;
256 MSPhaseDefinition* newPhase = myPhases[myStep];
257 //stores the time the phase started
259 // set the next event
260 return MAX2(newPhase->minDuration, getEarliest(prevStart));
261}
262
263void
265 myShowDetectors = show;
266 for (auto& item : myLaneDetectors) {
267 item.second->setVisible(myShowDetectors);
268 }
269}
270
271std::map<std::string, double>
273 std::map<std::string, double> result;
274 for (auto item : myLaneDetectors) {
275 result[item.second->getID()] = item.second->getCurrentVehicleNumber();
276 }
277 return result;
278}
279
280double
282 double result = 0.0;
283 for (auto item : myLaneDetectors) {
284 if (item.first->getID() == laneID) {
285 result = item.second->getCurrentVehicleNumber();
286 break;
287 }
288 }
289 return result;
290}
291
292double
294 double result = 0.0;
295 for (auto item : myLaneDetectors) {
296 if (item.first->getID() == laneID) {
297 result = item.second->getEstimateQueueLength();
298 break;
299 }
300 }
301 return result;
302}
303
304/****************************************************************************/
long long int SUMOTime
Definition GUI.h:36
#define INVALID_POSITION
@ DU_TL_CONTROL
#define WRITE_ERRORF(...)
Definition MsgHandler.h:296
#define TL(string)
Definition MsgHandler.h:304
#define SIMSTEP
Definition SUMOTime.h:69
constexpr SUMOTime TIME2STEPS(double x)
Definition SUMOTime.h:60
#define SIMTIME
Definition SUMOTime.h:70
bool noVehicles(SVCPermissions permissions)
Returns whether an edge with the given permissions forbids vehicles.
@ 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:80
T MAX2(T a, T b)
Definition StdDefs.h:86
T MAX3(T a, T b, T c)
Definition StdDefs.h:100
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition ToString.h:57
static std::string checkForRelativity(const std::string &filename, const std::string &basePath)
Returns the path from a configuration so that it is accessible 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.
virtual void setVisible(bool)
static bool gUseMesoSim
Definition MSGlobals.h:106
Representation of a lane in the micro simulation.
Definition MSLane.h:84
SVCPermissions getPermissions() const
Returns the vehicle class permissions for this lane.
Definition MSLane.h:640
const std::vector< IncomingLaneInfo > & getIncomingLanes() const
Definition MSLane.h:984
double getLength() const
Returns the lane's length.
Definition MSLane.h:632
MSLane * getLogicalPredecessorLane() const
get the most likely predecessor lane (sorted using by_connections_to_sorter). The result is cached in...
Definition MSLane.cpp:3271
const std::vector< MSLink * > & getLinkCont() const
returns the container with all links !!!
Definition MSLane.h:750
MSDetectorControl & getDetectorControl()
Returns the detector control.
Definition MSNet.h:465
static MSNet * getInstance()
Returns the pointer to the unique instance of MSNet (singleton).
Definition MSNet.cpp:201
SUMOTime getCurrentTimeStep() const
Returns the current simulation step.
Definition MSNet.h:334
The definition of a single phase of a tls logic.
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.
const std::string & getState() const
Returns the state within this 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.
const LaneVector & getLanesAt(int i) const
Returns the list of lanes that are controlled by the signals at the given position.
std::vector< MSLane * > LaneVector
Definition of the list of arrival lanes subjected to this tls.
const std::string & getProgramID() const
Returns this tl-logic's id.
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.
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.
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:124
const std::string & getID() const
Returns the id.
Definition Named.h:73
T get(const std::string &id) const
Retrieves an item.
static OptionsCont & getOptions()
Retrieves the options.
std::map< std::string, std::string > Map
parameters map
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,...