void MSEdge::recalcCache() { if (myLanes->empty()) { return; } myLength = myLanes->front()->getLength(); myEmptyTraveltime = myLength / MAX2(getSpeedLimit(), NUMERICAL_EPS); if (MSGlobals::gMesoTLSPenalty > 0 || MSGlobals::gMesoMinorPenalty > 0) { // add tls penalties to the minimum travel time SUMOTime minPenalty = -1; for (std::vector<MSLane*>::const_iterator i = myLanes->begin(); i != myLanes->end(); ++i) { MSLane* l = *i; const MSLinkCont& lc = l->getLinkCont(); for (MSLinkCont::const_iterator j = lc.begin(); j != lc.end(); ++j) { MSLink* link = *j; SUMOTime linkPenalty = link->getMesoTLSPenalty() + (link->havePriority() ? 0 : MSGlobals::gMesoMinorPenalty); if (minPenalty == -1) { minPenalty = linkPenalty; } else { minPenalty = MIN2(minPenalty, linkPenalty); } } } if (minPenalty > 0) { myEmptyTraveltime += STEPS2TIME(minPenalty); } } }
const MSEdge* MSEdge::getInternalFollowingEdge(const MSEdge* followerAfterInternal) const { //@todo to be optimized for (std::vector<MSLane*>::const_iterator i = myLanes->begin(); i != myLanes->end(); ++i) { MSLane* l = *i; const MSLinkCont& lc = l->getLinkCont(); for (MSLinkCont::const_iterator j = lc.begin(); j != lc.end(); ++j) { MSLink* link = *j; if (&link->getLane()->getEdge() == followerAfterInternal) { if (link->getViaLane() != 0) { return &link->getViaLane()->getEdge(); } else { return 0; // network without internal links } } } } return 0; }
// =========================================================================== // method definitions // =========================================================================== bool TraCIServerAPI_Lane::processGet(TraCIServer& server, tcpip::Storage& inputStorage, tcpip::Storage& outputStorage) { // variable int variable = inputStorage.readUnsignedByte(); std::string id = inputStorage.readString(); // check variable if (variable != ID_LIST && variable != LANE_LINK_NUMBER && variable != LANE_EDGE_ID && variable != VAR_LENGTH && variable != VAR_MAXSPEED && variable != LANE_LINKS && variable != VAR_SHAPE && variable != VAR_CO2EMISSION && variable != VAR_COEMISSION && variable != VAR_HCEMISSION && variable != VAR_PMXEMISSION && variable != VAR_NOXEMISSION && variable != VAR_FUELCONSUMPTION && variable != VAR_NOISEEMISSION && variable != VAR_WAITING_TIME && variable != LAST_STEP_MEAN_SPEED && variable != LAST_STEP_VEHICLE_NUMBER && variable != LAST_STEP_VEHICLE_ID_LIST && variable != LAST_STEP_OCCUPANCY && variable != LAST_STEP_VEHICLE_HALTING_NUMBER && variable != LAST_STEP_LENGTH && variable != VAR_CURRENT_TRAVELTIME && variable != LANE_ALLOWED && variable != LANE_DISALLOWED && variable != VAR_WIDTH && variable != ID_COUNT ) { return server.writeErrorStatusCmd(CMD_GET_LANE_VARIABLE, "Get Lane Variable: unsupported variable specified", outputStorage); } // begin response building tcpip::Storage tempMsg; // response-code, variableID, objectID tempMsg.writeUnsignedByte(RESPONSE_GET_LANE_VARIABLE); tempMsg.writeUnsignedByte(variable); tempMsg.writeString(id); if (variable == ID_LIST) { std::vector<std::string> ids; MSLane::insertIDs(ids); tempMsg.writeUnsignedByte(TYPE_STRINGLIST); tempMsg.writeStringList(ids); } else if (variable == ID_COUNT) { std::vector<std::string> ids; MSLane::insertIDs(ids); tempMsg.writeUnsignedByte(TYPE_INTEGER); tempMsg.writeInt((int) ids.size()); } else { MSLane* lane = MSLane::dictionary(id); if (lane == 0) { return server.writeErrorStatusCmd(CMD_GET_LANE_VARIABLE, "Lane '" + id + "' is not known", outputStorage); } switch (variable) { case LANE_LINK_NUMBER: tempMsg.writeUnsignedByte(TYPE_UBYTE); tempMsg.writeUnsignedByte((int) lane->getLinkCont().size()); break; case LANE_EDGE_ID: tempMsg.writeUnsignedByte(TYPE_STRING); tempMsg.writeString(lane->getEdge().getID()); break; case VAR_LENGTH: tempMsg.writeUnsignedByte(TYPE_DOUBLE); tempMsg.writeDouble(lane->getLength()); break; case VAR_MAXSPEED: tempMsg.writeUnsignedByte(TYPE_DOUBLE); tempMsg.writeDouble(lane->getSpeedLimit()); break; case LANE_LINKS: { tempMsg.writeUnsignedByte(TYPE_COMPOUND); tcpip::Storage tempContent; unsigned int cnt = 0; tempContent.writeUnsignedByte(TYPE_INTEGER); const MSLinkCont& links = lane->getLinkCont(); tempContent.writeInt((int) links.size()); ++cnt; const SUMOTime currTime = MSNet::getInstance()->getCurrentTimeStep(); for (MSLinkCont::const_iterator i = links.begin(); i != links.end(); ++i) { MSLink* link = (*i); // approached non-internal lane (if any) tempContent.writeUnsignedByte(TYPE_STRING); tempContent.writeString(link->getLane() != 0 ? link->getLane()->getID() : ""); ++cnt; // approached "via", internal lane (if any) tempContent.writeUnsignedByte(TYPE_STRING); #ifdef HAVE_INTERNAL_LANES tempContent.writeString(link->getViaLane() != 0 ? link->getViaLane()->getID() : ""); #else tempContent.writeString(""); #endif ++cnt; // priority tempContent.writeUnsignedByte(TYPE_UBYTE); tempContent.writeUnsignedByte(link->havePriority() ? 1 : 0); ++cnt; // opened tempContent.writeUnsignedByte(TYPE_UBYTE); const SUMOReal speed = MIN2(lane->getSpeedLimit(), link->getLane()->getSpeedLimit()); tempContent.writeUnsignedByte(link->opened(currTime, speed, speed, DEFAULT_VEH_LENGTH, 0.0, DEFAULT_VEH_DECEL, 0) ? 1 : 0); ++cnt; // approaching foe tempContent.writeUnsignedByte(TYPE_UBYTE); tempContent.writeUnsignedByte(link->hasApproachingFoe(currTime, currTime, 0) ? 1 : 0); ++cnt; // state (not implemented, yet) tempContent.writeUnsignedByte(TYPE_STRING); tempContent.writeString(SUMOXMLDefinitions::LinkStates.getString(link->getState())); ++cnt; // direction tempContent.writeUnsignedByte(TYPE_STRING); tempContent.writeString(SUMOXMLDefinitions::LinkDirections.getString(link->getDirection())); ++cnt; // length tempContent.writeUnsignedByte(TYPE_DOUBLE); tempContent.writeDouble(link->getLength()); ++cnt; } tempMsg.writeInt((int) cnt); tempMsg.writeStorage(tempContent); } break; case LANE_ALLOWED: { tempMsg.writeUnsignedByte(TYPE_STRINGLIST); SVCPermissions permissions = lane->getPermissions(); if (permissions == SVCFreeForAll) { // special case: write nothing permissions = 0; } tempMsg.writeStringList(getAllowedVehicleClassNamesList(permissions)); } case LANE_DISALLOWED: { tempMsg.writeUnsignedByte(TYPE_STRINGLIST); tempMsg.writeStringList(getAllowedVehicleClassNamesList(~(lane->getPermissions()))); // negation yields disallowed } break; case VAR_SHAPE: tempMsg.writeUnsignedByte(TYPE_POLYGON); tempMsg.writeUnsignedByte((int)MIN2(static_cast<size_t>(255), lane->getShape().size())); for (unsigned int iPoint = 0; iPoint < MIN2(static_cast<size_t>(255), lane->getShape().size()); ++iPoint) { tempMsg.writeDouble(lane->getShape()[iPoint].x()); tempMsg.writeDouble(lane->getShape()[iPoint].y()); } break; case VAR_CO2EMISSION: tempMsg.writeUnsignedByte(TYPE_DOUBLE); tempMsg.writeDouble(lane->getCO2Emissions()); break; case VAR_COEMISSION: tempMsg.writeUnsignedByte(TYPE_DOUBLE); tempMsg.writeDouble(lane->getCOEmissions()); break; case VAR_HCEMISSION: tempMsg.writeUnsignedByte(TYPE_DOUBLE); tempMsg.writeDouble(lane->getHCEmissions()); break; case VAR_PMXEMISSION: tempMsg.writeUnsignedByte(TYPE_DOUBLE); tempMsg.writeDouble(lane->getPMxEmissions()); break; case VAR_NOXEMISSION: tempMsg.writeUnsignedByte(TYPE_DOUBLE); tempMsg.writeDouble(lane->getNOxEmissions()); break; case VAR_FUELCONSUMPTION: tempMsg.writeUnsignedByte(TYPE_DOUBLE); tempMsg.writeDouble(lane->getFuelConsumption()); break; case VAR_NOISEEMISSION: tempMsg.writeUnsignedByte(TYPE_DOUBLE); tempMsg.writeDouble(lane->getHarmonoise_NoiseEmissions()); break; case LAST_STEP_VEHICLE_NUMBER: tempMsg.writeUnsignedByte(TYPE_INTEGER); tempMsg.writeInt((int) lane->getVehicleNumber()); break; case LAST_STEP_MEAN_SPEED: tempMsg.writeUnsignedByte(TYPE_DOUBLE); tempMsg.writeDouble(lane->getMeanSpeed()); break; case LAST_STEP_VEHICLE_ID_LIST: { std::vector<std::string> vehIDs; const MSLane::VehCont& vehs = lane->getVehiclesSecure(); for (MSLane::VehCont::const_iterator j = vehs.begin(); j != vehs.end(); ++j) { vehIDs.push_back((*j)->getID()); } lane->releaseVehicles(); tempMsg.writeUnsignedByte(TYPE_STRINGLIST); tempMsg.writeStringList(vehIDs); } break; case LAST_STEP_OCCUPANCY: tempMsg.writeUnsignedByte(TYPE_DOUBLE); tempMsg.writeDouble(lane->getNettoOccupancy()); break; case LAST_STEP_VEHICLE_HALTING_NUMBER: { int halting = 0; const MSLane::VehCont& vehs = lane->getVehiclesSecure(); for (MSLane::VehCont::const_iterator j = vehs.begin(); j != vehs.end(); ++j) { if ((*j)->getSpeed() < SUMO_const_haltingSpeed) { ++halting; } } lane->releaseVehicles(); tempMsg.writeUnsignedByte(TYPE_INTEGER); tempMsg.writeInt(halting); } break; case LAST_STEP_LENGTH: { SUMOReal lengthSum = 0; const MSLane::VehCont& vehs = lane->getVehiclesSecure(); for (MSLane::VehCont::const_iterator j = vehs.begin(); j != vehs.end(); ++j) { lengthSum += (*j)->getVehicleType().getLength(); } tempMsg.writeUnsignedByte(TYPE_DOUBLE); if (vehs.size() == 0) { tempMsg.writeDouble(0); } else { tempMsg.writeDouble(lengthSum / (SUMOReal) vehs.size()); } lane->releaseVehicles(); } break; case VAR_WAITING_TIME: { tempMsg.writeUnsignedByte(TYPE_DOUBLE); tempMsg.writeDouble(lane->getWaitingSeconds()); } break; case VAR_CURRENT_TRAVELTIME: { SUMOReal meanSpeed = lane->getMeanSpeed(); tempMsg.writeUnsignedByte(TYPE_DOUBLE); if (meanSpeed != 0) { tempMsg.writeDouble(lane->getLength() / meanSpeed); } else { tempMsg.writeDouble(1000000.); } } break; case VAR_WIDTH: tempMsg.writeUnsignedByte(TYPE_DOUBLE); tempMsg.writeDouble(lane->getWidth()); break; default: break; } } server.writeStatusCmd(CMD_GET_LANE_VARIABLE, RTYPE_OK, "", outputStorage); server.writeResponseWithLength(outputStorage, tempMsg); return true; }
// =========================================================================== // method definitions // =========================================================================== MSRightOfWayJunction::MSRightOfWayJunction(const std::string& id, SumoXMLNodeType type, const Position& position, const PositionVector& shape, std::vector<MSLane*> incoming, #ifdef HAVE_INTERNAL_LANES std::vector<MSLane*> internal, #endif MSJunctionLogic* logic) : MSLogicJunction(id, type, position, shape, incoming #ifdef HAVE_INTERNAL_LANES , internal), #else ), #endif myLogic(logic) {} MSRightOfWayJunction::~MSRightOfWayJunction() { delete myLogic; } void MSRightOfWayJunction::postloadInit() { // inform links where they have to report approaching vehicles to unsigned int requestPos = 0; std::vector<MSLane*>::iterator i; // going through the incoming lanes... unsigned int maxNo = 0; std::vector<std::pair<MSLane*, MSLink*> > sortedLinks; for (i = myIncomingLanes.begin(); i != myIncomingLanes.end(); ++i) { const MSLinkCont& links = (*i)->getLinkCont(); // ... set information for every link for (MSLinkCont::const_iterator j = links.begin(); j != links.end(); j++) { if ((*j)->getLane()->getEdge().isWalkingArea() || ((*i)->getEdge().isWalkingArea() && !(*j)->getLane()->getEdge().isCrossing())) { continue; } sortedLinks.push_back(std::make_pair(*i, *j)); ++maxNo; } } const bool hasFoes = myLogic->hasFoes(); for (i = myIncomingLanes.begin(); i != myIncomingLanes.end(); ++i) { const MSLinkCont& links = (*i)->getLinkCont(); // ... set information for every link for (MSLinkCont::const_iterator j = links.begin(); j != links.end(); j++) { if ((*j)->getLane()->getEdge().isWalkingArea() || ((*i)->getEdge().isWalkingArea() && !(*j)->getLane()->getEdge().isCrossing())) { continue; } if (myLogic->getLogicSize() <= requestPos) { throw ProcessError("Found invalid logic position of a link for junction '" + getID() + "' (" + toString(requestPos) + ", max " + toString(myLogic->getLogicSize()) + ") -> (network error)"); } const MSLogicJunction::LinkBits& linkResponse = myLogic->getResponseFor(requestPos); // SUMO_ATTR_RESPONSE const MSLogicJunction::LinkBits& linkFoes = myLogic->getFoesFor(requestPos); // SUMO_ATTR_FOES bool cont = myLogic->getIsCont(requestPos); myLinkFoeLinks[*j] = std::vector<MSLink*>(); for (unsigned int c = 0; c < maxNo; ++c) { if (linkResponse.test(c)) { MSLink* foe = sortedLinks[c].second; myLinkFoeLinks[*j].push_back(foe); #ifdef HAVE_INTERNAL_LANES if (MSGlobals::gUsingInternalLanes && foe->getViaLane() != 0) { assert(foe->getViaLane()->getLinkCont().size() == 1); MSLink* foeExitLink = foe->getViaLane()->getLinkCont()[0]; // add foe links after an internal junction if (foeExitLink->getViaLane() != 0) { myLinkFoeLinks[*j].push_back(foeExitLink); } } #endif } } std::vector<MSLink*> foes; for (unsigned int c = 0; c < maxNo; ++c) { if (linkFoes.test(c)) { MSLink* foe = sortedLinks[c].second; foes.push_back(foe); #ifdef HAVE_INTERNAL_LANES MSLane* l = foe->getViaLane(); if (l == 0) { continue; } // add foe links after an internal junction const MSLinkCont& lc = l->getLinkCont(); for (MSLinkCont::const_iterator q = lc.begin(); q != lc.end(); ++q) { if ((*q)->getViaLane() != 0) { foes.push_back(*q); } } #endif } } myLinkFoeInternalLanes[*j] = std::vector<MSLane*>(); #ifdef HAVE_INTERNAL_LANES if (MSGlobals::gUsingInternalLanes && myInternalLanes.size() > 0) { int li = 0; for (unsigned int c = 0; c < sortedLinks.size(); ++c) { if (sortedLinks[c].second->getLane() == 0) { // dead end continue; } if (linkFoes.test(c)) { myLinkFoeInternalLanes[*j].push_back(myInternalLanes[li]); if (linkResponse.test(c)) { const std::vector<MSLane::IncomingLaneInfo>& l = myInternalLanes[li]->getIncomingLanes(); if (l.size() == 1 && l[0].lane->getEdge().getPurpose() == MSEdge::EDGEFUNCTION_INTERNAL) { myLinkFoeInternalLanes[*j].push_back(l[0].lane); } } } ++li; } } #endif (*j)->setRequestInformation((int)requestPos, hasFoes, cont, myLinkFoeLinks[*j], myLinkFoeInternalLanes[*j]); #ifdef HAVE_INTERNAL_LANES // the exit link for a link before an internal junction is handled in MSInternalJunction // so we need to skip if cont=true if (MSGlobals::gUsingInternalLanes && (*j)->getViaLane() != 0 && !cont) { assert((*j)->getViaLane()->getLinkCont().size() == 1); MSLink* exitLink = (*j)->getViaLane()->getLinkCont()[0]; exitLink->setRequestInformation((int)requestPos, false, false, std::vector<MSLink*>(), myLinkFoeInternalLanes[*j], (*j)->getViaLane()); } #endif for (std::vector<MSLink*>::const_iterator k = foes.begin(); k != foes.end(); ++k) { (*j)->addBlockedLink(*k); (*k)->addBlockedLink(*j); } requestPos++; } } }
int MSLCM_LC2013::_wantsChange( int laneOffset, MSAbstractLaneChangeModel::MSLCMessager& msgPass, int blocked, const std::pair<MSVehicle*, SUMOReal>& leader, const std::pair<MSVehicle*, SUMOReal>& neighLead, const std::pair<MSVehicle*, SUMOReal>& neighFollow, const MSLane& neighLane, const std::vector<MSVehicle::LaneQ>& preb, MSVehicle** lastBlocked, MSVehicle** firstBlocked) { assert(laneOffset == 1 || laneOffset == -1); const SUMOTime currentTime = MSNet::getInstance()->getCurrentTimeStep(); // compute bestLaneOffset MSVehicle::LaneQ curr, neigh, best; int bestLaneOffset = 0; SUMOReal currentDist = 0; SUMOReal neighDist = 0; int currIdx = 0; MSLane* prebLane = myVehicle.getLane(); if (prebLane->getEdge().getPurpose() == MSEdge::EDGEFUNCTION_INTERNAL) { // internal edges are not kept inside the bestLanes structure prebLane = prebLane->getLinkCont()[0]->getLane(); } for (int p = 0; p < (int) preb.size(); ++p) { if (preb[p].lane == prebLane && p + laneOffset >= 0) { assert(p + laneOffset < (int)preb.size()); curr = preb[p]; neigh = preb[p + laneOffset]; currentDist = curr.length; neighDist = neigh.length; bestLaneOffset = curr.bestLaneOffset; if (bestLaneOffset == 0 && preb[p + laneOffset].bestLaneOffset == 0) { bestLaneOffset = laneOffset; } best = preb[p + bestLaneOffset]; currIdx = p; break; } } // direction specific constants const bool right = (laneOffset == -1); const int lca = (right ? LCA_RIGHT : LCA_LEFT); const int myLca = (right ? LCA_MRIGHT : LCA_MLEFT); const int lcaCounter = (right ? LCA_LEFT : LCA_RIGHT); const bool changeToBest = (right && bestLaneOffset < 0) || (!right && bestLaneOffset > 0); // keep information about being a leader/follower int ret = (myOwnState & 0xffff0000); ret = slowDownForBlocked(lastBlocked, ret); if (lastBlocked != firstBlocked) { ret = slowDownForBlocked(firstBlocked, ret); } // we try to estimate the distance which is necessary to get on a lane // we have to get on in order to keep our route // we assume we need something that depends on our velocity // and compare this with the free space on our wished lane // // if the free space is somehow less than the space we need, we should // definitely try to get to the desired lane // // this rule forces our vehicle to change the lane if a lane changing is necessary soon // lookAheadDistance: // we do not want the lookahead distance to change all the time so we discrectize the speed a bit if (myVehicle.getSpeed() > myLookAheadSpeed) { myLookAheadSpeed = myVehicle.getSpeed(); } else { myLookAheadSpeed = MAX2(LOOK_AHEAD_MIN_SPEED, (LOOK_AHEAD_SPEED_MEMORY * myLookAheadSpeed + (1 - LOOK_AHEAD_SPEED_MEMORY) * myVehicle.getSpeed())); } SUMOReal laDist = myLookAheadSpeed * (right ? LOOK_FORWARD_RIGHT : LOOK_FORWARD_LEFT); laDist += myVehicle.getVehicleType().getLengthWithGap() * (SUMOReal) 2.; // free space that is available for changing //const SUMOReal neighSpeed = (neighLead.first != 0 ? neighLead.first->getSpeed() : // neighFollow.first != 0 ? neighFollow.first->getSpeed() : // best.lane->getSpeedLimit()); // @note: while this lets vehicles change earlier into the correct direction // it also makes the vehicles more "selfish" and prevents changes which are necessary to help others int roundaboutEdgesAhead = 0; for (std::vector<MSLane*>::iterator it = curr.bestContinuations.begin(); it != curr.bestContinuations.end(); ++it) { if ((*it) != 0 && (*it)->getEdge().isRoundabout()) { roundaboutEdgesAhead += 1; } else if (roundaboutEdgesAhead > 0) { // only check the next roundabout break; } } int roundaboutEdgesAheadNeigh = 0; for (std::vector<MSLane*>::iterator it = neigh.bestContinuations.begin(); it != neigh.bestContinuations.end(); ++it) { if ((*it) != 0 && (*it)->getEdge().isRoundabout()) { roundaboutEdgesAheadNeigh += 1; } else if (roundaboutEdgesAheadNeigh > 0) { // only check the next roundabout break; } } if (roundaboutEdgesAhead > 1) { currentDist += roundaboutEdgesAhead * ROUNDABOUT_DIST_BONUS; neighDist += roundaboutEdgesAheadNeigh * ROUNDABOUT_DIST_BONUS; } const SUMOReal usableDist = (currentDist - myVehicle.getPositionOnLane() - best.occupation * JAM_FACTOR); const SUMOReal maxJam = MAX2(preb[currIdx + laneOffset].occupation, preb[currIdx].occupation); const SUMOReal neighLeftPlace = MAX2((SUMOReal) 0, neighDist - myVehicle.getPositionOnLane() - maxJam); if (changeToBest && bestLaneOffset == curr.bestLaneOffset && currentDistDisallows(usableDist, bestLaneOffset, laDist)) { /// @brief we urgently need to change lanes to follow our route ret = ret | lca | LCA_STRATEGIC | LCA_URGENT; } else { if (!myAllowOvertakingRight && !right && !myVehicle.congested() && neighLead.first != 0) { // check for slower leader on the left. we should not overtake but // rather move left ourselves (unless congested) MSVehicle* nv = neighLead.first; if (nv->getSpeed() < myVehicle.getSpeed()) { myVSafes.push_back(myCarFollowModel.followSpeed( &myVehicle, myVehicle.getSpeed(), neighLead.second, nv->getSpeed(), nv->getCarFollowModel().getMaxDecel())); if (nv->getSpeed() + 5 / 3.6 < myVehicle.getSpeed()) { mySpeedGainProbability += CHANGE_PROB_THRESHOLD_LEFT / 3; } } } if (!changeToBest && (currentDistDisallows(neighLeftPlace, abs(bestLaneOffset) + 2, laDist))) { // the opposite lane-changing direction should be done than the one examined herein // we'll check whether we assume we could change anyhow and get back in time... // // this rule prevents the vehicle from moving in opposite direction of the best lane // unless the way till the end where the vehicle has to be on the best lane // is long enough ret = ret | LCA_STAY | LCA_STRATEGIC; } else if (bestLaneOffset == 0 && (neighLeftPlace * 2. < laDist)) { // the current lane is the best and a lane-changing would cause a situation // of which we assume we will not be able to return to the lane we have to be on. // this rule prevents the vehicle from leaving the current, best lane when it is // close to this lane's end ret = ret | LCA_STAY | LCA_STRATEGIC; } } // check for overriding TraCI requests ret = myVehicle.influenceChangeDecision(ret); if ((ret & lcaCounter) != 0) { // we are not interested in traci requests for the opposite direction here ret &= ~(LCA_TRACI | lcaCounter | LCA_URGENT); } if ((ret & LCA_STAY) != 0) { return ret; } if ((ret & LCA_URGENT) != 0) { // prepare urgent lane change maneuver // save the left space myLeftSpace = currentDist - myVehicle.getPositionOnLane(); if (changeToBest && abs(bestLaneOffset) > 1) { // there might be a vehicle which needs to counter-lane-change one lane further and we cannot see it yet myLeadingBlockerLength = MAX2((SUMOReal)(right ? 20.0 : 40.0), myLeadingBlockerLength); } // letting vehicles merge in at the end of the lane in case of counter-lane change, step#1 // if there is a leader and he wants to change to the opposite direction saveBlockerLength(neighLead.first, lcaCounter); if (*firstBlocked != neighLead.first) { saveBlockerLength(*firstBlocked, lcaCounter); } const SUMOReal remainingSeconds = ((ret & LCA_TRACI) == 0 ? MAX2((SUMOReal)STEPS2TIME(TS), myLeftSpace / myLookAheadSpeed / abs(bestLaneOffset) / URGENCY) : myVehicle.getInfluencer().changeRequestRemainingSeconds(currentTime)); const SUMOReal plannedSpeed = informLeader(msgPass, blocked, myLca, neighLead, remainingSeconds); if (plannedSpeed >= 0) { // maybe we need to deal with a blocking follower informFollower(msgPass, blocked, myLca, neighFollow, remainingSeconds, plannedSpeed); } return ret; } if (roundaboutEdgesAhead > 1) { // try to use the inner lanes of a roundabout to increase throughput // unless we are approaching the exit if (lca == LCA_LEFT) { return ret | lca | LCA_COOPERATIVE; } else { return ret | LCA_STAY | LCA_COOPERATIVE; } } // let's also regard the case where the vehicle is driving on a highway... // in this case, we do not want to get to the dead-end of an on-ramp if (right) { if (bestLaneOffset == 0 && myVehicle.getLane()->getVehicleMaxSpeed(&myVehicle) > 80. / 3.6 && myLookAheadSpeed > SUMO_const_haltingSpeed) { return ret | LCA_STAY | LCA_STRATEGIC; } } // -------- // -------- make place on current lane if blocking follower //if (amBlockingFollowerPlusNB()) { // std::cout << myVehicle.getID() << ", " << currentDistAllows(neighDist, bestLaneOffset, laDist) // << " neighDist=" << neighDist // << " currentDist=" << currentDist // << "\n"; //} if (amBlockingFollowerPlusNB() && (changeToBest || currentDistAllows(neighDist, abs(bestLaneOffset) + 1, laDist))) { return ret | lca | LCA_COOPERATIVE | LCA_URGENT ;//| LCA_CHANGE_TO_HELP; } // -------- //// -------- security checks for krauss //// (vsafe fails when gap<0) //if ((blocked & LCA_BLOCKED) != 0) { // return ret; //} //// -------- // -------- higher speed //if ((congested(neighLead.first) && neighLead.second < 20) || predInteraction(leader.first)) { //!!! // return ret; //} SUMOReal thisLaneVSafe = myVehicle.getLane()->getVehicleMaxSpeed(&myVehicle); SUMOReal neighLaneVSafe = neighLane.getVehicleMaxSpeed(&myVehicle); if (neighLead.first == 0) { neighLaneVSafe = MIN2(neighLaneVSafe, myCarFollowModel.followSpeed(&myVehicle, myVehicle.getSpeed(), neighDist, 0, 0)); } else { // @todo: what if leader is below safe gap?!!! neighLaneVSafe = MIN2(neighLaneVSafe, myCarFollowModel.followSpeed( &myVehicle, myVehicle.getSpeed(), neighLead.second, neighLead.first->getSpeed(), neighLead.first->getCarFollowModel().getMaxDecel())); } if (leader.first == 0) { thisLaneVSafe = MIN2(thisLaneVSafe, myCarFollowModel.followSpeed(&myVehicle, myVehicle.getSpeed(), currentDist, 0, 0)); } else { // @todo: what if leader is below safe gap?!!! thisLaneVSafe = MIN2(thisLaneVSafe, myCarFollowModel.followSpeed(&myVehicle, myVehicle.getSpeed(), leader.second, leader.first->getSpeed(), leader.first->getCarFollowModel().getMaxDecel())); } thisLaneVSafe = MIN3(thisLaneVSafe, myVehicle.getVehicleType().getMaxSpeed(), myVehicle.getLane()->getVehicleMaxSpeed(&myVehicle)); neighLaneVSafe = MIN3(neighLaneVSafe, myVehicle.getVehicleType().getMaxSpeed(), neighLane.getVehicleMaxSpeed(&myVehicle)); const SUMOReal relativeGain = (neighLaneVSafe - thisLaneVSafe) / neighLaneVSafe; if (right) { // ONLY FOR CHANGING TO THE RIGHT if (thisLaneVSafe - 5 / 3.6 > neighLaneVSafe) { // ok, the current lane is faster than the right one... if (mySpeedGainProbability < 0) { mySpeedGainProbability /= 2.0; //myKeepRightProbability /= 2.0; } } else { // ok, the current lane is not faster than the right one mySpeedGainProbability -= relativeGain; // honor the obligation to keep right (Rechtsfahrgebot) // XXX consider fast approaching followers on the current lane //const SUMOReal vMax = myLookAheadSpeed; const SUMOReal vMax = MIN2(myVehicle.getVehicleType().getMaxSpeed(), myVehicle.getLane()->getVehicleMaxSpeed(&myVehicle)); const SUMOReal acceptanceTime = KEEP_RIGHT_ACCEPTANCE * vMax * MAX2((SUMOReal)1, myVehicle.getSpeed()) / myVehicle.getLane()->getSpeedLimit(); SUMOReal fullSpeedGap = MAX2((SUMOReal)0, neighDist - myVehicle.getCarFollowModel().brakeGap(vMax)); SUMOReal fullSpeedDrivingSeconds = MIN2(acceptanceTime, fullSpeedGap / vMax); if (neighLead.first != 0 && neighLead.first->getSpeed() < vMax) { fullSpeedGap = MAX2((SUMOReal)0, MIN2(fullSpeedGap, neighLead.second - myVehicle.getCarFollowModel().getSecureGap( vMax, neighLead.first->getSpeed(), neighLead.first->getCarFollowModel().getMaxDecel()))); fullSpeedDrivingSeconds = MIN2(fullSpeedDrivingSeconds, fullSpeedGap / (vMax - neighLead.first->getSpeed())); } const SUMOReal deltaProb = (CHANGE_PROB_THRESHOLD_RIGHT * STEPS2TIME(DELTA_T) * (fullSpeedDrivingSeconds / acceptanceTime) / KEEP_RIGHT_TIME); myKeepRightProbability -= deltaProb; if (gDebugFlag2) { std::cout << STEPS2TIME(currentTime) << " veh=" << myVehicle.getID() << " vMax=" << vMax << " neighDist=" << neighDist << " brakeGap=" << myVehicle.getCarFollowModel().brakeGap(myVehicle.getSpeed()) << " leaderSpeed=" << (neighLead.first == 0 ? -1 : neighLead.first->getSpeed()) << " secGap=" << (neighLead.first == 0 ? -1 : myVehicle.getCarFollowModel().getSecureGap( myVehicle.getSpeed(), neighLead.first->getSpeed(), neighLead.first->getCarFollowModel().getMaxDecel())) << " acceptanceTime=" << acceptanceTime << " fullSpeedGap=" << fullSpeedGap << " fullSpeedDrivingSeconds=" << fullSpeedDrivingSeconds << " dProb=" << deltaProb << "\n"; } if (myKeepRightProbability < -CHANGE_PROB_THRESHOLD_RIGHT) { return ret | lca | LCA_KEEPRIGHT; } } if (mySpeedGainProbability < -CHANGE_PROB_THRESHOLD_RIGHT && neighDist / MAX2((SUMOReal) .1, myVehicle.getSpeed()) > 20.) { //./MAX2((SUMOReal) .1, myVehicle.getSpeed())) { // -.1 return ret | lca | LCA_SPEEDGAIN; } } else { // ONLY FOR CHANGING TO THE LEFT if (thisLaneVSafe > neighLaneVSafe) { // this lane is better if (mySpeedGainProbability > 0) { mySpeedGainProbability /= 2.0; } } else { // left lane is better mySpeedGainProbability += relativeGain; } if (mySpeedGainProbability > CHANGE_PROB_THRESHOLD_LEFT && neighDist / MAX2((SUMOReal) .1, myVehicle.getSpeed()) > 20.) { // .1 return ret | lca | LCA_SPEEDGAIN; } } // -------- if (changeToBest && bestLaneOffset == curr.bestLaneOffset && (right ? mySpeedGainProbability < 0 : mySpeedGainProbability > 0)) { // change towards the correct lane, speedwise it does not hurt return ret | lca | LCA_STRATEGIC; } return ret; }
// =========================================================================== // method definitions // =========================================================================== MSRightOfWayJunction::MSRightOfWayJunction (const std::string& id, const Position& position, const PositionVector& shape, std::vector<MSLane*> incoming, const SUMOReal height, #ifdef HAVE_INTERNAL_LANES std::vector<MSLane*> internal, #endif MSJunctionLogic* logic) :MSLogicJunction(id, position, shape, incoming, height #ifdef HAVE_INTERNAL_LANES , internal), #else ), #endif myLogic(logic) { int i; if(OptionsCont::getOptions().getInt("buildVerbosity") > 1) { std::cout<<"----> MSRightOfWayJunction::MSRightOfWayJunction(...)"<<std::endl; std::cout<<"MSRightOfWayJunction:"<<std::endl; std::cout<<" id: "<<id<<std::endl; } static_cast < MSJunction * > (this)->setDynamicClassName("MSRightOfWayJunction"); for(i=0; i<incoming.size(); i++) { if(incoming.at(i)->getToJunction() == NULL) { //incoming.at(i)->setToJunction(this); } /* if(incoming.at(i)->getEdge().leftLane(incoming.at(i)) == incoming.at(i)) { if(incoming.at(i)->getRightLane()->getToJunction() == NULL) { ; } else { ; } } */ } } MSRightOfWayJunction::~MSRightOfWayJunction() { delete myLogic; } /* [UPREGO] This function is called from * MSJunctionControl::postloadInitContainer() */ void MSRightOfWayJunction::postloadInit() { // inform links where they have to report approaching vehicles to unsigned int requestPos = 0; std::vector<MSLane*>::iterator i; // going through the incoming lanes... unsigned int maxNo = 0; /* [UPREGO] How sorted? */ std::vector<std::pair<MSLane*,MSLink*> >sortedLinks; /* [UPREGO] Iterate with i over incoming lanes of this junction */ for (i = myIncomingLanes.begin(); i != myIncomingLanes.end(); ++i) { /* [UPREGO] Links of this incoming lane? */ const MSLinkCont& links = (*i)->getLinkCont(); // ... set information for every link for(MSLinkCont::const_iterator j = links.begin(); j != links.end(); j++) { /* [UPREGO] ??? */ if(myLogic->getLogicSize() <= requestPos) { std::cout<<"MSRightOfWayJunction.cpp:123 throwing exception!"<<std::endl; std::cout<<" getID(){"<<getID()<<"}"<<std::endl; //throw ProcessError("Found invalid logic position of a link (network error)"); /* TODO TASK FIXME ALERT DANGER if exception commented */ } /* [UPREGO] Create new link with: * - An incoming lane (i) of this junction (this) * - and one link (j) of the links container of the incoming lane */ sortedLinks.push_back(std::make_pair(*i, *j)); /* [UPREGO] And note it in maxNo */ ++maxNo; } } bool isCrossing = myLogic->isCrossing(); for (i = myIncomingLanes.begin(); i != myIncomingLanes.end(); ++i) { const MSLinkCont& links = (*i)->getLinkCont(); // ... set information for every link for(MSLinkCont::const_iterator j = links.begin(); j != links.end(); j++) { if(myLogic->getLogicSize() <= requestPos) { std::cout<<"MSRightOfWayJunction.cpp:144 throwing exception!"<<std::endl; std::cout<<" getID(){"<<getID()<<"}"<<std::endl; //throw ProcessError("Found invalid logic position of a link (network error)"); /* TODO TASK FIXME ALERT DANGER if exception commented */ } const MSLogicJunction::LinkFoes& foeLinks = myLogic->getFoesFor(requestPos); const std::bitset<64> &internalFoes = myLogic->getInternalFoesFor(requestPos); bool cont = myLogic->getIsCont(requestPos); myLinkFoeLinks[*j] = std::vector<MSLink*>(); for (unsigned int c = 0; c < maxNo; ++c) { if (foeLinks.test(c)) { myLinkFoeLinks[*j].push_back(sortedLinks[c].second); } } std::vector<MSLink*> foes; for (unsigned int c = 0; c < maxNo; ++c) { if (internalFoes.test(c)) { MSLink* foe = sortedLinks[c].second; foes.push_back(foe); #ifdef HAVE_INTERNAL_LANES MSLane* l = foe->getViaLane(); if (l == 0) { continue; } const MSLinkCont& lc = l->getLinkCont(); for (MSLinkCont::const_iterator q = lc.begin(); q != lc.end(); ++q) { if ((*q)->getViaLane() != 0) { foes.push_back(*q); } } #endif } } myLinkFoeInternalLanes[*j] = std::vector<MSLane*>(); #ifdef HAVE_INTERNAL_LANES if (MSGlobals::gUsingInternalLanes && myInternalLanes.size() > 0) { int li = 0; for (unsigned int c = 0; c < sortedLinks.size(); ++c) { if (sortedLinks[c].second->getLane() == 0) { // dead end continue; } if (internalFoes.test(c)) { myLinkFoeInternalLanes[*j].push_back(myInternalLanes[li]); } ++li; } } #endif (*j)->setRequestInformation(requestPos, requestPos, isCrossing, cont, myLinkFoeLinks[*j], myLinkFoeInternalLanes[*j]); for (std::vector<MSLink*>::const_iterator k = foes.begin(); k != foes.end(); ++k) { (*j)->addBlockedLink(*k); (*k)->addBlockedLink(*j); } requestPos++; } } #ifdef HAVE_INTERNAL_LANES // set information for the internal lanes requestPos = 0; for (i = myInternalLanes.begin(); i != myInternalLanes.end(); ++i) { // ... set information about participation static_cast<MSInternalLane*>(*i)->setParentJunctionInformation(&myInnerState, requestPos++); } #endif }
// =========================================================================== // method definitions // =========================================================================== MSRightOfWayJunction::MSRightOfWayJunction(const std::string& id, const Position& position, const PositionVector& shape, std::vector<MSLane*> incoming, #ifdef HAVE_INTERNAL_LANES std::vector<MSLane*> internal, #endif MSJunctionLogic* logic) : MSLogicJunction(id, position, shape, incoming #ifdef HAVE_INTERNAL_LANES , internal), #else ), #endif myLogic(logic) {} MSRightOfWayJunction::~MSRightOfWayJunction() { delete myLogic; } void MSRightOfWayJunction::postloadInit() { // inform links where they have to report approaching vehicles to unsigned int requestPos = 0; std::vector<MSLane*>::iterator i; // going through the incoming lanes... unsigned int maxNo = 0; std::vector<std::pair<MSLane*, MSLink*> > sortedLinks; for (i = myIncomingLanes.begin(); i != myIncomingLanes.end(); ++i) { const MSLinkCont& links = (*i)->getLinkCont(); // ... set information for every link for (MSLinkCont::const_iterator j = links.begin(); j != links.end(); j++) { if (myLogic->getLogicSize() <= requestPos) { throw ProcessError("Found invalid logic position of a link (network error)"); } sortedLinks.push_back(std::make_pair(*i, *j)); ++maxNo; } } bool isCrossing = myLogic->isCrossing(); for (i = myIncomingLanes.begin(); i != myIncomingLanes.end(); ++i) { const MSLinkCont& links = (*i)->getLinkCont(); // ... set information for every link for (MSLinkCont::const_iterator j = links.begin(); j != links.end(); j++) { if (myLogic->getLogicSize() <= requestPos) { throw ProcessError("Found invalid logic position of a link (network error)"); } const MSLogicJunction::LinkFoes& foeLinks = myLogic->getFoesFor(requestPos); const std::bitset<64>& internalFoes = myLogic->getInternalFoesFor(requestPos); bool cont = myLogic->getIsCont(requestPos); myLinkFoeLinks[*j] = std::vector<MSLink*>(); for (unsigned int c = 0; c < maxNo; ++c) { if (foeLinks.test(c)) { myLinkFoeLinks[*j].push_back(sortedLinks[c].second); } } std::vector<MSLink*> foes; for (unsigned int c = 0; c < maxNo; ++c) { if (internalFoes.test(c)) { MSLink* foe = sortedLinks[c].second; foes.push_back(foe); #ifdef HAVE_INTERNAL_LANES MSLane* l = foe->getViaLane(); if (l == 0) { continue; } const MSLinkCont& lc = l->getLinkCont(); for (MSLinkCont::const_iterator q = lc.begin(); q != lc.end(); ++q) { if ((*q)->getViaLane() != 0) { foes.push_back(*q); } } #endif } } myLinkFoeInternalLanes[*j] = std::vector<MSLane*>(); #ifdef HAVE_INTERNAL_LANES if (MSGlobals::gUsingInternalLanes && myInternalLanes.size() > 0) { int li = 0; for (unsigned int c = 0; c < sortedLinks.size(); ++c) { if (sortedLinks[c].second->getLane() == 0) { // dead end continue; } if (internalFoes.test(c)) { myLinkFoeInternalLanes[*j].push_back(myInternalLanes[li]); if (foeLinks.test(c)) { const std::vector<MSLane::IncomingLaneInfo>& l = myInternalLanes[li]->getIncomingLanes(); if (l.size() == 1 && l[0].lane->getEdge().getPurpose() == MSEdge::EDGEFUNCTION_INTERNAL) { myLinkFoeInternalLanes[*j].push_back(l[0].lane); } } } ++li; } } #endif (*j)->setRequestInformation(requestPos, requestPos, isCrossing, cont, myLinkFoeLinks[*j], myLinkFoeInternalLanes[*j]); for (std::vector<MSLink*>::const_iterator k = foes.begin(); k != foes.end(); ++k) { (*j)->addBlockedLink(*k); (*k)->addBlockedLink(*j); } requestPos++; } } #ifdef HAVE_INTERNAL_LANES // set information for the internal lanes requestPos = 0; for (i = myInternalLanes.begin(); i != myInternalLanes.end(); ++i) { // ... set information about participation static_cast<MSInternalLane*>(*i)->setParentJunctionInformation(&myInnerState, requestPos++); } #endif }
void MSRailSignal::init(NLDetectorBuilder&) { assert(myLanes.size() > 0); myConflictLanes.resize(myLinks.size()); myConflictLinks.resize(myLinks.size()); myRouteConflictLanes.resize(myLinks.size()); myRouteConflictLinks.resize(myLinks.size()); myLastRerouteAttempt.resize(myLinks.size(), std::make_pair(nullptr, -1)); if (OptionsCont::getOptions().isSet("railsignal-block-output")) { OutputDevice& od = OutputDevice::getDeviceByOption("railsignal-block-output"); od.openTag("railSignal"); od.writeAttr(SUMO_ATTR_ID, getID()); } for (LinkVector& links : myLinks) { //for every link index // collect lanes and links that are relevant for setting this signal // for each index we collect // - conflictLanes (signal must be red if any conflict lane is occupied) // - conflictLinks (signal must be red if any conflict link is approached by a vehicle // - that cannot break in time (arrivalSpeedBraking > 0) // - approached by a vehicle with higher switching priority (see #3941) // // forwardBlock // - search forward recursive from outgoing lane until controlled railSignal link found // -> add all found lanes // // bidiBlock (if any forwardBlock edge edge has bidi edge) // - search bidi backward recursive until first switch // - from switch search backward recursive all other incoming until controlled rail signal link // -> add final links // // backwardBlock // - search backward recursive from incoming lanes (not bidi for current outgoing lane) // until controlled railSignal link found // -> add all found lanes // -> add final links // // conditionalBlocks // - for each conflict link (always signalized) that enters from a // bidirectional track // - search bidi backward recursive until first switch that is // accessible from the bidi-direction // - from switch search bidi backward recursive until controlled rail signal link // -> add all found lanes // -> add final links std::vector<MSLink*> conflictLinks; LaneSet visited; std::vector<MSLane*> forwardBlock; std::vector<MSLane*> bidiBlock; std::vector<MSLane*> backwardBlock; // there should be only one link per index for railSignal if (links.size() > 1) { throw ProcessError("At railSignal '" + getID() + "' found " + toString(links.size()) + " links controlled by index " + toString(links[0]->getTLIndex())); } for (MSLink* link : links) { MSLane* toLane = link->getViaLaneOrLane(); //the lane this link is leading to MSLane* fromBidi = link->getLaneBefore()->getBidiLane(); if (fromBidi != nullptr) { // do not extend to forward block beyond the entering track (in case of a loop) visited.insert(fromBidi); } collectForwardBlock(toLane, 0., forwardBlock, visited); #ifdef DEBUG_FORWARD_BLOCK if (DEBUG_COND) { std::cout << "railSignal=" << getID() << " index=" << link->getTLIndex() << " forwardBlock=" << toString(forwardBlock) << "\n"; } #endif for (MSLane* forward : forwardBlock) { if (forward->getEdge().getBidiEdge() != nullptr) { MSLane* bidi = forward->getBidiLane(); for (MSLink* bidiOutLink : bidi->getLinkCont()) { if (bidiOutLink->getViaLane() != nullptr) { bidiBlock.push_back(bidiOutLink->getViaLane()); } } collectBidiBlock(bidi, 0., false, bidiBlock, visited); // assume bidirectional patches are continuous break; } } #ifdef DEBUG_BIDI_BLOCK if (DEBUG_COND) { std::cout << "railSignal=" << getID() << " index=" << link->getTLIndex() << " bidiBlock=" << toString(bidiBlock) << "\n"; } #endif // compute conflict links for (MSLane* cl : forwardBlock) { collectConflictLinks(cl, 0, backwardBlock, conflictLinks, visited, true); } for (MSLane* cl : bidiBlock) { collectConflictLinks(cl, 0, backwardBlock, conflictLinks, visited, false); } auto thisLinkIt = std::find(conflictLinks.begin(), conflictLinks.end(), link); if (thisLinkIt != conflictLinks.end()) { conflictLinks.erase(thisLinkIt); } else { WRITE_WARNING("At railSignal junction '" + getID() + "' link " + toString(link->getTLIndex()) + " with direction " + toString(link->getDirection()) + " should be uncontrolled"); } #ifdef DEBUG_BACKWARD_BLOCK if (DEBUG_COND) { std::cout << "railSignal=" << getID() << " index=" << link->getTLIndex() << " backwardBlock=" << toString(backwardBlock); std::cout << "railSignal=" << getID() << " index=" << link->getTLIndex() << " conflictLinks="; for (MSLink* cl : conflictLinks) { std::cout << toString(cl->getViaLaneOrLane()->getID()) << " "; } std::cout << "\n"; } #endif // compute conditional conflict lanes and links for (MSLink* cl : conflictLinks) { std::vector<MSLane*> routeConflictLanes; std::vector<MSLink*> routeConflictLinks; MSLane* in = const_cast<MSLane*>(cl->getLaneBefore()); LaneSet rCVisited = visited; // only collect if // 1) the in-edge is bidirectional // 2) the foe has no alternative track before reach meeting the end of the forwardBlock // 3) the forward block has no alternative track between the end of the forward block and the conflict link if (in->getEdge().getBidiEdge() != nullptr && !hasAlternativeTrack(cl) && !hasAlternativeTrackBetween(forwardBlock, cl)) { collectBidiBlock(in, 0., false, routeConflictLanes, rCVisited); std::vector<MSLane*> rCBackwardBlock; for (MSLane* rCLane : routeConflictLanes) { collectConflictLinks(rCLane, 0, rCBackwardBlock, routeConflictLinks, rCVisited); } } myRouteConflictLanes[link->getTLIndex()].push_back(routeConflictLanes); myRouteConflictLinks[link->getTLIndex()].push_back(routeConflictLinks); } if (OptionsCont::getOptions().isSet("railsignal-block-output")) { OutputDevice& od = OutputDevice::getDeviceByOption("railsignal-block-output"); od.openTag("link"); od.writeAttr(SUMO_ATTR_TLLINKINDEX, link->getTLIndex()); od.writeAttr(SUMO_ATTR_FROM, link->getLaneBefore()->getID()); od.writeAttr(SUMO_ATTR_TO, link->getViaLaneOrLane()->getID()); od.openTag("forwardBlock"); od.writeAttr(SUMO_ATTR_LANES, toString(forwardBlock)); od.closeTag(); od.openTag("bidiBlock"); od.writeAttr(SUMO_ATTR_LANES, toString(bidiBlock)); od.closeTag(); od.openTag("backwardBlock"); od.writeAttr(SUMO_ATTR_LANES, toString(backwardBlock)); od.closeTag(); od.openTag("conflictLinks"); std::vector<std::string> conflictLinkIDs; // railSignalID_tlIndex for (MSLink* cl : conflictLinks) { conflictLinkIDs.push_back(getTLLinkID(cl)); } od.writeAttr("logicIndex", toString(conflictLinkIDs)); for (int i = 0; i < (int)conflictLinks.size(); i++) { const std::vector<MSLane*>& rCLanes = myRouteConflictLanes[link->getTLIndex()][i]; const std::vector<MSLink*>& rCLinks = myRouteConflictLinks[link->getTLIndex()][i]; if (rCLanes.size() > 0 || rCLinks.size() > 0) { od.openTag("conflictLink"); od.writeAttr("logicIndex", getTLLinkID(conflictLinks[i])); if (rCLanes.size() > 0) { od.writeAttr("lanes", toString(rCLanes)); } if (rCLinks.size() > 0) { std::vector<std::string> rCLinkIDs; for (MSLink* rcl : rCLinks) { rCLinkIDs.push_back(getTLLinkID(rcl)); } od.writeAttr("links", toString(rCLinkIDs)); } od.closeTag(); } } od.closeTag(); // conflictLinks od.closeTag(); // link } std::vector<MSLane*> conflictLanes; conflictLanes.insert(conflictLanes.end(), forwardBlock.begin(), forwardBlock.end()); conflictLanes.insert(conflictLanes.end(), bidiBlock.begin(), bidiBlock.end()); conflictLanes.insert(conflictLanes.end(), backwardBlock.begin(), backwardBlock.end()); myConflictLanes[link->getTLIndex()] = conflictLanes; myConflictLinks[link->getTLIndex()] = conflictLinks; } } if (OptionsCont::getOptions().isSet("railsignal-block-output")) { OutputDevice& od = OutputDevice::getDeviceByOption("railsignal-block-output"); od.closeTag(); } updateCurrentPhase(); //check if this is necessary or if will be done already at another stage setTrafficLightSignals(MSNet::getInstance()->getCurrentTimeStep()); }
void MSRailSignal::collectBidiBlock(MSLane* toLane, double length, bool foundSwitch, std::vector<MSLane*>& bidiBlock, LaneSet& visited) { while (toLane != nullptr) { //std::cout << " toLane=" << toLane->getID() << " length=" << length << " foundSwitch=" << foundSwitch << "\n"; if (visited.count(toLane) != 0) { return; } visited.insert(toLane); bidiBlock.push_back(toLane); length += toLane->getLength(); if (length > MAX_BLOCK_LENGTH) { if (myNumWarnings < MAX_SIGNAL_WARNINGS) { WRITE_WARNING("Bidirectional block after rail signal junction '" + getID() + "' exceeds maximum length (stopped searching after lane '" + toLane->getID() + "' (length=" + toString(length) + "m)."); } myNumWarnings++; return; } const auto& incomingLaneInfos = toLane->getIncomingLanes(); MSLane* prev = toLane; toLane = nullptr; for (const auto& ili : incomingLaneInfos) { if (ili.viaLink->getDirection() == LINKDIR_TURN) { continue; } if (ili.viaLink->getTLLogic() != nullptr) { if (!foundSwitch && bidiBlock.size() > 1) { // check wether this node is switch (first edge doesn't count) for (MSLink* link : ili.lane->getLinkCont()) { if (link->getDirection() == LINKDIR_TURN) { continue; } if (link->getViaLaneOrLane() == prev) { continue; } //std::cout << " ili.lane=" << ili.lane->getID() // << " prev=" << prev->getID() // << " linkDir=" << ili.viaLink->getDirection() // << " linkIndex=" << ili.viaLink->getTLIndex() // << "\n"; foundSwitch = true; break; } } if (foundSwitch) { return; } } if (toLane == nullptr) { toLane = ili.lane; } else { foundSwitch = true; collectBidiBlock(ili.lane, length, true, bidiBlock, visited); } } if (toLane != nullptr && !foundSwitch && prev->getEdge().getBidiEdge() != nullptr) { // check switch in the other direction MSLane* prevBidi = prev->getBidiLane(); for (MSLink* link : prevBidi->getLinkCont()) { if (link->getDirection() == LINKDIR_TURN) { continue; } if (link->getViaLaneOrLane()->getEdge().getBidiEdge() != &toLane->getEdge()) { //std::cout << " toLane=" << toLane->getID() // << " prev=" << prev->getID() // << " prevBidi=" << prevBidi->getID() // << " linkLane=" << link->getViaLaneOrLane()->getEdge().getID() // << " linkLaneBidi=" << Named::getIDSecure(link->getViaLaneOrLane()->getEdge().getBidiEdge()) // << "\n"; foundSwitch = true; break; } } } } }
void MSRightOfWayJunction::postloadInit() { // inform links where they have to report approaching vehicles to int requestPos = 0; std::vector<MSLane*>::iterator i; // going through the incoming lanes... int maxNo = 0; std::vector<std::pair<MSLane*, MSLink*> > sortedLinks; for (i = myIncomingLanes.begin(); i != myIncomingLanes.end(); ++i) { const MSLinkCont& links = (*i)->getLinkCont(); // ... set information for every link for (MSLinkCont::const_iterator j = links.begin(); j != links.end(); j++) { if ((*j)->getLane()->getEdge().isWalkingArea() || ((*i)->getEdge().isWalkingArea() && !(*j)->getLane()->getEdge().isCrossing())) { continue; } sortedLinks.push_back(std::make_pair(*i, *j)); ++maxNo; } } const bool hasFoes = myLogic->hasFoes(); for (i = myIncomingLanes.begin(); i != myIncomingLanes.end(); ++i) { const MSLinkCont& links = (*i)->getLinkCont(); // ... set information for every link const MSLane* walkingAreaFoe = nullptr; for (MSLinkCont::const_iterator j = links.begin(); j != links.end(); j++) { if ((*j)->getLane()->getEdge().isWalkingArea()) { if ((*i)->getPermissions() != SVC_PEDESTRIAN) { // vehicular lane connects to a walkingarea walkingAreaFoe = (*j)->getLane(); } continue; } else if (((*i)->getEdge().isWalkingArea() && !(*j)->getLane()->getEdge().isCrossing())) { continue; } if (myLogic->getLogicSize() <= requestPos) { throw ProcessError("Found invalid logic position of a link for junction '" + getID() + "' (" + toString(requestPos) + ", max " + toString(myLogic->getLogicSize()) + ") -> (network error)"); } const MSLogicJunction::LinkBits& linkResponse = myLogic->getResponseFor(requestPos); // SUMO_ATTR_RESPONSE const MSLogicJunction::LinkBits& linkFoes = myLogic->getFoesFor(requestPos); // SUMO_ATTR_FOES bool cont = myLogic->getIsCont(requestPos); myLinkFoeLinks[*j] = std::vector<MSLink*>(); for (int c = 0; c < maxNo; ++c) { if (linkResponse.test(c)) { MSLink* foe = sortedLinks[c].second; myLinkFoeLinks[*j].push_back(foe); if (MSGlobals::gUsingInternalLanes && foe->getViaLane() != nullptr) { assert(foe->getViaLane()->getLinkCont().size() == 1); MSLink* foeExitLink = foe->getViaLane()->getLinkCont()[0]; // add foe links after an internal junction if (foeExitLink->getViaLane() != nullptr) { myLinkFoeLinks[*j].push_back(foeExitLink); } } } } std::vector<MSLink*> foes; for (int c = 0; c < maxNo; ++c) { if (linkFoes.test(c)) { MSLink* foe = sortedLinks[c].second; foes.push_back(foe); MSLane* l = foe->getViaLane(); if (l == nullptr) { continue; } // add foe links after an internal junction const MSLinkCont& lc = l->getLinkCont(); for (MSLinkCont::const_iterator q = lc.begin(); q != lc.end(); ++q) { if ((*q)->getViaLane() != nullptr) { foes.push_back(*q); } } } } myLinkFoeInternalLanes[*j] = std::vector<MSLane*>(); if (MSGlobals::gUsingInternalLanes && myInternalLanes.size() > 0) { int li = 0; for (int c = 0; c < (int)sortedLinks.size(); ++c) { if (sortedLinks[c].second->getLane() == nullptr) { // dead end continue; } if (linkFoes.test(c)) { myLinkFoeInternalLanes[*j].push_back(myInternalLanes[li]); if (linkResponse.test(c)) { const std::vector<MSLane::IncomingLaneInfo>& l = myInternalLanes[li]->getIncomingLanes(); if (l.size() == 1 && l[0].lane->getEdge().isInternal()) { myLinkFoeInternalLanes[*j].push_back(l[0].lane); } } } ++li; } } (*j)->setRequestInformation((int)requestPos, hasFoes, cont, myLinkFoeLinks[*j], myLinkFoeInternalLanes[*j]); // the exit link for a link before an internal junction is handled in MSInternalJunction // so we need to skip if cont=true if (MSGlobals::gUsingInternalLanes && (*j)->getViaLane() != nullptr && !cont) { assert((*j)->getViaLane()->getLinkCont().size() == 1); MSLink* exitLink = (*j)->getViaLane()->getLinkCont()[0]; exitLink->setRequestInformation((int)requestPos, false, false, std::vector<MSLink*>(), myLinkFoeInternalLanes[*j], (*j)->getViaLane()); for (const auto& ili : exitLink->getLane()->getIncomingLanes()) { if (ili.lane->getEdge().isWalkingArea()) { exitLink->addWalkingAreaFoeExit(ili.lane); break; } } } // the exit link for a crossing is needed for the pedestrian model if (MSGlobals::gUsingInternalLanes && (*j)->getLane()->getEdge().isCrossing()) { MSLink* exitLink = (*j)->getLane()->getLinkCont()[0]; exitLink->setRequestInformation((int)requestPos, false, false, std::vector<MSLink*>(), myLinkFoeInternalLanes[*j], (*j)->getLane()); } for (std::vector<MSLink*>::const_iterator k = foes.begin(); k != foes.end(); ++k) { (*j)->addBlockedLink(*k); (*k)->addBlockedLink(*j); } requestPos++; } if (walkingAreaFoe != nullptr && links.size() > 1) { for (MSLinkCont::const_iterator j = links.begin(); j != links.end(); j++) { if (!(*j)->getLane()->getEdge().isWalkingArea()) { MSLink* exitLink = (*j)->getViaLane()->getLinkCont()[0]; exitLink->addWalkingAreaFoe(walkingAreaFoe); } } } } }
void MSInternalJunction::postloadInit() { if (myIncomingLanes.size() == 0) { throw ProcessError("Internal junction " + getID() + " has no incoming lanes"); } // the first lane in the list of incoming lanes is special. It defines the // link that needs to do all the checking for this internal junction const MSLane* specialLane = myIncomingLanes[0]; assert(specialLane->getLinkCont().size() == 1); MSLink* thisLink = specialLane->getLinkCont()[0]; const MSRightOfWayJunction* parent = dynamic_cast<const MSRightOfWayJunction*>(specialLane->getEdge().getToJunction()); if (parent == nullptr) { // parent has type traffic_light_unregulated return; } const int ownLinkIndex = specialLane->getIncomingLanes()[0].viaLink->getIndex(); const MSLogicJunction::LinkBits& response = parent->getLogic()->getResponseFor(ownLinkIndex); // inform links where they have to report approaching vehicles to //std::cout << " special=" << specialLane->getID() << " incoming=" << toString(myIncomingLanes) << " internal=" << toString(myInternalLanes) << "\n"; for (std::vector<MSLane*>::iterator i = myInternalLanes.begin(); i != myInternalLanes.end(); ++i) { const MSLinkCont& lc = (*i)->getLinkCont(); for (MSLinkCont::const_iterator q = lc.begin(); q != lc.end(); ++q) { if ((*q)->getViaLane() != nullptr) { const int foeIndex = (*i)->getIncomingLanes()[0].viaLink->getIndex(); //std::cout << " response=" << response << " index=" << ownLinkIndex << " foeIndex=" << foeIndex << " ibct=" << indirectBicycleTurn(specialLane, thisLink, *i, *q) << "\n"; if (response.test(foeIndex) || indirectBicycleTurn(specialLane, thisLink, *i, *q)) { // only respect vehicles before internal junctions if they // have priority (see the analogous foeLinks.test() when // initializing myLinkFoeInternalLanes in MSRightOfWayJunction // Indirect left turns for bicycles are a special case // because they both intersect on their second part with the first part of the other one // and only one of the has priority myInternalLaneFoes.push_back(*i); } myInternalLaneFoes.push_back((*q)->getViaLane()); } else { myInternalLaneFoes.push_back(*i); } //std::cout << " i=" << (*i)->getID() << " qLane=" << (*q)->getLane()->getID() << " qVia=" << Named::getIDSecure((*q)->getViaLane()) << " foes=" << toString(myInternalLaneFoes) << "\n"; } } for (std::vector<MSLane*>::const_iterator i = myIncomingLanes.begin() + 1; i != myIncomingLanes.end(); ++i) { MSLane* l = *i; const MSLinkCont& lc = l->getLinkCont(); for (MSLinkCont::const_iterator j = lc.begin(); j != lc.end(); ++j) { MSLane* via = (*j)->getViaLane(); if (std::find(myInternalLanes.begin(), myInternalLanes.end(), via) == myInternalLanes.end()) { continue; } myInternalLinkFoes.push_back(*j); } } // thisLinks is itself an exitLink of the preceding internal lane thisLink->setRequestInformation(ownLinkIndex, true, false, myInternalLinkFoes, myInternalLaneFoes, thisLink->getViaLane()->getLogicalPredecessorLane()); assert(thisLink->getViaLane()->getLinkCont().size() == 1); MSLink* exitLink = thisLink->getViaLane()->getLinkCont()[0]; exitLink->setRequestInformation(ownLinkIndex, false, false, std::vector<MSLink*>(), myInternalLaneFoes, thisLink->getViaLane()); for (const auto& ili : exitLink->getLane()->getIncomingLanes()) { if (ili.lane->getEdge().isWalkingArea()) { exitLink->addWalkingAreaFoeExit(ili.lane); break; } } for (std::vector<MSLink*>::const_iterator k = myInternalLinkFoes.begin(); k != myInternalLinkFoes.end(); ++k) { thisLink->addBlockedLink(*k); (*k)->addBlockedLink(thisLink); } }
// =========================================================================== // method definitions // =========================================================================== bool TraCIServerAPI_Lane::processGet(TraCIServer &server, tcpip::Storage &inputStorage, tcpip::Storage &outputStorage) { Storage tmpResult; std::string warning = ""; // additional description for response // variable int variable = inputStorage.readUnsignedByte(); std::string id = inputStorage.readString(); // check variable if (variable!=ID_LIST&&variable!=LANE_LINK_NUMBER&&variable!=LANE_EDGE_ID&&variable!=VAR_LENGTH &&variable!=VAR_MAXSPEED&&variable!=LANE_LINKS&&variable!=VAR_SHAPE &&variable!=VAR_CO2EMISSION&&variable!=VAR_COEMISSION&&variable!=VAR_HCEMISSION&&variable!=VAR_PMXEMISSION &&variable!=VAR_NOXEMISSION&&variable!=VAR_FUELCONSUMPTION&&variable!=VAR_NOISEEMISSION &&variable!=LAST_STEP_MEAN_SPEED&&variable!=LAST_STEP_VEHICLE_NUMBER &&variable!=LAST_STEP_VEHICLE_ID_LIST&&variable!=LAST_STEP_OCCUPANCY&&variable!=LAST_STEP_VEHICLE_HALTING_NUMBER &&variable!=LAST_STEP_LENGTH&&variable!=VAR_CURRENT_TRAVELTIME &&variable!=LANE_ALLOWED&&variable!=LANE_DISALLOWED) { server.writeStatusCmd(CMD_GET_LANE_VARIABLE, RTYPE_ERR, "Get Lane Variable: unsupported variable specified", outputStorage); return false; } // begin response building Storage tempMsg; // response-code, variableID, objectID tempMsg.writeUnsignedByte(RESPONSE_GET_LANE_VARIABLE); tempMsg.writeUnsignedByte(variable); tempMsg.writeString(id); if (variable==ID_LIST) { std::vector<std::string> ids; MSLane::insertIDs(ids); tempMsg.writeUnsignedByte(TYPE_STRINGLIST); tempMsg.writeStringList(ids); } else { MSLane *lane = MSLane::dictionary(id); if (lane==0) { server.writeStatusCmd(CMD_GET_LANE_VARIABLE, RTYPE_ERR, "Lane '" + id + "' is not known", outputStorage); return false; } switch (variable) { case LANE_LINK_NUMBER: tempMsg.writeUnsignedByte(TYPE_UBYTE); tempMsg.writeUnsignedByte((int) lane->getLinkCont().size()); break; case LANE_EDGE_ID: tempMsg.writeUnsignedByte(TYPE_STRING); tempMsg.writeString(lane->getEdge().getID()); break; case VAR_LENGTH: tempMsg.writeUnsignedByte(TYPE_FLOAT); tempMsg.writeFloat(lane->getLength()); break; case VAR_MAXSPEED: tempMsg.writeUnsignedByte(TYPE_FLOAT); tempMsg.writeFloat(lane->getMaxSpeed()); break; case LANE_LINKS: { tempMsg.writeUnsignedByte(TYPE_COMPOUND); Storage tempContent; unsigned int cnt = 0; tempContent.writeUnsignedByte(TYPE_INTEGER); const MSLinkCont &links = lane->getLinkCont(); tempContent.writeInt((int) links.size()); ++cnt; for (MSLinkCont::const_iterator i=links.begin(); i!=links.end(); ++i) { MSLink *link = (*i); // approached non-internal lane (if any) tempContent.writeUnsignedByte(TYPE_STRING); tempContent.writeString(link->getLane()!=0 ? link->getLane()->getID() : ""); ++cnt; // approached "via", internal lane (if any) tempContent.writeUnsignedByte(TYPE_STRING); #ifdef HAVE_INTERNAL_LANES tempContent.writeString(link->getViaLane()!=0 ? link->getViaLane()->getID() : ""); #else tempContent.writeString(""); #endif ++cnt; // priority tempContent.writeUnsignedByte(TYPE_UBYTE); tempContent.writeUnsignedByte(link->havePriority() ? 1 : 0); ++cnt; // opened tempContent.writeUnsignedByte(TYPE_UBYTE); tempContent.writeUnsignedByte(link->opened(MSNet::getInstance()->getCurrentTimeStep(), MSNet::getInstance()->getCurrentTimeStep(), 0.) ? 1 : 0); ++cnt; // approaching foe tempContent.writeUnsignedByte(TYPE_UBYTE); tempContent.writeUnsignedByte(link->hasApproachingFoe(MSNet::getInstance()->getCurrentTimeStep(), MSNet::getInstance()->getCurrentTimeStep()) ? 1 : 0); ++cnt; // state (not implemented, yet) tempContent.writeUnsignedByte(TYPE_STRING); tempContent.writeString(""); ++cnt; // direction (not implemented, yet) tempContent.writeUnsignedByte(TYPE_STRING); tempContent.writeString(""); ++cnt; // length tempContent.writeUnsignedByte(TYPE_FLOAT); tempContent.writeFloat(link->getLength()); ++cnt; } tempMsg.writeInt((int) cnt); tempMsg.writeStorage(tempContent); } break; case LANE_ALLOWED: { const std::vector<SUMOVehicleClass> &allowed = lane->getAllowedClasses(); std::vector<std::string> allowedS; for (std::vector<SUMOVehicleClass>::const_iterator i=allowed.begin(); i!=allowed.end(); ++i) { allowedS.push_back(getVehicleClassName(*i)); } tempMsg.writeUnsignedByte(TYPE_STRINGLIST); tempMsg.writeStringList(allowedS); } case LANE_DISALLOWED: { const std::vector<SUMOVehicleClass> &disallowed = lane->getNotAllowedClasses(); std::vector<std::string> disallowedS; for (std::vector<SUMOVehicleClass>::const_iterator i=disallowed.begin(); i!=disallowed.end(); ++i) { disallowedS.push_back(getVehicleClassName(*i)); } tempMsg.writeUnsignedByte(TYPE_STRINGLIST); tempMsg.writeStringList(disallowedS); } break; case VAR_SHAPE: tempMsg.writeUnsignedByte(TYPE_POLYGON); tempMsg.writeUnsignedByte(MIN2(static_cast<size_t>(255),lane->getShape().size())); for (int iPoint=0; iPoint < MIN2(static_cast<size_t>(255),lane->getShape().size()); ++iPoint) { tempMsg.writeFloat(lane->getShape()[iPoint].x()); tempMsg.writeFloat(lane->getShape()[iPoint].y()); } break; case VAR_CO2EMISSION: tempMsg.writeUnsignedByte(TYPE_FLOAT); tempMsg.writeFloat(lane->getHBEFA_CO2Emissions()); break; case VAR_COEMISSION: tempMsg.writeUnsignedByte(TYPE_FLOAT); tempMsg.writeFloat(lane->getHBEFA_COEmissions()); break; case VAR_HCEMISSION: tempMsg.writeUnsignedByte(TYPE_FLOAT); tempMsg.writeFloat(lane->getHBEFA_HCEmissions()); break; case VAR_PMXEMISSION: tempMsg.writeUnsignedByte(TYPE_FLOAT); tempMsg.writeFloat(lane->getHBEFA_PMxEmissions()); break; case VAR_NOXEMISSION: tempMsg.writeUnsignedByte(TYPE_FLOAT); tempMsg.writeFloat(lane->getHBEFA_NOxEmissions()); break; case VAR_FUELCONSUMPTION: tempMsg.writeUnsignedByte(TYPE_FLOAT); tempMsg.writeFloat(lane->getHBEFA_FuelConsumption()); break; case VAR_NOISEEMISSION: tempMsg.writeUnsignedByte(TYPE_FLOAT); tempMsg.writeFloat(lane->getHarmonoise_NoiseEmissions()); break; case LAST_STEP_VEHICLE_NUMBER: tempMsg.writeUnsignedByte(TYPE_INTEGER); tempMsg.writeInt((int) lane->getVehicleNumber()); break; case LAST_STEP_MEAN_SPEED: tempMsg.writeUnsignedByte(TYPE_FLOAT); tempMsg.writeFloat(lane->getMeanSpeed()); break; case LAST_STEP_VEHICLE_ID_LIST: { std::vector<std::string> vehIDs; const std::deque<MSVehicle*> &vehs = lane->getVehiclesSecure(); for (std::deque<MSVehicle*>::const_iterator j=vehs.begin(); j!=vehs.end(); ++j) { vehIDs.push_back((*j)->getID()); } lane->releaseVehicles(); tempMsg.writeUnsignedByte(TYPE_STRINGLIST); tempMsg.writeStringList(vehIDs); } break; case LAST_STEP_OCCUPANCY: tempMsg.writeUnsignedByte(TYPE_FLOAT); tempMsg.writeFloat(lane->getOccupancy()); break; case LAST_STEP_VEHICLE_HALTING_NUMBER: { int halting = 0; const std::deque<MSVehicle*> &vehs = lane->getVehiclesSecure(); for (std::deque<MSVehicle*>::const_iterator j=vehs.begin(); j!=vehs.end(); ++j) { if ((*j)->getSpeed()<0.1) { ++halting; } } lane->releaseVehicles(); tempMsg.writeUnsignedByte(TYPE_INTEGER); tempMsg.writeInt(halting); } break; case LAST_STEP_LENGTH: { SUMOReal lengthSum = 0; const std::deque<MSVehicle*> &vehs = lane->getVehiclesSecure(); for (std::deque<MSVehicle*>::const_iterator j=vehs.begin(); j!=vehs.end(); ++j) { lengthSum += (*j)->getVehicleType().getLength(); } tempMsg.writeUnsignedByte(TYPE_FLOAT); if (vehs.size()==0) { tempMsg.writeFloat(0); } else { tempMsg.writeFloat(lengthSum / (SUMOReal) vehs.size()); } lane->releaseVehicles(); } break; case VAR_CURRENT_TRAVELTIME: { SUMOReal meanSpeed = lane->getMeanSpeed(); tempMsg.writeUnsignedByte(TYPE_FLOAT); if (meanSpeed!=0) { tempMsg.writeFloat(lane->getLength() / meanSpeed); } else { tempMsg.writeFloat(1000000.); } } break; default: break; } } server.writeStatusCmd(CMD_GET_LANE_VARIABLE, RTYPE_OK, warning, outputStorage); // send response outputStorage.writeUnsignedByte(0); // command length -> extended outputStorage.writeInt(1 + 4 + tempMsg.size()); outputStorage.writeStorage(tempMsg); return true; }