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-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
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->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
132MSDelayBasedTrafficLightLogic::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
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
262void
264 myShowDetectors = show;
265 for (auto& item : myLaneDetectors) {
266 item.second->setVisible(myShowDetectors);
267 }
268}
269
270std::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
279double
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
291double
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:36
#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.
@ 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.
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:614
const std::vector< IncomingLaneInfo > & getIncomingLanes() const
Definition MSLane.h:950
double getLength() const
Returns the lane's length.
Definition MSLane.h:606
MSLane * getLogicalPredecessorLane() const
get the most likely precedecessor lane (sorted using by_connections_to_sorter). The result is cached ...
Definition MSLane.cpp:3135
const std::vector< MSLink * > & getLinkCont() const
returns the container with all links !!!
Definition MSLane.h:724
MSDetectorControl & getDetectorControl()
Returns the detector control.
Definition MSNet.h:441
static MSNet * getInstance()
Returns the pointer to the unique instance of MSNet (singleton).
Definition MSNet.cpp:185
SUMOTime getCurrentTimeStep() const
Returns the current simulation step.
Definition MSNet.h:320
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: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.
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,...