SUMO - Simulation of Urban MObility
NBLoadedTLDef.cpp
Go to the documentation of this file.
00001 /****************************************************************************/
00010 // A loaded (complete) traffic light logic
00011 /****************************************************************************/
00012 // SUMO, Simulation of Urban MObility; see http://sumo.sourceforge.net/
00013 // Copyright (C) 2001-2012 DLR (http://www.dlr.de/) and contributors
00014 /****************************************************************************/
00015 //
00016 //   This file is part of SUMO.
00017 //   SUMO is free software: you can redistribute it and/or modify
00018 //   it under the terms of the GNU General Public License as published by
00019 //   the Free Software Foundation, either version 3 of the License, or
00020 //   (at your option) any later version.
00021 //
00022 /****************************************************************************/
00023 
00024 // ===========================================================================
00025 // included modules
00026 // ===========================================================================
00027 #ifdef _MSC_VER
00028 #include <windows_config.h>
00029 #else
00030 #include <config.h>
00031 #endif
00032 
00033 #include <vector>
00034 #include <set>
00035 #include <cassert>
00036 #include <iterator>
00037 #include <utils/common/MsgHandler.h>
00038 #include <utils/common/ToString.h>
00039 #include <utils/options/OptionsCont.h>
00040 #include "NBTrafficLightLogic.h"
00041 #include "NBTrafficLightDefinition.h"
00042 #include "NBLoadedTLDef.h"
00043 #include "NBNode.h"
00044 
00045 #ifdef CHECK_MEMORY_LEAKS
00046 #include <foreign/nvwa/debug_new.h>
00047 #endif // CHECK_MEMORY_LEAKS
00048 
00049 
00050 // ===========================================================================
00051 // method definitions
00052 // ===========================================================================
00053 /* -------------------------------------------------------------------------
00054  * NBLoadedTLDef::SignalGroup-methods
00055  * ----------------------------------------------------------------------- */
00056 NBLoadedTLDef::SignalGroup::SignalGroup(const std::string& id)
00057     : Named(id) {}
00058 
00059 NBLoadedTLDef::SignalGroup::~SignalGroup() {}
00060 
00061 void
00062 NBLoadedTLDef::SignalGroup::addConnection(const NBConnection& c) {
00063     assert(c.getFromLane() < 0 || c.getFrom()->getNumLanes() > (unsigned int)c.getFromLane());
00064     myConnections.push_back(c);
00065 }
00066 
00067 
00068 void
00069 NBLoadedTLDef::SignalGroup::addPhaseBegin(SUMOTime time, TLColor color) {
00070     myPhases.push_back(PhaseDef(time, color));
00071 }
00072 
00073 
00074 void
00075 NBLoadedTLDef::SignalGroup::setYellowTimes(SUMOTime tRedYellow,
00076         SUMOTime tYellow) {
00077     myTRedYellow = tRedYellow;
00078     myTYellow = tYellow;
00079 }
00080 
00081 
00082 void
00083 NBLoadedTLDef::SignalGroup::sortPhases() {
00084     sort(myPhases.begin(), myPhases.end(),
00085          phase_by_time_sorter());
00086 }
00087 
00088 
00089 void
00090 NBLoadedTLDef::SignalGroup::patchTYellow(SUMOTime tyellow) {
00091     if (myTYellow < tyellow) {
00092         WRITE_WARNING("TYellow of signal group '" + getID() + "' was less than the computed one; patched (was:" + toString<SUMOTime>(myTYellow) + ", is:" + toString<int>(tyellow) + ")");
00093         myTYellow = tyellow;
00094     }
00095 }
00096 
00097 
00098 std::vector<SUMOReal>
00099 NBLoadedTLDef::SignalGroup::getTimes(SUMOTime cycleDuration) const {
00100     // within the phase container, we should have the green and red phases
00101     //  add their times
00102     std::vector<SUMOReal> ret; // !!! time vector
00103     for (std::vector<PhaseDef>::const_iterator i = myPhases.begin(); i != myPhases.end(); i++) {
00104         ret.push_back((SUMOReal)(*i).myTime);
00105     }
00106     // further, we possibly should set the yellow phases
00107     if (myTYellow > 0) {
00108         for (std::vector<PhaseDef>::const_iterator i = myPhases.begin(); i != myPhases.end(); i++) {
00109             if ((*i).myColor == TLCOLOR_RED) {
00110                 SUMOTime time = (SUMOTime)(*i).myTime + myTYellow;
00111                 if (time > cycleDuration) {
00112                     time = time - cycleDuration ;
00113                 }
00114                 ret.push_back((SUMOReal) time);
00115             }
00116         }
00117     }
00118     return ret;
00119 }
00120 
00121 
00122 unsigned int
00123 NBLoadedTLDef::SignalGroup::getLinkNo() const {
00124     return (unsigned int) myConnections.size();
00125 }
00126 
00127 
00128 bool
00129 NBLoadedTLDef::SignalGroup::mayDrive(SUMOTime time) const {
00130     assert(myPhases.size() != 0);
00131     for (std::vector<PhaseDef>::const_reverse_iterator i = myPhases.rbegin(); i != myPhases.rend(); i++) {
00132         SUMOTime nextTime = (*i).myTime;
00133         if (time >= nextTime) {
00134             return (*i).myColor == TLCOLOR_GREEN;
00135         }
00136     }
00137     return (*(myPhases.end() - 1)).myColor == TLCOLOR_GREEN;
00138 }
00139 
00140 
00141 bool
00142 NBLoadedTLDef::SignalGroup::hasYellow(SUMOTime time) const {
00143     bool has_red_now = !mayDrive(time);
00144     bool had_green = mayDrive(time - myTYellow);
00145     return has_red_now && had_green;
00146 }
00147 
00148 
00149 bool
00150 NBLoadedTLDef::SignalGroup::containsConnection(NBEdge* from, NBEdge* to) const {
00151     for (NBConnectionVector::const_iterator i = myConnections.begin(); i != myConnections.end(); i++) {
00152         if ((*i).getFrom() == from && (*i).getTo() == to) {
00153             return true;
00154         }
00155     }
00156     return false;
00157 
00158 }
00159 
00160 
00161 const NBConnection&
00162 NBLoadedTLDef::SignalGroup::getConnection(unsigned int pos) const {
00163     assert(pos < myConnections.size());
00164     return myConnections[pos];
00165 }
00166 
00167 
00168 bool
00169 NBLoadedTLDef::SignalGroup::containsIncoming(NBEdge* from) const {
00170     for (NBConnectionVector::const_iterator i = myConnections.begin(); i != myConnections.end(); i++) {
00171         if ((*i).getFrom() == from) {
00172             return true;
00173         }
00174     }
00175     return false;
00176 }
00177 
00178 
00179 void
00180 NBLoadedTLDef::SignalGroup::remapIncoming(NBEdge* which, const EdgeVector& by) {
00181     NBConnectionVector newConns;
00182     for (NBConnectionVector::iterator i = myConnections.begin(); i != myConnections.end();) {
00183         if ((*i).getFrom() == which) {
00184             NBConnection conn((*i).getFrom(), (*i).getTo());
00185             i = myConnections.erase(i);
00186             for (EdgeVector::const_iterator j = by.begin(); j != by.end(); j++) {
00187                 NBConnection curr(conn);
00188                 if (!curr.replaceFrom(which, *j)) {
00189                     throw ProcessError("Could not replace edge '" + which->getID() + "' by '" + (*j)->getID() + "'.\nUndefined...");
00190                 }
00191                 newConns.push_back(curr);
00192             }
00193         } else {
00194             i++;
00195         }
00196     }
00197     copy(newConns.begin(), newConns.end(),
00198          back_inserter(myConnections));
00199 }
00200 
00201 
00202 bool
00203 NBLoadedTLDef::SignalGroup::containsOutgoing(NBEdge* to) const {
00204     for (NBConnectionVector::const_iterator i = myConnections.begin(); i != myConnections.end(); i++) {
00205         if ((*i).getTo() == to) {
00206             return true;
00207         }
00208     }
00209     return false;
00210 }
00211 
00212 
00213 void
00214 NBLoadedTLDef::SignalGroup::remapOutgoing(NBEdge* which, const EdgeVector& by) {
00215     NBConnectionVector newConns;
00216     for (NBConnectionVector::iterator i = myConnections.begin(); i != myConnections.end();) {
00217         if ((*i).getTo() == which) {
00218             NBConnection conn((*i).getFrom(), (*i).getTo());
00219             i = myConnections.erase(i);
00220             for (EdgeVector::const_iterator j = by.begin(); j != by.end(); j++) {
00221                 NBConnection curr(conn);
00222                 if (!curr.replaceTo(which, *j)) {
00223                     throw ProcessError("Could not replace edge '" + which->getID() + "' by '" + (*j)->getID() + "'.\nUndefined...");
00224                 }
00225                 newConns.push_back(curr);
00226             }
00227         } else {
00228             i++;
00229         }
00230     }
00231     copy(newConns.begin(), newConns.end(),
00232          back_inserter(myConnections));
00233 }
00234 
00235 
00236 void
00237 NBLoadedTLDef::SignalGroup::remap(NBEdge* removed, int removedLane,
00238                                   NBEdge* by, int byLane) {
00239     for (NBConnectionVector::iterator i = myConnections.begin(); i != myConnections.end(); i++) {
00240         if ((*i).getTo() == removed
00241                 &&
00242                 ((*i).getToLane() == removedLane
00243                  ||
00244                  (*i).getToLane() == -1)) {
00245             (*i).replaceTo(removed, removedLane, by, byLane);
00246 
00247         } else if ((*i).getTo() == removed && removedLane == -1) {
00248             (*i).replaceTo(removed, by);
00249         }
00250 
00251         if ((*i).getFrom() == removed
00252                 &&
00253                 ((*i).getFromLane() == removedLane
00254                  ||
00255                  (*i).getFromLane() == -1)) {
00256             (*i).replaceFrom(removed, removedLane, by, byLane);
00257 
00258         } else if ((*i).getFrom() == removed && removedLane == -1) {
00259             (*i).replaceFrom(removed, by);
00260         }
00261     }
00262 }
00263 
00264 
00265 /* -------------------------------------------------------------------------
00266  * NBLoadedTLDef::Phase-methods
00267  * ----------------------------------------------------------------------- */
00268 NBLoadedTLDef::NBLoadedTLDef(const std::string& id,
00269                              const std::vector<NBNode*> &junctions)
00270     : NBTrafficLightDefinition(id, junctions, DefaultProgramID) {}
00271 
00272 
00273 NBLoadedTLDef::NBLoadedTLDef(const std::string& id, NBNode* junction)
00274     : NBTrafficLightDefinition(id, junction, DefaultProgramID) {}
00275 
00276 
00277 NBLoadedTLDef::NBLoadedTLDef(const std::string& id)
00278     : NBTrafficLightDefinition(id, DefaultProgramID) {}
00279 
00280 
00281 NBLoadedTLDef::~NBLoadedTLDef() {
00282     for (SignalGroupCont::iterator i = mySignalGroups.begin(); i != mySignalGroups.end(); ++i) {
00283         delete(*i).second;
00284     }
00285 }
00286 
00287 
00288 NBTrafficLightLogic*
00289 NBLoadedTLDef::myCompute(const NBEdgeCont& ec, unsigned int brakingTime) {
00290     MsgHandler::getWarningInstance()->clear(); // !!!
00291     NBLoadedTLDef::SignalGroupCont::const_iterator i;
00292     // compute the switching times
00293     std::set<SUMOReal> tmpSwitchTimes;
00294     for (i = mySignalGroups.begin(); i != mySignalGroups.end(); i++) {
00295         NBLoadedTLDef::SignalGroup* group = (*i).second;
00296         // needed later
00297         group->sortPhases();
00298         // patch the yellow time for this group
00299         if (OptionsCont::getOptions().getBool("tls.yellow.patch-small")) {
00300             group->patchTYellow(brakingTime);
00301         }
00302         // copy the now valid times into the container
00303         //  both the given red and green phases are added and also the
00304         //  yellow times
00305         std::vector<SUMOReal> gtimes = group->getTimes(myCycleDuration);
00306         for (std::vector<SUMOReal>::const_iterator k = gtimes.begin(); k != gtimes.end(); k++) {
00307             tmpSwitchTimes.insert(*k);
00308         }
00309     }
00310     std::vector<SUMOReal> switchTimes;
00311     copy(tmpSwitchTimes.begin(), tmpSwitchTimes.end(), back_inserter(switchTimes));
00312     sort(switchTimes.begin(), switchTimes.end());
00313 
00314     // count the signals
00315     unsigned int noSignals = 0;
00316     for (i = mySignalGroups.begin(); i != mySignalGroups.end(); i++) {
00317         noSignals += (*i).second->getLinkNo();
00318     }
00319     // build the phases
00320     NBTrafficLightLogic* logic = new NBTrafficLightLogic(getID(), getProgramID(), noSignals);
00321     for (std::vector<SUMOReal>::iterator l = switchTimes.begin(); l != switchTimes.end(); l++) {
00322         // compute the duration of the current phase
00323         unsigned int duration;
00324         if (l != switchTimes.end() - 1) {
00325             // get from the difference to the next switching time
00326             duration = (unsigned int)((*(l + 1)) - (*l));
00327         } else {
00328             // get from the differenc to the first switching time
00329             duration = (unsigned int)(myCycleDuration - (*l) + * (switchTimes.begin())) ;
00330         }
00331         // no information about yellow times will be generated
00332         assert((*l) >= 0);
00333         logic->addStep(TIME2STEPS(duration), buildPhaseState(ec, (unsigned int)(*l)));
00334     }
00335     // check whether any warnings were printed
00336     if (MsgHandler::getWarningInstance()->wasInformed()) {
00337         WRITE_WARNING("During computation of traffic light '" + getID() + "'.");
00338     }
00339     logic->closeBuilding();
00340     return logic;
00341 }
00342 
00343 
00344 void
00345 NBLoadedTLDef::setTLControllingInformation(const NBEdgeCont& ec) const {
00346     // assign the links to the connections
00347     unsigned int pos = 0;
00348     for (SignalGroupCont::const_iterator m = mySignalGroups.begin(); m != mySignalGroups.end(); m++) {
00349         SignalGroup* group = (*m).second;
00350         unsigned int linkNo = group->getLinkNo();
00351         for (unsigned int j = 0; j < linkNo; j++) {
00352             const NBConnection& conn = group->getConnection(j);
00353             assert(conn.getFromLane() < 0 || (int) conn.getFrom()->getNumLanes() > conn.getFromLane());
00354             NBConnection tst(conn);
00355             tst.setTLIndex(pos);
00356             if (tst.check(ec)) {
00357                 NBEdge* edge = conn.getFrom();
00358                 if (edge->setControllingTLInformation(tst, getID())) {
00359                     pos++;
00360                 }
00361             } else {
00362                 WRITE_WARNING("Could not set signal on connection (signal: " + getID() + ", group: " + group->getID() + ")");
00363             }
00364         }
00365     }
00366 }
00367 
00368 
00369 std::string
00370 NBLoadedTLDef::buildPhaseState(const NBEdgeCont& ec, unsigned int time) const {
00371     unsigned int pos = 0;
00372     std::string state;
00373     // set the green and yellow information first;
00374     //  the information whether other have to break needs those masks
00375     //  completely filled
00376     for (SignalGroupCont::const_iterator i = mySignalGroups.begin(); i != mySignalGroups.end(); i++) {
00377         SignalGroup* group = (*i).second;
00378         unsigned int linkNo = group->getLinkNo();
00379         bool mayDrive = group->mayDrive(time);
00380         bool hasYellow = group->hasYellow(time);
00381         char c = 'r';
00382         if (mayDrive) {
00383             c = 'g';
00384         }
00385         if (hasYellow) {
00386             c = 'y';
00387         }
00388         for (unsigned int j = 0; j < linkNo; j++) {
00389             const NBConnection& conn = group->getConnection(j);
00390             NBConnection assConn(conn);
00391             // assert that the connection really exists
00392             if (assConn.check(ec)) {
00393                 state = state + c;
00394                 ++pos;
00395             }
00396         }
00397     }
00398     // set the braking mask
00399     pos = 0;
00400     for (SignalGroupCont::const_iterator i = mySignalGroups.begin(); i != mySignalGroups.end(); i++) {
00401         SignalGroup* group = (*i).second;
00402         unsigned int linkNo = group->getLinkNo();
00403         for (unsigned int j = 0; j < linkNo; j++) {
00404             const NBConnection& conn = group->getConnection(j);
00405             NBConnection assConn(conn);
00406             if (assConn.check(ec)) {
00407                 if (!mustBrake(ec, assConn, state, pos)) {
00408                     if (state[pos] == 'g') {
00409                         state[pos] = 'G';
00410                     }
00411                     if (state[pos] == 'y') {
00412                         state[pos] = 'Y';
00413                     }
00414                 }
00415                 pos++;
00416             }
00417         }
00418     }
00419     return state;
00420 }
00421 
00422 
00423 bool
00424 NBLoadedTLDef::mustBrake(const NBEdgeCont& ec,
00425                          const NBConnection& possProhibited,
00426                          const std::string& state,
00427                          unsigned int strmpos) const {
00428     // check whether the stream has red
00429     if (state[strmpos] != 'g' && state[strmpos] != 'G') {
00430         return true;
00431     }
00432 
00433     // check whether another stream which has green is a higher
00434     //  priorised foe to the given
00435     unsigned int pos = 0;
00436     for (SignalGroupCont::const_iterator i = mySignalGroups.begin(); i != mySignalGroups.end(); i++) {
00437         SignalGroup* group = (*i).second;
00438         // get otherlinks that have green
00439         unsigned int linkNo = group->getLinkNo();
00440         for (unsigned int j = 0; j < linkNo; j++) {
00441             // get the current connection (possible foe)
00442             const NBConnection& other = group->getConnection(j);
00443             NBConnection possProhibitor(other);
00444             // if the connction ist still valid ...
00445             if (possProhibitor.check(ec)) {
00446                 // ... do nothing if it starts at the same edge
00447                 if (possProhibited.getFrom() == possProhibitor.getFrom()) {
00448                     pos++;
00449                     continue;
00450                 }
00451                 if (state[pos] == 'g' || state[pos] == 'G') {
00452                     if (NBTrafficLightDefinition::mustBrake(possProhibited, possProhibitor, true)) {
00453                         return true;
00454                     }
00455                 }
00456                 pos++;
00457             }
00458         }
00459     }
00460     return false;
00461 }
00462 
00463 
00464 void
00465 NBLoadedTLDef::collectNodes() {
00466     myControlledNodes.clear();
00467     SignalGroupCont::const_iterator m;
00468     for (m = mySignalGroups.begin(); m != mySignalGroups.end(); m++) {
00469         SignalGroup* group = (*m).second;
00470         unsigned int linkNo = group->getLinkNo();
00471         for (unsigned int j = 0; j < linkNo; j++) {
00472             const NBConnection& conn = group->getConnection(j);
00473             NBEdge* edge = conn.getFrom();
00474             NBNode* node = edge->getToNode();
00475             myControlledNodes.push_back(node);
00476         }
00477     }
00478     std::sort(myControlledNodes.begin(), myControlledNodes.end(), NBNode::nodes_by_id_sorter());
00479 }
00480 
00481 
00482 void
00483 NBLoadedTLDef::collectLinks() {
00484     myControlledLinks.clear();
00485     // build the list of links which are controled by the traffic light
00486     for (EdgeVector::iterator i = myIncomingEdges.begin(); i != myIncomingEdges.end(); i++) {
00487         NBEdge* incoming = *i;
00488         unsigned int noLanes = incoming->getNumLanes();
00489         for (unsigned int j = 0; j < noLanes; j++) {
00490             std::vector<NBEdge::Connection> elv = incoming->getConnectionsFromLane(j);
00491             for (std::vector<NBEdge::Connection>::iterator k = elv.begin(); k != elv.end(); k++) {
00492                 NBEdge::Connection el = *k;
00493                 if (el.toEdge != 0) {
00494                     myControlledLinks.push_back(NBConnection(incoming, j, el.toEdge, el.toLane));
00495                 }
00496             }
00497         }
00498     }
00499 }
00500 
00501 
00502 NBLoadedTLDef::SignalGroup*
00503 NBLoadedTLDef::findGroup(NBEdge* from, NBEdge* to) const {
00504     for (SignalGroupCont::const_iterator i = mySignalGroups.begin(); i != mySignalGroups.end(); i++) {
00505         if ((*i).second->containsConnection(from, to)) {
00506             return (*i).second;
00507         }
00508     }
00509     return 0;
00510 }
00511 
00512 
00513 bool
00514 NBLoadedTLDef::addToSignalGroup(const std::string& groupid,
00515                                 const NBConnection& connection) {
00516     if (mySignalGroups.find(groupid) == mySignalGroups.end()) {
00517         return false;
00518     }
00519     mySignalGroups[groupid]->addConnection(connection);
00520     NBNode* n1 = connection.getFrom()->getToNode();
00521     if (n1 != 0) {
00522         addNode(n1);
00523         n1->addTrafficLight(this);
00524     }
00525     NBNode* n2 = connection.getTo()->getFromNode();
00526     if (n2 != 0) {
00527         addNode(n2);
00528         n2->addTrafficLight(this);
00529     }
00530     return true;
00531 }
00532 
00533 
00534 bool
00535 NBLoadedTLDef::addToSignalGroup(const std::string& groupid,
00536                                 const NBConnectionVector& connections) {
00537     bool ok = true;
00538     for (NBConnectionVector::const_iterator i = connections.begin(); i != connections.end(); i++) {
00539         ok &= addToSignalGroup(groupid, *i);
00540     }
00541     return ok;
00542 }
00543 
00544 
00545 void
00546 NBLoadedTLDef::addSignalGroup(const std::string& id) {
00547     assert(mySignalGroups.find(id) == mySignalGroups.end());
00548     mySignalGroups[id] = new SignalGroup(id);
00549 }
00550 
00551 
00552 void
00553 NBLoadedTLDef::addSignalGroupPhaseBegin(const std::string& groupid, SUMOTime time,
00554                                         TLColor color) {
00555     assert(mySignalGroups.find(groupid) != mySignalGroups.end());
00556     mySignalGroups[groupid]->addPhaseBegin(time, color);
00557 }
00558 
00559 void
00560 NBLoadedTLDef::setSignalYellowTimes(const std::string& groupid,
00561                                     SUMOTime myTRedYellow, SUMOTime myTYellow) {
00562     assert(mySignalGroups.find(groupid) != mySignalGroups.end());
00563     mySignalGroups[groupid]->setYellowTimes(myTRedYellow, myTYellow);
00564 }
00565 
00566 
00567 void
00568 NBLoadedTLDef::setCycleDuration(unsigned int cycleDur) {
00569     myCycleDuration = cycleDur;
00570 }
00571 
00572 
00573 void
00574 NBLoadedTLDef::remapRemoved(NBEdge* removed,
00575                             const EdgeVector& incoming,
00576                             const EdgeVector& outgoing) {
00577     for (SignalGroupCont::const_iterator i = mySignalGroups.begin(); i != mySignalGroups.end(); i++) {
00578         SignalGroup* group = (*i).second;
00579         if (group->containsIncoming(removed)) {
00580             group->remapIncoming(removed, incoming);
00581         }
00582         if (group->containsOutgoing(removed)) {
00583             group->remapOutgoing(removed, outgoing);
00584         }
00585     }
00586 }
00587 
00588 
00589 void
00590 NBLoadedTLDef::replaceRemoved(NBEdge* removed, int removedLane,
00591                               NBEdge* by, int byLane) {
00592     for (SignalGroupCont::const_iterator i = mySignalGroups.begin(); i != mySignalGroups.end(); i++) {
00593         SignalGroup* group = (*i).second;
00594         if (group->containsIncoming(removed) || group->containsOutgoing(removed)) {
00595             group->remap(removed, removedLane, by, byLane);
00596         }
00597     }
00598 }
00599 
00600 
00601 
00602 /****************************************************************************/
00603 
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Friends Defines