Line data Source code
1 : /****************************************************************************/
2 : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3 : // Copyright (C) 2001-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 EnergyParams.cpp
15 : /// @author Jakob Erdmann
16 : /// @date Sept 2021
17 : ///
18 : // A class for parameters used by the emission models
19 : /****************************************************************************/
20 : #include <config.h>
21 :
22 : #include <utils/common/MsgHandler.h>
23 : #include <utils/common/StringUtils.h>
24 : #include <utils/common/ToString.h>
25 : #include <utils/vehicle/SUMOVTypeParameter.h>
26 :
27 : #include "PollutantsInterface.h"
28 : #include "HelpersEnergy.h"
29 : #include "EnergyParams.h"
30 :
31 :
32 : // ===========================================================================
33 : // static definitions
34 : // ===========================================================================
35 : const EnergyParams* EnergyParams::myDefault = nullptr;
36 :
37 :
38 : // ===========================================================================
39 : // method definitions
40 : // ===========================================================================
41 317600 : EnergyParams::EnergyParams(const SUMOVTypeParameter* typeParams) :
42 317600 : EnergyParams(typeParams != nullptr ? typeParams->emissionClass : EMISSION_CLASS_UNSPECIFIED) {
43 317600 : if (typeParams != nullptr) {
44 9527286 : for (auto item : myMap) {
45 9209697 : myMap[item.first] = typeParams->getDouble(toString(item.first), item.second);
46 : }
47 317589 : for (auto item : myVecMap) {
48 0 : myVecMap[item.first] = typeParams->getDoubles(toString(item.first), item.second);
49 : }
50 635154 : for (auto item : myCharacteristicMapMap) {
51 635130 : std::string characteristicMapString = typeParams->getParameter(toString(item.first), "");
52 317565 : if (characteristicMapString != "") {
53 60 : myCharacteristicMapMap.at(item.first) = CharacteristicMap(typeParams->getParameter(toString(item.first)));
54 : }
55 : }
56 317589 : if (typeParams->wasSet(VTYPEPARS_MASS_SET)) {
57 243 : myMap[SUMO_ATTR_MASS] = typeParams->mass;
58 : }
59 317589 : myMap[SUMO_ATTR_LOADING] = typeParams->getDouble("loading", INVALID_DOUBLE);
60 317589 : myMap[SUMO_ATTR_WIDTH] = typeParams->width;
61 317589 : myMap[SUMO_ATTR_HEIGHT] = typeParams->height;
62 635178 : if (!StringUtils::startsWith(PollutantsInterface::getName(typeParams->emissionClass), "MMPEVEM")) {
63 635118 : if (typeParams->hasParameter(toString(SUMO_ATTR_INTERNALMOMENTOFINERTIA))) {
64 6 : WRITE_WARNINGF(TL("Vehicle type '%' uses the Energy model with parameter 'internalMomentOfInertia' which is deprecated. Use 'rotatingMass' instead."), typeParams->id);
65 4 : if (!typeParams->hasParameter(toString(SUMO_ATTR_ROTATINGMASS))) {
66 2 : myMap[SUMO_ATTR_ROTATINGMASS] = myMap[SUMO_ATTR_INTERNALMOMENTOFINERTIA];
67 : }
68 : }
69 : }
70 : }
71 317600 : }
72 :
73 :
74 319543 : EnergyParams::EnergyParams(const SUMOEmissionClass c) {
75 319543 : myMap[SUMO_ATTR_SHUT_OFF_STOP] = 300.;
76 319543 : myMap[SUMO_ATTR_SHUT_OFF_AUTO] = std::numeric_limits<double>::max();
77 319543 : myMap[SUMO_ATTR_DURATION] = -1.;
78 319543 : myMap[SUMO_ATTR_PARKING] = 0.;
79 319543 : myMap[SUMO_ATTR_WAITINGTIME] = -1.;
80 :
81 958607 : if (c != EMISSION_CLASS_UNSPECIFIED && StringUtils::startsWith(PollutantsInterface::getName(c), "PHEMlight5/")) {
82 34 : myMap[SUMO_ATTR_MASS] = INVALID_DOUBLE;
83 34 : myMap[SUMO_ATTR_LOADING] = INVALID_DOUBLE;
84 34 : myMap[SUMO_ATTR_FRONTSURFACEAREA] = INVALID_DOUBLE;
85 34 : myMap[SUMO_ATTR_AIRDRAGCOEFFICIENT] = INVALID_DOUBLE;
86 34 : myMap[SUMO_ATTR_CONSTANTPOWERINTAKE] = INVALID_DOUBLE;
87 34 : myMap[SUMO_ATTR_WHEELRADIUS] = INVALID_DOUBLE;
88 34 : myMap[SUMO_ATTR_ROLLDRAGCOEFFICIENT] = INVALID_DOUBLE;
89 34 : myMap[SUMO_ATTR_ROTATINGMASS] = INVALID_DOUBLE;
90 34 : return;
91 : }
92 319509 : const SUMOVTypeParameter::VClassDefaultValues defaultValues(SVC_PASSENGER);
93 319509 : myMap[SUMO_ATTR_MASS] = defaultValues.mass;
94 319509 : myMap[SUMO_ATTR_LOADING] = INVALID_DOUBLE;
95 319509 : myMap[SUMO_ATTR_WIDTH] = defaultValues.width;
96 319509 : myMap[SUMO_ATTR_HEIGHT] = defaultValues.height;
97 :
98 : // default values from
99 : // https://sumo.dlr.de/docs/Models/Electric.html#kia_soul_ev_2020
100 958505 : if (c != EMISSION_CLASS_UNSPECIFIED && StringUtils::startsWith(PollutantsInterface::getName(c), "Energy/")) {
101 124 : myMap[SUMO_ATTR_MASS] = 1830.;
102 : }
103 319509 : myMap[SUMO_ATTR_FRONTSURFACEAREA] = 2.6;
104 319509 : myMap[SUMO_ATTR_AIRDRAGCOEFFICIENT] = 0.35;
105 319509 : myMap[SUMO_ATTR_ROTATINGMASS] = 40.;
106 319509 : myMap[SUMO_ATTR_RADIALDRAGCOEFFICIENT] = 0.1;
107 319509 : myMap[SUMO_ATTR_ROLLDRAGCOEFFICIENT] = 0.01;
108 319509 : myMap[SUMO_ATTR_CONSTANTPOWERINTAKE] = 100.;
109 319509 : myMap[SUMO_ATTR_PROPULSIONEFFICIENCY] = 0.98;
110 319509 : myMap[SUMO_ATTR_RECUPERATIONEFFICIENCY] = 0.96;
111 319509 : myMap[SUMO_ATTR_RECUPERATIONEFFICIENCY_BY_DECELERATION] = 0.0;
112 319509 : myMap[SUMO_ATTR_ANGLE] = 0.; // actually angleDiff in the last step
113 : // @todo set myVecMap defaults as needed
114 :
115 : // Default values for the MMPEVEM, taken from the VW_ID3
116 319509 : myMap[SUMO_ATTR_WHEELRADIUS] = 0.3588; // [m]
117 319509 : myMap[SUMO_ATTR_MAXIMUMTORQUE] = 310.0; // [Nm]
118 : // @todo SUMO_ATTR_MAXIMUMPOWER predates the MMPEVEM emission model. Do you want to set this somewhere else or to another value?
119 319509 : myMap[SUMO_ATTR_MAXIMUMPOWER] = 107000.0; // [W]
120 319509 : myMap[SUMO_ATTR_GEAREFFICIENCY] = 0.96; // [1]
121 319509 : myMap[SUMO_ATTR_GEARRATIO] = 10.0; // [1]
122 319509 : myMap[SUMO_ATTR_MAXIMUMRECUPERATIONTORQUE] = 95.5; // [Nm]
123 319509 : myMap[SUMO_ATTR_MAXIMUMRECUPERATIONPOWER] = 42800.0; // [W]
124 319509 : myMap[SUMO_ATTR_INTERNALBATTERYRESISTANCE] = 0.1142; // [Ohm]
125 319509 : myMap[SUMO_ATTR_NOMINALBATTERYVOLTAGE] = 396.0; // [V]
126 319509 : myMap[SUMO_ATTR_INTERNALMOMENTOFINERTIA] = 12.5; // [kgm^2]
127 958527 : 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
128 : }
129 :
130 :
131 1163651 : EnergyParams::~EnergyParams() {}
132 :
133 :
134 : void
135 121828741 : EnergyParams::setDouble(SumoXMLAttr attr, double value) {
136 121828741 : myMap[attr] = value;
137 121828741 : }
138 :
139 :
140 : double
141 6163112099 : EnergyParams::getDouble(SumoXMLAttr attr) const {
142 : auto it = myMap.find(attr);
143 6163112099 : if (it != myMap.end()) {
144 3409569063 : return it->second;
145 : }
146 2753543036 : if (mySecondaryParams != nullptr) {
147 2753543036 : return mySecondaryParams->getDouble(attr);
148 : }
149 0 : throw UnknownElement("Unknown Energy Model parameter: " + toString(attr));
150 : }
151 :
152 :
153 : double
154 3930222 : EnergyParams::getDoubleOptional(SumoXMLAttr attr, const double def) const {
155 : auto it = myMap.find(attr);
156 3930222 : if (it != myMap.end() && it->second != INVALID_DOUBLE) {
157 : return it->second;
158 : }
159 3884302 : if (mySecondaryParams != nullptr) {
160 946916 : return mySecondaryParams->getDoubleOptional(attr, def);
161 : }
162 : return def;
163 : }
164 :
165 :
166 : const std::vector<double>&
167 0 : EnergyParams::getDoubles(SumoXMLAttr attr) const {
168 : auto it = myVecMap.find(attr);
169 0 : if (it != myVecMap.end()) {
170 0 : return it->second;
171 : }
172 0 : if (mySecondaryParams != nullptr) {
173 0 : return mySecondaryParams->getDoubles(attr);
174 : }
175 0 : throw UnknownElement("Unknown Energy Model parameter: " + toString(attr));
176 : }
177 :
178 :
179 : const CharacteristicMap&
180 10560 : EnergyParams::getCharacteristicMap(SumoXMLAttr attr) const {
181 : auto it = myCharacteristicMapMap.find(attr);
182 10560 : if (it != myCharacteristicMapMap.end()) {
183 5280 : return it->second;
184 : }
185 5280 : if (mySecondaryParams != nullptr) {
186 5280 : return mySecondaryParams->getCharacteristicMap(attr);
187 : }
188 0 : throw UnknownElement("Unknown Energy Model parameter: " + toString(attr));
189 : }
190 :
191 :
192 : void
193 0 : EnergyParams::checkParam(const SumoXMLAttr paramKey, const std::string& id, const double lower, const double upper) {
194 : const auto& p = myMap.find(paramKey);
195 0 : if (p != myMap.end() && (p->second < lower || p->second > upper)) {
196 0 : WRITE_WARNINGF(TL("Vehicle device '%' doesn't have a valid value for parameter % (%)."), id, toString(paramKey), p->second);
197 0 : setDouble(paramKey, EnergyParams::getDefault()->getDouble(paramKey));
198 : }
199 0 : }
200 :
201 :
202 : bool
203 604690361 : EnergyParams::isEngineOff() const {
204 : // they all got a default in the constructor so getDouble is safe here
205 1193450740 : return getDouble(SUMO_ATTR_DURATION) > getDouble(SUMO_ATTR_SHUT_OFF_STOP) ||
206 588760379 : getDouble(SUMO_ATTR_WAITINGTIME) > getDouble(SUMO_ATTR_SHUT_OFF_AUTO);
207 : }
208 :
209 :
210 : bool
211 0 : EnergyParams::isOff() const {
212 : // they all got a default in the constructor so getDouble is safe here
213 0 : return getDouble(SUMO_ATTR_DURATION) > getDouble(SUMO_ATTR_SHUT_OFF_STOP) && getDouble(SUMO_ATTR_PARKING) > 0.;
214 : }
215 :
216 :
217 : /****************************************************************************/
|