LCOV - code coverage report
Current view: top level - src/microsim - MSStateHandler.cpp (source / functions) Coverage Total Hit
Test: lcov.info Lines: 93.9 % 294 276
Test Date: 2024-10-24 15:46:30 Functions: 90.0 % 10 9

            Line data    Source code
       1              : /****************************************************************************/
       2              : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
       3              : // Copyright (C) 2012-2024 German Aerospace Center (DLR) and others.
       4              : // This program and the accompanying materials are made available under the
       5              : // terms of the Eclipse Public License 2.0 which is available at
       6              : // https://www.eclipse.org/legal/epl-2.0/
       7              : // This Source Code may also be made available under the following Secondary
       8              : // Licenses when the conditions for such availability set forth in the Eclipse
       9              : // Public License 2.0 are satisfied: GNU General Public License, version 2
      10              : // or later which is available at
      11              : // https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
      12              : // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
      13              : /****************************************************************************/
      14              : /// @file    MSStateHandler.cpp
      15              : /// @author  Daniel Krajzewicz
      16              : /// @author  Michael Behrisch
      17              : /// @author  Jakob Erdmann
      18              : /// @date    Thu, 13 Dec 2012
      19              : ///
      20              : // Parser and output filter for routes and vehicles state saving and loading
      21              : /****************************************************************************/
      22              : #include <config.h>
      23              : 
      24              : #ifdef HAVE_VERSION_H
      25              : #include <version.h>
      26              : #endif
      27              : 
      28              : #include <sstream>
      29              : #include <utils/common/StringUtils.h>
      30              : #include <utils/options/OptionsCont.h>
      31              : #include <utils/iodevices/OutputDevice.h>
      32              : #include <utils/xml/SUMOXMLDefinitions.h>
      33              : #include <utils/xml/SUMOSAXReader.h>
      34              : #include <utils/xml/XMLSubSys.h>
      35              : #include <utils/vehicle/SUMOVehicleParserHelper.h>
      36              : #include <microsim/traffic_lights/MSTLLogicControl.h>
      37              : #include <microsim/traffic_lights/MSRailSignalConstraint.h>
      38              : #include <microsim/traffic_lights/MSRailSignal.h>
      39              : #include <microsim/traffic_lights/MSDriveWay.h>
      40              : #include <microsim/devices/MSDevice_Routing.h>
      41              : #include <microsim/devices/MSDevice_BTreceiver.h>
      42              : #include <microsim/devices/MSDevice_ToC.h>
      43              : #include <microsim/transportables/MSTransportableControl.h>
      44              : #include <microsim/traffic_lights/MSRailSignalControl.h>
      45              : #include <microsim/MSEdge.h>
      46              : #include <microsim/MSLane.h>
      47              : #include <microsim/MSLink.h>
      48              : #include <microsim/MSGlobals.h>
      49              : #include <microsim/MSNet.h>
      50              : #include <microsim/MSVehicleTransfer.h>
      51              : #include <microsim/MSInsertionControl.h>
      52              : #include <microsim/MSEdgeControl.h>
      53              : #include <microsim/MSRoute.h>
      54              : #include <microsim/MSVehicleControl.h>
      55              : #include <microsim/MSDriverState.h>
      56              : #include <netload/NLHandler.h>
      57              : #include "MSStateHandler.h"
      58              : 
      59              : #include <mesosim/MESegment.h>
      60              : #include <mesosim/MELoop.h>
      61              : 
      62              : 
      63              : // ===========================================================================
      64              : // MSStateTimeHandler method definitions
      65              : // ===========================================================================
      66              : 
      67              : SUMOTime
      68          414 : MSStateHandler::MSStateTimeHandler::getTime(const std::string& fileName) {
      69              :     // build handler and parser
      70          414 :     MSStateTimeHandler handler;
      71          414 :     handler.setFileName(fileName);
      72          414 :     handler.myTime = -1;
      73          414 :     SUMOSAXReader* parser = XMLSubSys::getSAXReader(handler);
      74              :     try {
      75          815 :         if (!parser->parseFirst(fileName)) {
      76            0 :             delete parser;
      77            0 :             throw ProcessError(TLF("Can not read XML-file '%'.", fileName));
      78              :         }
      79           13 :     } catch (ProcessError&) {
      80           13 :         delete parser;
      81           13 :         throw;
      82           13 :     }
      83              :     // parse
      84        57489 :     while (parser->parseNext() && handler.myTime != -1);
      85              :     // clean up
      86          396 :     if (handler.myTime == -1) {
      87            0 :         delete parser;
      88            0 :         throw ProcessError(TLF("Could not parse time from state file '%'", fileName));
      89              :     }
      90          396 :     delete parser;
      91          396 :     return handler.myTime;
      92              : }
      93              : 
      94              : void
      95        23063 : MSStateHandler::MSStateTimeHandler::myStartElement(int element, const SUMOSAXAttributes& attrs) {
      96        23063 :     if (element == SUMO_TAG_SNAPSHOT) {
      97          401 :         myTime = string2time(attrs.getString(SUMO_ATTR_TIME));
      98              :     }
      99        23063 : }
     100              : 
     101              : // ===========================================================================
     102              : // method definitions
     103              : // ===========================================================================
     104          394 : MSStateHandler::MSStateHandler(const std::string& file, const SUMOTime offset) :
     105              :     MSRouteHandler(file, true),
     106          394 :     myOffset(offset),
     107          394 :     mySegment(nullptr),
     108          394 :     myCurrentLane(nullptr),
     109          394 :     myCurrentLink(nullptr),
     110          394 :     myAttrs(nullptr),
     111          394 :     myVCAttrs(nullptr),
     112          394 :     myLastParameterised(nullptr),
     113          394 :     myRemoved(0),
     114          394 :     myConstrainedSignal(nullptr) {
     115          394 :     myAmLoadingState = true;
     116          788 :     const std::vector<std::string> vehIDs = OptionsCont::getOptions().getStringVector("load-state.remove-vehicles");
     117              :     myVehiclesToRemove.insert(vehIDs.begin(), vehIDs.end());
     118          394 :     myAllowInternalRoutes = true;
     119          394 : }
     120              : 
     121              : 
     122          394 : MSStateHandler::~MSStateHandler() {
     123          394 :     delete myVCAttrs;
     124          394 : }
     125              : 
     126              : 
     127              : void
     128          424 : MSStateHandler::saveState(const std::string& file, SUMOTime step, bool usePrefix) {
     129          424 :     OutputDevice& out = OutputDevice::getDevice(file, usePrefix);
     130          424 :     out.setPrecision(OptionsCont::getOptions().getInt("save-state.precision"));
     131          424 :     out.writeHeader<MSEdge>(SUMO_TAG_SNAPSHOT);
     132         1272 :     out.writeAttr("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance").writeAttr("xsi:noNamespaceSchemaLocation", "http://sumo.dlr.de/xsd/state_file.xsd");
     133              :     out.writeAttr(SUMO_ATTR_VERSION, VERSION_STRING);
     134          424 :     out.writeAttr(SUMO_ATTR_TIME, time2string(step));
     135          727 :     out.writeAttr(SUMO_ATTR_TYPE, MSGlobals::gUseMesoSim ? "meso" : "micro");
     136          848 :     if (OptionsCont::getOptions().getBool("save-state.constraints")) {
     137           12 :         out.writeAttr(SUMO_ATTR_CONSTRAINTS, true);
     138              :     }
     139          424 :     if (MSDriveWay::haveDriveWays()) {
     140           22 :         out.writeAttr(SUMO_ATTR_RAIL, true);
     141              :     }
     142          848 :     if (OptionsCont::getOptions().getBool("save-state.rng")) {
     143            6 :         saveRNGs(out);
     144            6 :         if (!MSGlobals::gUseMesoSim) {
     145            3 :             MSNet::getInstance()->getEdgeControl().saveState(out);
     146              :         }
     147              :     }
     148          424 :     MSRoute::dict_saveState(out);
     149          424 :     MSNet::getInstance()->getVehicleControl().saveState(out);
     150          424 :     MSNet::getInstance()->getInsertionControl().saveState(out);
     151          848 :     if (OptionsCont::getOptions().getBool("save-state.transportables")) {
     152           29 :         if (MSNet::getInstance()->hasPersons()) {
     153           29 :             out.openTag(SUMO_TAG_TRANSPORTABLES).writeAttr(SUMO_ATTR_TYPE, "person");
     154           29 :             MSNet::getInstance()->getPersonControl().saveState(out);
     155           58 :             out.closeTag();
     156              :         }
     157           29 :         if (MSNet::getInstance()->hasContainers()) {
     158            0 :             out.openTag(SUMO_TAG_TRANSPORTABLES).writeAttr(SUMO_ATTR_TYPE, "container");
     159            0 :             MSNet::getInstance()->getContainerControl().saveState(out);
     160            0 :             out.closeTag();
     161              :         }
     162              :     }
     163          424 :     MSVehicleTransfer::getInstance()->saveState(out);
     164        10461 :     for (MSEdge* const edge : MSEdge::getAllEdges()) {
     165        10037 :         if (MSGlobals::gUseMesoSim) {
     166         7102 :             for (MESegment* s = MSGlobals::gMesoNet->getSegmentForEdge(*edge); s != nullptr; s = s->getNextSegment()) {
     167         5193 :                 s->saveState(out);
     168              :             }
     169              :         } else {
     170        16973 :             for (MSLane* const lane : edge->getLanes()) {
     171         8845 :                 lane->saveState(out);
     172              :             }
     173              :         }
     174              :     }
     175          424 :     MSNet::getInstance()->getTLSControl().saveState(out);
     176          424 :     out.close();
     177          424 : }
     178              : 
     179              : 
     180              : void
     181        23036 : MSStateHandler::myStartElement(int element, const SUMOSAXAttributes& attrs) {
     182        23036 :     MSRouteHandler::myStartElement(element, attrs);
     183        23036 :     MSVehicleControl& vc = MSNet::getInstance()->getVehicleControl();
     184        23036 :     switch (element) {
     185          394 :         case SUMO_TAG_SNAPSHOT: {
     186          394 :             myTime = string2time(attrs.getString(SUMO_ATTR_TIME));
     187          394 :             const std::string& version = attrs.getString(SUMO_ATTR_VERSION);
     188          394 :             if (version != VERSION_STRING) {
     189          528 :                 WRITE_WARNINGF(TL("State was written with sumo version % (present: %)!"), version, VERSION_STRING);
     190              :             }
     191              :             bool ok;
     192          394 :             if (attrs.getOpt<bool>(SUMO_ATTR_CONSTRAINTS, nullptr, ok, false)) {
     193            5 :                 MSRailSignalConstraint::clearAll();
     194              :             }
     195          394 :             if (attrs.getOpt<bool>(SUMO_ATTR_RAIL, nullptr, ok, false)) {
     196              :                 // init before loading any vehicles to ensure that driveways are built early
     197           13 :                 MSRailSignalControl::getInstance();
     198              :             }
     199              :             break;
     200              :         }
     201            6 :         case SUMO_TAG_RNGSTATE: {
     202            6 :             if (attrs.hasAttribute(SUMO_ATTR_DEFAULT)) {
     203           12 :                 RandHelper::loadState(attrs.getString(SUMO_ATTR_DEFAULT));
     204              :             }
     205            6 :             if (attrs.hasAttribute(SUMO_ATTR_RNG_ROUTEHANDLER)) {
     206           12 :                 RandHelper::loadState(attrs.getString(SUMO_ATTR_RNG_ROUTEHANDLER), MSRouteHandler::getParsingRNG());
     207              :             }
     208            6 :             if (attrs.hasAttribute(SUMO_ATTR_RNG_INSERTIONCONTROL)) {
     209           12 :                 RandHelper::loadState(attrs.getString(SUMO_ATTR_RNG_INSERTIONCONTROL), MSNet::getInstance()->getInsertionControl().getFlowRNG());
     210              :             }
     211            6 :             if (attrs.hasAttribute(SUMO_ATTR_RNG_DEVICE)) {
     212           12 :                 RandHelper::loadState(attrs.getString(SUMO_ATTR_RNG_DEVICE), MSDevice::getEquipmentRNG());
     213              :             }
     214            6 :             if (attrs.hasAttribute(SUMO_ATTR_RNG_DEVICE_BT)) {
     215           12 :                 RandHelper::loadState(attrs.getString(SUMO_ATTR_RNG_DEVICE_BT), MSVehicleDevice_BTreceiver::getEquipmentRNG());
     216              :             }
     217            6 :             if (attrs.hasAttribute(SUMO_ATTR_RNG_DRIVERSTATE)) {
     218           12 :                 RandHelper::loadState(attrs.getString(SUMO_ATTR_RNG_DRIVERSTATE), OUProcess::getRNG());
     219              :             }
     220            6 :             if (attrs.hasAttribute(SUMO_ATTR_RNG_DEVICE_TOC)) {
     221           12 :                 RandHelper::loadState(attrs.getString(SUMO_ATTR_RNG_DEVICE_TOC), MSDevice_ToC::getResponseTimeRNG());
     222              :             }
     223              :             break;
     224              :         }
     225          384 :         case SUMO_TAG_RNGLANE: {
     226          384 :             const int index = attrs.getInt(SUMO_ATTR_INDEX);
     227          384 :             const std::string state = attrs.getString(SUMO_ATTR_STATE);
     228          384 :             MSLane::loadRNGState(index, state);
     229              :             break;
     230              :         }
     231              :         case SUMO_TAG_EDGECONTROL: {
     232              :             bool ok;
     233              :             std::list<MSLane*> activeLanes;
     234            3 :             const std::vector<std::string>& laneIDs = attrs.get<std::vector<std::string> >(SUMO_ATTR_LANES, nullptr, ok, false);
     235            7 :             for (const std::string& laneID : laneIDs) {
     236            4 :                 MSLane* lane = MSLane::dictionary(laneID);
     237            4 :                 if (lane == nullptr) {
     238            0 :                     throw ProcessError(TLF("Unknown lane '%' in loaded state.", laneID));
     239              :                 }
     240              :                 activeLanes.push_back(lane);
     241              :             }
     242            3 :             MSNet::getInstance()->getEdgeControl().setActiveLanes(activeLanes);
     243              :             break;
     244            3 :         }
     245          394 :         case SUMO_TAG_DELAY: {
     246          394 :             if (myVCAttrs != nullptr) {
     247            0 :                 delete myVCAttrs;
     248              :             }
     249          394 :             myVCAttrs = attrs.clone();
     250          394 :             break;
     251              :         }
     252           43 :         case SUMO_TAG_FLOWSTATE: {
     253              :             bool ok;
     254           43 :             SUMOVehicleParameter* pars = SUMOVehicleParserHelper::parseFlowAttributes(SUMO_TAG_FLOWSTATE, attrs, true, true, -1, -1, true);
     255           43 :             pars->repetitionsDone = attrs.get<int>(SUMO_ATTR_DONE, pars->id.c_str(), ok);
     256           43 :             pars->repetitionTotalOffset = attrs.getOptSUMOTimeReporting(SUMO_ATTR_NEXT, pars->id.c_str(), ok, 0);
     257           43 :             int index = attrs.getInt(SUMO_ATTR_INDEX);
     258           43 :             MSNet::getInstance()->getInsertionControl().addFlow(pars, index);
     259              :             break;
     260              :         }
     261          623 :         case SUMO_TAG_VTYPE: {
     262          623 :             myLastParameterised = myCurrentVType;
     263          623 :             break;
     264              :         }
     265         4441 :         case SUMO_TAG_VEHICLE: {
     266         4441 :             myLastParameterised = myVehicleParameter;
     267         4441 :             myAttrs = attrs.clone();
     268         4441 :             break;
     269              :         }
     270         5340 :         case SUMO_TAG_DEVICE: {
     271         5340 :             myDeviceAttrs.push_back(attrs.clone());
     272         5340 :             break;
     273              :         }
     274          185 :         case SUMO_TAG_VEHICLETRANSFER: {
     275          185 :             MSVehicleTransfer::getInstance()->loadState(attrs, myOffset, vc);
     276          185 :             break;
     277              :         }
     278          171 :         case SUMO_TAG_SEGMENT: {
     279          171 :             const std::string& segmentID = attrs.getString(SUMO_ATTR_ID);
     280          342 :             const MSEdge* const edge = MSEdge::dictionary(segmentID.substr(0, segmentID.rfind(":")));
     281          171 :             int idx = StringUtils::toInt(segmentID.substr(segmentID.rfind(":") + 1));
     282          171 :             mySegment = MSGlobals::gMesoNet->getSegmentForEdge(*edge);
     283          269 :             while (idx-- > 0) {
     284           98 :                 mySegment = mySegment->getNextSegment();
     285              :             }
     286          171 :             myQueIndex = 0;
     287              :             break;
     288              :         }
     289          567 :         case SUMO_TAG_LANE: {
     290              :             bool ok;
     291          567 :             const std::string laneID = attrs.get<std::string>(SUMO_ATTR_ID, nullptr, ok);
     292          567 :             myCurrentLane = MSLane::dictionary(laneID);
     293          567 :             if (myCurrentLane == nullptr) {
     294            0 :                 throw ProcessError(TLF("Unknown lane '%' in loaded state.", laneID));
     295              :             }
     296              :             break;
     297              :         }
     298          727 :         case SUMO_TAG_VIEWSETTINGS_VEHICLES: {
     299              :             bool ok;
     300          727 :             const std::vector<std::string>& vehIDs = attrs.get<std::vector<std::string> >(SUMO_ATTR_VALUE, nullptr, ok, false);
     301          727 :             if (MSGlobals::gUseMesoSim) {
     302          362 :                 mySegment->loadState(vehIDs, MSNet::getInstance()->getVehicleControl(), StringUtils::toLong(attrs.getString(SUMO_ATTR_TIME)) - myOffset, myQueIndex);
     303              :             } else {
     304          546 :                 myCurrentLane->loadState(vehIDs, MSNet::getInstance()->getVehicleControl());
     305              :             }
     306          727 :             myQueIndex++;
     307              :             break;
     308          727 :         }
     309           37 :         case SUMO_TAG_LINK: {
     310              :             bool ok;
     311           37 :             myCurrentLink = nullptr;
     312           37 :             const std::string toLaneID = attrs.get<std::string>(SUMO_ATTR_TO, nullptr, ok);
     313           77 :             for (MSLink* link : myCurrentLane->getLinkCont()) {
     314           40 :                 if (link->getViaLaneOrLane()->getID() == toLaneID) {
     315           37 :                     myCurrentLink = link;
     316              :                 }
     317              :             }
     318           37 :             if (myCurrentLink == nullptr) {
     319            0 :                 throw ProcessError("Unknown link from lane '" + myCurrentLane->getID() + "' to lane '" + toLaneID + "' in loaded state");
     320              :             }
     321              :             break;
     322              :         }
     323           37 :         case SUMO_TAG_APPROACHING: {
     324              :             bool ok;
     325           37 :             const std::string vehID = attrs.get<std::string>(SUMO_ATTR_ID, nullptr, ok);
     326           37 :             const SUMOTime arrivalTime = attrs.get<SUMOTime>(SUMO_ATTR_ARRIVALTIME, nullptr, ok);
     327           37 :             const double arrivalSpeed = attrs.get<double>(SUMO_ATTR_ARRIVALSPEED, nullptr, ok);
     328           37 :             const double leaveSpeed = attrs.get<double>(SUMO_ATTR_DEPARTSPEED, nullptr, ok);
     329           37 :             const bool setRequest = attrs.get<bool>(SUMO_ATTR_REQUEST, nullptr, ok);
     330           37 :             const double arrivalSpeedBraking = attrs.get<double>(SUMO_ATTR_ARRIVALSPEEDBRAKING, nullptr, ok);
     331           37 :             const SUMOTime waitingTime = attrs.get<SUMOTime>(SUMO_ATTR_WAITINGTIME, nullptr, ok);
     332           37 :             const double dist = attrs.get<double>(SUMO_ATTR_DISTANCE, nullptr, ok);
     333           37 :             const double latOffset = attrs.getOpt<double>(SUMO_ATTR_POSITION_LAT, nullptr, ok, 0);
     334           37 :             SUMOVehicle* veh = vc.getVehicle(vehID);
     335           37 :             myCurrentLink->setApproaching(veh, arrivalTime, arrivalSpeed, leaveSpeed, setRequest, arrivalSpeedBraking, waitingTime, dist, latOffset);
     336           37 :             if (!MSGlobals::gUseMesoSim) {
     337           37 :                 MSVehicle* microVeh = dynamic_cast<MSVehicle*>(veh);
     338           37 :                 microVeh->loadPreviousApproaching(myCurrentLink, setRequest, arrivalTime, arrivalSpeed, arrivalSpeedBraking, dist, leaveSpeed);
     339              :             }
     340              :             break;
     341              :         }
     342            4 :         case SUMO_TAG_RAILSIGNAL_CONSTRAINT_TRACKER: {
     343            4 :             MSRailSignalConstraint_Predecessor::loadState(attrs);
     344            4 :             break;
     345              :         }
     346           29 :         case SUMO_TAG_DRIVEWAY: 
     347              :         case SUMO_TAG_SUBDRIVEWAY: { 
     348           29 :             MSDriveWay::loadState(attrs, element);
     349           29 :             break;
     350              :         }
     351          129 :         case SUMO_TAG_PARAM: {
     352              :             bool ok;
     353          129 :             const std::string key = attrs.get<std::string>(SUMO_ATTR_KEY, nullptr, ok);
     354              :             // circumventing empty string test
     355          129 :             const std::string val = attrs.hasAttribute(SUMO_ATTR_VALUE) ? attrs.getString(SUMO_ATTR_VALUE) : "";
     356              :             assert(myLastParameterised != 0);
     357          129 :             if (myLastParameterised != nullptr) {
     358          129 :                 myLastParameterised->setParameter(key, val);
     359              :             }
     360              :             break;
     361              :         }
     362           34 :         case SUMO_TAG_TRANSPORTABLES:
     363           34 :             if (attrs.getString(SUMO_ATTR_TYPE) == "person") {
     364           68 :                 MSNet::getInstance()->getPersonControl().loadState(attrs.getString(SUMO_ATTR_STATE));
     365              :             }
     366           34 :             if (attrs.getString(SUMO_ATTR_TYPE) == "container") {
     367            0 :                 MSNet::getInstance()->getContainerControl().loadState(attrs.getString(SUMO_ATTR_STATE));
     368              :             }
     369              :             break;
     370           48 :         case SUMO_TAG_PERSON:
     371              :         case SUMO_TAG_CONTAINER:
     372           48 :             myAttrs = attrs.clone();
     373           48 :             break;
     374           13 :         case SUMO_TAG_RAILSIGNAL_CONSTRAINTS: {
     375           13 :             bool ok = true;
     376           13 :             const std::string signalID = attrs.get<std::string>(SUMO_ATTR_ID, nullptr, ok);
     377           13 :             if (!MSNet::getInstance()->getTLSControl().knows(signalID)) {
     378            0 :                 throw InvalidArgument("Rail signal '" + signalID + "' in railSignalConstraints loaded from state is not known");
     379              :             }
     380           13 :             myConstrainedSignal = dynamic_cast<MSRailSignal*>(MSNet::getInstance()->getTLSControl().get(signalID).getDefault());
     381           13 :             if (myConstrainedSignal == nullptr) {
     382            0 :                 throw InvalidArgument("Traffic light '" + signalID + "' is not a rail signal");
     383              :             }
     384              :             break;
     385              :         }
     386           17 :         case SUMO_TAG_PREDECESSOR: // intended fall-through
     387              :         case SUMO_TAG_INSERTION_PREDECESSOR: // intended fall-through
     388              :         case SUMO_TAG_FOE_INSERTION: // intended fall-through
     389              :         case SUMO_TAG_INSERTION_ORDER: // intended fall-through
     390              :         case SUMO_TAG_BIDI_PREDECESSOR:
     391           17 :             myLastParameterised = NLHandler::addPredecessorConstraint(element, attrs, myConstrainedSignal);
     392           17 :             break;
     393         1430 :         case SUMO_TAG_TLLOGIC: {
     394              :             bool ok;
     395         1430 :             const std::string tlID = attrs.get<std::string>(SUMO_ATTR_ID, nullptr, ok);
     396         1430 :             const std::string programID = attrs.get<std::string>(SUMO_ATTR_PROGRAMID, tlID.c_str(), ok);
     397         1430 :             const int phase = attrs.get<int>(SUMO_ATTR_PHASE, tlID.c_str(), ok);
     398         1430 :             const SUMOTime spentDuration = attrs.get<SUMOTime>(SUMO_ATTR_DURATION, tlID.c_str(), ok);
     399         1430 :             MSTLLogicControl& tlc = MSNet::getInstance()->getTLSControl();
     400         1430 :             MSTrafficLightLogic* tl = tlc.get(tlID, programID);
     401         1430 :             if (tl == nullptr) {
     402            8 :                 if (programID == "online") {
     403           24 :                     WRITE_WARNINGF(TL("Ignoring program '%' for traffic light '%' in loaded state"), programID, tlID);
     404              :                     return;
     405              :                 } else {
     406            0 :                     throw ProcessError("Unknown program '" + programID + "' for traffic light '" + tlID + "'");
     407              :                 }
     408              :             }
     409         1422 :             if (phase >= tl->getPhaseNumber()) {
     410            0 :                 throw ProcessError("Invalid phase '" + toString(phase) + "' for traffic light '" + tlID + "'");
     411              :             }
     412              :             // might not be set if the phase happens to match and there are multiple programs
     413         1422 :             tl->loadState(tlc, myTime, phase, spentDuration);
     414              :             break;
     415              :         }
     416              :         default:
     417              :             break;
     418              :     }
     419              : }
     420              : 
     421              : 
     422              : void
     423        23036 : MSStateHandler::myEndElement(int element) {
     424        23036 :     MSRouteHandler::myEndElement(element);
     425        23036 :     switch (element) {
     426           48 :         case SUMO_TAG_PERSON:
     427              :         case SUMO_TAG_CONTAINER: {
     428           48 :             MSTransportableControl& tc = (element == SUMO_TAG_PERSON ? MSNet::getInstance()->getPersonControl() : MSNet::getInstance()->getContainerControl());
     429           48 :             MSTransportable* transportable = tc.get(myAttrs->getString(SUMO_ATTR_ID));
     430           48 :             transportable->loadState(myAttrs->getString(SUMO_ATTR_STATE));
     431           48 :             tc.fixLoadCount(transportable);
     432           48 :             delete myAttrs;
     433           48 :             myAttrs = nullptr;
     434           48 :             break;
     435              :         }
     436          394 :         case SUMO_TAG_SNAPSHOT: {
     437          394 :             if (myVCAttrs == nullptr) {
     438            0 :                 throw ProcessError(TL("Could not load vehicle control state"));
     439              :             }
     440          394 :             MSVehicleControl& vc = MSNet::getInstance()->getVehicleControl();
     441          394 :             vc.setState(myVCAttrs->getInt(SUMO_ATTR_NUMBER),
     442          394 :                         myVCAttrs->getInt(SUMO_ATTR_BEGIN),
     443          394 :                         myVCAttrs->getInt(SUMO_ATTR_END),
     444          394 :                         myVCAttrs->getFloat(SUMO_ATTR_DEPART),
     445          394 :                         myVCAttrs->getFloat(SUMO_ATTR_TIME));
     446          394 :             if (myRemoved > 0) {
     447           12 :                 WRITE_MESSAGEF(TL("Removed % vehicles while loading state."), toString(myRemoved));
     448            6 :                 vc.discountStateRemoved(myRemoved);
     449              :             }
     450              :             break;
     451              :         }
     452              :         default:
     453              :             break;
     454              :     }
     455        23036 :     if (element != SUMO_TAG_PARAM && myVehicleParameter == nullptr && myCurrentVType == nullptr) {
     456        14093 :         myLastParameterised = nullptr;
     457              :     }
     458        23036 : }
     459              : 
     460              : 
     461              : void
     462         4441 : MSStateHandler::closeVehicle() {
     463              :     assert(myVehicleParameter != nullptr);
     464         4441 :     myVehicleParameter->depart -= myOffset;
     465              :     // the vehicle was already counted in MSVehicleControl::setState
     466         4441 :     MSVehicleControl& vc = MSNet::getInstance()->getVehicleControl();
     467              :     // make a copy because myVehicleParameter is reset in closeVehicle()
     468         4441 :     const std::string vehID = myVehicleParameter->id;
     469              :     if (myVehiclesToRemove.count(vehID) == 0) {
     470         4435 :         MSRouteHandler::closeVehicle();
     471         4435 :         SUMOVehicle* v = vc.getVehicle(vehID);
     472         4435 :         if (v == nullptr) {
     473            0 :             throw ProcessError(TLF("Could not load vehicle '%' from state", vehID));
     474              :         }
     475         4435 :         v->setChosenSpeedFactor(myAttrs->getFloat(SUMO_ATTR_SPEEDFACTOR));
     476         4435 :         v->loadState(*myAttrs, myOffset);
     477              : 
     478         4435 :         if (v->hasDeparted()) {
     479              :             // vehicle already departed: disable pre-insertion rerouting and enable regular routing behavior
     480         1804 :             MSDevice_Routing* routingDevice = static_cast<MSDevice_Routing*>(v->getDevice(typeid(MSDevice_Routing)));
     481              :             if (routingDevice != nullptr) {
     482         1364 :                 routingDevice->notifyEnter(*v, MSMoveReminder::NOTIFICATION_DEPARTED);
     483              :             }
     484         1804 :             MSNet::getInstance()->getInsertionControl().alreadyDeparted(v);
     485         1804 :             if (MSRailSignalControl::hasInstance()) {
     486              :                 // register route for deadlock prevention (vehicleStateChanged would not be called otherwise)
     487           42 :                 MSRailSignalControl::getInstance().vehicleStateChanged(v, MSNet::VehicleState::NEWROUTE, "loadState");
     488              :             }
     489         1804 :             vc.handleTriggeredDepart(v, false);
     490         1804 :             if (v->hasArrived()) {
     491              :                 // state was created with active option --keep-after-arrival
     492            3 :                 vc.deleteKeptVehicle(v);
     493              :             }
     494              :         }
     495         9775 :         while (!myDeviceAttrs.empty()) {
     496         5340 :             const std::string attrID = myDeviceAttrs.back()->getString(SUMO_ATTR_ID);
     497        12624 :             for (MSVehicleDevice* const dev : v->getDevices()) {
     498         7284 :                 if (dev->getID() == attrID) {
     499         4952 :                     dev->loadState(*myDeviceAttrs.back());
     500              :                 }
     501              :             }
     502         5340 :             delete myDeviceAttrs.back();
     503              :             myDeviceAttrs.pop_back();
     504              :         }
     505              :     } else {
     506            6 :         delete myVehicleParameter;
     507            6 :         myVehicleParameter = nullptr;
     508            6 :         myRemoved++;
     509              :     }
     510         4441 :     delete myAttrs;
     511         4441 : }
     512              : 
     513              : 
     514              : void
     515            6 : MSStateHandler::saveRNGs(OutputDevice& out) {
     516            6 :     out.openTag(SUMO_TAG_RNGSTATE);
     517            6 :     out.writeAttr(SUMO_ATTR_DEFAULT, RandHelper::saveState());
     518            6 :     out.writeAttr(SUMO_ATTR_RNG_ROUTEHANDLER, RandHelper::saveState(MSRouteHandler::getParsingRNG()));
     519            6 :     out.writeAttr(SUMO_ATTR_RNG_INSERTIONCONTROL, RandHelper::saveState(MSNet::getInstance()->getInsertionControl().getFlowRNG()));
     520            6 :     out.writeAttr(SUMO_ATTR_RNG_DEVICE, RandHelper::saveState(MSDevice::getEquipmentRNG()));
     521            6 :     out.writeAttr(SUMO_ATTR_RNG_DEVICE_BT, RandHelper::saveState(MSDevice_BTreceiver::getRNG()));
     522            6 :     out.writeAttr(SUMO_ATTR_RNG_DRIVERSTATE, RandHelper::saveState(OUProcess::getRNG()));
     523            6 :     out.writeAttr(SUMO_ATTR_RNG_DEVICE_TOC, RandHelper::saveState(MSDevice_ToC::getResponseTimeRNG()));
     524            6 :     MSLane::saveRNGStates(out);
     525            6 :     out.closeTag();
     526              : 
     527            6 : }
     528              : 
     529              : 
     530              : /****************************************************************************/
        

Generated by: LCOV version 2.0-1