Eclipse SUMO - Simulation of Urban MObility
MSCFModel_Rail.cpp
Go to the documentation of this file.
1 /****************************************************************************/
2 // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3 // Copyright (C) 2012-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 /****************************************************************************/
19 // <description missing>
20 /****************************************************************************/
21 #include <config.h>
22 
23 #include <iostream>
27 #include <utils/geom/GeomHelper.h>
28 #include <microsim/MSVehicle.h>
30 #include "MSCFModel_Rail.h"
31 
32 // ===========================================================================
33 // trainParams method definitions
34 // ===========================================================================
35 
36 double
39  return (resCoef_quadratic * speed * speed + resCoef_linear * speed + resCoef_constant); // kN
40  } else {
41  return getInterpolatedValueFromLookUpMap(speed, &resistance); // kN
42  }
43 }
44 
45 
46 double
48  if (maxPower != INVALID_DOUBLE) {
49  return MIN2(maxPower / speed, maxTraction); // kN
50  } else {
51  return getInterpolatedValueFromLookUpMap(speed, &traction); // kN
52  }
53 }
54 
55 // ===========================================================================
56 // method definitions
57 // ===========================================================================
58 
59 
61  MSCFModel(vtype) {
62  const std::string trainType = vtype->getParameter().getCFParamString(SUMO_ATTR_TRAIN_TYPE, "NGT400");
63  if (trainType.compare("RB425") == 0) {
65  } else if (trainType.compare("RB628") == 0) {
67  } else if (trainType.compare("NGT400") == 0) {
69  } else if (trainType.compare("NGT400_16") == 0) {
71  } else if (trainType.compare("ICE1") == 0) {
73  } else if (trainType.compare("REDosto7") == 0) {
75  } else if (trainType.compare("Freight") == 0) {
77  } else if (trainType.compare("ICE3") == 0) {
79  } else if (trainType.compare("MireoPlusB") == 0) {
81  } else if (trainType.compare("MireoPlusH") == 0) {
83  } else if (trainType.compare("custom") == 0) {
85  } else {
86  WRITE_ERRORF(TL("Unknown train type: %. Exiting!"), trainType);
87  throw ProcessError();
88  }
89  // override with user values
90  if (vtype->wasSet(VTYPEPARS_MAXSPEED_SET)) {
91  myTrainParams.vmax = vtype->getMaxSpeed();
92  }
93  if (vtype->wasSet(VTYPEPARS_LENGTH_SET)) {
94  myTrainParams.length = vtype->getLength();
95  }
96  if (vtype->wasSet(VTYPEPARS_MASS_SET)) {
97  // kg to tons
98  myTrainParams.weight = vtype->getMass() / 1000;
99  }
104  // update type parameters so they are shown correctly in the gui (if defaults from trainType are used)
105  const_cast<MSVehicleType*>(vtype)->setMaxSpeed(myTrainParams.vmax);
106  const_cast<MSVehicleType*>(vtype)->setLength(myTrainParams.length);
107 
108  // init tabular curves
109  std::vector<double> speedTable = getValueTable(vtype, SUMO_ATTR_SPEED_TABLE);
110  std::vector<double> tractionTable = getValueTable(vtype, SUMO_ATTR_TRACTION_TABLE);
111  std::vector<double> resistanceTable = getValueTable(vtype, SUMO_ATTR_RESISTANCE_TABLE);
112  if (speedTable.size() > 0 || tractionTable.size() > 0 || resistanceTable.size() > 0) {
113  if (speedTable.size() == 1) {
114  throw ProcessError(TLF("Invalid size of speedTable for vType '%' (at least 2 values are required).", vtype->getID()));
115  } else if (speedTable.size() != tractionTable.size()) {
116  throw ProcessError(TLF("Mismatching size of speedTable and tractionTable for vType '%'.", vtype->getID()));
117  } else if (speedTable.size() != resistanceTable.size()) {
118  throw ProcessError(TLF("Mismatching size of speedTable and resistanceTable for vType '%'.", vtype->getID()));
119  }
120  myTrainParams.traction.clear();
121  myTrainParams.resistance.clear();
122  for (int i = 0; i < (int)speedTable.size(); i++) {
123  myTrainParams.traction[speedTable[i]] = tractionTable[i];
124  myTrainParams.resistance[speedTable[i]] = resistanceTable[i];
125  }
126  }
127 
128  // init parametric curves
134 
136  throw ProcessError(TLF("Undefined maxPower for vType '%'.", vtype->getID()));
138  throw ProcessError(TLF("Undefined maxTraction for vType '%'.", vtype->getID()));
139  }
140  if (myTrainParams.maxPower != INVALID_DOUBLE && tractionTable.size() > 0) {
141  WRITE_WARNING(TLF("Ignoring tractionTable because maxPower and maxTraction are set for vType '%'.", vtype->getID()));
142  }
143  const bool hasSomeResCoef = (myTrainParams.resCoef_constant != INVALID_DOUBLE
146  const bool hasAllResCoef = (myTrainParams.resCoef_constant != INVALID_DOUBLE
149  if (hasSomeResCoef && !hasAllResCoef) {
150  throw ProcessError(TLF("Some undefined resistance coefficients for vType '%' (requires resCoef_constant, resCoef_linear and resCoef_quadratic)", vtype->getID()));
151  }
152  if (myTrainParams.resCoef_constant != INVALID_DOUBLE && resistanceTable.size() > 0) {
153  WRITE_WARNING(TLF("Ignoring resistanceTable because resistance coefficents are set for vType '%'.", vtype->getID()));
154  }
155 
157  throw ProcessError(TLF("Either tractionTable or maxPower must be defined for vType '%' with Rail model type '%'.", vtype->getID(), trainType));
158  }
160  throw ProcessError(TLF("Either resistanceTable or resCoef_constant must be defined for vType '%' with Rail model type '%'.", vtype->getID(), trainType));
161  }
162 }
163 
164 
166 
167 
168 std::vector<double>
170  std::vector<double> result;
171  const std::string values = vtype->getParameter().getCFParamString(attr, "");
172  if (!values.empty()) {
173  for (std::string value : StringTokenizer(values).getVector()) {
174  result.push_back(StringUtils::toDouble(value));
175  }
176  }
177  return result;
178 }
179 
180 
181 double MSCFModel_Rail::followSpeed(const MSVehicle* const veh, double speed, double gap,
182  double /* predSpeed */, double /* predMaxDecel*/, const MSVehicle* const /*pred*/, const CalcReason /*usage*/) const {
183 
184  // followSpeed module is used for the simulation of moving block operations. The safety gap is chosen similar to the existing german
185  // system CIR-ELKE (based on LZB). Other implementations of moving block systems may differ, but for now no appropriate parameter
186  // can be set (would be per lane, not per train) -> hard-coded
187 
188  // @note: default train minGap of 5 is already subtracted from gap
189  if (speed >= 30 / 3.6) {
190  // safety distance for higher speeds (>= 30 km/h)
191  gap = MAX2(0.0, gap + veh->getVehicleType().getMinGap() - 50);
192  }
193 
194  const double vsafe = maximumSafeStopSpeed(gap, myDecel, speed, false, TS, false); // absolute breaking distance
195  const double vmin = minNextSpeed(speed, veh);
196  const double vmax = maxNextSpeed(speed, veh);
197 
199  return MIN2(vsafe, vmax);
200  } else {
201  // ballistic
202  // XXX: the euler variant can break as strong as it wishes immediately! The ballistic cannot, refs. #2575.
203  return MAX2(MIN2(vsafe, vmax), vmin);
204  }
205 }
206 
207 int
209  return SUMO_TAG_CF_RAIL;
210 }
211 
212 MSCFModel*
214  return new MSCFModel_Rail(vtype);
215 }
216 
217 double MSCFModel_Rail::maxNextSpeed(double speed, const MSVehicle* const veh) const {
218 
219  if (speed >= myTrainParams.vmax) {
220  return myTrainParams.vmax;
221  }
222 
223  double targetSpeed = myTrainParams.vmax;
224 
225  double res = myTrainParams.getResistance(speed); // kN
226 
227  double slope = veh->getSlope();
228  double gr = myTrainParams.weight * GRAVITY * sin(DEG2RAD(slope)); //kN
229 
230  double totalRes = res + gr; //kN
231 
232  double trac = myTrainParams.getTraction(speed); // kN
233 
234  double a;
235  if (speed < targetSpeed) {
236  a = (trac - totalRes) / myTrainParams.getRotWeight(); //kN/t == N/kg
237  } else {
238  a = 0.;
239  if (totalRes > trac) {
240  a = (trac - totalRes) / myTrainParams.getRotWeight(); //kN/t == N/kg
241  }
242  }
243  double maxNextSpeed = speed + ACCEL2SPEED(a);
244 
245 // std::cout << veh->getID() << " speed: " << (speed*3.6) << std::endl;
246 
247  return maxNextSpeed;
248 }
249 
250 double MSCFModel_Rail::minNextSpeed(double speed, const MSVehicle* const veh) const {
251 
252  const double slope = veh->getSlope();
253  const double gr = myTrainParams.weight * GRAVITY * sin(DEG2RAD(slope)); //kN
254  const double res = myTrainParams.getResistance(speed); // kN
255  const double totalRes = res + gr; //kN
256  const double a = myTrainParams.decl + totalRes / myTrainParams.getRotWeight();
257  const double vMin = speed - ACCEL2SPEED(a);
259  return MAX2(vMin, 0.);
260  } else {
261  // NOTE: ballistic update allows for negative speeds to indicate a stop within the next timestep
262  return vMin;
263  }
264 
265 }
266 
267 
268 double
269 MSCFModel_Rail::minNextSpeedEmergency(double speed, const MSVehicle* const veh) const {
270  return minNextSpeed(speed, veh);
271 }
272 
273 
274 double MSCFModel_Rail::getInterpolatedValueFromLookUpMap(double speed, const LookUpMap* lookUpMap) {
275  std::map<double, double>::const_iterator low, prev;
276  low = lookUpMap->lower_bound(speed);
277 
278  if (low == lookUpMap->end()) { //speed > max speed
279  return (lookUpMap->rbegin())->second;
280  }
281 
282  if (low == lookUpMap->begin()) {
283  return low->second;
284  }
285 
286  prev = low;
287  --prev;
288 
289  double range = low->first - prev->first;
290  double dist = speed - prev->first;
291  assert(range > 0);
292  assert(dist > 0);
293 
294  double weight = dist / range;
295 
296  double res = (1 - weight) * prev->second + weight * low->second;
297 
298  return res;
299 
300 }
301 
302 
303 
304 //void
305 //MSCFModel_Rail::initVehicleVariables(const MSVehicle *const veh, MSCFModel_Rail::VehicleVariables *pVariables) const {
306 //
307 // pVariables->setInitialized();
308 //
309 //}
310 
311 double MSCFModel_Rail::getSpeedAfterMaxDecel(double /* speed */) const {
312 
313 // //TODO: slope not known here
314 // double gr = 0; //trainParams.weight * GRAVITY * edge.grade
315 //
316 // double a = 0;//trainParams.decl - gr/trainParams.rotWeight;
317 //
318 // return speed + a * DELTA_T / 1000.;
319  WRITE_ERROR("function call not allowed for rail model. Exiting!");
320  throw ProcessError();
321 }
322 
324  VehicleVariables* ret = new VehicleVariables();
325  return ret;
326 }
327 
328 
329 double MSCFModel_Rail::finalizeSpeed(MSVehicle* const veh, double vPos) const {
330  return MSCFModel::finalizeSpeed(veh, vPos);
331 }
332 
333 double MSCFModel_Rail::freeSpeed(const MSVehicle* const /* veh */, double /* speed */, double dist, double targetSpeed,
334  const bool onInsertion, const CalcReason /*usage*/) const {
335 
336 // MSCFModel_Rail::VehicleVariables *vars = (MSCFModel_Rail::VehicleVariables *) veh->getCarFollowVariables();
337 // if (vars->isNotYetInitialized()) {
338 // initVehicleVariables(veh, vars);
339 // }
340 
341  //TODO: signals, coasting, ...
342 
344  // adapt speed to succeeding lane, no reaction time is involved
345  // when breaking for y steps the following distance g is covered
346  // (drive with v in the final step)
347  // g = (y^2 + y) * 0.5 * b + y * v
348  // y = ((((sqrt((b + 2.0*v)*(b + 2.0*v) + 8.0*b*g)) - b)*0.5 - v)/b)
349  const double v = SPEED2DIST(targetSpeed);
350  if (dist < v) {
351  return targetSpeed;
352  }
353  const double b = ACCEL2DIST(myDecel);
354  const double y = MAX2(0.0, ((sqrt((b + 2.0 * v) * (b + 2.0 * v) + 8.0 * b * dist) - b) * 0.5 - v) / b);
355  const double yFull = floor(y);
356  const double exactGap = (yFull * yFull + yFull) * 0.5 * b + yFull * v + (y > yFull ? v : 0.0);
357  const double fullSpeedGain = (yFull + (onInsertion ? 1. : 0.)) * ACCEL2SPEED(myTrainParams.decl);
358  return DIST2SPEED(MAX2(0.0, dist - exactGap) / (yFull + 1)) + fullSpeedGain + targetSpeed;
359  } else {
360  WRITE_ERROR(TL("Anything else than semi implicit euler update is not yet implemented. Exiting!"));
361  throw ProcessError();
362  }
363 }
364 
365 double MSCFModel_Rail::stopSpeed(const MSVehicle* const veh, const double speed, double gap, double decel, const CalcReason /*usage*/) const {
366  return MIN2(maximumSafeStopSpeed(gap, decel, speed, false, TS, false), maxNextSpeed(speed, veh));
367 }
368 
369 
370 void
371 MSCFModel_Rail::convertMap(LookUpMap& map, double keyFactor, double valueFactor) {
372  LookUpMap map2;
373  for (auto item : map) {
374  map2[item.first * keyFactor] = item.second * valueFactor;
375  }
376  map.clear();
377  map.insert(map2.begin(), map2.end());
378 }
#define DEG2RAD(x)
Definition: GeomHelper.h:35
#define GRAVITY
Definition: GeomHelper.h:37
#define WRITE_ERRORF(...)
Definition: MsgHandler.h:305
#define WRITE_ERROR(msg)
Definition: MsgHandler.h:304
#define WRITE_WARNING(msg)
Definition: MsgHandler.h:295
#define TL(string)
Definition: MsgHandler.h:315
#define TLF(string,...)
Definition: MsgHandler.h:317
#define SPEED2DIST(x)
Definition: SUMOTime.h:45
#define ACCEL2SPEED(x)
Definition: SUMOTime.h:51
#define TS
Definition: SUMOTime.h:42
#define DIST2SPEED(x)
Definition: SUMOTime.h:47
#define ACCEL2DIST(x)
Definition: SUMOTime.h:49
const long long int VTYPEPARS_MAXSPEED_SET
const long long int VTYPEPARS_MASS_SET
const long long int VTYPEPARS_LENGTH_SET
@ SUMO_TAG_CF_RAIL
SumoXMLAttr
Numbers representing SUMO-XML - attributes.
@ SUMO_ATTR_RESISTANCE_COEFFICIENT_CONSTANT
@ SUMO_ATTR_RESISTANCE_TABLE
@ SUMO_ATTR_TRAIN_TYPE
@ SUMO_ATTR_MASSFACTOR
@ SUMO_ATTR_MAXTRACTION
@ SUMO_ATTR_MAXPOWER
@ SUMO_ATTR_RESISTANCE_COEFFICIENT_QUADRATIC
@ SUMO_ATTR_DECEL
@ SUMO_ATTR_EMERGENCYDECEL
@ SUMO_ATTR_SPEED_TABLE
@ SUMO_ATTR_RESISTANCE_COEFFICIENT_LINEAR
@ SUMO_ATTR_TRACTION_TABLE
const double INVALID_DOUBLE
invalid double
Definition: StdDefs.h:64
T MIN2(T a, T b)
Definition: StdDefs.h:76
T MAX2(T a, T b)
Definition: StdDefs.h:82
const MSVehicleType & getVehicleType() const
Returns the vehicle's type definition.
TrainParams initICE3Params() const
TrainParams initNGT400_16Params() const
virtual ~MSCFModel_Rail()
TrainParams initREDosto7Params() const
MSCFModel::VehicleVariables * createVehicleVariables() const
Returns model specific values which are stored inside a vehicle and must be used with casting.
virtual double minNextSpeedEmergency(double speed, const MSVehicle *const veh=0) const
Returns the minimum speed after emergency braking, given the current speed (depends on the numerical ...
TrainParams initCustomParams() const
TrainParams initICE1Params() const
MSCFModel_Rail(const MSVehicleType *vtype)
Constructor.
TrainParams initMireoPlusB2TParams() const
double freeSpeed(const MSVehicle *const veh, double speed, double seen, double maxSpeed, const bool onInsertion, const CalcReason usage=CalcReason::CURRENT) const
Computes the vehicle's safe speed without a leader.
TrainParams initRB628Params() const
virtual MSCFModel * duplicate(const MSVehicleType *vtype) const
Duplicates the car-following model.
static double getInterpolatedValueFromLookUpMap(double speed, const LookUpMap *lookUpMap)
virtual int getModelID() const
Returns the model's ID; the XML-Tag number is used.
double getSpeedAfterMaxDecel(double v) const
Returns the velocity after maximum deceleration.
TrainParams myTrainParams
virtual double minNextSpeed(double speed, const MSVehicle *const veh) const
Returns the minimum speed given the current speed (depends on the numerical update scheme and its ste...
static void convertMap(LookUpMap &map, double keyFactor=1/3.6, double valueFactor=1)
std::vector< double > getValueTable(const MSVehicleType *vtype, SumoXMLAttr attr)
double followSpeed(const MSVehicle *const veh, double speed, double gap2pred, double predSpeed, double predMaxDecel, const MSVehicle *const pred=0, const CalcReason usage=CalcReason::CURRENT) const
Computes the vehicle's follow speed (no dawdling)
TrainParams initRB425Params() const
TrainParams initFreightParams() const
virtual double maxNextSpeed(double speed, const MSVehicle *const veh) const
Returns the maximum speed given the current speed.
TrainParams initNGT400Params() const
TrainParams initMireoPlusH2TParams() const
std::map< double, double > LookUpMap
double finalizeSpeed(MSVehicle *const veh, double vPos) const
Applies interaction with stops and lane changing model influences. Called at most once per simulation...
double stopSpeed(const MSVehicle *const veh, const double speed, double gap, double decel, const CalcReason usage=CalcReason::CURRENT) const
Computes the vehicle's safe speed for approaching a non-moving obstacle (no dawdling)
The car-following model abstraction.
Definition: MSCFModel.h:55
virtual void setEmergencyDecel(double decel)
Sets a new value for maximal physically possible deceleration [m/s^2].
Definition: MSCFModel.h:544
virtual double finalizeSpeed(MSVehicle *const veh, double vPos) const
Applies interaction with stops and lane changing model influences. Called at most once per simulation...
Definition: MSCFModel.cpp:187
virtual void setMaxDecel(double decel)
Sets a new value for maximal comfortable deceleration [m/s^2].
Definition: MSCFModel.h:536
CalcReason
What the return value of stop/follow/free-Speed is used for.
Definition: MSCFModel.h:77
double myDecel
The vehicle's maximum deceleration [m/s^2].
Definition: MSCFModel.h:701
double maximumSafeStopSpeed(double gap, double decel, double currentSpeed, bool onInsertion=false, double headway=-1, bool relaxEmergency=true) const
Returns the maximum next velocity for stopping within gap.
Definition: MSCFModel.cpp:774
static bool gSemiImplicitEulerUpdate
Definition: MSGlobals.h:53
Representation of a vehicle in the micro simulation.
Definition: MSVehicle.h:77
double getSlope() const
Returns the slope of the road at vehicle's position in degrees.
Definition: MSVehicle.cpp:1215
The car-following model and parameter.
Definition: MSVehicleType.h:63
double getMaxSpeed() const
Get vehicle's (technical) maximum speed [m/s].
double getMinGap() const
Get the free space in front of vehicles of this class.
bool wasSet(long long int what) const
Returns whether the given parameter was set.
Definition: MSVehicleType.h:80
const std::string & getID() const
Returns the name of the vehicle type.
Definition: MSVehicleType.h:91
double getLength() const
Get vehicle's length [m].
double getMass() const
Get this vehicle type's mass.
const SUMOVTypeParameter & getParameter() const
double getCFParam(const SumoXMLAttr attr, const double defaultValue) const
Returns the named value from the map, or the default if it is not contained there.
std::string getCFParamString(const SumoXMLAttr attr, const std::string defaultValue) const
Returns the named value from the map, or the default if it is not contained there.
static double toDouble(const std::string &sData)
converts a string into the double value described by it by calling the char-type converter
double getTraction(double speed) const
double getResistance(double speed) const