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 <utils/common/MsgHandler.h>
00032 #include <utils/common/Command.h>
00033 #include <utils/common/WrappingCommand.h>
00034 #include <microsim/MSLane.h>
00035 #include <utils/xml/SUMOXMLDefinitions.h>
00036 #include <utils/common/UtilExceptions.h>
00037 #include <utils/common/ToString.h>
00038 #include <microsim/MSEventControl.h>
00039 #include "MSEmitter.h"
00040 #include <microsim/MSGlobals.h>
00041
00042 #ifdef CHECK_MEMORY_LEAKS
00043 #include <foreign/nvwa/debug_new.h>
00044 #endif // CHECK_MEMORY_LEAKS
00045
00046
00047
00048
00049
00050
00051 MSEmitter::MSEmitter_FileTriggeredChild::MSEmitter_FileTriggeredChild(
00052 MSNet &net, const std::string &aXMLFilename,
00053 MSEmitter &parent, MSVehicleControl &vc) throw()
00054 : MSTriggeredXMLReader(net, aXMLFilename), MSEmitterChild(parent, vc),
00055 myHaveNext(false), myFlow(-1), myHaveInitialisedFlow(false), myRunningID(0) {
00056 myBeginTime = net.getCurrentTimeStep();
00057 }
00058
00059
00060 MSEmitter::MSEmitter_FileTriggeredChild::~MSEmitter_FileTriggeredChild() throw() {}
00061
00062
00063 SUMOTime
00064 MSEmitter::MSEmitter_FileTriggeredChild::execute(SUMOTime) throw(ProcessError) {
00065 if (myParent.childCheckEmit(this)) {
00066 buildAndScheduleFlowVehicle();
00067 return (SUMOTime) computeOffset(myFlow);
00068 }
00069 return 1;
00070 }
00071
00072
00073 bool
00074 MSEmitter::MSEmitter_FileTriggeredChild::processNextEntryReaderTriggered() {
00075 if (myFlow>=0) {
00076 return true;
00077 }
00078 if (!myHaveNext) {
00079 return true;
00080 }
00081 if (myParent.childCheckEmit(this)) {
00082 myHaveNext = false;
00083 return true;
00084 }
00085 return false;
00086 }
00087
00088
00089 void
00090 MSEmitter::MSEmitter_FileTriggeredChild::buildAndScheduleFlowVehicle() {
00091 SUMOVehicleParameter* pars = new SUMOVehicleParameter();
00092 pars->id = myParent.getID() + "_" + toString(myRunningID++);
00093 pars->depart = myOffset+1;
00094 pars->repetitionNumber = -1;
00095 pars->repetitionOffset = -1;
00096 MSVehicleType* aVehType = myVTypeDist.getOverallProb()>0
00097 ? myVTypeDist.get()
00098 : MSNet::getInstance()->getVehicleControl().getVType();
00099 if (aVehType==0) {
00100 WRITE_WARNING("MSTriggeredSource " + myParent.getID()+ ": no valid vehicle type exists.");
00101 WRITE_WARNING("Continuing with next element.");
00102 return;
00103 }
00104
00105 const MSRoute *aEmitRoute = myRouteDist.get();
00106 if (aEmitRoute==0) {
00107 WRITE_WARNING("MSTriggeredSource " + myParent.getID()+ ": no valid route exsists.");
00108 WRITE_WARNING("Continuing with next element.");
00109 return;
00110 }
00111
00112 MSVehicle *veh =
00113 MSNet::getInstance()->getVehicleControl().buildVehicle(pars, aEmitRoute, aVehType);
00114 myParent.schedule(this, veh, -1);
00115 myHaveNext = true;
00116 }
00117
00118
00119 void
00120 MSEmitter::MSEmitter_FileTriggeredChild::myStartElement(SumoXMLTag element,
00121 const SUMOSAXAttributes &attrs) throw(ProcessError) {
00122 if (element==SUMO_TAG_ROUTEDISTELEM) {
00123
00124 bool ok = true;
00125 SUMOReal prob = attrs.getSUMORealReporting(SUMO_ATTR_PROB, "emitter/routedistelem", myParent.getID().c_str(), ok);
00126 std::string routeStr = attrs.getStringReporting(SUMO_ATTR_ID, "emitter/routedistelem", myParent.getID().c_str(), ok);
00127 if (ok) {
00128 const MSRoute* route = MSRoute::dictionary(routeStr);
00129 if (route == 0) {
00130 throw ProcessError("MSTriggeredSource " + myParent.getID() + ": Route '" + routeStr + "' does not exist.");
00131 }
00132 if (prob<0) {
00133 throw ProcessError("MSTriggeredSource " + myParent.getID() + ": Attribute 'probability' for route '" + routeStr + "' is negative (must not).");
00134 }
00135
00136 myRouteDist.add(prob, route);
00137 return;
00138 }
00139 throw ProcessError();
00140 }
00141
00142 if (element==SUMO_TAG_VTYPEDISTELEM) {
00143 bool ok = true;
00144 SUMOReal prob = attrs.getSUMORealReporting(SUMO_ATTR_PROB, "emitter/vtypedistelem", myParent.getID().c_str(), ok);
00145 std::string vtypeStr = attrs.getStringReporting(SUMO_ATTR_ID, "emitter/vtypedistelem", myParent.getID().c_str(), ok);
00146 if (ok) {
00147 MSVehicleType *vtype = MSNet::getInstance()->getVehicleControl().getVType(vtypeStr);
00148 if (vtype==0) {
00149 throw ProcessError("MSTriggeredSource " + myParent.getID() + ": Vehicle type '" + vtypeStr + "' does not exist.");
00150 }
00151 if (prob<0) {
00152 throw ProcessError("MSTriggeredSource " + myParent.getID() + ": Attribute 'probability' for vtype '" + vtypeStr + "' is negative (must not).");
00153 }
00154 myVTypeDist.add(prob, vtype);
00155 return;
00156 }
00157 throw ProcessError();
00158 }
00159
00160 if (element==SUMO_TAG_FLOW) {
00161 bool ok = true;
00162 SUMOReal no = attrs.getSUMORealReporting(SUMO_ATTR_NO, "emitter/flow", myParent.getID().c_str(), ok);
00163 if (no<0) {
00164 throw ProcessError("MSTriggeredSource " + myParent.getID() + ": Negative flow in emitter '" + myParent.getID() + "'.");
00165 }
00166 SUMOTime end = attrs.getOptSUMOTimeReporting(SUMO_ATTR_END, "emitter/flow", myParent.getID().c_str(), ok, -1);
00167 if (!ok) {
00168 return;
00169 }
00170 myFlow = (SUMOReal) no;
00171 if (end==-1||end>=MSNet::getInstance()->getCurrentTimeStep()) {
00172 if (myFlow>0) {
00173 buildAndScheduleFlowVehicle();
00174 MSNet::getInstance()->getEmissionEvents().addEvent(
00175 new WrappingCommand<MSEmitter::MSEmitter_FileTriggeredChild>(this, &MSEmitter::MSEmitter_FileTriggeredChild::execute),
00176 (SUMOTime)(1. / (myFlow / 3600.))+MSNet::getInstance()->getCurrentTimeStep(),
00177 MSEventControl::ADAPT_AFTER_EXECUTION);
00178 myHaveInitialisedFlow = true;
00179 }
00180 }
00181 }
00182
00183
00184 if (element==SUMO_TAG_EMIT) {
00185 bool ok = true;
00186 SUMOTime depart = attrs.getOptSUMOTimeReporting(SUMO_ATTR_TIME, "emit", myParent.getID().c_str(), ok, -1);
00187 SUMOReal departSpeed = attrs.getOptSUMORealReporting(SUMO_ATTR_SPEED, "emit", myParent.getID().c_str(), ok, -1);
00188 std::string id = attrs.getOptStringReporting(SUMO_ATTR_ID, "emit", myParent.getID().c_str(), ok, "");
00189 std::string type = attrs.getOptStringReporting(SUMO_ATTR_TYPE, "emit", myParent.getID().c_str(), ok, "");
00190 std::string route = attrs.getOptStringReporting(SUMO_ATTR_ROUTE, "emit", myParent.getID().c_str(), ok, "");
00191 if (!ok) {
00192 return;
00193 }
00194 if (depart<myBeginTime) {
00195
00196 return;
00197 }
00198 SUMOVehicleParameter* pars = new SUMOVehicleParameter();
00199 pars->repetitionNumber = -1;
00200 pars->repetitionOffset = -1;
00201 pars->depart = depart;
00202 pars->departSpeed = departSpeed;
00203
00204 pars->id = id;
00205 if (myVehicleControl.getVehicle(pars->id)!=0) {
00206 WRITE_WARNING("MSTriggeredSource " + myParent.getID()+ ": Vehicle " + pars->id + " already exists.\n Generating a default id.");
00207 pars->id = "";
00208 }
00209 if (pars->id=="") {
00210 pars->id = myParent.getID() + "_" + time2string(pars->depart) + "_" + toString(myRunningID++);
00211 if (myVehicleControl.getVehicle(pars->id)!=0) {
00212 WRITE_WARNING("MSTriggeredSource " + myParent.getID()+ ": Vehicle " + pars->id + " already exists.\n Continuing with next element.");
00213 delete pars;
00214 return;
00215 }
00216 }
00217
00218 pars->vtypeid = type;
00219 MSVehicleType* aVehType = MSNet::getInstance()->getVehicleControl().getVType(pars->vtypeid);
00220 if (aVehType == 0) {
00221 if (myVTypeDist.getOverallProb()!=0) {
00222 aVehType = myVTypeDist.get();
00223 }
00224 if (aVehType==0) {
00225 aVehType = MSNet::getInstance()->getVehicleControl().getVType();
00226 if (aVehType==0) {
00227 WRITE_WARNING("MSTriggeredSource " + myParent.getID()+ ": no valid vehicle type exists.\n Continuing with next element.");
00228 delete pars;
00229 return;
00230 }
00231 }
00232 }
00233
00234 pars->routeid = route;
00235 const MSRoute *aEmitRoute = MSRoute::dictionary(pars->routeid);
00236 if (aEmitRoute==0) {
00237 if (myRouteDist.getOverallProb()!=0) {
00238 aEmitRoute = myRouteDist.get();
00239 }
00240 if (aEmitRoute==0) {
00241 WRITE_WARNING("MSTriggeredSource " + myParent.getID()+ ": no valid route exsists.");
00242 WRITE_WARNING("Continuing with next element.");
00243 delete pars;
00244 return;
00245 }
00246 }
00247
00248 MSVehicle *veh = MSNet::getInstance()->getVehicleControl().buildVehicle(pars, aEmitRoute, aVehType);
00249 myParent.schedule(this, veh, pars->departSpeed);
00250 myHaveNext = true;
00251 myOffset = SUMOTime(pars->depart);
00252 }
00253
00254 if (element==SUMO_TAG_RESET) {
00255 myVTypeDist.clear();
00256 myRouteDist.clear();
00257 }
00258 }
00259
00260
00261 bool
00262 MSEmitter::MSEmitter_FileTriggeredChild::nextRead() {
00263 return myHaveNext;
00264 }
00265
00266
00267 SUMOReal
00268 MSEmitter::MSEmitter_FileTriggeredChild::getLoadedFlow() const {
00269 return myFlow;
00270 }
00271
00272
00273 void
00274 MSEmitter::MSEmitter_FileTriggeredChild::inputEndReached() {
00275 if (myFlow>0&&!myHaveInitialisedFlow) {
00276 buildAndScheduleFlowVehicle();
00277 MSNet::getInstance()->getEmissionEvents().addEvent(
00278 new WrappingCommand<MSEmitter::MSEmitter_FileTriggeredChild>(this, &MSEmitter::MSEmitter_FileTriggeredChild::execute),
00279 (SUMOTime)(1. / (myFlow / 3600.))+MSNet::getInstance()->getCurrentTimeStep(),
00280 MSEventControl::ADAPT_AFTER_EXECUTION);
00281 myHaveInitialisedFlow = true;
00282 }
00283 }
00284
00285
00286
00287
00288
00289 MSEmitter::MSEmitter(const std::string &id,
00290 MSNet &net,
00291 MSLane* destLane, SUMOReal pos,
00292 const std::string &aXMLFilename) throw()
00293 : MSTrigger(id), myNet(net),
00294 myDestLane(destLane), myPos((SUMOReal) pos) {
00295 assert(myPos>=0);
00296 myActiveChild =
00297 new MSEmitter_FileTriggeredChild(net, aXMLFilename, *this, net.getVehicleControl());
00298 myFileBasedEmitter = myActiveChild;
00299 }
00300
00301
00302 MSEmitter::~MSEmitter() throw() {
00303 delete myFileBasedEmitter;
00304 std::map<MSEmitterChild*, std::pair<MSVehicle*, SUMOReal> >::iterator i;
00305 for (i=myToEmit.begin(); i!=myToEmit.end(); ++i) {
00306 delete(*i).second.first;
00307 }
00308 }
00309
00310
00311 bool
00312 MSEmitter::childCheckEmit(MSEmitterChild *child) {
00313 if (myToEmit.find(child)==myToEmit.end()) {
00314
00315 throw 1;
00316 }
00317 if (child!=myActiveChild||myDestLane->getEdge().isVaporizing()) {
00318
00319 if (myDestLane->getEdge().isVaporizing()) {
00320 myToEmit[child].first->setWasVaporized(true);
00321 }
00322
00323 delete myToEmit[child].first;
00324
00325 myToEmit.erase(myToEmit.find(child));
00326
00327 return true;
00328 }
00329
00330 MSVehicle *veh = myToEmit[child].first;
00331 if (veh->getDesiredDepart()>MSNet::getInstance()->getCurrentTimeStep()) {
00332 return false;
00333 }
00334 SUMOReal speed = myToEmit[child].second;
00335
00336
00337 SUMOReal pos = myPos;
00338 if (speed<0) {
00339 speed = MIN2(myDestLane->getMaxSpeed(), veh->getMaxSpeed());
00340 } else {
00341 speed = MIN3(myDestLane->getMaxSpeed(), veh->getMaxSpeed(), speed);
00342 }
00343
00344 #ifdef HAVE_MESOSIM
00345 if (MSGlobals::gUseMesoSim) {
00346 if (myDestLane->getEdge().emit(*veh, myNet.getCurrentTimeStep())) {
00347 veh->onDepart();
00348
00349 if (!myNet.getVehicleControl().addVehicle(veh->getID(), veh)) {
00350
00351 throw 1;
00352 }
00353
00354 myToEmit.erase(myToEmit.find(child));
00355 return true;
00356 }
00357 } else {
00358 #endif
00359 if (myDestLane->isEmissionSuccess(veh, speed, pos, true)) {
00360 veh->onDepart();
00361
00362 if (!myNet.getVehicleControl().addVehicle(veh->getID(), veh)) {
00363
00364 throw 1;
00365 }
00366
00367 myToEmit.erase(myToEmit.find(child));
00368 return true;
00369 }
00370 #ifdef HAVE_MESOSIM
00371 }
00372 #endif
00373 return false;
00374 }
00375
00376
00377 void
00378 MSEmitter::schedule(MSEmitterChild *child,
00379 MSVehicle *v, SUMOReal speed) {
00380 v->onTryEmit();
00381 myToEmit[child] = std::make_pair(v, speed);
00382 }
00383
00384
00385 size_t
00386 MSEmitter::getActiveChildIndex() const {
00387 return
00388 myFileBasedEmitter==myActiveChild ? 0 : 1;
00389 }
00390
00391
00392 void
00393 MSEmitter::setActiveChild(MSEmitterChild *c) {
00394 myActiveChild = c;
00395 }
00396
00397
00398
00399