|
SUMO - Simulation of Urban MObility
|
00001 /****************************************************************************/ 00007 // A loaded (complete) traffic light logic 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 // included modules 00022 // =========================================================================== 00023 #ifdef _MSC_VER 00024 #include <windows_config.h> 00025 #else 00026 #include <config.h> 00027 #endif 00028 00029 #include <vector> 00030 #include <set> 00031 #include <cassert> 00032 #include <iterator> 00033 #include <utils/common/MsgHandler.h> 00034 #include <utils/common/ToString.h> 00035 #include <utils/options/OptionsCont.h> 00036 #include "NBTrafficLightLogic.h" 00037 #include "NBTrafficLightDefinition.h" 00038 #include "NBLoadedTLDef.h" 00039 #include "NBNode.h" 00040 00041 #ifdef CHECK_MEMORY_LEAKS 00042 #include <foreign/nvwa/debug_new.h> 00043 #endif // CHECK_MEMORY_LEAKS 00044 00045 00046 // =========================================================================== 00047 // method definitions 00048 // =========================================================================== 00049 /* ------------------------------------------------------------------------- 00050 * NBLoadedTLDef::SignalGroup-methods 00051 * ----------------------------------------------------------------------- */ 00052 NBLoadedTLDef::SignalGroup::SignalGroup(const std::string& id) throw() 00053 : Named(id) {} 00054 00055 NBLoadedTLDef::SignalGroup::~SignalGroup() throw() {} 00056 00057 void 00058 NBLoadedTLDef::SignalGroup::addConnection(const NBConnection& c) throw() { 00059 assert(c.getFromLane()<0||c.getFrom()->getNumLanes()>(unsigned int)c.getFromLane()); 00060 myConnections.push_back(c); 00061 } 00062 00063 00064 void 00065 NBLoadedTLDef::SignalGroup::addPhaseBegin(SUMOTime time, TLColor color) throw() { 00066 myPhases.push_back(PhaseDef(time, color)); 00067 } 00068 00069 00070 void 00071 NBLoadedTLDef::SignalGroup::setYellowTimes(SUMOTime tRedYellow, 00072 SUMOTime tYellow) throw() { 00073 myTRedYellow = tRedYellow; 00074 myTYellow = tYellow; 00075 } 00076 00077 00078 void 00079 NBLoadedTLDef::SignalGroup::sortPhases() throw() { 00080 sort(myPhases.begin(), myPhases.end(), 00081 phase_by_time_sorter()); 00082 } 00083 00084 00085 void 00086 NBLoadedTLDef::SignalGroup::patchTYellow(SUMOTime tyellow) throw() { 00087 if (myTYellow<tyellow) { 00088 WRITE_WARNING("TYellow of signal group '" + getID()+ "' was less than the computed one; patched (was:" + toString<SUMOTime>(myTYellow) + ", is:" + toString<int>(tyellow) + ")"); 00089 myTYellow = tyellow; 00090 } 00091 } 00092 00093 00094 DoubleVector 00095 NBLoadedTLDef::SignalGroup::getTimes(SUMOTime cycleDuration) const throw() { 00096 // within the phase container, we should have the green and red phases 00097 // add their times 00098 DoubleVector ret; // !!! time vector 00099 for (std::vector<PhaseDef>::const_iterator i=myPhases.begin(); i!=myPhases.end(); i++) { 00100 ret.push_back((SUMOReal)(*i).myTime); 00101 } 00102 // further, we possibly should set the yellow phases 00103 if (myTYellow>0) { 00104 for (std::vector<PhaseDef>::const_iterator i=myPhases.begin(); i!=myPhases.end(); i++) { 00105 if ((*i).myColor==TLCOLOR_RED) { 00106 SUMOTime time = (SUMOTime)(*i).myTime + myTYellow; 00107 if (time>cycleDuration) { 00108 time = time - cycleDuration ; 00109 } 00110 ret.push_back((SUMOReal) time); 00111 } 00112 } 00113 } 00114 return ret; 00115 } 00116 00117 00118 unsigned int 00119 NBLoadedTLDef::SignalGroup::getLinkNo() const throw() { 00120 return (unsigned int) myConnections.size(); 00121 } 00122 00123 00124 bool 00125 NBLoadedTLDef::SignalGroup::mayDrive(SUMOTime time) const throw() { 00126 assert(myPhases.size()!=0); 00127 for (std::vector<PhaseDef>::const_reverse_iterator i=myPhases.rbegin(); i!=myPhases.rend(); i++) { 00128 SUMOTime nextTime = (*i).myTime; 00129 if (time>=nextTime) { 00130 return (*i).myColor==TLCOLOR_GREEN; 00131 } 00132 } 00133 return (*(myPhases.end()-1)).myColor==TLCOLOR_GREEN; 00134 } 00135 00136 00137 bool 00138 NBLoadedTLDef::SignalGroup::hasYellow(SUMOTime time) const throw() { 00139 bool has_red_now = !mayDrive(time); 00140 bool had_green = mayDrive(time-myTYellow); 00141 return has_red_now&&had_green; 00142 } 00143 00144 00145 bool 00146 NBLoadedTLDef::SignalGroup::containsConnection(NBEdge* from, NBEdge* to) const throw() { 00147 for (NBConnectionVector::const_iterator i=myConnections.begin(); i!=myConnections.end(); i++) { 00148 if ((*i).getFrom()==from&&(*i).getTo()==to) { 00149 return true; 00150 } 00151 } 00152 return false; 00153 00154 } 00155 00156 00157 const NBConnection& 00158 NBLoadedTLDef::SignalGroup::getConnection(unsigned int pos) const throw() { 00159 assert(pos<myConnections.size()); 00160 return myConnections[pos]; 00161 } 00162 00163 00164 bool 00165 NBLoadedTLDef::SignalGroup::containsIncoming(NBEdge* from) const throw() { 00166 for (NBConnectionVector::const_iterator i=myConnections.begin(); i!=myConnections.end(); i++) { 00167 if ((*i).getFrom()==from) { 00168 return true; 00169 } 00170 } 00171 return false; 00172 } 00173 00174 00175 void 00176 NBLoadedTLDef::SignalGroup::remapIncoming(NBEdge* which, const EdgeVector& by) throw(ProcessError) { 00177 NBConnectionVector newConns; 00178 for (NBConnectionVector::iterator i=myConnections.begin(); i!=myConnections.end();) { 00179 if ((*i).getFrom()==which) { 00180 NBConnection conn((*i).getFrom(), (*i).getTo()); 00181 i = myConnections.erase(i); 00182 for (EdgeVector::const_iterator j=by.begin(); j!=by.end(); j++) { 00183 NBConnection curr(conn); 00184 if (!curr.replaceFrom(which, *j)) { 00185 throw ProcessError("Could not replace edge '" + which->getID() + "' by '" + (*j)->getID() + "'.\nUndefined..."); 00186 } 00187 newConns.push_back(curr); 00188 } 00189 } else { 00190 i++; 00191 } 00192 } 00193 copy(newConns.begin(), newConns.end(), 00194 back_inserter(myConnections)); 00195 } 00196 00197 00198 bool 00199 NBLoadedTLDef::SignalGroup::containsOutgoing(NBEdge* to) const throw() { 00200 for (NBConnectionVector::const_iterator i=myConnections.begin(); i!=myConnections.end(); i++) { 00201 if ((*i).getTo()==to) { 00202 return true; 00203 } 00204 } 00205 return false; 00206 } 00207 00208 00209 void 00210 NBLoadedTLDef::SignalGroup::remapOutgoing(NBEdge* which, const EdgeVector& by) throw(ProcessError) { 00211 NBConnectionVector newConns; 00212 for (NBConnectionVector::iterator i=myConnections.begin(); i!=myConnections.end();) { 00213 if ((*i).getTo()==which) { 00214 NBConnection conn((*i).getFrom(), (*i).getTo()); 00215 i = myConnections.erase(i); 00216 for (EdgeVector::const_iterator j=by.begin(); j!=by.end(); j++) { 00217 NBConnection curr(conn); 00218 if (!curr.replaceTo(which, *j)) { 00219 throw ProcessError("Could not replace edge '" + which->getID() + "' by '" + (*j)->getID() + "'.\nUndefined..."); 00220 } 00221 newConns.push_back(curr); 00222 } 00223 } else { 00224 i++; 00225 } 00226 } 00227 copy(newConns.begin(), newConns.end(), 00228 back_inserter(myConnections)); 00229 } 00230 00231 00232 void 00233 NBLoadedTLDef::SignalGroup::remap(NBEdge* removed, int removedLane, 00234 NBEdge* by, int byLane) throw() { 00235 for (NBConnectionVector::iterator i=myConnections.begin(); i!=myConnections.end(); i++) { 00236 if ((*i).getTo()==removed 00237 && 00238 ((*i).getToLane()==removedLane 00239 || 00240 (*i).getToLane()==-1)) { 00241 (*i).replaceTo(removed, removedLane, by, byLane); 00242 00243 } else if ((*i).getTo()==removed && removedLane==-1) { 00244 (*i).replaceTo(removed, by); 00245 } 00246 00247 if ((*i).getFrom()==removed 00248 && 00249 ((*i).getFromLane()==removedLane 00250 || 00251 (*i).getFromLane()==-1)) { 00252 (*i).replaceFrom(removed, removedLane, by, byLane); 00253 00254 } else if ((*i).getFrom()==removed && removedLane==-1) { 00255 (*i).replaceFrom(removed, by); 00256 } 00257 } 00258 } 00259 00260 00261 /* ------------------------------------------------------------------------- 00262 * NBLoadedTLDef::Phase-methods 00263 * ----------------------------------------------------------------------- */ 00264 NBLoadedTLDef::NBLoadedTLDef(const std::string& id, 00265 const std::vector<NBNode*> &junctions) throw() 00266 : NBTrafficLightDefinition(id, junctions, DefaultProgramID) {} 00267 00268 00269 NBLoadedTLDef::NBLoadedTLDef(const std::string& id, NBNode* junction) throw() 00270 : NBTrafficLightDefinition(id, junction, DefaultProgramID) {} 00271 00272 00273 NBLoadedTLDef::NBLoadedTLDef(const std::string& id) throw() 00274 : NBTrafficLightDefinition(id, DefaultProgramID) {} 00275 00276 00277 NBLoadedTLDef::~NBLoadedTLDef() throw() { 00278 for (SignalGroupCont::iterator i=mySignalGroups.begin(); i!=mySignalGroups.end(); ++i) { 00279 delete(*i).second; 00280 } 00281 } 00282 00283 00284 NBTrafficLightLogic* 00285 NBLoadedTLDef::myCompute(const NBEdgeCont& ec, unsigned int brakingTime) throw() { 00286 MsgHandler::getWarningInstance()->clear(); // !!! 00287 NBLoadedTLDef::SignalGroupCont::const_iterator i; 00288 // compute the switching times 00289 std::set<SUMOReal> tmpSwitchTimes; 00290 for (i=mySignalGroups.begin(); i!=mySignalGroups.end(); i++) { 00291 NBLoadedTLDef::SignalGroup* group = (*i).second; 00292 // needed later 00293 group->sortPhases(); 00294 // patch the yellow time for this group 00295 if (OptionsCont::getOptions().getBool("tls.yellow.patch-small")) { 00296 group->patchTYellow(brakingTime); 00297 } 00298 // copy the now valid times into the container 00299 // both the given red and green phases are added and also the 00300 // yellow times 00301 DoubleVector gtimes = group->getTimes(myCycleDuration); 00302 for (DoubleVector::const_iterator k=gtimes.begin(); k!=gtimes.end(); k++) { 00303 tmpSwitchTimes.insert(*k); 00304 } 00305 } 00306 std::vector<SUMOReal> switchTimes; 00307 copy(tmpSwitchTimes.begin(), tmpSwitchTimes.end(), back_inserter(switchTimes)); 00308 sort(switchTimes.begin(), switchTimes.end()); 00309 00310 // count the signals 00311 unsigned int noSignals = 0; 00312 for (i=mySignalGroups.begin(); i!=mySignalGroups.end(); i++) { 00313 noSignals += (*i).second->getLinkNo(); 00314 } 00315 // build the phases 00316 NBTrafficLightLogic* logic = new NBTrafficLightLogic(getID(), getProgramID(), noSignals); 00317 for (std::vector<SUMOReal>::iterator l=switchTimes.begin(); l!=switchTimes.end(); l++) { 00318 // compute the duration of the current phase 00319 unsigned int duration; 00320 if (l!=switchTimes.end()-1) { 00321 // get from the difference to the next switching time 00322 duration = (unsigned int)((*(l+1)) - (*l)); 00323 } else { 00324 // get from the differenc to the first switching time 00325 duration = (unsigned int)(myCycleDuration - (*l) + *(switchTimes.begin())) ; 00326 } 00327 // no information about yellow times will be generated 00328 assert((*l)>=0); 00329 logic->addStep(TIME2STEPS(duration), buildPhaseState(ec, (unsigned int)(*l))); 00330 } 00331 // check whether any warnings were printed 00332 if (MsgHandler::getWarningInstance()->wasInformed()) { 00333 WRITE_WARNING("During computation of traffic light '" + getID() + "'."); 00334 } 00335 logic->closeBuilding(); 00336 return logic; 00337 } 00338 00339 00340 void 00341 NBLoadedTLDef::setTLControllingInformation(const NBEdgeCont& ec) const throw() { 00342 // assign the links to the connections 00343 unsigned int pos = 0; 00344 for (SignalGroupCont::const_iterator m=mySignalGroups.begin(); m!=mySignalGroups.end(); m++) { 00345 SignalGroup* group = (*m).second; 00346 unsigned int linkNo = group->getLinkNo(); 00347 for (unsigned int j=0; j<linkNo; j++) { 00348 const NBConnection& conn = group->getConnection(j); 00349 assert(conn.getFromLane()<0||(int) conn.getFrom()->getNumLanes()>conn.getFromLane()); 00350 NBConnection tst(conn); 00351 tst.setTLIndex(pos); 00352 if (tst.check(ec)) { 00353 NBEdge* edge = conn.getFrom(); 00354 if (edge->setControllingTLInformation(tst, getID())) { 00355 pos++; 00356 } 00357 } else { 00358 WRITE_WARNING("Could not set signal on connection (signal: " + getID() + ", group: " + group->getID()+ ")"); 00359 } 00360 } 00361 } 00362 } 00363 00364 00365 std::string 00366 NBLoadedTLDef::buildPhaseState(const NBEdgeCont& ec, unsigned int time) const throw() { 00367 unsigned int pos = 0; 00368 std::string state; 00369 // set the green and yellow information first; 00370 // the information whether other have to break needs those masks 00371 // completely filled 00372 for (SignalGroupCont::const_iterator i=mySignalGroups.begin(); i!=mySignalGroups.end(); i++) { 00373 SignalGroup* group = (*i).second; 00374 unsigned int linkNo = group->getLinkNo(); 00375 bool mayDrive = group->mayDrive(time); 00376 bool hasYellow = group->hasYellow(time); 00377 char c = 'r'; 00378 if (mayDrive) { 00379 c = 'g'; 00380 } 00381 if (hasYellow) { 00382 c = 'y'; 00383 } 00384 for (unsigned int j=0; j<linkNo; j++) { 00385 const NBConnection& conn = group->getConnection(j); 00386 NBConnection assConn(conn); 00387 // assert that the connection really exists 00388 if (assConn.check(ec)) { 00389 state = state + c; 00390 ++pos; 00391 } 00392 } 00393 } 00394 // set the braking mask 00395 pos = 0; 00396 for (SignalGroupCont::const_iterator i=mySignalGroups.begin(); i!=mySignalGroups.end(); i++) { 00397 SignalGroup* group = (*i).second; 00398 unsigned int linkNo = group->getLinkNo(); 00399 for (unsigned int j=0; j<linkNo; j++) { 00400 const NBConnection& conn = group->getConnection(j); 00401 NBConnection assConn(conn); 00402 if (assConn.check(ec)) { 00403 if (!mustBrake(ec, assConn, state, pos)) { 00404 if (state[pos]=='g') { 00405 state[pos] = 'G'; 00406 } 00407 if (state[pos]=='y') { 00408 state[pos] = 'Y'; 00409 } 00410 } 00411 pos++; 00412 } 00413 } 00414 } 00415 return state; 00416 } 00417 00418 00419 bool 00420 NBLoadedTLDef::mustBrake(const NBEdgeCont& ec, 00421 const NBConnection& possProhibited, 00422 const std::string& state, 00423 unsigned int strmpos) const throw() { 00424 // check whether the stream has red 00425 if (state[strmpos]!='g'&&state[strmpos]!='G') { 00426 return true; 00427 } 00428 00429 // check whether another stream which has green is a higher 00430 // priorised foe to the given 00431 unsigned int pos = 0; 00432 for (SignalGroupCont::const_iterator i=mySignalGroups.begin(); i!=mySignalGroups.end(); i++) { 00433 SignalGroup* group = (*i).second; 00434 // get otherlinks that have green 00435 unsigned int linkNo = group->getLinkNo(); 00436 for (unsigned int j=0; j<linkNo; j++) { 00437 // get the current connection (possible foe) 00438 const NBConnection& other = group->getConnection(j); 00439 NBConnection possProhibitor(other); 00440 // if the connction ist still valid ... 00441 if (possProhibitor.check(ec)) { 00442 // ... do nothing if it starts at the same edge 00443 if (possProhibited.getFrom()==possProhibitor.getFrom()) { 00444 pos++; 00445 continue; 00446 } 00447 if (state[pos]=='g'||state[pos]=='G') { 00448 if (NBTrafficLightDefinition::mustBrake(possProhibited, possProhibitor, true)) { 00449 return true; 00450 } 00451 } 00452 pos++; 00453 } 00454 } 00455 } 00456 return false; 00457 } 00458 00459 00460 void 00461 NBLoadedTLDef::collectNodes() throw() { 00462 myControlledNodes.clear(); 00463 SignalGroupCont::const_iterator m; 00464 for (m=mySignalGroups.begin(); m!=mySignalGroups.end(); m++) { 00465 SignalGroup* group = (*m).second; 00466 unsigned int linkNo = group->getLinkNo(); 00467 for (unsigned int j=0; j<linkNo; j++) { 00468 const NBConnection& conn = group->getConnection(j); 00469 NBEdge* edge = conn.getFrom(); 00470 NBNode* node = edge->getToNode(); 00471 myControlledNodes.push_back(node); 00472 } 00473 } 00474 std::sort(myControlledNodes.begin(), myControlledNodes.end(), NBNode::nodes_by_id_sorter()); 00475 } 00476 00477 00478 void 00479 NBLoadedTLDef::collectLinks() throw(ProcessError) { 00480 myControlledLinks.clear(); 00481 // build the list of links which are controled by the traffic light 00482 for (EdgeVector::iterator i=myIncomingEdges.begin(); i!=myIncomingEdges.end(); i++) { 00483 NBEdge* incoming = *i; 00484 unsigned int noLanes = incoming->getNumLanes(); 00485 for (unsigned int j=0; j<noLanes; j++) { 00486 std::vector<NBEdge::Connection> elv = incoming->getConnectionsFromLane(j); 00487 for (std::vector<NBEdge::Connection>::iterator k=elv.begin(); k!=elv.end(); k++) { 00488 NBEdge::Connection el = *k; 00489 if (el.toEdge!=0) { 00490 myControlledLinks.push_back(NBConnection(incoming, j, el.toEdge, el.toLane)); 00491 } 00492 } 00493 } 00494 } 00495 } 00496 00497 00498 NBLoadedTLDef::SignalGroup* 00499 NBLoadedTLDef::findGroup(NBEdge* from, NBEdge* to) const throw() { 00500 for (SignalGroupCont::const_iterator i=mySignalGroups.begin(); i!=mySignalGroups.end(); i++) { 00501 if ((*i).second->containsConnection(from, to)) { 00502 return (*i).second; 00503 } 00504 } 00505 return 0; 00506 } 00507 00508 00509 bool 00510 NBLoadedTLDef::addToSignalGroup(const std::string& groupid, 00511 const NBConnection& connection) throw() { 00512 if (mySignalGroups.find(groupid)==mySignalGroups.end()) { 00513 return false; 00514 } 00515 mySignalGroups[groupid]->addConnection(connection); 00516 NBNode* n1 = connection.getFrom()->getToNode(); 00517 if (n1!=0) { 00518 addNode(n1); 00519 n1->addTrafficLight(this); 00520 } 00521 NBNode* n2 = connection.getTo()->getFromNode(); 00522 if (n2!=0) { 00523 addNode(n2); 00524 n2->addTrafficLight(this); 00525 } 00526 return true; 00527 } 00528 00529 00530 bool 00531 NBLoadedTLDef::addToSignalGroup(const std::string& groupid, 00532 const NBConnectionVector& connections) throw() { 00533 bool ok = true; 00534 for (NBConnectionVector::const_iterator i=connections.begin(); i!=connections.end(); i++) { 00535 ok &= addToSignalGroup(groupid, *i); 00536 } 00537 return ok; 00538 } 00539 00540 00541 void 00542 NBLoadedTLDef::addSignalGroup(const std::string& id) throw() { 00543 assert(mySignalGroups.find(id)==mySignalGroups.end()); 00544 mySignalGroups[id] = new SignalGroup(id); 00545 } 00546 00547 00548 void 00549 NBLoadedTLDef::addSignalGroupPhaseBegin(const std::string& groupid, SUMOTime time, 00550 TLColor color) throw() { 00551 assert(mySignalGroups.find(groupid)!=mySignalGroups.end()); 00552 mySignalGroups[groupid]->addPhaseBegin(time, color); 00553 } 00554 00555 void 00556 NBLoadedTLDef::setSignalYellowTimes(const std::string& groupid, 00557 SUMOTime myTRedYellow, SUMOTime myTYellow) throw() { 00558 assert(mySignalGroups.find(groupid)!=mySignalGroups.end()); 00559 mySignalGroups[groupid]->setYellowTimes(myTRedYellow, myTYellow); 00560 } 00561 00562 00563 void 00564 NBLoadedTLDef::setCycleDuration(unsigned int cycleDur) throw() { 00565 myCycleDuration = cycleDur; 00566 } 00567 00568 00569 void 00570 NBLoadedTLDef::remapRemoved(NBEdge* removed, 00571 const EdgeVector& incoming, 00572 const EdgeVector& outgoing) throw() { 00573 for (SignalGroupCont::const_iterator i=mySignalGroups.begin(); i!=mySignalGroups.end(); i++) { 00574 SignalGroup* group = (*i).second; 00575 if (group->containsIncoming(removed)) { 00576 group->remapIncoming(removed, incoming); 00577 } 00578 if (group->containsOutgoing(removed)) { 00579 group->remapOutgoing(removed, outgoing); 00580 } 00581 } 00582 } 00583 00584 00585 void 00586 NBLoadedTLDef::replaceRemoved(NBEdge* removed, int removedLane, 00587 NBEdge* by, int byLane) throw() { 00588 for (SignalGroupCont::const_iterator i=mySignalGroups.begin(); i!=mySignalGroups.end(); i++) { 00589 SignalGroup* group = (*i).second; 00590 if (group->containsIncoming(removed)||group->containsOutgoing(removed)) { 00591 group->remap(removed, removedLane, by, byLane); 00592 } 00593 } 00594 } 00595 00596 00597 00598 /****************************************************************************/ 00599