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 #ifdef HAVE_VERSION_H
00031 #include <version.h>
00032 #endif
00033
00034 #include <iostream>
00035 #include <sstream>
00036 #include <typeinfo>
00037 #include <algorithm>
00038 #include <cassert>
00039 #include <vector>
00040 #include <sstream>
00041 #include <utils/common/UtilExceptions.h>
00042 #include "MSNet.h"
00043 #include "MSEdgeControl.h"
00044 #include "MSJunctionControl.h"
00045 #include "MSEmitControl.h"
00046 #include "MSEventControl.h"
00047 #include "MSEdge.h"
00048 #include "MSJunction.h"
00049 #include "MSJunctionLogic.h"
00050 #include "MSLane.h"
00051 #include "MSVehicleTransfer.h"
00052 #include "MSRoute.h"
00053 #include "MSRouteLoaderControl.h"
00054 #include "traffic_lights/MSTLLogicControl.h"
00055 #include "MSVehicleControl.h"
00056 #include "trigger/MSTrigger.h"
00057 #include "MSCORN.h"
00058 #include <utils/common/MsgHandler.h>
00059 #include <utils/common/ToString.h>
00060 #include <microsim/output/MSDetectorControl.h>
00061 #include <microsim/MSVehicleTransfer.h>
00062 #include "traffic_lights/MSTrafficLightLogic.h"
00063 #include <utils/shapes/Polygon2D.h>
00064 #include <utils/shapes/ShapeContainer.h>
00065 #include "output/MSXMLRawOut.h"
00066 #include <utils/iodevices/OutputDevice.h>
00067 #include <utils/common/SysUtils.h>
00068 #include <utils/common/WrappingCommand.h>
00069 #include <utils/options/OptionsCont.h>
00070 #include "MSGlobals.h"
00071 #include "MSRouteHandler.h"
00072 #include "MSRouteLoader.h"
00073 #include <utils/geom/GeoConvHelper.h>
00074 #include <ctime>
00075 #include "MSPerson.h"
00076 #include "MSEdgeWeightsStorage.h"
00077
00078
00079 #ifdef _MESSAGES
00080 #include "MSMessageEmitter.h"
00081 #endif
00082
00083 #ifdef HAVE_MESOSIM
00084 #include <mesosim/MELoop.h>
00085 #endif
00086
00087 #ifndef NO_TRACI
00088 #include <traci-server/TraCIServer.h>
00089 #endif
00090
00091 #ifdef CHECK_MEMORY_LEAKS
00092 #include <foreign/nvwa/debug_new.h>
00093 #endif // CHECK_MEMORY_LEAKS
00094
00095
00096
00097
00098
00099 MSNet* MSNet::myInstance = 0;
00100
00101
00102
00103
00104
00105
00106
00107
00108 SUMOReal
00109 MSNet::EdgeWeightsProxi::getEffort(const MSEdge * const e,
00110 const SUMOVehicle * const v,
00111 SUMOReal t) const {
00112 SUMOReal value;
00113 if (myVehicleKnowledge.retrieveExistingEffort(e, v, t, value)) {
00114 return value;
00115 }
00116 if (myNetKnowledge.retrieveExistingEffort(e, v, t, value)) {
00117 return value;
00118 }
00119 return 0;
00120 }
00121
00122
00123 SUMOReal
00124 MSNet::EdgeWeightsProxi::getTravelTime(const MSEdge * const e,
00125 const SUMOVehicle * const v,
00126 SUMOReal t) const {
00127 SUMOReal value;
00128 if (myVehicleKnowledge.retrieveExistingTravelTime(e, v, t, value)) {
00129 return value;
00130 }
00131 if (myNetKnowledge.retrieveExistingTravelTime(e, v, t, value)) {
00132 return value;
00133 }
00134 const MSLane * const l = e->getLanes()[0];
00135 return l->getLength() / l->getMaxSpeed();
00136 }
00137
00138
00139
00140
00141
00142
00143 MSNet*
00144 MSNet::getInstance(void) throw(ProcessError) {
00145 if (myInstance != 0) {
00146 return myInstance;
00147 }
00148 throw ProcessError("A network was not yet constructed.");
00149 }
00150
00151
00152 MSNet::MSNet(MSVehicleControl *vc, MSEventControl *beginOfTimestepEvents,
00153 MSEventControl *endOfTimestepEvents, MSEventControl *emissionEvents,
00154 ShapeContainer *shapeCont) throw(ProcessError) {
00155 if (myInstance!=0) {
00156 throw ProcessError("A network was already constructed.");
00157 }
00158 MSCORN::init();
00159 OptionsCont &oc = OptionsCont::getOptions();
00160 myStep = string2time(oc.getString("begin"));
00161 myLogExecutionTime = !oc.getBool("no-duration-log");
00162 myLogStepNumber = !oc.getBool("no-step-log");
00163 myTooManyVehicles = oc.getInt("too-many-vehicles");
00164 myEmitter = new MSEmitControl(*vc, (SUMOTime) oc.getInt("max-depart-delay"), oc.getBool("sloppy-emit"));
00165 myVehicleControl = vc;
00166 myDetectorControl = new MSDetectorControl();
00167 myEdges = 0;
00168 myJunctions = 0;
00169 myRouteLoaders = 0;
00170 myLogics = 0;
00171 myPersonControl = 0;
00172 myEdgeWeights = 0;
00173 myShapeContainer = shapeCont==0 ? new ShapeContainer() : shapeCont;
00174
00175 myBeginOfTimestepEvents = beginOfTimestepEvents;
00176 myEndOfTimestepEvents = endOfTimestepEvents;
00177 myEmissionEvents = emissionEvents;
00178
00179 #ifdef HAVE_MESOSIM
00180 if (MSGlobals::gUseMesoSim) {
00181 MSGlobals::gMesoNet = new MELoop();
00182 }
00183 #endif
00184 myInstance = this;
00185 }
00186
00187
00188
00189
00190 void
00191 MSNet::closeBuilding(MSEdgeControl *edges, MSJunctionControl *junctions,
00192 MSRouteLoaderControl *routeLoaders,
00193 MSTLLogicControl *tlc,
00194 std::vector<SUMOTime> stateDumpTimes,
00195 std::vector<std::string> stateDumpFiles) throw() {
00196 myEdges = edges;
00197 myJunctions = junctions;
00198 myRouteLoaders = routeLoaders;
00199 myLogics = tlc;
00200
00201 myStateDumpTimes = stateDumpTimes;
00202 myStateDumpFiles = stateDumpFiles;
00203
00204
00205 myJunctions->postloadInitContainer();
00206
00207 if (OptionsCont::getOptions().isSet("emissions-output")) {
00208 MSCORN::setWished(MSCORN::CORN_OUT_EMISSIONS);
00209 }
00210 if (OptionsCont::getOptions().isSet("tripinfo-output")) {
00211 MSCORN::setWished(MSCORN::CORN_OUT_TRIPDURATIONS);
00212 }
00213 if (OptionsCont::getOptions().isSet("vehroute-output")) {
00214 MSCORN::setWished(MSCORN::CORN_OUT_VEHROUTES);
00215 if (OptionsCont::getOptions().getBool("vehroute-output.exit-times")) {
00216 MSCORN::setWished(MSCORN::CORN_VEH_SAVE_EDGE_EXIT);
00217 }
00218 if (!OptionsCont::getOptions().getBool("vehroute-output.last-route")) {
00219 MSCORN::setWished(MSCORN::CORN_OUT_OLDROUTES);
00220 }
00221 if (OptionsCont::getOptions().getBool("device.routing.with-taz")) {
00222 MSCORN::setWished(MSCORN::CORN_OUT_TAZ);
00223 }
00224 }
00225
00226
00227 if (myLogExecutionTime) {
00228 mySimBeginMillis = SysUtils::getCurrentMillis();
00229 }
00230 }
00231
00232
00233 MSNet::~MSNet() throw() {
00234
00235 delete myJunctions;
00236 delete myDetectorControl;
00237
00238 delete myEdges;
00239 delete myEmitter;
00240 delete myLogics;
00241 delete myRouteLoaders;
00242 delete myVehicleControl;
00243 delete myShapeContainer;
00244 #ifdef _MESSAGES
00245 #ifdef _DEBUG
00246 std::cout << "MSNet: clearing myMsgEmitter" << std::endl;
00247 #endif
00248 myMsgEmitter.clear();
00249 #ifdef _DEBUG
00250 std::cout << "MSNet: clearing msgEmitVec" << std::endl;
00251 #endif
00252 msgEmitVec.clear();
00253 #endif
00254 #ifdef HAVE_MESOSIM
00255 if (MSGlobals::gUseMesoSim) {
00256 delete MSGlobals::gMesoNet;
00257 }
00258 #endif
00259 delete myBeginOfTimestepEvents;
00260 delete myEndOfTimestepEvents;
00261 delete myEmissionEvents;
00262 delete myEdgeWeights;
00263 clearAll();
00264 GeoConvHelper::close();
00265 myInstance = 0;
00266 }
00267
00268
00269 int
00270 MSNet::simulate(SUMOTime start, SUMOTime stop) {
00271
00272 std::string quitMessage = "";
00273 myStep = start;
00274 do {
00275 if (myLogStepNumber) {
00276 preSimStepOutput();
00277 }
00278 simulationStep();
00279 if (myLogStepNumber) {
00280 postSimStepOutput();
00281 }
00282 MSNet::SimulationState state = simulationState(stop);
00283 #ifndef NO_TRACI
00284 if (state!=SIMSTATE_RUNNING) {
00285 if (OptionsCont::getOptions().getInt("remote-port")!=0&&!traci::TraCIServer::wasClosed()) {
00286 state = SIMSTATE_RUNNING;
00287 }
00288 }
00289 #endif
00290 if (state!=SIMSTATE_RUNNING) {
00291 quitMessage = "Simulation End: " + getStateMessage(state);
00292 }
00293 } while (quitMessage=="");
00294 WRITE_MESSAGE(quitMessage);
00295
00296 closeSimulation(start);
00297 return 0;
00298 }
00299
00300
00301 void
00302 MSNet::closeSimulation(SUMOTime start) {
00303 if (myLogExecutionTime) {
00304 long duration = SysUtils::getCurrentMillis() - mySimBeginMillis;
00305 std::ostringstream msg;
00306 msg << "Performance: " << "\n" << " Duration: " << duration << " ms" << "\n";
00307 if (duration!=0) {
00308 msg << " Real time factor: " << ((SUMOReal)(myStep-start)*1000./(SUMOReal)duration) << "\n";
00309 msg.setf(std::ios::fixed , std::ios::floatfield);
00310 msg.setf(std::ios::showpoint);
00311 msg << " UPS: " << ((SUMOReal) myVehiclesMoved * 1000. / (SUMOReal) duration) << "\n";
00312 }
00313 msg << "Vehicles: " << "\n"
00314 << " Emitted: " << myVehicleControl->getEmittedVehicleNo() << "\n"
00315 << " Running: " << myVehicleControl->getRunningVehicleNo() << "\n"
00316 << " Waiting: " << myEmitter->getWaitingVehicleNo() << "\n";
00317 WRITE_MESSAGE(msg.str());
00318 }
00319 myDetectorControl->close(myStep);
00320 #ifndef NO_TRACI
00321 traci::TraCIServer::close();
00322 #endif
00323 }
00324
00325
00326 void
00327 MSNet::simulationStep() {
00328 #ifndef NO_TRACI
00329 traci::TraCIServer::processCommandsUntilSimStep(myStep);
00330 #endif
00331
00332 if (myLogExecutionTime) {
00333 mySimStepBegin = SysUtils::getCurrentMillis();
00334 }
00335 #ifdef HAVE_MESOSIM
00336
00337 std::vector<SUMOTime>::iterator timeIt = find(myStateDumpTimes.begin(), myStateDumpTimes.end(), myStep);
00338 if (timeIt!=myStateDumpTimes.end()) {
00339 const int dist = distance(myStateDumpTimes.begin(), timeIt);
00340 std::ofstream strm(myStateDumpFiles[dist].c_str(), std::fstream::out|std::fstream::binary);
00341 saveState(strm);
00342 }
00343 #endif
00344 myBeginOfTimestepEvents->execute(myStep);
00345 if (MSGlobals::gCheck4Accidents) {
00346 myEdges->detectCollisions(myStep);
00347 }
00348 #ifdef HAVE_MESOSIM
00349 if (MSGlobals::gUseMesoSim) {
00350 myJunctions->setAllowed();
00351 MSGlobals::gMesoNet->simulate(myStep);
00352 } else {
00353 #endif
00354
00355 myLogics->check2Switch(myStep);
00356
00357 myLogics->setTrafficLightSignals();
00358
00359
00360
00361 myEdges->patchActiveLanes();
00362
00363
00364
00365
00366 myEdges->moveCritical(myStep);
00367
00368
00369
00370 myEdges->moveFirst(myStep);
00371 if (MSGlobals::gCheck4Accidents) {
00372 myEdges->detectCollisions(myStep);
00373 }
00374
00375
00376 myEdges->changeLanes(myStep);
00377
00378 if (MSGlobals::gCheck4Accidents) {
00379 myEdges->detectCollisions(myStep);
00380 }
00381 #ifdef HAVE_MESOSIM
00382 }
00383 #endif
00384
00385 myRouteLoaders->loadNext(myStep, myEmitter);
00386
00387
00388 if (myPersonControl!=0) {
00389 while (myPersonControl->hasArrivedPersons(myStep)) {
00390 const MSPersonControl::PersonVector &persons = myPersonControl->popArrivedPersons(myStep);
00391 for (MSPersonControl::PersonVector::const_iterator i=persons.begin(); i!=persons.end(); ++i) {
00392 (*i)->proceed(this, myStep);
00393 }
00394 }
00395 }
00396
00397 myEmitter->emitVehicles(myStep);
00398 if (MSGlobals::gCheck4Accidents) {
00399 myEdges->detectCollisions(myStep);
00400 }
00401 MSVehicleTransfer::getInstance()->checkEmissions(myStep);
00402 myEmissionEvents->execute(myStep);
00403
00404
00405 myEndOfTimestepEvents->execute(myStep);
00406
00407
00408 writeOutput();
00409
00410 if (myLogExecutionTime) {
00411 mySimStepEnd = SysUtils::getCurrentMillis();
00412 mySimStepDuration = mySimStepEnd - mySimStepBegin;
00413 myVehiclesMoved += myVehicleControl->getRunningVehicleNo();
00414 }
00415 myStep += DELTA_T;
00416 }
00417
00418
00419 MSNet::SimulationState
00420 MSNet::simulationState(SUMOTime stopTime) const throw() {
00421 if (myTooManyVehicles>0&&(int) myVehicleControl->getRunningVehicleNo()>myTooManyVehicles) {
00422 return SIMSTATE_TOO_MANY_VEHICLES;
00423 }
00424 #ifndef NO_TRACI
00425 if (traci::TraCIServer::wasClosed()) {
00426 return SIMSTATE_CONNECTION_CLOSED;
00427 }
00428 if (stopTime < 0 && OptionsCont::getOptions().getInt("remote-port") == 0 && myVehicleControl->haveAllVehiclesQuit() && !myEmitter->hasPendingFlows()) {
00429 #else
00430 if (stopTime < 0 && myVehicleControl->haveAllVehiclesQuit() && !myEmitter->hasPendingFlows()) {
00431 #endif
00432 if (myEmissionEvents->isEmpty()) {
00433 return SIMSTATE_NO_FURTHER_VEHICLES;
00434 }
00435 }
00436 if (stopTime >= 0 && myStep >= stopTime) {
00437 return SIMSTATE_END_STEP_REACHED;
00438 }
00439 return SIMSTATE_RUNNING;
00440 }
00441
00442
00443 std::string
00444 MSNet::getStateMessage(MSNet::SimulationState state) throw() {
00445 switch (state) {
00446 case MSNet::SIMSTATE_RUNNING:
00447 return "";
00448 case MSNet::SIMSTATE_END_STEP_REACHED:
00449 return "The final simulation step has been reached.";
00450 case MSNet::SIMSTATE_NO_FURTHER_VEHICLES:
00451 return "All vehicles have left the simulation.";
00452 case MSNet::SIMSTATE_CONNECTION_CLOSED:
00453 return "TraCI requested termination.";
00454 case MSNet::SIMSTATE_ERROR_IN_SIM:
00455 return "Reason: An error occured (see log).";
00456 case MSNet::SIMSTATE_TOO_MANY_VEHICLES:
00457 return "Too many vehicles.";
00458 default:
00459 return "Unknown reason.";
00460 }
00461 }
00462
00463
00464 void
00465 MSNet::clearAll() {
00466
00467 MSEdge::clear();
00468 MSLane::clear();
00469 MSRoute::clear();
00470 delete MSVehicleTransfer::getInstance();
00471 }
00472
00473
00474 SUMOTime
00475 MSNet::getCurrentTimeStep() const {
00476 return myStep;
00477 }
00478
00479
00480 void
00481 MSNet::writeOutput() {
00482
00483 myDetectorControl->updateDetectors(myStep);
00484
00485 if (OptionsCont::getOptions().isSet("netstate-dump")) {
00486 MSXMLRawOut::write(OutputDevice::getDeviceByOption("netstate-dump"), *myEdges, myStep);
00487 }
00488
00489 if (OptionsCont::getOptions().isSet("emissions-output")) {
00490 std::string wt = myVehicleControl->getMeanWaitingTime() ? "-1.00" : time2string((SUMOTime) myVehicleControl->getMeanWaitingTime());
00491 std::string tt = myVehicleControl->getMeanTravelTime()<0 ? "-1.00" : time2string((SUMOTime) myVehicleControl->getMeanTravelTime());
00492 OutputDevice::getDeviceByOption("emissions-output")
00493 << " <emission-state time=\"" << time2string(myStep) << "\" "
00494 << "loaded=\"" << myVehicleControl->getLoadedVehicleNo() << "\" "
00495 << "emitted=\"" << myVehicleControl->getEmittedVehicleNo() << "\" "
00496 << "running=\"" << myVehicleControl->getRunningVehicleNo() << "\" "
00497 << "waiting=\"" << myEmitter->getWaitingVehicleNo() << "\" "
00498 << "ended=\"" << myVehicleControl->getEndedVehicleNo() << "\" "
00499 << "meanWaitingTime=\"" << wt << "\" "
00500 << "meanTravelTime=\"" << tt << "\" ";
00501 if (myLogExecutionTime) {
00502 OutputDevice::getDeviceByOption("emissions-output")
00503 << "duration=\"" << mySimStepDuration << "\" ";
00504 }
00505 OutputDevice::getDeviceByOption("emissions-output") << "/>\n";
00506 }
00507
00508 myDetectorControl->writeOutput(myStep + DELTA_T, false);
00509 }
00510
00511
00512 bool
00513 MSNet::logSimulationDuration() const throw() {
00514 return myLogExecutionTime;
00515 }
00516
00517
00518 #ifdef HAVE_MESOSIM
00519 void
00520 MSNet::saveState(std::ostream &os) throw() {
00521 FileHelpers::writeString(os, VERSION_STRING);
00522 FileHelpers::writeUInt(os, sizeof(size_t));
00523 FileHelpers::writeUInt(os, sizeof(SUMOReal));
00524 FileHelpers::writeUInt(os, MSEdge::dictSize());
00525 FileHelpers::writeUInt(os, myStep);
00526 myVehicleControl->saveState(os);
00527 if (MSGlobals::gUseMesoSim) {
00528 MSGlobals::gMesoNet->saveState(os);
00529 }
00530 }
00531
00532
00533 unsigned int
00534 MSNet::loadState(BinaryInputDevice &bis) throw() {
00535 std::string version;
00536 unsigned int sizeT, fpSize, numEdges, step;
00537 bis >> version;
00538 bis >> sizeT;
00539 bis >> fpSize;
00540 bis >> numEdges;
00541 bis >> step;
00542 if (version != VERSION_STRING) {
00543 WRITE_WARNING("State was written with sumo version " + version + " (present: " + VERSION_STRING +")!");
00544 }
00545 if (sizeT != sizeof(size_t)) {
00546 WRITE_WARNING("State was written on a different platform (32bit vs. 64bit)!");
00547 }
00548 if (fpSize != sizeof(SUMOReal)) {
00549 WRITE_WARNING("State was written with a different precision for SUMOReal!");
00550 }
00551 if (numEdges != MSEdge::dictSize()) {
00552 WRITE_WARNING("State was written for a different net!");
00553 }
00554 myVehicleControl->loadState(bis);
00555 if (MSGlobals::gUseMesoSim) {
00556 MSGlobals::gMesoNet->loadState(bis, *myVehicleControl);
00557 }
00558 return step;
00559 }
00560 #endif
00561
00562
00563 MSPersonControl &
00564 MSNet::getPersonControl() throw() {
00565 if (myPersonControl==0) {
00566 myPersonControl = new MSPersonControl();
00567 }
00568 return *myPersonControl;
00569 }
00570
00571
00572 MSEdgeWeightsStorage &
00573 MSNet::getWeightsStorage() throw() {
00574 if (myEdgeWeights==0) {
00575 myEdgeWeights = new MSEdgeWeightsStorage();
00576 }
00577 return *myEdgeWeights;
00578 }
00579
00580
00581 void
00582 MSNet::preSimStepOutput() const throw() {
00583 std::cout << std::setprecision(OUTPUT_ACCURACY);
00584 std::cout << "Step #" << time2string(myStep);
00585 }
00586
00587
00588 void
00589 MSNet::postSimStepOutput() const throw() {
00590 if (myLogExecutionTime) {
00591 std::string msg;
00592 std::ostringstream oss;
00593 oss.setf(std::ios::fixed , std::ios::floatfield);
00594 oss.setf(std::ios::showpoint);
00595 oss << std::setprecision(OUTPUT_ACCURACY);
00596 if (mySimStepDuration!=0) {
00597 oss << " (" << mySimStepDuration << "ms ~= "
00598 << (1000./ (SUMOReal) mySimStepDuration) << "*RT, ~"
00599 << ((SUMOReal) myVehicleControl->getRunningVehicleNo()/(SUMOReal) mySimStepDuration*1000.);
00600 } else {
00601 oss << " (0ms ?*RT. ?";
00602 }
00603 oss << "UPS, vehicles"
00604 << " TOT " << myVehicleControl->getEmittedVehicleNo()
00605 << " ACT " << myVehicleControl->getRunningVehicleNo()
00606 << ") ";
00607 msg = oss.str();
00608 std::string prev = "Step #" + time2string(myStep-DELTA_T);
00609 msg = msg.substr(0, 78 - prev.length());
00610 std::cout << msg;
00611 }
00612 std::cout << (char) 13;
00613 }
00614
00615
00616 void
00617 MSNet::addVehicleStateListener(VehicleStateListener *listener) throw() {
00618 if (find(myVehicleStateListeners.begin(), myVehicleStateListeners.end(), listener)==myVehicleStateListeners.end()) {
00619 myVehicleStateListeners.push_back(listener);
00620 }
00621 }
00622
00623
00624 void
00625 MSNet::removeVehicleStateListener(VehicleStateListener *listener) throw() {
00626 std::vector<VehicleStateListener*>::iterator i= find(myVehicleStateListeners.begin(), myVehicleStateListeners.end(), listener);
00627 if (i!=myVehicleStateListeners.end()) {
00628 myVehicleStateListeners.erase(i);
00629 }
00630 }
00631
00632
00633 void
00634 MSNet::informVehicleStateListener(const MSVehicle * const vehicle, VehicleState to) throw() {
00635 for (std::vector<VehicleStateListener*>::iterator i=myVehicleStateListeners.begin(); i!=myVehicleStateListeners.end(); ++i) {
00636 (*i)->vehicleStateChanged(vehicle, to);
00637 }
00638 }
00639
00640
00641
00642 #ifdef _MESSAGES
00643 MSMessageEmitter*
00644 MSNet::getMsgEmitter(const std::string& whatemit) {
00645 msgEmitVec.clear();
00646 msgEmitVec = myMsgEmitter.buildAndGetStaticVector();
00647 MSMessageEmitter *msgEmitter = 0;
00648 for (int i = 0; i < msgEmitVec.size(); ++i) {
00649 if (msgEmitVec.at(i)->getEventsEnabled(whatemit)) {
00650 msgEmitter = msgEmitVec.at(i);
00651 break;
00652 }
00653 }
00654
00655 return msgEmitter;
00656 }
00657
00658
00659 void
00660 MSNet::createMsgEmitter(std::string& id,
00661 std::string& file,
00662 const std::string& base,
00663 std::string& whatemit,
00664 bool reverse,
00665 bool table,
00666 bool xy,
00667 SUMOReal step) {
00668 MSMessageEmitter *msgEmitter = new MSMessageEmitter(file, base, whatemit, reverse, table, xy, step);
00669 myMsgEmitter.add(id, msgEmitter);
00670 }
00671 #endif
00672
00673
00674
00675