Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
eclipse
GitHub Repository: eclipse/sumo
Path: blob/main/src/microsim/MSLeaderInfo.cpp
185785 views
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
/****************************************************************************/
14
/// @file MSLeaderInfo.cpp
15
/// @author Jakob Erdmann
16
/// @date Oct 2015
17
///
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>
28
#include <microsim/lcmodels/MSAbstractLaneChangeModel.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
48
myFreeSublanes -= egoRightMost;
49
myFreeSublanes -= (int)myVehicles.size() - 1 - egoLeftMost;
50
}
51
}
52
53
54
MSLeaderInfo::~MSLeaderInfo() { }
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) {
82
myFreeSublanes--;
83
}
84
myVehicles[sublane] = veh;
85
myHasVehicles = true;
86
}
87
}
88
return myFreeSublanes;
89
}
90
91
92
void
93
MSLeaderInfo::clear() {
94
myVehicles.assign(myVehicles.size(), (MSVehicle*)nullptr);
95
myFreeSublanes = (int)myVehicles.size();
96
if (egoRightMost >= 0) {
97
myFreeSublanes -= egoRightMost;
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());
156
const double res = MSGlobals::gLateralResolution > 0 ? MSGlobals::gLateralResolution : myWidth;
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
171
MSLeaderInfo::toString() const {
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
187
MSLeaderInfo::setSublaneOffset(int offset) {
188
assert(MSGlobals::gLateralResolution > 0);
189
myOffset = offset;
190
}
191
192
193
bool
194
MSLeaderInfo::hasStoppedVehicle() const {
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
207
bool
208
MSLeaderInfo::hasVehicle(const MSVehicle* veh) const {
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
220
void
221
MSLeaderInfo::removeOpposite(const MSLane* lane) {
222
for (int i = 0; i < (int)myVehicles.size(); ++i) {
223
const MSVehicle* veh = myVehicles[i];
224
if (veh != 0 &&
225
(veh->getLaneChangeModel().isOpposite()
226
|| &lane->getEdge() != &veh->getLane()->getEdge())) {
227
myVehicles[i] = nullptr;
228
}
229
}
230
}
231
232
233
// ===========================================================================
234
// MSLeaderDistanceInfo member method definitions
235
// ===========================================================================
236
MSLeaderDistanceInfo::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
242
MSLeaderDistanceInfo::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
250
MSLeaderDistanceInfo::~MSLeaderDistanceInfo() { }
251
252
253
int
254
MSLeaderDistanceInfo::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) {
269
myFreeSublanes--;
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) {
287
myFreeSublanes--;
288
}
289
myVehicles[sublaneIdx] = veh;
290
myDistances[sublaneIdx] = gap;
291
myHasVehicles = true;
292
}
293
}
294
return myFreeSublanes;
295
}
296
297
298
void
299
MSLeaderDistanceInfo::addLeaders(MSLeaderDistanceInfo& other) {
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
311
void
312
MSLeaderDistanceInfo::clear() {
313
MSLeaderInfo::clear();
314
myDistances.assign(myVehicles.size(), std::numeric_limits<double>::max());
315
}
316
317
318
CLeaderDist
319
MSLeaderDistanceInfo::operator[](int sublane) const {
320
assert(sublane >= 0);
321
assert(sublane < (int)myVehicles.size());
322
return std::make_pair(myVehicles[sublane], myDistances[sublane]);
323
}
324
325
326
std::string
327
MSLeaderDistanceInfo::toString() const {
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
346
void
347
MSLeaderDistanceInfo::fixOppositeGaps(bool isFollower) {
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
362
void
363
MSLeaderDistanceInfo::patchGaps(double amount) {
364
for (int i = 0; i < (int)myVehicles.size(); ++i) {
365
if (myVehicles[i] != nullptr) {
366
myDistances[i] += amount;
367
}
368
}
369
}
370
371
CLeaderDist
372
MSLeaderDistanceInfo::getClosest() const {
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
388
void
389
MSLeaderDistanceInfo::moveSamePosTo(const MSVehicle* ego, MSLeaderDistanceInfo& other) {
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
403
double
404
MSLeaderDistanceInfo::getMinDistToStopped() const {
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
423
MSCriticalFollowerDistanceInfo::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
430
MSCriticalFollowerDistanceInfo::~MSCriticalFollowerDistanceInfo() { }
431
432
433
int
434
MSCriticalFollowerDistanceInfo::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) {
476
myFreeSublanes--;
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) {
498
myFreeSublanes--;
499
}
500
myVehicles[sublaneIdx] = veh;
501
myDistances[sublaneIdx] = gap;
502
myMissingGaps[sublaneIdx] = missingGap;
503
myHasVehicles = true;
504
}
505
}
506
return myFreeSublanes;
507
}
508
509
510
void
511
MSCriticalFollowerDistanceInfo::clear() {
512
MSLeaderDistanceInfo::clear();
513
myMissingGaps.assign(myVehicles.size(), -std::numeric_limits<double>::max());
514
}
515
516
517
std::string
518
MSCriticalFollowerDistanceInfo::toString() const {
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
/****************************************************************************/
539
540