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

Generated on Wed May 5 00:06:33 2010 for Sumo - Simulation of Urban MObility by  doxygen 1.5.6