SUMO - Simulation of Urban MObility

NLTriggerBuilder.cpp

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