SUMO - Simulation of Urban MObility

NBOwnTLDef.cpp

Go to the documentation of this file.
00001 /****************************************************************************/
00007 // A traffic light logics which must be computed (only nodes/edges are given)
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 // ===========================================================================
00022 // included modules
00023 // ===========================================================================
00024 #ifdef _MSC_VER
00025 #include <windows_config.h>
00026 #else
00027 #include <config.h>
00028 #endif
00029 
00030 #include <vector>
00031 #include <cassert>
00032 #include "NBTrafficLightDefinition.h"
00033 #include "NBNode.h"
00034 #include "NBOwnTLDef.h"
00035 #include "NBTrafficLightLogic.h"
00036 #include <utils/common/MsgHandler.h>
00037 #include <utils/common/UtilExceptions.h>
00038 #include <utils/common/ToString.h>
00039 #include <utils/options/OptionsCont.h>
00040 #include <utils/options/Option.h>
00041 
00042 #ifdef CHECK_MEMORY_LEAKS
00043 #include <foreign/nvwa/debug_new.h>
00044 #endif // CHECK_MEMORY_LEAKS
00045 
00046 
00047 // ===========================================================================
00048 // member method definitions
00049 // ===========================================================================
00050 NBOwnTLDef::NBOwnTLDef(const std::string& id,
00051                        const std::vector<NBNode*> &junctions) throw()
00052     : NBTrafficLightDefinition(id, junctions, DefaultProgramID) {}
00053 
00054 
00055 NBOwnTLDef::NBOwnTLDef(const std::string& id, NBNode* junction) throw()
00056     : NBTrafficLightDefinition(id, junction, DefaultProgramID) {}
00057 
00058 
00059 NBOwnTLDef::NBOwnTLDef(const std::string& id) throw()
00060     : NBTrafficLightDefinition(id, DefaultProgramID) {}
00061 
00062 
00063 NBOwnTLDef::~NBOwnTLDef() throw() {}
00064 
00065 
00066 int
00067 NBOwnTLDef::getToPrio(const NBEdge* const e) throw() {
00068     return e->getJunctionPriority(e->getToNode());
00069 }
00070 
00071 
00072 SUMOReal
00073 NBOwnTLDef::getDirectionalWeight(LinkDirection dir) throw() {
00074     switch (dir) {
00075     case LINKDIR_STRAIGHT:
00076     case LINKDIR_PARTLEFT:
00077     case LINKDIR_PARTRIGHT:
00078         return 2.;
00079     case LINKDIR_LEFT:
00080     case LINKDIR_RIGHT:
00081         return .5;
00082     case LINKDIR_NODIR:
00083     case LINKDIR_TURN:
00084         return 0;
00085     }
00086     return 0;
00087 }
00088 
00089 SUMOReal
00090 NBOwnTLDef::computeUnblockedWeightedStreamNumber(const NBEdge* const e1, const NBEdge* const e2) throw() {
00091     SUMOReal val = 0;
00092     for (unsigned int e1l=0; e1l<e1->getNumLanes(); e1l++) {
00093         std::vector<NBEdge::Connection> approached1 = e1->getConnectionsFromLane(e1l);
00094         for (unsigned int e2l=0; e2l<e2->getNumLanes(); e2l++) {
00095             std::vector<NBEdge::Connection> approached2 = e2->getConnectionsFromLane(e2l);
00096             for (std::vector<NBEdge::Connection>::iterator e1c=approached1.begin(); e1c!=approached1.end(); ++e1c) {
00097                 if (e1->getTurnDestination()==(*e1c).toEdge) {
00098                     continue;
00099                 }
00100                 for (std::vector<NBEdge::Connection>::iterator e2c=approached2.begin(); e2c!=approached2.end(); ++e2c) {
00101                     if (e2->getTurnDestination()==(*e2c).toEdge) {
00102                         continue;
00103                     }
00104                     if (!foes(e1, (*e1c).toEdge, e2, (*e2c).toEdge)) {
00105                         val += getDirectionalWeight(e1->getToNode()->getDirection(e1, (*e1c).toEdge));
00106                         val += getDirectionalWeight(e2->getToNode()->getDirection(e2, (*e2c).toEdge));
00107                     }
00108                 }
00109             }
00110         }
00111     }
00112     return val;
00113 }
00114 
00115 
00116 std::pair<NBEdge*, NBEdge*>
00117 NBOwnTLDef::getBestCombination(const EdgeVector& edges) throw() {
00118     std::pair<NBEdge*, NBEdge*> bestPair(static_cast<NBEdge*>(0), static_cast<NBEdge*>(0));
00119     SUMOReal bestValue = -1;
00120     for (EdgeVector::const_iterator i=edges.begin(); i!=edges.end(); ++i) {
00121         for (EdgeVector::const_iterator j=i+1; j!=edges.end(); ++j) {
00122             SUMOReal value = computeUnblockedWeightedStreamNumber(*i, *j);
00123             if (value>bestValue) {
00124                 bestValue = value;
00125                 bestPair = std::pair<NBEdge*, NBEdge*>(*i, *j);
00126             } else if (value==bestValue) {
00127                 SUMOReal ca = GeomHelper::getMinAngleDiff((*i)->getAngle(*(*i)->getToNode()), (*j)->getAngle(*(*j)->getToNode()));
00128                 SUMOReal oa = GeomHelper::getMinAngleDiff(bestPair.first->getAngle(*bestPair.first->getToNode()), bestPair.second->getAngle(*bestPair.second->getToNode()));
00129                 if (oa<ca) {
00130                     bestPair = std::pair<NBEdge*, NBEdge*>(*i, *j);
00131                 }
00132             }
00133         }
00134     }
00135     return bestPair;
00136 }
00137 
00138 
00139 std::pair<NBEdge*, NBEdge*>
00140 NBOwnTLDef::getBestPair(EdgeVector& incoming) throw() {
00141     if (incoming.size()==1) {
00142         // only one there - return the one
00143         std::pair<NBEdge*, NBEdge*> ret(*incoming.begin(), static_cast<NBEdge*>(0));
00144         incoming.clear();
00145         return ret;
00146     }
00147     // determine the best combination
00148     //  by priority, first
00149     EdgeVector used;
00150     std::sort(incoming.begin(), incoming.end(), edge_by_incoming_priority_sorter());
00151     used.push_back(*incoming.begin()); // the first will definitely be used
00152     // get the ones with the same priority
00153     int prio = getToPrio(*used.begin());
00154     for (EdgeVector::iterator i=incoming.begin()+1; i!=incoming.end()&&prio!=getToPrio(*i); ++i) {
00155         used.push_back(*i);
00156     }
00157     //  if there only lower priorised, use these, too
00158     if (used.size()<2) {
00159         used = incoming;
00160     }
00161     std::pair<NBEdge*, NBEdge*> ret = getBestCombination(used);
00162     incoming.erase(find(incoming.begin(), incoming.end(), ret.first));
00163     incoming.erase(find(incoming.begin(), incoming.end(), ret.second));
00164     return ret;
00165 }
00166 
00167 
00168 NBTrafficLightLogic*
00169 NBOwnTLDef::myCompute(const NBEdgeCont&,
00170                       unsigned int brakingTimeSeconds) throw() {
00171     SUMOTime brakingTime = TIME2STEPS(brakingTimeSeconds);
00172     // build complete lists first
00173     const EdgeVector& incoming = getIncomingEdges();
00174     EdgeVector fromEdges, toEdges;
00175     std::vector<bool> isLeftMoverV, isTurnaround;
00176     unsigned int noLanesAll = 0;
00177     unsigned int noLinksAll = 0;
00178     for (unsigned int i1=0; i1<incoming.size(); i1++) {
00179         unsigned int noLanes = incoming[i1]->getNumLanes();
00180         noLanesAll += noLanes;
00181         for (unsigned int i2=0; i2<noLanes; i2++) {
00182             NBEdge* fromEdge = incoming[i1];
00183             std::vector<NBEdge::Connection> approached = fromEdge->getConnectionsFromLane(i2);
00184             noLinksAll += (unsigned int) approached.size();
00185             for (unsigned int i3=0; i3<approached.size(); i3++) {
00186                 if (!fromEdge->mayBeTLSControlled(i2, approached[i3].toEdge, approached[i3].toLane)) {
00187                     --noLinksAll;
00188                     continue;
00189                 }
00190                 assert(i3<approached.size());
00191                 NBEdge* toEdge = approached[i3].toEdge;
00192                 fromEdges.push_back(fromEdge);
00193                 //myFromLanes.push_back(i2);
00194                 toEdges.push_back(toEdge);
00195                 if (toEdge!=0) {
00196                     isLeftMoverV.push_back(
00197                         isLeftMover(fromEdge, toEdge)
00198                         ||
00199                         fromEdge->isTurningDirectionAt(fromEdge->getToNode(), toEdge));
00200 
00201                     isTurnaround.push_back(
00202                         fromEdge->isTurningDirectionAt(
00203                             fromEdge->getToNode(), toEdge));
00204                 } else {
00205                     isLeftMoverV.push_back(true);
00206                     isTurnaround.push_back(true);
00207                 }
00208             }
00209         }
00210     }
00211 
00212     NBTrafficLightLogic* logic = new NBTrafficLightLogic(getID(), getProgramID(), noLinksAll);
00213     EdgeVector toProc = incoming;
00214     // build all phases
00215     while (toProc.size()>0) {
00216         std::pair<NBEdge*, NBEdge*> chosen;
00217         if (incoming.size()==2) {
00218             chosen = std::pair<NBEdge*, NBEdge*>(toProc[0], static_cast<NBEdge*>(0));
00219             toProc.erase(toProc.begin());
00220         } else {
00221             chosen = getBestPair(toProc);
00222         }
00223         unsigned int pos = 0;
00224         SUMOTime duration = TIME2STEPS(OptionsCont::getOptions().getInt("tls.green.time"));
00225         std::string state((size_t) noLinksAll, 'o');
00226         // plain straight movers
00227         for (unsigned int i1=0; i1<(unsigned int) incoming.size(); ++i1) {
00228             NBEdge* fromEdge = incoming[i1];
00229             bool inChosen = fromEdge==chosen.first||fromEdge==chosen.second;//chosen.find(fromEdge)!=chosen.end();
00230             unsigned int noLanes = fromEdge->getNumLanes();
00231             for (unsigned int i2=0; i2<noLanes; i2++) {
00232                 std::vector<NBEdge::Connection> approached = fromEdge->getConnectionsFromLane(i2);
00233                 for (unsigned int i3=0; i3<approached.size(); ++i3) {
00234                     if (!fromEdge->mayBeTLSControlled(i2, approached[i3].toEdge, approached[i3].toLane)) {
00235                         continue;
00236                     }
00237                     if (inChosen) {
00238                         state[pos] = 'G';
00239                     } else {
00240                         state[pos] = 'r';
00241                     }
00242                     ++pos;
00243                 }
00244             }
00245         }
00246         // correct behaviour for those that are not in chosen, but may drive, though
00247         for (unsigned int i1=0; i1<pos; ++i1) {
00248             if (state[i1]=='G') {
00249                 continue;
00250             }
00251             bool isForbidden = false;
00252             for (unsigned int i2=0; i2<pos&&!isForbidden; ++i2) {
00253                 if (state[i2]=='G'&&!isTurnaround[i2]&&
00254                         (forbids(fromEdges[i2], toEdges[i2], fromEdges[i1], toEdges[i1], true)||forbids(fromEdges[i1], toEdges[i1], fromEdges[i2], toEdges[i2], true))) {
00255                     isForbidden = true;
00256                 }
00257             }
00258             if (!isForbidden) {
00259                 state[i1] = 'G';
00260             }
00261         }
00262         // correct behaviour for those that have to wait (mainly left-mover)
00263         bool haveForbiddenLeftMover = false;
00264         for (unsigned int i1=0; i1<pos; ++i1) {
00265             if (state[i1]!='G') {
00266                 continue;
00267             }
00268             for (unsigned int i2=0; i2<pos; ++i2) {
00269                 if ((state[i2]=='G'||state[i2]=='g')&&forbids(fromEdges[i2], toEdges[i2], fromEdges[i1], toEdges[i1], true)) {
00270                     state[i1] = 'g';
00271                     if (!isTurnaround[i1]) {
00272                         haveForbiddenLeftMover = true;
00273                     }
00274                 }
00275             }
00276         }
00277 
00278         // add step
00279         logic->addStep(duration, state);
00280 
00281         if (brakingTime>0) {
00282             // build yellow (straight)
00283             duration = brakingTime;
00284             for (unsigned int i1=0; i1<pos; ++i1) {
00285                 if (state[i1]!='G'&&state[i1]!='g') {
00286                     continue;
00287                 }
00288                 if ((state[i1]>='a'&&state[i1]<='z')&&haveForbiddenLeftMover) {
00289                     continue;
00290                 }
00291                 state[i1] = 'y';
00292             }
00293             // add step
00294             logic->addStep(duration, state);
00295         }
00296 
00297         if (haveForbiddenLeftMover) {
00298             // build left green
00299             duration = TIME2STEPS(6);
00300             for (unsigned int i1=0; i1<pos; ++i1) {
00301                 if (state[i1]=='Y'||state[i1]=='y') {
00302                     state[i1] = 'r';
00303                     continue;
00304                 }
00305                 if (state[i1]=='g') {
00306                     state[i1] = 'G';
00307                 }
00308             }
00309             // add step
00310             logic->addStep(duration, state);
00311 
00312             // build left yellow
00313             if (brakingTime>0) {
00314                 duration = brakingTime;
00315                 for (unsigned int i1=0; i1<pos; ++i1) {
00316                     if (state[i1]!='G'&&state[i1]!='g') {
00317                         continue;
00318                     }
00319                     state[i1] = 'y';
00320                 }
00321                 // add step
00322                 logic->addStep(duration, state);
00323             }
00324         }
00325     }
00326     if (logic->getDuration()>0) {
00327         return logic;
00328     } else {
00329         delete logic;
00330         return 0;
00331     }
00332 
00333 }
00334 
00335 
00336 void
00337 NBOwnTLDef::collectNodes() throw() {}
00338 
00339 
00340 void
00341 NBOwnTLDef::collectLinks() throw(ProcessError) {
00342     myControlledLinks.clear();
00343     // build the list of links which are controled by the traffic light
00344     for (EdgeVector::iterator i=myIncomingEdges.begin(); i!=myIncomingEdges.end(); i++) {
00345         NBEdge* incoming = *i;
00346         unsigned int noLanes = incoming->getNumLanes();
00347         for (unsigned int j=0; j<noLanes; j++) {
00348             std::vector<NBEdge::Connection> connected = incoming->getConnectionsFromLane(j);
00349             for (std::vector<NBEdge::Connection>::iterator k=connected.begin(); k!=connected.end(); k++) {
00350                 const NBEdge::Connection& el = *k;
00351                 if (incoming->mayBeTLSControlled(el.fromLane, el.toEdge, el.toLane)) {
00352                     if (el.toEdge!=0&&el.toLane>=(int) el.toEdge->getNumLanes()) {
00353                         throw ProcessError("Connection '" + incoming->getID() + "_" + toString(j) + "->" + el.toEdge->getID() + "_" + toString(el.toLane) + "' yields in a not existing lane.");
00354                     }
00355                     int tlIndex = (int)myControlledLinks.size();
00356                     myControlledLinks.push_back(NBConnection(incoming, el.fromLane, el.toEdge, el.toLane, tlIndex));
00357                 }
00358             }
00359         }
00360     }
00361 }
00362 
00363 
00364 void
00365 NBOwnTLDef::setParticipantsInformation() throw() {
00366     // assign participating nodes to the request
00367     collectNodes();
00368     // collect the information about participating edges and links
00369     collectEdges();
00370     collectLinks();
00371 }
00372 
00373 
00374 void
00375 NBOwnTLDef::setTLControllingInformation(const NBEdgeCont&) const throw() {
00376     // set the information about the link's positions within the tl into the
00377     //  edges the links are starting at, respectively
00378     for (NBConnectionVector::const_iterator j=myControlledLinks.begin(); j!=myControlledLinks.end(); ++j) {
00379         const NBConnection& conn = *j;
00380         NBEdge* edge = conn.getFrom();
00381         edge->setControllingTLInformation(conn, getID());
00382     }
00383 }
00384 
00385 
00386 void
00387 NBOwnTLDef::remapRemoved(NBEdge* /*removed*/, const EdgeVector& /*incoming*/,
00388                          const EdgeVector& /*outgoing*/) throw() {}
00389 
00390 
00391 void
00392 NBOwnTLDef::replaceRemoved(NBEdge* /*removed*/, int /*removedLane*/,
00393                            NBEdge* /*by*/, int /*byLane*/) throw() {}
00394 
00395 
00396 
00397 /****************************************************************************/
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Friends Defines