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 2001-2010 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/MSEmitter.h>
00036 #include <microsim/trigger/MSTriggeredRerouter.h>
00037 #include <microsim/trigger/MSBusStop.h>
00038 #include <utils/common/StringTokenizer.h>
00039 #include <utils/common/FileHelpers.h>
00040 #include <utils/common/UtilExceptions.h>
00041 #include <utils/common/WrappingCommand.h>
00042 #include "NLHandler.h"
00043 #include "NLTriggerBuilder.h"
00044 #include <utils/xml/SUMOXMLDefinitions.h>
00045 #include <microsim/trigger/MSCalibrator.h>
00046 
00047 
00048 #ifdef HAVE_MESOSIM
00049 #include <mesosim/METriggeredCalibrator.h>
00050 #endif
00051 
00052 #ifdef CHECK_MEMORY_LEAKS
00053 #include <foreign/nvwa/debug_new.h>
00054 #endif // CHECK_MEMORY_LEAKS
00055 
00056 
00057 // ===========================================================================
00058 // method definitions
00059 // ===========================================================================
00060 NLTriggerBuilder::NLTriggerBuilder() throw()
00061         : myHaveInformedAboutDeprecatedTriggerDefinition(false),
00062         myHaveInformedAboutDeprecatedEmitter(false), myHandler(0) {}
00063 
00064 
00065 NLTriggerBuilder::~NLTriggerBuilder() throw() {}
00066 
00067 void
00068 NLTriggerBuilder::setHandler(NLHandler *handler) throw() {
00069     myHandler = handler;
00070 }
00071 
00072 
00073 void
00074 NLTriggerBuilder::buildTrigger(MSNet &net,
00075                                const SUMOSAXAttributes &attrs,
00076                                const std::string &base) throw(InvalidArgument) {
00077     bool ok = true;
00078     std::string type = attrs.getStringReporting(SUMO_ATTR_OBJECTTYPE, 0, 0, ok);
00079     std::string attr = attrs.getOptStringReporting(SUMO_ATTR_ATTR, 0, 0, ok, "");
00080     // check which type of a trigger shall be build
00081     if (type=="lane"&&attr=="speed") {
00082         parseAndBuildLaneSpeedTrigger(net, attrs, base);
00083     } else if (type=="emitter") {
00084         parseAndBuildLaneEmitTrigger(net, attrs, base);
00085     } else if (type=="rerouter") {
00086         parseAndBuildRerouter(net, attrs, base);
00087     } else if (type=="bus_stop") {
00088         parseAndBuildBusStop(net, attrs);
00089     } else if (type=="calibrator") {
00090         parseAndBuildCalibrator(net, attrs, base);
00091     }
00092     if (!myHaveInformedAboutDeprecatedTriggerDefinition) {
00093         MsgHandler::getWarningInstance()->inform("Defining '" + type + "' using a trigger definition is deprecated.");
00094         myHaveInformedAboutDeprecatedTriggerDefinition = true;
00095     }
00096 }
00097 
00098 
00099 
00100 void
00101 NLTriggerBuilder::buildVaporizer(const SUMOSAXAttributes &attrs) throw() {
00102     // get the id, throw if not given or empty...
00103     std::string id;
00104     if (!attrs.setIDFromAttributes("vaporizer", id, false)) {
00105         MsgHandler::getErrorInstance()->inform("Missing or empty id in a vaporizer-object.");
00106         return;
00107     }
00108     MSEdge *e = MSEdge::dictionary(id);
00109     if (e==0) {
00110         MsgHandler::getErrorInstance()->inform("Unknown edge ('" + id + "') referenced in a vaporizer.");
00111         return;
00112     }
00113     bool ok = true;
00114     SUMOTime begin = attrs.getSUMOTimeReporting(SUMO_ATTR_BEGIN, "vaporizer", 0, ok);
00115     SUMOTime end = attrs.getSUMOTimeReporting(SUMO_ATTR_END, "vaporizer", 0, ok);
00116     if (!ok) {
00117         return;
00118     }
00119     if (begin<0) {
00120         MsgHandler::getErrorInstance()->inform("A vaporization begin time is negative (edge id='" + id + "').");
00121         return;
00122     }
00123     if (begin>=end) {
00124         MsgHandler::getErrorInstance()->inform("A vaporization ends before it starts (edge id='" + id + "').");
00125         return;
00126     }
00127     if (end>=string2time(OptionsCont::getOptions().getString("begin"))) {
00128         Command* cb = new WrappingCommand< MSEdge >(e, &MSEdge::incVaporization);
00129         MSNet::getInstance()->getBeginOfTimestepEvents().addEvent(cb, begin, MSEventControl::ADAPT_AFTER_EXECUTION);
00130         Command* ce = new WrappingCommand< MSEdge >(e, &MSEdge::decVaporization);
00131         MSNet::getInstance()->getBeginOfTimestepEvents().addEvent(ce, end, MSEventControl::ADAPT_AFTER_EXECUTION);
00132     }
00133 }
00134 
00135 
00136 
00137 void
00138 NLTriggerBuilder::parseAndBuildLaneSpeedTrigger(MSNet &net, const SUMOSAXAttributes &attrs,
00139         const std::string &base) throw(InvalidArgument) {
00140     // get the id, throw if not given or empty...
00141     std::string id;
00142     if (!attrs.setIDFromAttributes("lane speed trigger", id, false)) {
00143         throw InvalidArgument("A lane speed trigger definition does not contain an id");
00144     }
00145     // get the file name to read further definitions from
00146     std::string file = getFileName(attrs, base, true);
00147     std::string objectid;
00148     bool ok = true;
00149     if (attrs.hasAttribute(SUMO_ATTR_LANES)) {
00150         objectid = attrs.getStringReporting(SUMO_ATTR_LANES, "vss", id.c_str(), ok);
00151     } else {
00152         if (attrs.hasAttribute(SUMO_ATTR_OBJECTID)) {
00153             objectid = attrs.getStringReporting(SUMO_ATTR_OBJECTID, "vss", id.c_str(), ok);
00154             MsgHandler::getWarningInstance()->inform("Defining the lanes using 'objectid' within a variable speed sign is deprecated, use 'lanes' instead.");
00155         }
00156     }
00157     if (!ok) {
00158         throw InvalidArgument("The lanes to use within MSLaneSpeedTrigger '" + id + "' are not known.");
00159     }
00160     std::vector<MSLane*> lanes;
00161     std::vector<std::string> laneIDs;
00162     SUMOSAXAttributes::parseStringVector(objectid, laneIDs);
00163     for (std::vector<std::string>::iterator i=laneIDs.begin(); i!=laneIDs.end(); ++i) {
00164         MSLane *lane = MSLane::dictionary(*i);
00165         if (lane==0) {
00166             throw InvalidArgument("The lane to use within MSLaneSpeedTrigger '" + id + "' is not known.");
00167         }
00168         lanes.push_back(lane);
00169     }
00170     if (lanes.size()==0) {
00171         throw InvalidArgument("No lane defined for MSLaneSpeedTrigger '" + id + "'.");
00172     }
00173     try {
00174         MSLaneSpeedTrigger* trigger = buildLaneSpeedTrigger(net, id, lanes, file);
00175         if (file == "") {
00176             trigger->registerParent(SUMO_TAG_VSS, myHandler);
00177         }
00178     } catch (ProcessError &e) {
00179         throw InvalidArgument(e.what());
00180     }
00181 }
00182 
00183 
00184 void
00185 NLTriggerBuilder::parseAndBuildLaneEmitTrigger(MSNet &net, const SUMOSAXAttributes &attrs,
00186         const std::string &base) throw(InvalidArgument) {
00187     if (!myHaveInformedAboutDeprecatedEmitter) {
00188         myHaveInformedAboutDeprecatedEmitter = true;
00189         MsgHandler::getWarningInstance()->inform("Emitter are deprecated; use departpos/departspeed within routes instead.");
00190     }
00191     // get the id, throw if not given or empty...
00192     std::string id;
00193     if (!attrs.setIDFromAttributes("emitter", id, false)) {
00194         throw InvalidArgument("An emitter does not contain an id");
00195     }
00196     // get the file name to read further definitions from
00197     std::string file = getFileName(attrs, base);
00198     MSLane *lane = getLane(attrs, "emitter", id);
00199     SUMOReal pos = getPosition(attrs, lane, "emitter", id);
00200     buildLaneEmitTrigger(net, id, lane, pos, file);
00201 }
00202 
00203 
00204 void
00205 NLTriggerBuilder::parseAndBuildBusStop(MSNet &net, const SUMOSAXAttributes &attrs) throw(InvalidArgument) {
00206     // get the id, throw if not given or empty...
00207     std::string id;
00208     if (!attrs.setIDFromAttributes("bus stop", id, false)) {
00209         throw InvalidArgument("A bus stop does not contain an id");
00210     }
00211     // get the lane
00212     MSLane *lane = getLane(attrs, "bus_stop", id);
00213     // get the positions
00214     bool ok = true;
00215     SUMOReal frompos = attrs.getSUMORealReporting(SUMO_ATTR_FROM, "busstop", id.c_str(), ok);
00216     SUMOReal topos = attrs.getSUMORealReporting(SUMO_ATTR_TO, "busstop", id.c_str(), ok);
00217     bool friendlyPos = attrs.getOptBoolReporting(SUMO_ATTR_FRIENDLY_POS, "busstop", id.c_str(), ok, false);
00218     if (!ok) {
00219         throw InvalidArgument("Error on parsing a bus stop.");
00220     }
00221     if (frompos<0) {
00222         frompos = lane->getLength() + frompos;
00223     }
00224     if (topos<0) {
00225         topos = lane->getLength() + topos;
00226     }
00227     // check positions
00228     if (topos<0 || topos>lane->getLength()) {
00229         if (!friendlyPos) {
00230             throw InvalidArgument("Bus stop '" + id + "' ends after the lane's end.");
00231         } else {
00232             MsgHandler::getWarningInstance()->inform("Bus stop '" + id + "' ends after the lane's end (moving to the end).");
00233             topos = lane->getLength() - (SUMOReal) .1;
00234         }
00235     }
00236     if (frompos<0 || frompos>lane->getLength()) {
00237         if (!friendlyPos) {
00238             throw InvalidArgument("Bus stop '" + id + "' begins after the lane's end.");
00239         } else {
00240             MsgHandler::getWarningInstance()->inform("Bus stop '" + id + "' begins after the lane's end (moving to the begin-10m).");
00241             frompos = MAX2(SUMOReal(0), SUMOReal(topos-10.));
00242         }
00243     }
00244     if (topos<frompos) {
00245         throw InvalidArgument("Bus stop's '" + id + "' end is in front of its begin.");
00246     }
00247     // get the lines
00248     std::vector<std::string> lines;
00249     SUMOSAXAttributes::parseStringVector(attrs.getOptStringReporting(SUMO_ATTR_LINES, "busstop", id.c_str(), ok, ""), lines);
00250     // build the bus stop
00251     buildBusStop(net, id, lines, lane, frompos, topos);
00252 }
00253 
00254 
00255 void
00256 NLTriggerBuilder::parseAndBuildCalibrator(MSNet &net, const SUMOSAXAttributes &attrs,
00257         const std::string &base) throw(InvalidArgument) {
00258     // get the id, throw if not given or empty...
00259     std::string id;
00260     if (!attrs.setIDFromAttributes("calibrator", id, false)) {
00261         throw InvalidArgument("A calibrator does not contain an id");
00262     }
00263     // get the file name to read further definitions from
00264     MSLane *lane = getLane(attrs, "calibrator", id);
00265     SUMOReal pos = getPosition(attrs, lane, "calibrator", id);
00266     bool ok = true;
00267     SUMOTime freq = attrs.getOptSUMOTimeReporting(SUMO_ATTR_FREQUENCY, "meandata_lane", id.c_str(), ok, DELTA_T); // !!! no error handling
00268 #ifdef HAVE_MESOSIM
00269     if (MSGlobals::gUseMesoSim) {
00270         std::string file = getFileName(attrs, base, true);
00271         bool ok = true;
00272         std::string outfile = attrs.getOptStringReporting(SUMO_ATTR_OUTPUT, 0, 0, ok, "");
00273         METriggeredCalibrator* trigger = buildCalibrator(net, id, &lane->getEdge(), pos, file, outfile, freq);
00274         if (file == "") {
00275             trigger->registerParent(SUMO_TAG_CALIBRATOR, myHandler);
00276         }
00277     } else {
00278 #endif
00279         std::string file = getFileName(attrs, base);
00280         buildLaneCalibrator(net, id, lane, pos, file);
00281 #ifdef HAVE_MESOSIM
00282     }
00283 #endif
00284 }
00285 
00286 
00287 void
00288 NLTriggerBuilder::parseAndBuildRerouter(MSNet &net, const SUMOSAXAttributes &attrs,
00289                                         const std::string &base) throw(InvalidArgument) {
00290     // get the id, throw if not given or empty...
00291     std::string id;
00292     if (!attrs.setIDFromAttributes("rerouter", id, false)) {
00293         throw InvalidArgument("A rerouter does not contain an id");
00294     }
00295     // get the file name to read further definitions from
00296     std::string file = getFileName(attrs, base);
00297     std::string objectid;
00298     bool ok = true;
00299     if (attrs.hasAttribute(SUMO_ATTR_EDGES)) {
00300         objectid = attrs.getStringReporting(SUMO_ATTR_EDGES, "rerouter", id.c_str(), ok);
00301     } else {
00302         if (attrs.hasAttribute(SUMO_ATTR_OBJECTID)) {
00303             objectid = attrs.getStringReporting(SUMO_ATTR_OBJECTID, "rerouter", id.c_str(), ok);
00304             MsgHandler::getWarningInstance()->inform("Defining the edges using 'objectid' within a rerouter is deprecated, use 'edges' instead.");
00305         }
00306     }
00307     if (!ok) {
00308         throw InvalidArgument("The edge to use within MSTriggeredRerouter '" + id + "' is not known.");
00309     }
00310     std::vector<MSEdge*> edges;
00311     std::vector<std::string> edgeIDs;
00312     SUMOSAXAttributes::parseStringVector(objectid, edgeIDs);
00313     for (std::vector<std::string>::iterator i=edgeIDs.begin(); i!=edgeIDs.end(); ++i) {
00314         MSEdge *edge = MSEdge::dictionary(*i);
00315         if (edge==0) {
00316             throw InvalidArgument("The edge to use within MSTriggeredRerouter '" + id + "' is not known.");
00317         }
00318         edges.push_back(edge);
00319     }
00320     if (edges.size()==0) {
00321         throw InvalidArgument("No edges found for MSTriggeredRerouter '" + id + "'.");
00322     }
00323     SUMOReal prob = attrs.getOptSUMORealReporting(SUMO_ATTR_PROB, "rerouter", id.c_str(), ok, 1);
00324     bool off = attrs.getOptBoolReporting(SUMO_ATTR_OFF, "rerouter", id.c_str(), ok, false);
00325     if (!ok) {
00326         throw InvalidArgument("Could not parse MSTriggeredRerouter '" + id + "'.");
00327     }
00328     buildRerouter(net, id, edges, prob, file, off);
00329 }
00330 
00331 
00332 // -------------------------
00333 
00334 
00335 MSLaneSpeedTrigger*
00336 NLTriggerBuilder::buildLaneSpeedTrigger(MSNet &net, const std::string &id,
00337                                         const std::vector<MSLane*> &destLanes,
00338                                         const std::string &file) throw(ProcessError) {
00339     return new MSLaneSpeedTrigger(id, destLanes, file);
00340 }
00341 
00342 
00343 void
00344 NLTriggerBuilder::buildLaneEmitTrigger(MSNet &net, const std::string &id,
00345                                        MSLane *destLane, SUMOReal pos,
00346                                        const std::string &file) throw() {
00347     new MSEmitter(id, net, destLane, pos, file);
00348 }
00349 
00350 
00351 void
00352 NLTriggerBuilder::buildLaneCalibrator(MSNet &net, const std::string &id,
00353                                       MSLane *destLane, SUMOReal pos,
00354                                       const std::string &file) throw() {
00355     new MSCalibrator(id, net, destLane, pos, file);
00356 }
00357 
00358 
00359 #ifdef HAVE_MESOSIM
00360 METriggeredCalibrator*
00361 NLTriggerBuilder::buildCalibrator(MSNet &net, const std::string &id,
00362                                   const MSEdge *edge, SUMOReal pos,
00363                                   const std::string &file,
00364                                   const std::string &outfile,
00365                                   const SUMOTime freq) throw() {
00366     return new METriggeredCalibrator(id, edge, pos, file, outfile, freq);
00367 }
00368 #endif
00369 
00370 
00371 void
00372 NLTriggerBuilder::buildRerouter(MSNet &, const std::string &id,
00373                                 std::vector<MSEdge*> &edges,
00374                                 SUMOReal prob, const std::string &file, bool off) throw() {
00375     new MSTriggeredRerouter(id, edges, prob, file, off);
00376 }
00377 
00378 
00379 void
00380 NLTriggerBuilder::buildBusStop(MSNet &net, const std::string &id,
00381                                const std::vector<std::string> &lines,
00382                                MSLane *lane, SUMOReal frompos, SUMOReal topos) throw() {
00383     net.addBusStop(new MSBusStop(id, lines, *lane, frompos, topos));
00384 }
00385 
00386 
00387 
00388 
00389 std::string
00390 NLTriggerBuilder::getFileName(const SUMOSAXAttributes &attrs,
00391                               const std::string &base,
00392                               const bool allowEmpty) throw(InvalidArgument) {
00393     // get the file name to read further definitions from
00394     bool ok = true;
00395     std::string file = attrs.getOptStringReporting(SUMO_ATTR_FILE, 0, 0, ok, "");
00396     if (file == "") {
00397         if (allowEmpty) {
00398             return file;
00399         }
00400         throw InvalidArgument("No filename given.");
00401     }
00402     // check whether absolute or relative filenames are given
00403     if (!FileHelpers::isAbsolute(file)) {
00404         return FileHelpers::getConfigurationRelative(base, file);
00405     }
00406     return file;
00407 }
00408 
00409 
00410 MSLane *
00411 NLTriggerBuilder::getLane(const SUMOSAXAttributes &attrs,
00412                           const std::string &tt,
00413                           const std::string &tid) throw(InvalidArgument) {
00414     bool ok = true;
00415     std::string objectid;
00416     if (attrs.hasAttribute(SUMO_ATTR_LANE)) {
00417         objectid = attrs.getStringReporting(SUMO_ATTR_LANE, tt.c_str(), tid.c_str(), ok);
00418     } else {
00419         if (attrs.hasAttribute(SUMO_ATTR_OBJECTID)) {
00420             objectid = attrs.getStringReporting(SUMO_ATTR_OBJECTID, tt.c_str(), tid.c_str(), ok);
00421             MsgHandler::getWarningInstance()->inform("Defining the lane using 'objectid' within " + tt + " is deprecated, use 'lane' instead.");
00422         }
00423     }
00424     MSLane *lane = MSLane::dictionary(objectid);
00425     if (lane==0) {
00426         throw InvalidArgument("The lane " + objectid + " to use within the " + tt + " '" + tid + "' is not known.");
00427     }
00428     return lane;
00429 }
00430 
00431 
00432 SUMOReal
00433 NLTriggerBuilder::getPosition(const SUMOSAXAttributes &attrs,
00434                               MSLane *lane,
00435                               const std::string &tt, const std::string &tid) throw(InvalidArgument) {
00436     bool ok = true;
00437     SUMOReal pos = attrs.getSUMORealReporting(SUMO_ATTR_POSITION, 0, 0, ok);
00438     bool friendlyPos = attrs.getOptBoolReporting(SUMO_ATTR_FRIENDLY_POS, 0, 0, ok, false);
00439     if (!ok) {
00440         throw InvalidArgument("Error on parsing a position information.");
00441     }
00442     if (pos<0) {
00443         pos = lane->getLength() + pos;
00444     }
00445     if (pos>lane->getLength()) {
00446         if (friendlyPos) {
00447             pos = lane->getLength() - (SUMOReal) 0.1;
00448         } else {
00449             throw InvalidArgument("The position of " + tt + " '" + tid + "' lies beyond the lane's '" + lane->getID() + "' length.");
00450         }
00451     }
00452     return pos;
00453 }
00454 
00455 
00456 
00457 /****************************************************************************/

Generated on Wed May 5 00:06:35 2010 for Sumo - Simulation of Urban MObility by  doxygen 1.5.6