SUMO - Simulation of Urban MObility

NLTriggerBuilder.cpp

Go to the documentation of this file.
00001 /****************************************************************************/
00012 // Builds trigger objects for microsim
00013 /****************************************************************************/
00014 // SUMO, Simulation of Urban MObility; see http://sumo.sourceforge.net/
00015 // Copyright (C) 2001-2012 DLR (http://www.dlr.de/) and contributors
00016 /****************************************************************************/
00017 //
00018 //   This file is part of SUMO.
00019 //   SUMO is free software: you can redistribute it and/or modify
00020 //   it under the terms of the GNU General Public License as published by
00021 //   the Free Software Foundation, either version 3 of the License, or
00022 //   (at your option) any later version.
00023 //
00024 /****************************************************************************/
00025 
00026 
00027 // ===========================================================================
00028 // included modules
00029 // ===========================================================================
00030 #ifdef _MSC_VER
00031 #include <windows_config.h>
00032 #else
00033 #include <config.h>
00034 #endif
00035 
00036 #include <string>
00037 #include <microsim/MSEventControl.h>
00038 #include <microsim/MSLane.h>
00039 #include <microsim/MSGlobals.h>
00040 #include <microsim/trigger/MSLaneSpeedTrigger.h>
00041 #include <microsim/trigger/MSTriggeredRerouter.h>
00042 #include <microsim/trigger/MSBusStop.h>
00043 #include <utils/common/StringTokenizer.h>
00044 #include <utils/common/FileHelpers.h>
00045 #include <utils/common/UtilExceptions.h>
00046 #include <utils/common/WrappingCommand.h>
00047 #include "NLHandler.h"
00048 #include "NLTriggerBuilder.h"
00049 #include <utils/xml/SUMOXMLDefinitions.h>
00050 
00051 
00052 #ifdef HAVE_MESOSIM
00053 #include <mesosim/METriggeredCalibrator.h>
00054 #endif
00055 
00056 #ifdef CHECK_MEMORY_LEAKS
00057 #include <foreign/nvwa/debug_new.h>
00058 #endif // CHECK_MEMORY_LEAKS
00059 
00060 
00061 // ===========================================================================
00062 // method definitions
00063 // ===========================================================================
00064 NLTriggerBuilder::NLTriggerBuilder()
00065     : myHandler(0), myHaveWarnedAboutDeprecatedFriendlyPos(false) {}
00066 
00067 
00068 NLTriggerBuilder::~NLTriggerBuilder() {}
00069 
00070 void
00071 NLTriggerBuilder::setHandler(NLHandler* handler) {
00072     myHandler = handler;
00073 }
00074 
00075 
00076 void
00077 NLTriggerBuilder::buildVaporizer(const SUMOSAXAttributes& attrs) {
00078     bool ok = true;
00079     // get the id, throw if not given or empty...
00080     std::string id = attrs.getStringReporting(SUMO_ATTR_ID, 0, ok);
00081     if (!ok) {
00082         return;
00083     }
00084     MSEdge* e = MSEdge::dictionary(id);
00085     if (e == 0) {
00086         WRITE_ERROR("Unknown edge ('" + id + "') referenced in a vaporizer.");
00087         return;
00088     }
00089     SUMOTime begin = attrs.getSUMOTimeReporting(SUMO_ATTR_BEGIN, 0, ok);
00090     SUMOTime end = attrs.getSUMOTimeReporting(SUMO_ATTR_END, 0, ok);
00091     if (!ok) {
00092         return;
00093     }
00094     if (begin < 0) {
00095         WRITE_ERROR("A vaporization begin time is negative (edge id='" + id + "').");
00096         return;
00097     }
00098     if (begin >= end) {
00099         WRITE_ERROR("A vaporization ends before it starts (edge id='" + id + "').");
00100         return;
00101     }
00102     if (end >= string2time(OptionsCont::getOptions().getString("begin"))) {
00103         Command* cb = new WrappingCommand< MSEdge >(e, &MSEdge::incVaporization);
00104         MSNet::getInstance()->getBeginOfTimestepEvents().addEvent(cb, begin, MSEventControl::ADAPT_AFTER_EXECUTION);
00105         Command* ce = new WrappingCommand< MSEdge >(e, &MSEdge::decVaporization);
00106         MSNet::getInstance()->getBeginOfTimestepEvents().addEvent(ce, end, MSEventControl::ADAPT_AFTER_EXECUTION);
00107     }
00108 }
00109 
00110 
00111 
00112 void
00113 NLTriggerBuilder::parseAndBuildLaneSpeedTrigger(MSNet& net, const SUMOSAXAttributes& attrs,
00114         const std::string& base) throw(InvalidArgument) {
00115     // get the id, throw if not given or empty...
00116     bool ok = true;
00117     // get the id, throw if not given or empty...
00118     std::string id = attrs.getStringReporting(SUMO_ATTR_ID, 0, ok);
00119     if (!ok) {
00120         return;
00121     }
00122     // get the file name to read further definitions from
00123     std::string file = getFileName(attrs, base, true);
00124     std::string objectid = attrs.getStringReporting(SUMO_ATTR_LANES, id.c_str(), ok);
00125     if (!ok) {
00126         throw InvalidArgument("The lanes to use within MSLaneSpeedTrigger '" + id + "' are not known.");
00127     }
00128     std::vector<MSLane*> lanes;
00129     std::vector<std::string> laneIDs;
00130     SUMOSAXAttributes::parseStringVector(objectid, laneIDs);
00131     for (std::vector<std::string>::iterator i = laneIDs.begin(); i != laneIDs.end(); ++i) {
00132         MSLane* lane = MSLane::dictionary(*i);
00133         if (lane == 0) {
00134             throw InvalidArgument("The lane to use within MSLaneSpeedTrigger '" + id + "' is not known.");
00135         }
00136         lanes.push_back(lane);
00137     }
00138     if (lanes.size() == 0) {
00139         throw InvalidArgument("No lane defined for MSLaneSpeedTrigger '" + id + "'.");
00140     }
00141     try {
00142         MSLaneSpeedTrigger* trigger = buildLaneSpeedTrigger(net, id, lanes, file);
00143         if (file == "") {
00144             trigger->registerParent(SUMO_TAG_VSS, myHandler);
00145         }
00146     } catch (ProcessError& e) {
00147         throw InvalidArgument(e.what());
00148     }
00149 }
00150 
00151 
00152 void
00153 NLTriggerBuilder::parseAndBuildBusStop(MSNet& net, const SUMOSAXAttributes& attrs) throw(InvalidArgument) {
00154     bool ok = true;
00155     // get the id, throw if not given or empty...
00156     std::string id = attrs.getStringReporting(SUMO_ATTR_ID, 0, ok);
00157     if (!ok) {
00158         throw ProcessError();
00159     }
00160     // get the lane
00161     MSLane* lane = getLane(attrs, "bus_stop", id);
00162     // get the positions
00163     SUMOReal frompos = attrs.getOptSUMORealReporting(SUMO_ATTR_STARTPOS, id.c_str(), ok, 0);
00164     SUMOReal topos = attrs.getOptSUMORealReporting(SUMO_ATTR_ENDPOS, id.c_str(), ok, lane->getLength());
00165     if (attrs.hasAttribute(SUMO_ATTR_FROM) || attrs.hasAttribute(SUMO_ATTR_TO)) {
00166         WRITE_WARNING("Deprecated attribute 'from' or 'to' in description of bus stop '" + id + "'.");
00167         frompos = attrs.getOptSUMORealReporting(SUMO_ATTR_FROM, id.c_str(), ok, 0);
00168         topos = attrs.getOptSUMORealReporting(SUMO_ATTR_TO, id.c_str(), ok, lane->getLength());
00169     }
00170     if (attrs.hasAttribute(SUMO_ATTR_FRIENDLY_POS__DEPRECATED) && !myHaveWarnedAboutDeprecatedFriendlyPos) {
00171         myHaveWarnedAboutDeprecatedFriendlyPos = true;
00172         WRITE_WARNING("'" + toString(SUMO_ATTR_FRIENDLY_POS__DEPRECATED) + "' is deprecated, use '" + toString(SUMO_ATTR_FRIENDLY_POS) + "' instead.");
00173     }
00174     const bool friendlyPos = attrs.hasAttribute(SUMO_ATTR_FRIENDLY_POS__DEPRECATED)
00175                              ? attrs.getOptBoolReporting(SUMO_ATTR_FRIENDLY_POS__DEPRECATED, id.c_str(), ok, false)
00176                              : attrs.getOptBoolReporting(SUMO_ATTR_FRIENDLY_POS, id.c_str(), ok, false);
00177     if (!ok || !myHandler->checkStopPos(frompos, topos, lane->getLength(), 10., friendlyPos)) {
00178         throw InvalidArgument("Invalid position for bus stop '" + id + "'.");
00179     }
00180     // get the lines
00181     std::vector<std::string> lines;
00182     SUMOSAXAttributes::parseStringVector(attrs.getOptStringReporting(SUMO_ATTR_LINES, id.c_str(), ok, ""), lines);
00183     // build the bus stop
00184     buildBusStop(net, id, lines, lane, frompos, topos);
00185 }
00186 
00187 
00188 #ifdef HAVE_MESOSIM
00189 void
00190 NLTriggerBuilder::parseAndBuildCalibrator(MSNet& net, const SUMOSAXAttributes& attrs,
00191         const std::string& base) throw(InvalidArgument) {
00192     bool ok = true;
00193     // get the id, throw if not given or empty...
00194     std::string id = attrs.getStringReporting(SUMO_ATTR_ID, 0, ok);
00195     if (!ok) {
00196         throw ProcessError();
00197     }
00198     // get the file name to read further definitions from
00199     MSLane* lane = getLane(attrs, "calibrator", id);
00200     const SUMOReal pos = getPosition(attrs, lane, "calibrator", id);
00201     if (MSGlobals::gUseMesoSim) {
00202         const SUMOTime freq = attrs.getOptSUMOTimeReporting(SUMO_ATTR_FREQUENCY, id.c_str(), ok, DELTA_T); // !!! no error handling
00203         std::string file = getFileName(attrs, base, true);
00204         bool ok = true;
00205         std::string outfile = attrs.getOptStringReporting(SUMO_ATTR_OUTPUT, 0, ok, "");
00206         METriggeredCalibrator* trigger = buildCalibrator(net, id, &lane->getEdge(), pos, file, outfile, freq);
00207         if (file == "") {
00208             trigger->registerParent(SUMO_TAG_CALIBRATOR, myHandler);
00209         }
00210     }
00211 }
00212 #endif
00213 
00214 
00215 void
00216 NLTriggerBuilder::parseAndBuildRerouter(MSNet& net, const SUMOSAXAttributes& attrs,
00217                                         const std::string& base) throw(InvalidArgument) {
00218     bool ok = true;
00219     // get the id, throw if not given or empty...
00220     std::string id = attrs.getStringReporting(SUMO_ATTR_ID, 0, ok);
00221     if (!ok) {
00222         throw ProcessError();
00223     }
00224     // get the file name to read further definitions from
00225     std::string file = getFileName(attrs, base);
00226     std::string objectid = attrs.getStringReporting(SUMO_ATTR_EDGES, id.c_str(), ok);
00227     if (!ok) {
00228         throw InvalidArgument("The edge to use within MSTriggeredRerouter '" + id + "' is not known.");
00229     }
00230     std::vector<MSEdge*> edges;
00231     std::vector<std::string> edgeIDs;
00232     SUMOSAXAttributes::parseStringVector(objectid, edgeIDs);
00233     for (std::vector<std::string>::iterator i = edgeIDs.begin(); i != edgeIDs.end(); ++i) {
00234         MSEdge* edge = MSEdge::dictionary(*i);
00235         if (edge == 0) {
00236             throw InvalidArgument("The edge to use within MSTriggeredRerouter '" + id + "' is not known.");
00237         }
00238         edges.push_back(edge);
00239     }
00240     if (edges.size() == 0) {
00241         throw InvalidArgument("No edges found for MSTriggeredRerouter '" + id + "'.");
00242     }
00243     SUMOReal prob = attrs.getOptSUMORealReporting(SUMO_ATTR_PROB, id.c_str(), ok, 1);
00244     bool off = attrs.getOptBoolReporting(SUMO_ATTR_OFF, id.c_str(), ok, false);
00245     if (!ok) {
00246         throw InvalidArgument("Could not parse MSTriggeredRerouter '" + id + "'.");
00247     }
00248     buildRerouter(net, id, edges, prob, file, off);
00249 }
00250 
00251 
00252 // -------------------------
00253 
00254 
00255 MSLaneSpeedTrigger*
00256 NLTriggerBuilder::buildLaneSpeedTrigger(MSNet& /*net*/, const std::string& id,
00257                                         const std::vector<MSLane*> &destLanes,
00258                                         const std::string& file) {
00259     return new MSLaneSpeedTrigger(id, destLanes, file);
00260 }
00261 
00262 
00263 #ifdef HAVE_MESOSIM
00264 METriggeredCalibrator*
00265 NLTriggerBuilder::buildCalibrator(MSNet& net, const std::string& id,
00266                                   const MSEdge* edge, SUMOReal pos,
00267                                   const std::string& file,
00268                                   const std::string& outfile,
00269                                   const SUMOTime freq) {
00270     return new METriggeredCalibrator(id, edge, pos, file, outfile, freq);
00271 }
00272 #endif
00273 
00274 
00275 void
00276 NLTriggerBuilder::buildRerouter(MSNet&, const std::string& id,
00277                                 std::vector<MSEdge*> &edges,
00278                                 SUMOReal prob, const std::string& file, bool off) {
00279     new MSTriggeredRerouter(id, edges, prob, file, off);
00280 }
00281 
00282 
00283 void
00284 NLTriggerBuilder::buildBusStop(MSNet& net, const std::string& id,
00285                                const std::vector<std::string> &lines,
00286                                MSLane* lane, SUMOReal frompos, SUMOReal topos) throw(InvalidArgument) {
00287     MSBusStop* stop = new MSBusStop(id, lines, *lane, frompos, topos);
00288     if (!net.addBusStop(stop)) {
00289         delete stop;
00290         throw InvalidArgument("Could not build bus stop '" + id + "'; probably declared twice.");
00291     }
00292 }
00293 
00294 
00295 
00296 
00297 std::string
00298 NLTriggerBuilder::getFileName(const SUMOSAXAttributes& attrs,
00299                               const std::string& base,
00300                               const bool allowEmpty) throw(InvalidArgument) {
00301     // get the file name to read further definitions from
00302     bool ok = true;
00303     std::string file = attrs.getOptStringReporting(SUMO_ATTR_FILE, 0, ok, "");
00304     if (file == "") {
00305         if (allowEmpty) {
00306             return file;
00307         }
00308         throw InvalidArgument("No filename given.");
00309     }
00310     // check whether absolute or relative filenames are given
00311     if (!FileHelpers::isAbsolute(file)) {
00312         return FileHelpers::getConfigurationRelative(base, file);
00313     }
00314     return file;
00315 }
00316 
00317 
00318 MSLane*
00319 NLTriggerBuilder::getLane(const SUMOSAXAttributes& attrs,
00320                           const std::string& tt,
00321                           const std::string& tid) throw(InvalidArgument) {
00322     bool ok = true;
00323     std::string objectid = attrs.getStringReporting(SUMO_ATTR_LANE, tid.c_str(), ok);
00324     MSLane* lane = MSLane::dictionary(objectid);
00325     if (lane == 0) {
00326         throw InvalidArgument("The lane " + objectid + " to use within the " + tt + " '" + tid + "' is not known.");
00327     }
00328     return lane;
00329 }
00330 
00331 
00332 SUMOReal
00333 NLTriggerBuilder::getPosition(const SUMOSAXAttributes& attrs,
00334                               MSLane* lane,
00335                               const std::string& tt, const std::string& tid) throw(InvalidArgument) {
00336     if (attrs.hasAttribute(SUMO_ATTR_FRIENDLY_POS__DEPRECATED) && !myHaveWarnedAboutDeprecatedFriendlyPos) {
00337         myHaveWarnedAboutDeprecatedFriendlyPos = true;
00338         WRITE_WARNING("'" + toString(SUMO_ATTR_FRIENDLY_POS__DEPRECATED) + "' is deprecated, use '" + toString(SUMO_ATTR_FRIENDLY_POS) + "' instead.");
00339     }
00340     bool ok = true;
00341     SUMOReal pos = attrs.getSUMORealReporting(SUMO_ATTR_POSITION, 0, ok);
00342     const bool friendlyPos = attrs.hasAttribute(SUMO_ATTR_FRIENDLY_POS__DEPRECATED)
00343                              ? attrs.getOptBoolReporting(SUMO_ATTR_FRIENDLY_POS__DEPRECATED, 0, ok, false)
00344                              : attrs.getOptBoolReporting(SUMO_ATTR_FRIENDLY_POS, 0, ok, false);
00345     if (!ok) {
00346         throw InvalidArgument("Error on parsing a position information.");
00347     }
00348     if (pos < 0) {
00349         pos = lane->getLength() + pos;
00350     }
00351     if (pos > lane->getLength()) {
00352         if (friendlyPos) {
00353             pos = lane->getLength() - (SUMOReal) 0.1;
00354         } else {
00355             throw InvalidArgument("The position of " + tt + " '" + tid + "' lies beyond the lane's '" + lane->getID() + "' length.");
00356         }
00357     }
00358     return pos;
00359 }
00360 
00361 
00362 
00363 /****************************************************************************/
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Friends Defines