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