#include <config.h>
#include <iostream>
#include <string>
#include <iomanip>
#include <utils/options/OptionsCont.h>
#include <utils/common/ToString.h>
#include <utils/common/StringTokenizer.h>
#include <utils/common/MsgHandler.h>
#include <utils/common/UtilExceptions.h>
#include <utils/common/FileHelpers.h>
#include <utils/xml/XMLSubSys.h>
#include <utils/xml/SAXWeightsHandler.h>
#include <utils/vehicle/SUMORouteLoader.h>
#include <utils/vehicle/SUMORouteLoaderControl.h>
#include "RONet.h"
#include "RONetHandler.h"
#include "ROLoader.h"
#include "ROLane.h"
#include "ROEdge.h"
#include "RORouteHandler.h"
void
ROLoader::EdgeFloatTimeLineRetriever_EdgeTravelTime::addEdgeWeight(const std::string& id,
double val, double beg, double end) const {
ROEdge* e = myNet.getEdge(id);
if (e != nullptr) {
e->addTravelTime(val, beg, end);
} else {
if (id[0] != ':') {
if (OptionsCont::getOptions().getBool("ignore-errors")) {
WRITE_WARNINGF(TL("Trying to set a weight for the unknown edge '%'."), id);
} else {
WRITE_ERRORF(TL("Trying to set a weight for the unknown edge '%'."), id);
}
}
}
}
void
ROLoader::EdgeFloatTimeLineRetriever_EdgeWeight::addEdgeWeight(const std::string& id,
double val, double beg, double end) const {
ROEdge* e = myNet.getEdge(id);
if (e != nullptr) {
e->addEffort(val, beg, end);
} else {
if (id[0] != ':') {
if (OptionsCont::getOptions().getBool("ignore-errors")) {
WRITE_WARNINGF(TL("Trying to set a weight for the unknown edge '%'."), id);
} else {
WRITE_ERRORF(TL("Trying to set a weight for the unknown edge '%'."), id);
}
}
}
}
ROLoader::ROLoader(OptionsCont& oc, const bool emptyDestinationsAllowed, const bool logSteps) :
myOptions(oc),
myEmptyDestinationsAllowed(emptyDestinationsAllowed),
myLogSteps(logSteps),
myLoaders(oc.exists("unsorted-input") && oc.getBool("unsorted-input") ? 0 : DELTA_T) {
}
ROLoader::~ROLoader() {
}
void
ROLoader::loadNet(RONet& toFill, ROAbstractEdgeBuilder& eb) {
std::string file = myOptions.getString("net-file");
if (file == "") {
throw ProcessError(TL("Missing definition of network to load!"));
}
if (!FileHelpers::isReadable(file)) {
throw ProcessError(TLF("The network file '%' is not accessible.", file));
}
PROGRESS_BEGIN_MESSAGE(TL("Loading net"));
RONetHandler handler(toFill, eb, !myOptions.exists("no-internal-links") || myOptions.getBool("no-internal-links"),
myOptions.exists("weights.minor-penalty") ? myOptions.getFloat("weights.minor-penalty") : 0,
myOptions.exists("weights.tls-penalty") ? myOptions.getFloat("weights.tls-penalty") : 0,
myOptions.exists("weights.turnaround-penalty") ? myOptions.getFloat("weights.turnaround-penalty") : 0);
handler.setFileName(file);
if (!XMLSubSys::runParser(handler, file, true)) {
PROGRESS_FAILED_MESSAGE();
throw ProcessError();
} else {
PROGRESS_DONE_MESSAGE();
}
if (!deprecatedVehicleClassesSeen.empty()) {
WRITE_WARNINGF(TL("Deprecated vehicle classes '%' in input network."), toString(deprecatedVehicleClassesSeen));
deprecatedVehicleClassesSeen.clear();
}
if (myOptions.isSet("additional-files", false)) {
std::vector<std::string> files = myOptions.getStringVector("additional-files");
for (std::vector<std::string>::const_iterator fileIt = files.begin(); fileIt != files.end(); ++fileIt) {
if (!FileHelpers::isReadable(*fileIt)) {
throw ProcessError(TLF("The additional file '%' is not accessible.", *fileIt));
}
PROGRESS_BEGIN_MESSAGE("Loading additional file '" + *fileIt + "' ");
handler.setFileName(*fileIt);
if (!XMLSubSys::runParser(handler, *fileIt)) {
PROGRESS_FAILED_MESSAGE();
throw ProcessError();
} else {
PROGRESS_DONE_MESSAGE();
}
}
}
if (myOptions.exists("junction-taz") && myOptions.getBool("junction-taz")) {
toFill.addJunctionTaz(eb);
}
toFill.setBidiEdges(handler.getBidiMap());
if (myOptions.exists("restriction-params") && myOptions.isSet("restriction-params")) {
const std::vector<std::string> paramKeys = myOptions.getStringVector("restriction-params");
for (auto& edgeIt : toFill.getEdgeMap()) {
edgeIt.second->cacheParamRestrictions(paramKeys);
}
}
if (toFill.hasRestrictions()) {
for (auto& edgeIt : toFill.getEdgeMap()) {
edgeIt.second->setRestrictions(toFill.getRestrictions(edgeIt.second->getType()));
}
}
}
void
ROLoader::openRoutes(RONet& net) {
bool ok = openTypedRoutes("additional-files", net, true);
ok &= openTypedRoutes("route-files", net);
if (ok) {
myLoaders.loadNext(string2time(myOptions.getString("begin")));
if (!net.furtherStored()) {
if (MsgHandler::getErrorInstance()->wasInformed()) {
throw ProcessError();
} else {
const std::string error = "No route input specified or all routes were invalid.";
if (myOptions.getBool("ignore-errors")) {
WRITE_WARNING(error);
} else {
throw ProcessError(error);
}
}
}
if (!myOptions.getBool("unsorted-input")) {
WRITE_MESSAGE("Skipped until: " + time2string(myLoaders.getFirstLoadTime()));
}
}
}
void
ROLoader::processRoutes(const SUMOTime start, const SUMOTime end, const SUMOTime increment,
RONet& net, const RORouterProvider& provider) {
const SUMOTime absNo = end - start;
const bool endGiven = !OptionsCont::getOptions().isDefault("end");
const SUMOTime firstStep = myLoaders.getFirstLoadTime();
SUMOTime lastStep = firstStep;
SUMOTime time = MIN2(firstStep, end);
while (time <= end) {
writeStats(time, start, absNo, endGiven);
myLoaders.loadNext(time);
if (!net.furtherStored() || MsgHandler::getErrorInstance()->wasInformed()) {
break;
}
lastStep = net.saveAndRemoveRoutesUntil(myOptions, provider, time);
if (time == end || (!net.furtherStored() && myLoaders.haveAllLoaded()) || MsgHandler::getErrorInstance()->wasInformed()) {
break;
}
if (time < end && time > end - increment) {
time = end;
} else {
time += increment;
}
}
if (myLogSteps) {
WRITE_MESSAGEF(TL("Routes found between time steps % and %."), time2string(firstStep), time2string(lastStep));
}
}
bool
ROLoader::openTypedRoutes(const std::string& optionName,
RONet& net, const bool readAll) {
if (!myOptions.isUsableFileList(optionName)) {
return !myOptions.isSet(optionName);
}
for (const std::string& fileIt : myOptions.getStringVector(optionName)) {
try {
RORouteHandler* handler = new RORouteHandler(net, fileIt, myOptions.getBool("repair"), myEmptyDestinationsAllowed, myOptions.getBool("ignore-errors"), !readAll);
if (readAll) {
if (!XMLSubSys::runParser(*handler, fileIt)) {
WRITE_ERRORF(TL("Loading of % failed."), fileIt);
return false;
}
delete handler;
} else {
myLoaders.add(new SUMORouteLoader(handler));
}
} catch (ProcessError& e) {
WRITE_ERRORF(TL("The loader for % from file '%' could not be initialised (%)."), optionName, fileIt, e.what());
return false;
}
}
return true;
}
bool
ROLoader::loadWeights(RONet& net, const std::string& optionName,
const std::string& measure, const bool useLanes, const bool boundariesOverride) {
if (!myOptions.isUsableFileList(optionName)) {
return false;
}
std::vector<SAXWeightsHandler::ToRetrieveDefinition*> retrieverDefs;
EdgeFloatTimeLineRetriever_EdgeTravelTime ttRetriever(net);
retrieverDefs.push_back(new SAXWeightsHandler::ToRetrieveDefinition("traveltime", !useLanes, ttRetriever));
EdgeFloatTimeLineRetriever_EdgeWeight eRetriever(net);
if (measure != "traveltime") {
std::string umeasure = measure;
if (measure == "CO" || measure == "CO2" || measure == "HC" || measure == "PMx" || measure == "NOx" || measure == "fuel" || measure == "electricity") {
umeasure = measure + "_perVeh";
}
retrieverDefs.push_back(new SAXWeightsHandler::ToRetrieveDefinition(umeasure, !useLanes, eRetriever));
}
SAXWeightsHandler handler(retrieverDefs, "");
std::vector<std::string> files = myOptions.getStringVector(optionName);
for (std::vector<std::string>::const_iterator fileIt = files.begin(); fileIt != files.end(); ++fileIt) {
PROGRESS_BEGIN_MESSAGE("Loading precomputed net weights from '" + *fileIt + "'");
if (XMLSubSys::runParser(handler, *fileIt)) {
PROGRESS_DONE_MESSAGE();
} else {
WRITE_MESSAGE(TL("failed."));
return false;
}
}
for (const auto& i : net.getEdgeMap()) {
i.second->buildTimeLines(measure, boundariesOverride);
}
return true;
}
void
ROLoader::writeStats(const SUMOTime time, const SUMOTime start, const SUMOTime absNo, bool endGiven) {
if (myLogSteps) {
if (endGiven) {
const double perc = (double)(time - start) / (double) absNo;
std::cout << "Reading up to time step: " + time2string(time) + " (" + time2string(time - start) + "/" + time2string(absNo) + " = " + toString(perc * 100) + "% done) \r";
} else {
std::cout << "Reading up to time step: " + time2string(time) + "\r";
}
}
}
SUMORouteHandler*
ROLoader::getRouteHandler() {
auto loader = myLoaders.getFirstLoader();
if (loader != nullptr) {
return loader->getRouteHandler();
} else {
return nullptr;
}
}