SUMO - Simulation of Urban MObility
|
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 /****************************************************************************/