1 /****************************************************************************/
2 // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
3 // Copyright (C) 2001-2019 German Aerospace Center (DLR) and others.
4 // This program and the accompanying materials
5 // are made available under the terms of the Eclipse Public License v2.0
6 // which accompanies this distribution, and is available at
7 // http://www.eclipse.org/legal/epl-v20.html
8 // SPDX-License-Identifier: EPL-2.0
9 /****************************************************************************/
10 /// @file MSMeanData_Emissions.cpp
11 /// @author Daniel Krajzewicz
12 /// @author Michael Behrisch
13 /// @date Mon, 10.05.2004
14 /// @version $Id$
15 ///
16 // Emission data collector for edges/lanes that
17 /****************************************************************************/
18
19
20 // ===========================================================================
21 // included modules
22 // ===========================================================================
23 #include <config.h>
24
25 #include <microsim/MSNet.h>
26 #include <microsim/MSLane.h>
27 #include <microsim/MSVehicle.h>
28 #include <microsim/MSVehicleControl.h>
29 #include <utils/common/SUMOTime.h>
30 #include <utils/common/ToString.h>
31 #include <utils/iodevices/OutputDevice.h>
32 #include "MSMeanData_Emissions.h"
33 #include <utils/emissions/PollutantsInterface.h>
34 #include <limits>
35
36
37 // ===========================================================================
38 // method definitions
39 // ===========================================================================
40 // ---------------------------------------------------------------------------
41 // MSMeanData_Emissions::MSLaneMeanDataValues - methods
42 // ---------------------------------------------------------------------------
MSLaneMeanDataValues(MSLane * const lane,const double length,const bool doAdd,const MSMeanData_Emissions * parent)43 MSMeanData_Emissions::MSLaneMeanDataValues::MSLaneMeanDataValues(MSLane* const lane,
44 const double length, const bool doAdd,
45 const MSMeanData_Emissions* parent)
46 : MSMeanData::MeanDataValues(lane, length, doAdd, parent),
47 myEmissions() {}
48
49
~MSLaneMeanDataValues()50 MSMeanData_Emissions::MSLaneMeanDataValues::~MSLaneMeanDataValues() {
51 }
52
53
54 void
reset(bool)55 MSMeanData_Emissions::MSLaneMeanDataValues::reset(bool) {
56 sampleSeconds = 0.;
57 travelledDistance = 0.;
58 myEmissions = PollutantsInterface::Emissions();
59 }
60
61
62 void
addTo(MSMeanData::MeanDataValues & val) const63 MSMeanData_Emissions::MSLaneMeanDataValues::addTo(MSMeanData::MeanDataValues& val) const {
64 MSLaneMeanDataValues& v = (MSLaneMeanDataValues&) val;
65 v.sampleSeconds += sampleSeconds;
66 v.travelledDistance += travelledDistance;
67 v.myEmissions.addScaled(myEmissions);
68 }
69
70
71 void
notifyMoveInternal(const SUMOTrafficObject & veh,const double,const double timeOnLane,const double,const double meanSpeedVehicleOnLane,const double,const double travelledDistanceVehicleOnLane,const double)72 MSMeanData_Emissions::MSLaneMeanDataValues::notifyMoveInternal(const SUMOTrafficObject& veh, const double /* frontOnLane */, const double timeOnLane, const double /*meanSpeedFrontOnLane*/, const double meanSpeedVehicleOnLane, const double /*travelledDistanceFrontOnLane*/, const double travelledDistanceVehicleOnLane, const double /* meanLengthOnLane */) {
73 sampleSeconds += timeOnLane;
74 travelledDistance += travelledDistanceVehicleOnLane;
75 const double a = veh.getAcceleration();
76 myEmissions.addScaled(PollutantsInterface::computeAll(veh.getVehicleType().getEmissionClass(),
77 // XXX: recheck, which value to use here for the speed. (Leo) Refs. #2579
78 meanSpeedVehicleOnLane, a, veh.getSlope()), timeOnLane);
79 }
80
81
82 void
write(OutputDevice & dev,const SUMOTime period,const double,const double defaultTravelTime,const int) const83 MSMeanData_Emissions::MSLaneMeanDataValues::write(OutputDevice& dev, const SUMOTime period,
84 const double /*numLanes*/, const double defaultTravelTime, const int /*numVehicles*/) const {
85 const double normFactor = double(3600. / STEPS2TIME(period) / myLaneLength);
86 dev << " CO_abs=\"" << OutputDevice::realString(myEmissions.CO, 6) <<
87 "\" CO2_abs=\"" << OutputDevice::realString(myEmissions.CO2, 6) <<
88 "\" HC_abs=\"" << OutputDevice::realString(myEmissions.HC, 6) <<
89 "\" PMx_abs=\"" << OutputDevice::realString(myEmissions.PMx, 6) <<
90 "\" NOx_abs=\"" << OutputDevice::realString(myEmissions.NOx, 6) <<
91 "\" fuel_abs=\"" << OutputDevice::realString(myEmissions.fuel, 6) <<
92 "\" electricity_abs=\"" << OutputDevice::realString(myEmissions.electricity, 6) <<
93 "\"\n CO_normed=\"" << OutputDevice::realString(normFactor * myEmissions.CO, 6) <<
94 "\" CO2_normed=\"" << OutputDevice::realString(normFactor * myEmissions.CO2, 6) <<
95 "\" HC_normed=\"" << OutputDevice::realString(normFactor * myEmissions.HC, 6) <<
96 "\" PMx_normed=\"" << OutputDevice::realString(normFactor * myEmissions.PMx, 6) <<
97 "\" NOx_normed=\"" << OutputDevice::realString(normFactor * myEmissions.NOx, 6) <<
98 "\" fuel_normed=\"" << OutputDevice::realString(normFactor * myEmissions.fuel, 6) <<
99 "\" electricity_normed=\"" << OutputDevice::realString(normFactor * myEmissions.electricity, 6);
100 if (sampleSeconds > myParent->getMinSamples()) {
101 double vehFactor = myParent->getMaxTravelTime() / sampleSeconds;
102 double traveltime = myParent->getMaxTravelTime();
103 if (travelledDistance > 0.f) {
104 vehFactor = MIN2(vehFactor, myLaneLength / travelledDistance);
105 traveltime = MIN2(traveltime, myLaneLength * sampleSeconds / travelledDistance);
106 }
107 dev << "\"\n traveltime=\"" << OutputDevice::realString(traveltime) <<
108 "\" CO_perVeh=\"" << OutputDevice::realString(myEmissions.CO * vehFactor, 6) <<
109 "\" CO2_perVeh=\"" << OutputDevice::realString(myEmissions.CO2 * vehFactor, 6) <<
110 "\" HC_perVeh=\"" << OutputDevice::realString(myEmissions.HC * vehFactor, 6) <<
111 "\" PMx_perVeh=\"" << OutputDevice::realString(myEmissions.PMx * vehFactor, 6) <<
112 "\" NOx_perVeh=\"" << OutputDevice::realString(myEmissions.NOx * vehFactor, 6) <<
113 "\" fuel_perVeh=\"" << OutputDevice::realString(myEmissions.fuel * vehFactor, 6) <<
114 "\" electricity_perVeh=\"" << OutputDevice::realString(myEmissions.electricity * vehFactor, 6);
115 } else if (defaultTravelTime >= 0.) {
116 const MSVehicleType* t = MSNet::getInstance()->getVehicleControl().getVType();
117 const double speed = MIN2(myLaneLength / defaultTravelTime, t->getMaxSpeed());
118 dev << "\"\n traveltime=\"" << OutputDevice::realString(defaultTravelTime) <<
119 "\" CO_perVeh=\"" << OutputDevice::realString(PollutantsInterface::computeDefault(t->getEmissionClass(), PollutantsInterface::CO, speed, t->getCarFollowModel().getMaxAccel(), 0, defaultTravelTime), 6) << // @todo: give correct slope
120 "\" CO2_perVeh=\"" << OutputDevice::realString(PollutantsInterface::computeDefault(t->getEmissionClass(), PollutantsInterface::CO2, speed, t->getCarFollowModel().getMaxAccel(), 0, defaultTravelTime), 6) << // @todo: give correct slope
121 "\" HC_perVeh=\"" << OutputDevice::realString(PollutantsInterface::computeDefault(t->getEmissionClass(), PollutantsInterface::HC, speed, t->getCarFollowModel().getMaxAccel(), 0, defaultTravelTime), 6) << // @todo: give correct slope
122 "\" PMx_perVeh=\"" << OutputDevice::realString(PollutantsInterface::computeDefault(t->getEmissionClass(), PollutantsInterface::PM_X, speed, t->getCarFollowModel().getMaxAccel(), 0, defaultTravelTime), 6) << // @todo: give correct slope
123 "\" NOx_perVeh=\"" << OutputDevice::realString(PollutantsInterface::computeDefault(t->getEmissionClass(), PollutantsInterface::NO_X, speed, t->getCarFollowModel().getMaxAccel(), 0, defaultTravelTime), 6) << // @todo: give correct slope
124 "\" fuel_perVeh=\"" << OutputDevice::realString(PollutantsInterface::computeDefault(t->getEmissionClass(), PollutantsInterface::FUEL, speed, t->getCarFollowModel().getMaxAccel(), 0, defaultTravelTime), 6) << // @todo: give correct slope
125 "\" electricity_perVeh=\"" << OutputDevice::realString(PollutantsInterface::computeDefault(t->getEmissionClass(), PollutantsInterface::ELEC, speed, t->getCarFollowModel().getMaxAccel(), 0, defaultTravelTime), 6); // @todo: give correct slope
126 }
127 dev << "\"";
128 dev.closeTag();
129 }
130
131
132
133 // ---------------------------------------------------------------------------
134 // MSMeanData_Emissions - methods
135 // ---------------------------------------------------------------------------
MSMeanData_Emissions(const std::string & id,const SUMOTime dumpBegin,const SUMOTime dumpEnd,const bool useLanes,const bool withEmpty,const bool printDefaults,const bool withInternal,const bool trackVehicles,const double maxTravelTime,const double minSamples,const std::string & vTypes)136 MSMeanData_Emissions::MSMeanData_Emissions(const std::string& id,
137 const SUMOTime dumpBegin,
138 const SUMOTime dumpEnd,
139 const bool useLanes, const bool withEmpty,
140 const bool printDefaults,
141 const bool withInternal,
142 const bool trackVehicles,
143 const double maxTravelTime,
144 const double minSamples,
145 const std::string& vTypes)
146 : MSMeanData(id, dumpBegin, dumpEnd, useLanes, withEmpty, printDefaults,
147 withInternal, trackVehicles, 0, maxTravelTime, minSamples, vTypes) {
148 }
149
150
~MSMeanData_Emissions()151 MSMeanData_Emissions::~MSMeanData_Emissions() {}
152
153
154 MSMeanData::MeanDataValues*
createValues(MSLane * const lane,const double length,const bool doAdd) const155 MSMeanData_Emissions::createValues(MSLane* const lane, const double length, const bool doAdd) const {
156 return new MSLaneMeanDataValues(lane, length, doAdd, this);
157 }
158
159
160 /****************************************************************************/
161