예제 #1
0
파일: MSEdge.cpp 프로젝트: planetsumo/sumo
void MSEdge::recalcCache() {
    if (myLanes->empty()) {
        return;
    }
    myLength = myLanes->front()->getLength();
    myEmptyTraveltime = myLength / MAX2(getSpeedLimit(), NUMERICAL_EPS);

    if (MSGlobals::gMesoTLSPenalty > 0 || MSGlobals::gMesoMinorPenalty > 0) {
        // add tls penalties to the minimum travel time
        SUMOTime minPenalty = -1;
        for (std::vector<MSLane*>::const_iterator i = myLanes->begin(); i != myLanes->end(); ++i) {
            MSLane* l = *i;
            const MSLinkCont& lc = l->getLinkCont();
            for (MSLinkCont::const_iterator j = lc.begin(); j != lc.end(); ++j) {
                MSLink* link = *j;
                SUMOTime linkPenalty = link->getMesoTLSPenalty() + (link->havePriority() ? 0 : MSGlobals::gMesoMinorPenalty);
                if (minPenalty == -1) {
                    minPenalty = linkPenalty;
                } else {
                    minPenalty = MIN2(minPenalty, linkPenalty);
                }
            }
        }
        if (minPenalty > 0) {
            myEmptyTraveltime += STEPS2TIME(minPenalty);
        }
    }
}
예제 #2
0
const MSEdge*
MSEdge::getInternalFollowingEdge(const MSEdge* followerAfterInternal) const {
    //@todo to be optimized
    for (std::vector<MSLane*>::const_iterator i = myLanes->begin(); i != myLanes->end(); ++i) {
        MSLane* l = *i;
        const MSLinkCont& lc = l->getLinkCont();
        for (MSLinkCont::const_iterator j = lc.begin(); j != lc.end(); ++j) {
            MSLink* link = *j;
            if (&link->getLane()->getEdge() == followerAfterInternal) {
                if (link->getViaLane() != 0) {
                    return &link->getViaLane()->getEdge();
                } else {
                    return 0; // network without internal links
                }
            }
        }
    }
    return 0;
}
// ===========================================================================
// method definitions
// ===========================================================================
bool
TraCIServerAPI_Lane::processGet(TraCIServer& server, tcpip::Storage& inputStorage,
                                tcpip::Storage& outputStorage) {
    // variable
    int variable = inputStorage.readUnsignedByte();
    std::string id = inputStorage.readString();
    // check variable
    if (variable != ID_LIST && variable != LANE_LINK_NUMBER && variable != LANE_EDGE_ID && variable != VAR_LENGTH
            && variable != VAR_MAXSPEED && variable != LANE_LINKS && variable != VAR_SHAPE
            && variable != VAR_CO2EMISSION && variable != VAR_COEMISSION && variable != VAR_HCEMISSION && variable != VAR_PMXEMISSION
            && variable != VAR_NOXEMISSION && variable != VAR_FUELCONSUMPTION && variable != VAR_NOISEEMISSION && variable != VAR_WAITING_TIME
            && variable != LAST_STEP_MEAN_SPEED && variable != LAST_STEP_VEHICLE_NUMBER
            && variable != LAST_STEP_VEHICLE_ID_LIST && variable != LAST_STEP_OCCUPANCY && variable != LAST_STEP_VEHICLE_HALTING_NUMBER
            && variable != LAST_STEP_LENGTH && variable != VAR_CURRENT_TRAVELTIME
            && variable != LANE_ALLOWED && variable != LANE_DISALLOWED && variable != VAR_WIDTH && variable != ID_COUNT
       ) {
        return server.writeErrorStatusCmd(CMD_GET_LANE_VARIABLE, "Get Lane Variable: unsupported variable specified", outputStorage);
    }
    // begin response building
    tcpip::Storage tempMsg;
    //  response-code, variableID, objectID
    tempMsg.writeUnsignedByte(RESPONSE_GET_LANE_VARIABLE);
    tempMsg.writeUnsignedByte(variable);
    tempMsg.writeString(id);
    if (variable == ID_LIST) {
        std::vector<std::string> ids;
        MSLane::insertIDs(ids);
        tempMsg.writeUnsignedByte(TYPE_STRINGLIST);
        tempMsg.writeStringList(ids);
    } else if (variable == ID_COUNT) {
        std::vector<std::string> ids;
        MSLane::insertIDs(ids);
        tempMsg.writeUnsignedByte(TYPE_INTEGER);
        tempMsg.writeInt((int) ids.size());
    } else {
        MSLane* lane = MSLane::dictionary(id);
        if (lane == 0) {
            return server.writeErrorStatusCmd(CMD_GET_LANE_VARIABLE, "Lane '" + id + "' is not known", outputStorage);
        }
        switch (variable) {
            case LANE_LINK_NUMBER:
                tempMsg.writeUnsignedByte(TYPE_UBYTE);
                tempMsg.writeUnsignedByte((int) lane->getLinkCont().size());
                break;
            case LANE_EDGE_ID:
                tempMsg.writeUnsignedByte(TYPE_STRING);
                tempMsg.writeString(lane->getEdge().getID());
                break;
            case VAR_LENGTH:
                tempMsg.writeUnsignedByte(TYPE_DOUBLE);
                tempMsg.writeDouble(lane->getLength());
                break;
            case VAR_MAXSPEED:
                tempMsg.writeUnsignedByte(TYPE_DOUBLE);
                tempMsg.writeDouble(lane->getSpeedLimit());
                break;
            case LANE_LINKS: {
                tempMsg.writeUnsignedByte(TYPE_COMPOUND);
                tcpip::Storage tempContent;
                unsigned int cnt = 0;
                tempContent.writeUnsignedByte(TYPE_INTEGER);
                const MSLinkCont& links = lane->getLinkCont();
                tempContent.writeInt((int) links.size());
                ++cnt;
                const SUMOTime currTime = MSNet::getInstance()->getCurrentTimeStep();
                for (MSLinkCont::const_iterator i = links.begin(); i != links.end(); ++i) {
                    MSLink* link = (*i);
                    // approached non-internal lane (if any)
                    tempContent.writeUnsignedByte(TYPE_STRING);
                    tempContent.writeString(link->getLane() != 0 ? link->getLane()->getID() : "");
                    ++cnt;
                    // approached "via", internal lane (if any)
                    tempContent.writeUnsignedByte(TYPE_STRING);
#ifdef HAVE_INTERNAL_LANES
                    tempContent.writeString(link->getViaLane() != 0 ? link->getViaLane()->getID() : "");
#else
                    tempContent.writeString("");
#endif
                    ++cnt;
                    // priority
                    tempContent.writeUnsignedByte(TYPE_UBYTE);
                    tempContent.writeUnsignedByte(link->havePriority() ? 1 : 0);
                    ++cnt;
                    // opened
                    tempContent.writeUnsignedByte(TYPE_UBYTE);
                    const SUMOReal speed = MIN2(lane->getSpeedLimit(), link->getLane()->getSpeedLimit());
                    tempContent.writeUnsignedByte(link->opened(currTime, speed, speed, DEFAULT_VEH_LENGTH, 0.0, DEFAULT_VEH_DECEL, 0) ? 1 : 0);
                    ++cnt;
                    // approaching foe
                    tempContent.writeUnsignedByte(TYPE_UBYTE);
                    tempContent.writeUnsignedByte(link->hasApproachingFoe(currTime, currTime, 0) ? 1 : 0);
                    ++cnt;
                    // state (not implemented, yet)
                    tempContent.writeUnsignedByte(TYPE_STRING);
                    tempContent.writeString(SUMOXMLDefinitions::LinkStates.getString(link->getState()));
                    ++cnt;
                    // direction
                    tempContent.writeUnsignedByte(TYPE_STRING);
                    tempContent.writeString(SUMOXMLDefinitions::LinkDirections.getString(link->getDirection()));
                    ++cnt;
                    // length
                    tempContent.writeUnsignedByte(TYPE_DOUBLE);
                    tempContent.writeDouble(link->getLength());
                    ++cnt;
                }
                tempMsg.writeInt((int) cnt);
                tempMsg.writeStorage(tempContent);
            }
            break;
            case LANE_ALLOWED: {
                tempMsg.writeUnsignedByte(TYPE_STRINGLIST);
                SVCPermissions permissions = lane->getPermissions();
                if (permissions == SVCFreeForAll) {  // special case: write nothing
                    permissions = 0;
                }
                tempMsg.writeStringList(getAllowedVehicleClassNamesList(permissions));
            }
            case LANE_DISALLOWED: {
                tempMsg.writeUnsignedByte(TYPE_STRINGLIST);
                tempMsg.writeStringList(getAllowedVehicleClassNamesList(~(lane->getPermissions()))); // negation yields disallowed
            }
            break;
            case VAR_SHAPE:
                tempMsg.writeUnsignedByte(TYPE_POLYGON);
                tempMsg.writeUnsignedByte((int)MIN2(static_cast<size_t>(255), lane->getShape().size()));
                for (unsigned int iPoint = 0; iPoint < MIN2(static_cast<size_t>(255), lane->getShape().size()); ++iPoint) {
                    tempMsg.writeDouble(lane->getShape()[iPoint].x());
                    tempMsg.writeDouble(lane->getShape()[iPoint].y());
                }
                break;
            case VAR_CO2EMISSION:
                tempMsg.writeUnsignedByte(TYPE_DOUBLE);
                tempMsg.writeDouble(lane->getCO2Emissions());
                break;
            case VAR_COEMISSION:
                tempMsg.writeUnsignedByte(TYPE_DOUBLE);
                tempMsg.writeDouble(lane->getCOEmissions());
                break;
            case VAR_HCEMISSION:
                tempMsg.writeUnsignedByte(TYPE_DOUBLE);
                tempMsg.writeDouble(lane->getHCEmissions());
                break;
            case VAR_PMXEMISSION:
                tempMsg.writeUnsignedByte(TYPE_DOUBLE);
                tempMsg.writeDouble(lane->getPMxEmissions());
                break;
            case VAR_NOXEMISSION:
                tempMsg.writeUnsignedByte(TYPE_DOUBLE);
                tempMsg.writeDouble(lane->getNOxEmissions());
                break;
            case VAR_FUELCONSUMPTION:
                tempMsg.writeUnsignedByte(TYPE_DOUBLE);
                tempMsg.writeDouble(lane->getFuelConsumption());
                break;
            case VAR_NOISEEMISSION:
                tempMsg.writeUnsignedByte(TYPE_DOUBLE);
                tempMsg.writeDouble(lane->getHarmonoise_NoiseEmissions());
                break;
            case LAST_STEP_VEHICLE_NUMBER:
                tempMsg.writeUnsignedByte(TYPE_INTEGER);
                tempMsg.writeInt((int) lane->getVehicleNumber());
                break;
            case LAST_STEP_MEAN_SPEED:
                tempMsg.writeUnsignedByte(TYPE_DOUBLE);
                tempMsg.writeDouble(lane->getMeanSpeed());
                break;
            case LAST_STEP_VEHICLE_ID_LIST: {
                std::vector<std::string> vehIDs;
                const MSLane::VehCont& vehs = lane->getVehiclesSecure();
                for (MSLane::VehCont::const_iterator j = vehs.begin(); j != vehs.end(); ++j) {
                    vehIDs.push_back((*j)->getID());
                }
                lane->releaseVehicles();
                tempMsg.writeUnsignedByte(TYPE_STRINGLIST);
                tempMsg.writeStringList(vehIDs);
            }
            break;
            case LAST_STEP_OCCUPANCY:
                tempMsg.writeUnsignedByte(TYPE_DOUBLE);
                tempMsg.writeDouble(lane->getNettoOccupancy());
                break;
            case LAST_STEP_VEHICLE_HALTING_NUMBER: {
                int halting = 0;
                const MSLane::VehCont& vehs = lane->getVehiclesSecure();
                for (MSLane::VehCont::const_iterator j = vehs.begin(); j != vehs.end(); ++j) {
                    if ((*j)->getSpeed() < SUMO_const_haltingSpeed) {
                        ++halting;
                    }
                }
                lane->releaseVehicles();
                tempMsg.writeUnsignedByte(TYPE_INTEGER);
                tempMsg.writeInt(halting);
            }
            break;
            case LAST_STEP_LENGTH: {
                SUMOReal lengthSum = 0;
                const MSLane::VehCont& vehs = lane->getVehiclesSecure();
                for (MSLane::VehCont::const_iterator j = vehs.begin(); j != vehs.end(); ++j) {
                    lengthSum += (*j)->getVehicleType().getLength();
                }
                tempMsg.writeUnsignedByte(TYPE_DOUBLE);
                if (vehs.size() == 0) {
                    tempMsg.writeDouble(0);
                } else {
                    tempMsg.writeDouble(lengthSum / (SUMOReal) vehs.size());
                }
                lane->releaseVehicles();
            }
            break;
            case VAR_WAITING_TIME: {
                tempMsg.writeUnsignedByte(TYPE_DOUBLE);
                tempMsg.writeDouble(lane->getWaitingSeconds());
            }
            break;
            case VAR_CURRENT_TRAVELTIME: {
                SUMOReal meanSpeed = lane->getMeanSpeed();
                tempMsg.writeUnsignedByte(TYPE_DOUBLE);
                if (meanSpeed != 0) {
                    tempMsg.writeDouble(lane->getLength() / meanSpeed);
                } else {
                    tempMsg.writeDouble(1000000.);
                }
            }
            break;
            case VAR_WIDTH:
                tempMsg.writeUnsignedByte(TYPE_DOUBLE);
                tempMsg.writeDouble(lane->getWidth());
                break;
            default:
                break;
        }
    }
    server.writeStatusCmd(CMD_GET_LANE_VARIABLE, RTYPE_OK, "", outputStorage);
    server.writeResponseWithLength(outputStorage, tempMsg);
    return true;
}
예제 #4
0
// ===========================================================================
// method definitions
// ===========================================================================
MSRightOfWayJunction::MSRightOfWayJunction(const std::string& id,
        SumoXMLNodeType type,
        const Position& position,
        const PositionVector& shape,
        std::vector<MSLane*> incoming,
#ifdef HAVE_INTERNAL_LANES
        std::vector<MSLane*> internal,
#endif
        MSJunctionLogic* logic)
    : MSLogicJunction(id, type, position, shape, incoming
#ifdef HAVE_INTERNAL_LANES
    , internal),
