void
RODFDetectorCon::writeEmitterPOIs(const std::string& file,
                                  const RODFDetectorFlows& flows) {
    OutputDevice& out = OutputDevice::getDevice(file);
    out.writeXMLHeader("additional");
    for (std::vector<RODFDetector*>::const_iterator i = myDetectors.begin(); i != myDetectors.end(); ++i) {
        RODFDetector* det = *i;
        SUMOReal flow = flows.getFlowSumSecure(det->getID());
        const unsigned char col = static_cast<unsigned char>(128 * flow / flows.getMaxDetectorFlow() + 128);
        out.openTag(SUMO_TAG_POI).writeAttr(SUMO_ATTR_ID, StringUtils::escapeXML((*i)->getID()) + ":" + toString(flow));
        switch ((*i)->getType()) {
            case BETWEEN_DETECTOR:
                out.writeAttr(SUMO_ATTR_TYPE, "between_detector_position").writeAttr(SUMO_ATTR_COLOR, RGBColor(0, 0, col, 255));
                break;
            case SOURCE_DETECTOR:
                out.writeAttr(SUMO_ATTR_TYPE, "source_detector_position").writeAttr(SUMO_ATTR_COLOR, RGBColor(0, col, 0, 255));
                break;
            case SINK_DETECTOR:
                out.writeAttr(SUMO_ATTR_TYPE, "sink_detector_position").writeAttr(SUMO_ATTR_COLOR, RGBColor(col, 0, 0, 255));
                break;
            case DISCARDED_DETECTOR:
                out.writeAttr(SUMO_ATTR_TYPE, "discarded_detector_position").writeAttr(SUMO_ATTR_COLOR, RGBColor(51, 51, 51, 255));
                break;
            default:
                throw 1;
        }
        out.writeAttr(SUMO_ATTR_LANE, (*i)->getLaneID()).writeAttr(SUMO_ATTR_POSITION, (*i)->getPos()).closeTag();
    }
    out.close();
}
Esempio n. 2
0
void
RODFDetectorCon::writeEmitterPOIs(const std::string& file,
                                  const RODFDetectorFlows& flows) {
    OutputDevice& out = OutputDevice::getDevice(file);
    out.writeXMLHeader("additional");
    for (std::vector<RODFDetector*>::const_iterator i = myDetectors.begin(); i != myDetectors.end(); ++i) {
        RODFDetector* det = *i;
        SUMOReal flow = flows.getFlowSumSecure(det->getID());
        SUMOReal col = flow / flows.getMaxDetectorFlow();
        col = (SUMOReal)(col / 2. + .5);
        SUMOReal r, g, b;
        r = g = b = 0;
        out << "   <poi id=\"" << StringUtils::escapeXML((*i)->getID()) << ":" << flow;
        switch ((*i)->getType()) {
            case BETWEEN_DETECTOR:
                out << "\" type=\"between_detector_position\" color=\"0,0," << col << "\"";
                break;
            case SOURCE_DETECTOR:
                out << "\" type=\"source_detector_position\" color=\"0," << col << ",0\"";
                break;
            case SINK_DETECTOR:
                out << "\" type=\"sink_detector_position\" color=\"" << col << ",0,0\"";
                break;
            case DISCARDED_DETECTOR:
                out << "\" type=\"discarded_detector_position\" color=\".2,.2,.2\"";
                break;
            default:
                throw 1;
        }
        out << " lane=\"" << (*i)->getLaneID() << "\" pos=\"" << (*i)->getPos() << "\"/>\n";
    }
    out.close();
}
Esempio n. 3
0
void
RODFDetectorCon::guessEmptyFlows(RODFDetectorFlows& flows) {
    // routes must be built (we have ensured this in main)
    // detector followers/prior must be build (we have ensured this in main)
    //
    for (std::vector<RODFDetector*>::const_iterator i = myDetectors.begin(); i != myDetectors.end(); ++i) {
        RODFDetector* det = *i;
        const std::set<const RODFDetector*>& prior = det->getPriorDetectors();
        const std::set<const RODFDetector*>& follower = det->getFollowerDetectors();
        int noFollowerWithRoutes = 0;
        int noPriorWithRoutes = 0;
        // count occurences of detectors with/without routes
        std::set<const RODFDetector*>::const_iterator j;
        for (j = prior.begin(); j != prior.end(); ++j) {
            if (flows.knows((*j)->getID())) {
                ++noPriorWithRoutes;
            }
        }
        for (j = follower.begin(); j != follower.end(); ++j) {
            if (flows.knows((*j)->getID())) {
                ++noFollowerWithRoutes;
            }
        }

        // do not process detectors which have no routes
        if (!flows.knows(det->getID())) {
            continue;
        }

        // plain case: all of the prior detectors have routes
        if (noPriorWithRoutes == (int)prior.size()) {
            // the number of vehicles is the sum of all vehicles on prior
            continue;
        }

        // plain case: all of the follower detectors have routes
        if (noFollowerWithRoutes == (int)follower.size()) {
            // the number of vehicles is the sum of all vehicles on follower
            continue;
        }

    }
}
Esempio n. 4
0
void
RODFDetectorCon::writeEmitters(const std::string& file,
                               const RODFDetectorFlows& flows,
                               SUMOTime startTime, SUMOTime endTime,
                               SUMOTime stepOffset, const RODFNet& net,
                               bool writeCalibrators,
                               bool includeUnusedRoutes,
                               SUMOReal scale,
                               int maxFollower,
                               bool insertionsOnly) {
    // compute turn probabilities at detector
    for (std::vector<RODFDetector*>::const_iterator i = myDetectors.begin(); i != myDetectors.end(); ++i) {
        (*i)->computeSplitProbabilities(&net, *this, flows, startTime, endTime, stepOffset);
    }
    //
    OutputDevice& out = OutputDevice::getDevice(file);
    out.writeXMLHeader("additional");
    for (std::vector<RODFDetector*>::const_iterator i = myDetectors.begin(); i != myDetectors.end(); ++i) {
        RODFDetector* det = *i;
        // get file name for values (emitter/calibrator definition)
        std::string escapedID = StringUtils::escapeXML(det->getID());
        std::string defFileName;
        if (det->getType() == SOURCE_DETECTOR) {
            defFileName = file;
        } else if (writeCalibrators && det->getType() == BETWEEN_DETECTOR) {
            defFileName = FileHelpers::getFilePath(file) + "calibrator_" + escapedID + ".def.xml";
        } else {
            defFileName = FileHelpers::getFilePath(file) + "other_" + escapedID + ".def.xml";
            continue;
        }
        // try to write the definition
        SUMOReal defaultSpeed = net.getEdge(det->getEdgeID())->getSpeed();
        //  ... compute routes' distribution over time
        std::map<size_t, RandomDistributor<size_t>* > dists;
        if (!insertionsOnly && flows.knows(det->getID())) {
            det->buildDestinationDistribution(*this, flows, startTime, endTime, stepOffset, net, dists, maxFollower);
        }
        //  ... write the definition
        if (!det->writeEmitterDefinition(defFileName, dists, flows, startTime, endTime, stepOffset, includeUnusedRoutes, scale, insertionsOnly, defaultSpeed)) {
            // skip if something failed... (!!!)
            continue;
        }
        //  ... clear temporary values
        clearDists(dists);
        // write the declaration into the file
        if (writeCalibrators && det->getType() == BETWEEN_DETECTOR) {
            out << "   <calibrator id=\"calibrator_" << escapedID
                << "\" pos=\"" << det->getPos() << "\" "
                << "lane=\"" << det->getLaneID() << "\" "
                << "friendlyPos=\"x\" " // !!!
                << "file=\"" << defFileName << "\"/>\n";
        }
    }
    out.close();
}
Esempio n. 5
0
void
RODFNet::removeEmptyDetectors(RODFDetectorCon& detectors,
                              RODFDetectorFlows& flows) {
    const std::vector<RODFDetector*>& dets = detectors.getDetectors();
    for (std::vector<RODFDetector*>::const_iterator i = dets.begin(); i != dets.end();) {
        bool remove = true;
        // check whether there is at least one entry with a flow larger than zero
        if (flows.knows((*i)->getID())) {
            remove = false;
        }
        if (remove) {
            WRITE_MESSAGE("Removed detector '" + (*i)->getID() + "' because no flows for him exist.");
            flows.removeFlow((*i)->getID());
            detectors.removeDetector((*i)->getID());
            i = dets.begin();
        } else {
            i++;
        }
    }
}
Esempio n. 6
0
void
RODFNet::reportEmptyDetectors(RODFDetectorCon& detectors,
                              RODFDetectorFlows& flows) {
    const std::vector<RODFDetector*>& dets = detectors.getDetectors();
    for (std::vector<RODFDetector*>::const_iterator i = dets.begin(); i != dets.end(); ++i) {
        bool remove = true;
        // check whether there is at least one entry with a flow larger than zero
        if (flows.knows((*i)->getID())) {
            remove = false;
        }
        if (remove) {
            WRITE_MESSAGE("Detector '" + (*i)->getID() + "' has no flow.");
        }
    }
}
Esempio n. 7
0
void
RODFNet::mesoJoin(RODFDetectorCon& detectors, RODFDetectorFlows& flows) {
    buildDetectorEdgeDependencies(detectors);
    std::map<ROEdge*, std::vector<std::string>, idComp>::iterator i;
    for (i = myDetectorsOnEdges.begin(); i != myDetectorsOnEdges.end(); ++i) {
        const std::vector<std::string>& dets = (*i).second;
        std::map<SUMOReal, std::vector<std::string> > cliques;
        // compute detector cliques
        for (std::vector<std::string>::const_iterator j = dets.begin(); j != dets.end(); ++j) {
            const RODFDetector& det = detectors.getDetector(*j);
            bool found = false;
            for (std::map<SUMOReal, std::vector<std::string> >::iterator k = cliques.begin(); !found && k != cliques.end(); ++k) {
                if (fabs((*k).first - det.getPos()) < 10.) {
                    (*k).second.push_back(*j);
                    found = true;
                }
            }
            if (!found) {
                cliques[det.getPos()] = std::vector<std::string>();
                cliques[det.getPos()].push_back(*j);
            }
        }
        // join detector cliques
        for (std::map<SUMOReal, std::vector<std::string> >::iterator m = cliques.begin(); m != cliques.end(); ++m) {
            std::vector<std::string> clique = (*m).second;
            // do not join if only one
            if (clique.size() == 1) {
                continue;
            }
            std::string nid;
            for (std::vector<std::string>::iterator n = clique.begin(); n != clique.end(); ++n) {
                std::cout << *n << " ";
                if (n != clique.begin()) {
                    nid = nid + "_";
                }
                nid = nid + *n;
            }
            std::cout << ":" << nid << std::endl;
            flows.mesoJoin(nid, (*m).second);
            detectors.mesoJoin(nid, (*m).second);
        }
    }
}
void
RODFDetectorCon::writeSpeedTrigger(const RODFNet* const net,
                                   const std::string& file,
                                   const RODFDetectorFlows& flows,
                                   SUMOTime startTime, SUMOTime endTime,
                                   SUMOTime stepOffset) {
    OutputDevice& out = OutputDevice::getDevice(file);
    out.writeXMLHeader("additional");
    for (std::vector<RODFDetector*>::const_iterator i = myDetectors.begin(); i != myDetectors.end(); ++i) {
        RODFDetector* det = *i;
        // write the declaration into the file
        if (det->getType() == SINK_DETECTOR && flows.knows(det->getID())) {
            std::string filename = FileHelpers::getFilePath(file) + "vss_" + det->getID() + ".def.xml";
            out.openTag(SUMO_TAG_VSS).writeAttr(SUMO_ATTR_ID, StringUtils::escapeXML(det->getID())).writeAttr(SUMO_ATTR_LANES, det->getLaneID()).writeAttr(SUMO_ATTR_FILE, filename).closeTag();
            SUMOReal defaultSpeed = net != 0 ? net->getEdge(det->getEdgeID())->getSpeed() : (SUMOReal) 200.;
            det->writeSingleSpeedTrigger(filename, flows, startTime, endTime, stepOffset, defaultSpeed);
        }
    }
    out.close();
}
void
RODFDetector::writeSingleSpeedTrigger(const std::string& file,
                                      const RODFDetectorFlows& flows,
                                      SUMOTime startTime, SUMOTime endTime,
                                      SUMOTime stepOffset, SUMOReal defaultSpeed) {
    OutputDevice& out = OutputDevice::getDevice(file);
    out.writeXMLHeader("vss");
    const std::vector<FlowDef>& mflows = flows.getFlowDefs(myID);
    unsigned int index = 0;
    for (SUMOTime t = startTime; t < endTime; t += stepOffset, index++) {
        assert(index < mflows.size());
        const FlowDef& srcFD = mflows[index];
        SUMOReal speed = MAX2(srcFD.vLKW, srcFD.vPKW);
        if (speed <= 0 || speed > 250) {
            speed = defaultSpeed;
        } else {
            speed = (SUMOReal)(speed / 3.6);
        }
        out.openTag(SUMO_TAG_STEP).writeAttr(SUMO_ATTR_TIME, time2string(t)).writeAttr(SUMO_ATTR_SPEED, speed).closeTag();
    }
    out.close();
}
Esempio n. 10
0
void
RODFDetectorCon::writeSpeedTrigger(const RODFNet* const net,
                                   const std::string& file,
                                   const RODFDetectorFlows& flows,
                                   SUMOTime startTime, SUMOTime endTime,
                                   SUMOTime stepOffset) {
    OutputDevice& out = OutputDevice::getDevice(file);
    out.writeXMLHeader("additional");
    for (std::vector<RODFDetector*>::const_iterator i = myDetectors.begin(); i != myDetectors.end(); ++i) {
        RODFDetector* det = *i;
        // write the declaration into the file
        if (det->getType() == SINK_DETECTOR && flows.knows(det->getID())) {
            std::string filename = FileHelpers::getFilePath(file) + "vss_" + det->getID() + ".def.xml";
            out << "   <variableSpeedSign id=\"vss_" << StringUtils::escapeXML(det->getID()) << '\"'
                << " lanes=\"" << det->getLaneID() << '\"'
                << " file=\"" << filename << "\"/>\n";
            SUMOReal defaultSpeed = net != 0 ? net->getEdge(det->getEdgeID())->getSpeed() : (SUMOReal) 200.;
            det->writeSingleSpeedTrigger(filename, flows, startTime, endTime, stepOffset, defaultSpeed);
        }
    }
    out.close();
}
Esempio n. 11
0
void
RODFDetector::writeSingleSpeedTrigger(const std::string& file,
                                      const RODFDetectorFlows& flows,
                                      SUMOTime startTime, SUMOTime endTime,
                                      SUMOTime stepOffset, SUMOReal defaultSpeed) {
    OutputDevice& out = OutputDevice::getDevice(file);
    out.writeXMLHeader("vss");
    const std::vector<FlowDef> &mflows = flows.getFlowDefs(myID);
    int index = 0;
    for (SUMOTime t = startTime; t < endTime; t += stepOffset, index++) {
        assert(index < mflows.size());
        const FlowDef& srcFD = mflows[index];
        SUMOReal speed = MAX2(srcFD.vLKW, srcFD.vPKW);
        if (speed <= 0 || speed > 250) {
            speed = defaultSpeed;
        } else {
            speed = (SUMOReal)(speed / 3.6);
        }
        out << "   <step time=\"" << t << "\" speed=\"" << speed << "\"/>\n";
    }
    out.close();
}
Esempio n. 12
0
void
RODFNet::revalidateFlows(const RODFDetector* detector,
                         RODFDetectorFlows& flows,
                         SUMOTime startTime, SUMOTime endTime,
                         SUMOTime stepOffset) {
    {
        if (flows.knows(detector->getID())) {
            const std::vector<FlowDef>& detFlows = flows.getFlowDefs(detector->getID());
            for (std::vector<FlowDef>::const_iterator j = detFlows.begin(); j != detFlows.end(); ++j) {
                if ((*j).qPKW > 0 || (*j).qLKW > 0) {
                    return;
                }
            }
        }
    }
    // ok, there is no information for the whole time;
    //  lets find preceding detectors and rebuild the flows if possible
    WRITE_WARNING("Detector '" + detector->getID() + "' has no flows.\n Trying to rebuild.");
    // go back and collect flows
    std::vector<ROEdge*> previous;
    {
        std::vector<IterationEdge> missing;
        IterationEdge ie;
        ie.depth = 0;
        ie.edge = getDetectorEdge(*detector);
        missing.push_back(ie);
        bool maxDepthReached = false;
        while (!missing.empty() && !maxDepthReached) {
            IterationEdge last = missing.back();
            missing.pop_back();
            std::vector<ROEdge*> approaching = myApproachingEdges[last.edge];
            for (std::vector<ROEdge*>::const_iterator j = approaching.begin(); j != approaching.end(); ++j) {
                if (hasDetector(*j)) {
                    previous.push_back(*j);
                } else {
                    ie.depth = last.depth + 1;
                    ie.edge = *j;
                    missing.push_back(ie);
                    if (ie.depth > 5) {
                        maxDepthReached = true;
                    }
                }
            }
        }
        if (maxDepthReached) {
            WRITE_WARNING(" Could not build list of previous flows.");
        }
    }
    // Edges with previous detectors are now in "previous";
    //  compute following
    std::vector<ROEdge*> latter;
    {
        std::vector<IterationEdge> missing;
        for (std::vector<ROEdge*>::const_iterator k = previous.begin(); k != previous.end(); ++k) {
            IterationEdge ie;
            ie.depth = 0;
            ie.edge = *k;
            missing.push_back(ie);
        }
        bool maxDepthReached = false;
        while (!missing.empty() && !maxDepthReached) {
            IterationEdge last = missing.back();
            missing.pop_back();
            std::vector<ROEdge*> approached = myApproachedEdges[last.edge];
            for (std::vector<ROEdge*>::const_iterator j = approached.begin(); j != approached.end(); ++j) {
                if (*j == getDetectorEdge(*detector)) {
                    continue;
                }
                if (hasDetector(*j)) {
                    latter.push_back(*j);
                } else {
                    IterationEdge ie;
                    ie.depth = last.depth + 1;
                    ie.edge = *j;
                    missing.push_back(ie);
                    if (ie.depth > 5) {
                        maxDepthReached = true;
                    }
                }
            }
        }
        if (maxDepthReached) {
            WRITE_WARNING(" Could not build list of latter flows.");
            return;
        }
    }
    // Edges with latter detectors are now in "latter";

    // lets not validate them by now - surely this should be done
    // for each time step: collect incoming flows; collect outgoing;
    std::vector<FlowDef> mflows;
    int index = 0;
    for (SUMOTime t = startTime; t < endTime; t += stepOffset, index++) {
        FlowDef inFlow;
        inFlow.qLKW = 0;
        inFlow.qPKW = 0;
        inFlow.vLKW = 0;
        inFlow.vPKW = 0;
        // collect incoming
        {
            // !! time difference is missing
            for (std::vector<ROEdge*>::iterator i = previous.begin(); i != previous.end(); ++i) {
                const std::vector<FlowDef>& flows = static_cast<const RODFEdge*>(*i)->getFlows();
                if (flows.size() != 0) {
                    const FlowDef& srcFD = flows[index];
                    inFlow.qLKW += srcFD.qLKW;
                    inFlow.qPKW += srcFD.qPKW;
                    inFlow.vLKW += srcFD.vLKW;
                    inFlow.vPKW += srcFD.vPKW;
                }
            }
        }
        inFlow.vLKW /= (SUMOReal) previous.size();
        inFlow.vPKW /= (SUMOReal) previous.size();
        // collect outgoing
        FlowDef outFlow;
        outFlow.qLKW = 0;
        outFlow.qPKW = 0;
        outFlow.vLKW = 0;
        outFlow.vPKW = 0;
        {
            // !! time difference is missing
            for (std::vector<ROEdge*>::iterator i = latter.begin(); i != latter.end(); ++i) {
                const std::vector<FlowDef>& flows = static_cast<const RODFEdge*>(*i)->getFlows();
                if (flows.size() != 0) {
                    const FlowDef& srcFD = flows[index];
                    outFlow.qLKW += srcFD.qLKW;
                    outFlow.qPKW += srcFD.qPKW;
                    outFlow.vLKW += srcFD.vLKW;
                    outFlow.vPKW += srcFD.vPKW;
                }
            }
        }
        outFlow.vLKW /= (SUMOReal) latter.size();
        outFlow.vPKW /= (SUMOReal) latter.size();
        //
        FlowDef mFlow;
        mFlow.qLKW = inFlow.qLKW - outFlow.qLKW;
        mFlow.qPKW = inFlow.qPKW - outFlow.qPKW;
        mFlow.vLKW = (inFlow.vLKW + outFlow.vLKW) / (SUMOReal) 2.;
        mFlow.vPKW = (inFlow.vPKW + outFlow.vPKW) / (SUMOReal) 2.;
        mflows.push_back(mFlow);
    }
    static_cast<RODFEdge*>(getDetectorEdge(*detector))->setFlows(mflows);
    flows.setFlows(detector->getID(), mflows);
}
Esempio n. 13
0
bool
RODFDetector::writeEmitterDefinition(const std::string& file,
                                     const std::map<SUMOTime, RandomDistributor<int>* >& dists,
                                     const RODFDetectorFlows& flows,
                                     SUMOTime startTime, SUMOTime endTime,
                                     SUMOTime stepOffset,
                                     bool includeUnusedRoutes,
                                     SUMOReal scale,
                                     bool insertionsOnly,
                                     SUMOReal defaultSpeed) const {
    OutputDevice& out = OutputDevice::getDevice(file);
    OptionsCont& oc = OptionsCont::getOptions();
    if (getType() != SOURCE_DETECTOR) {
        out.writeXMLHeader("additional", "additional_file.xsd");
    }
    // routes
    if (myRoutes != 0 && myRoutes->get().size() != 0) {
        const std::vector<RODFRouteDesc>& routes = myRoutes->get();
        out.openTag(SUMO_TAG_ROUTE_DISTRIBUTION).writeAttr(SUMO_ATTR_ID, myID);
        bool isEmptyDist = true;
        for (std::vector<RODFRouteDesc>::const_iterator i = routes.begin(); i != routes.end(); ++i) {
            if ((*i).overallProb > 0) {
                isEmptyDist = false;
            }
        }
        for (std::vector<RODFRouteDesc>::const_iterator i = routes.begin(); i != routes.end(); ++i) {
            if ((*i).overallProb > 0 || includeUnusedRoutes) {
                out.openTag(SUMO_TAG_ROUTE).writeAttr(SUMO_ATTR_REFID, (*i).routename).writeAttr(SUMO_ATTR_PROB, (*i).overallProb).closeTag();
            }
            if (isEmptyDist) {
                out.openTag(SUMO_TAG_ROUTE).writeAttr(SUMO_ATTR_REFID, (*i).routename).writeAttr(SUMO_ATTR_PROB, SUMOReal(1)).closeTag();
            }
        }
        out.closeTag(); // routeDistribution
    } else {
        WRITE_ERROR("Detector '" + getID() + "' has no routes!?");
        return false;
    }
    // insertions
    if (insertionsOnly || flows.knows(myID)) {
        // get the flows for this detector
        const std::vector<FlowDef>& mflows = flows.getFlowDefs(myID);
        // go through the simulation seconds
        int index = 0;
        for (SUMOTime time = startTime; time < endTime; time += stepOffset, index++) {
            // get own (departure flow)
            assert(index < (int)mflows.size());
            const FlowDef& srcFD = mflows[index];  // !!! check stepOffset
            // get flows at end
            RandomDistributor<int>* destDist = dists.find(time) != dists.end() ? dists.find(time)->second : 0;
            // go through the cars
            int carNo = (int)((srcFD.qPKW + srcFD.qLKW) * scale);
            for (int car = 0; car < carNo; ++car) {
                // get the vehicle parameter
                SUMOReal v = -1;
                std::string vtype;
                int destIndex = destDist != 0 && destDist->getOverallProb() > 0 ? (int) destDist->get() : -1;
                if (srcFD.isLKW >= 1) {
                    srcFD.isLKW = srcFD.isLKW - (SUMOReal) 1.;
                    v = srcFD.vLKW;
                    vtype = "LKW";
                } else {
                    v = srcFD.vPKW;
                    vtype = "PKW";
                }
                // compute insertion speed
                if (v <= 0 || v > 250) {
                    v = defaultSpeed;
                } else {
                    v = (SUMOReal)(v / 3.6);
                }
                // compute the departure time
                SUMOTime ctime = (SUMOTime)(time + ((SUMOReal) stepOffset * (SUMOReal) car / (SUMOReal) carNo));

                // write
                out.openTag(SUMO_TAG_VEHICLE);
                if (getType() == SOURCE_DETECTOR) {
                    out.writeAttr(SUMO_ATTR_ID, "emitter_" + myID + "_" + toString(ctime));
                } else {
                    out.writeAttr(SUMO_ATTR_ID, "calibrator_" + myID + "_" + toString(ctime));
                }
                if (oc.getBool("vtype")) {
                    out.writeAttr(SUMO_ATTR_TYPE, vtype);
                }
                out.writeAttr(SUMO_ATTR_DEPART, time2string(ctime));
                if (oc.isSet("departlane")) {
                    out.writeNonEmptyAttr(SUMO_ATTR_DEPARTLANE, oc.getString("departlane"));
                } else {
                    out.writeAttr(SUMO_ATTR_DEPARTLANE, TplConvert::_2int(myLaneID.substr(myLaneID.rfind("_") + 1).c_str()));
                }
                if (oc.isSet("departpos")) {
                    std::string posDesc = oc.getString("departpos");
                    if (posDesc.substr(0, 8) == "detector") {
                        SUMOReal position = myPosition;
                        if (posDesc.length() > 8) {
                            if (posDesc[8] == '+') {
                                position += TplConvert::_2SUMOReal(posDesc.substr(9).c_str());
                            } else if (posDesc[8] == '-') {
                                position -= TplConvert::_2SUMOReal(posDesc.substr(9).c_str());
                            } else {
                                throw NumberFormatException();
                            }
                        }
                        out.writeAttr(SUMO_ATTR_DEPARTPOS, position);
                    } else {
                        out.writeNonEmptyAttr(SUMO_ATTR_DEPARTPOS, posDesc);
                    }
                } else {
                    out.writeAttr(SUMO_ATTR_DEPARTPOS, myPosition);
                }
                if (oc.isSet("departspeed")) {
                    out.writeNonEmptyAttr(SUMO_ATTR_DEPARTSPEED, oc.getString("departspeed"));
                } else {
                    out.writeAttr(SUMO_ATTR_DEPARTSPEED, v);
                }
                if (oc.isSet("arrivallane")) {
                    out.writeNonEmptyAttr(SUMO_ATTR_ARRIVALLANE, oc.getString("arrivallane"));
                }
                if (oc.isSet("arrivalpos")) {
                    out.writeNonEmptyAttr(SUMO_ATTR_ARRIVALPOS, oc.getString("arrivalpos"));
                }
                if (oc.isSet("arrivalspeed")) {
                    out.writeNonEmptyAttr(SUMO_ATTR_ARRIVALSPEED, oc.getString("arrivalspeed"));
                }
                if (destIndex >= 0) {
                    out.writeAttr(SUMO_ATTR_ROUTE, myRoutes->get()[destIndex].routename);
                } else {
                    out.writeAttr(SUMO_ATTR_ROUTE, myID);
                }
                out.closeTag();
                srcFD.isLKW += srcFD.fLKW;
            }
        }
    }
    if (getType() != SOURCE_DETECTOR) {
        out.close();
    }
    return true;
}
Esempio n. 14
0
bool
RODFDetector::writeEmitterDefinition(const std::string& file,
                                     const std::map<size_t, RandomDistributor<size_t>* > &dists,
                                     const RODFDetectorFlows& flows,
                                     SUMOTime startTime, SUMOTime endTime,
                                     SUMOTime stepOffset,
                                     bool includeUnusedRoutes,
                                     SUMOReal scale,
                                     bool insertionsOnly,
                                     SUMOReal defaultSpeed) const {
    OutputDevice& out = OutputDevice::getDevice(file);
    if (getType() != SOURCE_DETECTOR) {
        out.writeXMLHeader("calibrator");
    }
    // routes
    if (myRoutes != 0 && myRoutes->get().size() != 0) {
        const std::vector<RODFRouteDesc> &routes = myRoutes->get();
        out.openTag("routeDistribution") <<  " id=\"" << myID << "\">\n";
        bool isEmptyDist = true;
        for (std::vector<RODFRouteDesc>::const_iterator i = routes.begin(); i != routes.end(); ++i) {
            if ((*i).overallProb > 0) {
                isEmptyDist = false;
            }
        }
        for (std::vector<RODFRouteDesc>::const_iterator i = routes.begin(); i != routes.end(); ++i) {
            if ((*i).overallProb > 0 || includeUnusedRoutes) {
                out.openTag("route") << " refId=\"" << (*i).routename << "\" probability=\"" << (*i).overallProb << "\"";
                out.closeTag(true);
            }
            if (isEmptyDist) {
                out.openTag("route") << " refId=\"" << (*i).routename << "\" probability=\"1\"";
                out.closeTag(true);
            }
        }
        out.closeTag();
    } else {
        WRITE_ERROR("Detector '" + getID() + "' has no routes!?");
        return false;
    }
    // emissions
    if (insertionsOnly || flows.knows(myID)) {
        // get the flows for this detector

        const std::vector<FlowDef> &mflows = flows.getFlowDefs(myID);
        // go through the simulation seconds
        int index = 0;
        for (SUMOTime time = startTime; time < endTime; time += stepOffset, index++) {
            // get own (departure flow)
            assert(index < mflows.size());
            const FlowDef& srcFD = mflows[index];  // !!! check stepOffset
            // get flows at end
            RandomDistributor<size_t> *destDist = dists.find(time) != dists.end() ? dists.find(time)->second : 0;
            // go through the cars
            size_t carNo = (size_t)((srcFD.qPKW + srcFD.qLKW) * scale);
            for (size_t car = 0; car < carNo; ++car) {
                // get the vehicle parameter
                std::string type = "test";
                SUMOReal v = -1;
                int destIndex = destDist != 0 && destDist->getOverallProb() > 0 ? (int) destDist->get() : -1;
                if (srcFD.isLKW >= 1) {
                    srcFD.isLKW = srcFD.isLKW - (SUMOReal) 1.;
//!!!		        	type = lkwTypes[vehSpeedDist.get()];
                    v = srcFD.vLKW;
                } else {
//!!!	    			type = pkwTypes[vehSpeedDist.get()];
                    v = srcFD.vPKW;
                }
                // compute emission speed
                if (v < 0 || v > 250) {
                    v = defaultSpeed;
                } else {
                    v = (SUMOReal)(v / 3.6);
                }
                // compute the departure time
                SUMOTime ctime = (SUMOTime)(time + ((SUMOReal) stepOffset * (SUMOReal) car / (SUMOReal) carNo));

                // write
                out.openTag("vehicle") << " id=\"";
                if (getType() == SOURCE_DETECTOR) {
                    out << "emitter_" << myID;
                } else {
                    out << "calibrator_" << myID;
                }
                out << "_" << ctime  << "\"" // !!! running
                    << " depart=\"" << time2string(ctime) << "\""
                    << " departSpeed=\"";
                if (v > defaultSpeed) {
                    out << "max";
                } else {
                    out << v;
                }
                out << "\" departPos=\"" << myPosition << "\""
                    << " departLane=\"" << myLaneID.substr(myLaneID.rfind("_") + 1) << "\" route=\"";
                if (destIndex >= 0) {
                    out << myRoutes->get()[destIndex].routename << "\"";
                } else {
                    out << myID << "\"";
                }
                out.closeTag(true);
                srcFD.isLKW += srcFD.fLKW;
            }
        }
    }
    if (getType() != SOURCE_DETECTOR) {
        out.close();
    }
    return true;
}
Esempio n. 15
0
void
RODFDetectorCon::writeEmitters(const std::string& file,
                               const RODFDetectorFlows& flows,
                               SUMOTime startTime, SUMOTime endTime,
                               SUMOTime stepOffset, const RODFNet& net,
                               bool writeCalibrators,
                               bool includeUnusedRoutes,
                               SUMOReal scale,
                               bool insertionsOnly) {
    // compute turn probabilities at detector
    for (std::vector<RODFDetector*>::const_iterator i = myDetectors.begin(); i != myDetectors.end(); ++i) {
        (*i)->computeSplitProbabilities(&net, *this, flows, startTime, endTime, stepOffset);
    }
    //
    OutputDevice& out = OutputDevice::getDevice(file);
    out.writeXMLHeader("additional", "additional_file.xsd");
    // write vType(s)
    const bool separateVTypeOutput = OptionsCont::getOptions().getString("vtype-output") != "";
    OutputDevice& vTypeOut = separateVTypeOutput ? OutputDevice::getDevice(OptionsCont::getOptions().getString("vtype-output")) : out;
    if (separateVTypeOutput) {
        vTypeOut.writeXMLHeader("additional", "additional_file.xsd");
    }
    const bool forceDev = !OptionsCont::getOptions().isDefault("speeddev");
    const SUMOReal speedDev = OptionsCont::getOptions().getFloat("speeddev");
    if (OptionsCont::getOptions().getBool("vtype")) {
        // write separate types
        SUMOVTypeParameter pkwType = SUMOVTypeParameter("PKW", SVC_PASSENGER);
        setSpeedFactorAndDev(pkwType, net.getMaxSpeedFactorPKW(), net.getAvgSpeedFactorPKW(), speedDev, forceDev);
        pkwType.setParameter |= VTYPEPARS_VEHICLECLASS_SET;
        pkwType.write(vTypeOut);
        SUMOVTypeParameter lkwType = SUMOVTypeParameter("LKW", SVC_TRUCK);
        setSpeedFactorAndDev(lkwType, net.getMaxSpeedFactorLKW(), net.getAvgSpeedFactorLKW(), speedDev, forceDev);
        lkwType.setParameter |= VTYPEPARS_VEHICLECLASS_SET;
        lkwType.write(vTypeOut);
    } else {
        // patch default type
        SUMOVTypeParameter type = SUMOVTypeParameter(DEFAULT_VTYPE_ID, SVC_PASSENGER);
        setSpeedFactorAndDev(type, MAX2(net.getMaxSpeedFactorPKW(), net.getMaxSpeedFactorLKW()), net.getAvgSpeedFactorPKW(), speedDev, forceDev);
        if (type.setParameter != 0) {
            type.write(vTypeOut);
        }
    }


    for (std::vector<RODFDetector*>::const_iterator i = myDetectors.begin(); i != myDetectors.end(); ++i) {
        RODFDetector* det = *i;
        // get file name for values (emitter/calibrator definition)
        std::string escapedID = StringUtils::escapeXML(det->getID());
        std::string defFileName;
        if (det->getType() == SOURCE_DETECTOR) {
            defFileName = file;
        } else if (writeCalibrators && det->getType() == BETWEEN_DETECTOR) {
            defFileName = FileHelpers::getFilePath(file) + "calibrator_" + escapedID + ".def.xml";
        } else {
            defFileName = FileHelpers::getFilePath(file) + "other_" + escapedID + ".def.xml";
            continue;
        }
        // try to write the definition
        SUMOReal defaultSpeed = net.getEdge(det->getEdgeID())->getSpeed();
        //  ... compute routes' distribution over time
        std::map<SUMOTime, RandomDistributor<int>* > dists;
        if (!insertionsOnly && flows.knows(det->getID())) {
            det->buildDestinationDistribution(*this, startTime, endTime, stepOffset, net, dists);
        }
        //  ... write the definition
        if (!det->writeEmitterDefinition(defFileName, dists, flows, startTime, endTime, stepOffset, includeUnusedRoutes, scale, insertionsOnly, defaultSpeed)) {
            // skip if something failed... (!!!)
            continue;
        }
        //  ... clear temporary values
        clearDists(dists);
        // write the declaration into the file
        if (writeCalibrators && det->getType() == BETWEEN_DETECTOR) {
            out.openTag(SUMO_TAG_CALIBRATOR).writeAttr(SUMO_ATTR_ID, "calibrator_" + escapedID).writeAttr(SUMO_ATTR_POSITION, det->getPos());
            out.writeAttr(SUMO_ATTR_LANE, det->getLaneID()).writeAttr(SUMO_ATTR_FRIENDLY_POS, true).writeAttr(SUMO_ATTR_FILE, defFileName).closeTag();
        }
    }
    out.close();
    if (separateVTypeOutput) {
        vTypeOut.close();
    }
}
bool
RODFDetector::writeEmitterDefinition(const std::string& file,
                                     const std::map<size_t, RandomDistributor<size_t>* >& dists,
                                     const RODFDetectorFlows& flows,
                                     SUMOTime startTime, SUMOTime endTime,
                                     SUMOTime stepOffset,
                                     bool includeUnusedRoutes,
                                     SUMOReal scale,
                                     bool insertionsOnly,
                                     SUMOReal defaultSpeed) const {
    OutputDevice& out = OutputDevice::getDevice(file);
    if (getType() != SOURCE_DETECTOR) {
        out.writeXMLHeader("calibrator");
    }
    // routes
    if (myRoutes != 0 && myRoutes->get().size() != 0) {
        const std::vector<RODFRouteDesc>& routes = myRoutes->get();
        out.openTag(SUMO_TAG_ROUTE_DISTRIBUTION).writeAttr(SUMO_ATTR_ID, myID);
        bool isEmptyDist = true;
        for (std::vector<RODFRouteDesc>::const_iterator i = routes.begin(); i != routes.end(); ++i) {
            if ((*i).overallProb > 0) {
                isEmptyDist = false;
            }
        }
        for (std::vector<RODFRouteDesc>::const_iterator i = routes.begin(); i != routes.end(); ++i) {
            if ((*i).overallProb > 0 || includeUnusedRoutes) {
                out.openTag(SUMO_TAG_ROUTE).writeAttr(SUMO_ATTR_REFID, (*i).routename).writeAttr(SUMO_ATTR_PROB, (*i).overallProb).closeTag();
            }
            if (isEmptyDist) {
                out.openTag(SUMO_TAG_ROUTE).writeAttr(SUMO_ATTR_REFID, (*i).routename).writeAttr(SUMO_ATTR_PROB, SUMOReal(1)).closeTag();
            }
        }
        out.closeTag(); // routeDistribution
    } else {
        WRITE_ERROR("Detector '" + getID() + "' has no routes!?");
        return false;
    }
    // insertions
    if (insertionsOnly || flows.knows(myID)) {
        // get the flows for this detector
        const std::vector<FlowDef>& mflows = flows.getFlowDefs(myID);
        // go through the simulation seconds
        unsigned int index = 0;
        for (SUMOTime time = startTime; time < endTime; time += stepOffset, index++) {
            // get own (departure flow)
            assert(index < mflows.size());
            const FlowDef& srcFD = mflows[index];  // !!! check stepOffset
            // get flows at end
            RandomDistributor<size_t>* destDist = dists.find(time) != dists.end() ? dists.find(time)->second : 0;
            // go through the cars
            size_t carNo = (size_t)((srcFD.qPKW + srcFD.qLKW) * scale);
            for (size_t car = 0; car < carNo; ++car) {
                // get the vehicle parameter
                SUMOReal v = -1;
                int destIndex = destDist != 0 && destDist->getOverallProb() > 0 ? (int) destDist->get() : -1;
                if (srcFD.isLKW >= 1) {
                    srcFD.isLKW = srcFD.isLKW - (SUMOReal) 1.;
                    v = srcFD.vLKW;
                } else {
                    v = srcFD.vPKW;
                }
                // compute insertion speed
                if (v <= 0 || v > 250) {
                    v = defaultSpeed;
                } else {
                    v = (SUMOReal)(v / 3.6);
                }
                // compute the departure time
                SUMOTime ctime = (SUMOTime)(time + ((SUMOReal) stepOffset * (SUMOReal) car / (SUMOReal) carNo));

                // write
                out.openTag(SUMO_TAG_VEHICLE);
                if (getType() == SOURCE_DETECTOR) {
                    out.writeAttr(SUMO_ATTR_ID, "emitter_" + myID + "_" + toString(ctime));
                } else {
                    out.writeAttr(SUMO_ATTR_ID, "calibrator_" + myID + "_" + toString(ctime));
                }
                out.writeAttr(SUMO_ATTR_DEPART, time2string(ctime));
                if (v > defaultSpeed) {
                    out.writeAttr(SUMO_ATTR_DEPARTSPEED, "max");
                } else {
                    out.writeAttr(SUMO_ATTR_DEPARTSPEED, v);
                }
                out.writeAttr(SUMO_ATTR_DEPARTPOS, myPosition).writeAttr(SUMO_ATTR_DEPARTLANE, TplConvert::_2int(myLaneID.substr(myLaneID.rfind("_") + 1).c_str()));
                if (destIndex >= 0) {
                    out.writeAttr(SUMO_ATTR_ROUTE, myRoutes->get()[destIndex].routename);
                } else {
                    out.writeAttr(SUMO_ATTR_ROUTE, myID);
                }
                out.closeTag();
                srcFD.isLKW += srcFD.fLKW;
            }
        }
    }
    if (getType() != SOURCE_DETECTOR) {
        out.close();
    }
    return true;
}
Esempio n. 17
0
void
RODFNet::buildEdgeFlowMap(const RODFDetectorFlows& flows,
                          const RODFDetectorCon& detectors,
                          SUMOTime startTime, SUMOTime endTime,
                          SUMOTime stepOffset) {
    std::map<ROEdge*, std::vector<std::string>, idComp>::iterator i;
    for (i = myDetectorsOnEdges.begin(); i != myDetectorsOnEdges.end(); ++i) {
        ROEdge* into = (*i).first;
        const std::vector<std::string>& dets = (*i).second;
        std::map<SUMOReal, std::vector<std::string> > cliques;
        std::vector<std::string>* maxClique = 0;
        for (std::vector<std::string>::const_iterator j = dets.begin(); j != dets.end(); ++j) {
            if (!flows.knows(*j)) {
                continue;
            }
            const RODFDetector& det = detectors.getDetector(*j);
            bool found = false;
            for (std::map<SUMOReal, std::vector<std::string> >::iterator k = cliques.begin(); !found && k != cliques.end(); ++k) {
                if (fabs((*k).first - det.getPos()) < 1) {
                    (*k).second.push_back(*j);
                    if ((*k).second.size() > maxClique->size()) {
                        maxClique = &(*k).second;
                    }
                    found = true;
                }
            }
            if (!found) {
                cliques[det.getPos()].push_back(*j);
                maxClique = &cliques[det.getPos()];
            }
        }
        if (maxClique == 0) {
            continue;
        }
        std::vector<FlowDef> mflows; // !!! reserve
        for (SUMOTime t = startTime; t < endTime; t += stepOffset) {
            FlowDef fd;
            fd.qPKW = 0;
            fd.qLKW = 0;
            fd.vLKW = 0;
            fd.vPKW = 0;
            fd.fLKW = 0;
            fd.isLKW = 0;
            mflows.push_back(fd);
        }
        for (std::vector<std::string>::iterator l = maxClique->begin(); l != maxClique->end(); ++l) {
            bool didWarn = false;
            const std::vector<FlowDef>& dflows = flows.getFlowDefs(*l);
            int index = 0;
            for (SUMOTime t = startTime; t < endTime; t += stepOffset, index++) {
                const FlowDef& srcFD = dflows[index];
                FlowDef& fd = mflows[index];
                fd.qPKW += srcFD.qPKW;
                fd.qLKW += srcFD.qLKW;
                fd.vLKW += (srcFD.vLKW / (SUMOReal) maxClique->size());
                fd.vPKW += (srcFD.vPKW / (SUMOReal) maxClique->size());
                fd.fLKW += (srcFD.fLKW / (SUMOReal) maxClique->size());
                fd.isLKW += (srcFD.isLKW / (SUMOReal) maxClique->size());
                if (!didWarn && srcFD.vPKW > 0 && srcFD.vPKW < 255 && srcFD.vPKW / 3.6 > into->getSpeed()) {
                    WRITE_MESSAGE("Detected PKW speed higher than allowed speed at '" + (*l) + "' on '" + into->getID() + "'.");
                    didWarn = true;
                }
                if (!didWarn && srcFD.vLKW > 0 && srcFD.vLKW < 255 && srcFD.vLKW / 3.6 > into->getSpeed()) {
                    WRITE_MESSAGE("Detected LKW speed higher than allowed speed at '" + (*l) + "' on '" + into->getID() + "'.");
                    didWarn = true;
                }
            }
        }
        static_cast<RODFEdge*>(into)->setFlows(mflows);
    }
}
void
startComputation(RODFNet* optNet, RODFDetectorFlows& flows, RODFDetectorCon& detectors, OptionsCont& oc) {
    if (oc.getBool("print-absolute-flows")) {
        flows.printAbsolute();
    }

    // if a network was loaded... (mode1)
    if (optNet != 0) {
        if (oc.getBool("remove-empty-detectors")) {
            PROGRESS_BEGIN_MESSAGE("Removing empty detectors");
            optNet->removeEmptyDetectors(detectors, flows);
            PROGRESS_DONE_MESSAGE();
        } else  if (oc.getBool("report-empty-detectors")) {
            PROGRESS_BEGIN_MESSAGE("Scanning for empty detectors");
            optNet->reportEmptyDetectors(detectors, flows);
            PROGRESS_DONE_MESSAGE();
        }
        // compute the detector types (optionally)
        if (!detectors.detectorsHaveCompleteTypes() || oc.getBool("revalidate-detectors")) {
            optNet->computeTypes(detectors, oc.getBool("strict-sources"));
        }
        std::vector<RODFDetector*>::const_iterator i = detectors.getDetectors().begin();
        for (; i != detectors.getDetectors().end(); ++i) {
            if ((*i)->getType() == SOURCE_DETECTOR) {
                break;
            }
        }
        if (i == detectors.getDetectors().end() && !oc.getBool("routes-for-all")) {
            throw ProcessError("No source detectors found.");
        }
        // compute routes between the detectors (optionally)
        if (!detectors.detectorsHaveRoutes() || oc.getBool("revalidate-routes") || oc.getBool("guess-empty-flows")) {
            PROGRESS_BEGIN_MESSAGE("Computing routes");
            optNet->buildRoutes(detectors,
                                oc.getBool("all-end-follower"), oc.getBool("keep-unfinished-routes"),
                                oc.getBool("routes-for-all"), !oc.getBool("keep-longer-routes"),
                                oc.getInt("max-search-depth"));
            PROGRESS_DONE_MESSAGE();
        }
    }

    // check
    // whether the detectors are valid
    if (!detectors.detectorsHaveCompleteTypes()) {
        throw ProcessError("The detector types are not defined; use in combination with a network");
    }
    // whether the detectors have routes
    if (!detectors.detectorsHaveRoutes()) {
        throw ProcessError("The emitters have no routes; use in combination with a network");
    }

    // save the detectors if wished
    if (oc.isSet("detector-output")) {
        detectors.save(oc.getString("detector-output"));
    }
    // save their positions as POIs if wished
    if (oc.isSet("detectors-poi-output")) {
        detectors.saveAsPOIs(oc.getString("detectors-poi-output"));
    }

    // save the routes file if it was changed or it's wished
    if (detectors.detectorsHaveRoutes() && oc.isSet("routes-output")) {
        detectors.saveRoutes(oc.getString("routes-output"));
    }

    // guess flows if wished
    if (oc.getBool("guess-empty-flows")) {
        optNet->buildDetectorDependencies(detectors);
        detectors.guessEmptyFlows(flows);
    }

    const SUMOTime begin = string2time(oc.getString("begin"));
    const SUMOTime end = string2time(oc.getString("end"));
    const SUMOTime step = string2time(oc.getString("time-step"));

    // save emitters if wished
    if (oc.isSet("emitters-output") || oc.isSet("emitters-poi-output")) {
        optNet->buildEdgeFlowMap(flows, detectors, begin, end, step); // !!!
        if (oc.getBool("revalidate-flows")) {
            PROGRESS_BEGIN_MESSAGE("Rechecking loaded flows");
            optNet->revalidateFlows(detectors, flows, begin, end, step);
            PROGRESS_DONE_MESSAGE();
        }
        if (oc.isSet("emitters-output")) {
            PROGRESS_BEGIN_MESSAGE("Writing emitters");
            detectors.writeEmitters(oc.getString("emitters-output"), flows,
                                    begin, end, step,
                                    *optNet,
                                    oc.getBool("calibrator-output"),
                                    oc.getBool("include-unused-routes"),
                                    oc.getFloat("scale"),
//                                    oc.getInt("max-search-depth"),
                                    oc.getBool("emissions-only"));
            PROGRESS_DONE_MESSAGE();
        }
        if (oc.isSet("emitters-poi-output")) {
            PROGRESS_BEGIN_MESSAGE("Writing emitter pois");
            detectors.writeEmitterPOIs(oc.getString("emitters-poi-output"), flows);
            PROGRESS_DONE_MESSAGE();
        }
    }
    // save end speed trigger if wished
    if (oc.isSet("variable-speed-sign-output")) {
        PROGRESS_BEGIN_MESSAGE("Writing speed triggers");
        detectors.writeSpeedTrigger(optNet, oc.getString("variable-speed-sign-output"), flows,
                                    begin, end, step);
        PROGRESS_DONE_MESSAGE();
    }
    // save checking detectors if wished
    if (oc.isSet("validation-output")) {
        PROGRESS_BEGIN_MESSAGE("Writing validation detectors");
        detectors.writeValidationDetectors(oc.getString("validation-output"),
                                           oc.getBool("validation-output.add-sources"), true, true); // !!!
        PROGRESS_DONE_MESSAGE();
    }
    // build global rerouter on end if wished
    if (oc.isSet("end-reroute-output")) {
        PROGRESS_BEGIN_MESSAGE("Writing highway end rerouter");
        detectors.writeEndRerouterDetectors(oc.getString("end-reroute-output")); // !!!
        PROGRESS_DONE_MESSAGE();
    }
    /*
       // save the insertion definitions
       if(oc.isSet("flow-definitions")) {
           buildVehicleEmissions(oc.getString("flow-definitions"));
       }
    */
    //
}