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