#else
                     ),
#endif
      myLogic(logic) {}


MSRightOfWayJunction::~MSRightOfWayJunction() {
    delete myLogic;
}


void
MSRightOfWayJunction::postloadInit() {
    // inform links where they have to report approaching vehicles to
    unsigned int requestPos = 0;
    std::vector<MSLane*>::iterator i;
    // going through the incoming lanes...
    unsigned int maxNo = 0;
    std::vector<std::pair<MSLane*, MSLink*> > sortedLinks;
    for (i = myIncomingLanes.begin(); i != myIncomingLanes.end(); ++i) {
        const MSLinkCont& links = (*i)->getLinkCont();
        // ... set information for every link
        for (MSLinkCont::const_iterator j = links.begin(); j != links.end(); j++) {
            if ((*j)->getLane()->getEdge().isWalkingArea() ||
                    ((*i)->getEdge().isWalkingArea() && !(*j)->getLane()->getEdge().isCrossing())) {
                continue;
            }
            sortedLinks.push_back(std::make_pair(*i, *j));
            ++maxNo;
        }
    }

    const bool hasFoes = myLogic->hasFoes();
    for (i = myIncomingLanes.begin(); i != myIncomingLanes.end(); ++i) {
        const MSLinkCont& links = (*i)->getLinkCont();
        // ... set information for every link
        for (MSLinkCont::const_iterator j = links.begin(); j != links.end(); j++) {
            if ((*j)->getLane()->getEdge().isWalkingArea() ||
                    ((*i)->getEdge().isWalkingArea() && !(*j)->getLane()->getEdge().isCrossing())) {
                continue;
            }
            if (myLogic->getLogicSize() <= requestPos) {
                throw ProcessError("Found invalid logic position of a link for junction '" + getID() + "' (" + toString(requestPos) + ", max " + toString(myLogic->getLogicSize()) + ") -> (network error)");
            }
            const MSLogicJunction::LinkBits& linkResponse = myLogic->getResponseFor(requestPos); // SUMO_ATTR_RESPONSE
            const MSLogicJunction::LinkBits& linkFoes = myLogic->getFoesFor(requestPos); // SUMO_ATTR_FOES
            bool cont = myLogic->getIsCont(requestPos);
            myLinkFoeLinks[*j] = std::vector<MSLink*>();
            for (unsigned int c = 0; c < maxNo; ++c) {
                if (linkResponse.test(c)) {
                    MSLink* foe = sortedLinks[c].second;
                    myLinkFoeLinks[*j].push_back(foe);
#ifdef HAVE_INTERNAL_LANES
                    if (MSGlobals::gUsingInternalLanes && foe->getViaLane() != 0) {
                        assert(foe->getViaLane()->getLinkCont().size() == 1);
                        MSLink* foeExitLink = foe->getViaLane()->getLinkCont()[0];
                        // add foe links after an internal junction
                        if (foeExitLink->getViaLane() != 0) {
                            myLinkFoeLinks[*j].push_back(foeExitLink);
                        }
                    }
#endif
                }
            }
            std::vector<MSLink*> foes;
            for (unsigned int c = 0; c < maxNo; ++c) {
                if (linkFoes.test(c)) {
                    MSLink* foe = sortedLinks[c].second;
                    foes.push_back(foe);
#ifdef HAVE_INTERNAL_LANES
                    MSLane* l = foe->getViaLane();
                    if (l == 0) {
                        continue;
                    }
                    // add foe links after an internal junction
                    const MSLinkCont& lc = l->getLinkCont();
                    for (MSLinkCont::const_iterator q = lc.begin(); q != lc.end(); ++q) {
                        if ((*q)->getViaLane() != 0) {
                            foes.push_back(*q);
                        }
                    }
#endif
                }
            }

            myLinkFoeInternalLanes[*j] = std::vector<MSLane*>();
#ifdef HAVE_INTERNAL_LANES
            if (MSGlobals::gUsingInternalLanes && myInternalLanes.size() > 0) {
                int li = 0;
                for (unsigned int c = 0; c < sortedLinks.size(); ++c) {
                    if (sortedLinks[c].second->getLane() == 0) { // dead end
                        continue;
                    }
                    if (linkFoes.test(c)) {
                        myLinkFoeInternalLanes[*j].push_back(myInternalLanes[li]);
                        if (linkResponse.test(c)) {
                            const std::vector<MSLane::IncomingLaneInfo>& l = myInternalLanes[li]->getIncomingLanes();
                            if (l.size() == 1 && l[0].lane->getEdge().getPurpose() == MSEdge::EDGEFUNCTION_INTERNAL) {
                                myLinkFoeInternalLanes[*j].push_back(l[0].lane);
                            }
                        }
                    }
                    ++li;
                }
            }
#endif
            (*j)->setRequestInformation((int)requestPos, hasFoes, cont, myLinkFoeLinks[*j], myLinkFoeInternalLanes[*j]);
#ifdef HAVE_INTERNAL_LANES
            // the exit link for a link before an internal junction is handled in MSInternalJunction
            // so we need to skip if cont=true
            if (MSGlobals::gUsingInternalLanes && (*j)->getViaLane() != 0 && !cont) {
                assert((*j)->getViaLane()->getLinkCont().size() == 1);
                MSLink* exitLink = (*j)->getViaLane()->getLinkCont()[0];
                exitLink->setRequestInformation((int)requestPos, false, false, std::vector<MSLink*>(),
                                                myLinkFoeInternalLanes[*j], (*j)->getViaLane());
            }
#endif
            for (std::vector<MSLink*>::const_iterator k = foes.begin(); k != foes.end(); ++k) {
                (*j)->addBlockedLink(*k);
                (*k)->addBlockedLink(*j);
            }
            requestPos++;
        }
    }
}
예제 #5
0
파일: MSLCM_LC2013.cpp 프로젝트: p1tt1/sumo
int
MSLCM_LC2013::_wantsChange(
    int laneOffset,
    MSAbstractLaneChangeModel::MSLCMessager& msgPass,
    int blocked,
    const std::pair<MSVehicle*, SUMOReal>& leader,
    const std::pair<MSVehicle*, SUMOReal>& neighLead,
    const std::pair<MSVehicle*, SUMOReal>& neighFollow,
    const MSLane& neighLane,
    const std::vector<MSVehicle::LaneQ>& preb,
    MSVehicle** lastBlocked,
    MSVehicle** firstBlocked) {
    assert(laneOffset == 1 || laneOffset == -1);
    const SUMOTime currentTime = MSNet::getInstance()->getCurrentTimeStep();
    // compute bestLaneOffset
    MSVehicle::LaneQ curr, neigh, best;
    int bestLaneOffset = 0;
    SUMOReal currentDist = 0;
    SUMOReal neighDist = 0;
    int currIdx = 0;
    MSLane* prebLane = myVehicle.getLane();
    if (prebLane->getEdge().getPurpose() == MSEdge::EDGEFUNCTION_INTERNAL) {
        // internal edges are not kept inside the bestLanes structure
        prebLane = prebLane->getLinkCont()[0]->getLane();
    }
    for (int p = 0; p < (int) preb.size(); ++p) {
        if (preb[p].lane == prebLane && p + laneOffset >= 0) {
            assert(p + laneOffset < (int)preb.size());
            curr = preb[p];
            neigh = preb[p + laneOffset];
            currentDist = curr.length;
            neighDist = neigh.length;
            bestLaneOffset = curr.bestLaneOffset;
            if (bestLaneOffset == 0 && preb[p + laneOffset].bestLaneOffset == 0) {
                bestLaneOffset = laneOffset;
            }
            best = preb[p + bestLaneOffset];
            currIdx = p;
            break;
        }
    }
    // direction specific constants
    const bool right = (laneOffset == -1);
    const int lca = (right ? LCA_RIGHT : LCA_LEFT);
    const int myLca = (right ? LCA_MRIGHT : LCA_MLEFT);
    const int lcaCounter = (right ? LCA_LEFT : LCA_RIGHT);
    const bool changeToBest = (right && bestLaneOffset < 0) || (!right && bestLaneOffset > 0);
    // keep information about being a leader/follower
    int ret = (myOwnState & 0xffff0000);

    ret = slowDownForBlocked(lastBlocked, ret);
    if (lastBlocked != firstBlocked) {
        ret = slowDownForBlocked(firstBlocked, ret);
    }


    // we try to estimate the distance which is necessary to get on a lane
    //  we have to get on in order to keep our route
    // we assume we need something that depends on our velocity
    // and compare this with the free space on our wished lane
    //
    // if the free space is somehow less than the space we need, we should
    //  definitely try to get to the desired lane
    //
    // this rule forces our vehicle to change the lane if a lane changing is necessary soon
    // lookAheadDistance:
    // we do not want the lookahead distance to change all the time so we discrectize the speed a bit

    if (myVehicle.getSpeed() > myLookAheadSpeed) {
        myLookAheadSpeed = myVehicle.getSpeed();
    } else {
        myLookAheadSpeed = MAX2(LOOK_AHEAD_MIN_SPEED,
                                (LOOK_AHEAD_SPEED_MEMORY * myLookAheadSpeed + (1 - LOOK_AHEAD_SPEED_MEMORY) * myVehicle.getSpeed()));
    }
    SUMOReal laDist = myLookAheadSpeed * (right ? LOOK_FORWARD_RIGHT : LOOK_FORWARD_LEFT);
    laDist += myVehicle.getVehicleType().getLengthWithGap() * (SUMOReal) 2.;
    // free space that is available for changing
    //const SUMOReal neighSpeed = (neighLead.first != 0 ? neighLead.first->getSpeed() :
    //        neighFollow.first != 0 ? neighFollow.first->getSpeed() :
    //        best.lane->getSpeedLimit());
    // @note: while this lets vehicles change earlier into the correct direction
    // it also makes the vehicles more "selfish" and prevents changes which are necessary to help others

    int roundaboutEdgesAhead = 0;
    for (std::vector<MSLane*>::iterator it = curr.bestContinuations.begin(); it != curr.bestContinuations.end(); ++it) {
        if ((*it) != 0 && (*it)->getEdge().isRoundabout()) {
            roundaboutEdgesAhead += 1;
        } else if (roundaboutEdgesAhead > 0) {
            // only check the next roundabout
            break;
        }
    }
    int roundaboutEdgesAheadNeigh = 0;
    for (std::vector<MSLane*>::iterator it = neigh.bestContinuations.begin(); it != neigh.bestContinuations.end(); ++it) {
        if ((*it) != 0 && (*it)->getEdge().isRoundabout()) {
            roundaboutEdgesAheadNeigh += 1;
        } else if (roundaboutEdgesAheadNeigh > 0) {
            // only check the next roundabout
            break;
        }
    }
    if (roundaboutEdgesAhead > 1) {
        currentDist += roundaboutEdgesAhead * ROUNDABOUT_DIST_BONUS;
        neighDist += roundaboutEdgesAheadNeigh * ROUNDABOUT_DIST_BONUS;
    }

    const SUMOReal usableDist = (currentDist - myVehicle.getPositionOnLane() - best.occupation *  JAM_FACTOR);
    const SUMOReal maxJam = MAX2(preb[currIdx + laneOffset].occupation, preb[currIdx].occupation);
    const SUMOReal neighLeftPlace = MAX2((SUMOReal) 0, neighDist - myVehicle.getPositionOnLane() - maxJam);

    if (changeToBest && bestLaneOffset == curr.bestLaneOffset
            && currentDistDisallows(usableDist, bestLaneOffset, laDist)) {
        /// @brief we urgently need to change lanes to follow our route
        ret = ret | lca | LCA_STRATEGIC | LCA_URGENT;
    } else {

        if (!myAllowOvertakingRight && !right && !myVehicle.congested() && neighLead.first != 0) {
            // check for slower leader on the left. we should not overtake but
            // rather move left ourselves (unless congested)
            MSVehicle* nv = neighLead.first;
            if (nv->getSpeed() < myVehicle.getSpeed()) {
                myVSafes.push_back(myCarFollowModel.followSpeed(
                                       &myVehicle, myVehicle.getSpeed(), neighLead.second, nv->getSpeed(), nv->getCarFollowModel().getMaxDecel()));
                if (nv->getSpeed() + 5 / 3.6 < myVehicle.getSpeed()) {
                    mySpeedGainProbability += CHANGE_PROB_THRESHOLD_LEFT / 3;
                }
            }
        }

        if (!changeToBest && (currentDistDisallows(neighLeftPlace, abs(bestLaneOffset) + 2, laDist))) {
            // the opposite lane-changing direction should be done than the one examined herein
            //  we'll check whether we assume we could change anyhow and get back in time...
            //
            // this rule prevents the vehicle from moving in opposite direction of the best lane
            //  unless the way till the end where the vehicle has to be on the best lane
            //  is long enough
            ret = ret | LCA_STAY | LCA_STRATEGIC;
        } else if (bestLaneOffset == 0 && (neighLeftPlace * 2. < laDist)) {
            // the current lane is the best and a lane-changing would cause a situation
            //  of which we assume we will not be able to return to the lane we have to be on.
            // this rule prevents the vehicle from leaving the current, best lane when it is
            //  close to this lane's end
            ret = ret | LCA_STAY | LCA_STRATEGIC;
        }
    }
    // check for overriding TraCI requests
    ret = myVehicle.influenceChangeDecision(ret);
    if ((ret & lcaCounter) != 0) {
        // we are not interested in traci requests for the opposite direction here
        ret &= ~(LCA_TRACI | lcaCounter | LCA_URGENT);
    }

    if ((ret & LCA_STAY) != 0) {
        return ret;
    }
    if ((ret & LCA_URGENT) != 0) {
        // prepare urgent lane change maneuver
        // save the left space
        myLeftSpace = currentDist - myVehicle.getPositionOnLane();
        if (changeToBest && abs(bestLaneOffset) > 1) {
            // there might be a vehicle which needs to counter-lane-change one lane further and we cannot see it yet
            myLeadingBlockerLength = MAX2((SUMOReal)(right ? 20.0 : 40.0), myLeadingBlockerLength);
        }

        // letting vehicles merge in at the end of the lane in case of counter-lane change, step#1
        //   if there is a leader and he wants to change to the opposite direction
        saveBlockerLength(neighLead.first, lcaCounter);
        if (*firstBlocked != neighLead.first) {
            saveBlockerLength(*firstBlocked, lcaCounter);
        }

        const SUMOReal remainingSeconds = ((ret & LCA_TRACI) == 0 ?
                                           MAX2((SUMOReal)STEPS2TIME(TS), myLeftSpace / myLookAheadSpeed / abs(bestLaneOffset) / URGENCY) :
                                           myVehicle.getInfluencer().changeRequestRemainingSeconds(currentTime));
        const SUMOReal plannedSpeed = informLeader(msgPass, blocked, myLca, neighLead, remainingSeconds);
        if (plannedSpeed >= 0) {
            // maybe we need to deal with a blocking follower
            informFollower(msgPass, blocked, myLca, neighFollow, remainingSeconds, plannedSpeed);
        }

        return ret;
    }

    if (roundaboutEdgesAhead > 1) {
        // try to use the inner lanes of a roundabout to increase throughput
        // unless we are approaching the exit
        if (lca == LCA_LEFT) {
            return ret | lca | LCA_COOPERATIVE;
        } else {
            return ret | LCA_STAY | LCA_COOPERATIVE;
        }
    }

    // let's also regard the case where the vehicle is driving on a highway...
    //  in this case, we do not want to get to the dead-end of an on-ramp
    if (right) {
        if (bestLaneOffset == 0 && myVehicle.getLane()->getVehicleMaxSpeed(&myVehicle) > 80. / 3.6 && myLookAheadSpeed > SUMO_const_haltingSpeed) {
            return ret | LCA_STAY | LCA_STRATEGIC;
        }
    }
    // --------

    // -------- make place on current lane if blocking follower
    //if (amBlockingFollowerPlusNB()) {
    //    std::cout << myVehicle.getID() << ", " << currentDistAllows(neighDist, bestLaneOffset, laDist)
    //        << " neighDist=" << neighDist
    //        << " currentDist=" << currentDist
    //        << "\n";
    //}
    if (amBlockingFollowerPlusNB()
            && (changeToBest || currentDistAllows(neighDist, abs(bestLaneOffset) + 1, laDist))) {

        return ret | lca | LCA_COOPERATIVE | LCA_URGENT ;//| LCA_CHANGE_TO_HELP;
    }

    // --------


    //// -------- security checks for krauss
    ////  (vsafe fails when gap<0)
    //if ((blocked & LCA_BLOCKED) != 0) {
    //    return ret;
    //}
    //// --------

    // -------- higher speed
    //if ((congested(neighLead.first) && neighLead.second < 20) || predInteraction(leader.first)) { //!!!
    //    return ret;
    //}
    SUMOReal thisLaneVSafe = myVehicle.getLane()->getVehicleMaxSpeed(&myVehicle);
    SUMOReal neighLaneVSafe = neighLane.getVehicleMaxSpeed(&myVehicle);
    if (neighLead.first == 0) {
        neighLaneVSafe = MIN2(neighLaneVSafe, myCarFollowModel.followSpeed(&myVehicle, myVehicle.getSpeed(), neighDist, 0, 0));
    } else {
        // @todo: what if leader is below safe gap?!!!
        neighLaneVSafe = MIN2(neighLaneVSafe, myCarFollowModel.followSpeed(
                                  &myVehicle, myVehicle.getSpeed(), neighLead.second, neighLead.first->getSpeed(), neighLead.first->getCarFollowModel().getMaxDecel()));
    }
    if (leader.first == 0) {
        thisLaneVSafe = MIN2(thisLaneVSafe, myCarFollowModel.followSpeed(&myVehicle, myVehicle.getSpeed(), currentDist, 0, 0));
    } else {
        // @todo: what if leader is below safe gap?!!!
        thisLaneVSafe = MIN2(thisLaneVSafe, myCarFollowModel.followSpeed(&myVehicle, myVehicle.getSpeed(), leader.second, leader.first->getSpeed(), leader.first->getCarFollowModel().getMaxDecel()));
    }

    thisLaneVSafe = MIN3(thisLaneVSafe, myVehicle.getVehicleType().getMaxSpeed(), myVehicle.getLane()->getVehicleMaxSpeed(&myVehicle));
    neighLaneVSafe = MIN3(neighLaneVSafe, myVehicle.getVehicleType().getMaxSpeed(), neighLane.getVehicleMaxSpeed(&myVehicle));

    const SUMOReal relativeGain = (neighLaneVSafe - thisLaneVSafe) / neighLaneVSafe;
    if (right) {
        // ONLY FOR CHANGING TO THE RIGHT
        if (thisLaneVSafe - 5 / 3.6 > neighLaneVSafe) {
            // ok, the current lane is faster than the right one...
            if (mySpeedGainProbability < 0) {
                mySpeedGainProbability /= 2.0;
                //myKeepRightProbability /= 2.0;
            }
        } else {
            // ok, the current lane is not faster than the right one
            mySpeedGainProbability -= relativeGain;

            // honor the obligation to keep right (Rechtsfahrgebot)
            // XXX consider fast approaching followers on the current lane
            //const SUMOReal vMax = myLookAheadSpeed;
            const SUMOReal vMax = MIN2(myVehicle.getVehicleType().getMaxSpeed(), myVehicle.getLane()->getVehicleMaxSpeed(&myVehicle));
            const SUMOReal acceptanceTime = KEEP_RIGHT_ACCEPTANCE * vMax * MAX2((SUMOReal)1, myVehicle.getSpeed()) / myVehicle.getLane()->getSpeedLimit();
            SUMOReal fullSpeedGap = MAX2((SUMOReal)0, neighDist - myVehicle.getCarFollowModel().brakeGap(vMax));
            SUMOReal fullSpeedDrivingSeconds = MIN2(acceptanceTime, fullSpeedGap / vMax);
            if (neighLead.first != 0 && neighLead.first->getSpeed() < vMax) {
                fullSpeedGap = MAX2((SUMOReal)0, MIN2(fullSpeedGap,
                            neighLead.second - myVehicle.getCarFollowModel().getSecureGap(
                                vMax, neighLead.first->getSpeed(), neighLead.first->getCarFollowModel().getMaxDecel())));
                fullSpeedDrivingSeconds = MIN2(fullSpeedDrivingSeconds, fullSpeedGap / (vMax - neighLead.first->getSpeed()));
            }
            const SUMOReal deltaProb = (CHANGE_PROB_THRESHOLD_RIGHT
                    * STEPS2TIME(DELTA_T)
                    * (fullSpeedDrivingSeconds / acceptanceTime) / KEEP_RIGHT_TIME);
            myKeepRightProbability -= deltaProb;

            if (gDebugFlag2) {
                std::cout << STEPS2TIME(currentTime)
                    << " veh=" << myVehicle.getID()
                    << " vMax=" << vMax
                    << " neighDist=" << neighDist
                    << " brakeGap=" << myVehicle.getCarFollowModel().brakeGap(myVehicle.getSpeed())
                    << " leaderSpeed=" << (neighLead.first == 0 ? -1 : neighLead.first->getSpeed())
                    << " secGap=" << (neighLead.first == 0 ? -1 : myVehicle.getCarFollowModel().getSecureGap(
                                myVehicle.getSpeed(), neighLead.first->getSpeed(), neighLead.first->getCarFollowModel().getMaxDecel()))
                    << " acceptanceTime=" << acceptanceTime
                    << " fullSpeedGap=" << fullSpeedGap
                    << " fullSpeedDrivingSeconds=" << fullSpeedDrivingSeconds
                    << " dProb=" << deltaProb
                    << "\n";
            }
            if (myKeepRightProbability < -CHANGE_PROB_THRESHOLD_RIGHT) {
                return ret | lca | LCA_KEEPRIGHT;
            }
        }

        if (mySpeedGainProbability < -CHANGE_PROB_THRESHOLD_RIGHT
                && neighDist / MAX2((SUMOReal) .1, myVehicle.getSpeed()) > 20.) { //./MAX2((SUMOReal) .1, myVehicle.getSpeed())) { // -.1
            return ret | lca | LCA_SPEEDGAIN;
        }
    } else {
        // ONLY FOR CHANGING TO THE LEFT
        if (thisLaneVSafe > neighLaneVSafe) {
            // this lane is better
            if (mySpeedGainProbability > 0) {
                mySpeedGainProbability /= 2.0;
            }
        } else {
            // left lane is better
            mySpeedGainProbability += relativeGain;
        }
        if (mySpeedGainProbability > CHANGE_PROB_THRESHOLD_LEFT && neighDist / MAX2((SUMOReal) .1, myVehicle.getSpeed()) > 20.) { // .1
            return ret | lca | LCA_SPEEDGAIN;
        }
    }
    // --------
    if (changeToBest && bestLaneOffset == curr.bestLaneOffset
            && (right ? mySpeedGainProbability < 0 : mySpeedGainProbability > 0)) {
        // change towards the correct lane, speedwise it does not hurt
        return ret | lca | LCA_STRATEGIC;
    }

    return ret;
}
예제 #6
0
// ===========================================================================
// method definitions
// ===========================================================================
MSRightOfWayJunction::MSRightOfWayJunction
(const std::string& id, const Position& position, const PositionVector& shape,
 std::vector<MSLane*> incoming, const SUMOReal height,
#ifdef HAVE_INTERNAL_LANES
 std::vector<MSLane*> internal,
#endif
 MSJunctionLogic* logic)
    :MSLogicJunction(id, position, shape, incoming, height
#ifdef HAVE_INTERNAL_LANES
    , internal),
