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