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.org/sumo
3 // Copyright (C) 2002-2022 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_ElecHybrid.h"
44 
45 
46 // ===========================================================================
47 // method definitions
48 // ===========================================================================
49 // ---------------------------------------------------------------------------
50 // static initialisation methods
51 // ---------------------------------------------------------------------------
52 void
54  oc.addOptionSubTopic("ElecHybrid Device");
55  insertDefaultAssignmentOptions("elechybrid", "ElecHybrid Device", oc);
56 }
57 
58 
59 void
60 MSDevice_ElecHybrid::buildVehicleDevices(SUMOVehicle& v, std::vector<MSVehicleDevice*>& into) {
61  // Check if vehicle should get an 'elecHybrid' device.
63  if (equippedByDefaultAssignmentOptions(oc, "elechybrid", v, false)) {
64  // Yes, build the device.
65  // Fetch the battery capacity (if present) from the vehicle descriptor.
66  const SUMOVTypeParameter& typeParams = v.getVehicleType().getParameter();
67  const SUMOVehicleParameter& vehicleParams = v.getParameter();
68  double actualBatteryCapacity = 0;
69  /* The actual battery capacity can be a parameter of the vehicle or its vehicle type.
70  The vehicle parameter takes precedence over the type parameter. */
71  std::string attrName = toString(SUMO_ATTR_ACTUALBATTERYCAPACITY);
72  if (vehicleParams.knowsParameter(attrName)) {
73  const std::string abc = vehicleParams.getParameter(attrName, "-1");
74  try {
75  actualBatteryCapacity = StringUtils::toDouble(abc);
76  } catch (...) {
77  WRITE_WARNING("Invalid value '" + abc + "'for vehicle parameter '" + attrName + "'. Using the default of " + std::to_string(actualBatteryCapacity));
78  }
79  } else {
80  if (typeParams.knowsParameter(attrName)) {
81  const std::string abc = typeParams.getParameter(attrName, "-1");
82  try {
83  actualBatteryCapacity = StringUtils::toDouble(abc);
84  WRITE_WARNING("Vehicle '" + v.getID() + "' does not provide vehicle parameter '" + attrName + "'. Using the vehicle type value of " + std::to_string(actualBatteryCapacity));
85  } catch (...) {
86  WRITE_WARNING("Invalid value '" + abc + "'for vehicle type parameter '" + attrName + "'. Using the default of " + std::to_string(actualBatteryCapacity));
87  }
88  } else {
89  WRITE_WARNING("Vehicle '" + v.getID() + "' does not provide vehicle or vehicle type parameter '" + attrName + "'. Using the default of " + std::to_string(actualBatteryCapacity));
90  }
91  }
92 
93  // obtain maximumBatteryCapacity
94  double maximumBatteryCapacity = 0;
96  if (typeParams.knowsParameter(attrName)) {
97  const std::string mbc = typeParams.getParameter(attrName, "-1");
98  try {
99  maximumBatteryCapacity = StringUtils::toDouble(mbc);
100  } catch (...) {
101  WRITE_WARNING("Invalid value '" + mbc + "'for vType parameter '" + attrName + "'");
102  }
103  } else {
104  WRITE_WARNING("Vehicle '" + v.getID() + "' is missing the vType parameter '" + attrName + "'. Using the default of " + std::to_string(maximumBatteryCapacity));
105  }
106 
107  // obtain overheadWireChargingPower
108  double overheadWireChargingPower = 0;
110  if (typeParams.knowsParameter(attrName)) {
111  const std::string ocp = typeParams.getParameter(attrName, "-1");
112  try {
113  overheadWireChargingPower = StringUtils::toDouble(ocp);
114  } catch (...) {
115  WRITE_WARNING("Invalid value '" + ocp + "'for vType parameter '" + attrName + "'");
116  }
117  } else {
118  WRITE_WARNING("Vehicle '" + v.getID() + "' is missing the vType parameter '" + attrName + "'. Using the default of " + std::to_string(overheadWireChargingPower));
119  }
120 
121  EnergyParams param(&typeParams);
122 
124 
125  // elecHybrid constructor
126  MSDevice_ElecHybrid* device = new MSDevice_ElecHybrid(v, "elecHybrid_" + v.getID(),
127  actualBatteryCapacity, maximumBatteryCapacity, overheadWireChargingPower, param);
128 
129  // Add device to vehicle
130  into.push_back(device);
131  }
132 }
133 
134 
135 // ---------------------------------------------------------------------------
136 // MSDevice_ElecHybrid-methods
137 // ---------------------------------------------------------------------------
139  const double actualBatteryCapacity, const double maximumBatteryCapacity, const double overheadWireChargingPower, const EnergyParams& param) :
140  MSVehicleDevice(holder, id),
141  myActualBatteryCapacity(0), // [actualBatteryCapacity <= maximumBatteryCapacity]
142  myMaximumBatteryCapacity(0), // [maximumBatteryCapacity >= 0]t
143  myOverheadWireChargingPower(0),
144  myParam(param),
145  myLastAngle(NAN),
146  myConsum(0),
147  myBatteryDischargedLogic(false),
148  myCharging(false), // Initially vehicle don't charge
149  myEnergyCharged(0), // Initially the energy charged is zero
150  myCircuitCurrent(NAN), // Initially the current is unknown
151  myCircuitVoltage(NAN), // Initially the voltage is unknown as well
152  myMaxBatteryCharge(NAN), // Initial maximum of the the battery energy during the simulation is unknown
153  myMinBatteryCharge(NAN), // Initial minimum of the the battery energy during the simulation is unknown
154  myTotalEnergyConsumed(0), // No energy spent yet
155  myTotalEnergyRegenerated(0), // No energy regenerated
156  myTotalEnergyWasted(0), // No energy wasted on resistors
157  // RICE_TODO: make these two parameters user configurable
158  mySOCMin(0.005), // Minimum SOC of the battery
159  mySOCMax(0.980), // Maximum SOC of the battery
160  myActOverheadWireSegment(nullptr), // Initially the vehicle isn't under any overhead wire segment
161  myPreviousOverheadWireSegment(nullptr), // Initially the vehicle wasn't under any overhead wire segment
162  veh_elem(nullptr),
163  veh_pos_tail_elem(nullptr),
164  pos_veh_node(nullptr) {
165  if (maximumBatteryCapacity < 0) {
166  WRITE_WARNING("ElecHybrid builder: Vehicle '" + getID() + "' doesn't have a valid value for parameter " + 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_WARNING("ElecHybrid builder: Vehicle '" + getID() + "' doesn't have a valid value for parameter " + toString(SUMO_ATTR_OVERHEADWIRECHARGINGPOWER) + " (" + toString(overheadWireChargingPower) + ").")
180  } else {
181  myOverheadWireChargingPower = overheadWireChargingPower;
182  }
183 
195 }
196 
198 }
199 
200 bool
201 MSDevice_ElecHybrid::notifyMove(SUMOTrafficObject& tObject, double /* oldPos */, double /* newPos */, double /* newSpeed */) {
202  if (!tObject.isVehicle()) {
203  return false;
204  }
205  SUMOVehicle& veh = static_cast<SUMOVehicle&>(tObject);
206  // Do not compute the current consumption here anymore:
207  // myConsum is (non-systematically, we agree) set in MSVehicle so that the vehicle `vNext` value can
208  // be influenced by the maximum traction power of the vehicle (i.e. installing a 80 kWh powertrain will
209  // limit the acceleration regardless of the acceleration specified in vehicleType params, in case that
210  // the vehicleType acceleration is too high).
211  //
212  // myParam[SUMO_ATTR_ANGLE] = myLastAngle == std::numeric_limits<double>::infinity() ? 0. : GeomHelper::angleDiff(myLastAngle, veh.getAngle());
213  // myConsum = PollutantsInterface::getEnergyHelper().compute(0, PollutantsInterface::ELEC, veh.getSpeed(), veh.getAcceleration(), veh.getSlope(), &myParam);
214  assert(!ISNAN(myConsum));
215 
216  // is battery pack discharged (from previous timestep)
219  } else {
220  myBatteryDischargedLogic = false;
221  }
222 
223  /* If baterry is discharged we will force the vehicle to slowly come to
224  a halt (freewheel motion). It could still happen that some energy will
225  be recovered in later steps due to regenerative braking. */
226  if (isBatteryDischarged()) {
227  std::vector<std::pair<SUMOTime, double> > speedTimeLine;
231  double accel = acceleration(veh, 0, veh.getSpeed()); // or use veh.getAcceleration() method???
232  const double nextSpeed = MAX2(0., veh.getSpeed() + ACCEL2SPEED(accel));
233  speedTimeLine.push_back(
234  std::make_pair(
235  MSNet::getInstance()->getCurrentTimeStep(),
236  veh.getSpeed()));
237  speedTimeLine.push_back(
238  std::make_pair(
239  MSNet::getInstance()->getCurrentTimeStep() + DELTA_T,
240  nextSpeed));
241 
242  static_cast<MSVehicle*>(&veh)->getInfluencer().setSpeedTimeLine(speedTimeLine);
243  }
244 
245  /* Check if there is an overhead wire either over the lane where the vehicle is or over a
246  neighbouring lanes. This check has to be performed at every simulation step as the
247  overhead wires for trolleybuses will typically end at a bus stop that is located somewhere
248  in the middle of the lane. */
249  std::string overheadWireSegmentID = MSNet::getInstance()->getStoppingPlaceID(veh.getLane(), veh.getPositionOnLane(), SUMO_TAG_OVERHEAD_WIRE_SEGMENT);
250 
251  //check overhead line on the left neighbouring lane
252  if (overheadWireSegmentID == "" && veh.getEdge()->leftLane(veh.getLane()) != nullptr) {
254  }
255  //check overhead line on the right neighbouring lane
256  if (overheadWireSegmentID == "" && veh.getEdge()->rightLane(veh.getLane()) != nullptr) {
258  }
259 
260  /* Store the amount of power that could not be recuperated. */
261  double energyWasted = 0.0;
262  /* If vehicle has access to an overhead wire (including the installation on neighbouring lanes) */
263  if (overheadWireSegmentID != "") {
264  /* Update the actual overhead wire segment of this device */
266  static_cast<MSOverheadWire*>(MSNet::getInstance()->getStoppingPlace(overheadWireSegmentID, SUMO_TAG_OVERHEAD_WIRE_SEGMENT));
267  /* Store the traction substation of the actual overhead wire segment */
269 
270  /* Disable charging from previous (not the actual) overhead wire segment.
271  REASON:
272  If there is no gap between two different overhead wire segments that are
273  places on the same lane, the vehicle switches from the one segment to another
274  in one timestep. */
276  if (myPreviousOverheadWireSegment != nullptr) {
277  /* Remove the vehicle from the list of vehicles powered by the previous segment. */
280  if (ts != nullptr) {
282  ts->eraseVehicle(this);
283  }
284  }
285  /* Add the vehicle reference to the current segment. */
287  if (actualSubstation != nullptr) {
288  actualSubstation->increaseElecHybridCount();
289  actualSubstation->addVehicle(this);
290  }
291  }
292 
293  /* Do we simulate the behaviour of the overhead wire electric circuit? */
295 #ifdef HAVE_EIGEN
297  /* Circuit update due to vehicle movement:
298  Delete vehicle resistor element, vehicle resistor nodes and vehicle resistor
299  tails in the circuit used in the previous timestep. */
301 
302  /* Add the vehicle to the circuit in case that there is a substation that provides
303  power to it. */
304  if (actualSubstation != nullptr) {
305  /* Add a resistor (current source in the future?) representing trolleybus
306  vehicle to the circuit.
307  pos/neg_veh_node elements
308  [0] .... vehicle_resistor
309  [1] .... leading resistor
310  [2] .... tail resistor pos/neg_tail_vehID
311  */
312 
313  // pos_veh_node and veh_elem shoud be NULL
314  if (pos_veh_node != nullptr || veh_elem != nullptr) {
315  WRITE_WARNING("pos_veh_node or neg_veh_node or veh_elem is not NULL (and they shoud be at the beginning of adding elecHybrid to the circuit)");
316  }
317 
318  // create pos and veh_elem
320  pos_veh_node = owc->addNode("pos_" + veh.getID());
321  assert(pos_veh_node != nullptr);
322  // 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.
323  veh_elem = owc->addElement("currentSrc" + veh.getID(), NAN,
324  pos_veh_node, owc->getNode("negNode_ground"),
325  Element::ElementType::CURRENT_SOURCE_traction_wire);
326 
327  // Connect vehicle to an existing overhead wire segment = add elecHybridVehicle to the myActOverheadWireSegment circuit
328  // Find pos resistor element of the actual overhead line section and their end nodes
329  Element* element_pos = owc->getElement("pos_" + myActOverheadWireSegment->getID());
330  Node* node_pos = element_pos->getNegNode();
331  double resistance = element_pos->getResistance();
332 
333  /* Find the correct position of the vehicle at the overhead line.
334  We start the while loop at the end of the actual overhead line section and go against the direction of vehicle movement.
335  The decision rule is based on the resistance value:
336  * from the vehicle position to the end of lane,
337  * sum of resistance of elements (going from the end of ovehead line section in the contrary direction).
338 
339  The original solution runs into problems when a vehicle is going on a neigboring lane and the two lanes have different lengths:
340  while (resistance < (veh.getLane()->getLength() - veh.getPositionOnLane())*WIRE_RESISTIVITY) {
341  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.)
342  */
343  double relativePosOnSegment =
345  (veh.getPositionOnLane() / veh.getLane()->getLength()));
346 
347  while (resistance < relativePosOnSegment * WIRE_RESISTIVITY) {
348  node_pos = element_pos->getPosNode();
349  element_pos = node_pos->getElements()->at(2);
350  resistance += element_pos->getResistance();
351  if (strncmp(element_pos->getName().c_str(), "pos_tail_", 9) != 0) {
352  WRITE_WARNING("splitting element is not 'pos_tail_XXX'")
353  }
354  }
355 
356  node_pos = element_pos->getPosNode();
357  //resistance of vehicle tail nodes
358  resistance -= relativePosOnSegment * WIRE_RESISTIVITY;
359 
360  /* dividing element_pos
361  before: |node_pos|---------------------------------------------|element_pos|----
362  after: |node_pos|----|veh_pos_tail_elem|----|pos_veh_node|----|element_pos|----
363  */
364  element_pos->setPosNode(pos_veh_node);
365  node_pos->eraseElement(element_pos);
366  pos_veh_node->addElement(element_pos);
367 
368  veh_pos_tail_elem = owc->addElement("pos_tail_" + veh.getID(),
369  resistance, node_pos, pos_veh_node, Element::ElementType::RESISTOR_traction_wire);
370 
371  if (element_pos->getResistance() - resistance < 0) {
372  WRITE_WARNING("The resistivity of overhead wire segment connected to vehicle " + veh.getID() + " is < 0. Set to 1e-6.");
373  }
374 
375  element_pos->setResistance(element_pos->getResistance() - resistance);
376 
377 
378  // Set the power requirement to the consumption + charging power.
379  // RICE_TODO: The charging power could be different when moving and when not. Add a parameter.
380  // Note that according to PMDP data, the charging power seems to be the same in both situations,
381  // ignoreing the potential benefits of using a higher charging power when the vehicle is moving.
384  } else {
386  }
387 
388  // No recuperation to overheadwire (only to the batterypack)
390  // the value of energyWasted is properly computed and updated after solving circuit by the solver
391  // energyWasted = 0;
392  veh_elem->setPowerWanted(0.0);
393  }
394 
395  // RICE_TODO: The voltage in the solver should never exceed or drop below some limits. Maximum allowed voltage is typicallty 800 V.
396  // The numerical solver that computes the circuit state needs initial values of electric currents and
397  // voltages from which it will start the iterative solving process. We prefer to reuse the "old" values
398  // as it is likely that the new values will not be far away from the old ones. The safety limits of
399  // 10 and 1500 Volts that are used below are chosen fairly arbitrarily to keep the initial values within
400  // reasonable limits.
401  double voltage = myCircuitVoltage;
402  if (voltage < 10.0 || voltage > 1500.0 || ISNAN(voltage)) {
403  // RICE_TODO : It seems to output warning whenever a vehicle is appearing under the overhead wire for the first time?
404  // WRITE_WARNING("The initial voltage is was " + toString(voltage) + " V, replacing it with substation voltage " + toString(actualSubstation->getSubstationVoltage()) + " V.");
405  voltage = actualSubstation->getSubstationVoltage();
406  }
407  // Initial value of the electric current flowing into the vehilce that will be used by the solver
408  double current = -(veh_elem->getPowerWanted() / voltage);
409  veh_elem->setCurrent(current);
410 
411  // Set the device as charging the battery by default
412  myCharging = true;
413 
414  // And register the call to solver at the end of the simulation step
415  actualSubstation->addSolvingCirucitToEndOfTimestepEvents();
416  } else {
417  /*
418  No substation on this wire ...
419  */
420  // 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,
421 
422  // Energy flowing to/from the battery pack [Wh] has to completely cover vehicle consumption.
424  // Update Battery charge
426  // No substation is connected to this segmenr and the charging output is therefore zero.
428  }
429 #else
430  WRITE_ERROR("Overhead wire solver is on, but the Eigen library has not been compiled in!")
431 #endif
432  } else {
433  /*
434  Faster approximaion without circuit solving at every simulation step.
435  */
436 
437  // First check that there is a traction substation connected to the overhead wire
438  double voltage = 0.0;
439  if (actualSubstation != nullptr) {
440  voltage = actualSubstation->getSubstationVoltage();
441  }
442 
443  // At this point the volate can be (a) NAN if the substation voltage was not specified,
444  // (b) 0 if no substation powers the current segment or if someone put its power to zero,
445  // (c) >0 if the substation can provide energy to the circuit.
446  if (voltage > 0.0) {
447  // There is a power source connected to this segment.
448  // Set the simplified power requirement to the consumption + charging power.
449  // RICE_TODO: The charging power could be different when moving and when not. Add a parameter. See a similar code snippet above.
450  // Note that according to PMDP data, the charging power seems to be the same in both situations,
451  // ignoreing the potential benefits of using a higher charging power when the vehicle is moving.
452  double powerWanted = WATTHR2WATT(myConsum);
454  // Additional `myOverheadWireChargingPower` due to charging of battery pack
455  powerWanted += myOverheadWireChargingPower;
456  }
457 
458  // No recuperation to overhead wire (only to the battery pack)
459  // RICE_TODO: How to recuperate into the circuit without solver? (energy balance?)
460  // - solution: assume, that any power is possible to recuperate
461  if (!MSGlobals::gOverheadWireRecuperation && powerWanted < 0.0) {
462  // the value of energyWasted is properly computed and updated below
463  powerWanted = 0.0;
464  }
465 
466  // Set the actual current and voltage of the global circuit
467  // RICE_TODO: Process the traction stataion current limiting here as well.
468  myCircuitCurrent = powerWanted / voltage;
469  myCircuitVoltage = voltage;
470 
471  // Calulate energy charged
472  double energyIn = WATT2WATTHR(powerWanted);
473 
474  // Calulate energy flowing to/from the battery in this step [Wh]
475  // RICE_TODO: It should be possible to define different efficiency values for direction overhead wire -> battery; motor -> battery.
476  // We use a simplification here. The biggest contributor to the total losses is the battery pack itself
477  // (the input LC filter is probably more efficient -- eta_LC ~ 0.99 -- compared to the induction motor
478  // with eta_motor ~ 0.95).
480 
481  // Update the energy that has been stored in the battery pack and return the real energy charged in this step
482  // considering SOC limits of the battery pack.
483  double realEnergyCharged = storeEnergyToBattery(myEnergyCharged);
484  // Set energy wasted
485  energyWasted = myEnergyCharged - realEnergyCharged;
486 
487  // Add the energy provided by the overhead wire segment to the output of the segment
489  } else {
490  /*
491  Overhead wire without a connected substation
492  */
493  // 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,
494 
495  // Energy for the powertrain is provided by the battery pack
497  // Update battery charge
499  // No energy was provided by the overhead wire segment
501  }
502  }
503  assert(myActOverheadWireSegment != nullptr);
505  } else {
506  /*
507  No overhead wires, no charging.
508  */
509 
510  // Disable charing flag
511  myCharging = false;
512 
513  // Invalidate the circuit voltage and current
514  myCircuitCurrent = NAN;
515  myCircuitVoltage = NAN;
516 
517  // Additional bookkeeping in case that the circuit solver is used
519 #ifdef HAVE_EIGEN
520  /*
521  Delete vehicle resistor element, vehicle resistor nodes and vehicle resistor tails
522  in the previous circuit (i.e. the circuit used in the previous timestep)
523  */
525 #else
526  WRITE_ERROR("Overhead wire solver is on, but the Eigen library has not been compiled in!")
527 #endif
528  }
529 
530  // Vehicle is not under an overhead wire
531  myActOverheadWireSegment = nullptr;
532 
533  // Remove the vehicle from overhead wire if it was under it in the previous step.
534  // This has to be called afer deleteVehicleFromCircuit() as the file uses myPreviousOverheadWire.
535  if (myPreviousOverheadWireSegment != nullptr) {
538  if (ts != nullptr) {
540  ts->eraseVehicle(this);
541  }
543  }
544 
545  // Energy for the powertrain is provided by the battery pack
547  // Update battery charge
549  }
550 
551  // Update the statistical values
552  // RICE_TODO: update these statistical values also after solving circuit by electric circuit
555  }
558  }
559 
560  if (myConsum > 0.0) {
562  } else {
564  }
565  myTotalEnergyWasted += energyWasted;
566 
567  myLastAngle = veh.getAngle();
568  return true; // keep the device
569 }
570 
571 // Note: This is called solely in the mesoscopic mode to mimic the `notifyMove()` reminder
572 void
574  const SUMOTrafficObject& tObject,
575  const double frontOnLane,
576  const double timeOnLane,
577  const double meanSpeedFrontOnLane,
578  const double meanSpeedVehicleOnLane,
579  const double travelledDistanceFrontOnLane,
580  const double travelledDistanceVehicleOnLane,
581  const double meanLengthOnLane) {
582  UNUSED_PARAMETER(tObject);
583  UNUSED_PARAMETER(frontOnLane);
584  UNUSED_PARAMETER(timeOnLane);
585  UNUSED_PARAMETER(meanSpeedFrontOnLane);
586  UNUSED_PARAMETER(meanSpeedVehicleOnLane);
587  UNUSED_PARAMETER(travelledDistanceFrontOnLane);
588  UNUSED_PARAMETER(travelledDistanceVehicleOnLane);
589  UNUSED_PARAMETER(meanLengthOnLane);
590 }
591 
592 void
594  if (myPreviousOverheadWireSegment != nullptr) {
596  //check if all pointers to vehicle elements and nodes are not nullptr
597  if (veh_elem == nullptr || veh_pos_tail_elem == nullptr || pos_veh_node == nullptr) {
598  WRITE_ERROR("During deleting vehicle '" + veh.getID() + "' from circuit some init previous Nodes or Elements was not assigned.");
599  }
600  //check if pos_veh_node has 3 elements - they shoud be: veh_elem, veh_pos_tail_elem and an overhead line resistor element "ahead" of vehicle.
601  if (pos_veh_node->getElements()->size() != 3) {
602  WRITE_ERROR("During deleting vehicle '" + veh.getID() + "' from circuit the size of element-vector of pNode or nNode was not 3. It should be 3 by Jakub's opinion.");
603  }
604  //delete vehicle resistor element "veh_elem" in the previous circuit,
607  delete veh_elem;
608  veh_elem = nullptr;
609 
610  //eraising of tail elements (the element connected to the veh_node is afterthen only the ahead overhead line resistor element)
612 
613  if (pos_veh_node->getElements()->size() != 1) {
614  WRITE_ERROR("During deleting vehicle '" + veh.getID() + "' from circuit the size of element-vector of pNode or nNode was not 1. It should be 1 by Jakub's opinion.");
615  }
616 
617  // add the resistance value of veh_tail element to the resistance value of the ahead overhead line element
618  pos_veh_node->getElements()->front()->setResistance(pos_veh_node->getElements()->front()->getResistance() + veh_pos_tail_elem->getResistance());
619  //set PosNode of the ahead overhead line element to the posNode value of tail element
620  Element* aux = pos_veh_node->getElements()->front();
621  //set node = 3 operations
623  aux->getPosNode()->eraseElement(aux);
625 
626  // erase tail element from its PosNode
628  // delete veh_pos_tail_elem
630  delete veh_pos_tail_elem;
631  veh_pos_tail_elem = nullptr;
632 
633  //erase pos_veh_node
635  //modify id of other elements (the id of erasing element shoud be the greatest)
636  int lastId = myPreviousOverheadWireSegment->getCircuit()->getLastId() - 1;
637  if (pos_veh_node->getId() != lastId) {
638  Node* node_last = myPreviousOverheadWireSegment->getCircuit()->getNode(lastId);
639  if (node_last != nullptr) {
640  node_last->setId(pos_veh_node->getId());
641  } else {
643  if (elem_last != nullptr) {
644  elem_last->setId(pos_veh_node->getId());
645  } else {
646  WRITE_ERROR("The element or node with the last Id was not found in the circuit!");
647  }
648  }
649  }
651  delete pos_veh_node;
652  pos_veh_node = nullptr;
653  }
654  }
655 }
656 
657 bool
659  SUMOTrafficObject& tObject,
660  MSMoveReminder::Notification /* reason */,
661  const MSLane* /* enteredLane */) {
662  if (!tObject.isVehicle()) {
663  return false;
664  }
665 #ifdef ELECHYBRID_MESOSCOPIC_DEBUG
666  SUMOVehicle& veh = static_cast<SUMOVehicle&>(tObject);
667  std::cout << "device '" << getID() << "' notifyEnter: reason=" << reason << " currentEdge=" << veh.getEdge()->getID() << "\n";
668 #endif
669 
670  return true; // keep the device
671 }
672 
673 bool
675  SUMOTrafficObject& tObject,
676  double /*lastPos*/,
678  const MSLane* /* enteredLane */) {
679  if (!tObject.isVehicle()) {
680  return false;
681  }
682  SUMOVehicle& veh = static_cast<SUMOVehicle&>(tObject);
683 #ifdef ELECHYBRID_MESOSCOPIC_DEBUG
684  SUMOVehicle& veh = static_cast<SUMOVehicle&>(tObject);
685  std::cout << "device '" << getID() << "' notifyLeave: reason=" << reason << " currentEdge=" << veh.getEdge()->getID() << "\n";
686  SUMOVehicle* sumoVehicle = *veh;
688  MEVehicle& v = dynamic_cast<MEVehicle&>(veh);
689  std::cout << "***************** MESO - notifyLeave*** START ****************** '" << v.getID() << "' \n";
690  //TODO the second argument of getStoptime should change
691  std::cout << "getSpeed: '" << v.getSpeed() << "' | getAverageSpeed: '" << v.getAverageSpeed() << "' | getStoptime: '" << v.getStoptime(v.getSegment(), 0) << "' \n";
692  std::cout << "getStopEdges: '" << "' | getLastEntryTime: '" << v.getLastEntryTime() << "' | getBlockTimeSeconds: '" << v.getBlockTimeSeconds() << "' \n";
693  std::cout << "getWaitingTime: '" << v.getWaitingTime() << "' | getAccumulatedWaitingTime: '" << v.getAccumulatedWaitingTime() << "' | getLastEntryTimeSeconds: '" << v.getLastEntryTimeSeconds() << "' \n";
694  std::cout << "***************** MESO - notifyLeave*** END ****************** '" << v.getID() << "' \n";
695  }
696 #endif
697 
698  // The MSMoveReminders are sorted so that we can do `<`. See also BTreceiver and BTsender devices...
700  return true;
701  }
702 
704 #ifdef HAVE_EIGEN
705  // ------- *** ------- delete vehicle resistor element, vehicle resistor nodes and vehicle resistor tails in the previous circuit (circuit used in the previous timestep)------- *** -------
707 #else
708  UNUSED_PARAMETER(veh);
709  WRITE_ERROR("Overhead wire solver is on, but the Eigen library has not been compiled in!")
710 #endif
711  }
712  // disable charging vehicle from overhead wire and segment and traction station
713  if (myPreviousOverheadWireSegment != nullptr) {
716  if (prevSubstation != nullptr) {
717  prevSubstation->decreaseElecHybridCount();
718  prevSubstation->eraseVehicle(this);
719  }
721  }
722  return true;
723 }
724 
725 void
727  const SumoXMLAttr paramKey,
728  const double lower,
729  const double upper) {
730  if (!myParam.knowsParameter(paramKey)
731  || myParam.getDouble(paramKey) < lower
732  || myParam.getDouble(paramKey) > upper) {
733  WRITE_WARNING("ElecHybrid builder: Vehicle '" + getID() + "' doesn't have a valid value for parameter " + toString(paramKey) + " (" + toString(myParam.getDouble(paramKey)) + ").");
734  myParam.setDouble(paramKey, PollutantsInterface::getEnergyHelper().getDefaultParam(paramKey));
735  }
736 }
737 
738 
739 void
741  if (tripinfoOut != nullptr) {
742  // Write the summary elecHybrid information into tripinfo output
743  tripinfoOut->openTag("elechybrid");
744  tripinfoOut->writeAttr("maxBatteryCharge", myMaxBatteryCharge);
745  tripinfoOut->writeAttr("minBatteryCharge", myMinBatteryCharge);
746  tripinfoOut->writeAttr("totalEnergyConsumed", myTotalEnergyConsumed);
747  tripinfoOut->writeAttr("totalEnergyRegenerated", myTotalEnergyRegenerated);
748  tripinfoOut->writeAttr("totalEnergyWasted", myTotalEnergyWasted);
749  tripinfoOut->closeTag();
750  }
751 }
752 
753 
754 double
757 }
758 
759 
760 double
763 }
764 
765 std::string
766 MSDevice_ElecHybrid::getParameter(const std::string& key) const {
767  // RICE_TODO: full traci support
770  } else if (key == toString(SUMO_ATTR_ENERGYCONSUMED)) {
771  return toString(myConsum);
772  } else if (key == toString(SUMO_ATTR_ENERGYCHARGED)) {
773  return toString(myEnergyCharged);
774  } else if (key == toString(SUMO_ATTR_MAXIMUMBATTERYCAPACITY)) {
776  } else if (key == toString(SUMO_ATTR_OVERHEADWIREID)) {
777  return getOverheadWireSegmentID();
778  } else if (key == toString(SUMO_ATTR_SUBSTATIONID)) {
779  return getTractionSubstationID();
780  } else if (key == toString(SUMO_ATTR_VEHICLEMASS)) {
782  }
783  throw InvalidArgument("Parameter '" + key + "' is not supported for device of type '" + deviceName() + "'");
784 }
785 
786 
787 double
788 MSDevice_ElecHybrid::getParameterDouble(const std::string& key) const {
789  if (key == toString(SUMO_ATTR_MAXIMUMPOWER)) {
791  } else if (key == toString(SUMO_ATTR_RECUPERATIONEFFICIENCY)) {
793  }
794  throw InvalidArgument("Parameter '" + key + "' is not supported for device of type '" + deviceName() + "'");
795 }
796 
797 
799  double energyCharged = energyIn - myConsum;
800  /*
801  Apply recuperation or propulsion efficiency if necessary
802  1. if (energyIn > 0.0 && energyCharged > 0 && it->getConsum() >= 0) = > recuper eff for energyCharged
803  2. if (energyIn > 0.0 && energyCharged > 0 && it->getConsum() < 0) => recuper eff only for energyIn
804  3. if (energyIn < 0.0 && it->getConsum() > 0) => 1/propulsion eff only for energyIn
805  4. if (energyIn < 0.0 && energyCharged < 0 && it->getConsum() < 0) => 1/propulsion eff only for energyCharged
806  */
807  if (energyIn > 0.0 && energyCharged > 0.0) {
808  // the vehicle is charging battery from overhead wire
809  if (myConsum >= 0) {
811  } else {
812  energyCharged = myParam.getDouble(SUMO_ATTR_RECUPERATIONEFFICIENCY) * energyIn - myConsum;
813  }
814  } else if (energyIn < 0.0 && energyCharged < 0.0) {
815  // the vehicle is recuperating energy into the overhead wire and discharging batterypack at the same time
816  if (myConsum >= 0) {
817  energyCharged *= energyIn / myParam.getDouble(SUMO_ATTR_PROPULSIONEFFICIENCY) - myConsum;
818  } else {
820  }
821  }
822  return energyCharged;
823 }
824 
825 double
827  return myConsum;
828 }
829 
830 void
831 MSDevice_ElecHybrid::setConsum(const double consumption) {
833 }
834 
835 void
837  myTotalEnergyWasted += energyWasted;
838 }
839 
840 double
842  return myEnergyCharged;
843 }
844 
845 void
847  myEnergyCharged = energyCharged;
848 }
849 
850 double
853 #ifdef HAVE_EIGEN
855  if (owc != nullptr) {
856  return owc->getAlphaBest() ;
857  }
858 #else
859  WRITE_ERROR("Overhead wire solver is on, but the Eigen library has not been compiled in!")
860 #endif
861  }
862  return NAN;
863 }
864 
865 double
867  if (veh_elem != nullptr) {
868  return veh_elem->getPowerWanted();
869  }
870  return NAN;
871 }
872 
873 double
875  return myCircuitCurrent;
876 }
877 
878 void
880  myCircuitCurrent = current;
881 }
882 
883 double
885  return myCircuitVoltage;
886 }
887 
888 void
890  myCircuitVoltage = voltage;
891 }
892 
893 std::string
895  if (myActOverheadWireSegment != nullptr) {
897  } else {
898  return "";
899  }
900 }
901 
902 std::string
904  if (myActOverheadWireSegment != nullptr) {
906  if (ts != nullptr) {
907  return ts->getID();
908  }
909  }
910  return "";
911 }
912 
913 bool
916 }
917 
918 double
920  // Original energy state of the battery pack
921  double previousEnergyInBattery = myActualBatteryCapacity;
922  // Push as much energy as the battery pack can accomodate.
923  // The battery has SOC limits that will prevent it from being overcharged, hence some energy may remain "free".
925  // The "free" energy that still remains and has to be stored elsewhere or burned on resistors is the difference.
926  return myActualBatteryCapacity - previousEnergyInBattery;
927 }
928 
929 void
930 MSDevice_ElecHybrid::setActualBatteryCapacity(const double actualBatteryCapacity) {
931  // Use the SOC limits to cap the actual battery capacity
932  if (actualBatteryCapacity < mySOCMin * myMaximumBatteryCapacity) {
933  //WRITE_WARNING("The Battery of vehicle '" + getID() + "' has been exhausted.");
935  } else if (actualBatteryCapacity > mySOCMax * myMaximumBatteryCapacity) {
937  } else {
938  myActualBatteryCapacity = actualBatteryCapacity;
939  }
940 }
941 
942 void
943 MSDevice_ElecHybrid::setParameter(const std::string& key, const std::string& value) {
944  double doubleValue;
945  try {
946  doubleValue = StringUtils::toDouble(value);
947  } catch (NumberFormatException&) {
948  throw InvalidArgument("Setting parameter '" + key + "' requires a number for device of type '" + deviceName() + "'");
949  }
951  myActualBatteryCapacity = doubleValue;
952  } else if (key == toString(SUMO_ATTR_MAXIMUMBATTERYCAPACITY)) {
953  myMaximumBatteryCapacity = doubleValue;
954  } else if (key == toString(SUMO_ATTR_OVERHEADWIRECHARGINGPOWER)) {
955  myOverheadWireChargingPower = doubleValue;
956  } else if (key == toString(SUMO_ATTR_VEHICLEMASS)) {
958  } else {
959  throw InvalidArgument("Setting parameter '" + key + "' is not supported for device of type '" + deviceName() + "'");
960  }
961 }
962 
963 double
964 MSDevice_ElecHybrid::acceleration(SUMOVehicle& veh, double power, double oldSpeed) {
967 }
968 
969 double
970 MSDevice_ElecHybrid::consumption(SUMOVehicle& veh, double a, double newSpeed) {
973 }
974 
975 
976 /****************************************************************************/
#define WATT2WATTHR(_x)
#define WATTHR2WATT(_x)
const double WIRE_RESISTIVITY
#define WRITE_ERROR(msg)
Definition: MsgHandler.h:288
#define WRITE_WARNING(msg)
Definition: MsgHandler.h:280
SUMOTime DELTA_T
Definition: SUMOTime.cpp:37
#define ACCEL2SPEED(x)
Definition: SUMOTime.h:49
#define TS
Definition: SUMOTime.h:40
@ SUMO_TAG_OVERHEAD_WIRE_SEGMENT
An overhead wire segment.
SumoXMLAttr
Numbers representing SUMO-XML - attributes.
@ 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_ROLLDRAGCOEFFICIENT
Roll Drag coefficient.
@ SUMO_ATTR_CONSTANTPOWERINTAKE
Constant Power Intake.
@ SUMO_ATTR_RECUPERATIONEFFICIENCY_BY_DECELERATION
Recuperation efficiency (by deceleration)
@ SUMO_ATTR_RECUPERATIONEFFICIENCY
Recuperation efficiency (constant)
@ SUMO_ATTR_AIRDRAGCOEFFICIENT
Air drag coefficient.
@ SUMO_ATTR_ANGLE
@ SUMO_ATTR_ACTUALBATTERYCAPACITY
@ SUMO_ATTR_VEHICLEMASS
Vehicle mass.
@ SUMO_ATTR_RADIALDRAGCOEFFICIENT
Radial drag coefficient.
@ SUMO_ATTR_ENERGYCHARGED
tgotal of Energy charged
@ SUMO_ATTR_OVERHEADWIREID
@ SUMO_ATTR_PROPULSIONEFFICIENCY
Propulsion efficiency.
@ SUMO_ATTR_INTERNALMOMENTOFINERTIA
Internal moment of inertia.
@ SUMO_ATTR_FRONTSURFACEAREA
Front surface area.
@ SUMO_ATTR_OVERHEADWIRECHARGINGPOWER
#define UNUSED_PARAMETER(x)
Definition: StdDefs.h:30
T MIN2(T a, T b)
Definition: StdDefs.h:74
T ISNAN(T a)
Definition: StdDefs.h:115
T MAX2(T a, T b)
Definition: StdDefs.h:80
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:126
Node * addNode(std::string name)
Definition: Circuit.cpp:55
Element * addElement(std::string name, double value, Node *pNode, Node *nNode, Element::ElementType et)
Definition: Circuit.cpp:803
void eraseNode(Node *node)
Definition: Circuit.cpp:75
int getLastId()
Definition: Circuit.h:239
Element * getElement(std::string name)
Definition: Circuit.cpp:129
Element * getVoltageSource(int id)
Definition: Circuit.cpp:152
Node * getNode(std::string name)
Definition: Circuit.cpp:111
void descreaseLastId()
Definition: Circuit.h:244
void eraseElement(Element *element)
Definition: Circuit.cpp:847
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:41
double getDouble(SumoXMLAttr attr) const
bool knowsParameter(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:179
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:307
double getBlockTimeSeconds() const
Returns the time at which the vehicle was blocked on the current segment.
Definition: MEVehicle.h:312
double getAverageSpeed() const
Returns the vehicle's estimated average speed on the segment assuming no further delays.
Definition: MEVehicle.cpp:118
SUMOTime getAccumulatedWaitingTime() const
Returns the duration for which the vehicle was blocked.
Definition: MEVehicle.h:296
SUMOTime getLastEntryTime() const
Returns the time the vehicle entered the current segment.
Definition: MEVehicle.h:263
MESegment * getSegment() const
Returns the current segment the vehicle is on.
Definition: MEVehicle.h:239
SUMOTime getWaitingTime() const
Returns the duration for which the vehicle was blocked.
Definition: MEVehicle.h:286
double getSpeed() const
Returns the vehicle's estimated speed assuming no delays.
Definition: MEVehicle.cpp:108
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)
EnergyParams myParam
Parameter collection.
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.
void checkParam(const SumoXMLAttr paramKey, const double lower=0., const double upper=std::numeric_limits< double >::infinity())
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.
MSDevice_ElecHybrid(SUMOVehicle &holder, const std::string &id, const double actualBatteryCapacity, const double maximumBatteryCapacity, const double overheadWireChargingPower, const EnergyParams &param)
Constructor.
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:137
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:205
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:379
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:385
static bool gUseMesoSim
Definition: MSGlobals.h:94
static bool gOverheadWireRecuperation
Definition: MSGlobals.h:112
static bool gOverheadWireSolver
Definition: MSGlobals.h:109
Representation of a lane in the micro simulation.
Definition: MSLane.h:82
double getLength() const
Returns the lane's length.
Definition: MSLane.h:541
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:174
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:1259
MSStoppingPlace * getStoppingPlace(const std::string &id, const SumoXMLTag category) const
Returns the named stopping place of the given category.
Definition: MSNet.cpp:1250
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.
Representation of a vehicle in the micro simulation.
Definition: MSVehicle.h:75
const SUMOVTypeParameter & getParameter() const
const std::string & getID() const
Returns the id.
Definition: Named.h:74
Definition: Node.h:39
std::vector< Element * > * getElements()
Definition: Node.cpp:100
int getId()
Definition: Node.cpp:76
void addElement(Element *element)
Definition: Node.cpp:43
void eraseElement(Element *element)
Definition: Node.cpp:47
void setId(int id)
Definition: Node.cpp:80
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:58
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:248
bool closeTag(const std::string &comment="")
Closes the most recently opened tag and optionally adds a comment.
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.
bool knowsParameter(const std::string &key) const
Returns whether the parameter is known.
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.
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
std::string to_string(const std::vector< double > &value)