Line data Source code
1 : /****************************************************************************/
2 : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3 : // Copyright (C) 2001-2025 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 MSStopOut.cpp
15 : /// @author Jakob Erdmann
16 : /// @date Wed, 21.12.2016
17 : ///
18 : // Ouput information about planned vehicle stop
19 : /****************************************************************************/
20 : #include <config.h>
21 :
22 : #include <utils/vehicle/SUMOVehicle.h>
23 : #include <utils/options/OptionsCont.h>
24 : #include <utils/common/MsgHandler.h>
25 : #include <microsim/MSNet.h>
26 : #include <microsim/MSEdge.h>
27 : #include <microsim/MSLane.h>
28 : #include <microsim/MSGlobals.h>
29 : #include <microsim/MSParkingArea.h>
30 : #include <microsim/MSStoppingPlace.h>
31 : #include <microsim/MSVehicleType.h>
32 : #include <microsim/trigger/MSChargingStation.h>
33 : #include <microsim/trigger/MSOverheadWire.h>
34 : #include "MSStopOut.h"
35 :
36 :
37 : // ---------------------------------------------------------------------------
38 : // static initialisation methods
39 : // ---------------------------------------------------------------------------
40 : MSStopOut* MSStopOut::myInstance = nullptr;
41 :
42 : void
43 38596 : MSStopOut::init() {
44 77192 : if (OptionsCont::getOptions().isSet("stop-output")) {
45 1353 : myInstance = new MSStopOut(OutputDevice::getDeviceByOption("stop-output"));
46 : }
47 38596 : }
48 :
49 : void
50 38670 : MSStopOut::cleanup() {
51 38670 : delete myInstance;
52 38670 : myInstance = nullptr;
53 38670 : }
54 :
55 : // ===========================================================================
56 : // method definitions
57 : // ===========================================================================
58 1353 : MSStopOut::MSStopOut(OutputDevice& dev) :
59 1353 : myDevice(dev) {
60 1353 : }
61 :
62 2698 : MSStopOut::~MSStopOut() {}
63 :
64 :
65 : void
66 4505 : MSStopOut::stopBlocked(const SUMOVehicle* veh, SUMOTime time) {
67 : assert(veh != nullptr);
68 : if (myStopped.count(veh) == 0) {
69 152 : myStopped.emplace(veh, StopInfo(-time, -1, -1));
70 : }
71 4505 : }
72 :
73 :
74 : void
75 6 : MSStopOut::stopNotStarted(const SUMOVehicle* veh) {
76 : assert(veh != nullptr);
77 : myStopped.erase(veh);
78 6 : }
79 :
80 :
81 : void
82 5893 : MSStopOut::stopStarted(const SUMOVehicle* veh, int numPersons, int numContainers, SUMOTime time) {
83 : assert(veh != nullptr);
84 : if (myStopped.count(veh) == 0) {
85 5745 : myStopped.emplace(veh, StopInfo(0, numPersons, numContainers));
86 : } else {
87 : MSStopOut::StopInfo& info = myStopped.find(veh)->second;
88 148 : info.blockTime += time;
89 148 : info.initialNumPersons = numPersons;
90 148 : info.initialNumContainers = numContainers;
91 : }
92 5893 : }
93 :
94 :
95 : void
96 2702 : MSStopOut::loadedPersons(const SUMOVehicle* veh, int n) {
97 : // ignore triggered vehicles
98 2702 : if (veh->hasDeparted()) {
99 : if (myStopped.count(veh) == 0) {
100 0 : WRITE_WARNINGF(TL("Vehicle '%' loads persons on edge '%', time=% without starting the stop."),
101 : veh->getID(), veh->getEdge()->getID(), time2string(SIMSTEP));
102 : } else {
103 2641 : myStopped.find(veh)->second.loadedPersons += n;
104 : }
105 : }
106 2702 : }
107 :
108 :
109 : void
110 1804 : MSStopOut::unloadedPersons(const SUMOVehicle* veh, int n) {
111 : if (myStopped.count(veh) == 0) {
112 0 : WRITE_WARNINGF(TL("Vehicle '%' unloads persons on edge '%', time=% without starting the stop."),
113 : veh->getID(), veh->getEdge()->getID(), time2string(SIMSTEP));
114 : } else {
115 1804 : myStopped.find(veh)->second.unloadedPersons += n;
116 : }
117 1804 : }
118 :
119 :
120 : void
121 187 : MSStopOut::loadedContainers(const SUMOVehicle* veh, int n) {
122 : // ignore triggered vehicles
123 187 : if (veh->hasDeparted()) {
124 : if (myStopped.count(veh) == 0) {
125 0 : WRITE_WARNINGF(TL("Vehicle '%' loads container on edge '%', time=% without starting the stop."),
126 : veh->getID(), veh->getEdge()->getID(), time2string(SIMSTEP));
127 : } else {
128 173 : myStopped.find(veh)->second.loadedContainers += n;
129 : }
130 : }
131 187 : }
132 :
133 :
134 : void
135 138 : MSStopOut::unloadedContainers(const SUMOVehicle* veh, int n) {
136 : if (myStopped.count(veh) == 0) {
137 0 : WRITE_WARNINGF(TL("Vehicle '%' unloads container on edge '%', time=% without starting the stop."),
138 : veh->getID(), veh->getEdge()->getID(), time2string(SIMSTEP));
139 : } else {
140 138 : myStopped.find(veh)->second.unloadedContainers += n;
141 : }
142 138 : }
143 :
144 :
145 : void
146 5727 : MSStopOut::stopEnded(const SUMOVehicle* veh, const SUMOVehicleParameter::Stop& stop, const std::string& laneOrEdgeID, bool simEnd) {
147 : assert(veh != nullptr);
148 : if (myStopped.count(veh) == 0) {
149 0 : WRITE_WARNINGF(TL("Vehicle '%' ends stop on edge '%', time=% without entering the stop."),
150 : veh->getID(), veh->getEdge()->getID(), time2string(SIMSTEP));
151 0 : return;
152 : }
153 : const StopInfo& si = myStopped.find(veh)->second;
154 5727 : double delay = -1;
155 5727 : double arrivalDelay = -1;
156 5727 : if (stop.until >= 0 && !simEnd) {
157 1640 : delay = STEPS2TIME(SIMSTEP - stop.until);
158 : }
159 5727 : if (stop.arrival >= 0) {
160 246 : arrivalDelay = STEPS2TIME(stop.started - stop.arrival);
161 : }
162 5727 : myDevice.openTag("stopinfo");
163 5727 : myDevice.writeAttr(SUMO_ATTR_ID, veh->getID());
164 5727 : myDevice.writeAttr(SUMO_ATTR_TYPE, veh->getVehicleType().getID());
165 5727 : if (MSGlobals::gUseMesoSim) {
166 897 : myDevice.writeAttr(SUMO_ATTR_EDGE, laneOrEdgeID);
167 : } else {
168 4830 : myDevice.writeAttr(SUMO_ATTR_LANE, laneOrEdgeID);
169 : }
170 5727 : myDevice.writeAttr(SUMO_ATTR_POSITION, veh->getPositionOnLane());
171 5727 : myDevice.writeAttr(SUMO_ATTR_PARKING, stop.parking);
172 5727 : myDevice.writeAttr(SUMO_ATTR_STARTED, time2string(stop.started));
173 5727 : myDevice.writeAttr(SUMO_ATTR_ENDED, simEnd ? "-1" : time2string(SIMSTEP));
174 5727 : if (stop.until >= 0) {
175 3280 : myDevice.writeAttr("delay", delay);
176 : }
177 5727 : if (stop.arrival >= 0) {
178 246 : myDevice.writeAttr(SUMO_ATTR_ARRIVALDELAY, arrivalDelay);
179 : }
180 5727 : if (stop.busstop != "") {
181 2508 : myDevice.writeAttr(SUMO_ATTR_BUS_STOP, stop.busstop);
182 : }
183 5727 : if (stop.containerstop != "") {
184 16 : myDevice.writeAttr(SUMO_ATTR_CONTAINER_STOP, stop.containerstop);
185 : }
186 5727 : if (stop.parkingarea != "") {
187 1805 : myDevice.writeAttr(SUMO_ATTR_PARKING_AREA, stop.parkingarea);
188 : }
189 5727 : if (stop.chargingStation != "") {
190 67 : myDevice.writeAttr(SUMO_ATTR_CHARGING_STATION, stop.chargingStation);
191 : }
192 5727 : if (stop.overheadWireSegment != "") {
193 0 : myDevice.writeAttr(SUMO_ATTR_OVERHEAD_WIRE_SEGMENT, stop.overheadWireSegment);
194 : }
195 5727 : if (stop.tripId != "") {
196 31 : myDevice.writeAttr(SUMO_ATTR_TRIP_ID, stop.tripId);
197 : }
198 5727 : if (stop.line != "") {
199 11 : myDevice.writeAttr(SUMO_ATTR_LINE, stop.line);
200 : }
201 5727 : if (stop.split != "") {
202 44 : myDevice.writeAttr(SUMO_ATTR_SPLIT, stop.split);
203 : }
204 5727 : if (MSGlobals::gUseStopEnded) {
205 30 : myDevice.writeAttr(SUMO_ATTR_USED_ENDED, stop.ended >= 0);
206 : }
207 5727 : myDevice.writeAttr("initialPersons", si.initialNumPersons);
208 5727 : myDevice.writeAttr("loadedPersons", si.loadedPersons);
209 5727 : myDevice.writeAttr("unloadedPersons", si.unloadedPersons);
210 5727 : myDevice.writeAttr("initialContainers", si.initialNumContainers);
211 5727 : myDevice.writeAttr("loadedContainers", si.loadedContainers);
212 5727 : myDevice.writeAttr("unloadedContainers", si.unloadedContainers);
213 11454 : myDevice.writeAttr("blockedDuration", time2string(si.blockTime));
214 11454 : myDevice.closeTag();
215 : myStopped.erase(veh);
216 : }
217 :
218 :
219 : void
220 120 : MSStopOut::generateOutputForUnfinished() {
221 1330 : while (!myStopped.empty()) {
222 : const auto& item = *myStopped.begin();
223 1210 : const SUMOVehicle* veh = item.first;
224 1210 : const SUMOVehicleParameter::Stop* stop = veh->getNextStopParameter();
225 : assert(stop != nullptr);
226 1210 : const std::string laneOrEdgeID = MSGlobals::gUseMesoSim ? veh->getEdge()->getID() : Named::getIDSecure(veh->getLane());
227 : // erases item from myStopped
228 1210 : stopEnded(veh, *stop, laneOrEdgeID, true);
229 : }
230 120 : }
231 :
232 :
233 : /****************************************************************************/
|