#else
                    ),
#endif
     myLogic(logic)
{
    int i;
    if(OptionsCont::getOptions().getInt("buildVerbosity") > 1)
    {
        std::cout<<"----> MSRightOfWayJunction::MSRightOfWayJunction(...)"<<std::endl;
        std::cout<<"MSRightOfWayJunction:"<<std::endl;
        std::cout<<" id: "<<id<<std::endl;
    }
    static_cast < MSJunction * > (this)->setDynamicClassName("MSRightOfWayJunction");
    for(i=0; i<incoming.size(); i++)
    {
        if(incoming.at(i)->getToJunction() == NULL)
        {
            //incoming.at(i)->setToJunction(this);
        }
        /*
        if(incoming.at(i)->getEdge().leftLane(incoming.at(i)) == incoming.at(i))
        {
          if(incoming.at(i)->getRightLane()->getToJunction() == NULL)
          {
            ;
          }
          else
          {
            ;
          }
        }
        */
    }
}

MSRightOfWayJunction::~MSRightOfWayJunction()
{
    delete myLogic;
}

/*   [UPREGO] This function is called from
 * MSJunctionControl::postloadInitContainer()
 */
void MSRightOfWayJunction::postloadInit()
{
    // inform links where they have to report approaching vehicles to
    unsigned int requestPos = 0;
    std::vector<MSLane*>::iterator i;
    // going through the incoming lanes...
    unsigned int maxNo = 0;
    /* [UPREGO] How sorted? */
    std::vector<std::pair<MSLane*,MSLink*> >sortedLinks;
    /* [UPREGO] Iterate with i over incoming lanes of this junction */
    for (i = myIncomingLanes.begin(); i != myIncomingLanes.end(); ++i) {
        /* [UPREGO] Links of this incoming lane? */
        const MSLinkCont& links = (*i)->getLinkCont();
        // ... set information for every link
        for(MSLinkCont::const_iterator j = links.begin(); j != links.end(); j++)
        {
            /* [UPREGO] ??? */
            if(myLogic->getLogicSize() <= requestPos)
            {
                std::cout<<"MSRightOfWayJunction.cpp:123 throwing exception!"<<std::endl;
                std::cout<<" getID(){"<<getID()<<"}"<<std::endl;
                //throw ProcessError("Found invalid logic position of a link (network error)");
                /* TODO TASK FIXME ALERT DANGER if exception commented */
            }
            /*   [UPREGO] Create new link with:
             * - An incoming lane (i) of this junction (this)
             * - and one link (j) of the links container of the incoming lane
             */
            sortedLinks.push_back(std::make_pair(*i, *j));
            /* [UPREGO] And note it in maxNo */
            ++maxNo;
        }
    }
    bool isCrossing = myLogic->isCrossing();
    for (i = myIncomingLanes.begin(); i != myIncomingLanes.end(); ++i) {
        const MSLinkCont& links = (*i)->getLinkCont();
        // ... set information for every link
        for(MSLinkCont::const_iterator j = links.begin(); j != links.end(); j++)
        {
            if(myLogic->getLogicSize() <= requestPos)
            {
                std::cout<<"MSRightOfWayJunction.cpp:144 throwing exception!"<<std::endl;
                std::cout<<" getID(){"<<getID()<<"}"<<std::endl;
                //throw ProcessError("Found invalid logic position of a link (network error)");
                /* TODO TASK FIXME ALERT DANGER if exception commented */
            }
            const MSLogicJunction::LinkFoes& foeLinks = myLogic->getFoesFor(requestPos);
            const std::bitset<64> &internalFoes = myLogic->getInternalFoesFor(requestPos);
            bool cont = myLogic->getIsCont(requestPos);
            myLinkFoeLinks[*j] = std::vector<MSLink*>();
            for (unsigned int c = 0; c < maxNo; ++c) {
                if (foeLinks.test(c)) {
                    myLinkFoeLinks[*j].push_back(sortedLinks[c].second);
                }
            }
            std::vector<MSLink*> foes;
            for (unsigned int c = 0; c < maxNo; ++c) {
                if (internalFoes.test(c)) {
                    MSLink* foe = sortedLinks[c].second;
                    foes.push_back(foe);
#ifdef HAVE_INTERNAL_LANES
                    MSLane* l = foe->getViaLane();
                    if (l == 0) {
                        continue;
                    }
                    const MSLinkCont& lc = l->getLinkCont();
                    for (MSLinkCont::const_iterator q = lc.begin(); q != lc.end(); ++q) {
                        if ((*q)->getViaLane() != 0) {
                            foes.push_back(*q);
                        }
                    }
#endif
                }
            }
            myLinkFoeInternalLanes[*j] = std::vector<MSLane*>();
#ifdef HAVE_INTERNAL_LANES
            if (MSGlobals::gUsingInternalLanes && myInternalLanes.size() > 0) {
                int li = 0;
                for (unsigned int c = 0; c < sortedLinks.size(); ++c) {
                    if (sortedLinks[c].second->getLane() == 0) { // dead end
                        continue;
                    }
                    if (internalFoes.test(c)) {
                        myLinkFoeInternalLanes[*j].push_back(myInternalLanes[li]);
                    }
                    ++li;
                }
            }
#endif
            (*j)->setRequestInformation(requestPos, requestPos, isCrossing, cont, myLinkFoeLinks[*j], myLinkFoeInternalLanes[*j]);
            for (std::vector<MSLink*>::const_iterator k = foes.begin(); k != foes.end(); ++k) {
                (*j)->addBlockedLink(*k);
                (*k)->addBlockedLink(*j);
            }
            requestPos++;
        }
    }
#ifdef HAVE_INTERNAL_LANES
    // set information for the internal lanes
    requestPos = 0;
    for (i = myInternalLanes.begin(); i != myInternalLanes.end(); ++i) {
        // ... set information about participation
        static_cast<MSInternalLane*>(*i)->setParentJunctionInformation(&myInnerState, requestPos++);
    }
#endif
}
// ===========================================================================
// method definitions
// ===========================================================================
MSRightOfWayJunction::MSRightOfWayJunction(const std::string& id,
        const Position& position,
        const PositionVector& shape,
        std::vector<MSLane*> incoming,
#ifdef HAVE_INTERNAL_LANES
        std::vector<MSLane*> internal,
#endif
        MSJunctionLogic* logic)
    : MSLogicJunction(id, position, shape, incoming
#ifdef HAVE_INTERNAL_LANES
                      , internal),
