Eclipse SUMO - Simulation of Urban MObility
Loading...
Searching...
No Matches
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-2025 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>
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// ===========================================================================
37MSLeaderInfo::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
57int
58MSLeaderInfo::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;
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
92void
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
103void
104MSLeaderInfo::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
152void
153MSLeaderInfo::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
162const MSVehicle*
163MSLeaderInfo::operator[](int sublane) const {
164 assert(sublane >= 0);
165 assert(sublane < (int)myVehicles.size());
166 return myVehicles[sublane];
167}
168
169
170std::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) {
177 if (i < (int)myVehicles.size() - 1) {
178 oss << ", ";
179 }
180 }
181 oss << " free=" << myFreeSublanes;
182 return oss.str();
183}
184
185
186void
189 myOffset = offset;
190}
191
192
193bool
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
207bool
209 if (!myHasVehicles) {
210 return false;
211 }
212 for (int i = 0; i < (int)myVehicles.size(); ++i) {
213 if (myVehicles[i] == veh) {
214 return true;
215 }
216 }
217 return false;
218}
219
220void
222 for (int i = 0; i < (int)myVehicles.size(); ++i) {
223 const MSVehicle* veh = myVehicles[i];
224 if (veh != 0 &&
226 || &lane->getEdge() != &veh->getLane()->getEdge())) {
227 myVehicles[i] = nullptr;
228 }
229 }
230}
231
232
233// ===========================================================================
234// MSLeaderDistanceInfo member method definitions
235// ===========================================================================
236MSLeaderDistanceInfo::MSLeaderDistanceInfo(const double laneWidth, const MSVehicle* ego, const double latOffset) :
237 MSLeaderInfo(laneWidth, ego, latOffset),
238 myDistances(myVehicles.size(), std::numeric_limits<double>::max()) {
239}
240
241
242MSLeaderDistanceInfo::MSLeaderDistanceInfo(const CLeaderDist& cLeaderDist, const double laneWidth) :
243 MSLeaderInfo(laneWidth, nullptr, 0.),
244 myDistances(1, cLeaderDist.second) {
245 assert(myVehicles.size() == 1);
246 myVehicles[0] = cLeaderDist.first;
247 myHasVehicles = cLeaderDist.first != nullptr;
248}
249
251
252
253int
254MSLeaderDistanceInfo::addLeader(const MSVehicle* veh, double gap, double latOffset, int sublane) {
255 //if (SIMTIME == 31 && gDebugFlag1 && veh != 0 && veh->getID() == "cars.8") {
256 // std::cout << " BREAKPOINT\n";
257 //}
258 if (veh == nullptr) {
259 return myFreeSublanes;
260 }
261 if (myVehicles.size() == 1) {
262 // speedup for the simple case
263 sublane = 0;
264 }
265 if (sublane >= 0 && sublane < (int)myVehicles.size()) {
266 // sublane is already given
267 if (gap < myDistances[sublane]) {
268 if (myVehicles[sublane] == 0) {
270 }
271 myVehicles[sublane] = veh;
272 myDistances[sublane] = gap;
273 myHasVehicles = true;
274 }
275 return myFreeSublanes;
276 }
277 int rightmost, leftmost;
278 getSubLanes(veh, latOffset, rightmost, leftmost);
279 //if (gDebugFlag1) std::cout << " addLeader veh=" << veh->getID() << " gap=" << gap << " latOffset=" << latOffset << " sublaneOffset=" << myOffset
280 // << " rightmost=" << rightmost << " leftmost=" << leftmost
281 // << " eRM=" << egoRightMost << " eLM=" << egoLeftMost
282 // << " myFreeSublanes=" << myFreeSublanes << "\n";
283 for (int sublaneIdx = rightmost; sublaneIdx <= leftmost; ++sublaneIdx) {
284 if ((egoRightMost < 0 || (egoRightMost <= sublaneIdx && sublaneIdx <= egoLeftMost))
285 && gap < myDistances[sublaneIdx]) {
286 if (myVehicles[sublaneIdx] == 0) {
288 }
289 myVehicles[sublaneIdx] = veh;
290 myDistances[sublaneIdx] = gap;
291 myHasVehicles = true;
292 }
293 }
294 return myFreeSublanes;
295}
296
297
298void
300 const int maxSubLane = MIN2(numSublanes(), other.numSublanes());
301 for (int i = 0; i < maxSubLane; i++) {
302 addLeader(other[i].first, other[i].second, 0, i);
303 //if ((myDistances[i] > 0 && myDistances[i] > other.myDistances[i])
304 // || (other.myDistances[i] < 0 && myDistances[i] < other.myDistances[i])) {
305 // addLeader(other[i].first, other[i].second, 0, i);
306 //}
307 }
308}
309
310
311void
314 myDistances.assign(myVehicles.size(), std::numeric_limits<double>::max());
315}
316
317
320 assert(sublane >= 0);
321 assert(sublane < (int)myVehicles.size());
322 return std::make_pair(myVehicles[sublane], myDistances[sublane]);
323}
324
325
326std::string
328 std::ostringstream oss;
329 oss.setf(std::ios::fixed, std::ios::floatfield);
330 oss << std::setprecision(2);
331 for (int i = 0; i < (int)myVehicles.size(); ++i) {
332 oss << Named::getIDSecure(myVehicles[i]) << ":";
333 if (myVehicles[i] == 0) {
334 oss << "inf";
335 } else {
336 oss << myDistances[i];
337 }
338 if (i < (int)myVehicles.size() - 1) {
339 oss << ", ";
340 }
341 }
342 oss << " free=" << myFreeSublanes;
343 return oss.str();
344}
345
346void
348 for (int i = 0; i < (int)myVehicles.size(); ++i) {
349 if (myVehicles[i] != nullptr) {
350 if (myVehicles[i]->getLaneChangeModel().isOpposite()) {
351 myDistances[i] -= myVehicles[i]->getVehicleType().getLength();
352 } else if (isFollower && myDistances[i] > POSITION_EPS) {
353 // can ignore oncoming followers once they are past
354 myVehicles[i] = nullptr;
355 myDistances[i] = -1;
356 }
357 }
358 }
359}
360
361
362void
364 for (int i = 0; i < (int)myVehicles.size(); ++i) {
365 if (myVehicles[i] != nullptr) {
366 myDistances[i] += amount;
367 }
368 }
369}
370
373 double minGap = -1;
374 const MSVehicle* veh = nullptr;
375 if (hasVehicles()) {
376 minGap = std::numeric_limits<double>::max();
377 for (int i = 0; i < (int)myVehicles.size(); ++i) {
378 if (myVehicles[i] != nullptr && myDistances[i] < minGap) {
379 minGap = myDistances[i];
380 veh = myVehicles[i];
381 }
382 }
383 }
384 return std::make_pair(veh, minGap);
385}
386
387
388void
390 const double pos = ego->getPositionOnLane();
391 for (int i = 0; i < (int)myVehicles.size(); ++i) {
392 if (myVehicles[i] != nullptr && myDistances[i] < 0 && myVehicles[i]->getPositionOnLane() == pos
393 && &myVehicles[i]->getLane()->getEdge() == &ego->getLane()->getEdge()) {
394 other.myVehicles[i] = myVehicles[i];
395 other.myDistances[i] = myDistances[i];
396 myVehicles[i] = nullptr;
397 myDistances[i] = -1;
398 }
399 }
400}
401
402
403double
405 double result = std::numeric_limits<double>::max();
406 if (!myHasVehicles) {
407 return result;
408 }
409 for (int i = 0; i < (int)myVehicles.size(); ++i) {
410 if (myVehicles[i] != 0 && myVehicles[i]->isStopped()) {
411 result = MIN2(result, myDistances[i]);
412 }
413 }
414 return result;
415}
416
417
418// ===========================================================================
419// MSCriticalFollowerDistanceInfo member method definitions
420// ===========================================================================
421
422
423MSCriticalFollowerDistanceInfo::MSCriticalFollowerDistanceInfo(const double laneWidth, const MSVehicle* ego, const double latOffset, const bool haveOppositeLeaders) :
424 MSLeaderDistanceInfo(laneWidth, ego, latOffset),
425 myMissingGaps(myVehicles.size(), -std::numeric_limits<double>::max()),
426 myHaveOppositeLeaders(haveOppositeLeaders)
427{ }
428
429
431
432
433int
434MSCriticalFollowerDistanceInfo::addFollower(const MSVehicle* veh, const MSVehicle* ego, double gap, double latOffset, int sublane) {
435 if (veh == nullptr) {
436 return myFreeSublanes;
437 }
438 const double requiredGap = (myHaveOppositeLeaders ? 0
439 : veh->getCarFollowModel().getSecureGap(veh, ego, veh->getSpeed(), ego->getSpeed(), ego->getCarFollowModel().getMaxDecel()));
440 const double missingGap = requiredGap - gap;
441 /*
442 if (ego->getID() == "disabled" || gDebugFlag1) {
443 std::cout << " addFollower veh=" << veh->getID()
444 << " ego=" << ego->getID()
445 << " gap=" << gap
446 << " reqGap=" << requiredGap
447 << " missingGap=" << missingGap
448 << " latOffset=" << latOffset
449 << " sublane=" << sublane
450 << "\n";
451 if (sublane > 0) {
452 std::cout
453 << " dists[s]=" << myDistances[sublane]
454 << " gaps[s]=" << myMissingGaps[sublane]
455 << "\n";
456 } else {
457 std::cout << toString() << "\n";
458 }
459 }
460 */
461 if (myVehicles.size() == 1) {
462 // speedup for the simple case
463 sublane = 0;
464 }
465 if (sublane >= 0 && sublane < (int)myVehicles.size()) {
466 // sublane is already given
467 // overlapping vehicles are stored preferably
468 // among those vehicles with missing gap, closer ones are preferred
469 if ((missingGap > myMissingGaps[sublane]
470 || (missingGap > 0 && gap < myDistances[sublane])
471 || (gap < 0 && myDistances[sublane] > 0))
472 && !(gap > 0 && myDistances[sublane] < 0)
473 && !(myMissingGaps[sublane] > 0 && myDistances[sublane] < gap)
474 ) {
475 if (myVehicles[sublane] == 0) {
477 }
478 myVehicles[sublane] = veh;
479 myDistances[sublane] = gap;
480 myMissingGaps[sublane] = missingGap;
481 myHasVehicles = true;
482 }
483 return myFreeSublanes;
484 }
485 int rightmost, leftmost;
486 getSubLanes(veh, latOffset, rightmost, leftmost);
487 for (int sublaneIdx = rightmost; sublaneIdx <= leftmost; ++sublaneIdx) {
488 if ((egoRightMost < 0 || (egoRightMost <= sublaneIdx && sublaneIdx <= egoLeftMost))
489 // overlapping vehicles are stored preferably
490 // among those vehicles with missing gap, closer ones are preferred
491 && (missingGap > myMissingGaps[sublaneIdx]
492 || (missingGap > 0 && gap < myDistances[sublaneIdx])
493 || (gap < 0 && myDistances[sublaneIdx] > 0))
494 && !(gap > 0 && myDistances[sublaneIdx] < 0)
495 && !(myMissingGaps[sublaneIdx] > 0 && myDistances[sublaneIdx] < gap)
496 ) {
497 if (myVehicles[sublaneIdx] == 0) {
499 }
500 myVehicles[sublaneIdx] = veh;
501 myDistances[sublaneIdx] = gap;
502 myMissingGaps[sublaneIdx] = missingGap;
503 myHasVehicles = true;
504 }
505 }
506 return myFreeSublanes;
507}
508
509
510void
513 myMissingGaps.assign(myVehicles.size(), -std::numeric_limits<double>::max());
514}
515
516
517std::string
519 std::ostringstream oss;
520 oss.setf(std::ios::fixed, std::ios::floatfield);
521 oss << std::setprecision(2);
522 for (int i = 0; i < (int)myVehicles.size(); ++i) {
523 oss << Named::getIDSecure(myVehicles[i]) << ":";
524 if (myVehicles[i] == 0) {
525 oss << "inf:-inf";
526 } else {
527 oss << myDistances[i] << ":" << myMissingGaps[i];
528 }
529 if (i < (int)myVehicles.size() - 1) {
530 oss << ", ";
531 }
532 }
533 oss << " free=" << myFreeSublanes;
534 return oss.str();
535}
536
537
538/****************************************************************************/
std::pair< const MSVehicle *, double > CLeaderDist
SUMOTime DELTA_T
Definition SUMOTime.cpp:38
T MIN2(T a, T b)
Definition StdDefs.h:80
T MAX2(T a, T b)
Definition StdDefs.h:86
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)
double getMaxDecel() const
Get the vehicle type's maximal comfortable deceleration [m/s^2].
Definition MSCFModel.h:269
std::vector< double > myMissingGaps
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:100
Representation of a lane in the micro simulation.
Definition MSLane.h:84
MSEdge & getEdge() const
Returns the lane's edge.
Definition MSLane.h:769
saves leader/follower vehicles and their distances relative to an ego vehicle
virtual void addLeaders(MSLeaderDistanceInfo &other)
updatd empty sublanes with vehicles and gaps from other
virtual std::string toString() const
print a debugging representation
double getMinDistToStopped() const
return minimum distance to a stopped vehicle or max double
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
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)
bool hasVehicle(const MSVehicle *veh) const
whether the given vehicle is part of this leaderInfo
std::vector< const MSVehicle * > myVehicles
int myFreeSublanes
the number of free sublanes
int myOffset
an extra offset for shifting the interpretation of sublane borders (default [0,myWidth])
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
void getSublaneBorders(int sublane, double latOffset, double &rightSide, double &leftSide) const
int numSublanes() const
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
void getSubLanes(const MSVehicle *veh, double latOffset, int &rightmost, int &leftmost) const
double myWidth
the width of the lane to which this instance applies
Representation of a vehicle in the micro simulation.
Definition MSVehicle.h:77
MSAbstractLaneChangeModel & getLaneChangeModel()
double getActionStepLengthSecs() const
Returns the vehicle's action step length in secs, i.e. the interval between two action points.
Definition MSVehicle.h:533
SUMOTime getActionStepLength() const
Returns the vehicle's action step length in millisecs, i.e. the interval between two action points.
Definition MSVehicle.h:525
const MSLane * getLane() const
Returns the lane the vehicle is on.
Definition MSVehicle.h:581
double getLateralPositionOnLane() const
Get the vehicle's lateral position on the lane.
Definition MSVehicle.h:413
double getSpeed() const
Returns the vehicle's current speed.
Definition MSVehicle.h:490
const MSCFModel & getCarFollowModel() const
Returns the vehicle's car following model definition.
Definition MSVehicle.h:969
double getPositionOnLane() const
Get the vehicle's position along the lane.
Definition MSVehicle.h:374
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