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