SUMO - Simulation of Urban MObility

NBLoadedTLDef.cpp

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