#else
                     ),
#endif
    myLogic(logic) {}


MSRightOfWayJunction::~MSRightOfWayJunction() {
    delete myLogic;
}


void
MSRightOfWayJunction::postloadInit() {
    // inform links where they have to report approaching vehicles to
    unsigned int requestPos = 0;
    std::vector<MSLane*>::iterator i;
    // going through the incoming lanes...
    unsigned int maxNo = 0;
    std::vector<std::pair<MSLane*, MSLink*> > sortedLinks;
    for (i = myIncomingLanes.begin(); i != myIncomingLanes.end(); ++i) {
        const MSLinkCont& links = (*i)->getLinkCont();
        // ... set information for every link
        for (MSLinkCont::const_iterator j = links.begin(); j != links.end(); j++) {
            if (myLogic->getLogicSize() <= requestPos) {
                throw ProcessError("Found invalid logic position of a link (network error)");
            }
            sortedLinks.push_back(std::make_pair(*i, *j));
            ++maxNo;
        }
    }

    bool isCrossing = myLogic->isCrossing();
    for (i = myIncomingLanes.begin(); i != myIncomingLanes.end(); ++i) {
        const MSLinkCont& links = (*i)->getLinkCont();
        // ... set information for every link
        for (MSLinkCont::const_iterator j = links.begin(); j != links.end(); j++) {
            if (myLogic->getLogicSize() <= requestPos) {
                throw ProcessError("Found invalid logic position of a link (network error)");
            }
            const MSLogicJunction::LinkFoes& foeLinks = myLogic->getFoesFor(requestPos);
            const std::bitset<64>& internalFoes = myLogic->getInternalFoesFor(requestPos);
            bool cont = myLogic->getIsCont(requestPos);
            myLinkFoeLinks[*j] = std::vector<MSLink*>();
            for (unsigned int c = 0; c < maxNo; ++c) {
                if (foeLinks.test(c)) {
                    myLinkFoeLinks[*j].push_back(sortedLinks[c].second);
                }
            }
            std::vector<MSLink*> foes;
            for (unsigned int c = 0; c < maxNo; ++c) {
                if (internalFoes.test(c)) {
                    MSLink* foe = sortedLinks[c].second;
                    foes.push_back(foe);
#ifdef HAVE_INTERNAL_LANES
                    MSLane* l = foe->getViaLane();
                    if (l == 0) {
                        continue;
                    }
                    const MSLinkCont& lc = l->getLinkCont();
                    for (MSLinkCont::const_iterator q = lc.begin(); q != lc.end(); ++q) {
                        if ((*q)->getViaLane() != 0) {
                            foes.push_back(*q);
                        }
                    }
#endif
                }
            }

            myLinkFoeInternalLanes[*j] = std::vector<MSLane*>();
#ifdef HAVE_INTERNAL_LANES
            if (MSGlobals::gUsingInternalLanes && myInternalLanes.size() > 0) {
                int li = 0;
                for (unsigned int c = 0; c < sortedLinks.size(); ++c) {
                    if (sortedLinks[c].second->getLane() == 0) { // dead end
                        continue;
                    }
                    if (internalFoes.test(c)) {
                        myLinkFoeInternalLanes[*j].push_back(myInternalLanes[li]);
                        if (foeLinks.test(c)) {
                            const std::vector<MSLane::IncomingLaneInfo>& l = myInternalLanes[li]->getIncomingLanes();
                            if (l.size() == 1 && l[0].lane->getEdge().getPurpose() == MSEdge::EDGEFUNCTION_INTERNAL) {
                                myLinkFoeInternalLanes[*j].push_back(l[0].lane);
                            }
                        }
                    }
                    ++li;
                }
            }
#endif
            (*j)->setRequestInformation(requestPos, requestPos, isCrossing, cont, myLinkFoeLinks[*j], myLinkFoeInternalLanes[*j]);
            for (std::vector<MSLink*>::const_iterator k = foes.begin(); k != foes.end(); ++k) {
                (*j)->addBlockedLink(*k);
                (*k)->addBlockedLink(*j);
            }
            requestPos++;
        }
    }
#ifdef HAVE_INTERNAL_LANES
    // set information for the internal lanes
    requestPos = 0;
    for (i = myInternalLanes.begin(); i != myInternalLanes.end(); ++i) {
        // ... set information about participation
        static_cast<MSInternalLane*>(*i)->setParentJunctionInformation(&myInnerState, requestPos++);
    }
#endif
}
예제 #8
0
void
MSRailSignal::init(NLDetectorBuilder&) {
    assert(myLanes.size() > 0);

    myConflictLanes.resize(myLinks.size());
    myConflictLinks.resize(myLinks.size());
    myRouteConflictLanes.resize(myLinks.size());
    myRouteConflictLinks.resize(myLinks.size());

    myLastRerouteAttempt.resize(myLinks.size(), std::make_pair(nullptr, -1));

    if (OptionsCont::getOptions().isSet("railsignal-block-output")) {
        OutputDevice& od = OutputDevice::getDeviceByOption("railsignal-block-output");
        od.openTag("railSignal");
        od.writeAttr(SUMO_ATTR_ID, getID());
    }

    for (LinkVector& links : myLinks) { //for every link index
        // collect lanes and links that are relevant for setting this signal
        // for each index we collect
        // - conflictLanes (signal must be red if any conflict lane is occupied)
        // - conflictLinks (signal must be red if any conflict link is approached by a vehicle
        //    - that cannot break in time (arrivalSpeedBraking > 0)
        //    - approached by a vehicle with higher switching priority (see #3941)
        //
        // forwardBlock
        // - search forward recursive from outgoing lane until controlled railSignal link found
        //   -> add all found lanes
        //
        // bidiBlock (if any forwardBlock edge edge has bidi edge)
        // - search bidi backward recursive until first switch
        //   - from switch search backward recursive all other incoming until controlled rail signal link
        //     -> add final links
        //
        // backwardBlock
        // - search backward recursive from incoming lanes (not bidi for current outgoing lane)
        //   until controlled railSignal link found
        //   -> add all found lanes
        //   -> add final links
        //
        // conditionalBlocks
        // - for each conflict link (always signalized) that enters from a
        // bidirectional track
        //   - search bidi backward recursive until first switch that is
        //   accessible from the bidi-direction
        //     - from switch search bidi backward recursive until controlled rail signal link
        //       -> add all found lanes
        //       -> add final links

        std::vector<MSLink*> conflictLinks;
        LaneSet visited;

        std::vector<MSLane*> forwardBlock;
        std::vector<MSLane*> bidiBlock;
        std::vector<MSLane*> backwardBlock;

        // there should be only one link per index for railSignal
        if (links.size() > 1) {
            throw ProcessError("At railSignal '" + getID() + "' found " + toString(links.size())
                               + " links controlled by index " + toString(links[0]->getTLIndex()));
        }
        for (MSLink* link : links) {
            MSLane* toLane = link->getViaLaneOrLane();   //the lane this link is leading to
            MSLane* fromBidi = link->getLaneBefore()->getBidiLane();
            if (fromBidi != nullptr) {
                // do not extend to forward block beyond the entering track (in case of a loop)
                visited.insert(fromBidi);
            }

            collectForwardBlock(toLane, 0., forwardBlock, visited);
#ifdef DEBUG_FORWARD_BLOCK
            if (DEBUG_COND) {
                std::cout << "railSignal=" << getID() << " index=" << link->getTLIndex() << " forwardBlock=" << toString(forwardBlock) << "\n";
            }
#endif

            for (MSLane* forward : forwardBlock) {
                if (forward->getEdge().getBidiEdge() != nullptr) {
                    MSLane* bidi = forward->getBidiLane();
                    for (MSLink* bidiOutLink : bidi->getLinkCont()) {
                        if (bidiOutLink->getViaLane() != nullptr) {
                            bidiBlock.push_back(bidiOutLink->getViaLane());
                        }
                    }
                    collectBidiBlock(bidi, 0., false, bidiBlock, visited);
                    // assume bidirectional patches are continuous
                    break;
                }
            }
#ifdef DEBUG_BIDI_BLOCK
            if (DEBUG_COND) {
                std::cout << "railSignal=" << getID() << " index=" << link->getTLIndex() << " bidiBlock=" << toString(bidiBlock) << "\n";
            }
#endif

            // compute conflict links
            for (MSLane* cl : forwardBlock) {
                collectConflictLinks(cl, 0, backwardBlock, conflictLinks, visited, true);
            }
            for (MSLane* cl : bidiBlock) {
                collectConflictLinks(cl, 0, backwardBlock, conflictLinks, visited, false);
            }

            auto thisLinkIt = std::find(conflictLinks.begin(), conflictLinks.end(), link);
            if (thisLinkIt != conflictLinks.end()) {
                conflictLinks.erase(thisLinkIt);
            } else {
                WRITE_WARNING("At railSignal junction '" + getID() + "' link " + toString(link->getTLIndex()) + " with direction " + toString(link->getDirection()) + " should be uncontrolled");
            }

#ifdef DEBUG_BACKWARD_BLOCK
            if (DEBUG_COND) {
                std::cout << "railSignal=" << getID() << " index=" << link->getTLIndex() << " backwardBlock=" << toString(backwardBlock);
                std::cout << "railSignal=" << getID() << " index=" << link->getTLIndex() << " conflictLinks=";
                for (MSLink* cl : conflictLinks) {
                    std::cout << toString(cl->getViaLaneOrLane()->getID()) << " ";
                }
                std::cout << "\n";
            }
#endif

            // compute conditional conflict lanes and links
            for (MSLink* cl : conflictLinks) {
                std::vector<MSLane*> routeConflictLanes;
                std::vector<MSLink*> routeConflictLinks;
                MSLane* in = const_cast<MSLane*>(cl->getLaneBefore());
                LaneSet rCVisited = visited;
                // only collect if
                // 1) the in-edge is bidirectional
                // 2) the foe has no alternative track before reach meeting the end of the forwardBlock
                // 3) the forward block has no alternative track between the end of the forward block and the conflict link
                if (in->getEdge().getBidiEdge() != nullptr
                        && !hasAlternativeTrack(cl)
                        && !hasAlternativeTrackBetween(forwardBlock, cl)) {
                    collectBidiBlock(in, 0., false, routeConflictLanes, rCVisited);
                    std::vector<MSLane*> rCBackwardBlock;
                    for (MSLane* rCLane : routeConflictLanes) {
                        collectConflictLinks(rCLane, 0, rCBackwardBlock, routeConflictLinks, rCVisited);
                    }
                }
                myRouteConflictLanes[link->getTLIndex()].push_back(routeConflictLanes);
                myRouteConflictLinks[link->getTLIndex()].push_back(routeConflictLinks);
            }


            if (OptionsCont::getOptions().isSet("railsignal-block-output")) {
                OutputDevice& od = OutputDevice::getDeviceByOption("railsignal-block-output");
                od.openTag("link");
                od.writeAttr(SUMO_ATTR_TLLINKINDEX, link->getTLIndex());
                od.writeAttr(SUMO_ATTR_FROM, link->getLaneBefore()->getID());
                od.writeAttr(SUMO_ATTR_TO, link->getViaLaneOrLane()->getID());

                od.openTag("forwardBlock");
                od.writeAttr(SUMO_ATTR_LANES, toString(forwardBlock));
                od.closeTag();
                od.openTag("bidiBlock");
                od.writeAttr(SUMO_ATTR_LANES, toString(bidiBlock));
                od.closeTag();
                od.openTag("backwardBlock");
                od.writeAttr(SUMO_ATTR_LANES, toString(backwardBlock));
                od.closeTag();
                od.openTag("conflictLinks");
                std::vector<std::string> conflictLinkIDs; // railSignalID_tlIndex
                for (MSLink* cl : conflictLinks) {
                    conflictLinkIDs.push_back(getTLLinkID(cl));
                }
                od.writeAttr("logicIndex", toString(conflictLinkIDs));
                for (int i = 0; i < (int)conflictLinks.size(); i++) {
                    const std::vector<MSLane*>& rCLanes = myRouteConflictLanes[link->getTLIndex()][i];
                    const std::vector<MSLink*>& rCLinks = myRouteConflictLinks[link->getTLIndex()][i];
                    if (rCLanes.size() > 0 || rCLinks.size() > 0) {
                        od.openTag("conflictLink");
                        od.writeAttr("logicIndex", getTLLinkID(conflictLinks[i]));
                        if (rCLanes.size() > 0) {
                            od.writeAttr("lanes", toString(rCLanes));
                        }
                        if (rCLinks.size() > 0) {
                            std::vector<std::string> rCLinkIDs;
                            for (MSLink* rcl : rCLinks) {
                                rCLinkIDs.push_back(getTLLinkID(rcl));
                            }
                            od.writeAttr("links", toString(rCLinkIDs));
                        }
                        od.closeTag();
                    }
                }
                od.closeTag(); // conflictLinks
                od.closeTag(); // link
            }

            std::vector<MSLane*> conflictLanes;
            conflictLanes.insert(conflictLanes.end(), forwardBlock.begin(), forwardBlock.end());
            conflictLanes.insert(conflictLanes.end(), bidiBlock.begin(), bidiBlock.end());
            conflictLanes.insert(conflictLanes.end(), backwardBlock.begin(), backwardBlock.end());
            myConflictLanes[link->getTLIndex()] = conflictLanes;
            myConflictLinks[link->getTLIndex()] = conflictLinks;
        }
    }
    if (OptionsCont::getOptions().isSet("railsignal-block-output")) {
        OutputDevice& od = OutputDevice::getDeviceByOption("railsignal-block-output");
        od.closeTag();
    }

    updateCurrentPhase();   //check if this is necessary or if will be done already at another stage
    setTrafficLightSignals(MSNet::getInstance()->getCurrentTimeStep());
}
예제 #9
0
void
MSRailSignal::collectBidiBlock(MSLane* toLane, double length, bool foundSwitch, std::vector<MSLane*>& bidiBlock, LaneSet& visited) {
    while (toLane != nullptr) {
        //std::cout << " toLane=" << toLane->getID() << " length=" << length << " foundSwitch=" << foundSwitch << "\n";
        if (visited.count(toLane) != 0) {
            return;
        }
        visited.insert(toLane);
        bidiBlock.push_back(toLane);
        length += toLane->getLength();
        if (length > MAX_BLOCK_LENGTH) {
            if (myNumWarnings < MAX_SIGNAL_WARNINGS) {
                WRITE_WARNING("Bidirectional block after rail signal junction '" + getID() +
                              "' exceeds maximum length (stopped searching after lane '" + toLane->getID() + "' (length=" + toString(length) + "m).");
            }
            myNumWarnings++;
            return;
        }
        const auto& incomingLaneInfos = toLane->getIncomingLanes();
        MSLane* prev = toLane;
        toLane = nullptr;
        for (const auto& ili : incomingLaneInfos) {
            if (ili.viaLink->getDirection() == LINKDIR_TURN) {
                continue;
            }
            if (ili.viaLink->getTLLogic() != nullptr) {
                if (!foundSwitch && bidiBlock.size() > 1) {
                    // check wether this node is switch (first edge doesn't count)
                    for (MSLink* link : ili.lane->getLinkCont()) {
                        if (link->getDirection() == LINKDIR_TURN) {
                            continue;
                        }
                        if (link->getViaLaneOrLane() == prev) {
                            continue;
                        }
                        //std::cout << "   ili.lane=" << ili.lane->getID()
                        //    << " prev=" << prev->getID()
                        //    << " linkDir=" << ili.viaLink->getDirection()
                        //    << " linkIndex=" << ili.viaLink->getTLIndex()
                        //    << "\n";
                        foundSwitch = true;
                        break;
                    }
                }
                if (foundSwitch) {
                    return;
                }
            }
            if (toLane == nullptr) {
                toLane = ili.lane;
            } else {
                foundSwitch = true;
                collectBidiBlock(ili.lane, length, true, bidiBlock, visited);
            }
        }
        if (toLane != nullptr && !foundSwitch && prev->getEdge().getBidiEdge() != nullptr) {
            // check switch in the other direction
            MSLane* prevBidi = prev->getBidiLane();
            for (MSLink* link : prevBidi->getLinkCont()) {
                if (link->getDirection() == LINKDIR_TURN) {
                    continue;
                }
                if (link->getViaLaneOrLane()->getEdge().getBidiEdge() != &toLane->getEdge()) {
                    //std::cout << "   toLane=" << toLane->getID()
                    //    << " prev=" << prev->getID()
                    //    << " prevBidi=" << prevBidi->getID()
                    //    << " linkLane=" << link->getViaLaneOrLane()->getEdge().getID()
                    //    << " linkLaneBidi=" << Named::getIDSecure(link->getViaLaneOrLane()->getEdge().getBidiEdge())
                    //    << "\n";
                    foundSwitch = true;
                    break;
                }
            }
        }
    }
}
예제 #10
0
void
MSRightOfWayJunction::postloadInit() {
    // inform links where they have to report approaching vehicles to
    int requestPos = 0;
    std::vector<MSLane*>::iterator i;
    // going through the incoming lanes...
    int maxNo = 0;
    std::vector<std::pair<MSLane*, MSLink*> > sortedLinks;
    for (i = myIncomingLanes.begin(); i != myIncomingLanes.end(); ++i) {
        const MSLinkCont& links = (*i)->getLinkCont();
        // ... set information for every link
        for (MSLinkCont::const_iterator j = links.begin(); j != links.end(); j++) {
            if ((*j)->getLane()->getEdge().isWalkingArea() ||
                    ((*i)->getEdge().isWalkingArea() && !(*j)->getLane()->getEdge().isCrossing())) {
                continue;
            }
            sortedLinks.push_back(std::make_pair(*i, *j));
            ++maxNo;
        }
    }

    const bool hasFoes = myLogic->hasFoes();
    for (i = myIncomingLanes.begin(); i != myIncomingLanes.end(); ++i) {
        const MSLinkCont& links = (*i)->getLinkCont();
        // ... set information for every link
        const MSLane* walkingAreaFoe = nullptr;
        for (MSLinkCont::const_iterator j = links.begin(); j != links.end(); j++) {
            if ((*j)->getLane()->getEdge().isWalkingArea()) {
                if ((*i)->getPermissions() != SVC_PEDESTRIAN) {
                    // vehicular lane connects to a walkingarea
                    walkingAreaFoe = (*j)->getLane();
                }
                continue;
            } else if (((*i)->getEdge().isWalkingArea() && !(*j)->getLane()->getEdge().isCrossing())) {
                continue;
            }
            if (myLogic->getLogicSize() <= requestPos) {
                throw ProcessError("Found invalid logic position of a link for junction '" + getID() + "' (" + toString(requestPos) + ", max " + toString(myLogic->getLogicSize()) + ") -> (network error)");
            }
            const MSLogicJunction::LinkBits& linkResponse = myLogic->getResponseFor(requestPos); // SUMO_ATTR_RESPONSE
            const MSLogicJunction::LinkBits& linkFoes = myLogic->getFoesFor(requestPos); // SUMO_ATTR_FOES
            bool cont = myLogic->getIsCont(requestPos);
            myLinkFoeLinks[*j] = std::vector<MSLink*>();
            for (int c = 0; c < maxNo; ++c) {
                if (linkResponse.test(c)) {
                    MSLink* foe = sortedLinks[c].second;
                    myLinkFoeLinks[*j].push_back(foe);
                    if (MSGlobals::gUsingInternalLanes && foe->getViaLane() != nullptr) {
                        assert(foe->getViaLane()->getLinkCont().size() == 1);
                        MSLink* foeExitLink = foe->getViaLane()->getLinkCont()[0];
                        // add foe links after an internal junction
                        if (foeExitLink->getViaLane() != nullptr) {
                            myLinkFoeLinks[*j].push_back(foeExitLink);
                        }
                    }
                }
            }
            std::vector<MSLink*> foes;
            for (int c = 0; c < maxNo; ++c) {
                if (linkFoes.test(c)) {
                    MSLink* foe = sortedLinks[c].second;
                    foes.push_back(foe);
                    MSLane* l = foe->getViaLane();
                    if (l == nullptr) {
                        continue;
                    }
                    // add foe links after an internal junction
                    const MSLinkCont& lc = l->getLinkCont();
                    for (MSLinkCont::const_iterator q = lc.begin(); q != lc.end(); ++q) {
                        if ((*q)->getViaLane() != nullptr) {
                            foes.push_back(*q);
                        }
                    }
                }
            }

            myLinkFoeInternalLanes[*j] = std::vector<MSLane*>();
            if (MSGlobals::gUsingInternalLanes && myInternalLanes.size() > 0) {
                int li = 0;
                for (int c = 0; c < (int)sortedLinks.size(); ++c) {
                    if (sortedLinks[c].second->getLane() == nullptr) { // dead end
                        continue;
                    }
                    if (linkFoes.test(c)) {
                        myLinkFoeInternalLanes[*j].push_back(myInternalLanes[li]);
                        if (linkResponse.test(c)) {
                            const std::vector<MSLane::IncomingLaneInfo>& l = myInternalLanes[li]->getIncomingLanes();
                            if (l.size() == 1 && l[0].lane->getEdge().isInternal()) {
                                myLinkFoeInternalLanes[*j].push_back(l[0].lane);
                            }
                        }
                    }
                    ++li;
                }
            }
            (*j)->setRequestInformation((int)requestPos, hasFoes, cont, myLinkFoeLinks[*j], myLinkFoeInternalLanes[*j]);
            // the exit link for a link before an internal junction is handled in MSInternalJunction
            // so we need to skip if cont=true
            if (MSGlobals::gUsingInternalLanes && (*j)->getViaLane() != nullptr && !cont) {
                assert((*j)->getViaLane()->getLinkCont().size() == 1);
                MSLink* exitLink = (*j)->getViaLane()->getLinkCont()[0];
                exitLink->setRequestInformation((int)requestPos, false, false, std::vector<MSLink*>(),
                                                myLinkFoeInternalLanes[*j], (*j)->getViaLane());
                for (const auto& ili : exitLink->getLane()->getIncomingLanes()) {
                    if (ili.lane->getEdge().isWalkingArea()) {
                        exitLink->addWalkingAreaFoeExit(ili.lane);
                        break;
                    }
                }
            }
            // the exit link for a crossing is needed for the pedestrian model
            if (MSGlobals::gUsingInternalLanes && (*j)->getLane()->getEdge().isCrossing()) {
                MSLink* exitLink = (*j)->getLane()->getLinkCont()[0];
                exitLink->setRequestInformation((int)requestPos, false, false, std::vector<MSLink*>(),
                                                myLinkFoeInternalLanes[*j], (*j)->getLane());
            }
            for (std::vector<MSLink*>::const_iterator k = foes.begin(); k != foes.end(); ++k) {
                (*j)->addBlockedLink(*k);
                (*k)->addBlockedLink(*j);
            }
            requestPos++;
        }
        if (walkingAreaFoe != nullptr && links.size() > 1) {
            for (MSLinkCont::const_iterator j = links.begin(); j != links.end(); j++) {
                if (!(*j)->getLane()->getEdge().isWalkingArea()) {
                    MSLink* exitLink = (*j)->getViaLane()->getLinkCont()[0];
                    exitLink->addWalkingAreaFoe(walkingAreaFoe);
                }
            }
        }
    }
}
예제 #11
0
void
MSInternalJunction::postloadInit() {
    if (myIncomingLanes.size() == 0) {
        throw ProcessError("Internal junction " + getID() + " has no incoming lanes");
    }
    // the first lane in the list of incoming lanes is special. It defines the
    // link that needs to do all the checking for this internal junction
    const MSLane* specialLane = myIncomingLanes[0];
    assert(specialLane->getLinkCont().size() == 1);
    MSLink* thisLink = specialLane->getLinkCont()[0];
    const MSRightOfWayJunction* parent = dynamic_cast<const MSRightOfWayJunction*>(specialLane->getEdge().getToJunction());
    if (parent == nullptr) {
        // parent has type traffic_light_unregulated
        return;
    }
    const int ownLinkIndex = specialLane->getIncomingLanes()[0].viaLink->getIndex();
    const MSLogicJunction::LinkBits& response = parent->getLogic()->getResponseFor(ownLinkIndex);
    // inform links where they have to report approaching vehicles to
    //std::cout << " special=" << specialLane->getID() << " incoming=" << toString(myIncomingLanes) << " internal=" << toString(myInternalLanes) << "\n";
    for (std::vector<MSLane*>::iterator i = myInternalLanes.begin(); i != myInternalLanes.end(); ++i) {
        const MSLinkCont& lc = (*i)->getLinkCont();
        for (MSLinkCont::const_iterator q = lc.begin(); q != lc.end(); ++q) {
            if ((*q)->getViaLane() != nullptr) {
                const int foeIndex = (*i)->getIncomingLanes()[0].viaLink->getIndex();
                //std::cout << "       response=" << response << " index=" << ownLinkIndex << " foeIndex=" << foeIndex << " ibct=" << indirectBicycleTurn(specialLane, thisLink, *i, *q) << "\n";
                if (response.test(foeIndex) || indirectBicycleTurn(specialLane, thisLink, *i, *q)) {
                    // only respect vehicles before internal junctions if they
                    // have priority (see the analogous foeLinks.test() when
                    // initializing myLinkFoeInternalLanes in MSRightOfWayJunction
                    // Indirect left turns for bicycles are a special case
                    // because they both intersect on their second part with the first part of the other one
                    // and only one of the has priority
                    myInternalLaneFoes.push_back(*i);
                }
                myInternalLaneFoes.push_back((*q)->getViaLane());
            } else {
                myInternalLaneFoes.push_back(*i);
            }
            //std::cout << "  i=" << (*i)->getID() << " qLane=" << (*q)->getLane()->getID() << " qVia=" << Named::getIDSecure((*q)->getViaLane()) << " foes=" << toString(myInternalLaneFoes) << "\n";
        }

    }
    for (std::vector<MSLane*>::const_iterator i = myIncomingLanes.begin() + 1; i != myIncomingLanes.end(); ++i) {
        MSLane* l = *i;
        const MSLinkCont& lc = l->getLinkCont();
        for (MSLinkCont::const_iterator j = lc.begin(); j != lc.end(); ++j) {
            MSLane* via = (*j)->getViaLane();
            if (std::find(myInternalLanes.begin(), myInternalLanes.end(), via) == myInternalLanes.end()) {
                continue;
            }
            myInternalLinkFoes.push_back(*j);
        }
    }
    // thisLinks is itself an exitLink of the preceding internal lane
    thisLink->setRequestInformation(ownLinkIndex, true, false, myInternalLinkFoes, myInternalLaneFoes, thisLink->getViaLane()->getLogicalPredecessorLane());
    assert(thisLink->getViaLane()->getLinkCont().size() == 1);
    MSLink* exitLink = thisLink->getViaLane()->getLinkCont()[0];
    exitLink->setRequestInformation(ownLinkIndex, false, false, std::vector<MSLink*>(),
                                    myInternalLaneFoes, thisLink->getViaLane());
    for (const auto& ili : exitLink->getLane()->getIncomingLanes()) {
        if (ili.lane->getEdge().isWalkingArea()) {
            exitLink->addWalkingAreaFoeExit(ili.lane);
            break;
        }
    }
    for (std::vector<MSLink*>::const_iterator k = myInternalLinkFoes.begin(); k != myInternalLinkFoes.end(); ++k) {
        thisLink->addBlockedLink(*k);
        (*k)->addBlockedLink(thisLink);
    }
}
예제 #12
0
// ===========================================================================
// method definitions
// ===========================================================================
bool
TraCIServerAPI_Lane::processGet(TraCIServer &server, tcpip::Storage &inputStorage,
                                tcpip::Storage &outputStorage) {
    Storage tmpResult;
    std::string warning = "";	// additional description for response
    // variable
    int variable = inputStorage.readUnsignedByte();
    std::string id = inputStorage.readString();
    // check variable
    if (variable!=ID_LIST&&variable!=LANE_LINK_NUMBER&&variable!=LANE_EDGE_ID&&variable!=VAR_LENGTH
            &&variable!=VAR_MAXSPEED&&variable!=LANE_LINKS&&variable!=VAR_SHAPE
            &&variable!=VAR_CO2EMISSION&&variable!=VAR_COEMISSION&&variable!=VAR_HCEMISSION&&variable!=VAR_PMXEMISSION
            &&variable!=VAR_NOXEMISSION&&variable!=VAR_FUELCONSUMPTION&&variable!=VAR_NOISEEMISSION
            &&variable!=LAST_STEP_MEAN_SPEED&&variable!=LAST_STEP_VEHICLE_NUMBER
            &&variable!=LAST_STEP_VEHICLE_ID_LIST&&variable!=LAST_STEP_OCCUPANCY&&variable!=LAST_STEP_VEHICLE_HALTING_NUMBER
            &&variable!=LAST_STEP_LENGTH&&variable!=VAR_CURRENT_TRAVELTIME
            &&variable!=LANE_ALLOWED&&variable!=LANE_DISALLOWED) {
        server.writeStatusCmd(CMD_GET_LANE_VARIABLE, RTYPE_ERR, "Get Lane Variable: unsupported variable specified", outputStorage);
        return false;
    }
    // begin response building
    Storage tempMsg;
    //  response-code, variableID, objectID
    tempMsg.writeUnsignedByte(RESPONSE_GET_LANE_VARIABLE);
    tempMsg.writeUnsignedByte(variable);
    tempMsg.writeString(id);
    if (variable==ID_LIST) {
        std::vector<std::string> ids;
        MSLane::insertIDs(ids);
        tempMsg.writeUnsignedByte(TYPE_STRINGLIST);
        tempMsg.writeStringList(ids);
    } else {
        MSLane *lane = MSLane::dictionary(id);
        if (lane==0) {
            server.writeStatusCmd(CMD_GET_LANE_VARIABLE, RTYPE_ERR, "Lane '" + id + "' is not known", outputStorage);
            return false;
        }
        switch (variable) {
        case LANE_LINK_NUMBER:
            tempMsg.writeUnsignedByte(TYPE_UBYTE);
            tempMsg.writeUnsignedByte((int) lane->getLinkCont().size());
            break;
        case LANE_EDGE_ID:
            tempMsg.writeUnsignedByte(TYPE_STRING);
            tempMsg.writeString(lane->getEdge().getID());
            break;
        case VAR_LENGTH:
            tempMsg.writeUnsignedByte(TYPE_FLOAT);
            tempMsg.writeFloat(lane->getLength());
            break;
        case VAR_MAXSPEED:
            tempMsg.writeUnsignedByte(TYPE_FLOAT);
            tempMsg.writeFloat(lane->getMaxSpeed());
            break;
        case LANE_LINKS: {
            tempMsg.writeUnsignedByte(TYPE_COMPOUND);
            Storage tempContent;
            unsigned int cnt = 0;
            tempContent.writeUnsignedByte(TYPE_INTEGER);
            const MSLinkCont &links = lane->getLinkCont();
            tempContent.writeInt((int) links.size());
            ++cnt;
            for (MSLinkCont::const_iterator i=links.begin(); i!=links.end(); ++i) {
                MSLink *link = (*i);
                // approached non-internal lane (if any)
                tempContent.writeUnsignedByte(TYPE_STRING);
                tempContent.writeString(link->getLane()!=0 ? link->getLane()->getID() : "");
                ++cnt;
                // approached "via", internal lane (if any)
                tempContent.writeUnsignedByte(TYPE_STRING);
#ifdef HAVE_INTERNAL_LANES
                tempContent.writeString(link->getViaLane()!=0 ? link->getViaLane()->getID() : "");
#else
                tempContent.writeString("");
#endif
                ++cnt;
                // priority
                tempContent.writeUnsignedByte(TYPE_UBYTE);
                tempContent.writeUnsignedByte(link->havePriority() ? 1 : 0);
                ++cnt;
                // opened
                tempContent.writeUnsignedByte(TYPE_UBYTE);
                tempContent.writeUnsignedByte(link->opened(MSNet::getInstance()->getCurrentTimeStep(), MSNet::getInstance()->getCurrentTimeStep(), 0.) ? 1 : 0);
                ++cnt;
                // approaching foe
                tempContent.writeUnsignedByte(TYPE_UBYTE);
                tempContent.writeUnsignedByte(link->hasApproachingFoe(MSNet::getInstance()->getCurrentTimeStep(), MSNet::getInstance()->getCurrentTimeStep()) ? 1 : 0);
                ++cnt;
                // state (not implemented, yet)
                tempContent.writeUnsignedByte(TYPE_STRING);
                tempContent.writeString("");
                ++cnt;
                // direction (not implemented, yet)
                tempContent.writeUnsignedByte(TYPE_STRING);
                tempContent.writeString("");
                ++cnt;
                // length
                tempContent.writeUnsignedByte(TYPE_FLOAT);
                tempContent.writeFloat(link->getLength());
                ++cnt;
            }
            tempMsg.writeInt((int) cnt);
            tempMsg.writeStorage(tempContent);
        }
        break;
        case LANE_ALLOWED: {
            const std::vector<SUMOVehicleClass> &allowed = lane->getAllowedClasses();
            std::vector<std::string> allowedS;
            for (std::vector<SUMOVehicleClass>::const_iterator i=allowed.begin(); i!=allowed.end(); ++i) {
                allowedS.push_back(getVehicleClassName(*i));
            }
            tempMsg.writeUnsignedByte(TYPE_STRINGLIST);
            tempMsg.writeStringList(allowedS);
        }
        case LANE_DISALLOWED: {
            const std::vector<SUMOVehicleClass> &disallowed = lane->getNotAllowedClasses();
            std::vector<std::string> disallowedS;
            for (std::vector<SUMOVehicleClass>::const_iterator i=disallowed.begin(); i!=disallowed.end(); ++i) {
                disallowedS.push_back(getVehicleClassName(*i));
            }
            tempMsg.writeUnsignedByte(TYPE_STRINGLIST);
            tempMsg.writeStringList(disallowedS);
        }
        break;
        case VAR_SHAPE:
            tempMsg.writeUnsignedByte(TYPE_POLYGON);
            tempMsg.writeUnsignedByte(MIN2(static_cast<size_t>(255),lane->getShape().size()));
            for (int iPoint=0; iPoint < MIN2(static_cast<size_t>(255),lane->getShape().size()); ++iPoint) {
                tempMsg.writeFloat(lane->getShape()[iPoint].x());
                tempMsg.writeFloat(lane->getShape()[iPoint].y());
            }
            break;
        case VAR_CO2EMISSION:
            tempMsg.writeUnsignedByte(TYPE_FLOAT);
            tempMsg.writeFloat(lane->getHBEFA_CO2Emissions());
            break;
        case VAR_COEMISSION:
            tempMsg.writeUnsignedByte(TYPE_FLOAT);
            tempMsg.writeFloat(lane->getHBEFA_COEmissions());
            break;
        case VAR_HCEMISSION:
            tempMsg.writeUnsignedByte(TYPE_FLOAT);
            tempMsg.writeFloat(lane->getHBEFA_HCEmissions());
            break;
        case VAR_PMXEMISSION:
            tempMsg.writeUnsignedByte(TYPE_FLOAT);
            tempMsg.writeFloat(lane->getHBEFA_PMxEmissions());
            break;
        case VAR_NOXEMISSION:
            tempMsg.writeUnsignedByte(TYPE_FLOAT);
            tempMsg.writeFloat(lane->getHBEFA_NOxEmissions());
            break;
        case VAR_FUELCONSUMPTION:
            tempMsg.writeUnsignedByte(TYPE_FLOAT);
            tempMsg.writeFloat(lane->getHBEFA_FuelConsumption());
            break;
        case VAR_NOISEEMISSION:
            tempMsg.writeUnsignedByte(TYPE_FLOAT);
            tempMsg.writeFloat(lane->getHarmonoise_NoiseEmissions());
            break;
        case LAST_STEP_VEHICLE_NUMBER:
            tempMsg.writeUnsignedByte(TYPE_INTEGER);
            tempMsg.writeInt((int) lane->getVehicleNumber());
            break;
        case LAST_STEP_MEAN_SPEED:
            tempMsg.writeUnsignedByte(TYPE_FLOAT);
            tempMsg.writeFloat(lane->getMeanSpeed());
            break;
        case LAST_STEP_VEHICLE_ID_LIST: {
            std::vector<std::string> vehIDs;
            const std::deque<MSVehicle*> &vehs = lane->getVehiclesSecure();
            for (std::deque<MSVehicle*>::const_iterator j=vehs.begin(); j!=vehs.end(); ++j) {
                vehIDs.push_back((*j)->getID());
            }
            lane->releaseVehicles();
            tempMsg.writeUnsignedByte(TYPE_STRINGLIST);
            tempMsg.writeStringList(vehIDs);
        }
        break;
        case LAST_STEP_OCCUPANCY:
            tempMsg.writeUnsignedByte(TYPE_FLOAT);
            tempMsg.writeFloat(lane->getOccupancy());
            break;
        case LAST_STEP_VEHICLE_HALTING_NUMBER: {
            int halting = 0;
            const std::deque<MSVehicle*> &vehs = lane->getVehiclesSecure();
            for (std::deque<MSVehicle*>::const_iterator j=vehs.begin(); j!=vehs.end(); ++j) {
                if ((*j)->getSpeed()<0.1) {
                    ++halting;
                }
            }
            lane->releaseVehicles();
            tempMsg.writeUnsignedByte(TYPE_INTEGER);
            tempMsg.writeInt(halting);
        }
        break;
        case LAST_STEP_LENGTH: {
            SUMOReal lengthSum = 0;
            const std::deque<MSVehicle*> &vehs = lane->getVehiclesSecure();
            for (std::deque<MSVehicle*>::const_iterator j=vehs.begin(); j!=vehs.end(); ++j) {
                lengthSum += (*j)->getVehicleType().getLength();
            }
            tempMsg.writeUnsignedByte(TYPE_FLOAT);
            if (vehs.size()==0) {
                tempMsg.writeFloat(0);
            } else {
                tempMsg.writeFloat(lengthSum / (SUMOReal) vehs.size());
            }
            lane->releaseVehicles();
        }
        break;
        case VAR_CURRENT_TRAVELTIME: {
            SUMOReal meanSpeed = lane->getMeanSpeed();
            tempMsg.writeUnsignedByte(TYPE_FLOAT);
            if (meanSpeed!=0) {
                tempMsg.writeFloat(lane->getLength() / meanSpeed);
            } else {
                tempMsg.writeFloat(1000000.);
            }
        }
        break;
        default:
            break;
        }
    }
    server.writeStatusCmd(CMD_GET_LANE_VARIABLE, RTYPE_OK, warning, outputStorage);
    // send response
    outputStorage.writeUnsignedByte(0); // command length -> extended
    outputStorage.writeInt(1 + 4 + tempMsg.size());
    outputStorage.writeStorage(tempMsg);
    return true;
}