void NBTrafficLightLogicCont::computeLogics(NBEdgeCont &ec, OptionsCont &oc) throw() { unsigned int no = 0; for (DefinitionContType::iterator i=myDefinitions.begin(); i!=myDefinitions.end(); i++) { std::string id = (*i).first; if (myComputed.find(id)!=myComputed.end()) { WRITE_WARNING("Traffic light '" + id + "' was already built."); continue; } // build program NBTrafficLightDefinition *def = (*i).second; NBTrafficLightLogic *built = def->compute(ec, oc); if (built==0) { WRITE_WARNING("Could not build traffic lights '" + id + "'"); continue; } // compute offset SUMOTime T = built->getDuration(); if (find(myHalfOffsetTLS.begin(), myHalfOffsetTLS.end(), id)!=myHalfOffsetTLS.end()) { built->setOffset((SUMOTime)(T/2.)); } if (find(myQuarterOffsetTLS.begin(), myQuarterOffsetTLS.end(), id)!=myQuarterOffsetTLS.end()) { built->setOffset((SUMOTime)(T/4.)); } // and insert the result after computation myComputed[(*i).first] = built; no++; } WRITE_MESSAGE(toString<int>(no) + " traffic light(s) computed."); }
bool NBTrafficLightLogicCont::computeSingleLogic(OptionsCont& oc, NBTrafficLightDefinition* def) { const std::string& id = def->getID(); const std::string& programID = def->getProgramID(); // build program NBTrafficLightLogic* built = def->compute(oc); if (built == 0) { WRITE_WARNING("Could not build program '" + programID + "' for traffic light '" + id + "'"); return false; } // compute offset SUMOTime T = built->getDuration(); if (myHalfOffsetTLS.count(id)) { built->setOffset((SUMOTime)(T / 2.)); } if (myQuarterOffsetTLS.count(id)) { built->setOffset((SUMOTime)(T / 4.)); } // and insert the result after computation // make sure we don't leak memory if computeSingleLogic is called externally if (myComputed[id][programID] != 0) { delete myComputed[id][programID]; } myComputed[id][programID] = built; return true; }
/* Test the method 'getDuration'*/ TEST(NBTrafficLightLogic, test_method_getDuration) { NBTrafficLightLogic *edge = new NBTrafficLightLogic("1","11",2); EXPECT_EQ(0, edge->getDuration()); edge->addStep(3,"gr"); edge->addStep(5,"rG"); EXPECT_EQ(8, edge->getDuration()); }
NBTrafficLightLogic* NBLoadedTLDef::myCompute(const NBEdgeCont& ec, unsigned int brakingTime) { MsgHandler::getWarningInstance()->clear(); // !!! NBLoadedTLDef::SignalGroupCont::const_iterator i; // compute the switching times std::set<SUMOReal> tmpSwitchTimes; for (i = mySignalGroups.begin(); i != mySignalGroups.end(); i++) { NBLoadedTLDef::SignalGroup* group = (*i).second; // needed later group->sortPhases(); // patch the yellow time for this group group->patchTYellow(brakingTime, OptionsCont::getOptions().getBool("tls.yellow.patch-small")); // copy the now valid times into the container // both the given red and green phases are added and also the // yellow times std::vector<SUMOReal> gtimes = group->getTimes(myCycleDuration); for (std::vector<SUMOReal>::const_iterator k = gtimes.begin(); k != gtimes.end(); k++) { tmpSwitchTimes.insert(*k); } } std::vector<SUMOReal> switchTimes; copy(tmpSwitchTimes.begin(), tmpSwitchTimes.end(), back_inserter(switchTimes)); sort(switchTimes.begin(), switchTimes.end()); // count the signals unsigned int noSignals = 0; for (i = mySignalGroups.begin(); i != mySignalGroups.end(); i++) { noSignals += (*i).second->getLinkNo(); } // build the phases NBTrafficLightLogic* logic = new NBTrafficLightLogic(getID(), getProgramID(), noSignals, myOffset, myType); for (std::vector<SUMOReal>::iterator l = switchTimes.begin(); l != switchTimes.end(); l++) { // compute the duration of the current phase unsigned int duration; if (l != switchTimes.end() - 1) { // get from the difference to the next switching time duration = (unsigned int)((*(l + 1)) - (*l)); } else { // get from the differenc to the first switching time duration = (unsigned int)(myCycleDuration - (*l) + * (switchTimes.begin())); } // no information about yellow times will be generated assert((*l) >= 0); logic->addStep(TIME2STEPS(duration), buildPhaseState(ec, (unsigned int)(*l))); } // check whether any warnings were printed if (MsgHandler::getWarningInstance()->wasInformed()) { WRITE_WARNING("During computation of traffic light '" + getID() + "'."); } logic->closeBuilding(); return logic; }
void NBLoadedSUMOTLDef::removeConnection(const NBConnection& conn, bool reconstruct) { NBConnectionVector::iterator it = myControlledLinks.begin(); // find the connection but ignore its TLIndex since it might have been // invalidated by an earlier removal for (; it != myControlledLinks.end(); ++it) { if (it->getFrom() == conn.getFrom() && it->getTo() == conn.getTo() && it->getFromLane() == conn.getFromLane() && it->getToLane() == conn.getToLane()) { break; } } if (it == myControlledLinks.end()) { // a traffic light doesn't always controll all connections at a junction // especially when using the option --tls.join return; } const int removed = it->getTLIndex(); // remove the connection myControlledLinks.erase(it); if (reconstruct) { // updating the edge is only needed for immediate use in NETEDIT. // It may conflict with loading diffs conn.getFrom()->setControllingTLInformation(conn, ""); // shift link numbers down so there is no gap for (NBConnectionVector::iterator it = myControlledLinks.begin(); it != myControlledLinks.end(); it++) { NBConnection& c = *it; if (c.getTLIndex() > removed) { c.setTLIndex(c.getTLIndex() - 1); } } // update controlling information with new link numbers setTLControllingInformation(); // rebuild the logic const std::vector<NBTrafficLightLogic::PhaseDefinition> phases = myTLLogic->getPhases(); NBTrafficLightLogic* newLogic = new NBTrafficLightLogic(getID(), getProgramID(), 0, myOffset, myType); for (std::vector<NBTrafficLightLogic::PhaseDefinition>::const_iterator it = phases.begin(); it != phases.end(); it++) { std::string newState = it->state; newState.erase(newState.begin() + removed); newLogic->addStep(it->duration, newState); } delete myTLLogic; myTLLogic = newLogic; } }
NBTrafficLightLogic* NBTrafficLightDefinition::compute(OptionsCont& oc) { // it is not really a traffic light if no incoming edge exists if (amInvalid()) { // make a copy of myControlledNodes because it will be modified; std::vector<NBNode*> nodes = myControlledNodes; for (std::vector<NBNode*>::iterator it = nodes.begin(); it != nodes.end(); it++) { (*it)->removeTrafficLight(this); } WRITE_WARNING("The traffic light '" + getID() + "' does not control any links; it will not be build."); return 0; } // compute the time needed to brake unsigned int brakingTime = computeBrakingTime(oc.getFloat("tls.yellow.min-decel")); // perform the computation depending on whether the traffic light // definition was loaded or shall be computed new completely if (oc.isSet("tls.yellow.time")) { brakingTime = oc.getInt("tls.yellow.time"); } NBTrafficLightLogic* ret = myCompute(brakingTime); ret->addParameter(getMap()); return ret; }
NBTrafficLightLogic* NBLoadedTLDef::myCompute(unsigned int brakingTimeSeconds) { MsgHandler::getWarningInstance()->clear(); // !!! NBLoadedTLDef::SignalGroupCont::const_iterator i; // compute the switching times std::set<SUMOReal> tmpSwitchTimes; for (i = mySignalGroups.begin(); i != mySignalGroups.end(); i++) { NBLoadedTLDef::SignalGroup* group = (*i).second; // needed later group->sortPhases(); // patch the yellow time for this group group->patchTYellow(brakingTimeSeconds, OptionsCont::getOptions().getBool("tls.yellow.patch-small")); // copy the now valid times into the container // both the given red and green phases are added and also the // yellow times std::vector<SUMOReal> gtimes = group->getTimes(myCycleDuration); for (std::vector<SUMOReal>::const_iterator k = gtimes.begin(); k != gtimes.end(); k++) { tmpSwitchTimes.insert(*k); } } std::vector<SUMOReal> switchTimes; copy(tmpSwitchTimes.begin(), tmpSwitchTimes.end(), back_inserter(switchTimes)); sort(switchTimes.begin(), switchTimes.end()); // count the signals unsigned int noSignals = 0; for (i = mySignalGroups.begin(); i != mySignalGroups.end(); i++) { noSignals += (*i).second->getLinkNo(); } // build the phases NBTrafficLightLogic* logic = new NBTrafficLightLogic(getID(), getProgramID(), noSignals, myOffset, myType); for (std::vector<SUMOReal>::iterator l = switchTimes.begin(); l != switchTimes.end(); l++) { // compute the duration of the current phase unsigned int duration; if (l != switchTimes.end() - 1) { // get from the difference to the next switching time duration = (unsigned int)((*(l + 1)) - (*l)); } else { // get from the differenc to the first switching time duration = (unsigned int)(myCycleDuration - (*l) + * (switchTimes.begin())); } // no information about yellow times will be generated assert((*l) >= 0); logic->addStep(TIME2STEPS(duration), buildPhaseState((unsigned int)(*l))); } // check whether any warnings were printed if (MsgHandler::getWarningInstance()->wasInformed()) { WRITE_WARNING("During computation of traffic light '" + getID() + "'."); } logic->closeBuilding(); // initialize myNeedsContRelation myNeedsContRelation.clear(); const bool controlledWithin = !OptionsCont::getOptions().getBool("tls.uncontrolled-within"); const std::vector<NBTrafficLightLogic::PhaseDefinition> phases = logic->getPhases(); for (std::vector<NBTrafficLightLogic::PhaseDefinition>::const_iterator it = phases.begin(); it != phases.end(); it++) { const std::string state = (*it).state; for (NBConnectionVector::const_iterator it1 = myControlledLinks.begin(); it1 != myControlledLinks.end(); it1++) { const NBConnection& c1 = *it1; const int i1 = c1.getTLIndex(); if (i1 == NBConnection::InvalidTlIndex || state[i1] != 'g' || c1.getFrom() == 0 || c1.getTo() == 0) { continue; } for (NBConnectionVector::const_iterator it2 = myControlledLinks.begin(); it2 != myControlledLinks.end(); it2++) { const NBConnection& c2 = *it2; const int i2 = c2.getTLIndex(); if (i2 != NBConnection::InvalidTlIndex && i2 != i1 && (state[i2] == 'G' || state[i2] == 'g') && c2.getFrom() != 0 && c2.getTo() != 0) { const bool rightTurnConflict = NBNode::rightTurnConflict( c1.getFrom(), c1.getTo(), c1.getFromLane(), c2.getFrom(), c2.getTo(), c2.getFromLane()); if (forbids(c2.getFrom(), c2.getTo(), c1.getFrom(), c1.getTo(), true, controlledWithin) || rightTurnConflict) { myNeedsContRelation.insert(StreamPair(c1.getFrom(), c1.getTo(), c2.getFrom(), c2.getTo())); } } } } } myNeedsContRelationReady = true; return logic; }
NBTrafficLightLogic* NBOwnTLDef::myCompute(const NBEdgeCont&, unsigned int brakingTimeSeconds) { const SUMOTime brakingTime = TIME2STEPS(brakingTimeSeconds); const SUMOTime leftTurnTime = TIME2STEPS(6); // make configurable ? // build complete lists first const EdgeVector& incoming = getIncomingEdges(); EdgeVector fromEdges, toEdges; std::vector<bool> isLeftMoverV, isTurnaround; unsigned int noLanesAll = 0; unsigned int noLinksAll = 0; for (unsigned int i1 = 0; i1 < incoming.size(); i1++) { unsigned int noLanes = incoming[i1]->getNumLanes(); noLanesAll += noLanes; for (unsigned int i2 = 0; i2 < noLanes; i2++) { NBEdge* fromEdge = incoming[i1]; std::vector<NBEdge::Connection> approached = fromEdge->getConnectionsFromLane(i2); noLinksAll += (unsigned int) approached.size(); for (unsigned int i3 = 0; i3 < approached.size(); i3++) { if (!fromEdge->mayBeTLSControlled(i2, approached[i3].toEdge, approached[i3].toLane)) { --noLinksAll; continue; } assert(i3 < approached.size()); NBEdge* toEdge = approached[i3].toEdge; fromEdges.push_back(fromEdge); //myFromLanes.push_back(i2); toEdges.push_back(toEdge); if (toEdge != 0) { isLeftMoverV.push_back( isLeftMover(fromEdge, toEdge) || fromEdge->isTurningDirectionAt(fromEdge->getToNode(), toEdge)); isTurnaround.push_back( fromEdge->isTurningDirectionAt( fromEdge->getToNode(), toEdge)); } else { isLeftMoverV.push_back(true); isTurnaround.push_back(true); } } } } NBTrafficLightLogic* logic = new NBTrafficLightLogic(getID(), getProgramID(), noLinksAll, myOffset, myType); EdgeVector toProc = incoming; const SUMOTime greenTime = TIME2STEPS(OptionsCont::getOptions().getInt("tls.green.time")); // build all phases while (toProc.size() > 0) { std::pair<NBEdge*, NBEdge*> chosen; if (incoming.size() == 2) { chosen = std::pair<NBEdge*, NBEdge*>(toProc[0], static_cast<NBEdge*>(0)); toProc.erase(toProc.begin()); } else { chosen = getBestPair(toProc); } unsigned int pos = 0; std::string state((size_t) noLinksAll, 'o'); // plain straight movers for (unsigned int i1 = 0; i1 < (unsigned int) incoming.size(); ++i1) { NBEdge* fromEdge = incoming[i1]; const bool inChosen = fromEdge == chosen.first || fromEdge == chosen.second; //chosen.find(fromEdge)!=chosen.end(); const unsigned int numLanes = fromEdge->getNumLanes(); for (unsigned int i2 = 0; i2 < numLanes; i2++) { std::vector<NBEdge::Connection> approached = fromEdge->getConnectionsFromLane(i2); for (unsigned int i3 = 0; i3 < approached.size(); ++i3) { if (!fromEdge->mayBeTLSControlled(i2, approached[i3].toEdge, approached[i3].toLane)) { continue; } if (inChosen) { state[pos] = 'G'; } else { state[pos] = 'r'; } ++pos; } } } // correct behaviour for those that are not in chosen, but may drive, though for (unsigned int i1 = 0; i1 < pos; ++i1) { if (state[i1] == 'G') { continue; } bool isForbidden = false; for (unsigned int i2 = 0; i2 < pos && !isForbidden; ++i2) { if (state[i2] == 'G' && !isTurnaround[i2] && (forbids(fromEdges[i2], toEdges[i2], fromEdges[i1], toEdges[i1], true) || forbids(fromEdges[i1], toEdges[i1], fromEdges[i2], toEdges[i2], true))) { isForbidden = true; } } if (!isForbidden) { state[i1] = 'G'; } } // correct behaviour for those that have to wait (mainly left-mover) bool haveForbiddenLeftMover = false; for (unsigned int i1 = 0; i1 < pos; ++i1) { if (state[i1] != 'G') { continue; } for (unsigned int i2 = 0; i2 < pos; ++i2) { if ((state[i2] == 'G' || state[i2] == 'g') && forbids(fromEdges[i2], toEdges[i2], fromEdges[i1], toEdges[i1], true)) { state[i1] = 'g'; if (!isTurnaround[i1]) { haveForbiddenLeftMover = true; } } } } // add step logic->addStep(greenTime, state); if (brakingTime > 0) { // build yellow (straight) for (unsigned int i1 = 0; i1 < pos; ++i1) { if (state[i1] != 'G' && state[i1] != 'g') { continue; } if ((state[i1] >= 'a' && state[i1] <= 'z') && haveForbiddenLeftMover) { continue; } state[i1] = 'y'; } // add step logic->addStep(brakingTime, state); } if (haveForbiddenLeftMover && !myHaveSinglePhase) { // build left green for (unsigned int i1 = 0; i1 < pos; ++i1) { if (state[i1] == 'Y' || state[i1] == 'y') { state[i1] = 'r'; continue; } if (state[i1] == 'g') { state[i1] = 'G'; } } // add step logic->addStep(leftTurnTime, state); // build left yellow if (brakingTime > 0) { for (unsigned int i1 = 0; i1 < pos; ++i1) { if (state[i1] != 'G' && state[i1] != 'g') { continue; } state[i1] = 'y'; } // add step logic->addStep(brakingTime, state); } } } const SUMOTime totalDuration = logic->getDuration(); if (totalDuration > 0) { if (totalDuration > 3 * (greenTime + 2 * brakingTime + leftTurnTime)) { WRITE_WARNING("The traffic light '" + getID() + "' has a high cycle time of " + time2string(totalDuration) + "."); } return logic; } else { delete logic; return 0; } }
NBTrafficLightLogic * NBOwnTLDef::myCompute(const NBEdgeCont &, unsigned int brakingTime) throw() { // build complete lists first const EdgeVector &incoming = getIncomingEdges(); std::vector<NBEdge*> fromEdges, toEdges; std::vector<bool> isLeftMoverV, isTurnaround; unsigned int noLanesAll = 0; unsigned int noLinksAll = 0; for (unsigned int i1=0; i1<incoming.size(); i1++) { unsigned int noLanes = incoming[i1]->getNoLanes(); noLanesAll += noLanes; for (unsigned int i2=0; i2<noLanes; i2++) { NBEdge *fromEdge = incoming[i1]; std::vector<NBEdge::Connection> approached = fromEdge->getConnectionsFromLane(i2); noLinksAll += (unsigned int) approached.size(); for (unsigned int i3=0; i3<approached.size(); i3++) { if (!fromEdge->mayBeTLSControlled(i2, approached[i3].toEdge, approached[i3].toLane)) { --noLinksAll; continue; } assert(i3<approached.size()); NBEdge *toEdge = approached[i3].toEdge; fromEdges.push_back(fromEdge); //myFromLanes.push_back(i2); toEdges.push_back(toEdge); if (toEdge!=0) { isLeftMoverV.push_back( isLeftMover(fromEdge, toEdge) || fromEdge->isTurningDirectionAt(fromEdge->getToNode(), toEdge)); isTurnaround.push_back( fromEdge->isTurningDirectionAt( fromEdge->getToNode(), toEdge)); } else { isLeftMoverV.push_back(true); isTurnaround.push_back(true); } } } } NBTrafficLightLogic *logic = new NBTrafficLightLogic(getID(), "0", noLinksAll); std::vector<NBEdge*> toProc = incoming; // build all phases while (toProc.size()>0) { std::pair<NBEdge*, NBEdge*> chosen; if (incoming.size()==2) { chosen = std::pair<NBEdge*, NBEdge*>(toProc[0], static_cast<NBEdge*>(0)); toProc.erase(toProc.begin()); } else { chosen = getBestPair(toProc); } unsigned int pos = 0; unsigned int duration = 31; if (OptionsCont::getOptions().isSet("traffic-light-green")) { duration = OptionsCont::getOptions().getInt("traffic-light-green"); } std::string state((size_t) noLinksAll, 'o'); // plain straight movers for (unsigned int i1=0; i1<(unsigned int) incoming.size(); ++i1) { NBEdge *fromEdge = incoming[i1]; bool inChosen = fromEdge==chosen.first||fromEdge==chosen.second;//chosen.find(fromEdge)!=chosen.end(); unsigned int noLanes = fromEdge->getNoLanes(); for (unsigned int i2=0; i2<noLanes; i2++) { std::vector<NBEdge::Connection> approached = fromEdge->getConnectionsFromLane(i2); for (unsigned int i3=0; i3<approached.size(); ++i3) { if (!fromEdge->mayBeTLSControlled(i2, approached[i3].toEdge, approached[i3].toLane)) { continue; } if (inChosen) { state[pos] = 'G'; } else { state[pos] = 'r'; } ++pos; } } } // correct behaviour for those that are not in chosen, but may drive, though for (unsigned int i1=0; i1<pos; ++i1) { if (state[i1]=='G') { continue; } bool isForbidden = false; for (unsigned int i2=0; i2<pos&&!isForbidden; ++i2) { if (state[i2]=='G'&&!isTurnaround[i2]&& (forbids(fromEdges[i2], toEdges[i2], fromEdges[i1], toEdges[i1], true)||forbids(fromEdges[i1], toEdges[i1], fromEdges[i2], toEdges[i2], true))) { isForbidden = true; } } if (!isForbidden) { state[i1] = 'G'; } } // correct behaviour for those that have to wait (mainly left-mover) bool haveForbiddenLeftMover = false; for (unsigned int i1=0; i1<pos; ++i1) { if (state[i1]!='G') { continue; } for (unsigned int i2=0; i2<pos; ++i2) { if ((state[i2]=='G'||state[i2]=='g')&&forbids(fromEdges[i2], toEdges[i2], fromEdges[i1], toEdges[i1], true)) { state[i1] = 'g'; if (!isTurnaround[i1]) { haveForbiddenLeftMover = true; } } } } // add step logic->addStep(duration, state); if (brakingTime>0) { // build yellow (straight) duration = brakingTime; for (unsigned int i1=0; i1<pos; ++i1) { if (state[i1]!='G'&&state[i1]!='g') { continue; } if ((state[i1]>='a'&&state[i1]<='z')&&haveForbiddenLeftMover) { continue; } state[i1] = 'y'; } // add step logic->addStep(duration, state); } if (haveForbiddenLeftMover) { // build left green duration = 6; for (unsigned int i1=0; i1<pos; ++i1) { if (state[i1]=='Y'||state[i1]=='y') { state[i1] = 'r'; continue; } if (state[i1]=='g') { state[i1] = 'G'; } } // add step logic->addStep(duration, state); // build left yellow if (brakingTime>0) { duration = brakingTime; for (unsigned int i1=0; i1<pos; ++i1) { if (state[i1]!='G'&&state[i1]!='g') { continue; } state[i1] = 'y'; } // add step logic->addStep(duration, state); } } } if (logic->getDuration()>0) { return logic; } else { delete logic; return 0; } }