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-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 /****************************************************************************/
20 // A container for traffic light definitions and built programs
21 /****************************************************************************/
22 #include <config.h>
23 #include <map>
24 #include <string>
25 #include <algorithm>
27 #include <utils/common/ToString.h>
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 
55 void
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 
72 bool
74  myExtracted.erase(logic);
75  if (myDefinitions.count(logic->getID())) {
76  if (myDefinitions[logic->getID()].count(logic->getProgramID())) {
77  if (forceInsert) {
78  const Program2Def& programs = myDefinitions[logic->getID()];
79  IDSupplier idS("", 0);
80  for (Program2Def::const_iterator it_prog = programs.begin(); it_prog != programs.end(); it_prog++) {
81  idS.avoid(it_prog->first);
82  }
83  logic->setProgramID(idS.getNext());
84  } else {
85  return false;
86  }
87  }
88  } else {
89  myDefinitions[logic->getID()] = Program2Def();
90  }
91  myDefinitions[logic->getID()][logic->getProgramID()] = logic;
92  return true;
93 }
94 
95 
96 bool
97 NBTrafficLightLogicCont::removeFully(const std::string id) {
98  if (myDefinitions.count(id)) {
99  // delete all programs
100  for (Program2Def::iterator i = myDefinitions[id].begin(); i != myDefinitions[id].end(); i++) {
101  delete i->second;
102  }
103  myDefinitions.erase(id);
104  // also delete any logics that were already computed
105  if (myComputed.count(id)) {
106  for (Program2Logic::iterator i = myComputed[id].begin(); i != myComputed[id].end(); i++) {
107  delete i->second;
108  }
109  myComputed.erase(id);
110  }
111  return true;
112  } else {
113  return false;
114  }
115 }
116 
117 
118 bool
119 NBTrafficLightLogicCont::removeProgram(const std::string id, const std::string programID, bool del) {
120  if (myDefinitions.count(id) && myDefinitions[id].count(programID)) {
121  if (del) {
122  delete myDefinitions[id][programID];
123  }
124  myDefinitions[id].erase(programID);
125  return true;
126  } else {
127  return false;
128  }
129 }
130 
131 
132 void
134  myExtracted.insert(definition);
135  removeProgram(definition->getID(), definition->getProgramID(), false);
136 }
137 
138 
139 std::pair<int, int>
141  // clean previous logics
142  Logics logics = getComputed();
143  for (Logics::iterator it = logics.begin(); it != logics.end(); it++) {
144  delete *it;
145  }
146  myComputed.clear();
147 
148  if (oc.getBool("tls.group-signals")) {
149  // replace NBOwnTLDef tld with NBLoadedSUMOTLDef
151  NBLoadedSUMOTLDef* lDef = dynamic_cast<NBLoadedSUMOTLDef*>(def);
152  if (lDef == nullptr) {
153  NBTrafficLightLogic* logic = def->compute(oc);
154  if (logic != nullptr) {
155  lDef = new NBLoadedSUMOTLDef(*def, *logic);
157  for (NBNode* node : lDef->getNodes()) {
158  node->removeTrafficLight(def);
159  node->addTrafficLight(lDef);
160  }
161  removeProgram(def->getID(), def->getProgramID());
162  insert(lDef);
163  }
164  }
165  if (lDef != nullptr) {
166  lDef->groupSignals();
167  }
168  }
169  } else if (oc.getBool("tls.ungroup-signals")) {
171  NBLoadedSUMOTLDef* lDef = dynamic_cast<NBLoadedSUMOTLDef*>(def);
172  // NBOwnTLDef are always ungrouped
173  if (lDef != nullptr) {
174  if (lDef->usingSignalGroups()) {
175  lDef->ungroupSignals();
176  }
177  }
178  }
179  }
180  int numPrograms = 0;
182  if (computeSingleLogic(oc, def)) {
183  numPrograms++;
184  }
185  }
186  return std::pair<int, int>((int)myComputed.size(), numPrograms);
187 }
188 
189 
190 bool
192  if (def->getNodes().size() == 0) {
193  return false;
194  }
195  const std::string& id = def->getID();
196  const std::string& programID = def->getProgramID();
197  // build program
198  NBTrafficLightLogic* built = def->compute(oc);
199  if (built == nullptr) {
200  WRITE_WARNING("Could not build program '" + programID + "' for traffic light '" + id + "'");
201  return false;
202  }
203  // compute offset
204  SUMOTime T = built->getDuration();
205  if (myHalfOffsetTLS.count(id)) {
206  built->setOffset(TIME2STEPS(floor(STEPS2TIME(T / 2.))));
207  }
208  if (myQuarterOffsetTLS.count(id)) {
209  built->setOffset(TIME2STEPS(floor(STEPS2TIME(T / 4.))));
210  }
211  // and insert the result after computation
212  // make sure we don't leak memory if computeSingleLogic is called externally
213  if (myComputed[id][programID] != nullptr) {
214  delete myComputed[id][programID];
215  }
216  myComputed[id][programID] = built;
217  return true;
218 }
219 
220 
221 void
223  Definitions definitions = getDefinitions();
224  for (Definitions::iterator it = definitions.begin(); it != definitions.end(); it++) {
225  delete *it;
226  }
227  myDefinitions.clear();
228  Logics logics = getComputed();
229  for (Logics::iterator it = logics.begin(); it != logics.end(); it++) {
230  delete *it;
231  }
232  myComputed.clear();
233  for (std::set<NBTrafficLightDefinition*>::iterator it = myExtracted.begin(); it != myExtracted.end(); it++) {
234  delete *it;
235  }
236  myExtracted.clear();
237 }
238 
239 
240 void
242  const EdgeVector& outgoing) {
243  Definitions definitions = getDefinitions();
244  for (Definitions::iterator it = definitions.begin(); it != definitions.end(); it++) {
245  (*it)->remapRemoved(removed, incoming, outgoing);
246  }
247 }
248 
249 
250 void
252  NBEdge* by, int byLane, bool incoming) {
253  Definitions definitions = getDefinitions();
254  for (Definitions::iterator it = definitions.begin(); it != definitions.end(); it++) {
255  (*it)->replaceRemoved(removed, removedLane, by, byLane, incoming);
256  }
257 }
258 
259 
261 NBTrafficLightLogicCont::getDefinition(const std::string& id, const std::string& programID) const {
262  Id2Defs::const_iterator i = myDefinitions.find(id);
263  if (i != myDefinitions.end()) {
264  Program2Def programs = i->second;
265  Program2Def::const_iterator i2 = programs.find(programID);
266  if (i2 != programs.end()) {
267  return i2->second;
268  }
269  }
270  return nullptr;
271 }
272 
274 NBTrafficLightLogicCont::getPrograms(const std::string& id) const {
275  Id2Defs::const_iterator it = myDefinitions.find(id);
276  if (it != myDefinitions.end()) {
277  return it->second;
278  } else {
279  return EmptyDefinitions;
280  }
281 }
282 
283 
285 NBTrafficLightLogicCont::getLogic(const std::string& id, const std::string& programID) const {
286  Id2Logics::const_iterator i = myComputed.find(id);
287  if (i != myComputed.end()) {
288  Program2Logic programs = i->second;
289  Program2Logic::const_iterator i2 = programs.find(programID);
290  if (i2 != programs.end()) {
291  return i2->second;
292  }
293  }
294  return nullptr;
295 }
296 
297 
298 void
300  Definitions definitions = getDefinitions();
301  // set the information about all participants, first
302  for (Definitions::iterator it = definitions.begin(); it != definitions.end(); it++) {
303  (*it)->setParticipantsInformation();
304  }
305  // clear previous information because tlDefs may have been removed in NETEDIT
307  // insert the information about the tl-controlling
308  for (Definitions::iterator it = definitions.begin(); it != definitions.end(); it++) {
309  (*it)->setTLControllingInformation();
310  }
311  // handle rail signals which are not instantiated as normal definitions
312  for (std::map<std::string, NBNode*>::const_iterator it = nc.begin(); it != nc.end(); it ++) {
313  NBNode* n = it->second;
315  NBOwnTLDef dummy(n->getID(), n, 0, TrafficLightType::STATIC);
318  n->setCrossingTLIndices(dummy.getID(), (int)dummy.getControlledLinks().size());
319  n->removeTrafficLight(&dummy);
320  }
321  }
322 }
323 
324 
325 void
327  Definitions definitions = getDefinitions();
329  std::map<NBEdge*, std::string> defaultSignalIDs;
330  for (const NBConnection& con : def->getControlledLinks()) {
331  const NBEdge::Connection& c = con.getFrom()->getConnection(con.getFromLane(), con.getTo(), con.getToLane());
332  if (c.knowsParameter("signalID")) {
333  defaultSignalIDs[con.getFrom()] = c.getParameter("signalID");
334  def->setParameter("linkSignalID:" + toString(con.getTLIndex()), c.getParameter("signalID"));
335  }
336  }
337  // oftentimes, signals are placed on connecting road but are meant to apply to all connections from the incoming edge
338  for (const NBConnection& con : def->getControlledLinks()) {
339  const NBEdge::Connection& c = con.getFrom()->getConnection(con.getFromLane(), con.getTo(), con.getToLane());
340  if (!c.knowsParameter("signalID") && defaultSignalIDs.count(con.getFrom()) != 0) {
341  WRITE_WARNINGF("Guessing signalID for link index % at traffic light '%'.", con.getTLIndex(), def->getID());
342  def->setParameter("linkSignalID:" + toString(con.getTLIndex()), defaultSignalIDs[con.getFrom()]);
343  }
344  }
345  }
346 }
347 
348 
351  Logics result;
352  for (Id2Logics::const_iterator it_id = myComputed.begin(); it_id != myComputed.end(); it_id++) {
353  const Program2Logic& programs = it_id->second;
354  for (Program2Logic::const_iterator it_prog = programs.begin(); it_prog != programs.end(); it_prog++) {
355  result.push_back(it_prog->second);
356  }
357  }
358  return result;
359 }
360 
361 
364  Definitions result;
365  for (Id2Defs::const_iterator it_id = myDefinitions.begin(); it_id != myDefinitions.end(); it_id++) {
366  const Program2Def& programs = it_id->second;
367  for (Program2Def::const_iterator it_prog = programs.begin(); it_prog != programs.end(); it_prog++) {
368  result.push_back(it_prog->second);
369  }
370  }
371  return result;
372 }
373 
374 
375 /****************************************************************************/
#define WRITE_WARNINGF(...)
Definition: MsgHandler.h:281
#define WRITE_WARNING(msg)
Definition: MsgHandler.h:280
std::vector< NBEdge * > EdgeVector
container for (sorted) edges
Definition: NBCont.h:35
#define STEPS2TIME(x)
Definition: SUMOTime.h:53
#define TIME2STEPS(x)
Definition: SUMOTime.h:55
long long int SUMOTime
Definition: SUMOTime.h:32
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:798
The representation of a single edge during network building.
Definition: NBEdge.h:91
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:58
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:3449
SumoXMLNodeType getType() const
Returns the type of this node.
Definition: NBNode.h:273
void removeTrafficLight(NBTrafficLightDefinition *tlDef)
Removes the given traffic light from this node.
Definition: NBNode.cpp:375
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:829
The base class for traffic light logic definitions.
const NBConnectionVector & getControlledLinks() const
returns the controlled links (depends on previous call to collectLinks)
const std::string & getProgramID() const
Returns the ProgramID.
virtual void setProgramID(const std::string &programID)
Sets the programID.
const std::vector< NBNode * > & getNodes() const
Returns the list of controlled nodes.
NBTrafficLightLogic * compute(OptionsCont &oc)
Computes the traffic light logic.
virtual void setParticipantsInformation()
Builds the list of participating nodes/edges/links.
void replaceRemoved(NBEdge *removed, int removedLane, NBEdge *by, int byLane, bool incoming)
Replaces occurences 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.
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
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)
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 occurences 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.
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:197