00001
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
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
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
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
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
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
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
00192 std::string id;
00193 if (!attrs.setIDFromAttributes("emitter", id, false)) {
00194 throw InvalidArgument("An emitter does not contain an id");
00195 }
00196
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
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
00212 MSLane *lane = getLane(attrs, "bus_stop", id);
00213
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
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
00248 std::vector<std::string> lines;
00249 SUMOSAXAttributes::parseStringVector(attrs.getOptStringReporting(SUMO_ATTR_LINES, "busstop", id.c_str(), ok, ""), lines);
00250
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
00259 std::string id;
00260 if (!attrs.setIDFromAttributes("calibrator", id, false)) {
00261 throw InvalidArgument("A calibrator does not contain an id");
00262 }
00263
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);
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
00291 std::string id;
00292 if (!attrs.setIDFromAttributes("rerouter", id, false)) {
00293 throw InvalidArgument("A rerouter does not contain an id");
00294 }
00295
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
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
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