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 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 // ===========================================================================
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) {}
00053 
00054 
00055 NBOwnTLDef::NBOwnTLDef(const std::string &id, NBNode *junction) throw()
00056         : NBTrafficLightDefinition(id, junction) {}
00057 
00058 
00059 NBOwnTLDef::NBOwnTLDef(const std::string &id) throw()
00060         : NBTrafficLightDefinition(id) {}
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(NBMMLDirection dir) throw() {
00074     switch (dir) {
00075     case MMLDIR_STRAIGHT:
00076     case MMLDIR_PARTLEFT:
00077     case MMLDIR_PARTRIGHT:
00078         return 2.;
00079     case MMLDIR_LEFT:
00080     case MMLDIR_RIGHT:
00081         return .5;
00082     case MMLDIR_NODIR:
00083     case MMLDIR_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->getNoLanes(); e1l++) {
00093         std::vector<NBEdge::Connection> approached1 = e1->getConnectionsFromLane(e1l);
00094         for (unsigned int e2l=0; e2l<e2->getNoLanes(); 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()->getMMLDirection(e1, (*e1c).toEdge));
00106                         val += getDirectionalWeight(e2->getToNode()->getMMLDirection(e2, (*e2c).toEdge));
00107                     }
00108                 }
00109             }
00110         }
00111     }
00112     return val;
00113 }
00114 
00115 
00116 std::pair<NBEdge*, NBEdge*>
00117 NBOwnTLDef::getBestCombination(const std::vector<NBEdge*> &edges) throw() {
00118     std::pair<NBEdge*, NBEdge*> bestPair(0,0);
00119     SUMOReal bestValue = -1;
00120     for (std::vector<NBEdge*>::const_iterator i=edges.begin(); i!=edges.end(); ++i) {
00121         for (std::vector<NBEdge*>::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(std::vector<NBEdge*> &incoming) throw() {
00141     if (incoming.size()==1) {
00142         // only one there - return the one
00143         std::pair<NBEdge*, NBEdge*> ret(*incoming.begin(), 0);
00144         incoming.clear();
00145         return ret;
00146     }
00147     // determine the best combination
00148     //  by priority, first
00149     std::vector<NBEdge*> 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 (std::vector<NBEdge*>::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 brakingTime) throw() {
00171     // build complete lists first
00172     const EdgeVector &incoming = getIncomingEdges();
00173     std::vector<NBEdge*> fromEdges, toEdges;
00174     std::vector<bool> isLeftMoverV, isTurnaround;
00175     unsigned int noLanesAll = 0;
00176     unsigned int noLinksAll = 0;
00177     for (unsigned int i1=0; i1<incoming.size(); i1++) {
00178         unsigned int noLanes = incoming[i1]->getNoLanes();
00179         noLanesAll += noLanes;
00180         for (unsigned int i2=0; i2<noLanes; i2++) {
00181             NBEdge *fromEdge = incoming[i1];
00182             std::vector<NBEdge::Connection> approached = fromEdge->getConnectionsFromLane(i2);
00183             noLinksAll += (unsigned int) approached.size();
00184             for (unsigned int i3=0; i3<approached.size(); i3++) {
00185                 if (!fromEdge->mayBeTLSControlled(i2, approached[i3].toEdge, approached[i3].toLane)) {
00186                     --noLinksAll;
00187                     continue;
00188                 }
00189                 assert(i3<approached.size());
00190                 NBEdge *toEdge = approached[i3].toEdge;
00191                 fromEdges.push_back(fromEdge);
00192                 //myFromLanes.push_back(i2);
00193                 toEdges.push_back(toEdge);
00194                 if (toEdge!=0) {
00195                     isLeftMoverV.push_back(
00196                         isLeftMover(fromEdge, toEdge)
00197                         ||
00198                         fromEdge->isTurningDirectionAt(fromEdge->getToNode(), toEdge));
00199 
00200                     isTurnaround.push_back(
00201                         fromEdge->isTurningDirectionAt(
00202                             fromEdge->getToNode(), toEdge));
00203                 } else {
00204                     isLeftMoverV.push_back(true);
00205                     isTurnaround.push_back(true);
00206                 }
00207             }
00208         }
00209     }
00210 
00211     NBTrafficLightLogic *logic = new NBTrafficLightLogic(getID(), "0", noLinksAll);
00212     std::vector<NBEdge*> toProc = incoming;
00213     // build all phases
00214     while (toProc.size()>0) {
00215         std::pair<NBEdge*, NBEdge*> chosen;
00216         if (incoming.size()==2) {
00217             chosen = std::pair<NBEdge*, NBEdge*>(toProc[0], 0);
00218             toProc.erase(toProc.begin());
00219         } else {
00220             chosen = getBestPair(toProc);
00221         }
00222         unsigned int pos = 0;
00223         unsigned int duration = 31;
00224         if (OptionsCont::getOptions().isSet("traffic-light-green")) {
00225             duration = OptionsCont::getOptions().getInt("traffic-light-green");
00226         }
00227         std::string state((size_t) noLinksAll, 'o');
00228         // plain straight movers
00229         for (unsigned int i1=0; i1<(unsigned int) incoming.size(); ++i1) {
00230             NBEdge *fromEdge = incoming[i1];
00231             bool inChosen = fromEdge==chosen.first||fromEdge==chosen.second;//chosen.find(fromEdge)!=chosen.end();
00232             unsigned int noLanes = fromEdge->getNoLanes();
00233             for (unsigned int i2=0; i2<noLanes; i2++) {
00234                 std::vector<NBEdge::Connection> approached = fromEdge->getConnectionsFromLane(i2);
00235                 for (unsigned int i3=0; i3<approached.size(); ++i3) {
00236                     if (!fromEdge->mayBeTLSControlled(i2, approached[i3].toEdge, approached[i3].toLane)) {
00237                         continue;
00238                     }
00239                     if (inChosen) {
00240                         state[pos] = 'G';
00241                     } else {
00242                         state[pos] = 'r';
00243                     }
00244                     ++pos;
00245                 }
00246             }
00247         }
00248         // correct behaviour for those that are not in chosen, but may drive, though
00249         for (unsigned int i1=0; i1<pos; ++i1) {
00250             if (state[i1]=='G') {
00251                 continue;
00252             }
00253             bool isForbidden = false;
00254             for (unsigned int i2=0; i2<pos&&!isForbidden; ++i2) {
00255                 if (state[i2]=='G'&&!isTurnaround[i2]&&
00256                         (forbids(fromEdges[i2], toEdges[i2], fromEdges[i1], toEdges[i1], true)||forbids(fromEdges[i1], toEdges[i1], fromEdges[i2], toEdges[i2], true))) {
00257                     isForbidden = true;
00258                 }
00259             }
00260             if (!isForbidden) {
00261                 state[i1] = 'G';
00262             }
00263         }
00264         // correct behaviour for those that have to wait (mainly left-mover)
00265         bool haveForbiddenLeftMover = false;
00266         for (unsigned int i1=0; i1<pos; ++i1) {
00267             if (state[i1]!='G') {
00268                 continue;
00269             }
00270             for (unsigned int i2=0; i2<pos; ++i2) {
00271                 if ((state[i2]=='G'||state[i2]=='g')&&forbids(fromEdges[i2], toEdges[i2], fromEdges[i1], toEdges[i1], true)) {
00272                     state[i1] = 'g';
00273                     if (!isTurnaround[i1]) {
00274                         haveForbiddenLeftMover = true;
00275                     }
00276                 }
00277             }
00278         }
00279 
00280         // add step
00281         logic->addStep(duration, state);
00282 
00283         if (brakingTime>0) {
00284             // build yellow (straight)
00285             duration = brakingTime;
00286             for (unsigned int i1=0; i1<pos; ++i1) {
00287                 if (state[i1]!='G'&&state[i1]!='g') {
00288                     continue;
00289                 }
00290                 if ((state[i1]>='a'&&state[i1]<='z')&&haveForbiddenLeftMover) {
00291                     continue;
00292                 }
00293                 state[i1] = 'y';
00294             }
00295             // add step
00296             logic->addStep(duration, state);
00297         }
00298 
00299         if (haveForbiddenLeftMover) {
00300             // build left green
00301             duration = 6;
00302             for (unsigned int i1=0; i1<pos; ++i1) {
00303                 if (state[i1]=='Y'||state[i1]=='y') {
00304                     state[i1] = 'r';
00305                     continue;
00306                 }
00307                 if (state[i1]=='g') {
00308                     state[i1] = 'G';
00309                 }
00310             }
00311             // add step
00312             logic->addStep(duration, state);
00313 
00314             // build left yellow
00315             if (brakingTime>0) {
00316                 duration = brakingTime;
00317                 for (unsigned int i1=0; i1<pos; ++i1) {
00318                     if (state[i1]!='G'&&state[i1]!='g') {
00319                         continue;
00320                     }
00321                     state[i1] = 'y';
00322                 }
00323                 // add step
00324                 logic->addStep(duration, state);
00325             }
00326         }
00327     }
00328     if (logic->getDuration()>0) {
00329         return logic;
00330     } else {
00331         delete logic;
00332         return 0;
00333     }
00334 
00335 }
00336 
00337 
00338 void
00339 NBOwnTLDef::collectNodes() throw() {}
00340 
00341 
00342 void
00343 NBOwnTLDef::collectLinks() throw(ProcessError) {
00344     // build the list of links which are controled by the traffic light
00345     for (EdgeVector::iterator i=myIncomingEdges.begin(); i!=myIncomingEdges.end(); i++) {
00346         NBEdge *incoming = *i;
00347         unsigned int noLanes = incoming->getNoLanes();
00348         for (unsigned int j=0; j<noLanes; j++) {
00349             std::vector<NBEdge::Connection> connected = incoming->getConnectionsFromLane(j);
00350             for (std::vector<NBEdge::Connection>::iterator k=connected.begin(); k!=connected.end(); k++) {
00351                 const NBEdge::Connection &el = *k;
00352                 if (incoming->mayBeTLSControlled(el.fromLane, el.toEdge, el.toLane)) {
00353                     if (el.toEdge!=0&&el.toLane>=(int) el.toEdge->getNoLanes()) {
00354                         throw ProcessError("Connection '" + incoming->getID() + "_" + toString(j) + "->" + el.toEdge->getID() + "_" + toString(el.toLane) + "' yields in a not existing lane.");
00355                     }
00356                     myControlledLinks.push_back(NBConnection(incoming, j, el.toEdge, el.toLane));
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     unsigned int pos = 0;
00379     for (NBConnectionVector::const_iterator j=myControlledLinks.begin(); j!=myControlledLinks.end(); ++j) {
00380         const NBConnection &conn = *j;
00381         NBEdge *edge = conn.getFrom();
00382         if (edge->setControllingTLInformation(conn.getFromLane(), conn.getTo(), conn.getToLane(), getID(), pos)) {
00383             pos++;
00384         }
00385     }
00386 }
00387 
00388 
00389 void
00390 NBOwnTLDef::remapRemoved(NBEdge * /*removed*/, const EdgeVector &/*incoming*/,
00391                          const EdgeVector &/*outgoing*/) throw() {}
00392 
00393 
00394 void
00395 NBOwnTLDef::replaceRemoved(NBEdge * /*removed*/, int /*removedLane*/,
00396                            NBEdge * /*by*/, int /*byLane*/) throw() {}
00397 
00398 
00399 
00400 /****************************************************************************/

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