SUMO - Simulation of Urban MObility
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
NBLoadedTLDef.cpp
Go to the documentation of this file.
1 /****************************************************************************/
10 // A loaded (complete) traffic light logic
11 /****************************************************************************/
12 // SUMO, Simulation of Urban MObility; see http://sumo.sourceforge.net/
13 // Copyright (C) 2001-2012 DLR (http://www.dlr.de/) and contributors
14 /****************************************************************************/
15 //
16 // This file is part of SUMO.
17 // SUMO is free software: you can redistribute it and/or modify
18 // it under the terms of the GNU General Public License as published by
19 // the Free Software Foundation, either version 3 of the License, or
20 // (at your option) any later version.
21 //
22 /****************************************************************************/
23 
24 // ===========================================================================
25 // included modules
26 // ===========================================================================
27 #ifdef _MSC_VER
28 #include <windows_config.h>
29 #else
30 #include <config.h>
31 #endif
32 
33 #include <vector>
34 #include <set>
35 #include <cassert>
36 #include <iterator>
38 #include <utils/common/ToString.h>
40 #include "NBTrafficLightLogic.h"
42 #include "NBLoadedTLDef.h"
43 #include "NBNode.h"
44 
45 #ifdef CHECK_MEMORY_LEAKS
46 #include <foreign/nvwa/debug_new.h>
47 #endif // CHECK_MEMORY_LEAKS
48 
49 
50 // ===========================================================================
51 // method definitions
52 // ===========================================================================
53 /* -------------------------------------------------------------------------
54  * NBLoadedTLDef::SignalGroup-methods
55  * ----------------------------------------------------------------------- */
57  : Named(id) {}
58 
60 
61 void
63  assert(c.getFromLane() < 0 || c.getFrom()->getNumLanes() > (unsigned int)c.getFromLane());
64  myConnections.push_back(c);
65 }
66 
67 
68 void
70  myPhases.push_back(PhaseDef(time, color));
71 }
72 
73 
74 void
76  SUMOTime tYellow) {
77  myTRedYellow = tRedYellow;
78  myTYellow = tYellow;
79 }
80 
81 
82 void
84  sort(myPhases.begin(), myPhases.end(),
86 }
87 
88 
89 void
91  if (myTYellow < tyellow) {
92  WRITE_WARNING("TYellow of signal group '" + getID() + "' was less than the computed one; patched (was:" + toString<SUMOTime>(myTYellow) + ", is:" + toString<int>(tyellow) + ")");
93  myTYellow = tyellow;
94  }
95 }
96 
97 
98 std::vector<SUMOReal>
100  // within the phase container, we should have the green and red phases
101  // add their times
102  std::vector<SUMOReal> ret; // !!! time vector
103  for (std::vector<PhaseDef>::const_iterator i = myPhases.begin(); i != myPhases.end(); i++) {
104  ret.push_back((SUMOReal)(*i).myTime);
105  }
106  // further, we possibly should set the yellow phases
107  if (myTYellow > 0) {
108  for (std::vector<PhaseDef>::const_iterator i = myPhases.begin(); i != myPhases.end(); i++) {
109  if ((*i).myColor == TLCOLOR_RED) {
110  SUMOTime time = (SUMOTime)(*i).myTime + myTYellow;
111  if (time > cycleDuration) {
112  time = time - cycleDuration ;
113  }
114  ret.push_back((SUMOReal) time);
115  }
116  }
117  }
118  return ret;
119 }
120 
121 
122 unsigned int
124  return (unsigned int) myConnections.size();
125 }
126 
127 
128 bool
130  assert(myPhases.size() != 0);
131  for (std::vector<PhaseDef>::const_reverse_iterator i = myPhases.rbegin(); i != myPhases.rend(); i++) {
132  SUMOTime nextTime = (*i).myTime;
133  if (time >= nextTime) {
134  return (*i).myColor == TLCOLOR_GREEN;
135  }
136  }
137  return (*(myPhases.end() - 1)).myColor == TLCOLOR_GREEN;
138 }
139 
140 
141 bool
143  bool has_red_now = !mayDrive(time);
144  bool had_green = mayDrive(time - myTYellow);
145  return has_red_now && had_green;
146 }
147 
148 
149 bool
151  for (NBConnectionVector::const_iterator i = myConnections.begin(); i != myConnections.end(); i++) {
152  if ((*i).getFrom() == from && (*i).getTo() == to) {
153  return true;
154  }
155  }
156  return false;
157 
158 }
159 
160 
161 const NBConnection&
163  assert(pos < myConnections.size());
164  return myConnections[pos];
165 }
166 
167 
168 bool
170  for (NBConnectionVector::const_iterator i = myConnections.begin(); i != myConnections.end(); i++) {
171  if ((*i).getFrom() == from) {
172  return true;
173  }
174  }
175  return false;
176 }
177 
178 
179 void
181  NBConnectionVector newConns;
182  for (NBConnectionVector::iterator i = myConnections.begin(); i != myConnections.end();) {
183  if ((*i).getFrom() == which) {
184  NBConnection conn((*i).getFrom(), (*i).getTo());
185  i = myConnections.erase(i);
186  for (EdgeVector::const_iterator j = by.begin(); j != by.end(); j++) {
187  NBConnection curr(conn);
188  if (!curr.replaceFrom(which, *j)) {
189  throw ProcessError("Could not replace edge '" + which->getID() + "' by '" + (*j)->getID() + "'.\nUndefined...");
190  }
191  newConns.push_back(curr);
192  }
193  } else {
194  i++;
195  }
196  }
197  copy(newConns.begin(), newConns.end(),
198  back_inserter(myConnections));
199 }
200 
201 
202 bool
204  for (NBConnectionVector::const_iterator i = myConnections.begin(); i != myConnections.end(); i++) {
205  if ((*i).getTo() == to) {
206  return true;
207  }
208  }
209  return false;
210 }
211 
212 
213 void
215  NBConnectionVector newConns;
216  for (NBConnectionVector::iterator i = myConnections.begin(); i != myConnections.end();) {
217  if ((*i).getTo() == which) {
218  NBConnection conn((*i).getFrom(), (*i).getTo());
219  i = myConnections.erase(i);
220  for (EdgeVector::const_iterator j = by.begin(); j != by.end(); j++) {
221  NBConnection curr(conn);
222  if (!curr.replaceTo(which, *j)) {
223  throw ProcessError("Could not replace edge '" + which->getID() + "' by '" + (*j)->getID() + "'.\nUndefined...");
224  }
225  newConns.push_back(curr);
226  }
227  } else {
228  i++;
229  }
230  }
231  copy(newConns.begin(), newConns.end(),
232  back_inserter(myConnections));
233 }
234 
235 
236 void
237 NBLoadedTLDef::SignalGroup::remap(NBEdge* removed, int removedLane,
238  NBEdge* by, int byLane) {
239  for (NBConnectionVector::iterator i = myConnections.begin(); i != myConnections.end(); i++) {
240  if ((*i).getTo() == removed
241  &&
242  ((*i).getToLane() == removedLane
243  ||
244  (*i).getToLane() == -1)) {
245  (*i).replaceTo(removed, removedLane, by, byLane);
246 
247  } else if ((*i).getTo() == removed && removedLane == -1) {
248  (*i).replaceTo(removed, by);
249  }
250 
251  if ((*i).getFrom() == removed
252  &&
253  ((*i).getFromLane() == removedLane
254  ||
255  (*i).getFromLane() == -1)) {
256  (*i).replaceFrom(removed, removedLane, by, byLane);
257 
258  } else if ((*i).getFrom() == removed && removedLane == -1) {
259  (*i).replaceFrom(removed, by);
260  }
261  }
262 }
263 
264 
265 /* -------------------------------------------------------------------------
266  * NBLoadedTLDef::Phase-methods
267  * ----------------------------------------------------------------------- */
268 NBLoadedTLDef::NBLoadedTLDef(const std::string& id,
269  const std::vector<NBNode*> &junctions)
270  : NBTrafficLightDefinition(id, junctions, DefaultProgramID) {}
271 
272 
273 NBLoadedTLDef::NBLoadedTLDef(const std::string& id, NBNode* junction)
274  : NBTrafficLightDefinition(id, junction, DefaultProgramID) {}
275 
276 
277 NBLoadedTLDef::NBLoadedTLDef(const std::string& id)
278  : NBTrafficLightDefinition(id, DefaultProgramID) {}
279 
280 
282  for (SignalGroupCont::iterator i = mySignalGroups.begin(); i != mySignalGroups.end(); ++i) {
283  delete(*i).second;
284  }
285 }
286 
287 
289 NBLoadedTLDef::myCompute(const NBEdgeCont& ec, unsigned int brakingTime) {
291  NBLoadedTLDef::SignalGroupCont::const_iterator i;
292  // compute the switching times
293  std::set<SUMOReal> tmpSwitchTimes;
294  for (i = mySignalGroups.begin(); i != mySignalGroups.end(); i++) {
295  NBLoadedTLDef::SignalGroup* group = (*i).second;
296  // needed later
297  group->sortPhases();
298  // patch the yellow time for this group
299  if (OptionsCont::getOptions().getBool("tls.yellow.patch-small")) {
300  group->patchTYellow(brakingTime);
301  }
302  // copy the now valid times into the container
303  // both the given red and green phases are added and also the
304  // yellow times
305  std::vector<SUMOReal> gtimes = group->getTimes(myCycleDuration);
306  for (std::vector<SUMOReal>::const_iterator k = gtimes.begin(); k != gtimes.end(); k++) {
307  tmpSwitchTimes.insert(*k);
308  }
309  }
310  std::vector<SUMOReal> switchTimes;
311  copy(tmpSwitchTimes.begin(), tmpSwitchTimes.end(), back_inserter(switchTimes));
312  sort(switchTimes.begin(), switchTimes.end());
313 
314  // count the signals
315  unsigned int noSignals = 0;
316  for (i = mySignalGroups.begin(); i != mySignalGroups.end(); i++) {
317  noSignals += (*i).second->getLinkNo();
318  }
319  // build the phases
320  NBTrafficLightLogic* logic = new NBTrafficLightLogic(getID(), getProgramID(), noSignals);
321  for (std::vector<SUMOReal>::iterator l = switchTimes.begin(); l != switchTimes.end(); l++) {
322  // compute the duration of the current phase
323  unsigned int duration;
324  if (l != switchTimes.end() - 1) {
325  // get from the difference to the next switching time
326  duration = (unsigned int)((*(l + 1)) - (*l));
327  } else {
328  // get from the differenc to the first switching time
329  duration = (unsigned int)(myCycleDuration - (*l) + * (switchTimes.begin())) ;
330  }
331  // no information about yellow times will be generated
332  assert((*l) >= 0);
333  logic->addStep(TIME2STEPS(duration), buildPhaseState(ec, (unsigned int)(*l)));
334  }
335  // check whether any warnings were printed
336  if (MsgHandler::getWarningInstance()->wasInformed()) {
337  WRITE_WARNING("During computation of traffic light '" + getID() + "'.");
338  }
339  logic->closeBuilding();
340  return logic;
341 }
342 
343 
344 void
346  // assign the links to the connections
347  unsigned int pos = 0;
348  for (SignalGroupCont::const_iterator m = mySignalGroups.begin(); m != mySignalGroups.end(); m++) {
349  SignalGroup* group = (*m).second;
350  unsigned int linkNo = group->getLinkNo();
351  for (unsigned int j = 0; j < linkNo; j++) {
352  const NBConnection& conn = group->getConnection(j);
353  assert(conn.getFromLane() < 0 || (int) conn.getFrom()->getNumLanes() > conn.getFromLane());
354  NBConnection tst(conn);
355  tst.setTLIndex(pos);
356  if (tst.check(ec)) {
357  NBEdge* edge = conn.getFrom();
358  if (edge->setControllingTLInformation(tst, getID())) {
359  pos++;
360  }
361  } else {
362  WRITE_WARNING("Could not set signal on connection (signal: " + getID() + ", group: " + group->getID() + ")");
363  }
364  }
365  }
366 }
367 
368 
369 std::string
370 NBLoadedTLDef::buildPhaseState(const NBEdgeCont& ec, unsigned int time) const {
371  unsigned int pos = 0;
372  std::string state;
373  // set the green and yellow information first;
374  // the information whether other have to break needs those masks
375  // completely filled
376  for (SignalGroupCont::const_iterator i = mySignalGroups.begin(); i != mySignalGroups.end(); i++) {
377  SignalGroup* group = (*i).second;
378  unsigned int linkNo = group->getLinkNo();
379  bool mayDrive = group->mayDrive(time);
380  bool hasYellow = group->hasYellow(time);
381  char c = 'r';
382  if (mayDrive) {
383  c = 'g';
384  }
385  if (hasYellow) {
386  c = 'y';
387  }
388  for (unsigned int j = 0; j < linkNo; j++) {
389  const NBConnection& conn = group->getConnection(j);
390  NBConnection assConn(conn);
391  // assert that the connection really exists
392  if (assConn.check(ec)) {
393  state = state + c;
394  ++pos;
395  }
396  }
397  }
398  // set the braking mask
399  pos = 0;
400  for (SignalGroupCont::const_iterator i = mySignalGroups.begin(); i != mySignalGroups.end(); i++) {
401  SignalGroup* group = (*i).second;
402  unsigned int linkNo = group->getLinkNo();
403  for (unsigned int j = 0; j < linkNo; j++) {
404  const NBConnection& conn = group->getConnection(j);
405  NBConnection assConn(conn);
406  if (assConn.check(ec)) {
407  if (!mustBrake(ec, assConn, state, pos)) {
408  if (state[pos] == 'g') {
409  state[pos] = 'G';
410  }
411  if (state[pos] == 'y') {
412  state[pos] = 'Y';
413  }
414  }
415  pos++;
416  }
417  }
418  }
419  return state;
420 }
421 
422 
423 bool
425  const NBConnection& possProhibited,
426  const std::string& state,
427  unsigned int strmpos) const {
428  // check whether the stream has red
429  if (state[strmpos] != 'g' && state[strmpos] != 'G') {
430  return true;
431  }
432 
433  // check whether another stream which has green is a higher
434  // priorised foe to the given
435  unsigned int pos = 0;
436  for (SignalGroupCont::const_iterator i = mySignalGroups.begin(); i != mySignalGroups.end(); i++) {
437  SignalGroup* group = (*i).second;
438  // get otherlinks that have green
439  unsigned int linkNo = group->getLinkNo();
440  for (unsigned int j = 0; j < linkNo; j++) {
441  // get the current connection (possible foe)
442  const NBConnection& other = group->getConnection(j);
443  NBConnection possProhibitor(other);
444  // if the connction ist still valid ...
445  if (possProhibitor.check(ec)) {
446  // ... do nothing if it starts at the same edge
447  if (possProhibited.getFrom() == possProhibitor.getFrom()) {
448  pos++;
449  continue;
450  }
451  if (state[pos] == 'g' || state[pos] == 'G') {
452  if (NBTrafficLightDefinition::mustBrake(possProhibited, possProhibitor, true)) {
453  return true;
454  }
455  }
456  pos++;
457  }
458  }
459  }
460  return false;
461 }
462 
463 
464 void
466  myControlledNodes.clear();
467  SignalGroupCont::const_iterator m;
468  for (m = mySignalGroups.begin(); m != mySignalGroups.end(); m++) {
469  SignalGroup* group = (*m).second;
470  unsigned int linkNo = group->getLinkNo();
471  for (unsigned int j = 0; j < linkNo; j++) {
472  const NBConnection& conn = group->getConnection(j);
473  NBEdge* edge = conn.getFrom();
474  NBNode* node = edge->getToNode();
475  myControlledNodes.push_back(node);
476  }
477  }
479 }
480 
481 
482 void
484  myControlledLinks.clear();
485  // build the list of links which are controled by the traffic light
486  for (EdgeVector::iterator i = myIncomingEdges.begin(); i != myIncomingEdges.end(); i++) {
487  NBEdge* incoming = *i;
488  unsigned int noLanes = incoming->getNumLanes();
489  for (unsigned int j = 0; j < noLanes; j++) {
490  std::vector<NBEdge::Connection> elv = incoming->getConnectionsFromLane(j);
491  for (std::vector<NBEdge::Connection>::iterator k = elv.begin(); k != elv.end(); k++) {
492  NBEdge::Connection el = *k;
493  if (el.toEdge != 0) {
494  myControlledLinks.push_back(NBConnection(incoming, j, el.toEdge, el.toLane));
495  }
496  }
497  }
498  }
499 }
500 
501 
504  for (SignalGroupCont::const_iterator i = mySignalGroups.begin(); i != mySignalGroups.end(); i++) {
505  if ((*i).second->containsConnection(from, to)) {
506  return (*i).second;
507  }
508  }
509  return 0;
510 }
511 
512 
513 bool
514 NBLoadedTLDef::addToSignalGroup(const std::string& groupid,
515  const NBConnection& connection) {
516  if (mySignalGroups.find(groupid) == mySignalGroups.end()) {
517  return false;
518  }
519  mySignalGroups[groupid]->addConnection(connection);
520  NBNode* n1 = connection.getFrom()->getToNode();
521  if (n1 != 0) {
522  addNode(n1);
523  n1->addTrafficLight(this);
524  }
525  NBNode* n2 = connection.getTo()->getFromNode();
526  if (n2 != 0) {
527  addNode(n2);
528  n2->addTrafficLight(this);
529  }
530  return true;
531 }
532 
533 
534 bool
535 NBLoadedTLDef::addToSignalGroup(const std::string& groupid,
536  const NBConnectionVector& connections) {
537  bool ok = true;
538  for (NBConnectionVector::const_iterator i = connections.begin(); i != connections.end(); i++) {
539  ok &= addToSignalGroup(groupid, *i);
540  }
541  return ok;
542 }
543 
544 
545 void
546 NBLoadedTLDef::addSignalGroup(const std::string& id) {
547  assert(mySignalGroups.find(id) == mySignalGroups.end());
548  mySignalGroups[id] = new SignalGroup(id);
549 }
550 
551 
552 void
553 NBLoadedTLDef::addSignalGroupPhaseBegin(const std::string& groupid, SUMOTime time,
554  TLColor color) {
555  assert(mySignalGroups.find(groupid) != mySignalGroups.end());
556  mySignalGroups[groupid]->addPhaseBegin(time, color);
557 }
558 
559 void
560 NBLoadedTLDef::setSignalYellowTimes(const std::string& groupid,
561  SUMOTime myTRedYellow, SUMOTime myTYellow) {
562  assert(mySignalGroups.find(groupid) != mySignalGroups.end());
563  mySignalGroups[groupid]->setYellowTimes(myTRedYellow, myTYellow);
564 }
565 
566 
567 void
568 NBLoadedTLDef::setCycleDuration(unsigned int cycleDur) {
569  myCycleDuration = cycleDur;
570 }
571 
572 
573 void
575  const EdgeVector& incoming,
576  const EdgeVector& outgoing) {
577  for (SignalGroupCont::const_iterator i = mySignalGroups.begin(); i != mySignalGroups.end(); i++) {
578  SignalGroup* group = (*i).second;
579  if (group->containsIncoming(removed)) {
580  group->remapIncoming(removed, incoming);
581  }
582  if (group->containsOutgoing(removed)) {
583  group->remapOutgoing(removed, outgoing);
584  }
585  }
586 }
587 
588 
589 void
590 NBLoadedTLDef::replaceRemoved(NBEdge* removed, int removedLane,
591  NBEdge* by, int byLane) {
592  for (SignalGroupCont::const_iterator i = mySignalGroups.begin(); i != mySignalGroups.end(); i++) {
593  SignalGroup* group = (*i).second;
594  if (group->containsIncoming(removed) || group->containsOutgoing(removed)) {
595  group->remap(removed, removedLane, by, byLane);
596  }
597  }
598 }
599 
600 
601 
602 /****************************************************************************/
603