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