Eclipse SUMO - Simulation of Urban MObility
MSDevice_ElecHybrid.cpp
Go to the documentation of this file.
1 /****************************************************************************/
2 // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3 // Copyright (C) 2002-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 // The ElecHybrid device simulates internal electric parameters of an
20 // battery-assisted electric vehicle (typically a trolleybus), i.e. a vehicle
21 // that is being powered by overhead wires and has also a battery pack
22 // installed, that is being charged from the overhead wires.
23 /****************************************************************************/
24 #include <config.h>
25 
26 #include <string.h> //due to strncmp
27 #include <ctime> //due to clock()
32 #include <utils/common/SUMOTime.h>
35 #include <microsim/MSNet.h>
36 #include <microsim/MSLane.h>
37 #include <microsim/MSEdge.h>
38 #include <microsim/MSVehicle.h>
39 #include <microsim/MSGlobals.h>
40 #include <microsim/MSEdgeControl.h>
41 #include <mesosim/MEVehicle.h>
42 #include "MSDevice_Tripinfo.h"
43 #include "MSDevice_Emissions.h"
44 #include "MSDevice_ElecHybrid.h"
45 
46 
47 // ===========================================================================
48 // method definitions
49 // ===========================================================================
50 // ---------------------------------------------------------------------------
51 // static initialisation methods
52 // ---------------------------------------------------------------------------
53 void
55  oc.addOptionSubTopic("ElecHybrid Device");
56  insertDefaultAssignmentOptions("elechybrid", "ElecHybrid Device", oc);
57 }
58 
59 
60 void
61 MSDevice_ElecHybrid::buildVehicleDevices(SUMOVehicle& v, std::vector<MSVehicleDevice*>& into) {
62  // Check if vehicle should get an 'elecHybrid' device.
64  if (equippedByDefaultAssignmentOptions(oc, "elechybrid", v, false)) {
65  // Yes, build the device.
66  // Fetch the battery capacity (if present) from the vehicle descriptor.
67  const SUMOVTypeParameter& typeParams = v.getVehicleType().getParameter();
68  const SUMOVehicleParameter& vehicleParams = v.getParameter();
69  double actualBatteryCapacity = 0;
70  /* The actual battery capacity can be a parameter of the vehicle or its vehicle type.
71  The vehicle parameter takes precedence over the type parameter. */
72  std::string attrName = toString(SUMO_ATTR_ACTUALBATTERYCAPACITY);
73  if (vehicleParams.hasParameter(attrName)) {
74  const std::string abc = vehicleParams.getParameter(attrName, "-1");
75  try {
76  actualBatteryCapacity = StringUtils::toDouble(abc);
77  } catch (...) {
78  WRITE_WARNING("Invalid value '" + abc + "'for vehicle parameter '" + attrName + "'. Using the default of " + std::to_string(actualBatteryCapacity));
79  }
80  } else {
81  if (typeParams.hasParameter(attrName)) {
82  const std::string abc = typeParams.getParameter(attrName, "-1");
83  try {
84  actualBatteryCapacity = StringUtils::toDouble(abc);
85  WRITE_WARNING("Vehicle '" + v.getID() + "' does not provide vehicle parameter '" + attrName + "'. Using the vehicle type value of " + std::to_string(actualBatteryCapacity));
86  } catch (...) {
87  WRITE_WARNING("Invalid value '" + abc + "'for vehicle type parameter '" + attrName + "'. Using the default of " + std::to_string(actualBatteryCapacity));
88  }
89  } else {
90  WRITE_WARNING("Vehicle '" + v.getID() + "' does not provide vehicle or vehicle type parameter '" + attrName + "'. Using the default of " + std::to_string(actualBatteryCapacity));
91  }
92  }
93 
94  // obtain maximumBatteryCapacity
95  double maximumBatteryCapacity = 0;
97  if (typeParams.hasParameter(attrName)) {
98  const std::string mbc = typeParams.getParameter(attrName, "-1");
99  try {
100  maximumBatteryCapacity = StringUtils::toDouble(mbc);
101  } catch (...) {
102  WRITE_WARNINGF(TL("Invalid value '%'for vType parameter '%'"), mbc, attrName);
103  }
104  } else {
105  WRITE_WARNING("Vehicle '" + v.getID() + "' is missing the vType parameter '" + attrName + "'. Using the default of " + std::to_string(maximumBatteryCapacity));
106  }
107 
108  // obtain overheadWireChargingPower
109  double overheadWireChargingPower = 0;
111  if (typeParams.hasParameter(attrName)) {
112  const std::string ocp = typeParams.getParameter(attrName, "-1");
113  try {
114  overheadWireChargingPower = StringUtils::toDouble(ocp);
115  } catch (...) {
116  WRITE_WARNINGF(TL("Invalid value '%'for vType parameter '%'"), ocp, attrName);
117  }
118  } else {
119  WRITE_WARNING("Vehicle '" + v.getID() + "' is missing the vType parameter '" + attrName + "'. Using the default of " + std::to_string(overheadWireChargingPower));
120  }
121 
122  // elecHybrid constructor
123  MSDevice_ElecHybrid* device = new MSDevice_ElecHybrid(v, "elecHybrid_" + v.getID(),
124  actualBatteryCapacity, maximumBatteryCapacity, overheadWireChargingPower);
125 
126  // Add device to vehicle
127  into.push_back(device);
128  }
129 }
130 
131 
132 // ---------------------------------------------------------------------------
133 // MSDevice_ElecHybrid-methods
134 // ---------------------------------------------------------------------------
136  const double actualBatteryCapacity, const double maximumBatteryCapacity, const double overheadWireChargingPower) :
137  MSVehicleDevice(holder, id),
138  myActualBatteryCapacity(0), // [actualBatteryCapacity <= maximumBatteryCapacity]
139  myMaximumBatteryCapacity(0), // [maximumBatteryCapacity >= 0]t
140  myOverheadWireChargingPower(0),
141  myLastAngle(NAN),
142  myConsum(0),
143  myBatteryDischargedLogic(false),
144  myCharging(false), // Initially vehicle don't charge
145  myEnergyCharged(0), // Initially the energy charged is zero
146  myCircuitCurrent(NAN), // Initially the current is unknown
147  myCircuitVoltage(NAN), // Initially the voltage is unknown as well
148  myMaxBatteryCharge(NAN), // Initial maximum of the the battery energy during the simulation is unknown
149  myMinBatteryCharge(NAN), // Initial minimum of the the battery energy during the simulation is unknown
150  myTotalEnergyConsumed(0), // No energy spent yet
151  myTotalEnergyRegenerated(0), // No energy regenerated
152  myTotalEnergyWasted(0), // No energy wasted on resistors
153  // RICE_TODO: make these two parameters user configurable
154  mySOCMin(0.005), // Minimum SOC of the battery
155  mySOCMax(0.980), // Maximum SOC of the battery
156  myActOverheadWireSegment(nullptr), // Initially the vehicle isn't under any overhead wire segment
157  myPreviousOverheadWireSegment(nullptr), // Initially the vehicle wasn't under any overhead wire segment
158  veh_elem(nullptr),
159  veh_pos_tail_elem(nullptr),
160  pos_veh_node(nullptr) {
161 
162  EnergyParams* const params = myHolder.getEmissionParameters();
164 
165  if (maximumBatteryCapacity < 0) {
166  WRITE_WARNINGF(TL("ElecHybrid builder: Vehicle '%' doesn't have a valid value for parameter % (%)."), getID(), toString(SUMO_ATTR_MAXIMUMBATTERYCAPACITY), toString(maximumBatteryCapacity));
167  } else {
168  myMaximumBatteryCapacity = maximumBatteryCapacity;
169  }
170 
171  if (actualBatteryCapacity > maximumBatteryCapacity) {
172  WRITE_WARNING("ElecHybrid builder: Vehicle '" + getID() + "' has a " + toString(SUMO_ATTR_ACTUALBATTERYCAPACITY) + " (" + toString(actualBatteryCapacity) + ") greater than it's " + toString(SUMO_ATTR_MAXIMUMBATTERYCAPACITY) + " (" + toString(maximumBatteryCapacity) + "). A max battery capacity value will be asigned");
174  } else {
175  myActualBatteryCapacity = actualBatteryCapacity;
176  }
177 
178  if (overheadWireChargingPower < 0) {
179  WRITE_WARNINGF(TL("ElecHybrid builder: Vehicle '%' doesn't have a valid value for parameter % (%)."), getID(), toString(SUMO_ATTR_OVERHEADWIRECHARGINGPOWER), toString(overheadWireChargingPower));
180  } else {
181  myOverheadWireChargingPower = overheadWireChargingPower;
182  }
183 }
184 
185 
187 }
188 
189 
190 bool
191 MSDevice_ElecHybrid::notifyMove(SUMOTrafficObject& tObject, double /* oldPos */, double /* newPos */, double /* newSpeed */) {
192  if (!tObject.isVehicle()) {
193  return false;
194  }
195  SUMOVehicle& veh = static_cast<SUMOVehicle&>(tObject);
196  // Do not compute the current consumption here anymore:
197  // myConsum is (non-systematically, we agree) set in MSVehicle so that the vehicle `vNext` value can
198  // be influenced by the maximum traction power of the vehicle (i.e. installing a 80 kWh powertrain will
199  // limit the acceleration regardless of the acceleration specified in vehicleType params, in case that
200  // the vehicleType acceleration is too high).
201  //
202  // myParam[SUMO_ATTR_ANGLE] = myLastAngle == std::numeric_limits<double>::infinity() ? 0. : GeomHelper::angleDiff(myLastAngle, veh.getAngle());
203  // myConsum = PollutantsInterface::getEnergyHelper().compute(0, PollutantsInterface::ELEC, veh.getSpeed(), veh.getAcceleration(), veh.getSlope(), &myParam);
204  assert(!std::isnan(myConsum));
205 
206  // is battery pack discharged (from previous timestep)
209  } else {
210  myBatteryDischargedLogic = false;
211  }
212 
213  /* If battery is discharged we will force the vehicle to slowly come to
214  a halt (freewheel motion). It could still happen that some energy will
215  be recovered in later steps due to regenerative braking. */
216  if (isBatteryDischarged()) {
217  std::vector<std::pair<SUMOTime, double> > speedTimeLine;
221  double accel = acceleration(veh, 0, veh.getSpeed()); // or use veh.getAcceleration() method???
222  const double nextSpeed = MAX2(0., veh.getSpeed() + ACCEL2SPEED(accel));
223  speedTimeLine.push_back(
224  std::make_pair(
225  MSNet::getInstance()->getCurrentTimeStep(),
226  veh.getSpeed()));
227  speedTimeLine.push_back(
228  std::make_pair(
229  MSNet::getInstance()->getCurrentTimeStep() + DELTA_T,
230  nextSpeed));
231 
232  static_cast<MSVehicle*>(&veh)->getInfluencer().setSpeedTimeLine(speedTimeLine);
233  }
234 
235  /* Check if there is an overhead wire either over the lane where the vehicle is or over a
236  neighbouring lanes. This check has to be performed at every simulation step as the
237  overhead wires for trolleybuses will typically end at a bus stop that is located somewhere
238  in the middle of the lane. */
239  std::string overheadWireSegmentID = MSNet::getInstance()->getStoppingPlaceID(veh.getLane(), veh.getPositionOnLane(), SUMO_TAG_OVERHEAD_WIRE_SEGMENT);
240 
241  //check overhead line on the left neighbouring lane
242  if (overheadWireSegmentID == "" && veh.getEdge()->leftLane(veh.getLane()) != nullptr) {
244  }
245  //check overhead line on the right neighbouring lane
246  if (overheadWireSegmentID == "" && veh.getEdge()->rightLane(veh.getLane()) != nullptr) {
248  }
249 
250  /* Store the amount of power that could not be recuperated. */
251  double energyWasted = 0.0;
252  /* If vehicle has access to an overhead wire (including the installation on neighbouring lanes) */
253  if (overheadWireSegmentID != "") {
254  /* Update the actual overhead wire segment of this device */
256  static_cast<MSOverheadWire*>(MSNet::getInstance()->getStoppingPlace(overheadWireSegmentID, SUMO_TAG_OVERHEAD_WIRE_SEGMENT));
257  /* Store the traction substation of the actual overhead wire segment */
259 
260  /* Disable charging from previous (not the actual) overhead wire segment.
261  REASON:
262  If there is no gap between two different overhead wire segments that are
263  places on the same lane, the vehicle switches from the one segment to another
264  in one timestep. */
266  if (myPreviousOverheadWireSegment != nullptr) {
267  /* Remove the vehicle from the list of vehicles powered by the previous segment. */
270  if (ts != nullptr) {
272  ts->eraseVehicle(this);
273  }
274  }
275  /* Add the vehicle reference to the current segment. */
277  if (actualSubstation != nullptr) {
278  actualSubstation->increaseElecHybridCount();
279  actualSubstation->addVehicle(this);
280  }
281  }
282 
283  /* Do we simulate the behaviour of the overhead wire electric circuit? */
285 #ifdef HAVE_EIGEN
287  /* Circuit update due to vehicle movement:
288  Delete vehicle resistor element, vehicle resistor nodes and vehicle resistor
289  tails in the circuit used in the previous timestep. */
291 
292  /* Add the vehicle to the circuit in case that there is a substation that provides
293  power to it. */
294  if (actualSubstation != nullptr) {
295  /* Add a resistor (current source in the future?) representing trolleybus
296  vehicle to the circuit.
297  pos/neg_veh_node elements
298  [0] .... vehicle_resistor
299  [1] .... leading resistor
300  [2] .... tail resistor pos/neg_tail_vehID
301  */
302 
303  // pos_veh_node and veh_elem should be NULL
304  if (pos_veh_node != nullptr || veh_elem != nullptr) {
305  WRITE_WARNING("pos_veh_node or neg_veh_node or veh_elem is not NULL (and they should be at the beginning of adding elecHybrid to the circuit)");
306  }
307 
308  // create pos and veh_elem
310  pos_veh_node = owc->addNode("pos_" + veh.getID());
311  assert(pos_veh_node != nullptr);
312  // adding current source element representing elecHybrid vehicle. The value of current is computed from wantedPower later by circuit solver. Thus NAN is used as an initial value.
313  veh_elem = owc->addElement("currentSrc" + veh.getID(), NAN,
314  pos_veh_node, owc->getNode("negNode_ground"),
315  Element::ElementType::CURRENT_SOURCE_traction_wire);
316 
317  // Connect vehicle to an existing overhead wire segment = add elecHybridVehicle to the myActOverheadWireSegment circuit
318  // Find pos resistor element of the actual overhead line section and their end nodes
319  Element* element_pos = owc->getElement("pos_" + myActOverheadWireSegment->getID());
320  Node* node_pos = element_pos->getNegNode();
321  double resistance = element_pos->getResistance();
322 
323  /* Find the correct position of the vehicle at the overhead line.
324  We start the while loop at the end of the actual overhead line section and go against the direction of vehicle movement.
325  The decision rule is based on the resistance value:
326  * from the vehicle position to the end of lane,
327  * sum of resistance of elements (going from the end of ovehead line section in the contrary direction).
328 
329  The original solution runs into problems when a vehicle is going on a neigboring lane and the two lanes have different lengths:
330  while (resistance < (veh.getLane()->getLength() - veh.getPositionOnLane())*WIRE_RESISTIVITY) {
331  Improvement: take the relative distance of the vehicle to the end of its lane and map it to the segment's lane length. (This works also in case that the segment's lane and the vehicle's lane are identical.)
332  */
333  double relativePosOnSegment =
335  (veh.getPositionOnLane() / veh.getLane()->getLength()));
336 
337  while (resistance < relativePosOnSegment * WIRE_RESISTIVITY) {
338  node_pos = element_pos->getPosNode();
339  element_pos = node_pos->getElements()->at(2);
340  resistance += element_pos->getResistance();
341  if (strncmp(element_pos->getName().c_str(), "pos_tail_", 9) != 0) {
342  WRITE_WARNING("splitting element is not 'pos_tail_XXX'")
343  }
344  }
345 
346  node_pos = element_pos->getPosNode();
347  //resistance of vehicle tail nodes
348  resistance -= relativePosOnSegment * WIRE_RESISTIVITY;
349 
350  /* dividing element_pos
351  before: |node_pos|---------------------------------------------|element_pos|----
352  after: |node_pos|----|veh_pos_tail_elem|----|pos_veh_node|----|element_pos|----
353  */
354  element_pos->setPosNode(pos_veh_node);
355  node_pos->eraseElement(element_pos);
356  pos_veh_node->addElement(element_pos);
357 
358  veh_pos_tail_elem = owc->addElement("pos_tail_" + veh.getID(),
359  resistance, node_pos, pos_veh_node, Element::ElementType::RESISTOR_traction_wire);
360 
361  if (element_pos->getResistance() - resistance < 0) {
362  WRITE_WARNINGF(TL("The resistivity of overhead wire segment connected to vehicle % is < 0. Set to 1e-6."), veh.getID());
363  }
364 
365  element_pos->setResistance(element_pos->getResistance() - resistance);
366 
367 
368  // Set the power requirement to the consumption + charging power.
369  // RICE_TODO: The charging power could be different when moving and when not. Add a parameter.
370  // Note that according to PMDP data, the charging power seems to be the same in both situations,
371  // ignoreing the potential benefits of using a higher charging power when the vehicle is moving.
374  } else {
376  }
377 
378  // No recuperation to overheadwire (only to the batterypack)
380  // the value of energyWasted is properly computed and updated after solving circuit by the solver
381  // energyWasted = 0;
382  veh_elem->setPowerWanted(0.0);
383  }
384 
385  // RICE_TODO: The voltage in the solver should never exceed or drop below some limits. Maximum allowed voltage is typicallty 800 V.
386  // The numerical solver that computes the circuit state needs initial values of electric currents and
387  // voltages from which it will start the iterative solving process. We prefer to reuse the "old" values
388  // as it is likely that the new values will not be far away from the old ones. The safety limits of
389  // 10 and 1500 Volts that are used below are chosen fairly arbitrarily to keep the initial values within
390  // reasonable limits.
391  double voltage = myCircuitVoltage;
392  if (voltage < 10.0 || voltage > 1500.0 || std::isnan(voltage)) {
393  // RICE_TODO : It seems to output warning whenever a vehicle is appearing under the overhead wire for the first time?
394  // WRITE_WARNINGF(TL("The initial voltage is was % V, replacing it with substation voltage % V."), toString(voltage), toString(actualSubstation->getSubstationVoltage()));
395  voltage = actualSubstation->getSubstationVoltage();
396  }
397  // Initial value of the electric current flowing into the vehilce that will be used by the solver
398  double current = -(veh_elem->getPowerWanted() / voltage);
399  veh_elem->setCurrent(current);
400 
401  // Set the device as charging the battery by default
402  myCharging = true;
403 
404  // And register the call to solver at the end of the simulation step
405  actualSubstation->addSolvingCirucitToEndOfTimestepEvents();
406  } else {
407  /*
408  No substation on this wire ...
409  */
410  // RICE_TODO myCharging = false; current 0 or nan, voltage 0 or nan, maybe write warning that the overhead wire is not connected to any substation,
411 
412  // Energy flowing to/from the battery pack [Wh] has to completely cover vehicle consumption.
414  // Update Battery charge
416  // No substation is connected to this segmenr and the charging output is therefore zero.
418  }
419 #else
420  WRITE_ERROR(TL("Overhead wire solver is on, but the Eigen library has not been compiled in!"))
421 #endif
422  } else {
423  /*
424  Faster approximaion without circuit solving at every simulation step.
425  */
426 
427  // First check that there is a traction substation connected to the overhead wire
428  double voltage = 0.0;
429  if (actualSubstation != nullptr) {
430  voltage = actualSubstation->getSubstationVoltage();
431  }
432 
433  // At this point the volate can be (a) NAN if the substation voltage was not specified,
434  // (b) 0 if no substation powers the current segment or if someone put its power to zero,
435  // (c) >0 if the substation can provide energy to the circuit.
436  if (voltage > 0.0) {
437  // There is a power source connected to this segment.
438  // Set the simplified power requirement to the consumption + charging power.
439  // RICE_TODO: The charging power could be different when moving and when not. Add a parameter. See a similar code snippet above.
440  // Note that according to PMDP data, the charging power seems to be the same in both situations,
441  // ignoreing the potential benefits of using a higher charging power when the vehicle is moving.
442  double powerWanted = WATTHR2WATT(myConsum);
444  // Additional `myOverheadWireChargingPower` due to charging of battery pack
445  powerWanted += myOverheadWireChargingPower;
446  }
447 
448  // No recuperation to overhead wire (only to the battery pack)
449  // RICE_TODO: How to recuperate into the circuit without solver? (energy balance?)
450  // - solution: assume, that any power is possible to recuperate
451  if (!MSGlobals::gOverheadWireRecuperation && powerWanted < 0.0) {
452  // the value of energyWasted is properly computed and updated below
453  powerWanted = 0.0;
454  }
455 
456  // Set the actual current and voltage of the global circuit
457  // RICE_TODO: Process the traction stataion current limiting here as well.
458  myCircuitCurrent = powerWanted / voltage;
459  myCircuitVoltage = voltage;
460 
461  // Calulate energy charged
462  double energyIn = WATT2WATTHR(powerWanted);
463 
464  // Calulate energy flowing to/from the battery in this step [Wh]
465  // RICE_TODO: It should be possible to define different efficiency values for direction overhead wire -> battery; motor -> battery.
466  // We use a simplification here. The biggest contributor to the total losses is the battery pack itself
467  // (the input LC filter is probably more efficient -- eta_LC ~ 0.99 -- compared to the induction motor
468  // with eta_motor ~ 0.95).
470 
471  // Update the energy that has been stored in the battery pack and return the real energy charged in this step
472  // considering SOC limits of the battery pack.
473  double realEnergyCharged = storeEnergyToBattery(myEnergyCharged);
474  // Set energy wasted
475  energyWasted = myEnergyCharged - realEnergyCharged;
476 
477  // Add the energy provided by the overhead wire segment to the output of the segment
479  } else {
480  /*
481  Overhead wire without a connected substation
482  */
483  // RICE_TODO myCharging = false; current 0 or nan, voltage 0 or nan, maybe write warning that the overhead wire is not connected to any substation,
484 
485  // Energy for the powertrain is provided by the battery pack
487  // Update battery charge
489  // No energy was provided by the overhead wire segment
491  }
492  }
493  assert(myActOverheadWireSegment != nullptr);
495  } else {
496  /*
497  No overhead wires, no charging.
498  */
499 
500  // Disable charing flag
501  myCharging = false;
502 
503  // Invalidate the circuit voltage and current
504  myCircuitCurrent = NAN;
505  myCircuitVoltage = NAN;
506 
507  // Additional bookkeeping in case that the circuit solver is used
509 #ifdef HAVE_EIGEN
510  /*
511  Delete vehicle resistor element, vehicle resistor nodes and vehicle resistor tails
512  in the previous circuit (i.e. the circuit used in the previous timestep)
513  */
515 #else
516  WRITE_ERROR(TL("Overhead wire solver is on, but the Eigen library has not been compiled in!"))
517 #endif
518  }
519 
520  // Vehicle is not under an overhead wire
521  myActOverheadWireSegment = nullptr;
522 
523  // Remove the vehicle from overhead wire if it was under it in the previous step.
524  // This has to be called afer deleteVehicleFromCircuit() as the file uses myPreviousOverheadWire.
525  if (myPreviousOverheadWireSegment != nullptr) {
528  if (ts != nullptr) {
530  ts->eraseVehicle(this);
531  }
533  }
534 
535  // Energy for the powertrain is provided by the battery pack
537  // Update battery charge
539  }
540 
541  // Update the statistical values
542  // RICE_TODO: update these statistical values also after solving circuit by electric circuit
545  }
548  }
549 
550  if (myConsum > 0.0) {
552  } else {
554  }
555  myTotalEnergyWasted += energyWasted;
556 
557  myLastAngle = veh.getAngle();
558  return true; // keep the device
559 }
560 
561 // Note: This is called solely in the mesoscopic mode to mimic the `notifyMove()` reminder
562 void
564  const SUMOTrafficObject& tObject,
565  const double frontOnLane,
566  const double timeOnLane,
567  const double meanSpeedFrontOnLane,
568  const double meanSpeedVehicleOnLane,
569  const double travelledDistanceFrontOnLane,
570  const double travelledDistanceVehicleOnLane,
571  const double meanLengthOnLane) {
572  UNUSED_PARAMETER(tObject);
573  UNUSED_PARAMETER(frontOnLane);
574  UNUSED_PARAMETER(timeOnLane);
575  UNUSED_PARAMETER(meanSpeedFrontOnLane);
576  UNUSED_PARAMETER(meanSpeedVehicleOnLane);
577  UNUSED_PARAMETER(travelledDistanceFrontOnLane);
578  UNUSED_PARAMETER(travelledDistanceVehicleOnLane);
579  UNUSED_PARAMETER(meanLengthOnLane);
580 }
581 
582 void
584  if (myPreviousOverheadWireSegment != nullptr) {
586  //check if all pointers to vehicle elements and nodes are not nullptr
587  if (veh_elem == nullptr || veh_pos_tail_elem == nullptr || pos_veh_node == nullptr) {
588  WRITE_ERRORF("During deleting vehicle '%' from circuit some init previous Nodes or Elements was not assigned.", veh.getID());
589  }
590  //check if pos_veh_node has 3 elements - they should be: veh_elem, veh_pos_tail_elem and an overhead line resistor element "ahead" of vehicle.
591  if (pos_veh_node->getElements()->size() != 3) {
592  WRITE_ERRORF("During deleting vehicle '%' from circuit the size of element-vector of pNode or nNode was not 3. It should be 3 by Jakub's opinion.", veh.getID());
593  }
594  //delete vehicle resistor element "veh_elem" in the previous circuit,
597  delete veh_elem;
598  veh_elem = nullptr;
599 
600  //eraising of tail elements (the element connected to the veh_node is afterthen only the ahead overhead line resistor element)
602 
603  if (pos_veh_node->getElements()->size() != 1) {
604  WRITE_ERRORF("During deleting vehicle '%' from circuit the size of element-vector of pNode or nNode was not 1. It should be 1 by Jakub's opinion.", veh.getID());
605  }
606 
607  // add the resistance value of veh_tail element to the resistance value of the ahead overhead line element
608  pos_veh_node->getElements()->front()->setResistance(pos_veh_node->getElements()->front()->getResistance() + veh_pos_tail_elem->getResistance());
609  //set PosNode of the ahead overhead line element to the posNode value of tail element
610  Element* aux = pos_veh_node->getElements()->front();
611  //set node = 3 operations
613  aux->getPosNode()->eraseElement(aux);
615 
616  // erase tail element from its PosNode
618  // delete veh_pos_tail_elem
620  delete veh_pos_tail_elem;
621  veh_pos_tail_elem = nullptr;
622 
623  //erase pos_veh_node
625  //modify id of other elements (the id of erasing element should be the greatest)
626  int lastId = myPreviousOverheadWireSegment->getCircuit()->getLastId() - 1;
627  if (pos_veh_node->getId() != lastId) {
628  Node* node_last = myPreviousOverheadWireSegment->getCircuit()->getNode(lastId);
629  if (node_last != nullptr) {
630  node_last->setId(pos_veh_node->getId());
631  } else {
633  if (elem_last != nullptr) {
634  elem_last->setId(pos_veh_node->getId());
635  } else {
636  WRITE_ERROR(TL("The element or node with the last Id was not found in the circuit!"));
637  }
638  }
639  }
641  delete pos_veh_node;
642  pos_veh_node = nullptr;
643  }
644  }
645 }
646 
647 bool
649  SUMOTrafficObject& tObject,
650  MSMoveReminder::Notification /* reason */,
651  const MSLane* /* enteredLane */) {
652  if (!tObject.isVehicle()) {
653  return false;
654  }
655 #ifdef ELECHYBRID_MESOSCOPIC_DEBUG
656  SUMOVehicle& veh = static_cast<SUMOVehicle&>(tObject);
657  std::cout << "device '" << getID() << "' notifyEnter: reason=" << reason << " currentEdge=" << veh.getEdge()->getID() << "\n";
658 #endif
659 
660  return true; // keep the device
661 }
662 
663 bool
665  SUMOTrafficObject& tObject,
666  double /*lastPos*/,
668  const MSLane* /* enteredLane */) {
669  if (!tObject.isVehicle()) {
670  return false;
671  }
672  SUMOVehicle& veh = static_cast<SUMOVehicle&>(tObject);
673 #ifdef ELECHYBRID_MESOSCOPIC_DEBUG
674  SUMOVehicle& veh = static_cast<SUMOVehicle&>(tObject);
675  std::cout << "device '" << getID() << "' notifyLeave: reason=" << reason << " currentEdge=" << veh.getEdge()->getID() << "\n";
676  SUMOVehicle* sumoVehicle = *veh;
678  MEVehicle& v = dynamic_cast<MEVehicle&>(veh);
679  std::cout << "***************** MESO - notifyLeave*** START ****************** '" << v.getID() << "' \n";
680  //TODO the second argument of getStoptime should change
681  std::cout << "getSpeed: '" << v.getSpeed() << "' | getAverageSpeed: '" << v.getAverageSpeed() << "' | getStoptime: '" << v.getStoptime(v.getSegment(), 0) << "' \n";
682  std::cout << "getStopEdges: '" << "' | getLastEntryTime: '" << v.getLastEntryTime() << "' | getBlockTimeSeconds: '" << v.getBlockTimeSeconds() << "' \n";
683  std::cout << "getWaitingTime: '" << v.getWaitingTime() << "' | getAccumulatedWaitingTime: '" << v.getWaitingTime(true) << "' | getLastEntryTimeSeconds: '" << v.getLastEntryTimeSeconds() << "' \n";
684  std::cout << "***************** MESO - notifyLeave*** END ****************** '" << v.getID() << "' \n";
685  }
686 #endif
687 
688  // The MSMoveReminders are sorted so that we can do `<`. See also BTreceiver and BTsender devices...
690  return true;
691  }
692 
694 #ifdef HAVE_EIGEN
695  // ------- *** ------- delete vehicle resistor element, vehicle resistor nodes and vehicle resistor tails in the previous circuit (circuit used in the previous timestep)------- *** -------
697 #else
698  UNUSED_PARAMETER(veh);
699  WRITE_ERROR(TL("Overhead wire solver is on, but the Eigen library has not been compiled in!"))
700 #endif
701  }
702  // disable charging vehicle from overhead wire and segment and traction station
703  if (myPreviousOverheadWireSegment != nullptr) {
706  if (prevSubstation != nullptr) {
707  prevSubstation->decreaseElecHybridCount();
708  prevSubstation->eraseVehicle(this);
709  }
711  }
712  return true;
713 }
714 
715 
716 void
718  if (tripinfoOut != nullptr) {
719  // Write the summary elecHybrid information into tripinfo output
720  tripinfoOut->openTag("elechybrid");
721  tripinfoOut->writeAttr("maxBatteryCharge", myMaxBatteryCharge);
722  tripinfoOut->writeAttr("minBatteryCharge", myMinBatteryCharge);
723  tripinfoOut->writeAttr("totalEnergyConsumed", myTotalEnergyConsumed);
724  tripinfoOut->writeAttr("totalEnergyRegenerated", myTotalEnergyRegenerated);
725  tripinfoOut->writeAttr("totalEnergyWasted", myTotalEnergyWasted);
726  tripinfoOut->closeTag();
727  }
728 }
729 
730 
731 double
734 }
735 
736 
737 double
740 }
741 
742 std::string
743 MSDevice_ElecHybrid::getParameter(const std::string& key) const {
744  // RICE_TODO: full traci support
747  } else if (key == toString(SUMO_ATTR_ENERGYCONSUMED)) {
748  return toString(myConsum);
749  } else if (key == toString(SUMO_ATTR_ENERGYCHARGED)) {
750  return toString(myEnergyCharged);
751  } else if (key == toString(SUMO_ATTR_MAXIMUMBATTERYCAPACITY)) {
753  } else if (key == toString(SUMO_ATTR_OVERHEADWIREID)) {
754  return getOverheadWireSegmentID();
755  } else if (key == toString(SUMO_ATTR_SUBSTATIONID)) {
756  return getTractionSubstationID();
757  } else if (key == toString(SUMO_ATTR_VEHICLEMASS)) {
758  WRITE_WARNING(TL("Getting the vehicle mass via parameters is deprecated, please use getMass for the vehicle or its type."));
760  }
761  throw InvalidArgument("Parameter '" + key + "' is not supported for device of type '" + deviceName() + "'");
762 }
763 
764 
765 double
766 MSDevice_ElecHybrid::getParameterDouble(const std::string& key) const {
767  if (key == toString(SUMO_ATTR_MAXIMUMPOWER)) {
769  } else if (key == toString(SUMO_ATTR_RECUPERATIONEFFICIENCY)) {
771  }
772  throw InvalidArgument("Parameter '" + key + "' is not supported for device of type '" + deviceName() + "'");
773 }
774 
775 
777  double energyCharged = energyIn - myConsum;
778  /*
779  Apply recuperation or propulsion efficiency if necessary
780  1. if (energyIn > 0.0 && energyCharged > 0 && it->getConsum() >= 0) = > recuper eff for energyCharged
781  2. if (energyIn > 0.0 && energyCharged > 0 && it->getConsum() < 0) => recuper eff only for energyIn
782  3. if (energyIn < 0.0 && it->getConsum() > 0) => 1/propulsion eff only for energyIn
783  4. if (energyIn < 0.0 && energyCharged < 0 && it->getConsum() < 0) => 1/propulsion eff only for energyCharged
784  */
785  if (energyIn > 0.0 && energyCharged > 0.0) {
786  // the vehicle is charging battery from overhead wire
787  if (myConsum >= 0) {
789  } else {
791  }
792  } else if (energyIn < 0.0 && energyCharged < 0.0) {
793  // the vehicle is recuperating energy into the overhead wire and discharging batterypack at the same time
794  if (myConsum >= 0) {
796  } else {
798  }
799  }
800  return energyCharged;
801 }
802 
803 double
805  return myConsum;
806 }
807 
808 void
809 MSDevice_ElecHybrid::setConsum(const double consumption) {
811 }
812 
813 void
815  myTotalEnergyWasted += energyWasted;
816 }
817 
818 double
820  return myEnergyCharged;
821 }
822 
823 void
825  myEnergyCharged = energyCharged;
826 }
827 
828 double
831 #ifdef HAVE_EIGEN
833  if (owc != nullptr) {
834  return owc->getAlphaBest() ;
835  }
836 #else
837  WRITE_ERROR(TL("Overhead wire solver is on, but the Eigen library has not been compiled in!"))
838 #endif
839  }
840  return NAN;
841 }
842 
843 double
845  if (veh_elem != nullptr) {
846  return veh_elem->getPowerWanted();
847  }
848  return NAN;
849 }
850 
851 double
853  return myCircuitCurrent;
854 }
855 
856 void
858  myCircuitCurrent = current;
859 }
860 
861 double
863  return myCircuitVoltage;
864 }
865 
866 void
868  myCircuitVoltage = voltage;
869 }
870 
871 std::string
873  if (myActOverheadWireSegment != nullptr) {
875  } else {
876  return "";
877  }
878 }
879 
880 std::string
882  if (myActOverheadWireSegment != nullptr) {
884  if (ts != nullptr) {
885  return ts->getID();
886  }
887  }
888  return "";
889 }
890 
891 bool
894 }
895 
896 double
898  // Original energy state of the battery pack
899  double previousEnergyInBattery = myActualBatteryCapacity;
900  // Push as much energy as the battery pack can accomodate.
901  // The battery has SOC limits that will prevent it from being overcharged, hence some energy may remain "free".
903  // The "free" energy that still remains and has to be stored elsewhere or burned on resistors is the difference.
904  return myActualBatteryCapacity - previousEnergyInBattery;
905 }
906 
907 void
908 MSDevice_ElecHybrid::setActualBatteryCapacity(const double actualBatteryCapacity) {
909  // Use the SOC limits to cap the actual battery capacity
910  if (actualBatteryCapacity < mySOCMin * myMaximumBatteryCapacity) {
911  //WRITE_WARNINGF(TL("The Battery of vehicle '%' has been exhausted."), getID());
913  } else if (actualBatteryCapacity > mySOCMax * myMaximumBatteryCapacity) {
915  } else {
916  myActualBatteryCapacity = actualBatteryCapacity;
917  }
918 }
919 
920 void
921 MSDevice_ElecHybrid::setParameter(const std::string& key, const std::string& value) {
922  double doubleValue;
923  try {
924  doubleValue = StringUtils::toDouble(value);
925  } catch (NumberFormatException&) {
926  throw InvalidArgument("Setting parameter '" + key + "' requires a number for device of type '" + deviceName() + "'");
927  }
929  myActualBatteryCapacity = doubleValue;
930  } else if (key == toString(SUMO_ATTR_MAXIMUMBATTERYCAPACITY)) {
931  myMaximumBatteryCapacity = doubleValue;
932  } else if (key == toString(SUMO_ATTR_OVERHEADWIRECHARGINGPOWER)) {
933  myOverheadWireChargingPower = doubleValue;
934  } else if (key == toString(SUMO_ATTR_VEHICLEMASS)) {
935  WRITE_WARNING(TL("Setting the vehicle mass via parameters is deprecated, please use setMass for the vehicle or its type."));
937  } else {
938  throw InvalidArgument("Setting parameter '" + key + "' is not supported for device of type '" + deviceName() + "'");
939  }
940 }
941 
942 double
943 MSDevice_ElecHybrid::acceleration(SUMOVehicle& veh, double power, double oldSpeed) {
946 }
947 
948 double
949 MSDevice_ElecHybrid::consumption(SUMOVehicle& veh, double a, double newSpeed) {
952 }
953 
954 
955 /****************************************************************************/
#define WATT2WATTHR(_x)
#define WATTHR2WATT(_x)
const double WIRE_RESISTIVITY
#define WRITE_WARNINGF(...)
Definition: MsgHandler.h:296
#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
SUMOTime DELTA_T
Definition: SUMOTime.cpp:38
#define ACCEL2SPEED(x)
Definition: SUMOTime.h:51
#define TS
Definition: SUMOTime.h:42
@ SUMO_TAG_OVERHEAD_WIRE_SEGMENT
An overhead wire segment.
@ SUMO_ATTR_MAXIMUMPOWER
Maximum Power.
@ SUMO_ATTR_ENERGYCONSUMED
Energy consumed.
@ SUMO_ATTR_SUBSTATIONID
id of a traction substation substation
@ SUMO_ATTR_MAXIMUMBATTERYCAPACITY
Maxium battery capacity.
@ SUMO_ATTR_MASS
@ SUMO_ATTR_RECUPERATIONEFFICIENCY
Recuperation efficiency (constant)
@ SUMO_ATTR_ANGLE
@ SUMO_ATTR_ACTUALBATTERYCAPACITY
@ SUMO_ATTR_VEHICLEMASS
Vehicle mass.
@ SUMO_ATTR_ENERGYCHARGED
tgotal of Energy charged
@ SUMO_ATTR_OVERHEADWIREID
@ SUMO_ATTR_PROPULSIONEFFICIENCY
Propulsion efficiency.
@ SUMO_ATTR_OVERHEADWIRECHARGINGPOWER
#define UNUSED_PARAMETER(x)
Definition: StdDefs.h:30
T MIN2(T a, T b)
Definition: StdDefs.h:76
T MAX2(T a, T b)
Definition: StdDefs.h:82
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition: ToString.h:46
double getAlphaBest()
return alphaBest variable, the best alpha scaling value
Definition: Circuit.h:127
Node * addNode(std::string name)
Definition: Circuit.cpp:42
Element * addElement(std::string name, double value, Node *pNode, Node *nNode, Element::ElementType et)
Definition: Circuit.cpp:787
void eraseNode(Node *node)
Definition: Circuit.cpp:62
int getLastId()
Definition: Circuit.h:240
Element * getElement(std::string name)
Definition: Circuit.cpp:116
Element * getVoltageSource(int id)
Definition: Circuit.cpp:139
Node * getNode(std::string name)
Definition: Circuit.cpp:98
void descreaseLastId()
Definition: Circuit.h:245
void eraseElement(Element *element)
Definition: Circuit.cpp:831
void setId(int id)
Definition: Element.cpp:133
double getResistance()
Definition: Element.cpp:99
void setCurrent(double current)
Definition: Element.cpp:63
double getPowerWanted()
Definition: Element.cpp:102
Node * getNegNode()
Definition: Element.cpp:115
std::string getName()
Definition: Element.cpp:122
void setPosNode(Node *node)
Definition: Element.cpp:126
Node * getPosNode()
Definition: Element.cpp:112
void setResistance(double resistance)
Definition: Element.cpp:66
void setPowerWanted(double powerWanted)
Definition: Element.cpp:73
An upper class for objects with additional parameters.
Definition: EnergyParams.h:43
double getDouble(SumoXMLAttr attr) const
void setDouble(SumoXMLAttr attr, double value)
Sets a parameter.
static double angleDiff(const double angle1, const double angle2)
Returns the difference of the second angle to the first angle in radiants.
Definition: GeomHelper.cpp:178
double compute(const SUMOEmissionClass c, const PollutantsInterface::EmissionType e, const double v, const double a, const double slope, const EnergyParams *param) const
Computes the emitted pollutant amount using the given speed and acceleration.
double acceleration(const SUMOEmissionClass c, const PollutantsInterface::EmissionType e, const double v, const double P, const double slope, const EnergyParams *param) const
Computes the achievable acceleration using the given speed and amount of consumed electric power.
A vehicle from the mesoscopic point of view.
Definition: MEVehicle.h:42
double getLastEntryTimeSeconds() const
Returns the entry time for the current segment.
Definition: MEVehicle.h:287
double getBlockTimeSeconds() const
Returns the time at which the vehicle was blocked on the current segment.
Definition: MEVehicle.h:292
double getAverageSpeed() const
Returns the vehicle's estimated average speed on the segment assuming no further delays.
Definition: MEVehicle.cpp:110
SUMOTime getWaitingTime(const bool accumulated=false) const
Returns the duration for which the vehicle was blocked.
Definition: MEVehicle.h:271
SUMOTime getLastEntryTime() const
Returns the time the vehicle entered the current segment.
Definition: MEVehicle.h:248
MESegment * getSegment() const
Returns the current segment the vehicle is on.
Definition: MEVehicle.h:218
double getSpeed() const
Returns the vehicle's estimated speed assuming no delays.
Definition: MEVehicle.cpp:100
A device which collects info on the vehicle trip (mainly on departure and arrival)
void setEnergyCharged(double energyCharged)
bool myCharging
Parameter, Flag: Vehicle is charging (by default is false)
MSDevice_ElecHybrid(SUMOVehicle &holder, const std::string &id, const double actualBatteryCapacity, const double maximumBatteryCapacity, const double overheadWireChargingPower)
Constructor.
void setCurrentFromOverheadWire(double current)
double myMaximumBatteryCapacity
Parameter, The total vehicles's Battery Capacity in Wh, [myMaximumBatteryCapacity >= 0].
double getCircuitAlpha() const
MSOverheadWire * myPreviousOverheadWireSegment
Parameter, Pointer to the act overhead wire segment in previous step (by default is nullptr),...
static void buildVehicleDevices(SUMOVehicle &v, std::vector< MSVehicleDevice * > &into)
Build devices for the given vehicle, if needed.
void deleteVehicleFromCircuit(SUMOVehicle &veh)
double getVoltageOfOverheadWire() const
Get actual voltage on the overhead wire segment.
double myEnergyCharged
Energy flowing into (+) or from (-) the battery pack in the given timestep.
bool notifyLeave(SUMOTrafficObject &tObject, double lastPos, MSMoveReminder::Notification reason, const MSLane *enteredLane=0)
Saves arrival info.
double mySOCMax
Maximal SOC of the battery pack, battery will not be charged above this level. (But the buffer may st...
double getMaximumBatteryCapacity() const
Get the total vehicle's Battery Capacity in kWh.
double consumption(SUMOVehicle &veh, double a, double newSpeed)
return energy consumption in Wh (power multiplied by TS)
double computeChargedEnergy(double energyIn)
compute charged energy properly considering recuperation and propulsion efficiency during charging ba...
double getParameterDouble(const std::string &key) const
double myTotalEnergyWasted
Energy that could not be stored back to the battery or traction station and was wasted on resistors....
void setConsum(const double consumption)
bool isBatteryDischarged() const
Get consum.
void generateOutput(OutputDevice *tripinfoOut) const
Called on writing tripinfo output.
double myConsum
Parameter, Vehicle consumption during a time step (by default is 0.)
void setActualBatteryCapacity(const double actualBatteryCapacity)
Set actual vehicle's Battery Capacity in kWh.
std::string getParameter(const std::string &key) const
try to retrieve the given parameter from this device. Throw exception for unsupported key
double acceleration(SUMOVehicle &veh, double power, double oldSpeed)
double storeEnergyToBattery(const double energy)
Attempt to store energy into battery pack and return the energy that could not be accomodated due to ...
void updateTotalEnergyWasted(const double energyWasted)
Add energyWasted to the total sum myTotalEnergyWasted.
double myLastAngle
Parameter, Vehicle's last angle.
double getCurrentFromOverheadWire() const
Get actual current in the overhead wire segment.
bool myBatteryDischargedLogic
Parameter, Flag: Battery of Vehicle is fully discharged (by default is false)
const std::string deviceName() const
return the name for this type of device
bool notifyMove(SUMOTrafficObject &tObject, double oldPos, double newPos, double newSpeed)
Checks for waiting steps when the vehicle moves.
double myOverheadWireChargingPower
Parameter, overhead wire charging power to battery, if the battery SoC is not full (in Watt)
void setVoltageOfOverheadWire(double voltage)
static void insertOptions(OptionsCont &oc)
Inserts MSDevice_ElecHybrid-options.
MSOverheadWire * myActOverheadWireSegment
Parameter, Pointer to the actual overhead wire segment in which vehicle is placed (by default is null...
double myActualBatteryCapacity
Parameter, The actual vehicles's Battery Capacity in Wh, [myActualBatteryCapacity <= myMaximumBattery...
double getEnergyCharged() const
Get charged energy.
std::string getTractionSubstationID() const
Get actual traction substationn ID.
virtual void notifyMoveInternal(const SUMOTrafficObject &tObject, const double frontOnLane, const double timeOnLane, const double meanSpeedFrontOnLane, const double meanSpeedVehicleOnLane, const double travelledDistanceFrontOnLane, const double travelledDistanceVehicleOnLane, const double meanLengthOnLane)
Internal notification about the vehicle moves.
bool notifyEnter(SUMOTrafficObject &tObject, MSMoveReminder::Notification reason, const MSLane *enteredLane=0)
Saves departure info on insertion.
double getActualBatteryCapacity() const
Get the actual vehicle's Battery Capacity in kWh.
double getConsum() const
Get consum.
double myCircuitCurrent
Parameter, Current wanted at overhead wire in next timestep.
std::string getOverheadWireSegmentID() const
Get actual overhead wire segment ID.
void setParameter(const std::string &key, const std::string &value)
try to set the given parameter for this device. Throw exception for unsupported key
static void insertDefaultAssignmentOptions(const std::string &deviceName, const std::string &optionsTopic, OptionsCont &oc, const bool isPerson=false)
Adds common command options that allow to assign devices to vehicles.
Definition: MSDevice.cpp:155
static bool equippedByDefaultAssignmentOptions(const OptionsCont &oc, const std::string &deviceName, DEVICEHOLDER &v, bool outputOptionSet, const bool isPerson=false)
Determines whether a vehicle should get a certain device.
Definition: MSDevice.h:203
MSLane * leftLane(const MSLane *const lane) const
Returns the lane left to the one given, 0 if the given lane is leftmost.
Definition: MSEdge.cpp:445
MSLane * rightLane(const MSLane *const lane) const
Returns the lane right to the one given, 0 if the given lane is rightmost.
Definition: MSEdge.cpp:451
static bool gUseMesoSim
Definition: MSGlobals.h:103
static bool gOverheadWireRecuperation
Definition: MSGlobals.h:121
static bool gOverheadWireSolver
Definition: MSGlobals.h:118
Representation of a lane in the micro simulation.
Definition: MSLane.h:84
double getLength() const
Returns the lane's length.
Definition: MSLane.h:598
Notification
Definition of a vehicle state.
@ NOTIFICATION_TELEPORT
The vehicle is being teleported.
static MSNet * getInstance()
Returns the pointer to the unique instance of MSNet (singleton).
Definition: MSNet.cpp:182
std::string getStoppingPlaceID(const MSLane *lane, const double pos, const SumoXMLTag category) const
Returns the stop of the given category close to the given position.
Definition: MSNet.cpp:1373
MSStoppingPlace * getStoppingPlace(const std::string &id, const SumoXMLTag category) const
Returns the named stopping place of the given category.
Definition: MSNet.cpp:1364
Definition of overhead wire segment.
Circuit * getCircuit() const
void addChargeValueForOutput(double WCharged, MSDevice_ElecHybrid *elecHybrid, bool ischarging=1)
add charge value for output
MSTractionSubstation * getTractionSubstation() const
void eraseVehicle(SUMOVehicle &veh)
void addVehicle(SUMOVehicle &veh)
const MSLane & getLane() const
Returns the lane this stop is located at.
Traction substaction powering one or more overhead wire sections.
void eraseVehicle(MSDevice_ElecHybrid *elecHybrid)
double getSubstationVoltage() const
void addSolvingCirucitToEndOfTimestepEvents()
void addVehicle(MSDevice_ElecHybrid *elecHybrid)
Abstract in-vehicle device.
SUMOVehicle & myHolder
The vehicle that stores the device.
Representation of a vehicle in the micro simulation.
Definition: MSVehicle.h:77
const SUMOVTypeParameter & getParameter() const
const std::string & getID() const
Returns the id.
Definition: Named.h:74
Definition: Node.h:39
int getId()
Definition: Node.cpp:77
void addElement(Element *element)
Definition: Node.cpp:44
void eraseElement(Element *element)
Definition: Node.cpp:48
void setId(int id)
Definition: Node.cpp:81
std::vector< Element * > * getElements()
Definition: Node.cpp:101
A storage for options typed value containers)
Definition: OptionsCont.h:89
void addOptionSubTopic(const std::string &topic)
Adds an option subtopic.
static OptionsCont & getOptions()
Retrieves the options.
Definition: OptionsCont.cpp:60
Static storage of an output device and its base (abstract) implementation.
Definition: OutputDevice.h:61
OutputDevice & openTag(const std::string &xmlElement)
Opens an XML tag.
OutputDevice & writeAttr(const SumoXMLAttr attr, const T &val)
writes a named attribute
Definition: OutputDevice.h:254
bool closeTag(const std::string &comment="")
Closes the most recently opened tag and optionally adds a comment.
bool hasParameter(const std::string &key) const
Returns whether the parameter is set.
double getDouble(const std::string &key, const double defaultValue) const
Returns the value for a given key converted to a double.
virtual const std::string getParameter(const std::string &key, const std::string defaultValue="") const
Returns the value for a given key.
static const HelpersEnergy & getEnergyHelper()
get energy helper
Representation of a vehicle, person, or container.
virtual bool isVehicle() const
Whether it is a vehicle.
virtual double getSlope() const =0
Returns the slope of the road at object's position in degrees.
virtual double getSpeed() const =0
Returns the object's current speed.
virtual const MSVehicleType & getVehicleType() const =0
Returns the object's "vehicle" type.
virtual const SUMOVehicleParameter & getParameter() const =0
Returns the vehicle's parameter (including departure definition)
virtual const MSLane * getLane() const =0
Returns the lane the object is currently at.
virtual const MSEdge * getEdge() const =0
Returns the edge the object is currently at.
virtual double getPositionOnLane() const =0
Get the object's position along the lane.
Structure representing possible vehicle parameter.
Representation of a vehicle.
Definition: SUMOVehicle.h:60
virtual double getAngle() const =0
Get the vehicle's angle.
virtual EnergyParams * getEmissionParameters() const =0
Returns the vehicle's emission model parameter.
Structure representing possible vehicle parameter.
static double toDouble(const std::string &sData)
converts a string into the double value described by it by calling the char-type converter
NLOHMANN_BASIC_JSON_TPL_DECLARATION std::string to_string(const NLOHMANN_BASIC_JSON_TPL &j)
user-defined to_string function for JSON values
Definition: json.hpp:21838