std::pair<MSVehicle* const, SUMOReal> MSLaneChanger::getRealLeader(const ChangerIt& target) const { // get the leading vehicle on the lane to change to MSVehicle* neighLead = target->lead; // check whether the hopped vehicle got the leader if (target->hoppedVeh != 0) { SUMOReal hoppedPos = target->hoppedVeh->getPositionOnLane(); if (hoppedPos > veh(myCandi)->getPositionOnLane() && (neighLead == 0 || neighLead->getPositionOnLane() > hoppedPos)) { neighLead = target->hoppedVeh; } } if (neighLead == 0) { MSLane* targetLane = target->lane; MSVehicle* predP = targetLane->getPartialOccupator(); if (predP != 0) { return std::pair<MSVehicle*, SUMOReal>(predP, targetLane->getPartialOccupatorEnd() - veh(myCandi)->getPositionOnLane() - veh(myCandi)->getVehicleType().getMinGap()); } const std::vector<MSLane*>& bestLaneConts = veh(myCandi)->getBestLanesContinuation(myCandi->lane); SUMOReal seen = myCandi->lane->getLength() - veh(myCandi)->getPositionOnLane(); SUMOReal speed = veh(myCandi)->getSpeed(); SUMOReal dist = veh(myCandi)->getCarFollowModel().brakeGap(speed) + veh(myCandi)->getVehicleType().getMinGap(); if (seen > dist) { return std::pair<MSVehicle* const, SUMOReal>(static_cast<MSVehicle*>(0), -1); } return target->lane->getLeaderOnConsecutive(dist, seen, speed, *veh(myCandi), bestLaneConts); } else { MSVehicle* candi = veh(myCandi); return std::pair<MSVehicle* const, SUMOReal>(neighLead, neighLead->getPositionOnLane() - neighLead->getVehicleType().getLength() - candi->getPositionOnLane() - candi->getVehicleType().getMinGap()); } }
std::pair<MSVehicle* const, SUMOReal> MSLaneChanger::getRealFollower(const ChangerIt& target) const { MSVehicle* neighFollow = veh(target); // check whether the hopped vehicle got the follower if (target->hoppedVeh != 0) { SUMOReal hoppedPos = target->hoppedVeh->getPositionOnLane(); if (hoppedPos <= veh(myCandi)->getPositionOnLane() && (neighFollow == 0 || neighFollow->getPositionOnLane() > hoppedPos)) { neighFollow = target->hoppedVeh; } } if (neighFollow == 0) { SUMOReal speed = target->lane->getSpeedLimit(); // in order to look back, we'd need the minimum braking ability of vehicles in the net... // we'll assume it to be 4m/s^2 // !!!revisit SUMOReal dist = speed * speed / (2.*4.) + SPEED2DIST(speed); dist = MIN2(dist, (SUMOReal) 500.); MSVehicle* candi = veh(myCandi); SUMOReal seen = candi->getPositionOnLane() - candi->getVehicleType().getLength(); return target->lane->getFollowerOnConsecutive(dist, seen, candi->getSpeed(), candi->getPositionOnLane() - candi->getVehicleType().getLength(), 4.5);//!!! recheck } else { MSVehicle* candi = veh(myCandi); return std::pair<MSVehicle* const, SUMOReal>(neighFollow, candi->getPositionOnLane() - candi->getVehicleType().getLength() - neighFollow->getPositionOnLane() - neighFollow->getVehicleType().getMinGap()); } }
std::pair<MSVehicle*, SUMOReal> MSLink::getLeaderInfo(const std::map<const MSLink*, std::string>& previousLeaders, SUMOReal dist) const { if (MSGlobals::gUsingInternalLanes && myJunctionInlane == 0) { // this is an exit link // there might have been a link leader from previous steps who still qualifies // but is not the last vehicle on the foe lane anymore std::map<const MSLink*, std::string>::const_iterator it = previousLeaders.find(this); if (it != previousLeaders.end()) { MSVehicle* leader = dynamic_cast<MSVehicle*>(MSNet::getInstance()->getVehicleControl().getVehicle(it->second)); if (leader != 0 && std::find(myFoeLanes.begin(), myFoeLanes.end(), leader->getLane()) != myFoeLanes.end()) { return std::make_pair(leader, dist - (leader->getLane()->getLength() - leader->getPositionOnLane()) - leader->getVehicleType().getLength()); } } // now check for last vehicle on foe lane for (std::vector<MSLane*>::const_iterator i = myFoeLanes.begin(); i != myFoeLanes.end(); ++i) { assert((*i)->getLinkCont().size() == 1); MSLink* exitLink = (*i)->getLinkCont()[0]; if (myLane == exitLink->getLane()) { MSVehicle* leader = (*i)->getLastVehicle(); if (leader != 0) { return std::make_pair(leader, dist - ((*i)->getLength() - leader->getPositionOnLane()) - leader->getVehicleType().getLength()); } } } } return std::make_pair<MSVehicle*, SUMOReal>(0, 0); }
MSVehicle * const MSLane::getLastVehicle(const MSVehicle::StripCont &strips) const { MSVehicle::StripContConstIter strip = strips.begin(); MSVehicle *last = 0; while (strip != strips.end()) { last = (*strip)->getLastVehicle(); if (last != 0) break; strip++; } if (last == 0) return last; for (MSVehicle::StripContConstIter it=strip+1; it != strips.end(); ++it) { MSVehicle *curr = (*it)->getLastVehicle(); if (!curr) continue; if (last->getPositionOnLane()-last->getVehicleType().getLength() > curr->getPositionOnLane()-curr->getVehicleType().getLength()) last = curr; } //DEBUG ///* std::pair<MSVehicle*, SUMOReal> lvInfo = getLastVehicleInformation(); if (last != lvInfo.first) MsgHandler::getWarningInstance()->inform("LastVEH_ERR::Lane=" + this->getID() + ", time=" + time2string(MSNet::getInstance()->getCurrentTimeStep()) + "."); //*/ return last; }
void MSInductLoop::notifyLeave(MSVehicle& veh, bool isArrival, bool isLaneChange) throw() { if (veh.getPositionOnLane() > myPosition && veh.getPositionOnLane() - veh.getVehicleType().getLength() <= myPosition) { // vehicle is on detector during lane change leaveDetectorByLaneChange(veh); } }
std::pair<MSVehicle* const, SUMOReal> MSLaneChanger::getRealThisLeader(const ChangerIt& target) const { // get the leading vehicle on the lane to change to MSVehicle* leader = target->lead; if (leader == 0) { MSLane* targetLane = target->lane; MSVehicle* predP = targetLane->getPartialOccupator(); if (predP != 0) { return std::pair<MSVehicle*, SUMOReal>(predP, targetLane->getPartialOccupatorEnd() - veh(myCandi)->getPositionOnLane()); } const std::vector<MSLane*>& bestLaneConts = veh(myCandi)->getBestLanesContinuation(); MSLinkCont::const_iterator link = targetLane->succLinkSec(*veh(myCandi), 1, *targetLane, bestLaneConts); if (targetLane->isLinkEnd(link)) { return std::pair<MSVehicle*, SUMOReal>(static_cast<MSVehicle*>(0), -1); } MSLane* nextLane = (*link)->getLane(); if (nextLane == 0) { return std::pair<MSVehicle*, SUMOReal>(static_cast<MSVehicle*>(0), -1); } leader = nextLane->getLastVehicle(); if (leader == 0) { return std::pair<MSVehicle*, SUMOReal>(static_cast<MSVehicle*>(0), -1); } SUMOReal gap = leader->getPositionOnLane() - leader->getVehicleType().getLength() + (myCandi->lane->getLength() - veh(myCandi)->getPositionOnLane() - veh(myCandi)->getVehicleType().getMinGap()); // !!! recheck return std::pair<MSVehicle* const, SUMOReal>(leader, MAX2((SUMOReal) 0, gap)); } else { MSVehicle* candi = veh(myCandi); SUMOReal gap = leader->getPositionOnLane() - leader->getVehicleType().getLength() - candi->getPositionOnLane() - candi->getVehicleType().getMinGap(); return std::pair<MSVehicle* const, SUMOReal>(leader, MAX2((SUMOReal) 0, gap)); } }
std::pair<MSVehicle * const, SUMOReal> MSLane::getFollowerOnConsecutive(SUMOReal dist, SUMOReal seen, SUMOReal leaderSpeed, SUMOReal backOffset) const { // ok, a vehicle has not noticed the lane about itself; // iterate as long as necessary to search for an approaching one std::set<MSLane*> visited; std::vector<std::pair<MSVehicle *, SUMOReal> > possible; std::vector<MSLane::IncomingLaneInfo> newFound; std::vector<MSLane::IncomingLaneInfo> toExamine = myIncomingLanes; while (toExamine.size()!=0) { for (std::vector<MSLane::IncomingLaneInfo>::iterator i=toExamine.begin(); i!=toExamine.end(); ++i) { /* if ((*i).viaLink->getState()==MSLink::LINKSTATE_TL_RED) { continue; } */ MSLane *next = (*i).lane; if (next->getFirstVehicle()!=0) { MSVehicle * v = (MSVehicle*) next->getFirstVehicle(); SUMOReal agap = (*i).length - v->getPositionOnLane() + backOffset; if (!v->getCarFollowModel().hasSafeGap(v->getCarFollowModel().maxNextSpeed(v->getSpeed()), agap, leaderSpeed, v->getLane().getMaxSpeed())) { possible.push_back(std::make_pair(v, (*i).length-v->getPositionOnLane()+seen)); } } else { if ((*i).length+seen<dist) { const std::vector<MSLane::IncomingLaneInfo> &followers = next->getIncomingLanes(); for (std::vector<MSLane::IncomingLaneInfo>::const_iterator j=followers.begin(); j!=followers.end(); ++j) { if (visited.find((*j).lane)==visited.end()) { visited.insert((*j).lane); MSLane::IncomingLaneInfo ili; ili.lane = (*j).lane; ili.length = (*j).length + (*i).length; ili.viaLink = (*j).viaLink; newFound.push_back(ili); } } } } } toExamine.clear(); swap(newFound, toExamine); } if (possible.size()==0) { return std::pair<MSVehicle * const, SUMOReal>(0, -1); } sort(possible.begin(), possible.end(), by_second_sorter()); return *(possible.begin()); }
std::pair<MSVehicle * const, SUMOReal> MSLane::getLeaderOnConsecutive(SUMOReal dist, SUMOReal seen, SUMOReal speed, const MSVehicle &veh, const std::vector<MSLane*> &bestLaneConts) const { if (seen>dist) { return std::pair<MSVehicle * const, SUMOReal>(0, -1); } unsigned int view = 1; // loop over following lanes const MSLane * targetLane = this; MSVehicle *leader = targetLane->getPartialOccupator(); if (leader!=0) { return std::pair<MSVehicle * const, SUMOReal>(leader, seen-targetLane->getPartialOccupatorEnd()); } const MSLane * nextLane = targetLane; while (true) { // get the next link used MSLinkCont::const_iterator link = targetLane->succLinkSec(veh, view, *nextLane, bestLaneConts); if (nextLane->isLinkEnd(link) || !(*link)->havePriority() || (*link)->getState()==MSLink::LINKSTATE_TL_RED) { return std::pair<MSVehicle * const, SUMOReal>(0, -1); } #ifdef HAVE_INTERNAL_LANES bool nextInternal = false; nextLane = (*link)->getViaLane(); if (nextLane==0) { nextLane = (*link)->getLane(); } else { nextInternal = true; } #else nextLane = (*link)->getLane(); #endif if (nextLane==0) { return std::pair<MSVehicle * const, SUMOReal>(0, -1); } MSVehicle * leader = nextLane->getLastVehicle(veh.getStrips()); if (leader!=0) { return std::pair<MSVehicle * const, SUMOReal>(leader, seen+leader->getPositionOnLane()-leader->getVehicleType().getLength()); } else { leader = nextLane->getPartialOccupator(); if (leader!=0) { return std::pair<MSVehicle * const, SUMOReal>(leader, seen+nextLane->getPartialOccupatorEnd()); } } if (nextLane->getMaxSpeed()<speed) { dist = veh.getCarFollowModel().brakeGap(nextLane->getMaxSpeed()); } seen += nextLane->getLength(); if (seen>dist) { return std::pair<MSVehicle * const, SUMOReal>(0, -1); } #ifdef HAVE_INTERNAL_LANES if (!nextInternal) { view++; } #else view++; #endif } }
std::pair<MSVehicle* const, SUMOReal> MSLaneChanger::getRealFollower(const ChangerIt& target) const { MSVehicle* candi = veh(myCandi); const SUMOReal candiPos = candi->getPositionOnLane(); MSVehicle* neighFollow = veh(target); // check whether the hopped vehicle became the follower neighFollow = getCloserFollower(candiPos, neighFollow, target->hoppedVeh); neighFollow = getCloserFollower(candiPos, neighFollow, target->lane->getPartialBehind(candi)); if (neighFollow == 0) { return target->lane->getFollowerOnConsecutive( candi->getPositionOnLane() - candi->getVehicleType().getLength(), candi->getSpeed(), candi->getCarFollowModel().getMaxDecel()); } else { MSVehicle* candi = veh(myCandi); return std::pair<MSVehicle* const, SUMOReal>(neighFollow, candi->getPositionOnLane() - candi->getVehicleType().getLength() - neighFollow->getPositionOnLane() - neighFollow->getVehicleType().getMinGap()); } }
bool MSMsgInductLoop::notifyEnter(MSVehicle& veh, bool, bool) throw() { if (veh.getPositionOnLane() - veh.getVehicleType().getLength() > myPosition) { // vehicle-front is beyond detector. Ignore return false; } // vehicle is in front of detector return true; }
void MSVehicleTransfer::loadState(const SUMOSAXAttributes& attrs, const SUMOTime offset, MSVehicleControl& vc) { MSVehicle* veh = dynamic_cast<MSVehicle*>(vc.getVehicle(attrs.getString(SUMO_ATTR_ID))); assert(veh != 0); SUMOTime proceedTime = (SUMOTime)attrs.getLong(SUMO_ATTR_DEPART); MSLane* parkingLane = attrs.hasAttribute(SUMO_ATTR_PARKING) ? MSLane::dictionary(attrs.getString(SUMO_ATTR_PARKING)): 0; myVehicles.push_back(VehicleInformation(veh, proceedTime + offset, parkingLane != 0)); if (parkingLane != 0) { myParkingVehicles[parkingLane].insert(veh); veh->setTentativeLaneAndPosition(parkingLane, veh->getPositionOnLane()); veh->processNextStop(veh->getSpeed()); } MSNet::getInstance()->getInsertionControl().alreadyDeparted(veh); }
const MSVehicle * const MSLane::getFirstVehicle() const { //XXX: partial occupators don't count? StripCont::const_iterator it = myStrips.begin(); const MSVehicle *first = (*it)->getFirstVehicle(); for (; it != myStrips.end(); ++it) { MSVehicle *curr = (*it)->getLastVehicle(); if (curr == 0) continue; else if (first == 0 && curr != 0) first = curr; if (first->getPositionOnLane() < curr->getPositionOnLane()) first = curr; } return first; }
bool MSLink::maybeOccupied(MSLane* lane) { MSVehicle* veh = lane->getLastVehicle(); SUMOReal distLeft = 0; if (veh == 0) { veh = lane->getPartialOccupator(); distLeft = lane->getLength() - lane->getPartialOccupatorEnd(); } else { distLeft = lane->getLength() - veh->getPositionOnLane() + veh->getVehicleType().getLength(); } if (veh == 0) { return false; } else { assert(distLeft > 0); // can we be sure that the vehicle leaves this lane in the next step? bool result = distLeft > (veh->getSpeed() - veh->getCarFollowModel().getMaxDecel()); return result; } }
size_t MSLane::getEmptyStartStripID(size_t vehWidth) const { StripCont::const_iterator strip = myStrips.begin(); std::vector<SUMOReal> vehPositions(myStrips.size(), getLength()); std::vector<SUMOReal>::iterator it, start, end; size_t startPos = 0; it = vehPositions.begin(); // vehPositions contains position of end of last vehicle of every strip // or length of lane if there is no last vehicle int i=0; for (i=0; strip != myStrips.end(); ++strip, ++i) { MSVehicle *veh = (*strip)->getLastVehicle(); if (veh != 0) vehPositions[i] = veh->getPositionOnLane() - veh->getVehicleType().getLength(); } assert(i==myStrips.size()); // for each possible position of vehicle, find the vehicle closest to current one // (in all strips current vehicle occupies) std::map<size_t, SUMOReal> possiblePosn; std::map<size_t, SUMOReal>::iterator pos; for (size_t myStart = 0; myStart <= myStrips.size() - vehWidth; ++myStart) { // find min dist among all strips that vehicle may occupy start = vehPositions.begin() + myStart; end = start + vehWidth; it = std::min_element(start, end); possiblePosn[myStart] = *it; } // now find the maximum among the possible start positions pos = possiblePosn.begin(); SUMOReal currMaxPos = pos->second; startPos = pos->first; for (; pos != possiblePosn.end(); ++pos) { if (currMaxPos < pos->second) { currMaxPos = pos->second; startPos = pos->first; } } //std::cerr << getID() << "::getEmptyStartStrip(" << vehWidth << ") = " << startPos << std::endl; return startPos; }
std::pair<MSVehicle* const, SUMOReal> MSLaneChanger::getRealLeader(const ChangerIt& target) const { // get the leading vehicle on the lane to change to MSVehicle* neighLead = target->lead; //if (veh(myCandi)->getID() == "disabled") std::cout << SIMTIME // << " target=" << target->lane->getID() // << " neighLead=" << Named::getIDSecure(neighLead) // << " hopped=" << Named::getIDSecure(target->hoppedVeh) // << " (416)\n"; // check whether the hopped vehicle became the leader if (target->hoppedVeh != 0) { SUMOReal hoppedPos = target->hoppedVeh->getPositionOnLane(); if (hoppedPos > veh(myCandi)->getPositionOnLane() && (neighLead == 0 || neighLead->getPositionOnLane() > hoppedPos)) { neighLead = target->hoppedVeh; //if (veh(myCandi)->getID() == "flow.21") std::cout << SIMTIME << " neighLead=" << Named::getIDSecure(neighLead) << " (422)\n"; } } if (neighLead == 0) { MSLane* targetLane = target->lane; if (targetLane->myPartialVehicles.size() > 0) { assert(targetLane->myPartialVehicles.size() == 1); MSVehicle* leader = targetLane->myPartialVehicles.front(); return std::pair<MSVehicle*, SUMOReal>(leader, leader->getBackPositionOnLane(targetLane) - veh(myCandi)->getPositionOnLane() - veh(myCandi)->getVehicleType().getMinGap()); } SUMOReal seen = myCandi->lane->getLength() - veh(myCandi)->getPositionOnLane(); SUMOReal speed = veh(myCandi)->getSpeed(); SUMOReal dist = veh(myCandi)->getCarFollowModel().brakeGap(speed) + veh(myCandi)->getVehicleType().getMinGap(); if (seen > dist) { return std::pair<MSVehicle* const, SUMOReal>(static_cast<MSVehicle*>(0), -1); } const std::vector<MSLane*>& bestLaneConts = veh(myCandi)->getBestLanesContinuation(targetLane); //if (veh(myCandi)->getID() == "flow.21") std::cout << SIMTIME << " calling getLeaderOnConsecutive (443)\n"; return target->lane->getLeaderOnConsecutive(dist, seen, speed, *veh(myCandi), bestLaneConts); } else { MSVehicle* candi = veh(myCandi); return std::pair<MSVehicle* const, SUMOReal>(neighLead, neighLead->getBackPositionOnLane(target->lane) - candi->getPositionOnLane() - candi->getVehicleType().getMinGap()); } }
int MSCalibrator::remainingVehicleCapacity(int laneIndex) const { if (laneIndex < 0) { const int numLanes = (int)myEdge->getLanes().size(); int result = 0; for (int i = 0; i < numLanes; ++i) { result = MAX2(result, remainingVehicleCapacity(i)); } return result; } assert(laneIndex < (int)myEdge->getLanes().size()); MSLane* lane = myEdge->getLanes()[laneIndex]; MSVehicle* last = lane->getLastFullVehicle(); const SUMOVehicleParameter* pars = myCurrentStateInterval->vehicleParameter; const MSVehicleType* vtype = MSNet::getInstance()->getVehicleControl().getVType(pars->vtypeid); const double spacePerVehicle = vtype->getLengthWithGap() + myEdge->getSpeedLimit() * vtype->getCarFollowModel().getHeadwayTime(); if (last == nullptr) { // ensure vehicles can be inserted on short edges return MAX2(1, (int)(myEdge->getLength() / spacePerVehicle)); } else { return (int)(last->getPositionOnLane() / spacePerVehicle); } }
bool MSLane::isEmissionSuccess(MSVehicle* aVehicle, SUMOReal speed, SUMOReal pos, bool patchSpeed, size_t startStripId) throw(ProcessError) { // and the speed is not too high (vehicle should decelerate) // try to get a leader on consecutive lanes // we have to do this even if we have found a leader on our lane because it may // be driving into another direction //std::cerr<<"EMISSION speed:"<<speed<<std::endl; std::cerr<<"EMISSION vehicle:"<<aVehicle->getID()<<std::endl; size_t endStripId = startStripId + aVehicle->getWidth() - 1; assert(startStripId >=0 && endStripId < myStrips.size()); aVehicle->getBestLanes(true, this); const MSCFModel &cfModel = aVehicle->getCarFollowModel(); const std::vector<MSLane*> &bestLaneConts = aVehicle->getBestLanesContinuation(this); std::vector<MSLane*>::const_iterator ri = bestLaneConts.begin(); SUMOReal seen = getLength() - pos; SUMOReal dist = cfModel.brakeGap(speed); const MSRoute &r = aVehicle->getRoute(); MSRouteIterator ce = r.begin(); MSLane *currentLane = this; MSLane *nextLane = this; while (seen<dist&&ri!=bestLaneConts.end()&&nextLane!=0/*&&ce!=r.end()*/) { // get the next link used... MSLinkCont::const_iterator link = currentLane->succLinkSec(*aVehicle, 1, *currentLane, bestLaneConts); // ...and the next used lane (including internal) if (!currentLane->isLinkEnd(link) && (*link)->havePriority() && (*link)->getState()!=MSLink::LINKSTATE_TL_RED) { // red may have priority? #ifdef HAVE_INTERNAL_LANES bool nextInternal = false; nextLane = (*link)->getViaLane(); if (nextLane==0) { nextLane = (*link)->getLane(); } else { nextInternal = true; } #else nextLane = (*link)->getLane(); #endif } else { nextLane = 0; } // check how next lane effects the journey if (nextLane!=0) { SUMOReal gap = 0; //TODO: fix get & set partial occupator to strip level MSVehicle * leader = 0;//currentLane->getPartialOccupator(); if (leader!=0) { gap = getPartialOccupatorEnd(); } else { // check leader on next lane leader = nextLane->getLastVehicle(aVehicle->getStrips()); if (leader!=0) { gap = seen+leader->getPositionOnLane()-leader->getVehicleType().getLength(); } } if (leader!=0) { SUMOReal nspeed = gap>=0 ? cfModel.ffeV(aVehicle, speed, gap, leader->getSpeed()) : 0; if (nspeed<speed) { if (patchSpeed) { speed = MIN2(nspeed, speed); dist = cfModel.brakeGap(speed); } else { // we may not drive with the given velocity - we crash into the leader return false; } } } // check next lane's maximum velocity SUMOReal nspeed = nextLane->getMaxSpeed(); if (nspeed<speed) { // patch speed if needed if (patchSpeed) { speed = MIN2(cfModel.ffeV(aVehicle, speed, seen, nspeed), speed); dist = cfModel.brakeGap(speed); } else { // we may not drive with the given velocity - we would be too fast on the next lane return false; } } // check traffic on next junctions const SUMOTime arrivalTime = MSNet::getInstance()->getCurrentTimeStep() + TIME2STEPS(seen / speed); #ifdef HAVE_INTERNAL_LANES const SUMOTime leaveTime = (*link)->getViaLane()==0 ? arrivalTime + TIME2STEPS((*link)->getLength() * speed) : arrivalTime + TIME2STEPS((*link)->getViaLane()->getLength() * speed); #else const SUMOTime leaveTime = arrivalTime + TIME2STEPS((*link)->getLength() * speed); #endif if ((*link)->hasApproachingFoe(arrivalTime, leaveTime)) { SUMOReal nspeed = cfModel.ffeV(aVehicle, speed, seen, 0); if (nspeed<speed) { if (patchSpeed) { speed = MIN2(nspeed, speed); dist = cfModel.brakeGap(speed); } else { // we may not drive with the given velocity - we crash into the leader return false; } } } else { // we can only drive to the end of the current lane... SUMOReal nspeed = cfModel.ffeV(aVehicle, speed, seen, 0); if (nspeed<speed) { if (patchSpeed) { speed = MIN2(nspeed, speed); dist = cfModel.brakeGap(speed); } else { // we may not drive with the given velocity - we crash into the leader return false; } } } seen += nextLane->getLength(); ++ce; ++ri; currentLane = nextLane; } } if (seen<dist) { SUMOReal nspeed = cfModel.ffeV(aVehicle, speed, seen, 0); if (nspeed<speed) { if (patchSpeed) { speed = MIN2(nspeed, speed); dist = cfModel.brakeGap(speed); } else { // we may not drive with the given velocity - we crash into the leader MsgHandler::getErrorInstance()->inform("Vehicle '" + aVehicle->getID() + "' will not be able to emit using given velocity!"); // !!! we probably should do something else... return false; } } } // get the pointer to the vehicle next in front of the given position MSVehicle *pred; std::vector<MSVehicle *> predCont; std::vector<MSVehicle *>::iterator predIt, it; for (unsigned int i=startStripId; i<=endStripId; ++i) { predCont.push_back(myStrips.at(i)->getPredAtPos(pos)); } predIt = predCont.begin(); SUMOReal currMin = -1; if (*predIt != 0) { currMin = (*predIt)->getPositionOnLane(); } else { // signals no leader in front predIt = predCont.end(); } for (it = predCont.begin(); it != predCont.end(); ++it) { if (*it == 0) continue; if ((*it)->getPositionOnLane() < currMin) { predIt = it; currMin = (*it)->getPositionOnLane(); } } if (predIt != predCont.end()) { // ok, there is one (a leader) MSVehicle* leader = *predIt; SUMOReal frontGapNeeded = aVehicle->getCarFollowModel().getSecureGap(speed, leader->getCarFollowModel().getSpeedAfterMaxDecel(leader->getSpeed())); SUMOReal gap = MSVehicle::gap(leader->getPositionOnLane(), leader->getVehicleType().getLength(), pos); if (gap<frontGapNeeded) { // too close to the leader on this lane return false; } } // FIXME: implement look back // check back vehicle if (false/*predIt!=myVehicles.begin()*/) { // there is direct follower on this lane MSVehicle *follower = *(predIt-1); SUMOReal backGapNeeded = follower->getCarFollowModel().getSecureGap(follower->getSpeed(), aVehicle->getCarFollowModel().getSpeedAfterMaxDecel(speed)); SUMOReal gap = MSVehicle::gap(pos, aVehicle->getVehicleType().getLength(), follower->getPositionOnLane()); if (gap<backGapNeeded) { // too close to the follower on this lane return false; } } else if (false) { // check approaching vehicle (consecutive follower) SUMOReal lspeed = getMaxSpeed(); // in order to look back, we'd need the minimum braking ability of vehicles in the net... // we'll assume it to be 4m/s^2 // !!!revisit SUMOReal dist = lspeed * lspeed * SUMOReal(1./2.*4.) + SPEED2DIST(lspeed); std::pair<const MSVehicle * const, SUMOReal> approaching = getFollowerOnConsecutive(dist, 0, speed, pos - aVehicle->getVehicleType().getLength()); if (approaching.first!=0) { const MSVehicle *const follower = approaching.first; SUMOReal backGapNeeded = follower->getCarFollowModel().getSecureGap(follower->getSpeed(), aVehicle->getCarFollowModel().getSpeedAfterMaxDecel(speed)); SUMOReal gap = approaching.second - pos - aVehicle->getVehicleType().getLength(); if (gap<backGapNeeded) { // too close to the consecutive follower return false; } } // check for in-lapping vehicle MSVehicle* leader = getPartialOccupator(); if (leader!=0) { SUMOReal frontGapNeeded = aVehicle->getCarFollowModel().getSecureGap(speed, leader->getCarFollowModel().getSpeedAfterMaxDecel(leader->getSpeed())); SUMOReal gap = getPartialOccupatorEnd() - pos; if (gap<=frontGapNeeded) { // too close to the leader on this lane return false; } } } // may got negative while adaptation if (speed<0) { return false; } // enter //XXX: later change to enterStripAtEmit()? //if (speed < 0.0001) speed += 10.0; StripCont strips; strips.resize(aVehicle->getWidth()); StripCont::iterator start = myStrips.begin() + startStripId; std::copy(start, start + aVehicle->getWidth(), strips.begin()); aVehicle->enterLaneAtEmit(this, pos, speed, strips); bool wasInactive = getVehicleNumber()==0; if (true/*predIt==myVehicles.end()*/) { // vehicle will be the first on the lane //std::cerr<<"startStripId:"<<startStripId<<", NumStrips:"<<strips.size()<<", VehWidth:"<<aVehicle->getWidth()<<std::endl; for (size_t i=startStripId; i<startStripId+strips.size(); ++i) { this->getStrip(i)->pushIntoStrip(aVehicle); this->getStrip(i)->setVehLenSum(this->getStrip(i)->getVehLenSum() + aVehicle->getVehicleType().getLength()); } aVehicle->printDebugMsg("Emitting"); printDebugMsg(); } else { //this->getStrip(0).insert(0, aVehicle); } //myVehicleLengthSum += aVehicle->getVehicleType().getLength(); if (wasInactive) { MSNet::getInstance()->getEdgeControl().gotActive(this); } return true; }
// ------ Vehicle emission ------ bool MSLane::freeEmit(MSVehicle& veh, SUMOReal mspeed) throw() { size_t stripId = getEmptyStartStripID(veh.getWidth()); bool adaptableSpeed = true; if (getVehicleNumber()==0) { if (isEmissionSuccess(&veh, mspeed, 0, adaptableSpeed,stripId)) { return true; } } else { // check whether the vehicle can be put behind the last one if there is such MSVehicle *leader = getLastVehicle(veh.getStrips()); if (leader != 0) { SUMOReal leaderPos = leader->getPositionOnLane() - leader->getVehicleType().getLength(); SUMOReal speed = mspeed; if (adaptableSpeed) { speed = leader->getSpeed(); } SUMOReal frontGapNeeded = veh.getCarFollowModel().getSecureGap(speed, leader->getCarFollowModel().getSpeedAfterMaxDecel(leader->getSpeed())); if (leaderPos-frontGapNeeded>=0) { SUMOReal tspeed = MIN2(veh.getCarFollowModel().ffeV(&veh, mspeed, frontGapNeeded, leader->getSpeed()), mspeed); // check whether we can emit in behind the last vehicle on the lane if (isEmissionSuccess(&veh, tspeed, 0, adaptableSpeed, stripId)) { return true; } else std::cerr << "not successful emission 1" ; } } else { if (isEmissionSuccess(&veh, mspeed, 0, adaptableSpeed, stripId)) { return true; } else std::cerr << "not successful emission 2" ; } } /* ashu StripCont strips =getMyStrips(); for (StripContConstIter it=strips.begin(); it != strips.end(); ++it) {if ((*it)->freeEmitCheck(veh, mspeed)) return true;} //TODO: Uncomment and fix // go through the lane, look for free positions (starting after the last vehicle) MSLane::VehCont::iterator predIt = myVehicles.begin(); while (predIt!=myVehicles.end()) { // get leader (may be zero) and follower const MSVehicle *leader = predIt!=myVehicles.end()-1 ? *(predIt+1) : getPartialOccupator(); const MSVehicle *follower = *predIt; // patch speed if allowed SUMOReal speed = mspeed; if (adaptableSpeed&&leader!=0) { speed = MIN2(leader->getSpeed(), mspeed); } // compute the space needed to not collide with leader SUMOReal frontMax = getLength(); if (leader!=0) { SUMOReal leaderRearPos = leader->getPositionOnLane() - leader->getVehicleType().getLength(); if (leader == getPartialOccupator()) { leaderRearPos = getPartialOccupatorEnd(); } frontMax = leaderRearPos - veh.getCarFollowModel().getSecureGap(speed, leader->getCarFollowModel().getSpeedAfterMaxDecel(leader->getSpeed())); } // compute the space needed to not let the follower collide const SUMOReal followPos = follower->getPositionOnLane(); const SUMOReal backGapNeeded = follower->getCarFollowModel().getSecureGap(follower->getSpeed(), veh.getCarFollowModel().getSpeedAfterMaxDecel(speed)); const SUMOReal backMin = followPos + backGapNeeded + veh.getVehicleType().getLength(); // check whether there is enough room (given some extra space for rounding errors) if (frontMax>0 && backMin+POSITION_EPS<frontMax) { // try emit vehicle (should be always ok) if (isEmissionSuccess(&veh, speed, backMin+POSITION_EPS, adaptableSpeed)) { std::cerr << "FIX working" ; return true; } } ++predIt; } */ //TODO: Recheck01 ___AB oct 2011 StripCont strips =getMyStrips(); for (StripContConstIter it=strips.begin(); it != strips.end(); ++it) { // go through the lane, look for free positions (starting after the last vehicle) MSLane::VehCont::iterator predIt = (*it)->myVehicles.begin(); while (predIt!=(*it)->myVehicles.end()) { // get leader (may be zero) and follower const MSVehicle *leader = predIt!=(*it)->myVehicles.end()-1 ? *(predIt+1) : (*it)->getPartialOccupator(); const MSVehicle *follower = *predIt; // patch speed if allowed SUMOReal speed = mspeed; if (adaptableSpeed&&leader!=0) { speed = MIN2(leader->getSpeed(), mspeed); } // compute the space needed to not collide with leader SUMOReal frontMax = getLength(); if (leader!=0) { SUMOReal leaderRearPos = leader->getPositionOnLane() - leader->getVehicleType().getLength(); if (leader == (*it)->getPartialOccupator()) { leaderRearPos = (*it)->getPartialOccupatorEnd(); } frontMax = leaderRearPos - veh.getCarFollowModel().getSecureGap(speed, leader->getCarFollowModel().getSpeedAfterMaxDecel(leader->getSpeed())); } // compute the space needed to not let the follower collide const SUMOReal followPos = follower->getPositionOnLane(); const SUMOReal backGapNeeded = follower->getCarFollowModel().getSecureGap(follower->getSpeed(), veh.getCarFollowModel().getSpeedAfterMaxDecel(speed)); const SUMOReal backMin = followPos + backGapNeeded + veh.getVehicleType().getLength(); // check whether there is enough room (given some extra space for rounding errors) if (frontMax>0 && backMin+POSITION_EPS<frontMax) { // try emit vehicle (should be always ok) if (isEmissionSuccess(&veh, speed, backMin+POSITION_EPS, adaptableSpeed, stripId)) { std::cerr << "FIX working" ; return true; } } ++predIt; } }//for // first check at lane's begin std::cerr << "not successful emission last" ; return false; }
std::pair<MSVehicle* const, SUMOReal> MSLaneChanger::getRealFollower(const ChangerIt& target) const { assert(veh(myCandi) != 0); #ifdef DEBUG_SURROUNDING_VEHICLES MSVehicle* vehicle = veh(myCandi); if (DEBUG_COND) { std::cout << SIMTIME << " veh '" << vehicle->getID() << "' looks for follower on lc-target lane '" << target->lane->getID() << "'." << std::endl; } #endif MSVehicle* candi = veh(myCandi); const SUMOReal candiPos = candi->getPositionOnLane(); MSVehicle* neighFollow = veh(target); #ifdef DEBUG_SURROUNDING_VEHICLES if (DEBUG_COND) { if (neighFollow != 0) { std::cout << "veh(target) returns '" << neighFollow->getID() << "' at position " << neighFollow->getPositionOnLane() << std::endl; } else { std::cout << "veh(target) returns none." << std::endl; } } #endif #ifdef DEBUG_SURROUNDING_VEHICLES if (DEBUG_COND) { if (getCloserFollower(candiPos, neighFollow, target->hoppedVeh) != neighFollow) { std::cout << "Hopped vehicle '" << target->hoppedVeh->getID() << "' at position " << target->hoppedVeh->getPositionOnLane() << " is closer." << std::endl; } } #endif // check whether the hopped vehicle became the follower neighFollow = getCloserFollower(candiPos, neighFollow, target->hoppedVeh); #ifdef DEBUG_SURROUNDING_VEHICLES if (DEBUG_COND) { MSVehicle* partialBehind = getCloserFollower(candiPos, neighFollow, target->lane->getPartialBehind(candi)); if (partialBehind != 0 && partialBehind != neighFollow) { std::cout << "'Partial behind'-vehicle '" << target->lane->getPartialBehind(candi)->getID() << "' at position " << target->hoppedVeh->getPositionOnLane() << " is closer." << std::endl; } } #endif // or a follower which is partially lapping into the target lane neighFollow = getCloserFollower(candiPos, neighFollow, target->lane->getPartialBehind(candi)); if (neighFollow == 0) { std::pair<MSVehicle* const, SUMOReal> consecutiveFollower = target->lane->getFollowerOnConsecutive( candi->getPositionOnLane() - candi->getVehicleType().getLength(), candi->getSpeed(), candi->getCarFollowModel().getMaxDecel()); #ifdef DEBUG_SURROUNDING_VEHICLES if (DEBUG_COND) { if (consecutiveFollower.first == 0) { std::cout << "no follower found." << std::endl; } else { std::cout << "found follower '" << consecutiveFollower.first->getID() << "' on consecutive lanes." << std::endl; } } #endif return consecutiveFollower; } else { #ifdef DEBUG_SURROUNDING_VEHICLES if (DEBUG_COND) { std::cout << "found follower '" << neighFollow->getID() << "'." << std::endl; } #endif MSVehicle* candi = veh(myCandi); return std::pair<MSVehicle* const, SUMOReal>(neighFollow, candi->getPositionOnLane() - candi->getVehicleType().getLength() - neighFollow->getPositionOnLane() - neighFollow->getVehicleType().getMinGap()); } }
void MSE2Collector::detectorUpdate(const SUMOTime /* step */) { JamInfo* currentJam = 0; std::map<SUMOVehicle*, SUMOTime> haltingVehicles; std::map<SUMOVehicle*, SUMOTime> intervalHaltingVehicles; std::vector<JamInfo*> jams; SUMOReal lengthSum = 0; myCurrentMeanSpeed = 0; myCurrentMeanLength = 0; myCurrentStartedHalts = 0; myCurrentHaltingsNumber = 0; // go through the (sorted) list of vehicles positioned on the detector // sum up values and prepare the list of jams myKnownVehicles.sort(by_vehicle_position_sorter(getLane())); for (std::list<SUMOVehicle*>::const_iterator i = myKnownVehicles.begin(); i != myKnownVehicles.end(); ++i) { MSVehicle* veh = static_cast<MSVehicle*>(*i); SUMOReal length = veh->getVehicleType().getLength(); if (veh->getLane() == getLane()) { if (veh->getPositionOnLane() - veh->getVehicleType().getLength() < myStartPos) { // vehicle entered detector partially length -= (veh->getVehicleType().getLength() - (veh->getPositionOnLane() - myStartPos)); } if (veh->getPositionOnLane() > myEndPos && veh->getPositionOnLane() - veh->getVehicleType().getLength() <= myEndPos) { // vehicle left detector partially length -= (veh->getPositionOnLane() - myEndPos); } } else { // ok, the vehicle is only partially still on the detector, has already moved to the // next lane; still, we do not know how far away it is assert(veh == myLane->getPartialOccupator()); length = myEndPos - myLane->getPartialOccupatorEnd(); } assert(length >= 0); mySpeedSum += veh->getSpeed(); myCurrentMeanSpeed += veh->getSpeed(); lengthSum += length; myCurrentMeanLength += length; // jam-checking begins bool isInJam = false; // first, check whether the vehicle is slow enough to be states as halting if (veh->getSpeed() < myJamHaltingSpeedThreshold) { myCurrentHaltingsNumber++; // we have to track the time it was halting; // so let's look up whether it was halting before and compute the overall halting time bool wasHalting = myHaltingVehicleDurations.find(veh) != myHaltingVehicleDurations.end(); if (wasHalting) { haltingVehicles[veh] = myHaltingVehicleDurations[veh] + DELTA_T; intervalHaltingVehicles[veh] = myIntervalHaltingVehicleDurations[veh] + DELTA_T; } else { haltingVehicles[veh] = DELTA_T; intervalHaltingVehicles[veh] = DELTA_T; myCurrentStartedHalts++; myStartedHalts++; } // we now check whether the halting time is large enough if (haltingVehicles[veh] > myJamHaltingTimeThreshold) { // yep --> the vehicle is a part of a jam isInJam = true; } } else { // is not standing anymore; keep duration information std::map<SUMOVehicle*, SUMOTime>::iterator v = myHaltingVehicleDurations.find(veh); if (v != myHaltingVehicleDurations.end()) { myPastStandingDurations.push_back((*v).second); myHaltingVehicleDurations.erase(v); } v = myIntervalHaltingVehicleDurations.find(veh); if (v != myIntervalHaltingVehicleDurations.end()) { myPastIntervalStandingDurations.push_back((*v).second); myIntervalHaltingVehicleDurations.erase(v); } } // jam-building if (isInJam) { // the vehicle is in a jam; // it may be a new one or already an existing one if (currentJam == 0) { // the vehicle is the first vehicle in a jam currentJam = new JamInfo; currentJam->firstStandingVehicle = i; } else { // ok, we have a jam already. But - maybe it is too far away // ... honestly, I can hardly find a reason for doing this, // but jams were defined this way in an earlier version... if (veh->getPositionOnLane() - (*currentJam->lastStandingVehicle)->getPositionOnLane() > myJamDistanceThreshold) { // yep, yep, yep - it's a new one... // close the frist, build a new jams.push_back(currentJam); currentJam = new JamInfo; currentJam->firstStandingVehicle = i; } } currentJam->lastStandingVehicle = i; } else { // the vehicle is not part of a jam... // maybe we have to close an already computed jam if (currentJam != 0) { jams.push_back(currentJam); currentJam = 0; } } } if (currentJam != 0) { jams.push_back(currentJam); currentJam = 0; } myCurrentMaxJamLengthInMeters = 0; myCurrentMaxJamLengthInVehicles = 0; myCurrentJamLengthInMeters = 0; myCurrentJamLengthInVehicles = 0; // process jam information for (std::vector<JamInfo*>::iterator i = jams.begin(); i != jams.end(); ++i) { // compute current jam's values SUMOReal jamLengthInMeters = (*(*i)->firstStandingVehicle)->getPositionOnLane() - (*(*i)->lastStandingVehicle)->getPositionOnLane() + (*(*i)->lastStandingVehicle)->getVehicleType().getLengthWithGap(); const MSVehicle* const occ = myLane->getPartialOccupator(); if (occ && occ == *(*i)->firstStandingVehicle && occ != *(*i)->lastStandingVehicle) { jamLengthInMeters = myLane->getPartialOccupatorEnd() + occ->getVehicleType().getLengthWithGap() - (*(*i)->lastStandingVehicle)->getPositionOnLane() + (*(*i)->lastStandingVehicle)->getVehicleType().getLengthWithGap(); } unsigned jamLengthInVehicles = (unsigned) distance((*i)->firstStandingVehicle, (*i)->lastStandingVehicle) + 1; // apply them to the statistics myCurrentMaxJamLengthInMeters = MAX2(myCurrentMaxJamLengthInMeters, jamLengthInMeters); myCurrentMaxJamLengthInVehicles = MAX2(myCurrentMaxJamLengthInVehicles, jamLengthInVehicles); myJamLengthInMetersSum += jamLengthInMeters; myJamLengthInVehiclesSum += jamLengthInVehicles; myCurrentJamLengthInMeters += jamLengthInMeters; myCurrentJamLengthInVehicles += jamLengthInVehicles; } myCurrentJamNo = (unsigned) jams.size(); unsigned noVehicles = (unsigned) myKnownVehicles.size(); myVehicleSamples += noVehicles; myTimeSamples += 1; // compute occupancy values SUMOReal currentOccupancy = lengthSum / (myEndPos - myStartPos) * (SUMOReal) 100.; myCurrentOccupancy = currentOccupancy; myOccupancySum += currentOccupancy; myMaxOccupancy = MAX2(myMaxOccupancy, currentOccupancy); // compute jam values myMeanMaxJamInVehicles += myCurrentMaxJamLengthInVehicles; myMeanMaxJamInMeters += myCurrentMaxJamLengthInMeters; myMaxJamInVehicles = MAX2(myMaxJamInVehicles, myCurrentMaxJamLengthInVehicles); myMaxJamInMeters = MAX2(myMaxJamInMeters, myCurrentMaxJamLengthInMeters); // save information about halting vehicles myHaltingVehicleDurations = haltingVehicles; myIntervalHaltingVehicleDurations = intervalHaltingVehicles; // compute information about vehicle numbers myMeanVehicleNumber += (unsigned) myKnownVehicles.size(); myMaxVehicleNumber = MAX2((unsigned) myKnownVehicles.size(), myMaxVehicleNumber); // norm current values myCurrentMeanSpeed = noVehicles != 0 ? myCurrentMeanSpeed / (SUMOReal) noVehicles : -1; myCurrentMeanLength = noVehicles != 0 ? myCurrentMeanLength / (SUMOReal) noVehicles : -1; // clean up for (std::vector<JamInfo*>::iterator i = jams.begin(); i != jams.end(); ++i) { delete *i; } jams.clear(); }
int MSLaneChanger::checkChange( int laneOffset, const MSLane* targetLane, const std::pair<MSVehicle* const, SUMOReal>& leader, const std::pair<MSVehicle* const, SUMOReal>& neighLead, const std::pair<MSVehicle* const, SUMOReal>& neighFollow, const std::vector<MSVehicle::LaneQ>& preb) const { MSVehicle* vehicle = veh(myCandi); // Debug (Leo) #ifdef DEBUG_CHECK_CHANGE if (DEBUG_COND) { std::cout << "\n" << SIMTIME << " checkChange() for vehicle '" << vehicle->getID() << "'" << std::endl; } #endif int blocked = 0; int blockedByLeader = (laneOffset == -1 ? LCA_BLOCKED_BY_RIGHT_LEADER : LCA_BLOCKED_BY_LEFT_LEADER); int blockedByFollower = (laneOffset == -1 ? LCA_BLOCKED_BY_RIGHT_FOLLOWER : LCA_BLOCKED_BY_LEFT_FOLLOWER); // overlap if (neighFollow.first != 0 && neighFollow.second < 0) { blocked |= (blockedByFollower | LCA_OVERLAPPING); // Debug (Leo) #ifdef DEBUG_CHECK_CHANGE if (DEBUG_COND) { std::cout << SIMTIME << " overlapping with follower..." << std::endl; } #endif } if (neighLead.first != 0 && neighLead.second < 0) { blocked |= (blockedByLeader | LCA_OVERLAPPING); // Debug (Leo) #ifdef DEBUG_CHECK_CHANGE if (DEBUG_COND) { std::cout << SIMTIME << " overlapping with leader..." << std::endl; } #endif } // safe back gap if ((blocked & blockedByFollower) == 0 && neighFollow.first != 0) { // !!! eigentlich: vsafe braucht die Max. Geschwindigkeit beider Spuren if (neighFollow.second < neighFollow.first->getCarFollowModel().getSecureGap(neighFollow.first->getSpeed(), vehicle->getSpeed(), vehicle->getCarFollowModel().getMaxDecel())) { blocked |= blockedByFollower; // Debug (Leo) #ifdef DEBUG_CHECK_CHANGE if (DEBUG_COND) { std::cout << SIMTIME << " back gap unsafe: " << "gap = " << neighFollow.second << ", secureGap = " << neighFollow.first->getCarFollowModel().getSecureGap(neighFollow.first->getSpeed(), vehicle->getSpeed(), vehicle->getCarFollowModel().getMaxDecel()) << std::endl; } #endif } } // safe front gap if ((blocked & blockedByLeader) == 0 && neighLead.first != 0) { // !!! eigentlich: vsafe braucht die Max. Geschwindigkeit beider Spuren if (neighLead.second < vehicle->getCarFollowModel().getSecureGap(vehicle->getSpeed(), neighLead.first->getSpeed(), neighLead.first->getCarFollowModel().getMaxDecel())) { blocked |= blockedByLeader; // Debug (Leo) #ifdef DEBUG_CHECK_CHANGE if (DEBUG_COND) { std::cout << SIMTIME << " front gap unsafe: " << "gap = " << neighLead.second << ", secureGap = " << vehicle->getCarFollowModel().getSecureGap(vehicle->getSpeed(), neighLead.first->getSpeed(), neighLead.first->getCarFollowModel().getMaxDecel()) << std::endl; } #endif } } MSAbstractLaneChangeModel::MSLCMessager msg(leader.first, neighLead.first, neighFollow.first); int state = blocked | vehicle->getLaneChangeModel().wantsChange( laneOffset, msg, blocked, leader, neighLead, neighFollow, *targetLane, preb, &(myCandi->lastBlocked), &(myCandi->firstBlocked)); if (blocked == 0 && (state & LCA_WANTS_LANECHANGE) != 0 && neighLead.first != 0) { // do are more carefull (but expensive) check to ensure that a // safety-critical leader is not being overloocked const SUMOReal seen = myCandi->lane->getLength() - vehicle->getPositionOnLane(); const SUMOReal speed = vehicle->getSpeed(); const SUMOReal dist = vehicle->getCarFollowModel().brakeGap(speed) + vehicle->getVehicleType().getMinGap(); if (seen < dist) { std::pair<MSVehicle* const, SUMOReal> neighLead2 = targetLane->getCriticalLeader(dist, seen, speed, *vehicle); if (neighLead2.first != 0 && neighLead2.first != neighLead.first && (neighLead2.second < vehicle->getCarFollowModel().getSecureGap( vehicle->getSpeed(), neighLead2.first->getSpeed(), neighLead2.first->getCarFollowModel().getMaxDecel()))) { state |= blockedByLeader; } } } if (blocked == 0 && (state & LCA_WANTS_LANECHANGE)) { // ensure that merging is safe for any upcoming zipper links after changing if (vehicle->unsafeLinkAhead(targetLane)) { state |= blockedByLeader; } } if ((state & LCA_BLOCKED) == 0 && (state & LCA_WANTS_LANECHANGE) != 0 && MSGlobals::gLaneChangeDuration > DELTA_T) { // ensure that a continuous lane change manoeuvre can be completed // before the next turning movement SUMOReal seen = myCandi->lane->getLength() - vehicle->getPositionOnLane(); const SUMOReal decel = vehicle->getCarFollowModel().getMaxDecel() * STEPS2TIME(MSGlobals::gLaneChangeDuration); const SUMOReal avgSpeed = 0.5 * ( MAX2((SUMOReal)0, vehicle->getSpeed() - ACCEL2SPEED(vehicle->getCarFollowModel().getMaxDecel())) + MAX2((SUMOReal)0, vehicle->getSpeed() - decel)); const SUMOReal space2change = avgSpeed * STEPS2TIME(MSGlobals::gLaneChangeDuration); // for finding turns it doesn't matter whether we look along the current lane or the target lane const std::vector<MSLane*>& bestLaneConts = vehicle->getBestLanesContinuation(); int view = 1; MSLane* nextLane = vehicle->getLane(); MSLinkCont::const_iterator link = MSLane::succLinkSec(*vehicle, view, *nextLane, bestLaneConts); while (!nextLane->isLinkEnd(link) && seen <= space2change) { if ((*link)->getDirection() == LINKDIR_LEFT || (*link)->getDirection() == LINKDIR_RIGHT // the lanes after an internal junction are on different // edges and do not allow lane-changing || (nextLane->getEdge().isInternal() && (*link)->getViaLaneOrLane()->getEdge().isInternal()) ) { state |= LCA_INSUFFICIENT_SPACE; break; } #ifdef HAVE_INTERNAL_LANES if ((*link)->getViaLane() == 0) { view++; } #else view++; #endif nextLane = (*link)->getViaLaneOrLane(); seen += nextLane->getLength(); // get the next link used link = MSLane::succLinkSec(*vehicle, view, *nextLane, bestLaneConts); } if (nextLane->isLinkEnd(link) && seen < space2change) { #ifdef DEBUG_CHECK_CHANGE if (DEBUG_COND) { std::cout << SIMTIME << " checkChange insufficientSpace: seen=" << seen << " space2change=" << space2change << "\n"; } #endif state |= LCA_INSUFFICIENT_SPACE; } if ((state & LCA_BLOCKED) == 0) { // check for dangerous leaders in case the target lane changes laterally between // now and the lane-changing midpoint const SUMOReal speed = vehicle->getSpeed(); seen = myCandi->lane->getLength() - vehicle->getPositionOnLane(); nextLane = vehicle->getLane(); view = 1; const SUMOReal dist = vehicle->getCarFollowModel().brakeGap(speed) + vehicle->getVehicleType().getMinGap(); MSLinkCont::const_iterator link = MSLane::succLinkSec(*vehicle, view, *nextLane, bestLaneConts); while (!nextLane->isLinkEnd(link) && seen <= space2change && seen <= dist) { nextLane = (*link)->getViaLaneOrLane(); MSLane* targetLane = nextLane->getParallelLane(laneOffset); if (targetLane == 0) { state |= LCA_INSUFFICIENT_SPACE; break; } else { std::pair<MSVehicle* const, SUMOReal> neighLead2 = targetLane->getLeader(vehicle, -seen, std::vector<MSLane*>()); if (neighLead2.first != 0 && neighLead2.first != neighLead.first && (neighLead2.second < vehicle->getCarFollowModel().getSecureGap( vehicle->getSpeed(), neighLead2.first->getSpeed(), neighLead2.first->getCarFollowModel().getMaxDecel()))) { state |= blockedByLeader; break; } } #ifdef HAVE_INTERNAL_LANES if ((*link)->getViaLane() == 0) { view++; } #else view++; #endif seen += nextLane->getLength(); // get the next link used link = MSLane::succLinkSec(*vehicle, view, *nextLane, bestLaneConts); } } } #ifndef NO_TRACI #ifdef DEBUG_CHECK_CHANGE const int oldstate = state; #endif // let TraCI influence the wish to change lanes and the security to take state = vehicle->influenceChangeDecision(state); #endif #ifdef DEBUG_CHECK_CHANGE if (DEBUG_COND) { std::cout << SIMTIME << " veh=" << vehicle->getID() << " oldState=" << toString((LaneChangeAction)oldstate) << " newState=" << toString((LaneChangeAction)state) << ((blocked & LCA_BLOCKED) ? " (blocked)" : "") << ((blocked & LCA_OVERLAPPING) ? " (overlap)" : "") << "\n"; } #endif return state; }
std::pair<MSVehicle* const, SUMOReal> MSLaneChanger::getRealLeader(const ChangerIt& target) const { assert(veh(myCandi) != 0); #ifdef DEBUG_SURROUNDING_VEHICLES MSVehicle* vehicle = veh(myCandi); if (DEBUG_COND) { std::cout << SIMTIME << " veh '" << vehicle->getID() << "' looks for leader on lc-target lane '" << target->lane->getID() << "'." << std::endl; } #endif // get the leading vehicle on the lane to change to MSVehicle* neighLead = target->lead; #ifdef DEBUG_SURROUNDING_VEHICLES if (DEBUG_COND) { if (neighLead != 0) { std::cout << "Considering '" << neighLead->getID() << "' at position " << neighLead->getPositionOnLane() << std::endl; } } #endif //if (veh(myCandi)->getID() == "disabled") std::cout << SIMTIME // << " target=" << target->lane->getID() // << " neighLead=" << Named::getIDSecure(neighLead) // << " hopped=" << Named::getIDSecure(target->hoppedVeh) // << " (416)\n"; // check whether the hopped vehicle became the leader if (target->hoppedVeh != 0) { SUMOReal hoppedPos = target->hoppedVeh->getPositionOnLane(); #ifdef DEBUG_SURROUNDING_VEHICLES if (DEBUG_COND) { std::cout << "Considering hopped vehicle '" << target->hoppedVeh->getID() << "' at position " << hoppedPos << std::endl; } #endif if (hoppedPos > veh(myCandi)->getPositionOnLane() && (neighLead == 0 || neighLead->getPositionOnLane() > hoppedPos)) { neighLead = target->hoppedVeh; //if (veh(myCandi)->getID() == "flow.21") std::cout << SIMTIME << " neighLead=" << Named::getIDSecure(neighLead) << " (422)\n"; } } if (neighLead == 0) { #ifdef DEBUG_SURROUNDING_VEHICLES if (DEBUG_COND) { std::cout << "Looking for leader on consecutive lanes." << std::endl; } #endif // There's no leader on the target lane. Look for leaders on consecutive lanes. MSLane* targetLane = target->lane; if (targetLane->myPartialVehicles.size() > 0) { assert(targetLane->myPartialVehicles.size() > 0); std::vector<MSVehicle*>::const_iterator i = targetLane->myPartialVehicles.begin(); MSVehicle* leader = *i; SUMOReal leaderPos = leader->getBackPositionOnLane(targetLane); while (++i != targetLane->myPartialVehicles.end()) { if ((*i)->getBackPositionOnLane(targetLane) < leader->getBackPositionOnLane(targetLane)) { leader = *i; leaderPos = leader->getBackPositionOnLane(targetLane); } } return std::pair<MSVehicle*, SUMOReal>(leader, leaderPos - veh(myCandi)->getPositionOnLane() - veh(myCandi)->getVehicleType().getMinGap()); } SUMOReal seen = myCandi->lane->getLength() - veh(myCandi)->getPositionOnLane(); SUMOReal speed = veh(myCandi)->getSpeed(); SUMOReal dist = veh(myCandi)->getCarFollowModel().brakeGap(speed) + veh(myCandi)->getVehicleType().getMinGap(); if (seen > dist) { return std::pair<MSVehicle* const, SUMOReal>(static_cast<MSVehicle*>(0), -1); } const std::vector<MSLane*>& bestLaneConts = veh(myCandi)->getBestLanesContinuation(targetLane); return target->lane->getLeaderOnConsecutive(dist, seen, speed, *veh(myCandi), bestLaneConts); } else { MSVehicle* candi = veh(myCandi); return std::pair<MSVehicle* const, SUMOReal>(neighLead, neighLead->getBackPositionOnLane(target->lane) - candi->getPositionOnLane() - candi->getVehicleType().getMinGap()); } }
bool MSLaneChanger::changeOpposite(std::pair<MSVehicle*, SUMOReal> leader) { if (!myChangeToOpposite) { return false; } myCandi = findCandidate(); MSVehicle* vehicle = veh(myCandi); MSLane* source = vehicle->getLane(); if (vehicle->isStopped()) { // stopped vehicles obviously should not change lanes. Usually this is // prevent by appropriate bestLane distances return false; } const bool isOpposite = vehicle->getLaneChangeModel().isOpposite(); if (!isOpposite && leader.first == 0) { // no reason to change unless there is a leader // or we are changing back to the propper direction // XXX also check whether the leader is so far away as to be irrelevant return false; } if (!source->getEdge().canChangeToOpposite()) { return false; } MSLane* opposite = source->getOpposite(); if (opposite == 0) { return false; } // changing into the opposite direction is always to the left (XXX except for left-hand networkds) int direction = vehicle->getLaneChangeModel().isOpposite() ? -1 : 1; std::pair<MSVehicle*, SUMOReal> neighLead((MSVehicle*)0, -1); // preliminary sanity checks for overtaking space if (!isOpposite) { assert(leader.first != 0); // find a leader vehicle with sufficient space ahead for merging back const SUMOReal overtakingSpeed = source->getVehicleMaxSpeed(vehicle); // just a guess const SUMOReal mergeBrakeGap = vehicle->getCarFollowModel().brakeGap(overtakingSpeed); const SUMOReal maxLookAhead = 150; // just a guess std::pair<MSVehicle*, SUMOReal> columnLeader = leader; SUMOReal egoGap = leader.second; bool foundSpaceAhead = false; SUMOReal seen = leader.second + leader.first->getVehicleType().getLengthWithGap(); std::vector<MSLane*> conts = vehicle->getBestLanesContinuation(); while (!foundSpaceAhead) { const SUMOReal requiredSpaceAfterLeader = (columnLeader.first->getCarFollowModel().getSecureGap( columnLeader.first->getSpeed(), overtakingSpeed, vehicle->getCarFollowModel().getMaxDecel()) + vehicle->getVehicleType().getLengthWithGap()); std::pair<MSVehicle* const, SUMOReal> leadLead = columnLeader.first->getLane()->getLeader( columnLeader.first, columnLeader.first->getPositionOnLane(), conts, requiredSpaceAfterLeader + mergeBrakeGap, true); #ifdef DEBUG_CHANGE_OPPOSITE if (DEBUG_COND) { std::cout << " leadLead=" << Named::getIDSecure(leadLead.first) << " gap=" << leadLead.second << "\n"; } #endif if (leadLead.first == 0) { foundSpaceAhead = true; } else { const SUMOReal requiredSpace = (requiredSpaceAfterLeader + vehicle->getCarFollowModel().getSecureGap(overtakingSpeed, leadLead.first->getSpeed(), leadLead.first->getCarFollowModel().getMaxDecel())); if (leadLead.second > requiredSpace) { foundSpaceAhead = true; } else { #ifdef DEBUG_CHANGE_OPPOSITE if (DEBUG_COND) { std::cout << " not enough space after columnLeader=" << leadLead.first->getID() << " gap=" << leadLead.second << " required=" << requiredSpace << "\n"; } #endif seen += leadLead.second + leadLead.first->getVehicleType().getLengthWithGap(); if (seen > maxLookAhead) { #ifdef DEBUG_CHANGE_OPPOSITE if (DEBUG_COND) { std::cout << " cannot changeOpposite due to insufficient free space after columnLeader (seen=" << seen << " columnLeader=" << leadLead.first->getID() << ")\n"; } #endif return false; } // see if merging after leadLead is possible egoGap += columnLeader.first->getVehicleType().getLengthWithGap() + leadLead.second; columnLeader = leadLead; #ifdef DEBUG_CHANGE_OPPOSITE if (DEBUG_COND) { std::cout << " new columnLeader=" << columnLeader.first->getID() << "\n"; } #endif } } } #ifdef DEBUG_CHANGE_OPPOSITE if (DEBUG_COND) { std::cout << " compute time/space to overtake for columnLeader=" << columnLeader.first->getID() << " gap=" << columnLeader.second << "\n"; } #endif SUMOReal timeToOvertake; SUMOReal spaceToOvertake; computeOvertakingTime(vehicle, columnLeader.first, egoGap, timeToOvertake, spaceToOvertake); // check for upcoming stops if (vehicle->nextStopDist() < spaceToOvertake) { #ifdef DEBUG_CHANGE_OPPOSITE if (DEBUG_COND) { std::cout << " cannot changeOpposite due to upcoming stop (dist=" << vehicle->nextStopDist() << " spaceToOvertake=" << spaceToOvertake << ")\n"; } #endif return false; } neighLead = opposite->getOppositeLeader(vehicle, timeToOvertake * opposite->getSpeedLimit() * 2 + spaceToOvertake); #ifdef DEBUG_CHANGE_OPPOSITE if (DEBUG_COND) { std::cout << SIMTIME << " veh=" << vehicle->getID() << " changeOpposite opposite=" << opposite->getID() << " lead=" << Named::getIDSecure(leader.first) << " oncoming=" << Named::getIDSecure(neighLead.first) << " timeToOvertake=" << timeToOvertake << " spaceToOvertake=" << spaceToOvertake << "\n"; } #endif // check for dangerous oncoming leader if (!vehicle->getLaneChangeModel().isOpposite() && neighLead.first != 0) { const MSVehicle* oncoming = neighLead.first; /// XXX what about overtaking multiple vehicles? #ifdef DEBUG_CHANGE_OPPOSITE if (DEBUG_COND) { std::cout << SIMTIME << " timeToOvertake=" << timeToOvertake << " spaceToOvertake=" << spaceToOvertake << " oncomingGap=" << neighLead.second << " leaderGap=" << leader.second << "\n"; } #endif if (neighLead.second - spaceToOvertake - timeToOvertake * oncoming->getSpeed() < 0) { #ifdef DEBUG_CHANGE_OPPOSITE if (DEBUG_COND) { std::cout << " cannot changeOpposite due to dangerous oncoming\n"; } #endif return false; } } // check for sufficient space on the opposite side seen = source->getLength() - vehicle->getPositionOnLane(); if (!vehicle->getLaneChangeModel().isOpposite() && seen < spaceToOvertake) { const std::vector<MSLane*>& bestLaneConts = vehicle->getBestLanesContinuation(); assert(bestLaneConts.size() >= 1); std::vector<MSLane*>::const_iterator it = bestLaneConts.begin() + 1; while (seen < spaceToOvertake && it != bestLaneConts.end()) { if ((*it)->getOpposite() == 0) { break; } // do not overtake past a minor link if (*(it - 1) != 0) { MSLink* link = MSLinkContHelper::getConnectingLink(**(it - 1), **it); if (link == 0 || !link->havePriority() || link->getState() == LINKSTATE_ZIPPER) { break; } } seen += (*it)->getLength(); } if (seen < spaceToOvertake) { #ifdef DEBUG_CHANGE_OPPOSITE if (DEBUG_COND) { std::cout << " cannot changeOpposite due to insufficient space (seen=" << seen << " spaceToOvertake=" << spaceToOvertake << ")\n"; } #endif return false; } #ifdef DEBUG_CHANGE_OPPOSITE if (DEBUG_COND) { std::cout << " seen=" << seen << " spaceToOvertake=" << spaceToOvertake << " timeToOvertake=" << timeToOvertake << "\n"; } #endif } } else { /// XXX compute sensible distance leader = source->getOppositeLeader(vehicle, 200); neighLead = opposite->getOppositeLeader(vehicle, -1); } // compute wish to change std::vector<MSVehicle::LaneQ> preb = vehicle->getBestLanes(); if (isOpposite && leader.first != 0) { MSVehicle::LaneQ& laneQ = preb[preb.size() - 1]; /// XXX compute sensible usable dist laneQ.length -= MIN2(laneQ.length, opposite->getOppositePos(vehicle->getPositionOnLane()) + leader.second / 2); leader.first = 0; // ignore leader } std::pair<MSVehicle* const, SUMOReal> neighFollow = opposite->getOppositeFollower(vehicle); int state = checkChange(direction, opposite, leader, neighLead, neighFollow, preb); bool changingAllowed = (state & LCA_BLOCKED) == 0; // change if the vehicle wants to and is allowed to change if ((state & LCA_WANTS_LANECHANGE) != 0 && changingAllowed) { vehicle->getLaneChangeModel().startLaneChangeManeuver(source, opposite, direction); /// XXX use a dedicated transformation function vehicle->myState.myPos = source->getOppositePos(vehicle->myState.myPos); vehicle->myState.myBackPos = source->getOppositePos(vehicle->myState.myBackPos); /// XXX compute a bette lateral position opposite->forceVehicleInsertion(vehicle, vehicle->getPositionOnLane(), MSMoveReminder::NOTIFICATION_LANE_CHANGE, 0); #ifdef DEBUG_CHANGE_OPPOSITE if (DEBUG_COND) { std::cout << SIMTIME << " changing to opposite veh=" << vehicle->getID() << " dir=" << direction << " opposite=" << Named::getIDSecure(opposite) << " state=" << state << "\n"; } #endif return true; } #ifdef DEBUG_CHANGE_OPPOSITE if (DEBUG_COND) { std::cout << SIMTIME << " not changing to opposite veh=" << vehicle->getID() << " dir=" << direction << " opposite=" << Named::getIDSecure(opposite) << " state=" << state << "\n"; } #endif return false; }
bool MSLaneChanger::change() { // Find change-candidate. If it is on an allowed lane, try to change // to the right (there is a rule in Germany that you have to change // to the right, unless you are overtaking). If change to the right // isn't possible, check if there is a possibility to overtake (on the // left. // If candidate isn't on an allowed lane, changing to an allowed has // priority. myCandi = findCandidate(); MSVehicle* vehicle = veh(myCandi); #ifdef DEBUG_VEHICLE_GUI_SELECTION if (gDebugSelectedVehicle == vehicle->getID()) { int bla = 0; } #endif if (vehicle->getLaneChangeModel().isChangingLanes()) { return continueChange(vehicle, myCandi); } if (!myAllowsChanging || vehicle->getLaneChangeModel().alreadyChanged()) { registerUnchanged(vehicle); return false; } std::pair<MSVehicle* const, SUMOReal> leader = getRealLeader(myCandi); if (myChanger.size() == 1) { if (changeOpposite(leader)) { return true; } registerUnchanged(vehicle); return false; } #ifndef NO_TRACI if (vehicle->isRemoteControlled()) { return false; // !!! temporary; just because it broke, here } #endif vehicle->updateBestLanes(); // needed? for (int i = 0; i < (int) myChanger.size(); ++i) { vehicle->adaptBestLanesOccupation(i, myChanger[i].dens); } const std::vector<MSVehicle::LaneQ>& preb = vehicle->getBestLanes(); // check whether the vehicle wants and is able to change to right lane int state1 = 0; if (mayChange(-1)) { state1 = checkChangeWithinEdge(-1, leader, preb); bool changingAllowed1 = (state1 & LCA_BLOCKED) == 0; // change if the vehicle wants to and is allowed to change if ((state1 & LCA_RIGHT) != 0 && changingAllowed1) { vehicle->getLaneChangeModel().setOwnState(state1); startChange(vehicle, myCandi, -1); return true; } if ((state1 & LCA_RIGHT) != 0 && (state1 & LCA_URGENT) != 0) { (myCandi - 1)->lastBlocked = vehicle; if ((myCandi - 1)->firstBlocked == 0) { (myCandi - 1)->firstBlocked = vehicle; } } } // check whether the vehicle wants and is able to change to left lane int state2 = 0; if (mayChange(1)) { state2 = checkChangeWithinEdge(1, leader, preb); bool changingAllowed2 = (state2 & LCA_BLOCKED) == 0; // change if the vehicle wants to and is allowed to change if ((state2 & LCA_LEFT) != 0 && changingAllowed2) { vehicle->getLaneChangeModel().setOwnState(state2); startChange(vehicle, myCandi, 1); return true; } if ((state2 & LCA_LEFT) != 0 && (state2 & LCA_URGENT) != 0) { (myCandi + 1)->lastBlocked = vehicle; if ((myCandi + 1)->firstBlocked == 0) { (myCandi + 1)->firstBlocked = vehicle; } } } if ((state1 & (LCA_URGENT)) != 0 && (state2 & (LCA_URGENT)) != 0) { // ... wants to go to the left AND to the right // just let them go to the right lane... state2 = 0; } vehicle->getLaneChangeModel().setOwnState(state2 | state1); // check whether the vehicles should be swapped if (myAllowsSwap && ((state1 & (LCA_URGENT)) != 0 || (state2 & (LCA_URGENT)) != 0)) { // get the direction ... ChangerIt target; int direction = 0; if ((state1 & (LCA_URGENT)) != 0) { // ... wants to go right target = myCandi - 1; direction = -1; } if ((state2 & (LCA_URGENT)) != 0) { // ... wants to go left target = myCandi + 1; direction = 1; } MSVehicle* prohibitor = target->lead; if (target->hoppedVeh != 0) { SUMOReal hoppedPos = target->hoppedVeh->getPositionOnLane(); if (prohibitor == 0 || (hoppedPos > vehicle->getPositionOnLane() && prohibitor->getPositionOnLane() > hoppedPos)) { prohibitor = 0;// !!! vehicles should not jump over more than one lanetarget->hoppedVeh; } } if (prohibitor != 0 && ((prohibitor->getLaneChangeModel().getOwnState() & (LCA_URGENT/*|LCA_SPEEDGAIN*/)) != 0 && (prohibitor->getLaneChangeModel().getOwnState() & (LCA_LEFT | LCA_RIGHT)) != (vehicle->getLaneChangeModel().getOwnState() & (LCA_LEFT | LCA_RIGHT)) ) ) { // check for position and speed if (prohibitor->getVehicleType().getLengthWithGap() == vehicle->getVehicleType().getLengthWithGap()) { // ok, may be swapped // remove vehicle to swap with MSLane::VehCont::iterator i = find(target->lane->myTmpVehicles.begin(), target->lane->myTmpVehicles.end(), prohibitor); if (i != target->lane->myTmpVehicles.end()) { assert(*i == prohibitor); target->lane->myTmpVehicles.erase(i); startChange(vehicle, myCandi, direction); startChange(prohibitor, target, -direction); std::swap(vehicle->myState, prohibitor->myState); myCandi->lead = prohibitor; target->lead = vehicle; return true; } } } } if (!changeOpposite(leader)) { registerUnchanged(vehicle); return false; } else { return true; } }
bool MSLaneChanger::change() { // Find change-candidate. If it is on an allowed lane, try to change // to the right (there is a rule in Germany that you have to change // to the right, unless you are overtaking). If change to the right // isn't possible, check if there is a possibility to overtake (on the // left. // If candidate isn't on an allowed lane, changing to an allowed has // priority. myCandi = findCandidate(); MSVehicle* vehicle = veh(myCandi); #ifdef DEBUG_VEHICLE_GUI_SELECTION if (gSelected.isSelected(GLO_VEHICLE, static_cast<const GUIVehicle*>(vehicle)->getGlID())) { int bla = 0; } #endif const std::vector<MSVehicle::LaneQ>& preb = vehicle->getBestLanes(); assert(preb.size() == myChanger.size()); for (int i = 0; i < (int) myChanger.size(); ++i) { ((std::vector<MSVehicle::LaneQ>&) preb)[i].occupation = myChanger[i].dens + preb[i].nextOccupation; } vehicle->getLaneChangeModel().prepareStep(); std::pair<MSVehicle* const, SUMOReal> leader = getRealThisLeader(myCandi); // check whether the vehicle wants and is able to change to right lane int state1 = 0; if (myCandi != myChanger.begin() && (myCandi - 1)->lane->allowsVehicleClass(veh(myCandi)->getVehicleType().getVehicleClass())) { std::pair<MSVehicle* const, SUMOReal> rLead = getRealLeader(myCandi - 1); std::pair<MSVehicle* const, SUMOReal> rFollow = getRealFollower(myCandi - 1); state1 = change2right(leader, rLead, rFollow, preb); if ((state1 & LCA_URGENT) != 0 || (state1 & LCA_SPEEDGAIN) != 0) { state1 |= LCA_RIGHT; } bool changingAllowed1 = (state1 & LCA_BLOCKED) == 0; // change if the vehicle wants to and is allowed to change if ((state1 & LCA_RIGHT) != 0 && changingAllowed1) { #ifndef NO_TRACI // inform lane change model about this change vehicle->getLaneChangeModel().fulfillChangeRequest(MSVehicle::REQUEST_RIGHT); #endif (myCandi - 1)->hoppedVeh = vehicle; (myCandi - 1)->lane->myTmpVehicles.push_front(vehicle); vehicle->leaveLane(MSMoveReminder::NOTIFICATION_LANE_CHANGE); myCandi->lane->leftByLaneChange(vehicle); vehicle->enterLaneAtLaneChange((myCandi - 1)->lane); (myCandi - 1)->lane->enteredByLaneChange(vehicle); vehicle->myLastLaneChangeOffset = 0; vehicle->getLaneChangeModel().changed(); (myCandi - 1)->dens += (myCandi - 1)->hoppedVeh->getVehicleType().getLengthWithGap(); return true; } if ((state1 & LCA_RIGHT) != 0 && (state1 & LCA_URGENT) != 0) { (myCandi - 1)->lastBlocked = vehicle; } } // check whether the vehicle wants and is able to change to left lane int state2 = 0; if ((myCandi + 1) != myChanger.end() && (myCandi + 1)->lane->allowsVehicleClass(veh(myCandi)->getVehicleType().getVehicleClass())) { std::pair<MSVehicle* const, SUMOReal> lLead = getRealLeader(myCandi + 1); std::pair<MSVehicle* const, SUMOReal> lFollow = getRealFollower(myCandi + 1); state2 = change2left(leader, lLead, lFollow, preb); if ((state2 & LCA_URGENT) != 0 || (state2 & LCA_SPEEDGAIN) != 0) { state2 |= LCA_LEFT; } bool changingAllowed2 = (state2 & LCA_BLOCKED) == 0; //vehicle->getLaneChangeModel().setOwnState(state2|state1); // change if the vehicle wants to and is allowed to change if ((state2 & LCA_LEFT) != 0 && changingAllowed2) { #ifndef NO_TRACI // inform lane change model about this change vehicle->getLaneChangeModel().fulfillChangeRequest(MSVehicle::REQUEST_LEFT); #endif (myCandi + 1)->hoppedVeh = veh(myCandi); (myCandi + 1)->lane->myTmpVehicles.push_front(veh(myCandi)); vehicle->leaveLane(MSMoveReminder::NOTIFICATION_LANE_CHANGE); myCandi->lane->leftByLaneChange(vehicle); vehicle->enterLaneAtLaneChange((myCandi + 1)->lane); (myCandi + 1)->lane->enteredByLaneChange(vehicle); vehicle->myLastLaneChangeOffset = 0; vehicle->getLaneChangeModel().changed(); (myCandi + 1)->dens += (myCandi + 1)->hoppedVeh->getVehicleType().getLengthWithGap(); return true; } if ((state2 & LCA_LEFT) != 0 && (state2 & LCA_URGENT) != 0) { (myCandi + 1)->lastBlocked = vehicle; } } vehicle->getLaneChangeModel().setOwnState(state2 | state1); if ((state1 & (LCA_URGENT)) != 0 && (state2 & (LCA_URGENT)) != 0) { // ... wants to go to the left AND to the right // just let them go to the right lane... state2 = 0; vehicle->getLaneChangeModel().setOwnState(state1); } // check whether the vehicles should be swapped if (myAllowsSwap && ((state1 & (LCA_URGENT)) != 0 || (state2 & (LCA_URGENT)) != 0)) { // get the direction ... ChangerIt target; if ((state1 & (LCA_URGENT)) != 0) { // ... wants to go right target = myCandi - 1; } if ((state2 & (LCA_URGENT)) != 0) { // ... wants to go left target = myCandi + 1; } MSVehicle* prohibitor = target->lead; if (target->hoppedVeh != 0) { SUMOReal hoppedPos = target->hoppedVeh->getPositionOnLane(); if (prohibitor == 0 || (hoppedPos > vehicle->getPositionOnLane() && prohibitor->getPositionOnLane() > hoppedPos)) { prohibitor = 0;// !!! vehicles should not jump over more than one lanetarget->hoppedVeh; } } if (prohibitor != 0 && ((prohibitor->getLaneChangeModel().getOwnState() & (LCA_URGENT/*|LCA_SPEEDGAIN*/)) != 0 && (prohibitor->getLaneChangeModel().getOwnState() & (LCA_LEFT | LCA_RIGHT)) != (vehicle->getLaneChangeModel().getOwnState() & (LCA_LEFT | LCA_RIGHT)) ) ) { // check for position and speed if (prohibitor->getVehicleType().getLengthWithGap() - vehicle->getVehicleType().getLengthWithGap() == 0) { // ok, may be swapped // remove vehicle to swap with MSLane::VehCont::iterator i = find(target->lane->myTmpVehicles.begin(), target->lane->myTmpVehicles.end(), prohibitor); if (i != target->lane->myTmpVehicles.end()) { MSVehicle* bla = *i; assert(bla == prohibitor); target->lane->myTmpVehicles.erase(i); // set this vehicle target->hoppedVeh = vehicle; target->lane->myTmpVehicles.push_front(vehicle); myCandi->hoppedVeh = prohibitor; myCandi->lane->myTmpVehicles.push_front(prohibitor); // leave lane and detectors vehicle->leaveLane(MSMoveReminder::NOTIFICATION_LANE_CHANGE); prohibitor->leaveLane(MSMoveReminder::NOTIFICATION_LANE_CHANGE); // patch position and speed SUMOReal p1 = vehicle->getPositionOnLane(); vehicle->myState.myPos = prohibitor->myState.myPos; prohibitor->myState.myPos = p1; p1 = vehicle->getSpeed(); vehicle->myState.mySpeed = prohibitor->myState.mySpeed; prohibitor->myState.mySpeed = p1; // enter lane and detectors vehicle->enterLaneAtLaneChange(target->lane); prohibitor->enterLaneAtLaneChange(myCandi->lane); // mark lane change vehicle->getLaneChangeModel().changed(); vehicle->myLastLaneChangeOffset = 0; prohibitor->getLaneChangeModel().changed(); prohibitor->myLastLaneChangeOffset = 0; (myCandi)->dens += prohibitor->getVehicleType().getLengthWithGap(); (target)->dens += vehicle->getVehicleType().getLengthWithGap(); return true; } } } } // Candidate didn't change lane. myCandi->lane->myTmpVehicles.push_front(veh(myCandi)); vehicle->myLastLaneChangeOffset += DELTA_T; (myCandi)->dens += vehicle->getVehicleType().getLengthWithGap(); return false; }
bool MSLaneChanger::changeOpposite(std::pair<MSVehicle*, SUMOReal> leader) { if (!myChangeToOpposite) { return false; } myCandi = findCandidate(); MSVehicle* vehicle = veh(myCandi); MSLane* source = vehicle->getLane(); if (vehicle->isStopped()) { // stopped vehicles obviously should not change lanes. Usually this is // prevent by appropriate bestLane distances return false; } const bool isOpposite = vehicle->getLaneChangeModel().isOpposite(); if (!isOpposite && leader.first == 0) { // no reason to change unless there is a leader // or we are changing back to the propper direction // XXX also check whether the leader is so far away as to be irrelevant return false; } MSLane* opposite = source->getOpposite(); if (opposite == 0) { return false; } // changing into the opposite direction is always to the left (XXX except for left-hand networkds) int direction = isOpposite ? -1 : 1; std::pair<MSVehicle*, SUMOReal> neighLead((MSVehicle*)0, -1); // preliminary sanity checks for overtaking space SUMOReal timeToOvertake; SUMOReal spaceToOvertake; if (!isOpposite) { assert(leader.first != 0); // find a leader vehicle with sufficient space ahead for merging back const SUMOReal overtakingSpeed = source->getVehicleMaxSpeed(vehicle); // just a guess const SUMOReal mergeBrakeGap = vehicle->getCarFollowModel().brakeGap(overtakingSpeed); std::pair<MSVehicle*, SUMOReal> columnLeader = leader; SUMOReal egoGap = leader.second; bool foundSpaceAhead = false; SUMOReal seen = leader.second + leader.first->getVehicleType().getLengthWithGap(); std::vector<MSLane*> conts = vehicle->getBestLanesContinuation(); while (!foundSpaceAhead) { const SUMOReal requiredSpaceAfterLeader = (columnLeader.first->getCarFollowModel().getSecureGap( columnLeader.first->getSpeed(), overtakingSpeed, vehicle->getCarFollowModel().getMaxDecel()) + vehicle->getVehicleType().getLengthWithGap()); // all leader vehicles on the current laneChanger edge are already moved into MSLane::myTmpVehicles const bool checkTmpVehicles = (&columnLeader.first->getLane()->getEdge() == &source->getEdge()); std::pair<MSVehicle* const, SUMOReal> leadLead = columnLeader.first->getLane()->getLeader( columnLeader.first, columnLeader.first->getPositionOnLane(), conts, requiredSpaceAfterLeader + mergeBrakeGap, checkTmpVehicles); #ifdef DEBUG_CHANGE_OPPOSITE if (DEBUG_COND) { std::cout << " leadLead=" << Named::getIDSecure(leadLead.first) << " gap=" << leadLead.second << "\n"; } #endif if (leadLead.first == 0) { foundSpaceAhead = true; } else { const SUMOReal requiredSpace = (requiredSpaceAfterLeader + vehicle->getCarFollowModel().getSecureGap(overtakingSpeed, leadLead.first->getSpeed(), leadLead.first->getCarFollowModel().getMaxDecel())); if (leadLead.second > requiredSpace) { foundSpaceAhead = true; } else { #ifdef DEBUG_CHANGE_OPPOSITE if (DEBUG_COND) { std::cout << " not enough space after columnLeader=" << columnLeader.first->getID() << " required=" << requiredSpace << "\n"; } #endif seen += MAX2((SUMOReal)0, leadLead.second) + leadLead.first->getVehicleType().getLengthWithGap(); if (seen > OPPOSITE_OVERTAKING_MAX_LOOKAHEAD) { #ifdef DEBUG_CHANGE_OPPOSITE if (DEBUG_COND) { std::cout << " cannot changeOpposite due to insufficient free space after columnLeader (seen=" << seen << " columnLeader=" << columnLeader.first->getID() << ")\n"; } #endif return false; } // see if merging after leadLead is possible egoGap += columnLeader.first->getVehicleType().getLengthWithGap() + leadLead.second; columnLeader = leadLead; #ifdef DEBUG_CHANGE_OPPOSITE if (DEBUG_COND) { std::cout << " new columnLeader=" << columnLeader.first->getID() << "\n"; } #endif } } } #ifdef DEBUG_CHANGE_OPPOSITE if (DEBUG_COND) { std::cout << " compute time/space to overtake for columnLeader=" << columnLeader.first->getID() << " gap=" << columnLeader.second << "\n"; } #endif computeOvertakingTime(vehicle, columnLeader.first, egoGap, timeToOvertake, spaceToOvertake); // check for upcoming stops if (vehicle->nextStopDist() < spaceToOvertake) { #ifdef DEBUG_CHANGE_OPPOSITE if (DEBUG_COND) { std::cout << " cannot changeOpposite due to upcoming stop (dist=" << vehicle->nextStopDist() << " spaceToOvertake=" << spaceToOvertake << ")\n"; } #endif return false; } neighLead = opposite->getOppositeLeader(vehicle, timeToOvertake * opposite->getSpeedLimit() * 2 + spaceToOvertake, true); #ifdef DEBUG_CHANGE_OPPOSITE if (DEBUG_COND) { std::cout << SIMTIME << " veh=" << vehicle->getID() << " changeOpposite opposite=" << opposite->getID() << " lead=" << Named::getIDSecure(leader.first) << " timeToOvertake=" << timeToOvertake << " spaceToOvertake=" << spaceToOvertake << "\n"; } #endif // check for dangerous oncoming leader if (neighLead.first != 0) { const MSVehicle* oncoming = neighLead.first; #ifdef DEBUG_CHANGE_OPPOSITE if (DEBUG_COND) { std::cout << SIMTIME << " oncoming=" << oncoming->getID() << " oncomingGap=" << neighLead.second << " leaderGap=" << leader.second << "\n"; } #endif if (neighLead.second - spaceToOvertake - timeToOvertake * oncoming->getSpeed() < 0) { #ifdef DEBUG_CHANGE_OPPOSITE if (DEBUG_COND) { std::cout << " cannot changeOpposite due to dangerous oncoming\n"; } #endif return false; } } } else { timeToOvertake = -1; // look forward as far as possible spaceToOvertake = std::numeric_limits<SUMOReal>::max(); leader = source->getOppositeLeader(vehicle, OPPOSITE_OVERTAKING_ONCOMING_LOOKAHEAD, true); // -1 will use getMaximumBrakeDist() as look-ahead distance neighLead = opposite->getOppositeLeader(vehicle, -1, false); } // compute remaining space on the opposite side // 1. the part that remains on the current lane SUMOReal usableDist = isOpposite ? vehicle->getPositionOnLane() : source->getLength() - vehicle->getPositionOnLane(); if (usableDist < spaceToOvertake) { // look forward along the next lanes const std::vector<MSLane*>& bestLaneConts = vehicle->getBestLanesContinuation(); assert(bestLaneConts.size() >= 1); std::vector<MSLane*>::const_iterator it = bestLaneConts.begin() + 1; while (usableDist < spaceToOvertake && it != bestLaneConts.end()) { #ifdef DEBUG_CHANGE_OPPOSITE if (DEBUG_COND) { std::cout << " usableDist=" << usableDist << " opposite=" << Named::getIDSecure((*it)->getOpposite()) << "\n"; } #endif if ((*it)->getOpposite() == 0) { // opposite lane ends break; } // do not overtake past a minor link or turn if (*(it - 1) != 0) { MSLink* link = MSLinkContHelper::getConnectingLink(**(it - 1), **it); if (link == 0 || !link->havePriority() || link->getState() == LINKSTATE_ZIPPER || link->getDirection() != LINKDIR_STRAIGHT) { break; } } usableDist += (*it)->getLength(); ++it; } } if (!isOpposite && usableDist < spaceToOvertake) { #ifdef DEBUG_CHANGE_OPPOSITE if (DEBUG_COND) { std::cout << " cannot changeOpposite due to insufficient space (seen=" << usableDist << " spaceToOvertake=" << spaceToOvertake << ")\n"; } #endif return false; } #ifdef DEBUG_CHANGE_OPPOSITE if (DEBUG_COND) { std::cout << " usableDist=" << usableDist << " spaceToOvertake=" << spaceToOvertake << " timeToOvertake=" << timeToOvertake << "\n"; } #endif // compute wish to change std::vector<MSVehicle::LaneQ> preb = vehicle->getBestLanes(); if (isOpposite) { // compute the remaining distance that can be drive on the opposite side // this value will put into LaneQ.length of the leftmost lane // @note: length counts from the start of the current lane // @note: see MSLCM_LC2013::_wantsChange @1092 (isOpposite() MSVehicle::LaneQ& laneQ = preb[preb.size() - 1]; // position on the target lane const SUMOReal forwardPos = source->getOppositePos(vehicle->getPositionOnLane()); // consider usableDist (due to minor links or end of opposite lanes) laneQ.length = MIN2(laneQ.length, usableDist + forwardPos); // consider upcoming stops laneQ.length = MIN2(laneQ.length, vehicle->nextStopDist() + forwardPos); // consider oncoming leaders if (leader.first != 0) { laneQ.length = MIN2(laneQ.length, leader.second / 2 + forwardPos); #ifdef DEBUG_CHANGE_OPPOSITE if (DEBUG_COND) { std::cout << SIMTIME << " found oncoming leader=" << leader.first->getID() << " gap=" << leader.second << "\n"; } #endif leader.first = 0; // ignore leader after this } #ifdef DEBUG_CHANGE_OPPOSITE if (DEBUG_COND) { std::cout << SIMTIME << " veh=" << vehicle->getID() << " remaining dist=" << laneQ.length - forwardPos << " forwardPos=" << forwardPos << " laneQ.length=" << laneQ.length << "\n"; } #endif } std::pair<MSVehicle* const, SUMOReal> neighFollow = opposite->getOppositeFollower(vehicle); int state = checkChange(direction, opposite, leader, neighLead, neighFollow, preb); bool changingAllowed = (state & LCA_BLOCKED) == 0; // change if the vehicle wants to and is allowed to change if ((state & LCA_WANTS_LANECHANGE) != 0 && changingAllowed // do not change to the opposite direction for cooperative reasons && (isOpposite || (state & LCA_COOPERATIVE) == 0)) { vehicle->getLaneChangeModel().startLaneChangeManeuver(source, opposite, direction); /// XXX use a dedicated transformation function vehicle->myState.myPos = source->getOppositePos(vehicle->myState.myPos); /// XXX compute a better lateral position opposite->forceVehicleInsertion(vehicle, vehicle->getPositionOnLane(), MSMoveReminder::NOTIFICATION_LANE_CHANGE, 0); if (!isOpposite) { vehicle->myState.myBackPos = source->getOppositePos(vehicle->myState.myBackPos); } #ifdef DEBUG_CHANGE_OPPOSITE if (DEBUG_COND) { std::cout << SIMTIME << " changing to opposite veh=" << vehicle->getID() << " dir=" << direction << " opposite=" << Named::getIDSecure(opposite) << " state=" << state << "\n"; } #endif return true; } #ifdef DEBUG_CHANGE_OPPOSITE if (DEBUG_COND) { std::cout << SIMTIME << " not changing to opposite veh=" << vehicle->getID() << " dir=" << direction << " opposite=" << Named::getIDSecure(opposite) << " state=" << toString((LaneChangeAction)state) << "\n"; } #endif return false; }