Eclipse SUMO - Simulation of Urban MObility
MSLeaderInfo.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 /****************************************************************************/
18 // Information about vehicles ahead (may be multiple vehicles if
19 // lateral-resolution is active)
20 /****************************************************************************/
21 #include <config.h>
22 
23 #include <cassert>
24 #include <cmath>
25 #include <utils/common/ToString.h>
26 #include <microsim/MSGlobals.h>
27 #include <microsim/MSVehicle.h>
29 #include <microsim/MSNet.h>
30 #include <microsim/MSLane.h>
31 #include "MSLeaderInfo.h"
32 
33 
34 // ===========================================================================
35 // MSLeaderInfo member method definitions
36 // ===========================================================================
37 MSLeaderInfo::MSLeaderInfo(const double laneWidth, const MSVehicle* ego, const double latOffset) :
38  myWidth(laneWidth),
39  myOffset(0),
40  myVehicles(MAX2(1, int(ceil(laneWidth / MSGlobals::gLateralResolution))), (MSVehicle*)nullptr),
41  myFreeSublanes((int)myVehicles.size()),
42  egoRightMost(-1),
43  egoLeftMost(-1),
44  myHasVehicles(false) {
45  if (ego != nullptr) {
46  getSubLanes(ego, latOffset, egoRightMost, egoLeftMost);
47  // filter out sublanes not of interest to ego
49  myFreeSublanes -= (int)myVehicles.size() - 1 - egoLeftMost;
50  }
51 }
52 
53 
55 
56 
57 int
58 MSLeaderInfo::addLeader(const MSVehicle* veh, bool beyond, double latOffset) {
59  if (veh == nullptr) {
60  return myFreeSublanes;
61  }
62  if (myVehicles.size() == 1) {
63  // speedup for the simple case
64  if (!beyond || myVehicles[0] == 0) {
65  myVehicles[0] = veh;
66  myFreeSublanes = 0;
67  myHasVehicles = true;
68  }
69  return myFreeSublanes;
70  }
71  // map center-line based coordinates into [0, myWidth] coordinates
72  int rightmost, leftmost;
73  getSubLanes(veh, latOffset, rightmost, leftmost);
74  //if (gDebugFlag1) std::cout << " addLeader veh=" << veh->getID() << " beyond=" << beyond << " latOffset=" << latOffset << " sublaneOffset=" << myOffset
75  // << " rightmost=" << rightmost << " leftmost=" << leftmost
76  // << " eRM=" << egoRightMost << " eLM=" << egoLeftMost
77  // << " myFreeSublanes=" << myFreeSublanes << "\n";
78  for (int sublane = rightmost; sublane <= leftmost; ++sublane) {
79  if ((egoRightMost < 0 || (egoRightMost <= sublane && sublane <= egoLeftMost))
80  && (!beyond || myVehicles[sublane] == 0)) {
81  if (myVehicles[sublane] == 0) {
83  }
84  myVehicles[sublane] = veh;
85  myHasVehicles = true;
86  }
87  }
88  return myFreeSublanes;
89 }
90 
91 
92 void
94  myVehicles.assign(myVehicles.size(), (MSVehicle*)nullptr);
95  myFreeSublanes = (int)myVehicles.size();
96  if (egoRightMost >= 0) {
98  myFreeSublanes -= (int)myVehicles.size() - 1 - egoLeftMost;
99  }
100 }
101 
102 
103 void
104 MSLeaderInfo::getSubLanes(const MSVehicle* veh, double latOffset, int& rightmost, int& leftmost) const {
105  if (myVehicles.size() == 1) {
106  // speedup for the simple case
107  rightmost = 0;
108  leftmost = 0;
109  return;
110  }
111  // map center-line based coordinates into [0, myWidth] coordinates
112  const double vehCenter = veh->getLateralPositionOnLane() + 0.5 * myWidth + latOffset + myOffset * MSGlobals::gLateralResolution;
113  const double vehHalfWidth = 0.5 * veh->getVehicleType().getWidth();
114  double rightVehSide = vehCenter - vehHalfWidth;
115  double leftVehSide = vehCenter + vehHalfWidth;
116  // Reserve some additional space if the vehicle is performing a maneuver continuation.
117  if (veh->getActionStepLength() != DELTA_T) {
118  if (veh->getLaneChangeModel().getManeuverDist() < 0. || veh->getLaneChangeModel().getSpeedLat() < 0.) {
119  const double maneuverDist = MIN2(veh->getVehicleType().getMaxSpeedLat() * veh->getActionStepLengthSecs(), -MIN2(0., veh->getLaneChangeModel().getManeuverDist()));
120  rightVehSide -= maneuverDist;
121  }
122  if (veh->getLaneChangeModel().getManeuverDist() > 0. || veh->getLaneChangeModel().getSpeedLat() > 0.) {
123  const double maneuverDist = MIN2(veh->getVehicleType().getMaxSpeedLat() * veh->getActionStepLengthSecs(), MAX2(0., veh->getLaneChangeModel().getManeuverDist()));
124  leftVehSide += maneuverDist;
125  }
126  }
127  if (rightVehSide > myWidth || leftVehSide < 0) {
128  // vehicle does not touch this lane
129  // set the values so that an iteration
130  // for (i = rightmost; i <= leftmost; i++) stops immediately
131  rightmost = -1000;
132  leftmost = -2000;
133  } else {
134  rightmost = MAX2(0, (int)floor((rightVehSide + NUMERICAL_EPS) / MSGlobals::gLateralResolution));
135  leftmost = MIN2((int)myVehicles.size() - 1, (int)floor(MAX2(0.0, leftVehSide - NUMERICAL_EPS) / MSGlobals::gLateralResolution));
136  }
137  //if (veh->isSelected()) std::cout << SIMTIME << " veh=" << veh->getID()
138  // << std::setprecision(2)
139  // << " posLat=" << veh->getLateralPositionOnLane()
140  // << " latOffset=" << latOffset
141  // << " vehCenter=" << vehCenter
142  // << " rightVehSide=" << rightVehSide
143  // << " leftVehSide=" << leftVehSide
144  // << " rightmost=" << rightmost
145  // << " leftmost=" << leftmost
146  // << " myOffset=" << myOffset
147  // << std::setprecision(2)
148  // << "\n";
149 }
150 
151 
152 void
153 MSLeaderInfo::getSublaneBorders(int sublane, double latOffset, double& rightSide, double& leftSide) const {
154  assert(sublane >= 0);
155  assert(sublane < (int)myVehicles.size());
157  rightSide = sublane * res + latOffset - myOffset * MSGlobals::gLateralResolution;
158  leftSide = MIN2((sublane + 1) * res, myWidth) + latOffset - myOffset * MSGlobals::gLateralResolution;
159 }
160 
161 
162 const MSVehicle*
163 MSLeaderInfo::operator[](int sublane) const {
164  assert(sublane >= 0);
165  assert(sublane < (int)myVehicles.size());
166  return myVehicles[sublane];
167 }
168 
169 
170 std::string
172  std::ostringstream oss;
173  oss.setf(std::ios::fixed, std::ios::floatfield);
174  oss << std::setprecision(2);
175  for (int i = 0; i < (int)myVehicles.size(); ++i) {
176  oss << Named::getIDSecure(myVehicles[i]);
177  if (i < (int)myVehicles.size() - 1) {
178  oss << ", ";
179  }
180  }
181  oss << " free=" << myFreeSublanes;
182  return oss.str();
183 }
184 
185 
186 void
188  assert(MSGlobals::gLateralResolution > 0);
189  myOffset = offset;
190 }
191 
192 
193 bool
195  if (!myHasVehicles) {
196  return false;
197  }
198  for (int i = 0; i < (int)myVehicles.size(); ++i) {
199  if (myVehicles[i] != 0 && myVehicles[i]->isStopped()) {
200  return true;
201  }
202  }
203  return false;
204 }
205 
206 void
208  for (int i = 0; i < (int)myVehicles.size(); ++i) {
209  const MSVehicle* veh = myVehicles[i];
210  if (veh != 0 &&
212  || &lane->getEdge() != &veh->getLane()->getEdge())) {
213  myVehicles[i] = nullptr;
214  }
215  }
216 }
217 
218 
219 // ===========================================================================
220 // MSLeaderDistanceInfo member method definitions
221 // ===========================================================================
222 MSLeaderDistanceInfo::MSLeaderDistanceInfo(const double laneWidth, const MSVehicle* ego, const double latOffset) :
223  MSLeaderInfo(laneWidth, ego, latOffset),
224  myDistances(myVehicles.size(), std::numeric_limits<double>::max()) {
225 }
226 
227 
228 MSLeaderDistanceInfo::MSLeaderDistanceInfo(const CLeaderDist& cLeaderDist, const double laneWidth) :
229  MSLeaderInfo(laneWidth, nullptr, 0.),
230  myDistances(1, cLeaderDist.second) {
231  assert(myVehicles.size() == 1);
232  myVehicles[0] = cLeaderDist.first;
233  myHasVehicles = cLeaderDist.first != nullptr;
234 }
235 
237 
238 
239 int
240 MSLeaderDistanceInfo::addLeader(const MSVehicle* veh, double gap, double latOffset, int sublane) {
241  //if (SIMTIME == 31 && gDebugFlag1 && veh != 0 && veh->getID() == "cars.8") {
242  // std::cout << " BREAKPOINT\n";
243  //}
244  if (veh == nullptr) {
245  return myFreeSublanes;
246  }
247  if (myVehicles.size() == 1) {
248  // speedup for the simple case
249  sublane = 0;
250  }
251  if (sublane >= 0 && sublane < (int)myVehicles.size()) {
252  // sublane is already given
253  if (gap < myDistances[sublane]) {
254  if (myVehicles[sublane] == 0) {
255  myFreeSublanes--;
256  }
257  myVehicles[sublane] = veh;
258  myDistances[sublane] = gap;
259  myHasVehicles = true;
260  }
261  return myFreeSublanes;
262  }
263  int rightmost, leftmost;
264  getSubLanes(veh, latOffset, rightmost, leftmost);
265  //if (gDebugFlag1) std::cout << " addLeader veh=" << veh->getID() << " gap=" << gap << " latOffset=" << latOffset << " sublaneOffset=" << myOffset
266  // << " rightmost=" << rightmost << " leftmost=" << leftmost
267  // << " eRM=" << egoRightMost << " eLM=" << egoLeftMost
268  // << " myFreeSublanes=" << myFreeSublanes << "\n";
269  for (int sublaneIdx = rightmost; sublaneIdx <= leftmost; ++sublaneIdx) {
270  if ((egoRightMost < 0 || (egoRightMost <= sublaneIdx && sublaneIdx <= egoLeftMost))
271  && gap < myDistances[sublaneIdx]) {
272  if (myVehicles[sublaneIdx] == 0) {
273  myFreeSublanes--;
274  }
275  myVehicles[sublaneIdx] = veh;
276  myDistances[sublaneIdx] = gap;
277  myHasVehicles = true;
278  }
279  }
280  return myFreeSublanes;
281 }
282 
283 
284 void
286  const int maxSubLane = MIN2(numSublanes(), other.numSublanes());
287  for (int i = 0; i < maxSubLane; i++) {
288  addLeader(other[i].first, other[i].second, 0, i);
289  //if ((myDistances[i] > 0 && myDistances[i] > other.myDistances[i])
290  // || (other.myDistances[i] < 0 && myDistances[i] < other.myDistances[i])) {
291  // addLeader(other[i].first, other[i].second, 0, i);
292  //}
293  }
294 }
295 
296 
297 void
300  myDistances.assign(myVehicles.size(), std::numeric_limits<double>::max());
301 }
302 
303 
306  assert(sublane >= 0);
307  assert(sublane < (int)myVehicles.size());
308  return std::make_pair(myVehicles[sublane], myDistances[sublane]);
309 }
310 
311 
312 std::string
314  std::ostringstream oss;
315  oss.setf(std::ios::fixed, std::ios::floatfield);
316  oss << std::setprecision(2);
317  for (int i = 0; i < (int)myVehicles.size(); ++i) {
318  oss << Named::getIDSecure(myVehicles[i]) << ":";
319  if (myVehicles[i] == 0) {
320  oss << "inf";
321  } else {
322  oss << myDistances[i];
323  }
324  if (i < (int)myVehicles.size() - 1) {
325  oss << ", ";
326  }
327  }
328  oss << " free=" << myFreeSublanes;
329  return oss.str();
330 }
331 
332 void
334  for (int i = 0; i < (int)myVehicles.size(); ++i) {
335  if (myVehicles[i] != nullptr) {
336  if (myVehicles[i]->getLaneChangeModel().isOpposite()) {
337  myDistances[i] -= myVehicles[i]->getVehicleType().getLength();
338  } else if (isFollower && myDistances[i] > POSITION_EPS) {
339  // can ignore oncoming followers once they are past
340  myVehicles[i] = nullptr;
341  myDistances[i] = -1;
342  }
343  }
344  }
345 }
346 
347 
348 void
350  for (int i = 0; i < (int)myVehicles.size(); ++i) {
351  if (myVehicles[i] != nullptr) {
352  myDistances[i] += amount;
353  }
354  }
355 }
356 
359  double minGap = -1;
360  const MSVehicle* veh = nullptr;
361  if (hasVehicles()) {
362  minGap = std::numeric_limits<double>::max();
363  for (int i = 0; i < (int)myVehicles.size(); ++i) {
364  if (myVehicles[i] != nullptr && myDistances[i] < minGap) {
365  minGap = myDistances[i];
366  veh = myVehicles[i];
367  }
368  }
369  }
370  return std::make_pair(veh, minGap);
371 }
372 
373 
374 void
376  const double pos = ego->getPositionOnLane();
377  for (int i = 0; i < (int)myVehicles.size(); ++i) {
378  if (myVehicles[i] != nullptr && myDistances[i] < 0 && myVehicles[i]->getPositionOnLane() == pos
379  && &myVehicles[i]->getLane()->getEdge() == &ego->getLane()->getEdge()) {
380  other.myVehicles[i] = myVehicles[i];
381  other.myDistances[i] = myDistances[i];
382  myVehicles[i] = nullptr;
383  myDistances[i] = -1;
384  }
385  }
386 }
387 
388 // ===========================================================================
389 // MSCriticalFollowerDistanceInfo member method definitions
390 // ===========================================================================
391 
392 
393 MSCriticalFollowerDistanceInfo::MSCriticalFollowerDistanceInfo(const double laneWidth, const MSVehicle* ego, const double latOffset, const bool haveOppositeLeaders) :
394  MSLeaderDistanceInfo(laneWidth, ego, latOffset),
395  myMissingGaps(myVehicles.size(), -std::numeric_limits<double>::max()),
396  myHaveOppositeLeaders(haveOppositeLeaders)
397 { }
398 
399 
401 
402 
403 int
404 MSCriticalFollowerDistanceInfo::addFollower(const MSVehicle* veh, const MSVehicle* ego, double gap, double latOffset, int sublane) {
405  if (veh == nullptr) {
406  return myFreeSublanes;
407  }
408  const double requiredGap = (myHaveOppositeLeaders ? 0
409  : veh->getCarFollowModel().getSecureGap(veh, ego, veh->getSpeed(), ego->getSpeed(), ego->getCarFollowModel().getMaxDecel()));
410  const double missingGap = requiredGap - gap;
411  /*
412  if (ego->getID() == "disabled" || gDebugFlag1) {
413  std::cout << " addFollower veh=" << veh->getID()
414  << " ego=" << ego->getID()
415  << " gap=" << gap
416  << " reqGap=" << requiredGap
417  << " missingGap=" << missingGap
418  << " latOffset=" << latOffset
419  << " sublane=" << sublane
420  << "\n";
421  if (sublane > 0) {
422  std::cout
423  << " dists[s]=" << myDistances[sublane]
424  << " gaps[s]=" << myMissingGaps[sublane]
425  << "\n";
426  } else {
427  std::cout << toString() << "\n";
428  }
429  }
430  */
431  if (myVehicles.size() == 1) {
432  // speedup for the simple case
433  sublane = 0;
434  }
435  if (sublane >= 0 && sublane < (int)myVehicles.size()) {
436  // sublane is already given
437  // overlapping vehicles are stored preferably
438  // among those vehicles with missing gap, closer ones are preferred
439  if ((missingGap > myMissingGaps[sublane]
440  || (missingGap > 0 && gap < myDistances[sublane])
441  || (gap < 0 && myDistances[sublane] > 0))
442  && !(gap > 0 && myDistances[sublane] < 0)
443  && !(myMissingGaps[sublane] > 0 && myDistances[sublane] < gap)
444  ) {
445  if (myVehicles[sublane] == 0) {
446  myFreeSublanes--;
447  }
448  myVehicles[sublane] = veh;
449  myDistances[sublane] = gap;
450  myMissingGaps[sublane] = missingGap;
451  myHasVehicles = true;
452  }
453  return myFreeSublanes;
454  }
455  int rightmost, leftmost;
456  getSubLanes(veh, latOffset, rightmost, leftmost);
457  for (int sublaneIdx = rightmost; sublaneIdx <= leftmost; ++sublaneIdx) {
458  if ((egoRightMost < 0 || (egoRightMost <= sublaneIdx && sublaneIdx <= egoLeftMost))
459  // overlapping vehicles are stored preferably
460  // among those vehicles with missing gap, closer ones are preferred
461  && (missingGap > myMissingGaps[sublaneIdx]
462  || (missingGap > 0 && gap < myDistances[sublaneIdx])
463  || (gap < 0 && myDistances[sublaneIdx] > 0))
464  && !(gap > 0 && myDistances[sublaneIdx] < 0)
465  && !(myMissingGaps[sublaneIdx] > 0 && myDistances[sublaneIdx] < gap)
466  ) {
467  if (myVehicles[sublaneIdx] == 0) {
468  myFreeSublanes--;
469  }
470  myVehicles[sublaneIdx] = veh;
471  myDistances[sublaneIdx] = gap;
472  myMissingGaps[sublaneIdx] = missingGap;
473  myHasVehicles = true;
474  }
475  }
476  return myFreeSublanes;
477 }
478 
479 
480 void
483  myMissingGaps.assign(myVehicles.size(), -std::numeric_limits<double>::max());
484 }
485 
486 
487 std::string
489  std::ostringstream oss;
490  oss.setf(std::ios::fixed, std::ios::floatfield);
491  oss << std::setprecision(2);
492  for (int i = 0; i < (int)myVehicles.size(); ++i) {
493  oss << Named::getIDSecure(myVehicles[i]) << ":";
494  if (myVehicles[i] == 0) {
495  oss << "inf:-inf";
496  } else {
497  oss << myDistances[i] << ":" << myMissingGaps[i];
498  }
499  if (i < (int)myVehicles.size() - 1) {
500  oss << ", ";
501  }
502  }
503  oss << " free=" << myFreeSublanes;
504  return oss.str();
505 }
506 
507 
508 /****************************************************************************/
std::pair< const MSVehicle *, double > CLeaderDist
Definition: MSLeaderInfo.h:32
SUMOTime DELTA_T
Definition: SUMOTime.cpp:38
T MIN2(T a, T b)
Definition: StdDefs.h:76
T MAX2(T a, T b)
Definition: StdDefs.h:82
double getManeuverDist() const
Returns the remaining unblocked distance for the current maneuver. (only used by sublane model)
double getSpeedLat() const
return the lateral speed of the current lane change maneuver
const MSVehicleType & getVehicleType() const
Returns the vehicle's type definition.
virtual double getSecureGap(const MSVehicle *const veh, const MSVehicle *const, const double speed, const double leaderSpeed, const double leaderMaxDecel) const
Returns the minimum gap to reserve if the leader is braking at maximum (>=0)
Definition: MSCFModel.cpp:166
double getMaxDecel() const
Get the vehicle type's maximal comfortable deceleration [m/s^2].
Definition: MSCFModel.h:264
std::vector< double > myMissingGaps
Definition: MSLeaderInfo.h:251
virtual ~MSCriticalFollowerDistanceInfo()
Destructor.
MSCriticalFollowerDistanceInfo(const double laneWidth, const MSVehicle *ego, const double latOffset, const bool haveOppositeLeaders=false)
Constructor.
std::string toString() const
print a debugging representation
void clear()
discard all information
int addFollower(const MSVehicle *veh, const MSVehicle *ego, double gap, double latOffset=0, int sublane=-1)
static double gLateralResolution
Definition: MSGlobals.h:97
Representation of a lane in the micro simulation.
Definition: MSLane.h:84
MSEdge & getEdge() const
Returns the lane's edge.
Definition: MSLane.h:752
saves leader/follower vehicles and their distances relative to an ego vehicle
Definition: MSLeaderInfo.h:144
virtual void addLeaders(MSLeaderDistanceInfo &other)
updatd empty sublanes with vehicles and gaps from other
virtual std::string toString() const
print a debugging representation
CLeaderDist getClosest() const
return vehicle with the smalles gap
virtual ~MSLeaderDistanceInfo()
Destructor.
MSLeaderDistanceInfo(const double laneWidth, const MSVehicle *ego, const double latOffset)
Constructor.
CLeaderDist operator[](int sublane) const
return the vehicle and its distance for the given sublane
virtual void clear()
discard all information
std::vector< double > myDistances
Definition: MSLeaderInfo.h:201
void fixOppositeGaps(bool isFollower)
subtract vehicle length from all gaps if the leader vehicle is driving in the opposite direction
void patchGaps(double amount)
add given value to all gaps
virtual int addLeader(const MSVehicle *veh, double gap, double latOffset=0, int sublane=-1)
void moveSamePosTo(const MSVehicle *ego, MSLeaderDistanceInfo &other)
std::vector< const MSVehicle * > myVehicles
Definition: MSLeaderInfo.h:127
int myFreeSublanes
the number of free sublanes
Definition: MSLeaderInfo.h:132
int myOffset
an extra offset for shifting the interpretation of sublane borders (default [0,myWidth])
Definition: MSLeaderInfo.h:125
void setSublaneOffset(int offset)
set number of sublanes by which to shift positions
bool hasStoppedVehicle() const
whether a stopped vehicle is leader
void removeOpposite(const MSLane *lane)
remove vehicles that are driving in the opposite direction (fully or partially) on the given lane
int egoRightMost
borders of the ego vehicle for filtering of free sublanes
Definition: MSLeaderInfo.h:135
void getSublaneBorders(int sublane, double latOffset, double &rightSide, double &leftSide) const
int numSublanes() const
Definition: MSLeaderInfo.h:86
virtual int addLeader(const MSVehicle *veh, bool beyond, double latOffset=0.)
virtual std::string toString() const
print a debugging representation
virtual void clear()
discard all information
MSLeaderInfo(const double laneWidth, const MSVehicle *ego=nullptr, const double latOffset=0.)
Constructor.
virtual ~MSLeaderInfo()
Destructor.
const MSVehicle * operator[](int sublane) const
return the vehicle for the given sublane
bool hasVehicles() const
Definition: MSLeaderInfo.h:94
void getSubLanes(const MSVehicle *veh, double latOffset, int &rightmost, int &leftmost) const
double myWidth
the width of the lane to which this instance applies
Definition: MSLeaderInfo.h:122
bool myHasVehicles
Definition: MSLeaderInfo.h:138
Representation of a vehicle in the micro simulation.
Definition: MSVehicle.h:77
MSAbstractLaneChangeModel & getLaneChangeModel()
Definition: MSVehicle.cpp:5720
double getActionStepLengthSecs() const
Returns the vehicle's action step length in secs, i.e. the interval between two action points.
Definition: MSVehicle.h:536
SUMOTime getActionStepLength() const
Returns the vehicle's action step length in millisecs, i.e. the interval between two action points.
Definition: MSVehicle.h:528
double getLateralPositionOnLane() const
Get the vehicle's lateral position on the lane.
Definition: MSVehicle.h:416
double getSpeed() const
Returns the vehicle's current speed.
Definition: MSVehicle.h:493
double getPositionOnLane() const
Get the vehicle's position along the lane.
Definition: MSVehicle.h:377
const MSLane * getLane() const
Returns the lane the vehicle is on.
Definition: MSVehicle.h:584
const MSCFModel & getCarFollowModel() const
Returns the vehicle's car following model definition.
Definition: MSVehicle.h:974
double getWidth() const
Get the width which vehicles of this class shall have when being drawn.
double getMaxSpeedLat() const
Get vehicle's maximum lateral speed [m/s].
static std::string getIDSecure(const T *obj, const std::string &fallBack="NULL")
get an identifier for Named-like object which may be Null
Definition: Named.h:67
Definition: json.hpp:4471