// =========================================================================== // method definitions // =========================================================================== GUILaneWrapper::GUILaneWrapper(GUIGlObjectStorage &idStorage, MSLane &lane, const Position2DVector &shape) throw() : GUIGlObject(idStorage, "lane:"+lane.getID()), myLane(lane), myShape(shape) { SUMOReal x1 = shape[0].x(); SUMOReal y1 = shape[0].y(); SUMOReal x2 = shape[-1].x(); SUMOReal y2 = shape[-1].y(); SUMOReal length = myLane.getLength(); // also the virtual length is set in here myVisLength = sqrt((x1-x2)*(x1-x2) + (y1-y2)*(y1-y2)); // check maximum speed if (myAllMaxSpeed<lane.getMaxSpeed()) { myAllMaxSpeed = lane.getMaxSpeed(); } // myShapeRotations.reserve(myShape.size()-1); myShapeLengths.reserve(myShape.size()-1); int e = (int) myShape.size() - 1; for (int i=0; i<e; ++i) { const Position2D &f = myShape[i]; const Position2D &s = myShape[i+1]; myShapeLengths.push_back(f.distanceTo(s)); myShapeRotations.push_back((SUMOReal) atan2((s.x()-f.x()), (f.y()-s.y()))*(SUMOReal) 180.0/(SUMOReal) PI); } }
void MSFullExport::writeLane(OutputDevice& of, const MSLane& lane) { of.openTag("lane").writeAttr("id", lane.getID()).writeAttr("CO", lane.getCOEmissions()).writeAttr("CO2", lane.getCO2Emissions()); of.writeAttr("NOx", lane.getNOxEmissions()).writeAttr("PMx", lane.getPMxEmissions()).writeAttr("HC", lane.getHCEmissions()); of.writeAttr("noise", lane.getHarmonoise_NoiseEmissions()).writeAttr("fuel", lane.getFuelConsumption()).writeAttr("maxspeed", lane.getSpeedLimit()); of.writeAttr("meanspeed", lane.getMeanSpeed() * 3.6).writeAttr("occupancy", lane.getNettoOccupancy()).writeAttr("vehicle_count", lane.getVehicleNumber()); of.closeTag(); }
// =========================================================================== // method definitions // =========================================================================== MSCalibrator::MSCalibrator(const std::string& id, const MSEdge* const edge, MSLane* lane, const double pos, const std::string& aXMLFilename, const std::string& outputFilename, const SUMOTime freq, const double length, const MSRouteProbe* probe, bool addLaneMeanData) : MSTrigger(id), MSRouteHandler(aXMLFilename, true), myEdge(edge), myLane(lane), myPos(pos), myProbe(probe), myEdgeMeanData(nullptr, length, false, nullptr), myCurrentStateInterval(myIntervals.begin()), myOutput(nullptr), myFrequency(freq), myRemoved(0), myInserted(0), myClearedInJam(0), mySpeedIsDefault(true), myDidSpeedAdaption(false), myDidInit(false), myDefaultSpeed(myLane == nullptr ? myEdge->getSpeedLimit() : myLane->getSpeedLimit()), myHaveWarnedAboutClearingJam(false), myAmActive(false) { if (outputFilename != "") { myOutput = &OutputDevice::getDevice(outputFilename); myOutput->writeXMLHeader("calibratorstats", "calibratorstats_file.xsd"); } if (aXMLFilename != "") { XMLSubSys::runParser(*this, aXMLFilename); if (!myDidInit) { init(); } } if (addLaneMeanData) { // disabled for METriggeredCalibrator for (int i = 0; i < (int)myEdge->getLanes().size(); ++i) { MSLane* lane = myEdge->getLanes()[i]; if (myLane == nullptr || myLane == lane) { //std::cout << " cali=" << getID() << " myLane=" << Named::getIDSecure(myLane) << " checkLane=" << i << "\n"; MSMeanData_Net::MSLaneMeanDataValues* laneData = new MSMeanData_Net::MSLaneMeanDataValues(lane, lane->getLength(), true, nullptr); laneData->setDescription("meandata_calibrator_" + lane->getID()); LeftoverReminders.push_back(laneData); myLaneMeanData.push_back(laneData); VehicleRemover* remover = new VehicleRemover(lane, (int)i, this); LeftoverReminders.push_back(remover); myVehicleRemovers.push_back(remover); } } } }
void MSFullExport::writeLane(OutputDevice& of, const MSLane& lane) { of.openTag("lane") << " id=\"" << lane.getID() << "\" co=\"" << lane.getHBEFA_COEmissions() << "\" co2=\"" << lane.getHBEFA_CO2Emissions() << "\" nox=\"" << lane.getHBEFA_NOxEmissions() << "\" pmx=\"" << lane.getHBEFA_PMxEmissions() << "\" hc=\"" << lane.getHBEFA_HCEmissions() << "\" noise=\"" << lane.getHarmonoise_NoiseEmissions() << "\" fuel=\"" << lane.getHBEFA_FuelConsumption() << "\" maxspeed=\"" << lane.getSpeedLimit() * 3.6 << "\" meanspeed=\"" << lane.getMeanSpeed() * 3.6 << "\" occupancy=\"" << lane.getOccupancy() << "\" vehicle_count=\"" << lane.getVehicleNumber() << "\""; of.closeTag(); }
void MSActuatedTrafficLightLogic::init(NLDetectorBuilder& nb) { MSTrafficLightLogic::init(nb); assert(myLanes.size() > 0); // change values for setting the loops and lanestate-detectors, here //SUMOTime inductLoopInterval = 1; // LaneVectorVector::const_iterator i2; LaneVector::const_iterator i; // build the induct loops double maxDetectorGap = 0; for (i2 = myLanes.begin(); i2 != myLanes.end(); ++i2) { const LaneVector& lanes = *i2; for (i = lanes.begin(); i != lanes.end(); i++) { MSLane* lane = (*i); if (noVehicles(lane->getPermissions())) { // do not build detectors on green verges or sidewalks continue; } double length = lane->getLength(); double speed = lane->getSpeedLimit(); double inductLoopPosition = myDetectorGap * speed; // check whether the lane is long enough double ilpos = length - inductLoopPosition; if (ilpos < 0) { ilpos = 0; } // Build the induct loop and set it into the container std::string id = "TLS" + myID + "_" + myProgramID + "_InductLoopOn_" + lane->getID(); if (myInductLoops.find(lane) == myInductLoops.end()) { myInductLoops[lane] = nb.createInductLoop(id, lane, ilpos, myVehicleTypes, myShowDetectors); MSNet::getInstance()->getDetectorControl().add(SUMO_TAG_INDUCTION_LOOP, myInductLoops[lane], myFile, myFreq); } maxDetectorGap = MAX2(maxDetectorGap, length - ilpos); } } // warn if the minGap is insufficient to clear vehicles between stop line and detector SUMOTime minMinDur = getMinimumMinDuration(); if (floor(floor(maxDetectorGap / DEFAULT_LENGTH_WITH_GAP) * myPassingTime) > STEPS2TIME(minMinDur)) { WRITE_WARNING("At actuated tlLogic '" + getID() + "', minDur " + time2string(minMinDur) + " is too short for a detector gap of " + toString(maxDetectorGap) + "m."); } }
// =========================================================================== // method definitions // =========================================================================== GUILaneWrapper::GUILaneWrapper(MSLane& lane, const PositionVector& shape, unsigned int index) : GUIGlObject(GLO_LANE, lane.getID()), myLane(lane), myShape(shape), myIndex(index) #ifdef HAVE_OSG , myGeom(0) #endif { myShapeRotations.reserve(myShape.size() - 1); myShapeLengths.reserve(myShape.size() - 1); int e = (int) myShape.size() - 1; for (int i = 0; i < e; ++i) { const Position& f = myShape[i]; const Position& s = myShape[i + 1]; myShapeLengths.push_back(f.distanceTo2D(s)); myShapeRotations.push_back(RAD2DEG(atan2(s.x() - f.x(), f.y() - s.y()))); } // myHalfLaneWidth = (SUMOReal)(myLane.getWidth() / 2.); myQuarterLaneWidth = (SUMOReal)(myLane.getWidth() / 4.); }
void MSQueueExport::writeLane(OutputDevice& of, const MSLane& lane) { // maximum of all vehicle waiting times SUMOReal queueing_time = 0.0; // back of last stopped vehicle (XXX does not check for continuous queue) SUMOReal queueing_length = 0.0; // back of last slow vehicle (XXX does not check for continuous queue) SUMOReal queueing_length2 = 0.0; const SUMOReal threshold_velocity = 5 / 3.6; // slow if (!lane.empty()) { for (MSLane::VehCont::const_iterator it_veh = lane.myVehicles.begin(); it_veh != lane.myVehicles.end(); ++it_veh) { const MSVehicle& veh = **it_veh; if (!veh.isOnRoad()) { continue; } if (veh.getWaitingSeconds() > 0) { queueing_time = MAX2(veh.getWaitingSeconds(), queueing_time); const SUMOReal veh_back_to_lane_end = (lane.getLength() - veh.getPositionOnLane()) + veh.getVehicleType().getLength(); queueing_length = MAX2(veh_back_to_lane_end, queueing_length); } //Experimental if (veh.getSpeed() < (threshold_velocity) && (veh.getPositionOnLane() > (veh.getLane()->getLength()) * 0.25)) { const SUMOReal veh_back_to_lane_end = (lane.getLength() - veh.getPositionOnLane()) + veh.getVehicleType().getLength(); queueing_length2 = MAX2(veh_back_to_lane_end, queueing_length2); } } } //Output if (queueing_length > 1 || queueing_length2 > 1) { of.openTag("lane").writeAttr("id", lane.getID()).writeAttr("queueing_time", queueing_time).writeAttr("queueing_length", queueing_length); of.writeAttr("queueing_length_experimental", queueing_length2).closeTag(); } }
void NLHandler::addConnection(const SUMOSAXAttributes& attrs) { bool ok = true; std::string fromID = attrs.get<std::string>(SUMO_ATTR_FROM, 0, ok); if (!MSGlobals::gUsingInternalLanes && fromID[0] == ':') { return; } try { bool ok = true; const std::string toID = attrs.get<std::string>(SUMO_ATTR_TO, 0, ok); const int fromLaneIdx = attrs.get<int>(SUMO_ATTR_FROM_LANE, 0, ok); const int toLaneIdx = attrs.get<int>(SUMO_ATTR_TO_LANE, 0, ok); LinkDirection dir = parseLinkDir(attrs.get<std::string>(SUMO_ATTR_DIR, 0, ok)); LinkState state = parseLinkState(attrs.get<std::string>(SUMO_ATTR_STATE, 0, ok)); std::string tlID = attrs.getOpt<std::string>(SUMO_ATTR_TLID, 0, ok, ""); #ifdef HAVE_INTERNAL_LANES std::string viaID = attrs.getOpt<std::string>(SUMO_ATTR_VIA, 0, ok, ""); #endif MSEdge* from = MSEdge::dictionary(fromID); if (from == 0) { WRITE_ERROR("Unknown from-edge '" + fromID + "' in connection"); return; } MSEdge* to = MSEdge::dictionary(toID); if (to == 0) { WRITE_ERROR("Unknown to-edge '" + toID + "' in connection"); return; } if (fromLaneIdx < 0 || static_cast<unsigned int>(fromLaneIdx) >= from->getLanes().size() || toLaneIdx < 0 || static_cast<unsigned int>(toLaneIdx) >= to->getLanes().size()) { WRITE_ERROR("Invalid lane index in connection from '" + from->getID() + "' to '" + to->getID() + "'."); return; } MSLane* fromLane = from->getLanes()[fromLaneIdx]; MSLane* toLane = to->getLanes()[toLaneIdx]; assert(fromLane); assert(toLane); int tlLinkIdx = -1; if (tlID != "") { tlLinkIdx = attrs.get<int>(SUMO_ATTR_TLLINKINDEX, 0, ok); // make sure that the index is in range MSTrafficLightLogic* logic = myJunctionControlBuilder.getTLLogic(tlID).getActive(); if (tlLinkIdx < 0 || tlLinkIdx >= (int)logic->getCurrentPhaseDef().getState().size()) { WRITE_ERROR("Invalid " + toString(SUMO_ATTR_TLLINKINDEX) + " '" + toString(tlLinkIdx) + "' in connection controlled by '" + tlID + "'"); return; } if (!ok) { return; } } SUMOReal length = fromLane->getShape()[-1].distanceTo(toLane->getShape()[0]); MSLink* link = 0; // build the link #ifdef HAVE_INTERNAL_LANES MSLane* via = 0; if (viaID != "" && MSGlobals::gUsingInternalLanes) { via = MSLane::dictionary(viaID); if (via == 0) { WRITE_ERROR("An unknown lane ('" + viaID + "') should be set as a via-lane for lane '" + toLane->getID() + "'."); return; } length = via->getLength(); } link = new MSLink(toLane, via, dir, state, length); if (via != 0) { via->addIncomingLane(fromLane, link); } else { toLane->addIncomingLane(fromLane, link); } #else link = new MSLink(toLane, dir, state, length); toLane->addIncomingLane(fromLane, link); #endif toLane->addApproachingLane(fromLane); // if a traffic light is responsible for it, inform the traffic light // check whether this link is controlled by a traffic light if (tlID != "") { myJunctionControlBuilder.getTLLogic(tlID).addLink(link, fromLane, tlLinkIdx); } // add the link fromLane->addLink(link); } catch (InvalidArgument& e) { WRITE_ERROR(e.what()); } }
void Person::moveToXY(const std::string& personID, const std::string& edgeID, const double x, const double y, double angle, const int keepRouteFlag) { MSPerson* p = getPerson(personID); bool keepRoute = (keepRouteFlag == 1); bool mayLeaveNetwork = (keepRouteFlag == 2); Position pos(x, y); #ifdef DEBUG_MOVEXY const double origAngle = angle; #endif // angle must be in [0,360] because it will be compared against those returned by naviDegree() // angle set to INVALID_DOUBLE_VALUE is ignored in the evaluated and later set to the angle of the matched lane if (angle != INVALID_DOUBLE_VALUE) { while (angle >= 360.) { angle -= 360.; } while (angle < 0.) { angle += 360.; } } Position currentPos = p->getPosition(); #ifdef DEBUG_MOVEXY std::cout << std::endl << "begin person " << p->getID() << " lanePos:" << p->getEdgePos() << " edge:" << Named::getIDSecure(p->getEdge()) << "\n"; std::cout << " want pos:" << pos << " edgeID:" << edgeID << " origAngle:" << origAngle << " angle:" << angle << " keepRoute:" << keepRoute << std::endl; #endif ConstMSEdgeVector edges; MSLane* lane = nullptr; double lanePos; double lanePosLat = 0; double bestDistance = std::numeric_limits<double>::max(); int routeOffset = 0; bool found = false; double maxRouteDistance = 100; ConstMSEdgeVector ev; ev.push_back(p->getEdge()); int routeIndex = 0; MSLane* currentLane = const_cast<MSLane*>(getSidewalk<MSEdge, MSLane>(p->getEdge())); switch (p->getStageType(0)) { case MSTransportable::MOVING_WITHOUT_VEHICLE: { MSPerson::MSPersonStage_Walking* s = dynamic_cast<MSPerson::MSPersonStage_Walking*>(p->getCurrentStage()); assert(s != 0); ev = s->getEdges(); routeIndex = (int)(s->getRouteStep() - s->getRoute().begin()); } break; default: break; } if (keepRoute) { // case a): vehicle is on its earlier route // we additionally assume it is moving forward (SUMO-limit); // note that the route ("edges") is not changed in this case found = Helper::moveToXYMap_matchingRoutePosition(pos, edgeID, ev, routeIndex, bestDistance, &lane, lanePos, routeOffset); } else { double speed = pos.distanceTo2D(p->getPosition()); // !!!veh->getSpeed(); found = Helper::moveToXYMap(pos, maxRouteDistance, mayLeaveNetwork, edgeID, angle, speed, ev, routeIndex, currentLane, p->getEdgePos(), true, bestDistance, &lane, lanePos, routeOffset, edges); } if ((found && bestDistance <= maxRouteDistance) || mayLeaveNetwork) { // compute lateral offset if (found) { const double perpDist = lane->getShape().distance2D(pos, false); if (perpDist != GeomHelper::INVALID_OFFSET) { lanePosLat = perpDist; if (!mayLeaveNetwork) { lanePosLat = MIN2(lanePosLat, 0.5 * (lane->getWidth() + p->getVehicleType().getWidth())); } // figure out whether the offset is to the left or to the right PositionVector tmp = lane->getShape(); try { tmp.move2side(-lanePosLat); // moved to left } catch (ProcessError&) { WRITE_WARNING("Could not determine position on lane '" + lane->getID() + " at lateral position " + toString(-lanePosLat) + "."); } //std::cout << " lane=" << lane->getID() << " posLat=" << lanePosLat << " shape=" << lane->getShape() << " tmp=" << tmp << " tmpDist=" << tmp.distance2D(pos) << "\n"; if (tmp.distance2D(pos) > perpDist) { lanePosLat = -lanePosLat; } } } if (found && !mayLeaveNetwork && MSGlobals::gLateralResolution < 0) { // mapped position may differ from pos pos = lane->geometryPositionAtOffset(lanePos, -lanePosLat); } assert((found && lane != 0) || (!found && lane == 0)); if (angle == INVALID_DOUBLE_VALUE) { if (lane != nullptr) { angle = GeomHelper::naviDegree(lane->getShape().rotationAtOffset(lanePos)); } else { // compute angle outside road network from old and new position angle = GeomHelper::naviDegree(p->getPosition().angleTo2D(pos)); } } switch (p->getStageType(0)) { case MSTransportable::MOVING_WITHOUT_VEHICLE: { Helper::setRemoteControlled(p, pos, lane, lanePos, lanePosLat, angle, routeOffset, edges, MSNet::getInstance()->getCurrentTimeStep()); break; } default: throw TraCIException("Command moveToXY is not supported for person '" + personID + "' while " + p->getCurrentStageDescription() + "."); } } else { if (lane == nullptr) { throw TraCIException("Could not map person '" + personID + "' no road found within " + toString(maxRouteDistance) + "m."); } else { throw TraCIException("Could not map person '" + personID + "' distance to road is " + toString(bestDistance) + "."); } } }
void MSQueueExport::writeLane(OutputDevice& of, const MSLane& lane) { //Fahrzeug mit der höchsten Wartezeit //Fahrzeug am Ende des Rückstaus double queueing_time = 0.0; double queueing_length = 0.0; double queueing_length2 = 0.0; if (lane.getVehicleNumber() != 0) { for (std::vector<MSVehicle*>::const_iterator veh = lane.myVehBuffer.begin(); veh != lane.myVehBuffer.end(); ++veh) { const MSVehicle& veh_tmp = **veh; if (veh_tmp.isOnRoad()) { if (veh_tmp.getWaitingSeconds() > 0) { if (veh_tmp.getWaitingSeconds() > queueing_time) { queueing_time = veh_tmp.getWaitingSeconds(); } double tmp_length = (lane.getLength() - veh_tmp.getPositionOnLane()) + veh_tmp.getVehicleType().getLengthWithGap(); if (tmp_length > queueing_length) { queueing_length = tmp_length; } } } } for (MSLane::VehCont::const_iterator veh = lane.myVehicles.begin(); veh != lane.myVehicles.end(); ++veh) { const MSVehicle& veh_tmp = **veh; if (veh_tmp.isOnRoad()) { if (veh_tmp.getWaitingSeconds() > 0) { if (veh_tmp.getWaitingSeconds() > queueing_time) { queueing_time = veh_tmp.getWaitingSeconds(); } double tmp_length = (lane.getLength() - veh_tmp.getPositionOnLane()) + veh_tmp.getVehicleType().getLengthWithGap(); if (tmp_length > queueing_length) { queueing_length = tmp_length; } } } } //Experimental double tmp_length2 = 0.0; for (MSLane::VehCont::const_iterator veh = lane.myVehicles.begin(); veh != lane.myVehicles.end(); ++veh) { //wenn Fahrzeug langsamer als 5 km/h fährt = Rückstau double threshold_velocity = 5 / 3.6; const MSVehicle& veh_tmp = **veh; if (veh_tmp.isOnRoad()) { if (veh_tmp.getSpeed() < (threshold_velocity) && (veh_tmp.getPositionOnLane() > (veh_tmp.getLane()->getLength()) * 0.25)) { tmp_length2 = (lane.getLength() - veh_tmp.getPositionOnLane()) + veh_tmp.getVehicleType().getLengthWithGap(); } if (tmp_length2 > queueing_length2) { queueing_length2 = tmp_length2; } } } } //Output if (queueing_length > 1 || queueing_length2 > 1) { of.openTag("lane") << " id=\"" << lane.getID() << "\""; of << " queueing_time=\"" << queueing_time << "\" queueing_length=\"" << queueing_length << "\" queueing_length_experimental=\"" << queueing_length2 << "\""; of.closeTag(true); } }
void MSRailSignal::collectConflictLinks(MSLane* toLane, double length, std::vector<MSLane*>& backwardBlock, std::vector<MSLink*>& conflictLinks, LaneSet& visited, bool checkFoes) { while (toLane != nullptr) { //std::cout << "collectConflictLinks " << getID() << " toLane=" << toLane->getID() << " length=" << length // << " backward=" << toString(backwardBlock) // << " conflictLinks=" << conflictLinks.size() // << " visited=" << visited.size() // << " checkFoes=" << checkFoes // << "\n"; const auto& incomingLaneInfos = toLane->getIncomingLanes(); MSLane* orig = toLane; toLane = nullptr; for (const auto& ili : incomingLaneInfos) { if (ili.viaLink->getDirection() == LINKDIR_TURN) { continue; } if (visited.count(ili.lane) != 0) { continue; } if (ili.viaLink->getTLLogic() != nullptr) { conflictLinks.push_back(ili.viaLink); continue; } backwardBlock.push_back(ili.lane); visited.insert(ili.lane); length += orig->getLength(); if (length > MAX_BLOCK_LENGTH) { if (myNumWarnings < MAX_SIGNAL_WARNINGS) { WRITE_WARNING("incoming conflict block after rail signal junction '" + getID() + "' exceeds maximum length (stopped searching after lane '" + orig->getID() + "' (length=" + toString(length) + "m)."); } myNumWarnings++; return; } if (toLane == nullptr) { toLane = ili.lane; } else { collectConflictLinks(ili.lane, length, backwardBlock, conflictLinks, visited, false); } } if (checkFoes && orig->isInternal()) { // check for crossed tracks MSLink* link = orig->getIncomingLanes().front().viaLink; if (link->getDirection() != LINKDIR_TURN) { for (const MSLane* foeConst : link->getFoeLanes()) { MSLane* foe = const_cast<MSLane*>(foeConst); if (visited.count(foe) == 0) { backwardBlock.push_back(foe); visited.insert(foe); collectConflictLinks(foe, length, backwardBlock, conflictLinks, visited, 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; }
void NLDetectorBuilder::buildE2Detector(const std::string& id, std::vector<MSLane*> lanes, double pos, double endPos, const std::string& device, SUMOTime frequency, SUMOTime haltingTimeThreshold, double haltingSpeedThreshold, double jamDistThreshold, const std::string& vTypes, bool friendlyPos, bool showDetector, MSTLLogicControl::TLSLogicVariants* tlls, MSLane* toLane) { bool tlsGiven = tlls != 0; bool toLaneGiven = toLane != 0; assert(pos != std::numeric_limits<double>::max()); assert(endPos != std::numeric_limits<double>::max()); assert(lanes.size() != 0); MSLane* firstLane = lanes[0]; MSLane* lastLane = lanes[lanes.size() - 1]; // Check positioning if (pos >= firstLane->getLength() || (pos < 0 && -pos > firstLane->getLength())) { std::stringstream ss; ss << "The given position (=" << pos << ") for detector '" << id << "' does not lie on the given lane '" << firstLane->getID() << "' with length " << firstLane->getLength(); if (friendlyPos) { double newPos = pos > 0 ? firstLane->getLength() - POSITION_EPS : 0.; ss << " (adjusting to new position " << newPos; WRITE_WARNING(ss.str()); pos = newPos; } else { ss << " (0 <= pos < lane->getLength() is required)"; throw InvalidArgument(ss.str()); } } if (endPos > lastLane->getLength() || (endPos <= 0 && -endPos >= lastLane->getLength())) { std::stringstream ss; ss << "The given end position (=" << endPos << ") for detector '" << id << "' does not lie on the given lane '" << lastLane->getID() << "' with length " << lastLane->getLength(); if (friendlyPos) { double newEndPos = endPos > 0 ? lastLane->getLength() : POSITION_EPS; ss << " (adjusting to new position " << newEndPos; WRITE_WARNING(ss.str()); pos = newEndPos; } else { ss << " (0 <= pos < lane->getLength() is required)"; throw InvalidArgument(ss.str()); } } MSE2Collector* det = 0; if (tlsGiven) { // Detector connected to TLS det = createE2Detector(id, DU_USER_DEFINED, lanes, pos, endPos, haltingTimeThreshold, haltingSpeedThreshold, jamDistThreshold, vTypes, showDetector); myNet.getDetectorControl().add(SUMO_TAG_LANE_AREA_DETECTOR, det); // add the file output (XXX: Where's the corresponding delete?) if (toLaneGiven) { // Detector also associated to specific link MSLane* lastLane = det->getLastLane(); MSLink* link = MSLinkContHelper::getConnectingLink(*lastLane, *toLane); if (link == 0) { throw InvalidArgument( "The detector '" + id + "' cannot be build as no connection between lanes '" + lastLane->getID() + "' and '" + toLane->getID() + "' exists."); } new Command_SaveTLCoupledLaneDet(*tlls, det, myNet.getCurrentTimeStep(), OutputDevice::getDevice(device), link); } else { // detector for tls but without specific link new Command_SaveTLCoupledDet(*tlls, det, myNet.getCurrentTimeStep(), OutputDevice::getDevice(device)); } } else { // User specified detector for xml-output checkSampleInterval(frequency, SUMO_TAG_E2DETECTOR, id); det = createE2Detector(id, DU_USER_DEFINED, lanes, pos, endPos, haltingTimeThreshold, haltingSpeedThreshold, jamDistThreshold, vTypes, showDetector); myNet.getDetectorControl().add(SUMO_TAG_LANE_AREA_DETECTOR, det, device, frequency); } }
void MSAgentbasedTrafficLightLogic::init(NLDetectorBuilder &nb) throw(ProcessError) { SUMOReal det_offset = TplConvert<char>::_2SUMOReal(myParameter.find("detector_offset")->second.c_str()); LaneVectorVector::const_iterator i2; LaneVector::const_iterator i; // build the detectors for (i2=myLanes.begin(); i2!=myLanes.end(); ++i2) { const LaneVector &lanes = *i2; for (i=lanes.begin(); i!=lanes.end(); i++) { MSLane *lane = (*i); // Build the lane state detetcor and set it into the container std::string id = "TL_" + myID + "_" + myProgramID + "_E2OverLanesDetectorStartingAt_" + lane->getID(); if (myE2Detectors.find(lane)==myE2Detectors.end()) { MS_E2_ZS_CollectorOverLanes* det = nb.buildMultiLaneE2Det(id, DU_TL_CONTROL, lane, 0, det_offset, /*haltingTimeThreshold!!!*/ 1, /*haltingSpeedThreshold!!!*/(SUMOReal)(5.0/3.6), /*jamDistThreshold!!!*/ 10); myE2Detectors[lane] = det; } } } // initialise the duration unsigned int tCycleIst = 0; // the actual cycletime unsigned int tCycleMin = 0; // the minimum cycle time unsigned int tDeltaGreen = 0; // the difference between the actual cycle time and the required cycle time /// Calculation of starting values for (unsigned int actStep = 0; actStep!=myPhases.size(); actStep++) { unsigned int dur = (unsigned int) myPhases[actStep]->duration; tCycleIst = tCycleIst + dur; if (myPhases[actStep]->isGreenPhase()) { unsigned int mindur = (unsigned int) myPhases[actStep]->minDuration; tCycleMin = tCycleMin + mindur; } else { tCycleMin = tCycleMin + dur; } } if (tCycle < tCycleMin) { tCycle = tCycleMin; } if (tCycleIst < tCycle) { tDeltaGreen = tCycle - tCycleIst; lengthenCycleTime(tDeltaGreen); } if (tCycleIst > tCycle) { tDeltaGreen = tCycleIst - tCycle; cutCycleTime(tDeltaGreen); } }
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; }