Line data Source code
1 : /****************************************************************************/
2 : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3 : // Copyright (C) 2014-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 TrajectoriesHandler.cpp
15 : /// @author Michael Behrisch
16 : /// @date 14.03.2014
17 : ///
18 : // An XML-Handler for amitran and netstate trajectories
19 : /****************************************************************************/
20 : #include <config.h>
21 :
22 : #include <string>
23 : #include <utility>
24 : #include <iostream>
25 : #include <utils/common/UtilExceptions.h>
26 : #include <utils/common/MsgHandler.h>
27 : #include <utils/common/ToString.h>
28 : #include <utils/emissions/PollutantsInterface.h>
29 : #include <utils/emissions/EnergyParams.h>
30 : #include <utils/geom/GeomHelper.h>
31 : #include <utils/iodevices/OutputDevice.h>
32 : #include <utils/xml/SUMOSAXHandler.h>
33 : #include <utils/xml/SUMOXMLDefinitions.h>
34 : #include "TrajectoriesHandler.h"
35 :
36 :
37 : // ===========================================================================
38 : // method definitions
39 : // ===========================================================================
40 996 : TrajectoriesHandler::TrajectoriesHandler(const bool computeA, const bool computeAForward,
41 : const bool accelZeroCorrection, const SUMOEmissionClass defaultClass, EnergyParams* params,
42 996 : long long int attributes, const double defaultSlope, std::ostream* stdOut, OutputDevice* xmlOut) :
43 : SUMOSAXHandler(""),
44 996 : myComputeA(computeA),
45 996 : myComputeAForward(computeAForward),
46 996 : myAccelZeroCorrection(accelZeroCorrection),
47 996 : myDefaultClass(defaultClass),
48 996 : myParams(params), myAttributes(attributes),
49 1992 : myDefaultSlope(defaultSlope), myStdOut(stdOut), myXMLOut(xmlOut), myCurrentTime(-1), myStepSize(TS) {}
50 :
51 :
52 1992 : TrajectoriesHandler::~TrajectoriesHandler() {}
53 :
54 :
55 : void
56 592 : TrajectoriesHandler::myStartElement(int element,
57 : const SUMOSAXAttributes& attrs) {
58 592 : bool ok = true;
59 592 : switch (element) {
60 2 : case SUMO_TAG_TRAJECTORIES:
61 2 : myStepSize = attrs.getFloat("timeStepSize") / 1000.;
62 2 : break;
63 0 : case SUMO_TAG_TIMESTEP:
64 0 : myCurrentTime = attrs.getSUMOTimeReporting(SUMO_ATTR_TIME, nullptr, ok);
65 0 : break;
66 4 : case SUMO_TAG_VEHICLE:
67 4 : if (attrs.hasAttribute(SUMO_ATTR_SPEED)) {
68 0 : double v = attrs.getFloat(SUMO_ATTR_SPEED);
69 0 : double a = INVALID_VALUE;
70 0 : double s = INVALID_VALUE;
71 0 : writeEmissions(std::cout, attrs.getString(SUMO_ATTR_ID), myDefaultClass, myParams, myAttributes, STEPS2TIME(myCurrentTime), v, a, s);
72 : } else {
73 4 : const std::string acId = attrs.getString(SUMO_ATTR_ACTORCONFIG);
74 4 : const std::string id = attrs.getString(SUMO_ATTR_ID);
75 : if (myEmissionClassByType.count(acId) == 0) {
76 0 : WRITE_WARNINGF(TL("Unknown actor configuration '%' for vehicle '%'!"), acId, id);
77 : } else {
78 4 : myEmissionClassByVehicle[id] = myEmissionClassByType.count(acId) > 0 ? myEmissionClassByType[acId] : myDefaultClass;
79 : }
80 : }
81 : break;
82 2 : case SUMO_TAG_ACTORCONFIG: {
83 2 : const std::string id = attrs.getString(SUMO_ATTR_ID);
84 2 : const std::string vClass = attrs.getString(SUMO_ATTR_VEHICLECLASS);
85 2 : const std::string fuel = attrs.getString(SUMO_ATTR_FUEL);
86 2 : const std::string eClass = attrs.getString(SUMO_ATTR_EMISSIONCLASS);
87 2 : const double weight = attrs.getOpt<double>(SUMO_ATTR_WEIGHT, id.c_str(), ok, 0.) * 10.;
88 2 : myEmissionClassByType[id] = PollutantsInterface::getClass(myDefaultClass, vClass, fuel, eClass, weight);
89 : break;
90 : }
91 584 : case SUMO_TAG_MOTIONSTATE: {
92 584 : const std::string id = attrs.getString(SUMO_ATTR_VEHICLE);
93 : if (myEmissionClassByVehicle.count(id) == 0) {
94 0 : WRITE_WARNINGF(TL("Motion state for unknown vehicle '%'!"), id);
95 0 : myEmissionClassByVehicle[id] = myDefaultClass;
96 : }
97 584 : const SUMOEmissionClass c = myEmissionClassByVehicle[id];
98 584 : double v = attrs.getFloat(SUMO_ATTR_SPEED) / 100.;
99 584 : double a = attrs.hasAttribute(SUMO_ATTR_ACCELERATION) ? attrs.get<double>(SUMO_ATTR_ACCELERATION, id.c_str(), ok) / 1000. : INVALID_VALUE;
100 584 : double s = attrs.hasAttribute(SUMO_ATTR_SLOPE) ? RAD2DEG(asin(attrs.get<double>(SUMO_ATTR_SLOPE, id.c_str(), ok) / 10000.)) : INVALID_VALUE;
101 584 : const SUMOTime time = attrs.getOpt<int>(SUMO_ATTR_TIME, id.c_str(), ok, INVALID_VALUE);
102 584 : if (myXMLOut != nullptr) {
103 1168 : writeXMLEmissions(id, c, nullptr, time, v, a, s);
104 : }
105 584 : if (myStdOut != nullptr) {
106 0 : writeEmissions(*myStdOut, id, c, nullptr, myAttributes, STEPS2TIME(time), v, a, s);
107 : }
108 : break;
109 : }
110 : default:
111 : break;
112 : }
113 592 : }
114 :
115 :
116 : const PollutantsInterface::Emissions
117 1171329 : TrajectoriesHandler::computeEmissions(const std::string id, const SUMOEmissionClass c,
118 : EnergyParams* params,
119 : double& v, double& a, double& s) {
120 :
121 1171329 : if (myComputeA) {
122 : if (myLastV.count(id) == 0) {
123 0 : a = 0.;
124 : } else {
125 1171037 : a = v - myLastV[id];
126 : }
127 1171037 : myLastV[id] = v;
128 1171037 : if (myComputeAForward) {
129 0 : v -= a;
130 : }
131 : }
132 1171329 : if (myAccelZeroCorrection) {
133 0 : a = PollutantsInterface::getModifiedAccel(c, v, a, s, params);
134 : }
135 1171329 : if (a == INVALID_VALUE) {
136 0 : throw ProcessError(TL("Acceleration information is missing; try running with --compute-a."));
137 : }
138 1171329 : if (s == INVALID_VALUE) {
139 1171329 : s = myDefaultSlope;
140 : }
141 1171329 : const PollutantsInterface::Emissions result = PollutantsInterface::computeAll(c, v, a, s, params);
142 1171329 : mySums[id].addScaled(result, myStepSize);
143 1171329 : if (id != "") {
144 1164 : mySums[""].addScaled(result, myStepSize);
145 : }
146 1171329 : return result;
147 : }
148 :
149 :
150 : void
151 12878217 : TrajectoriesHandler::writeOptional(std::ostream& o, long long int attributes, const SumoXMLAttr attr, double v) {
152 12878217 : if ((attributes & ((long long int)1 << attr)) != 0) {
153 : o << ";" << v;
154 : }
155 12878217 : }
156 :
157 :
158 : bool
159 1171740 : TrajectoriesHandler::writeEmissions(std::ostream& o, const std::string id,
160 : const SUMOEmissionClass c,
161 : EnergyParams* params,
162 : long long int attributes,
163 : double t, double& v,
164 : double& a, double& s) {
165 1171740 : if (myComputeA && myLastV.count(id) == 0) {
166 993 : myLastV[id] = v;
167 993 : myLastSlope[id] = s;
168 993 : return false;
169 : }
170 1170747 : if (myComputeAForward) {
171 0 : t -= TS;
172 0 : const double nextS = s;
173 0 : s = myLastSlope[id];
174 0 : myLastSlope[id] = nextS;
175 : }
176 2341494 : const PollutantsInterface::Emissions e = computeEmissions(id, c, params, v, a, s);
177 : o << t;
178 1170747 : writeOptional(o, attributes, SUMO_ATTR_SPEED, v);
179 1170747 : writeOptional(o, attributes, SUMO_ATTR_ACCELERATION, a);
180 1170747 : writeOptional(o, attributes, SUMO_ATTR_SLOPE, s);
181 1170747 : writeOptional(o, attributes, SUMO_ATTR_CO_ABS, e.CO);
182 1170747 : writeOptional(o, attributes, SUMO_ATTR_CO2_ABS, e.CO2);
183 1170747 : writeOptional(o, attributes, SUMO_ATTR_HC_ABS, e.HC);
184 1170747 : writeOptional(o, attributes, SUMO_ATTR_PMX_ABS, e.PMx);
185 1170747 : writeOptional(o, attributes, SUMO_ATTR_NOX_ABS, e.NOx);
186 1170747 : writeOptional(o, attributes, SUMO_ATTR_FUEL_ABS, e.fuel);
187 1170747 : writeOptional(o, attributes, SUMO_ATTR_ELECTRICITY_ABS, e.electricity);
188 1170747 : writeOptional(o, attributes, SUMO_ATTR_AMOUNT, PollutantsInterface::getCoastingDecel(c, v, a, s, params));
189 : o << std::endl;
190 : return true;
191 : }
192 :
193 :
194 : bool
195 584 : TrajectoriesHandler::writeXMLEmissions(const std::string id,
196 : const SUMOEmissionClass c,
197 : EnergyParams* params,
198 : SUMOTime t, double& v,
199 : double a, double s) {
200 584 : if (myComputeA && myLastV.count(id) == 0) {
201 2 : myLastV[id] = v;
202 2 : return false;
203 : }
204 582 : if (myCurrentTime != t) {
205 299 : if (myCurrentTime != -1) {
206 594 : myXMLOut->closeTag();
207 : }
208 299 : myCurrentTime = t;
209 598 : myXMLOut->openTag(SUMO_TAG_TIMESTEP).writeAttr(SUMO_ATTR_TIME, time2string(t));
210 : }
211 582 : const PollutantsInterface::Emissions e = computeEmissions(id, c, params, v, a, s);
212 1746 : myXMLOut->openTag("vehicle").writeAttr("id", id).writeAttr("eclass", PollutantsInterface::getName(c));
213 2910 : myXMLOut->writeAttr("CO2", e.CO2).writeAttr("CO", e.CO).writeAttr("HC", e.HC).writeAttr("NOx", e.NOx);
214 2328 : myXMLOut->writeAttr("PMx", e.PMx).writeAttr("fuel", e.fuel).writeAttr("electricity", e.electricity);
215 1746 : myXMLOut->writeAttr("speed", v).closeTag();
216 582 : return true;
217 : }
218 :
219 :
220 : void
221 995 : TrajectoriesHandler::writeSums(std::ostream& o, const std::string id) {
222 995 : o << "CO:" << mySums[id].CO << std::endl
223 995 : << "CO2:" << mySums[id].CO2 << std::endl
224 995 : << "HC:" << mySums[id].HC << std::endl
225 995 : << "NOx:" << mySums[id].NOx << std::endl
226 995 : << "PMx:" << mySums[id].PMx << std::endl
227 995 : << "fuel:" << mySums[id].fuel << std::endl
228 995 : << "electricity:" << mySums[id].electricity << std::endl;
229 995 : }
230 :
231 :
232 : void
233 0 : TrajectoriesHandler::writeNormedSums(std::ostream& o, const std::string id, const double factor) {
234 0 : o << mySums[id].fuel / factor << ","
235 0 : << mySums[id].electricity / factor << ","
236 0 : << mySums[id].CO2 / factor << ","
237 0 : << mySums[id].NOx / factor << ","
238 0 : << mySums[id].CO / factor << ","
239 0 : << mySums[id].HC / factor << ","
240 0 : << mySums[id].PMx / factor << std::endl;
241 0 : }
242 :
243 :
244 : /****************************************************************************/
|