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