|
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/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 /****************************************************************************/