Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
eclipse
GitHub Repository: eclipse/sumo
Path: blob/main/src/tools/TrajectoriesHandler.cpp
169665 views
1
/****************************************************************************/
2
// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3
// Copyright (C) 2014-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 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
TrajectoriesHandler::TrajectoriesHandler(const bool computeA, const bool computeAForward,
41
const bool accelZeroCorrection, const SUMOEmissionClass defaultClass, EnergyParams* params,
42
long long int attributes, const double defaultSlope, std::ostream* stdOut, OutputDevice* xmlOut) :
43
SUMOSAXHandler(""),
44
myComputeA(computeA),
45
myComputeAForward(computeAForward),
46
myAccelZeroCorrection(accelZeroCorrection),
47
myDefaultClass(defaultClass),
48
myParams(params), myAttributes(attributes),
49
myDefaultSlope(defaultSlope), myStdOut(stdOut), myXMLOut(xmlOut), myCurrentTime(-1), myStepSize(TS) {}
50
51
52
TrajectoriesHandler::~TrajectoriesHandler() {}
53
54
55
void
56
TrajectoriesHandler::myStartElement(int element,
57
const SUMOSAXAttributes& attrs) {
58
bool ok = true;
59
switch (element) {
60
case SUMO_TAG_TRAJECTORIES:
61
myStepSize = attrs.getFloat("timeStepSize") / 1000.;
62
break;
63
case SUMO_TAG_TIMESTEP:
64
myCurrentTime = attrs.getSUMOTimeReporting(SUMO_ATTR_TIME, nullptr, ok);
65
break;
66
case SUMO_TAG_VEHICLE:
67
if (attrs.hasAttribute(SUMO_ATTR_SPEED)) {
68
double v = attrs.getFloat(SUMO_ATTR_SPEED);
69
double a = INVALID_VALUE;
70
double s = INVALID_VALUE;
71
writeEmissions(std::cout, attrs.getString(SUMO_ATTR_ID), myDefaultClass, myParams, myAttributes, STEPS2TIME(myCurrentTime), v, a, s);
72
} else {
73
const std::string acId = attrs.getString(SUMO_ATTR_ACTORCONFIG);
74
const std::string id = attrs.getString(SUMO_ATTR_ID);
75
if (myEmissionClassByType.count(acId) == 0) {
76
WRITE_WARNINGF(TL("Unknown actor configuration '%' for vehicle '%'!"), acId, id);
77
} else {
78
myEmissionClassByVehicle[id] = myEmissionClassByType.count(acId) > 0 ? myEmissionClassByType[acId] : myDefaultClass;
79
}
80
}
81
break;
82
case SUMO_TAG_ACTORCONFIG: {
83
const std::string id = attrs.getString(SUMO_ATTR_ID);
84
const std::string vClass = attrs.getString(SUMO_ATTR_VEHICLECLASS);
85
const std::string fuel = attrs.getString(SUMO_ATTR_FUEL);
86
const std::string eClass = attrs.getString(SUMO_ATTR_EMISSIONCLASS);
87
const double weight = attrs.getOpt<double>(SUMO_ATTR_WEIGHT, id.c_str(), ok, 0.) * 10.;
88
myEmissionClassByType[id] = PollutantsInterface::getClass(myDefaultClass, vClass, fuel, eClass, weight);
89
break;
90
}
91
case SUMO_TAG_MOTIONSTATE: {
92
const std::string id = attrs.getString(SUMO_ATTR_VEHICLE);
93
if (myEmissionClassByVehicle.count(id) == 0) {
94
WRITE_WARNINGF(TL("Motion state for unknown vehicle '%'!"), id);
95
myEmissionClassByVehicle[id] = myDefaultClass;
96
}
97
const SUMOEmissionClass c = myEmissionClassByVehicle[id];
98
double v = attrs.getFloat(SUMO_ATTR_SPEED) / 100.;
99
double a = attrs.hasAttribute(SUMO_ATTR_ACCELERATION) ? attrs.get<double>(SUMO_ATTR_ACCELERATION, id.c_str(), ok) / 1000. : INVALID_VALUE;
100
double s = attrs.hasAttribute(SUMO_ATTR_SLOPE) ? RAD2DEG(asin(attrs.get<double>(SUMO_ATTR_SLOPE, id.c_str(), ok) / 10000.)) : INVALID_VALUE;
101
const SUMOTime time = attrs.getOpt<int>(SUMO_ATTR_TIME, id.c_str(), ok, INVALID_VALUE);
102
if (myXMLOut != nullptr) {
103
writeXMLEmissions(id, c, nullptr, time, v, a, s);
104
}
105
if (myStdOut != nullptr) {
106
writeEmissions(*myStdOut, id, c, nullptr, myAttributes, STEPS2TIME(time), v, a, s);
107
}
108
break;
109
}
110
default:
111
break;
112
}
113
}
114
115
116
const PollutantsInterface::Emissions
117
TrajectoriesHandler::computeEmissions(const std::string id, const SUMOEmissionClass c,
118
EnergyParams* params,
119
double& v, double& a, double& s) {
120
121
if (myComputeA) {
122
if (myLastV.count(id) == 0) {
123
a = 0.;
124
} else {
125
a = v - myLastV[id];
126
}
127
myLastV[id] = v;
128
if (myComputeAForward) {
129
v -= a;
130
}
131
}
132
if (myAccelZeroCorrection) {
133
a = PollutantsInterface::getModifiedAccel(c, v, a, s, params);
134
}
135
if (a == INVALID_VALUE) {
136
throw ProcessError(TL("Acceleration information is missing; try running with --compute-a."));
137
}
138
if (s == INVALID_VALUE) {
139
s = myDefaultSlope;
140
}
141
const PollutantsInterface::Emissions result = PollutantsInterface::computeAll(c, v, a, s, params);
142
mySums[id].addScaled(result, myStepSize);
143
if (id != "") {
144
mySums[""].addScaled(result, myStepSize);
145
}
146
return result;
147
}
148
149
150
void
151
TrajectoriesHandler::writeOptional(std::ostream& o, long long int attributes, const SumoXMLAttr attr, double v) {
152
if ((attributes & ((long long int)1 << attr)) != 0) {
153
o << ";" << v;
154
}
155
}
156
157
158
bool
159
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
if (myComputeA && myLastV.count(id) == 0) {
166
myLastV[id] = v;
167
myLastSlope[id] = s;
168
return false;
169
}
170
if (myComputeAForward) {
171
t -= TS;
172
const double nextS = s;
173
s = myLastSlope[id];
174
myLastSlope[id] = nextS;
175
}
176
const PollutantsInterface::Emissions e = computeEmissions(id, c, params, v, a, s);
177
o << t;
178
writeOptional(o, attributes, SUMO_ATTR_SPEED, v);
179
writeOptional(o, attributes, SUMO_ATTR_ACCELERATION, a);
180
writeOptional(o, attributes, SUMO_ATTR_SLOPE, s);
181
writeOptional(o, attributes, SUMO_ATTR_CO_ABS, e.CO);
182
writeOptional(o, attributes, SUMO_ATTR_CO2_ABS, e.CO2);
183
writeOptional(o, attributes, SUMO_ATTR_HC_ABS, e.HC);
184
writeOptional(o, attributes, SUMO_ATTR_PMX_ABS, e.PMx);
185
writeOptional(o, attributes, SUMO_ATTR_NOX_ABS, e.NOx);
186
writeOptional(o, attributes, SUMO_ATTR_FUEL_ABS, e.fuel);
187
writeOptional(o, attributes, SUMO_ATTR_ELECTRICITY_ABS, e.electricity);
188
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
TrajectoriesHandler::writeXMLEmissions(const std::string id,
196
const SUMOEmissionClass c,
197
EnergyParams* params,
198
SUMOTime t, double& v,
199
double a, double s) {
200
if (myComputeA && myLastV.count(id) == 0) {
201
myLastV[id] = v;
202
return false;
203
}
204
if (myCurrentTime != t) {
205
if (myCurrentTime != -1) {
206
myXMLOut->closeTag();
207
}
208
myCurrentTime = t;
209
myXMLOut->openTag(SUMO_TAG_TIMESTEP).writeAttr(SUMO_ATTR_TIME, time2string(t));
210
}
211
const PollutantsInterface::Emissions e = computeEmissions(id, c, params, v, a, s);
212
myXMLOut->openTag("vehicle").writeAttr("id", id).writeAttr("eclass", PollutantsInterface::getName(c));
213
myXMLOut->writeAttr("CO2", e.CO2).writeAttr("CO", e.CO).writeAttr("HC", e.HC).writeAttr("NOx", e.NOx);
214
myXMLOut->writeAttr("PMx", e.PMx).writeAttr("fuel", e.fuel).writeAttr("electricity", e.electricity);
215
myXMLOut->writeAttr("speed", v).closeTag();
216
return true;
217
}
218
219
220
void
221
TrajectoriesHandler::writeSums(std::ostream& o, const std::string id) {
222
o << "CO:" << mySums[id].CO << std::endl
223
<< "CO2:" << mySums[id].CO2 << std::endl
224
<< "HC:" << mySums[id].HC << std::endl
225
<< "NOx:" << mySums[id].NOx << std::endl
226
<< "PMx:" << mySums[id].PMx << std::endl
227
<< "fuel:" << mySums[id].fuel << std::endl
228
<< "electricity:" << mySums[id].electricity << std::endl;
229
}
230
231
232
void
233
TrajectoriesHandler::writeNormedSums(std::ostream& o, const std::string id, const double factor) {
234
o << mySums[id].fuel / factor << ","
235
<< mySums[id].electricity / factor << ","
236
<< mySums[id].CO2 / factor << ","
237
<< mySums[id].NOx / factor << ","
238
<< mySums[id].CO / factor << ","
239
<< mySums[id].HC / factor << ","
240
<< mySums[id].PMx / factor << std::endl;
241
}
242
243
244
/****************************************************************************/
245
246