Eclipse SUMO - Simulation of Urban MObility
NBTrafficLightLogicCont.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-2023 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/****************************************************************************/
20// A container for traffic light definitions and built programs
21/****************************************************************************/
22#include <config.h>
23#include <map>
24#include <string>
25#include <algorithm>
31#include "NBTrafficLightLogic.h"
33#include "NBOwnTLDef.h"
34#include "NBLoadedSUMOTLDef.h"
35#include "NBEdgeCont.h"
36#include "NBNodeCont.h"
37
38
39// ===========================================================================
40// static members
41// ===========================================================================
43
44// ===========================================================================
45// method definitions
46// ===========================================================================
48
49
51 clear();
52}
53
54
55void
57 // check whether any offsets shall be manipulated by setting
58 // them to half of the duration
59 if (oc.isSet("tls.half-offset")) {
60 std::vector<std::string> ids = oc.getStringVector("tls.half-offset");
61 myHalfOffsetTLS.insert(ids.begin(), ids.end());
62 }
63 // check whether any offsets shall be manipulated by setting
64 // them to a quarter of the duration
65 if (oc.isSet("tls.quarter-offset")) {
66 std::vector<std::string> ids = oc.getStringVector("tls.quarter-offset");
67 myQuarterOffsetTLS.insert(ids.begin(), ids.end());
68 }
69}
70
71
72std::string
73NBTrafficLightLogicCont::getNextProgramID(const std::string& id) const {
74 IDSupplier idS("", 0);
75 if (myDefinitions.count(id)) {
76 const Program2Def& programs = myDefinitions.find(id)->second;
77 for (auto item : programs) {
78 idS.avoid(item.first);
79 }
80 }
81 return idS.getNext();
82}
83
84
85bool
87 myExtracted.erase(logic);
88 if (myDefinitions.count(logic->getID())) {
89 if (myDefinitions[logic->getID()].count(logic->getProgramID())) {
90 if (forceInsert) {
91 logic->setProgramID(getNextProgramID(logic->getID()));
92 } else {
93 return false;
94 }
95 }
96 } else {
97 myDefinitions[logic->getID()] = Program2Def();
98 }
99 myDefinitions[logic->getID()][logic->getProgramID()] = logic;
100 return true;
101}
102
103
104bool
106 if (myDefinitions.count(id)) {
107 // delete all programs
108 for (Program2Def::iterator i = myDefinitions[id].begin(); i != myDefinitions[id].end(); i++) {
109 delete i->second;
110 }
111 myDefinitions.erase(id);
112 // also delete any logics that were already computed
113 if (myComputed.count(id)) {
114 for (Program2Logic::iterator i = myComputed[id].begin(); i != myComputed[id].end(); i++) {
115 delete i->second;
116 }
117 myComputed.erase(id);
118 }
119 return true;
120 } else {
121 return false;
122 }
123}
124
125
126bool
127NBTrafficLightLogicCont::removeProgram(const std::string id, const std::string programID, bool del) {
128 if (myDefinitions.count(id) && myDefinitions[id].count(programID)) {
129 if (del) {
130 delete myDefinitions[id][programID];
131 }
132 myDefinitions[id].erase(programID);
133 return true;
134 } else {
135 return false;
136 }
137}
138
139
140void
142 myExtracted.insert(definition);
143 removeProgram(definition->getID(), definition->getProgramID(), false);
144}
145
146
147bool
148NBTrafficLightLogicCont::exist(const std::string& newID) const {
149 const auto itD = myDefinitions.find(newID);
150 const auto itC = myComputed.find(newID);
151 if ((itD != myDefinitions.end()) && (itC != myComputed.end())) {
152 return true;
153 } else {
154 return false;
155 }
156}
157
158
159std::pair<int, int>
161 // clean previous logics
162 Logics logics = getComputed();
163 for (Logics::iterator it = logics.begin(); it != logics.end(); it++) {
164 delete *it;
165 }
166 myComputed.clear();
167 if (oc.getBool("tls.rebuild")) {
169 NBLoadedSUMOTLDef* lDef = dynamic_cast<NBLoadedSUMOTLDef*>(def);
170 if (lDef != nullptr) {
171 NBOwnTLDef* oDef = new NBOwnTLDef(def->getID(), def->getNodes(), def->getOffset(), def->getType());
172 oDef->setProgramID(def->getProgramID());
174 for (NBNode* node : oDef->getNodes()) {
175 node->removeTrafficLight(def);
176 }
177 removeProgram(def->getID(), def->getProgramID());
178 insert(oDef);
179 }
180 }
181 }
182 if (oc.getBool("tls.group-signals")) {
183 // replace NBOwnTLDef tld with NBLoadedSUMOTLDef
185 NBLoadedSUMOTLDef* lDef = dynamic_cast<NBLoadedSUMOTLDef*>(def);
186 if (lDef == nullptr) {
187 NBTrafficLightLogic* logic = def->compute(oc);
188 if (logic != nullptr) {
189 lDef = new NBLoadedSUMOTLDef(*def, *logic);
191 for (NBNode* node : lDef->getNodes()) {
192 node->removeTrafficLight(def);
193 node->addTrafficLight(lDef);
194 }
195 removeProgram(def->getID(), def->getProgramID());
196 insert(lDef);
197 delete logic;
198 }
199 }
200 if (lDef != nullptr) {
201 lDef->groupSignals();
202 }
203 }
204 } else if (oc.getBool("tls.ungroup-signals")) {
206 NBLoadedSUMOTLDef* lDef = dynamic_cast<NBLoadedSUMOTLDef*>(def);
207 // NBOwnTLDef are always ungrouped
208 if (lDef != nullptr) {
209 if (lDef->usingSignalGroups()) {
210 lDef->ungroupSignals();
211 }
212 }
213 }
214 }
215 int numPrograms = 0;
217 if (computeSingleLogic(oc, def)) {
218 numPrograms++;
219 }
220 }
221 return std::pair<int, int>((int)myComputed.size(), numPrograms);
222}
223
224
225bool
227 if (def->getNodes().size() == 0) {
228 return false;
229 }
230 const std::string& id = def->getID();
231 const std::string& programID = def->getProgramID();
232 // build program
233 NBTrafficLightLogic* built = def->compute(oc);
234 if (built == nullptr) {
235 WRITE_WARNINGF(TL("Could not build program '%' for traffic light '%'"), programID, id);
236 return false;
237 }
238 // compute offset
239 SUMOTime T = built->getDuration();
240 if (myHalfOffsetTLS.count(id)) {
241 built->setOffset(TIME2STEPS(floor(STEPS2TIME(T / 2))));
242 }
243 if (myQuarterOffsetTLS.count(id)) {
244 built->setOffset(TIME2STEPS(floor(STEPS2TIME(T / 4))));
245 }
246 // and insert the result after computation
247 // make sure we don't leak memory if computeSingleLogic is called externally
248 if (myComputed[id][programID] != nullptr) {
249 delete myComputed[id][programID];
250 }
251 myComputed[id][programID] = built;
252 return true;
253}
254
255
256void
258 Definitions definitions = getDefinitions();
259 for (Definitions::iterator it = definitions.begin(); it != definitions.end(); it++) {
260 delete *it;
261 }
262 myDefinitions.clear();
263 Logics logics = getComputed();
264 for (Logics::iterator it = logics.begin(); it != logics.end(); it++) {
265 delete *it;
266 }
267 myComputed.clear();
268 for (std::set<NBTrafficLightDefinition*>::iterator it = myExtracted.begin(); it != myExtracted.end(); it++) {
269 delete *it;
270 }
271 myExtracted.clear();
272}
273
274
275void
277 const EdgeVector& outgoing) {
278 Definitions definitions = getDefinitions();
279 for (Definitions::iterator it = definitions.begin(); it != definitions.end(); it++) {
280 (*it)->remapRemoved(removed, incoming, outgoing);
281 }
282}
283
284
285void
287 NBEdge* by, int byLane, bool incoming) {
288 Definitions definitions = getDefinitions();
289 for (Definitions::iterator it = definitions.begin(); it != definitions.end(); it++) {
290 (*it)->replaceRemoved(removed, removedLane, by, byLane, incoming);
291 }
292}
293
294
296NBTrafficLightLogicCont::getDefinition(const std::string& id, const std::string& programID) const {
297 Id2Defs::const_iterator i = myDefinitions.find(id);
298 if (i != myDefinitions.end()) {
299 Program2Def programs = i->second;
300 Program2Def::const_iterator i2 = programs.find(programID);
301 if (i2 != programs.end()) {
302 return i2->second;
303 }
304 }
305 return nullptr;
306}
307
309NBTrafficLightLogicCont::getPrograms(const std::string& id) const {
310 Id2Defs::const_iterator it = myDefinitions.find(id);
311 if (it != myDefinitions.end()) {
312 return it->second;
313 } else {
314 return EmptyDefinitions;
315 }
316}
317
318
320NBTrafficLightLogicCont::getLogic(const std::string& id, const std::string& programID) const {
321 Id2Logics::const_iterator i = myComputed.find(id);
322 if (i != myComputed.end()) {
323 Program2Logic programs = i->second;
324 Program2Logic::const_iterator i2 = programs.find(programID);
325 if (i2 != programs.end()) {
326 return i2->second;
327 }
328 }
329 return nullptr;
330}
331
332
333void
335 Definitions definitions = getDefinitions();
336 // set the information about all participants, first
337 for (Definitions::iterator it = definitions.begin(); it != definitions.end(); it++) {
338 (*it)->setParticipantsInformation();
339 }
340 // clear previous information because tlDefs may have been removed in netedit
342 // insert the information about the tl-controlling
343 for (Definitions::iterator it = definitions.begin(); it != definitions.end(); it++) {
344 (*it)->setTLControllingInformation();
345 }
346 // handle rail signals which are not instantiated as normal definitions
347 for (std::map<std::string, NBNode*>::const_iterator it = nc.begin(); it != nc.end(); it ++) {
348 NBNode* n = it->second;
350 NBOwnTLDef dummy(n->getID(), n, 0, TrafficLightType::STATIC);
353 n->setCrossingTLIndices(dummy.getID(), (int)dummy.getControlledLinks().size());
354 n->removeTrafficLight(&dummy);
355 }
356 }
357}
358
359
360void
362 Definitions definitions = getDefinitions();
364 std::map<NBEdge*, std::string> defaultSignalIDs;
365 for (const NBConnection& con : def->getControlledLinks()) {
366 const NBEdge::Connection& c = con.getFrom()->getConnection(con.getFromLane(), con.getTo(), con.getToLane());
367 if (c.knowsParameter("signalID")) {
368 defaultSignalIDs[con.getFrom()] = c.getParameter("signalID");
369 def->setParameter("linkSignalID:" + toString(con.getTLIndex()), c.getParameter("signalID"));
370 }
371 }
372 // oftentimes, signals are placed on connecting road but are meant to apply to all connections from the incoming edge
373 for (const NBConnection& con : def->getControlledLinks()) {
374 const NBEdge::Connection& c = con.getFrom()->getConnection(con.getFromLane(), con.getTo(), con.getToLane());
375 if (!c.knowsParameter("signalID") && defaultSignalIDs.count(con.getFrom()) != 0) {
376 WRITE_WARNINGF(TL("Guessing signalID for link index % at traffic light '%'."), con.getTLIndex(), def->getID());
377 def->setParameter("linkSignalID:" + toString(con.getTLIndex()), defaultSignalIDs[con.getFrom()]);
378 }
379 }
380 }
381}
382
383
386 Logics result;
387 for (Id2Logics::const_iterator it_id = myComputed.begin(); it_id != myComputed.end(); it_id++) {
388 const Program2Logic& programs = it_id->second;
389 for (Program2Logic::const_iterator it_prog = programs.begin(); it_prog != programs.end(); it_prog++) {
390 result.push_back(it_prog->second);
391 }
392 }
393 return result;
394}
395
396
399 Definitions result;
400 for (Id2Defs::const_iterator it_id = myDefinitions.begin(); it_id != myDefinitions.end(); it_id++) {
401 const Program2Def& programs = it_id->second;
402 for (Program2Def::const_iterator it_prog = programs.begin(); it_prog != programs.end(); it_prog++) {
403 result.push_back(it_prog->second);
404 }
405 }
406 return result;
407}
408
409
410void
412 auto it = myDefinitions.find(tlDef->getID());
413 if (it != myDefinitions.end()) {
414 for (auto item : it->second) {
415 item.second->setID(newID);
416 }
417 myDefinitions[newID] = it->second;
418 myDefinitions.erase(it);
419 }
420 auto it2 = myComputed.find(tlDef->getID());
421 if (it2 != myComputed.end()) {
422 for (auto item : it2->second) {
423 item.second->setID(newID);
424 }
425 myComputed[newID] = it2->second;
426 myComputed.erase(it2);
427 }
428}
429
430
431int
433 return (int)myExtracted.size();
434}
435
436/****************************************************************************/
long long int SUMOTime
Definition: GUI.h:36
#define WRITE_WARNINGF(...)
Definition: MsgHandler.h:268
#define TL(string)
Definition: MsgHandler.h:284
std::vector< NBEdge * > EdgeVector
container for (sorted) edges
Definition: NBCont.h:42
#define STEPS2TIME(x)
Definition: SUMOTime.h:54
#define TIME2STEPS(x)
Definition: SUMOTime.h:56
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition: ToString.h:46
std::string getNext()
Returns the next id.
Definition: IDSupplier.cpp:51
void avoid(const std::string &id)
make sure that the given id is never supplied
Definition: IDSupplier.cpp:59
Storage for edges, including some functionality operating on multiple edges.
Definition: NBEdgeCont.h:59
void clearControllingTLInformation() const
Clears information about controlling traffic lights for all connenections of all edges.
Definition: NBEdgeCont.cpp:833
The representation of a single edge during network building.
Definition: NBEdge.h:92
A loaded (complete) traffic light logic.
bool usingSignalGroups() const
whether this definition uses signal group (multiple connections with the same link index)
void ungroupSignals()
let all connections use a distinct link index
void groupSignals()
let connections with the same state use the same link index
Container for nodes during the netbuilding process.
Definition: NBNodeCont.h:57
std::map< std::string, NBNode * >::const_iterator begin() const
Returns the pointer to the begin of the stored nodes.
Definition: NBNodeCont.h:113
std::map< std::string, NBNode * >::const_iterator end() const
Returns the pointer to the end of the stored nodes.
Definition: NBNodeCont.h:118
Represents a single node (junction) during network building.
Definition: NBNode.h:66
bool setCrossingTLIndices(const std::string &tlID, int startIndex)
Definition: NBNode.cpp:3715
SumoXMLNodeType getType() const
Returns the type of this node.
Definition: NBNode.h:283
void removeTrafficLight(NBTrafficLightDefinition *tlDef)
Removes the given traffic light from this node.
Definition: NBNode.cpp:400
A traffic light logics which must be computed (only nodes/edges are given)
Definition: NBOwnTLDef.h:44
void setTLControllingInformation() const
Informs edges about being controlled by a tls.
Definition: NBOwnTLDef.cpp:935
The base class for traffic light logic definitions.
const std::vector< NBNode * > & getNodes() const
Returns the list of controlled nodes.
const std::string & getProgramID() const
Returns the ProgramID.
virtual void setProgramID(const std::string &programID)
Sets the programID.
NBTrafficLightLogic * compute(const OptionsCont &oc)
Computes the traffic light logic.
const NBConnectionVector & getControlledLinks() const
returns the controlled links (depends on previous call to collectLinks)
virtual void setParticipantsInformation()
Builds the list of participating nodes/edges/links.
void replaceRemoved(NBEdge *removed, int removedLane, NBEdge *by, int byLane, bool incoming)
Replaces occurrences of the removed edge/lane in all definitions by the given edge.
void applyOptions(OptionsCont &oc)
Initialises the storage by applying given options.
void setOpenDriveSignalParameters()
set OpenDRIVE signal reference parameters after all link indices are known
std::vector< NBTrafficLightLogic * > getComputed() const
Returns a list of all computed logics.
void rename(NBTrafficLightDefinition *tlDef, const std::string &newID)
rename traffic light
std::map< std::string, NBTrafficLightDefinition * > Program2Def
std::set< std::string > myHalfOffsetTLS
List of tls which shall have an offset of T/2.
static const Program2Def EmptyDefinitions
empty definition
std::vector< NBTrafficLightLogic * > Logics
std::vector< NBTrafficLightDefinition * > Definitions
Returns a list of all definitions (convenience for easier iteration)
bool removeProgram(const std::string id, const std::string programID, bool del=true)
Removes a program of a logic definition from the dictionary.
bool computeSingleLogic(OptionsCont &oc, NBTrafficLightDefinition *def)
Computes a specific traffic light logic (using by netedit)
int getNumExtracted() const
return the number of extracted traffic light definitions
bool exist(const std::string &newID) const
check if exists a definition with the given ID
void clear()
Destroys all stored definitions and logics.
const std::map< std::string, NBTrafficLightDefinition * > & getPrograms(const std::string &id) const
Returns all programs for the given tl-id.
void remapRemoved(NBEdge *removed, const EdgeVector &incoming, const EdgeVector &outgoing)
Replaces occurrences of the removed edge in incoming/outgoing edges of all definitions.
std::set< std::string > myQuarterOffsetTLS
List of tls which shall have an offset of T/2.
Id2Logics myComputed
The container for previously computed tl-logics.
NBTrafficLightLogic * getLogic(const std::string &id, const std::string &programID) const
Returns the computed logic for the given name.
Id2Defs myDefinitions
The container for tl-ids to their definitions.
std::pair< int, int > computeLogics(OptionsCont &oc)
Computes the traffic light logics using the stored definitions and stores the results.
bool removeFully(const std::string id)
Removes a logic definition (and all programs) from the dictionary.
std::map< std::string, NBTrafficLightLogic * > Program2Logic
Definition of internal the container types.
std::string getNextProgramID(const std::string &id) const
Returns a new (unused) programID for the given traffic light.
bool insert(NBTrafficLightDefinition *logic, bool forceInsert=false)
Adds a logic definition to the dictionary.
NBTrafficLightDefinition * getDefinition(const std::string &id, const std::string &programID) const
Returns the named definition.
void extract(NBTrafficLightDefinition *definition)
Extracts a traffic light definition from myDefinitions but keeps it in myExtracted for eventual * del...
void setTLControllingInformation(const NBEdgeCont &ec, const NBNodeCont &nc)
Informs the edges about being controlled by a tls.
std::set< NBTrafficLightDefinition * > myExtracted
The container for extracted definitions.
A SUMO-compliant built logic for a traffic light.
SUMOTime getDuration() const
Returns the duration of the complete cycle.
void setOffset(SUMOTime offset)
Sets the offset of this tls.
const std::string & getID() const
Returns the id.
Definition: Named.h:74
A storage for options typed value containers)
Definition: OptionsCont.h:89
bool isSet(const std::string &name, bool failOnNonExistant=true) const
Returns the information whether the named option is set.
bool getBool(const std::string &name) const
Returns the boolean-value of the named option (only for Option_Bool)
const StringVector & getStringVector(const std::string &name) const
Returns the list of string-value of the named option (only for Option_StringVector)
virtual const std::string getParameter(const std::string &key, const std::string defaultValue="") const
Returns the value for a given key.
bool knowsParameter(const std::string &key) const
Returns whether the parameter is known.
A structure which describes a connection between edges or lanes.
Definition: NBEdge.h:201