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
00031 #include <string>
00032 #include <utils/common/MsgHandler.h>
00033 #include <utils/common/Command.h>
00034 #include <utils/common/WrappingCommand.h>
00035 #include <microsim/MSLane.h>
00036 #include <utils/xml/SUMOXMLDefinitions.h>
00037 #include <utils/common/UtilExceptions.h>
00038 #include <utils/common/ToString.h>
00039 #include <microsim/MSEventControl.h>
00040 #include "MSCalibrator.h"
00041 #include <microsim/MSGlobals.h>
00042
00043
00044 #include <netload/NLDetectorBuilder.h>
00045 #include <microsim/output/MSInductLoop.h>
00046 #include <utils/iodevices/OutputDevice.h>
00047
00048 #ifdef CHECK_MEMORY_LEAKS
00049 #include <foreign/nvwa/debug_new.h>
00050 #endif // CHECK_MEMORY_LEAKS
00051
00052
00053
00054
00055
00056
00057 MSCalibrator::MSCalibrator_FileTriggeredChild::MSCalibrator_FileTriggeredChild(
00058 MSNet &net, const std::string &aXMLFilename,
00059 MSCalibrator &parent, MSVehicleControl &vc) throw()
00060 : MSTriggeredXMLReader(net, aXMLFilename), MSCalibratorChild(parent, vc),
00061 myHaveNext(false), myFlow(-1), myHaveInitialisedFlow(false), myRunningID(0) {
00062 myBeginTime = net.getCurrentTimeStep();
00063 }
00064
00065
00066 MSCalibrator::MSCalibrator_FileTriggeredChild::~MSCalibrator_FileTriggeredChild() throw() {}
00067
00068
00069 SUMOTime
00070 MSCalibrator::MSCalibrator_FileTriggeredChild::execute(SUMOTime) throw(ProcessError) {
00071 if (myParent.childCheckEmit(this)) {
00072 buildAndScheduleFlowVehicle();
00073 return (SUMOTime) computeOffset(myFlow);
00074 }
00075 return 1;
00076 }
00077
00078
00079
00080 SUMOTime
00081 MSCalibrator::execute(SUMOTime timestep) throw(ProcessError) {
00082
00083 if (timestep == 0) {
00084 return 1;
00085 }
00086
00087 if (myNumVehicles == -1) {
00088 return 1;
00089 }
00090
00091
00092
00093 SUMOReal vehPerInterval = myNumVehicles / (myInterval);
00094 int num_replacements = 0;
00095
00096
00097
00098
00099
00100
00101
00102 unsigned veh_cnt = myIL->getNVehContributed();
00103 SUMOReal diff = veh_cnt - vehPerInterval + myToCalibrate;
00104 SUMOReal meanSpeed = myIL->getCurrentSpeed();
00105
00106 if (diff > 0) {
00107
00108 unsigned int vehNum = myDestLane->getVehicleNumber();
00109
00110
00111 if (vehNum < diff) {
00112
00113 myToCalibrate = diff - vehNum;
00114
00115 diff = (SUMOReal)vehNum;
00116 } else {
00117 myToCalibrate = diff - floor(diff);
00118 }
00119
00120 for (int i=1; i <= diff; i++) {
00121
00122 for (MSLane::VehCont::const_iterator it = myDestLane->getVehiclesSecure().begin();
00123 it < myDestLane->getVehiclesSecure().end();
00124 it++) {
00125
00126 MSVehicle * veh = (*it);
00127
00128 if (veh->getVehicleType().getID() == "BUS") {
00129 continue;
00130 } else {
00131 veh->onRemovalFromNet(false);
00132 myDestLane->removeVehicle(veh);
00133 MSNet::getInstance()->getVehicleControl().scheduleVehicleRemoval(veh);
00134 num_replacements++;
00135 break;
00136 }
00137 }
00138
00139 }
00140
00141
00142 myToCalibrate+diff-num_replacements;
00143 } else if (diff < 0) {
00144
00145 myToCalibrate = diff - ceil(diff);
00146 for (int i=-1; i >= diff; i--) {
00147
00148
00149 ((MSCalibrator_FileTriggeredChild*) myFileBasedCalibrator)->buildAndScheduleFlowVehicle(meanSpeed);
00150 childCheckEmit(myFileBasedCalibrator);
00151 num_replacements--;
00152 }
00153 } else if (diff == 0) {
00154 myToCalibrate = 0;
00155 }
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168 return 1;
00169 }
00171
00172 bool
00173 MSCalibrator::MSCalibrator_FileTriggeredChild::processNextEntryReaderTriggered() {
00174 if (myFlow>=0) {
00175 return true;
00176 }
00177 if (!myHaveNext) {
00178 return true;
00179 }
00180 if (myParent.childCheckEmit(this)) {
00181 myHaveNext = false;
00182 return true;
00183 }
00184 return false;
00185 }
00186
00187
00188 void
00189 MSCalibrator::MSCalibrator_FileTriggeredChild::buildAndScheduleFlowVehicle(SUMOReal speed) {
00190 SUMOVehicleParameter* pars = new SUMOVehicleParameter();
00191 pars->id = myParent.getID() + "_" + toString(myRunningID++);
00192 pars->depart = myOffset+1;
00193 pars->repetitionNumber = -1;
00194 pars->repetitionOffset = -1;
00195 MSVehicleType* aVehType = myVTypeDist.getOverallProb()>0
00196 ? myVTypeDist.get()
00197 : MSNet::getInstance()->getVehicleControl().getVType();
00198 if (aVehType==0) {
00199 WRITE_WARNING("MSTriggeredSource " + myParent.getID()+ ": no valid vehicle type exists.");
00200 WRITE_WARNING("Continuing with next element.");
00201 return;
00202 }
00203
00204 const MSRoute *aEmitRoute = myRouteDist.get();
00205 if (aEmitRoute==0) {
00206 WRITE_WARNING("MSTriggeredSource " + myParent.getID()+ ": no valid route exsists.");
00207 WRITE_WARNING("Continuing with next element.");
00208 return;
00209 }
00210
00211 MSVehicle *veh =
00212 MSNet::getInstance()->getVehicleControl().buildVehicle(pars, aEmitRoute, aVehType);
00213 myParent.schedule(this, veh, speed);
00214 myHaveNext = true;
00215 }
00216
00217
00218 void
00219 MSCalibrator::MSCalibrator_FileTriggeredChild::myStartElement(SumoXMLTag element,
00220 const SUMOSAXAttributes &attrs) throw(ProcessError) {
00221 if (element==SUMO_TAG_ROUTEDISTELEM) {
00222 bool ok = true;
00223 SUMOReal freq = attrs.getSUMORealReporting(SUMO_ATTR_PROB, "calibrator/routedistelem", myParent.getID().c_str(), ok);
00224 std::string routeStr = attrs.getStringReporting(SUMO_ATTR_ID, "calibrator/routedistelem", myParent.getID().c_str(), ok);
00225 if (ok) {
00226 const MSRoute* route = MSRoute::dictionary(routeStr);
00227 if (route == 0) {
00228 throw ProcessError("MSTriggeredSource " + myParent.getID() + ": Route '" + routeStr + "' does not exist.");
00229 }
00230 if (freq<0) {
00231 throw ProcessError("MSTriggeredSource " + myParent.getID() + ": Attribute \"probability\" is negative (must not).");
00232 }
00233
00234 myRouteDist.add(freq, route);
00235 }
00236 return;
00237 }
00238
00239 if (element==SUMO_TAG_VTYPEDISTELEM) {
00240
00241 std::string id;
00242 if (!attrs.setIDFromAttributes("vtypedistelem", id)) {
00243 return;
00244 }
00245 bool ok = true;
00246 SUMOReal prob = attrs.getSUMORealReporting(SUMO_ATTR_PROB, "vtypedistelem", id.c_str(), ok);
00247 if (ok) {
00248 if (prob<=0) {
00249 MsgHandler::getErrorInstance()->inform("False probability while parsing calibrator '" + myParent.getID() + "' (" + toString(prob) + ").");
00250 return;
00251 }
00252 MSVehicleType *vtype = MSNet::getInstance()->getVehicleControl().getVType(id);
00253 if (vtype==0) {
00254 MsgHandler::getErrorInstance()->inform("Unknown vtype-object '" + id + "'.");
00255 return;
00256 }
00257 myVTypeDist.add(prob, vtype);
00258 }
00259 }
00260
00261 if (element==SUMO_TAG_FLOW) {
00262 bool ok = true;
00263 SUMOReal no = attrs.getSUMORealReporting(SUMO_ATTR_NO, "flow", myParent.getID().c_str(), ok);
00264 if (no<0) {
00265 MsgHandler::getErrorInstance()->inform("Negative flow in calibrator '" + myParent.getID() + "'.");
00266 return;
00267 }
00268 SUMOTime end = attrs.getOptSUMOTimeReporting(SUMO_ATTR_END, "flow", myParent.getID().c_str(), ok, -1);
00269 if (!ok) {
00270 return;
00271 }
00272 myFlow = (SUMOReal) no;
00273 if (end==-1||end>=MSNet::getInstance()->getCurrentTimeStep()) {
00274 if (myFlow>0) {
00275 buildAndScheduleFlowVehicle();
00276 MSNet::getInstance()->getEmissionEvents().addEvent(
00277 new WrappingCommand<MSCalibrator::MSCalibrator_FileTriggeredChild>(this, &MSCalibrator::MSCalibrator_FileTriggeredChild::execute),
00278 (SUMOTime)(1. / (myFlow / 3600.))+MSNet::getInstance()->getCurrentTimeStep(),
00279 MSEventControl::ADAPT_AFTER_EXECUTION);
00280 myHaveInitialisedFlow = true;
00281 }
00282 }
00283 }
00284
00285
00286 if (element==SUMO_TAG_EMIT) {
00287 bool ok = true;
00288 SUMOTime depart = attrs.getSUMOTimeReporting(SUMO_ATTR_TIME, "emit", 0, ok);
00289 SUMOReal departSpeed = attrs.getOptSUMORealReporting(SUMO_ATTR_SPEED, "emit", myParent.getID().c_str(), ok, -1);
00290 if (!ok) {
00291 return;
00292 }
00293 if (depart<myBeginTime) {
00294
00295 return;
00296 }
00297
00298 SUMOVehicleParameter* pars = new SUMOVehicleParameter();
00299 pars->repetitionNumber = -1;
00300 pars->repetitionOffset = -1;
00301 pars->depart = depart;
00302 pars->departSpeed = departSpeed;
00303
00304 pars->id = attrs.getStringSecure(SUMO_ATTR_ID, "");
00305 if (myVehicleControl.getVehicle(pars->id)!=0) {
00306 WRITE_WARNING("MSTriggeredSource " + myParent.getID()+ ": Vehicle " + pars->id + " already exists.\n Generating a default id.");
00307 pars->id = "";
00308 }
00309 if (pars->id=="") {
00310 pars->id = myParent.getID() + "_" + toString(pars->depart) + "_" + toString(myRunningID++);
00311 if (myVehicleControl.getVehicle(pars->id)!=0) {
00312 WRITE_WARNING("MSTriggeredSource " + myParent.getID()+ ": Vehicle " + pars->id + " already exists.\n Continuing with next element.");
00313 return;
00314 }
00315 }
00316
00317 pars->vtypeid = attrs.getStringReporting(SUMO_ATTR_TYPE, "calibrator/routedistelem", myParent.getID().c_str(), ok, "");
00318 MSVehicleType* aVehType = MSNet::getInstance()->getVehicleControl().getVType(pars->vtypeid);
00319 if (aVehType == 0) {
00320 if (myVTypeDist.getOverallProb()!=0) {
00321 aVehType = myVTypeDist.get();
00322 }
00323 if (aVehType==0) {
00324 aVehType = MSNet::getInstance()->getVehicleControl().getVType();
00325 if (aVehType==0) {
00326 WRITE_WARNING("MSTriggeredSource " + myParent.getID()+ ": no valid vehicle type exists.\n Continuing with next element.");
00327 return;
00328 }
00329 }
00330 }
00331
00332 pars->routeid = attrs.getStringReporting(SUMO_ATTR_ROUTE, "calibrator/routedistelem", myParent.getID().c_str(), ok, "");
00333 const MSRoute *aEmitRoute = MSRoute::dictionary(pars->routeid);
00334 if (aEmitRoute==0) {
00335 if (myRouteDist.getOverallProb()!=0) {
00336 aEmitRoute = myRouteDist.get();
00337 }
00338 if (aEmitRoute==0) {
00339 WRITE_WARNING("MSTriggeredSource " + myParent.getID()+ ": no valid route exsists.");
00340 WRITE_WARNING("Continuing with next element.");
00341 return;
00342 }
00343 }
00344
00345 MSVehicle *veh = MSNet::getInstance()->getVehicleControl().buildVehicle(pars, aEmitRoute, aVehType);
00346 myParent.schedule(this, veh, pars->departSpeed);
00347 myHaveNext = true;
00348 myOffset = SUMOTime(pars->depart);
00349 }
00350
00351 if (element==SUMO_TAG_RESET) {
00352 myVTypeDist.clear();
00353 myRouteDist.clear();
00354 }
00355 #if 0
00356 #ifdef TM_CALIB
00357 if (element==SUMO_TAG_CALIB) {
00358
00359 WRITE_WARNING("FOUND calib Tag!!!");
00360
00361
00362
00363
00364
00365
00366
00367
00368 }
00369 #endif //TM_CALIB
00370 #endif //0
00371 }
00372
00373
00374 bool
00375 MSCalibrator::MSCalibrator_FileTriggeredChild::nextRead() {
00376 return myHaveNext;
00377 }
00378
00379
00380 SUMOReal
00381 MSCalibrator::MSCalibrator_FileTriggeredChild::getLoadedFlow() const {
00382 return myFlow;
00383 }
00384
00385
00386 void
00387 MSCalibrator::MSCalibrator_FileTriggeredChild::inputEndReached() {
00388 if (myFlow>0&&!myHaveInitialisedFlow) {
00389 buildAndScheduleFlowVehicle();
00390 MSNet::getInstance()->getEmissionEvents().addEvent(
00391 new WrappingCommand<MSCalibrator::MSCalibrator_FileTriggeredChild>(this, &MSCalibrator::MSCalibrator_FileTriggeredChild::execute),
00392 (SUMOTime)(1. / (myFlow / 3600.))+MSNet::getInstance()->getCurrentTimeStep(),
00393 MSEventControl::ADAPT_AFTER_EXECUTION);
00394 myHaveInitialisedFlow = true;
00395 }
00396 }
00397
00398
00399
00400
00401
00402 MSCalibrator::MSCalibrator(const std::string &id,
00403 MSNet &net,
00404 MSLane* destLane, SUMOReal pos,
00405 const std::string &aXMLFilename) throw()
00406 : MSTrigger(id), myNet(net),
00407 myDestLane(destLane), myPos((SUMOReal) pos), myDb(net),
00408 myDebugLevel(0), myDebugFilesBaseName("x:\\temp\\dbg_") {
00409 assert(myPos>=0);
00410
00411 myToCalibrate = 0;
00412
00413
00414
00415 myInterval = 60;
00416 myNumVehicles= -1;
00417
00418
00419
00420 std::string ilId = "Calib_InductLoopOn_" + myDestLane->getID();
00421 myIL = myDb.createInductLoop(ilId, myDestLane, myPos);
00422
00423 MSNet::getInstance()->getEmissionEvents().addEvent(
00424 new WrappingCommand<MSCalibrator>(this, &MSCalibrator::execute),
00425
00426 0,
00427 MSEventControl::ADAPT_AFTER_EXECUTION);
00428
00429
00430
00431 MSCalibrator::calibratorMap[id]=this;
00432
00433 myActiveChild =
00434 new MSCalibrator_FileTriggeredChild(net, aXMLFilename, *this, net.getVehicleControl());
00435 myFileBasedCalibrator = myActiveChild;
00436 }
00437
00438
00439 MSCalibrator::~MSCalibrator() throw() {
00440 {
00441 delete myFileBasedCalibrator;
00442 }
00443 {
00444 std::map<MSCalibratorChild*, std::pair<MSVehicle*, SUMOReal> >::iterator i;
00445 for (i=myToEmit.begin(); i!=myToEmit.end(); ++i) {
00446 delete(*i).second.first;
00447 }
00448 }
00449 }
00450
00451
00452 bool
00453 MSCalibrator::childCheckEmit(MSCalibratorChild *child) {
00454 if (myToEmit.find(child)==myToEmit.end()) {
00455
00456 throw 1;
00457 }
00458 if (child!=myActiveChild||myDestLane->getEdge().isVaporizing()) {
00459
00460 if (myDestLane->getEdge().isVaporizing()) {
00461 myToEmit[child].first->setWasVaporized(true);
00462 }
00463
00464 delete myToEmit[child].first;
00465
00466 myToEmit.erase(myToEmit.find(child));
00467
00468 return true;
00469 }
00470
00471 MSVehicle *veh = myToEmit[child].first;
00472 SUMOReal speed = myToEmit[child].second;
00473
00474
00475 SUMOReal pos = myPos+1;
00476 if (speed<0) {
00477 speed = MIN2(myDestLane->getMaxSpeed(), veh->getMaxSpeed());
00478 }
00479
00480 #ifdef HAVE_MESOSIM
00481 if (MSGlobals::gUseMesoSim) {
00482 if (myDestLane->getEdge().emit(*veh, myNet.getCurrentTimeStep())) {
00483 veh->onDepart();
00484
00485 if (!myNet.getVehicleControl().addVehicle(veh->getID(), veh)) {
00486
00487 throw 1;
00488 }
00489
00490 myToEmit.erase(myToEmit.find(child));
00491 return true;
00492 }
00493 } else {
00494 #endif
00495 if (myDestLane->isEmissionSuccess(veh, speed, pos, false)) {
00496 veh->onDepart();
00497
00498 if (!myNet.getVehicleControl().addVehicle(veh->getID(), veh)) {
00499
00500 throw 1;
00501 }
00502
00503 myToEmit.erase(myToEmit.find(child));
00504 return true;
00505 }
00506 #ifdef HAVE_MESOSIM
00507 }
00508 #endif
00509 return false;
00510 }
00511
00512
00513 void
00514 MSCalibrator::schedule(MSCalibratorChild *child,
00515 MSVehicle *v, SUMOReal speed) {
00516 myToEmit[child] = std::make_pair(v, speed);
00517 }
00518
00519
00520 size_t
00521 MSCalibrator::getActiveChildIndex() const {
00522 return
00523 myFileBasedCalibrator==myActiveChild ? 0 : 1;
00524 }
00525
00526
00527 void
00528 MSCalibrator::setActiveChild(MSCalibratorChild *c) {
00529 myActiveChild = c;
00530 }
00531
00532 std::map<std::string, MSCalibrator*> MSCalibrator::calibratorMap;
00533
00534 void
00535 MSCalibrator::updateCalibrator(std::string name, int time, SUMOReal count) {
00536
00537 std::map<std::string, MSCalibrator*>::iterator it = MSCalibrator::calibratorMap.find(name);
00538
00539 if (it==MSCalibrator::calibratorMap.end()) {
00540 WRITE_ERROR("WRONG UPDATE COMMAND, CALIBRATOR NOT FOUND: " + name);
00541 return;
00542 }
00543
00544 MSCalibrator * calibrator = (*it).second;
00545
00546 calibrator->myInterval = time;
00547 calibrator->myNumVehicles = count;
00548
00549
00550 int i=0;
00551
00552
00553 }
00554
00555
00556
00557