Line data Source code
1 : /****************************************************************************/
2 : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3 : // Copyright (C) 2001-2026 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 EnergyParams.cpp
15 : /// @author Jakob Erdmann
16 : /// @author Michael Behrisch
17 : /// @date Sept 2021
18 : ///
19 : // A class for parameters used by the emission models
20 : /****************************************************************************/
21 : #include <config.h>
22 :
23 : #include <utils/common/MsgHandler.h>
24 : #include <utils/common/StringUtils.h>
25 : #include <utils/common/ToString.h>
26 : #include <utils/geom/GeomHelper.h>
27 : #include <utils/vehicle/SUMOVTypeParameter.h>
28 :
29 : #include "PollutantsInterface.h"
30 : #include "HelpersEnergy.h"
31 : #include "EnergyParams.h"
32 :
33 :
34 : // ===========================================================================
35 : // static definitions
36 : // ===========================================================================
37 : const EnergyParams* EnergyParams::myDefault = nullptr;
38 : const std::vector<SumoXMLAttr> EnergyParams::myParamAttrs = {
39 : SUMO_ATTR_SHUT_OFF_STOP, SUMO_ATTR_SHUT_OFF_AUTO,
40 : SUMO_ATTR_LOADING, SUMO_ATTR_FRONTSURFACEAREA, SUMO_ATTR_AIRDRAGCOEFFICIENT,
41 : SUMO_ATTR_CONSTANTPOWERINTAKE, SUMO_ATTR_WHEELRADIUS, SUMO_ATTR_ROLLDRAGCOEFFICIENT, SUMO_ATTR_ROTATINGMASS,
42 : SUMO_ATTR_RADIALDRAGCOEFFICIENT, SUMO_ATTR_PROPULSIONEFFICIENCY, SUMO_ATTR_RECUPERATIONEFFICIENCY,
43 : SUMO_ATTR_RECUPERATIONEFFICIENCY_BY_DECELERATION,
44 : SUMO_ATTR_MAXIMUMTORQUE, SUMO_ATTR_MAXIMUMPOWER, SUMO_ATTR_GEAREFFICIENCY, SUMO_ATTR_GEARRATIO,
45 : SUMO_ATTR_MAXIMUMRECUPERATIONTORQUE, SUMO_ATTR_MAXIMUMRECUPERATIONPOWER,
46 : SUMO_ATTR_INTERNALBATTERYRESISTANCE, SUMO_ATTR_NOMINALBATTERYVOLTAGE, SUMO_ATTR_INTERNALMOMENTOFINERTIA
47 : };
48 :
49 :
50 : // ===========================================================================
51 : // method definitions
52 : // ===========================================================================
53 316474 : EnergyParams::EnergyParams(const SUMOVTypeParameter* typeParams) {
54 632948 : myCharacteristicMapMap.insert(std::pair<SumoXMLAttr, CharacteristicMap>(SUMO_ATTR_POWERLOSSMAP, CharacteristicMap("2,1|-1e9,1e9;-1e9,1e9|0,0,0,0"))); // P_loss_EM = 0 W for all operating points in the default EV power loss map
55 :
56 316474 : if (typeParams == nullptr) {
57 1957 : myMap[SUMO_ATTR_MASS] = DEFAULT_VEH_MASS;
58 1957 : myHaveDefaultMass = true;
59 1957 : myMap[SUMO_ATTR_FRONTSURFACEAREA] = DEFAULT_VEH_WIDTH * DEFAULT_VEH_HEIGHT * M_PI / 4.;
60 1957 : myHaveDefaultFrontSurfaceArea = true;
61 : } else {
62 7233891 : for (SumoXMLAttr attr : myParamAttrs) {
63 13838748 : if (typeParams->hasParameter(toString(attr))) {
64 2476 : myMap[attr] = typeParams->getDouble(toString(attr), INVALID_DOUBLE);
65 : }
66 : }
67 629034 : for (auto item : myCharacteristicMapMap) {
68 629034 : std::string characteristicMapString = typeParams->getParameter(toString(item.first), "");
69 314517 : if (characteristicMapString != "") {
70 60 : myCharacteristicMapMap.at(item.first) = CharacteristicMap(typeParams->getParameter(toString(item.first)));
71 : }
72 : }
73 314517 : myMap[SUMO_ATTR_MASS] = typeParams->mass;
74 314517 : myHaveDefaultMass = !typeParams->wasSet(VTYPEPARS_MASS_SET);
75 314517 : if (myHaveDefaultMass) {
76 314168 : const double ecMass = PollutantsInterface::getWeight(typeParams->emissionClass);
77 314168 : if (ecMass != -1.) {
78 144 : myMap[SUMO_ATTR_MASS] = ecMass;
79 : }
80 : }
81 : if (myMap.count(SUMO_ATTR_FRONTSURFACEAREA) == 0) {
82 314244 : myHaveDefaultFrontSurfaceArea = true;
83 314244 : myMap[SUMO_ATTR_FRONTSURFACEAREA] = typeParams->width * typeParams->height * M_PI / 4.;
84 : }
85 314517 : const std::string& ecName = PollutantsInterface::getName(typeParams->emissionClass);
86 314517 : if (typeParams->vehicleClass != SVC_IGNORING && (typeParams->vehicleClass & (SVC_PRIVATE | SVC_VIP | SVC_PASSENGER | SVC_HOV | SVC_TAXI | SVC_E_VEHICLE | SVC_CUSTOM1 | SVC_CUSTOM2)) == 0 && myHaveDefaultFrontSurfaceArea) {
87 401638 : if (StringUtils::startsWith(ecName, "MMPEVEM") || StringUtils::startsWith(ecName, "Energy")) {
88 51 : WRITE_WARNINGF(TL("Vehicle type '%' uses the emission class '%' which does not have proper defaults for its vehicle class. "
89 : "Please use a different emission model or complete the vType definition with further parameters."), typeParams->id, ecName);
90 17 : if (!typeParams->wasSet(VTYPEPARS_MASS_SET)) {
91 10 : WRITE_WARNING(TL(" And also set a vehicle mass!"));
92 : }
93 : }
94 : }
95 629034 : if (!StringUtils::startsWith(ecName, "MMPEVEM")) {
96 : if (myMap.count(SUMO_ATTR_INTERNALMOMENTOFINERTIA) > 0) {
97 6 : WRITE_WARNINGF(TL("Vehicle type '%' uses the Energy model parameter 'internalMomentOfInertia' which is deprecated. Use 'rotatingMass' instead."), typeParams->id);
98 4 : if (!typeParams->hasParameter(toString(SUMO_ATTR_ROTATINGMASS))) {
99 2 : myMap[SUMO_ATTR_ROTATINGMASS] = myMap[SUMO_ATTR_INTERNALMOMENTOFINERTIA];
100 : }
101 : }
102 : }
103 : }
104 316474 : }
105 :
106 :
107 1381453 : EnergyParams::~EnergyParams() {}
108 :
109 :
110 : void
111 139397822 : EnergyParams::setDynamicValues(const SUMOTime stopDuration, const bool parking, const SUMOTime waitingTime, const double angle) {
112 139397822 : if ((stopDuration >= 0 && myStopDurationSeconds < 0.) || (stopDuration < 0 && myStopDurationSeconds >= 0.)) {
113 16192 : myStopDurationSeconds = STEPS2TIME(stopDuration);
114 16192 : myAmParking = parking;
115 : }
116 139397822 : myWaitingTimeSeconds = STEPS2TIME(waitingTime);
117 139397822 : myLastAngle = myAngle;
118 139397822 : myAngle = angle;
119 139397822 : }
120 :
121 :
122 : void
123 505 : EnergyParams::setMass(const double mass) {
124 505 : myMap[SUMO_ATTR_MASS] = mass;
125 505 : myHaveDefaultMass = false;
126 505 : }
127 :
128 :
129 : void
130 1076362 : EnergyParams::setTransportableMass(const double mass) {
131 1076362 : myTransportableMass = mass;
132 : assert(myTransportableMass >= 0);
133 1076362 : }
134 :
135 :
136 : double
137 647316 : EnergyParams::getTotalMass(const double defaultEmptyMass, const double defaultLoading) const {
138 647316 : return getDoubleOptional(SUMO_ATTR_MASS, defaultEmptyMass) + getDoubleOptional(SUMO_ATTR_LOADING, defaultLoading) + getTransportableMass();
139 : }
140 :
141 :
142 : double
143 641916 : EnergyParams::getAngleDiff() const {
144 641916 : return myLastAngle == INVALID_DOUBLE ? 0. : GeomHelper::angleDiff(myLastAngle, myAngle);
145 : }
146 :
147 :
148 : double
149 1515147418 : EnergyParams::getDouble(SumoXMLAttr attr) const {
150 : auto it = myMap.find(attr);
151 1515147418 : if (it != myMap.end()) {
152 767476452 : return it->second;
153 : }
154 747670966 : if (mySecondaryParams != nullptr) {
155 747670966 : return mySecondaryParams->getDouble(attr);
156 : }
157 0 : throw UnknownElement("Unknown emission model parameter: " + toString(attr));
158 : }
159 :
160 :
161 : double
162 2916423617 : EnergyParams::getDoubleOptional(SumoXMLAttr attr, const double def) const {
163 : auto it = myMap.find(attr);
164 2916423617 : if (it != myMap.end() && it->second != INVALID_DOUBLE) {
165 2536834 : if (attr == SUMO_ATTR_MASS) {
166 997152 : if (!myHaveDefaultMass) {
167 : return it->second;
168 : }
169 1539682 : } else if (attr == SUMO_ATTR_FRONTSURFACEAREA) {
170 936697 : if (!myHaveDefaultFrontSurfaceArea) {
171 : return it->second;
172 : }
173 : } else {
174 : return it->second;
175 : }
176 : }
177 2915612750 : if (mySecondaryParams != nullptr) {
178 1448829043 : return mySecondaryParams->getDoubleOptional(attr, def);
179 : }
180 : return def;
181 : }
182 :
183 :
184 : const CharacteristicMap&
185 10660 : EnergyParams::getCharacteristicMap(SumoXMLAttr attr) const {
186 : auto it = myCharacteristicMapMap.find(attr);
187 10660 : if (it != myCharacteristicMapMap.end()) {
188 5330 : return it->second;
189 : }
190 5330 : if (mySecondaryParams != nullptr) {
191 5330 : return mySecondaryParams->getCharacteristicMap(attr);
192 : }
193 0 : throw UnknownElement("Unknown emission model parameter: " + toString(attr));
194 : }
195 :
196 :
197 : bool
198 738857998 : EnergyParams::isEngineOff() const {
199 1459258001 : return myStopDurationSeconds > getDoubleOptional(SUMO_ATTR_SHUT_OFF_STOP, DEFAULT_VEH_SHUT_OFF_STOP) ||
200 720400003 : myWaitingTimeSeconds > getDoubleOptional(SUMO_ATTR_SHUT_OFF_AUTO, std::numeric_limits<double>::max());
201 : }
202 :
203 :
204 : bool
205 742330 : EnergyParams::isOff() const {
206 742330 : return myStopDurationSeconds > getDoubleOptional(SUMO_ATTR_SHUT_OFF_STOP, DEFAULT_VEH_SHUT_OFF_STOP);
207 : }
208 :
209 :
210 : /****************************************************************************/
|