SUMO - Simulation of Urban MObility
|
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 /****************************************************************************/