Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
eclipse
GitHub Repository: eclipse/sumo
Path: blob/main/src/microsim/MSLane.cpp
185785 views
1
/****************************************************************************/
2
// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3
// Copyright (C) 2001-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 MSLane.cpp
15
/// @author Christian Roessel
16
/// @author Jakob Erdmann
17
/// @author Daniel Krajzewicz
18
/// @author Tino Morenz
19
/// @author Axel Wegener
20
/// @author Michael Behrisch
21
/// @author Christoph Sommer
22
/// @author Mario Krumnow
23
/// @author Leonhard Luecken
24
/// @author Mirko Barthauer
25
/// @date Mon, 05 Mar 2001
26
///
27
// Representation of a lane in the micro simulation
28
/****************************************************************************/
29
#include <config.h>
30
31
#include <cmath>
32
#include <bitset>
33
#include <iostream>
34
#include <cassert>
35
#include <functional>
36
#include <algorithm>
37
#include <iterator>
38
#include <exception>
39
#include <climits>
40
#include <set>
41
#include <utils/common/UtilExceptions.h>
42
#include <utils/common/StdDefs.h>
43
#include <utils/common/MsgHandler.h>
44
#include <utils/common/ToString.h>
45
#ifdef HAVE_FOX
46
#include <utils/common/ScopedLocker.h>
47
#endif
48
#include <utils/options/OptionsCont.h>
49
#include <utils/emissions/HelpersHarmonoise.h>
50
#include <utils/geom/GeomHelper.h>
51
#include <libsumo/TraCIConstants.h>
52
#include <microsim/transportables/MSPModel.h>
53
#include <microsim/transportables/MSTransportableControl.h>
54
#include <microsim/traffic_lights/MSRailSignal.h>
55
#include <microsim/traffic_lights/MSRailSignalControl.h>
56
#include <microsim/traffic_lights/MSDriveWay.h>
57
#include <microsim/lcmodels/MSAbstractLaneChangeModel.h>
58
#include <microsim/devices/MSDevice_Taxi.h>
59
#include <mesosim/MELoop.h>
60
#include "MSNet.h"
61
#include "MSVehicleType.h"
62
#include "MSEdge.h"
63
#include "MSEdgeControl.h"
64
#include "MSJunction.h"
65
#include "MSLogicJunction.h"
66
#include "MSLink.h"
67
#include "MSLane.h"
68
#include "MSVehicleTransfer.h"
69
#include "MSGlobals.h"
70
#include "MSVehicleControl.h"
71
#include "MSInsertionControl.h"
72
#include "MSVehicleControl.h"
73
#include "MSLeaderInfo.h"
74
#include "MSVehicle.h"
75
#include "MSStop.h"
76
77
//#define DEBUG_INSERTION
78
//#define DEBUG_PLAN_MOVE
79
//#define DEBUG_EXEC_MOVE
80
//#define DEBUG_CONTEXT
81
//#define DEBUG_PARTIALS
82
//#define DEBUG_OPPOSITE
83
//#define DEBUG_VEHICLE_CONTAINER
84
//#define DEBUG_COLLISIONS
85
//#define DEBUG_JUNCTION_COLLISIONS
86
//#define DEBUG_PEDESTRIAN_COLLISIONS
87
//#define DEBUG_LANE_SORTER
88
//#define DEBUG_NO_CONNECTION
89
//#define DEBUG_SURROUNDING
90
//#define DEBUG_EXTRAPOLATE_DEPARTPOS
91
//#define DEBUG_ITERATOR
92
93
//#define DEBUG_COND (false)
94
//#define DEBUG_COND (true)
95
#define DEBUG_COND (isSelected())
96
#define DEBUG_COND2(obj) ((obj != nullptr && (obj)->isSelected()))
97
//#define DEBUG_COND (getID() == "ego")
98
//#define DEBUG_COND2(obj) ((obj != 0 && (obj)->getID() == "ego"))
99
//#define DEBUG_COND2(obj) (true)
100
101
102
// ===========================================================================
103
// static member definitions
104
// ===========================================================================
105
MSLane::DictType MSLane::myDict;
106
MSLane::CollisionAction MSLane::myCollisionAction(MSLane::COLLISION_ACTION_TELEPORT);
107
MSLane::CollisionAction MSLane::myIntermodalCollisionAction(MSLane::COLLISION_ACTION_WARN);
108
bool MSLane::myCheckJunctionCollisions(false);
109
double MSLane::myCheckJunctionCollisionMinGap(0);
110
SUMOTime MSLane::myCollisionStopTime(0);
111
SUMOTime MSLane::myIntermodalCollisionStopTime(0);
112
double MSLane::myCollisionMinGapFactor(1.0);
113
bool MSLane::myExtrapolateSubstepDepart(false);
114
std::vector<SumoRNG> MSLane::myRNGs;
115
DepartSpeedDefinition MSLane::myDefaultDepartSpeedDefinition(DepartSpeedDefinition::DEFAULT);
116
double MSLane::myDefaultDepartSpeed(0);
117
118
119
// ===========================================================================
120
// internal class method definitions
121
// ===========================================================================
122
void
123
MSLane::StoringVisitor::add(const MSLane* const l) const {
124
switch (myDomain) {
125
case libsumo::CMD_GET_VEHICLE_VARIABLE: {
126
for (const MSVehicle* veh : l->getVehiclesSecure()) {
127
if (myShape.distance2D(veh->getPosition()) <= myRange) {
128
myObjects.insert(veh);
129
}
130
}
131
for (const MSBaseVehicle* veh : l->getParkingVehicles()) {
132
if (myShape.distance2D(veh->getPosition()) <= myRange) {
133
myObjects.insert(veh);
134
}
135
}
136
l->releaseVehicles();
137
}
138
break;
139
case libsumo::CMD_GET_PERSON_VARIABLE: {
140
l->getVehiclesSecure();
141
std::vector<MSTransportable*> persons = l->getEdge().getSortedPersons(MSNet::getInstance()->getCurrentTimeStep(), true);
142
for (auto p : persons) {
143
if (myShape.distance2D(p->getPosition()) <= myRange) {
144
myObjects.insert(p);
145
}
146
}
147
l->releaseVehicles();
148
}
149
break;
150
case libsumo::CMD_GET_EDGE_VARIABLE: {
151
if (myShape.size() != 1 || l->getShape().distance2D(myShape[0]) <= myRange) {
152
myObjects.insert(&l->getEdge());
153
}
154
}
155
break;
156
case libsumo::CMD_GET_LANE_VARIABLE: {
157
if (myShape.size() != 1 || l->getShape().distance2D(myShape[0]) <= myRange) {
158
myObjects.insert(l);
159
}
160
}
161
break;
162
default:
163
break;
164
165
}
166
}
167
168
169
MSLane::AnyVehicleIterator&
170
MSLane::AnyVehicleIterator::operator++() {
171
if (nextIsMyVehicles()) {
172
if (myI1 != myI1End) {
173
myI1 += myDirection;
174
} else if (myI3 != myI3End) {
175
myI3 += myDirection;
176
}
177
// else: already at end
178
} else {
179
myI2 += myDirection;
180
}
181
//if (DEBUG_COND2(myLane)) std::cout << SIMTIME << " AnyVehicleIterator::operator++ lane=" << myLane->getID() << " myI1=" << myI1 << " myI2=" << myI2 << "\n";
182
return *this;
183
}
184
185
186
const MSVehicle*
187
MSLane::AnyVehicleIterator::operator*() {
188
if (nextIsMyVehicles()) {
189
if (myI1 != myI1End) {
190
return myLane->myVehicles[myI1];
191
} else if (myI3 != myI3End) {
192
return myLane->myTmpVehicles[myI3];
193
} else {
194
assert(myI2 == myI2End);
195
return nullptr;
196
}
197
} else {
198
return myLane->myPartialVehicles[myI2];
199
}
200
}
201
202
203
bool
204
MSLane::AnyVehicleIterator::nextIsMyVehicles() const {
205
#ifdef DEBUG_ITERATOR
206
if (DEBUG_COND2(myLane)) std::cout << SIMTIME << " AnyVehicleIterator::nextIsMyVehicles lane=" << myLane->getID()
207
<< " myI1=" << myI1
208
<< " myI1End=" << myI1End
209
<< " myI2=" << myI2
210
<< " myI2End=" << myI2End
211
<< " myI3=" << myI3
212
<< " myI3End=" << myI3End
213
<< "\n";
214
#endif
215
if (myI1 == myI1End && myI3 == myI3End) {
216
if (myI2 != myI2End) {
217
return false;
218
} else {
219
return true; // @note. must be caught
220
}
221
} else {
222
if (myI2 == myI2End) {
223
return true;
224
} else {
225
MSVehicle* cand = myI1 == myI1End ? myLane->myTmpVehicles[myI3] : myLane->myVehicles[myI1];
226
#ifdef DEBUG_ITERATOR
227
if (DEBUG_COND2(myLane)) std::cout << " "
228
<< " veh1=" << cand->getID()
229
<< " isTmp=" << (myI1 == myI1End)
230
<< " veh2=" << myLane->myPartialVehicles[myI2]->getID()
231
<< " pos1=" << cand->getPositionOnLane(myLane)
232
<< " pos2=" << myLane->myPartialVehicles[myI2]->getPositionOnLane(myLane)
233
<< "\n";
234
#endif
235
if (cand->getPositionOnLane() < myLane->myPartialVehicles[myI2]->getPositionOnLane(myLane)) {
236
return myDownstream;
237
} else {
238
return !myDownstream;
239
}
240
}
241
}
242
}
243
244
245
// ===========================================================================
246
// member method definitions
247
// ===========================================================================
248
#ifdef _MSC_VER
249
#pragma warning(push)
250
#pragma warning(disable: 4355) // mask warning about "this" in initializers
251
#endif
252
MSLane::MSLane(const std::string& id, double maxSpeed, double friction, double length, MSEdge* const edge,
253
int numericalID, const PositionVector& shape, double width,
254
SVCPermissions permissions,
255
SVCPermissions changeLeft, SVCPermissions changeRight,
256
int index, bool isRampAccel,
257
const std::string& type,
258
const PositionVector& outlineShape) :
259
Named(id),
260
myNumericalID(numericalID), myShape(shape), myIndex(index),
261
myVehicles(), myLength(length), myWidth(width),
262
myEdge(edge), myMaxSpeed(maxSpeed),
263
myFrictionCoefficient(friction),
264
mySpeedByVSS(false),
265
mySpeedByTraCI(false),
266
myPermissions(permissions),
267
myChangeLeft(changeLeft),
268
myChangeRight(changeRight),
269
myOriginalPermissions(permissions),
270
myLogicalPredecessorLane(nullptr),
271
myCanonicalPredecessorLane(nullptr),
272
myCanonicalSuccessorLane(nullptr),
273
myBruttoVehicleLengthSum(0), myNettoVehicleLengthSum(0),
274
myBruttoVehicleLengthSumToRemove(0), myNettoVehicleLengthSumToRemove(0),
275
myRecalculateBruttoSum(false),
276
myLeaderInfo(width, nullptr, 0.),
277
myFollowerInfo(width, nullptr, 0.),
278
myLeaderInfoTime(SUMOTime_MIN),
279
myFollowerInfoTime(SUMOTime_MIN),
280
myLengthGeometryFactor(MAX2(POSITION_EPS, myShape.length()) / myLength), // factor should not be 0
281
myIsRampAccel(isRampAccel),
282
myLaneType(type),
283
myRightSideOnEdge(0), // initialized in MSEdge::initialize
284
myRightmostSublane(0),
285
myNeedsCollisionCheck(false),
286
myOpposite(nullptr),
287
myBidiLane(nullptr),
288
#ifdef HAVE_FOX
289
mySimulationTask(*this, 0),
290
#endif
291
myStopWatch(3) {
292
// initialized in MSEdge::initialize
293
initRestrictions();// may be reloaded again from initialized in MSEdge::closeBuilding
294
assert(myRNGs.size() > 0);
295
myRNGIndex = numericalID % myRNGs.size();
296
if (outlineShape.size() > 0) {
297
myOutlineShape = new PositionVector(outlineShape);
298
}
299
}
300
#ifdef _MSC_VER
301
#pragma warning(pop)
302
#endif
303
304
305
MSLane::~MSLane() {
306
for (MSLink* const l : myLinks) {
307
delete l;
308
}
309
delete myOutlineShape;
310
}
311
312
313
void
314
MSLane::initRestrictions() {
315
// simplify unit testing without MSNet instance
316
myRestrictions = MSGlobals::gUnitTests ? nullptr : MSNet::getInstance()->getRestrictions(myEdge->getEdgeType());
317
}
318
319
320
void
321
MSLane::checkBufferType() {
322
if (MSGlobals::gNumSimThreads <= 1) {
323
myVehBuffer.unsetCondition();
324
// } else {
325
// this is an idea for better memory locality, lanes with nearby numerical ids get the same rng and thus the same thread
326
// first tests show no visible effect though
327
// myRNGIndex = myNumericalID * myRNGs.size() / dictSize();
328
}
329
}
330
331
332
void
333
MSLane::addLink(MSLink* link) {
334
myLinks.push_back(link);
335
}
336
337
338
void
339
MSLane::setOpposite(MSLane* oppositeLane) {
340
myOpposite = oppositeLane;
341
if (myOpposite != nullptr && getLength() > myOpposite->getLength()) {
342
WRITE_WARNINGF(TL("Unequal lengths of neigh lane '%' and lane '%' (% != %)."), getID(), myOpposite->getID(), getLength(), myOpposite->getLength());
343
}
344
}
345
346
void
347
MSLane::setBidiLane(MSLane* bidiLane) {
348
myBidiLane = bidiLane;
349
if (myBidiLane != nullptr && getLength() > myBidiLane->getLength()) {
350
if (isNormal() || MSGlobals::gUsingInternalLanes) {
351
WRITE_WARNINGF(TL("Unequal lengths of bidi lane '%' and lane '%' (% != %)."), getID(), myBidiLane->getID(), getLength(), myBidiLane->getLength());
352
}
353
}
354
}
355
356
357
358
// ------ interaction with MSMoveReminder ------
359
void
360
MSLane::addMoveReminder(MSMoveReminder* rem, bool addToVehicles) {
361
myMoveReminders.push_back(rem);
362
if (addToVehicles) {
363
for (MSVehicle* const veh : myVehicles) {
364
veh->addReminder(rem);
365
}
366
}
367
// XXX: Here, the partial occupators are ignored!? Refs. #3255
368
}
369
370
371
void
372
MSLane::removeMoveReminder(MSMoveReminder* rem) {
373
auto it = std::find(myMoveReminders.begin(), myMoveReminders.end(), rem);
374
if (it != myMoveReminders.end()) {
375
myMoveReminders.erase(it);
376
for (MSVehicle* const veh : myVehicles) {
377
veh->removeReminder(rem);
378
}
379
}
380
}
381
382
383
double
384
MSLane::setPartialOccupation(MSVehicle* v) {
385
// multithreading: there are concurrent writes to myNeedsCollisionCheck but all of them should set it to true
386
myNeedsCollisionCheck = true; // always check
387
#ifdef DEBUG_PARTIALS
388
if (DEBUG_COND2(v)) {
389
std::cout << SIMTIME << " setPartialOccupation. lane=" << getID() << " veh=" << v->getID() << "\n";
390
}
391
#endif
392
// XXX update occupancy here?
393
#ifdef HAVE_FOX
394
ScopedLocker<> lock(myPartialOccupatorMutex, MSGlobals::gNumSimThreads > 1);
395
#endif
396
//assert(std::find(myPartialVehicles.begin(), myPartialVehicles.end(), v) == myPartialVehicles.end());
397
myPartialVehicles.push_back(v);
398
return myLength;
399
}
400
401
402
void
403
MSLane::resetPartialOccupation(MSVehicle* v) {
404
#ifdef HAVE_FOX
405
ScopedLocker<> lock(myPartialOccupatorMutex, MSGlobals::gNumSimThreads > 1);
406
#endif
407
#ifdef DEBUG_PARTIALS
408
if (DEBUG_COND2(v)) {
409
std::cout << SIMTIME << " resetPartialOccupation. lane=" << getID() << " veh=" << v->getID() << "\n";
410
}
411
#endif
412
for (VehCont::iterator i = myPartialVehicles.begin(); i != myPartialVehicles.end(); ++i) {
413
if (v == *i) {
414
myPartialVehicles.erase(i);
415
// XXX update occupancy here?
416
//std::cout << " removed from myPartialVehicles\n";
417
return;
418
}
419
}
420
// bluelight eqipped vehicle can teleport onto the intersection without using a connection
421
assert(false || MSGlobals::gClearState || v->getLaneChangeModel().hasBlueLight());
422
}
423
424
425
void
426
MSLane::setManeuverReservation(MSVehicle* v) {
427
#ifdef DEBUG_CONTEXT
428
if (DEBUG_COND2(v)) {
429
std::cout << SIMTIME << " setManeuverReservation. lane=" << getID() << " veh=" << v->getID() << "\n";
430
}
431
#endif
432
myManeuverReservations.push_back(v);
433
}
434
435
436
void
437
MSLane::resetManeuverReservation(MSVehicle* v) {
438
#ifdef DEBUG_CONTEXT
439
if (DEBUG_COND2(v)) {
440
std::cout << SIMTIME << " resetManeuverReservation(): lane=" << getID() << " veh=" << v->getID() << "\n";
441
}
442
#endif
443
for (VehCont::iterator i = myManeuverReservations.begin(); i != myManeuverReservations.end(); ++i) {
444
if (v == *i) {
445
myManeuverReservations.erase(i);
446
return;
447
}
448
}
449
assert(false);
450
}
451
452
453
// ------ Vehicle emission ------
454
void
455
MSLane::incorporateVehicle(MSVehicle* veh, double pos, double speed, double posLat, const MSLane::VehCont::iterator& at, MSMoveReminder::Notification notification) {
456
myNeedsCollisionCheck = true;
457
assert(pos <= myLength);
458
bool wasInactive = myVehicles.size() == 0;
459
veh->enterLaneAtInsertion(this, pos, speed, posLat, notification);
460
if (at == myVehicles.end()) {
461
// vehicle will be the first on the lane
462
myVehicles.push_back(veh);
463
} else {
464
myVehicles.insert(at, veh);
465
}
466
myBruttoVehicleLengthSum += veh->getVehicleType().getLengthWithGap();
467
myNettoVehicleLengthSum += veh->getVehicleType().getLength();
468
myEdge->markDelayed();
469
if (wasInactive) {
470
MSNet::getInstance()->getEdgeControl().gotActive(this);
471
}
472
if (getBidiLane() != nullptr && (!isRailway(veh->getVClass()) || (getPermissions() & ~SVC_RAIL_CLASSES) != 0)) {
473
// railways don't need to "see" each other when moving in opposite directions on the same track (efficiency)
474
getBidiLane()->setPartialOccupation(veh);
475
}
476
}
477
478
479
bool
480
MSLane::lastInsertion(MSVehicle& veh, double mspeed, double posLat, bool patchSpeed) {
481
double pos = getLength() - POSITION_EPS;
482
MSVehicle* leader = getLastAnyVehicle();
483
// back position of leader relative to this lane
484
double leaderBack;
485
if (leader == nullptr) {
486
/// look for a leaders on consecutive lanes
487
veh.setTentativeLaneAndPosition(this, pos, posLat);
488
veh.updateBestLanes(false, this);
489
std::pair<MSVehicle* const, double> leaderInfo = getLeader(&veh, pos, veh.getBestLanesContinuation(), veh.getCarFollowModel().brakeGap(mspeed));
490
leader = leaderInfo.first;
491
leaderBack = pos + leaderInfo.second + veh.getVehicleType().getMinGap();
492
} else {
493
leaderBack = leader->getBackPositionOnLane(this);
494
//std::cout << " leaderPos=" << leader->getPositionOnLane(this) << " leaderBack=" << leader->getBackPositionOnLane(this) << " leaderLane=" << leader->getLane()->getID() << "\n";
495
}
496
if (leader == nullptr) {
497
// insert at the end of this lane
498
return isInsertionSuccess(&veh, mspeed, pos, posLat, patchSpeed, MSMoveReminder::NOTIFICATION_DEPARTED);
499
} else {
500
// try to insert behind the leader
501
const double frontGapNeeded = veh.getCarFollowModel().getSecureGap(&veh, leader, mspeed, leader->getSpeed(), leader->getCarFollowModel().getMaxDecel()) + veh.getVehicleType().getMinGap() + POSITION_EPS;
502
if (leaderBack >= frontGapNeeded) {
503
pos = MIN2(pos, leaderBack - frontGapNeeded);
504
bool result = isInsertionSuccess(&veh, mspeed, pos, posLat, patchSpeed, MSMoveReminder::NOTIFICATION_DEPARTED);
505
//if (!result) std::cout << " insertLast failed for " << veh.getID() << " pos=" << pos << " leaderBack=" << leaderBack << " frontGapNeeded=" << frontGapNeeded << "\n";
506
return result;
507
}
508
//std::cout << " insertLast failed for " << veh.getID() << " pos=" << pos << " leaderBack=" << leaderBack << " frontGapNeeded=" << frontGapNeeded << "\n";
509
}
510
return false;
511
}
512
513
514
bool
515
MSLane::freeInsertion(MSVehicle& veh, double mspeed, double posLat,
516
MSMoveReminder::Notification notification) {
517
// try to insert teleporting vehicles fully on this lane
518
double maxPos = myLength;
519
if (veh.hasStops() && veh.getNextStop().edge == veh.getCurrentRouteEdge()) {
520
maxPos = MAX2(0.0, veh.getNextStop().getEndPos(veh));
521
}
522
const double minPos = (notification == MSMoveReminder::NOTIFICATION_TELEPORT ?
523
MIN2(maxPos, veh.getVehicleType().getLength()) : 0);
524
veh.setTentativeLaneAndPosition(this, minPos, 0);
525
if (myVehicles.size() == 0) {
526
// ensure sufficient gap to followers on predecessor lanes
527
const double backOffset = minPos - veh.getVehicleType().getLength();
528
const double missingRearGap = getMissingRearGap(&veh, backOffset, mspeed);
529
if (missingRearGap > 0) {
530
if (minPos + missingRearGap <= maxPos) {
531
// @note. The rear gap is tailored to mspeed. If it changes due
532
// to a leader vehicle (on subsequent lanes) insertion will
533
// still fail. Under the right combination of acceleration and
534
// deceleration values there might be another insertion
535
// positions that would be successful be we do not look for it.
536
//std::cout << SIMTIME << " freeInsertion lane=" << getID() << " veh=" << veh.getID() << " unclear @(340)\n";
537
return isInsertionSuccess(&veh, mspeed, minPos + missingRearGap, posLat, true, notification);
538
}
539
return false;
540
} else {
541
return isInsertionSuccess(&veh, mspeed, minPos, posLat, true, notification);
542
}
543
544
} else {
545
// check whether the vehicle can be put behind the last one if there is such
546
const MSVehicle* const leader = myVehicles.back(); // @todo reproduction of bogus old behavior. see #1961
547
const double leaderPos = leader->getBackPositionOnLane(this);
548
const double speed = leader->getSpeed();
549
const double frontGapNeeded = veh.getCarFollowModel().getSecureGap(&veh, leader, speed, leader->getSpeed(), leader->getCarFollowModel().getMaxDecel()) + veh.getVehicleType().getMinGap();
550
if (leaderPos >= frontGapNeeded) {
551
const double tspeed = MIN2(veh.getCarFollowModel().insertionFollowSpeed(&veh, mspeed, frontGapNeeded, leader->getSpeed(), leader->getCarFollowModel().getMaxDecel(), leader), mspeed);
552
// check whether we can insert our vehicle behind the last vehicle on the lane
553
if (isInsertionSuccess(&veh, tspeed, minPos, posLat, true, notification)) {
554
//std::cout << SIMTIME << " freeInsertion lane=" << getID() << " veh=" << veh.getID() << " pos=" << minPos<< " speed=" << speed << " tspeed=" << tspeed << " frontGapNeeded=" << frontGapNeeded << " lead=" << leader->getID() << " lPos=" << leaderPos << "\n vehsOnLane=" << toString(myVehicles) << " @(358)\n";
555
return true;
556
}
557
}
558
}
559
// go through the lane, look for free positions (starting after the last vehicle)
560
MSLane::VehCont::iterator predIt = myVehicles.begin();
561
while (predIt != myVehicles.end()) {
562
// get leader (may be zero) and follower
563
// @todo compute secure position in regard to sublane-model
564
const MSVehicle* leader = predIt != myVehicles.end() - 1 ? *(predIt + 1) : nullptr;
565
if (leader == nullptr && myPartialVehicles.size() > 0) {
566
leader = myPartialVehicles.front();
567
}
568
const MSVehicle* follower = *predIt;
569
570
// patch speed if allowed
571
double speed = mspeed;
572
if (leader != nullptr) {
573
speed = MIN2(leader->getSpeed(), mspeed);
574
}
575
576
// compute the space needed to not collide with leader
577
double frontMax = maxPos;
578
if (leader != nullptr) {
579
double leaderRearPos = leader->getBackPositionOnLane(this);
580
double frontGapNeeded = veh.getCarFollowModel().getSecureGap(&veh, leader, speed, leader->getSpeed(), leader->getCarFollowModel().getMaxDecel()) + veh.getVehicleType().getMinGap();
581
frontMax = MIN2(maxPos, leaderRearPos - frontGapNeeded);
582
}
583
// compute the space needed to not let the follower collide
584
const double followPos = follower->getPositionOnLane() + follower->getVehicleType().getMinGap();
585
const double backGapNeeded = follower->getCarFollowModel().getSecureGap(follower, &veh, follower->getSpeed(), veh.getSpeed(), veh.getCarFollowModel().getMaxDecel());
586
const double backMin = followPos + backGapNeeded + veh.getVehicleType().getLength();
587
588
// check whether there is enough room (given some extra space for rounding errors)
589
if (frontMax > minPos && backMin + POSITION_EPS < frontMax) {
590
// try to insert vehicle (should be always ok)
591
if (isInsertionSuccess(&veh, speed, backMin + POSITION_EPS, posLat, true, notification)) {
592
//std::cout << SIMTIME << " freeInsertion lane=" << getID() << " veh=" << veh.getID() << " @(393)\n";
593
return true;
594
}
595
}
596
++predIt;
597
}
598
// first check at lane's begin
599
//std::cout << SIMTIME << " freeInsertion lane=" << getID() << " veh=" << veh.getID() << " fail final\n";
600
return false;
601
}
602
603
604
double
605
MSLane::getDepartSpeed(const MSVehicle& veh, bool& patchSpeed) {
606
double speed = 0;
607
const SUMOVehicleParameter& pars = veh.getParameter();
608
DepartSpeedDefinition dsd = pars.departSpeedProcedure;
609
if (dsd == DepartSpeedDefinition::DEFAULT) {
610
dsd = myDefaultDepartSpeedDefinition;
611
if (dsd == DepartSpeedDefinition::GIVEN) {
612
speed = myDefaultDepartSpeed;
613
}
614
} else if (dsd == DepartSpeedDefinition::GIVEN) {
615
speed = pars.departSpeed;;
616
}
617
switch (dsd) {
618
case DepartSpeedDefinition::GIVEN:
619
patchSpeed = false;
620
break;
621
case DepartSpeedDefinition::RANDOM:
622
speed = roundDecimal(RandHelper::rand(getVehicleMaxSpeed(&veh)), gPrecisionRandom);
623
patchSpeed = true;
624
break;
625
case DepartSpeedDefinition::MAX:
626
speed = getVehicleMaxSpeed(&veh);
627
patchSpeed = true;
628
break;
629
case DepartSpeedDefinition::DESIRED:
630
speed = getVehicleMaxSpeed(&veh);
631
patchSpeed = false;
632
break;
633
case DepartSpeedDefinition::LIMIT:
634
speed = getVehicleMaxSpeed(&veh) / veh.getChosenSpeedFactor();
635
patchSpeed = false;
636
break;
637
case DepartSpeedDefinition::LAST: {
638
MSVehicle* last = getLastAnyVehicle();
639
speed = getVehicleMaxSpeed(&veh);
640
if (last != nullptr) {
641
speed = MIN2(speed, last->getSpeed());
642
patchSpeed = false;
643
}
644
break;
645
}
646
case DepartSpeedDefinition::AVG: {
647
speed = MIN2(getVehicleMaxSpeed(&veh), getMeanSpeed());
648
if (getLastAnyVehicle() != nullptr) {
649
patchSpeed = false;
650
}
651
break;
652
}
653
case DepartSpeedDefinition::DEFAULT:
654
default:
655
// speed = 0 was set before
656
patchSpeed = false; // @todo check
657
break;
658
}
659
return speed;
660
}
661
662
663
double
664
MSLane::getDepartPosLat(const MSVehicle& veh) {
665
const SUMOVehicleParameter& pars = veh.getParameter();
666
switch (pars.departPosLatProcedure) {
667
case DepartPosLatDefinition::GIVEN:
668
return pars.departPosLat;
669
case DepartPosLatDefinition::RIGHT:
670
return -getWidth() * 0.5 + veh.getVehicleType().getWidth() * 0.5;
671
case DepartPosLatDefinition::LEFT:
672
return getWidth() * 0.5 - veh.getVehicleType().getWidth() * 0.5;
673
case DepartPosLatDefinition::RANDOM: {
674
const double raw = RandHelper::rand(getWidth() - veh.getVehicleType().getWidth()) - getWidth() * 0.5 + veh.getVehicleType().getWidth() * 0.5;
675
return roundDecimal(raw, gPrecisionRandom);
676
}
677
case DepartPosLatDefinition::CENTER:
678
case DepartPosLatDefinition::DEFAULT:
679
// @note:
680
// case DepartPosLatDefinition::FREE
681
// case DepartPosLatDefinition::RANDOM_FREE
682
// are not handled here because they involve multiple insertion attempts
683
default:
684
return 0;
685
}
686
}
687
688
689
bool
690
MSLane::insertVehicle(MSVehicle& veh) {
691
double pos = 0;
692
bool patchSpeed = true; // whether the speed shall be adapted to infrastructure/traffic in front
693
const SUMOVehicleParameter& pars = veh.getParameter();
694
double speed = getDepartSpeed(veh, patchSpeed);
695
double posLat = getDepartPosLat(veh);
696
697
// determine the position
698
switch (pars.departPosProcedure) {
699
case DepartPosDefinition::GIVEN:
700
pos = pars.departPos;
701
if (pos < 0.) {
702
pos += myLength;
703
}
704
break;
705
case DepartPosDefinition::RANDOM:
706
pos = roundDecimal(RandHelper::rand(getLength()), gPrecisionRandom);
707
break;
708
case DepartPosDefinition::RANDOM_FREE: {
709
for (int i = 0; i < 10; i++) {
710
// we will try some random positions ...
711
pos = RandHelper::rand(getLength());
712
posLat = getDepartPosLat(veh); // could be random as well
713
if (isInsertionSuccess(&veh, speed, pos, posLat, patchSpeed, MSMoveReminder::NOTIFICATION_DEPARTED)) {
714
MSNet::getInstance()->getInsertionControl().retractDescheduleDeparture(&veh);
715
return true;
716
}
717
}
718
// ... and if that doesn't work, we put the vehicle to the free position
719
bool success = freeInsertion(veh, speed, posLat);
720
if (success) {
721
MSNet::getInstance()->getInsertionControl().retractDescheduleDeparture(&veh);
722
}
723
return success;
724
}
725
case DepartPosDefinition::FREE:
726
return freeInsertion(veh, speed, posLat);
727
case DepartPosDefinition::LAST:
728
return lastInsertion(veh, speed, posLat, patchSpeed);
729
case DepartPosDefinition::STOP:
730
if (veh.hasStops() && veh.getNextStop().edge == veh.getCurrentRouteEdge()) {
731
// getLastFreePos of stopping place could return negative position to avoid blocking the stop
732
pos = MAX2(0.0, veh.getNextStop().getEndPos(veh));
733
break;
734
}
735
FALLTHROUGH;
736
case DepartPosDefinition::BASE:
737
case DepartPosDefinition::DEFAULT:
738
case DepartPosDefinition::SPLIT_FRONT:
739
default:
740
if (pars.departProcedure == DepartDefinition::SPLIT) {
741
pos = getLength();
742
// find the vehicle from which we are splitting off (should only be a single lane to check)
743
AnyVehicleIterator end = anyVehiclesEnd();
744
for (AnyVehicleIterator it = anyVehiclesBegin(); it != end; ++it) {
745
const MSVehicle* cand = *it;
746
if (cand->isStopped() && cand->getNextStopParameter()->split == veh.getID()) {
747
if (pars.departPosProcedure == DepartPosDefinition::SPLIT_FRONT) {
748
pos = cand->getPositionOnLane() + cand->getVehicleType().getMinGap() + veh.getLength();
749
} else {
750
pos = cand->getBackPositionOnLane() - veh.getVehicleType().getMinGap();
751
}
752
break;
753
}
754
}
755
} else {
756
pos = veh.basePos(myEdge);
757
}
758
break;
759
}
760
// determine the lateral position for special cases
761
if (MSGlobals::gLateralResolution > 0) {
762
switch (pars.departPosLatProcedure) {
763
case DepartPosLatDefinition::RANDOM_FREE: {
764
for (int i = 0; i < 10; i++) {
765
// we will try some random positions ...
766
posLat = RandHelper::rand(getWidth()) - getWidth() * 0.5;
767
if (isInsertionSuccess(&veh, speed, pos, posLat, patchSpeed, MSMoveReminder::NOTIFICATION_DEPARTED)) {
768
return true;
769
}
770
}
771
FALLTHROUGH;
772
}
773
// no break! continue with DepartPosLatDefinition::FREE
774
case DepartPosLatDefinition::FREE: {
775
// systematically test all positions until a free lateral position is found
776
double posLatMin = -getWidth() * 0.5 + veh.getVehicleType().getWidth() * 0.5;
777
double posLatMax = getWidth() * 0.5 - veh.getVehicleType().getWidth() * 0.5;
778
for (posLat = posLatMin; posLat < posLatMax; posLat += MSGlobals::gLateralResolution) {
779
if (isInsertionSuccess(&veh, speed, pos, posLat, patchSpeed, MSMoveReminder::NOTIFICATION_DEPARTED)) {
780
return true;
781
}
782
}
783
return false;
784
}
785
default:
786
break;
787
}
788
}
789
// try to insert
790
const bool success = isInsertionSuccess(&veh, speed, pos, posLat, patchSpeed, MSMoveReminder::NOTIFICATION_DEPARTED);
791
#ifdef DEBUG_EXTRAPOLATE_DEPARTPOS
792
if (DEBUG_COND2(&veh)) {
793
std::cout << SIMTIME << " veh=" << veh.getID() << " success=" << success << " extrapolate=" << myExtrapolateSubstepDepart << " delay=" << veh.getDepartDelay() << " speed=" << speed << "\n";
794
}
795
#endif
796
if (success && myExtrapolateSubstepDepart && veh.getDepartDelay() > 0) {
797
SUMOTime relevantDelay = MIN2(DELTA_T, veh.getDepartDelay());
798
// try to compensate sub-step depart delay by moving the vehicle forward
799
speed = veh.getSpeed(); // may have been adapted in isInsertionSuccess
800
double dist = speed * STEPS2TIME(relevantDelay);
801
std::pair<MSVehicle* const, double> leaderInfo = getLeader(&veh, pos, veh.getBestLanesContinuation());
802
if (leaderInfo.first != nullptr) {
803
MSVehicle* leader = leaderInfo.first;
804
const double frontGapNeeded = veh.getCarFollowModel().getSecureGap(&veh, leader, speed, leader->getSpeed(),
805
leader->getCarFollowModel().getMaxDecel());
806
dist = MIN2(dist, leaderInfo.second - frontGapNeeded);
807
}
808
if (dist > 0) {
809
veh.executeFractionalMove(dist);
810
}
811
}
812
return success;
813
}
814
815
816
bool
817
MSLane::checkFailure(const MSVehicle* aVehicle, double& speed, double& dist, const double nspeed, const bool patchSpeed, const std::string errorMsg, InsertionCheck check) const {
818
if (nspeed < speed) {
819
if (patchSpeed) {
820
speed = MIN2(nspeed, speed);
821
dist = aVehicle->getCarFollowModel().brakeGap(speed) + aVehicle->getVehicleType().getMinGap();
822
} else if (speed > 0) {
823
if ((aVehicle->getInsertionChecks() & (int)check) == 0) {
824
return false;
825
}
826
if (MSGlobals::gEmergencyInsert) {
827
// Check whether vehicle can stop at the given distance when applying emergency braking
828
double emergencyBrakeGap = 0.5 * speed * speed / aVehicle->getCarFollowModel().getEmergencyDecel();
829
if (emergencyBrakeGap <= dist) {
830
// Vehicle may stop in time with emergency deceleration
831
// still, emit a warning
832
WRITE_WARNINGF(TL("Vehicle '%' is inserted in an emergency situation, time=%."), aVehicle->getID(), time2string(SIMSTEP));
833
return false;
834
}
835
}
836
837
if (errorMsg != "") {
838
WRITE_ERRORF(TL("Vehicle '%' will not be able to depart on lane '%' with speed % (%), time=%."),
839
aVehicle->getID(), getID(), speed, errorMsg, time2string(SIMSTEP));
840
MSNet::getInstance()->getInsertionControl().descheduleDeparture(aVehicle);
841
}
842
return true;
843
}
844
}
845
return false;
846
}
847
848
849
bool
850
MSLane::isInsertionSuccess(MSVehicle* aVehicle,
851
double speed, double pos, double posLat, bool patchSpeed,
852
MSMoveReminder::Notification notification) {
853
int insertionChecks = aVehicle->getInsertionChecks();
854
if (pos < 0 || pos > myLength) {
855
// we may not start there
856
WRITE_WARNINGF(TL("Invalid departPos % given for vehicle '%', time=%. Inserting at lane end instead."),
857
pos, aVehicle->getID(), time2string(SIMSTEP));
858
pos = myLength;
859
}
860
861
#ifdef DEBUG_INSERTION
862
if (DEBUG_COND2(aVehicle) || DEBUG_COND) {
863
std::cout << "\nIS_INSERTION_SUCCESS\n"
864
<< SIMTIME << " lane=" << getID()
865
<< " veh '" << aVehicle->getID()
866
<< " bestLanes=" << toString(aVehicle->getBestLanesContinuation(this))
867
<< " pos=" << pos
868
<< " speed=" << speed
869
<< " patchSpeed=" << patchSpeed
870
<< "'\n";
871
}
872
#endif
873
874
aVehicle->setTentativeLaneAndPosition(this, pos, posLat);
875
aVehicle->updateBestLanes(false, this);
876
const MSCFModel& cfModel = aVehicle->getCarFollowModel();
877
const std::vector<MSLane*>& bestLaneConts = aVehicle->getBestLanesContinuation(this);
878
std::vector<MSLane*>::const_iterator ri = bestLaneConts.begin();
879
double seen = getLength() - pos; // == distance from insertion position until the end of the currentLane
880
double dist = cfModel.brakeGap(speed) + aVehicle->getVehicleType().getMinGap();
881
const bool isRail = aVehicle->isRail();
882
if (isRail && insertionChecks != (int)InsertionCheck::NONE
883
&& aVehicle->getParameter().departProcedure != DepartDefinition::SPLIT
884
&& MSRailSignalControl::isSignalized(aVehicle->getVClass())
885
&& isRailwayOrShared(myPermissions)) {
886
const MSDriveWay* dw = MSDriveWay::getDepartureDriveway(aVehicle);
887
MSEdgeVector occupied;
888
if (dw->foeDriveWayOccupied(false, aVehicle, occupied)) {
889
setParameter("insertionBlocked:" + aVehicle->getID(), dw->getID());
890
#ifdef DEBUG_INSERTION
891
if (DEBUG_COND2(aVehicle) || DEBUG_COND) {
892
std::cout << " foe of driveway " + dw->getID() + " has occupied edges " + toString(occupied) << "\n";
893
}
894
#endif
895
return false;
896
}
897
}
898
// do not insert if the bidirectional edge is occupied
899
if (getBidiLane() != nullptr && isRail && getBidiLane()->getVehicleNumberWithPartials() > 0) {
900
if ((insertionChecks & (int)InsertionCheck::BIDI) != 0) {
901
#ifdef DEBUG_INSERTION
902
if (DEBUG_COND2(aVehicle) || DEBUG_COND) {
903
std::cout << " bidi-lane occupied\n";
904
}
905
#endif
906
return false;
907
}
908
}
909
MSLink* firstRailSignal = nullptr;
910
double firstRailSignalDist = -1;
911
912
// before looping through the continuation lanes, check if a stop is scheduled on this lane
913
// (the code is duplicated in the loop)
914
if (aVehicle->hasStops()) {
915
const MSStop& nextStop = aVehicle->getNextStop();
916
if (nextStop.lane == this) {
917
std::stringstream msg;
918
double distToStop, safeSpeed;
919
if (nextStop.pars.speed > 0) {
920
msg << "scheduled waypoint on lane '" << myID << "' too close";
921
distToStop = MAX2(0.0, nextStop.pars.startPos - pos);
922
safeSpeed = cfModel.freeSpeed(aVehicle, speed, distToStop, nextStop.pars.speed, true, MSCFModel::CalcReason::FUTURE);
923
} else {
924
msg << "scheduled stop on lane '" << myID << "' too close";
925
distToStop = nextStop.pars.endPos - pos;
926
safeSpeed = cfModel.stopSpeed(aVehicle, speed, distToStop, MSCFModel::CalcReason::FUTURE);
927
}
928
if (checkFailure(aVehicle, speed, dist, MAX2(0.0, safeSpeed), patchSpeed, msg.str(), InsertionCheck::STOP)) {
929
// we may not drive with the given velocity - we cannot stop at the stop
930
return false;
931
}
932
}
933
}
934
// check leader vehicle first because it could have influenced the departSpeed (for departSpeed=avg)
935
// get the pointer to the vehicle next in front of the given position
936
const MSLeaderInfo leaders = getLastVehicleInformation(aVehicle, 0, pos);
937
//if (aVehicle->getID() == "disabled") std::cout << " leaders=" << leaders.toString() << "\n";
938
const double nspeed = safeInsertionSpeed(aVehicle, -pos, leaders, speed);
939
if (nspeed == INVALID_SPEED || checkFailure(aVehicle, speed, dist, nspeed, patchSpeed, "", InsertionCheck::LEADER_GAP)) {
940
// we may not drive with the given velocity - we crash into the leader
941
#ifdef DEBUG_INSERTION
942
if (DEBUG_COND2(aVehicle) || DEBUG_COND) {
943
std::cout << SIMTIME << " isInsertionSuccess lane=" << getID()
944
<< " veh=" << aVehicle->getID()
945
<< " pos=" << pos
946
<< " posLat=" << posLat
947
<< " patchSpeed=" << patchSpeed
948
<< " speed=" << speed
949
<< " nspeed=" << nspeed
950
<< " leaders=" << leaders.toString()
951
<< " failed (@700)!\n";
952
}
953
#endif
954
return false;
955
}
956
#ifdef DEBUG_INSERTION
957
if (DEBUG_COND2(aVehicle) || DEBUG_COND) {
958
std::cout << SIMTIME << " speed = " << speed << " nspeed = " << nspeed << " leaders=" << leaders.toString() << "\n";
959
}
960
#endif
961
962
const MSRoute& r = aVehicle->getRoute();
963
MSRouteIterator ce = r.begin();
964
int nRouteSuccs = 1;
965
MSLane* currentLane = this;
966
MSLane* nextLane = this;
967
SUMOTime arrivalTime = MSNet::getInstance()->getCurrentTimeStep() + TIME2STEPS(seen / MAX2(speed, SUMO_const_haltingSpeed));
968
while ((seen < dist || (isRail && firstRailSignal == nullptr)) && ri != bestLaneConts.end()) {
969
// get the next link used...
970
std::vector<MSLink*>::const_iterator link = succLinkSec(*aVehicle, nRouteSuccs, *currentLane, bestLaneConts);
971
// get the next used lane (including internal)
972
if (currentLane->isLinkEnd(link)) {
973
if (&currentLane->getEdge() == r.getLastEdge()) {
974
// reached the end of the route
975
if (aVehicle->getParameter().arrivalSpeedProcedure == ArrivalSpeedDefinition::GIVEN) {
976
const double remaining = seen + aVehicle->getArrivalPos() - currentLane->getLength();
977
const double fspeed = cfModel.freeSpeed(aVehicle, speed, remaining, aVehicle->getParameter().arrivalSpeed, true, MSCFModel::CalcReason::FUTURE);
978
if (checkFailure(aVehicle, speed, dist, fspeed,
979
patchSpeed, "arrival speed too low", InsertionCheck::ARRIVAL_SPEED)) {
980
// we may not drive with the given velocity - we cannot match the specified arrival speed
981
return false;
982
}
983
}
984
} else {
985
// lane does not continue
986
if (checkFailure(aVehicle, speed, dist, cfModel.insertionStopSpeed(aVehicle, speed, seen),
987
patchSpeed, "junction '" + currentLane->getEdge().getToJunction()->getID() + "' too close", InsertionCheck::JUNCTION)) {
988
// we may not drive with the given velocity - we cannot stop at the junction
989
return false;
990
}
991
}
992
break;
993
}
994
if (isRail && firstRailSignal == nullptr) {
995
std::string constraintInfo;
996
bool isInsertionOrder;
997
if (MSRailSignal::hasInsertionConstraint(*link, aVehicle, constraintInfo, isInsertionOrder)) {
998
setParameter((isInsertionOrder ? "insertionOrder" : "insertionConstraint:")
999
+ aVehicle->getID(), constraintInfo);
1000
#ifdef DEBUG_INSERTION
1001
if (DEBUG_COND2(aVehicle) || DEBUG_COND) {
1002
std::cout << " insertion constraint at link " << (*link)->getDescription() << " not cleared \n";
1003
}
1004
#endif
1005
return false;
1006
}
1007
}
1008
1009
// might also by a regular traffic_light instead of a rail_signal
1010
if (firstRailSignal == nullptr && (*link)->getTLLogic() != nullptr) {
1011
firstRailSignal = *link;
1012
firstRailSignalDist = seen;
1013
}
1014
nextLane = (*link)->getViaLaneOrLane();
1015
if (!(*link)->opened(arrivalTime, speed, speed, aVehicle->getVehicleType().getLength(), aVehicle->getImpatience(),
1016
cfModel.getMaxDecel(), 0, posLat, nullptr, false, aVehicle)
1017
|| (*link)->railSignalWasPassed()
1018
|| !(*link)->havePriority()) {
1019
// have to stop at junction
1020
std::string errorMsg = "";
1021
const LinkState state = (*link)->getState();
1022
if (state == LINKSTATE_MINOR
1023
|| state == LINKSTATE_EQUAL
1024
|| state == LINKSTATE_STOP
1025
|| state == LINKSTATE_ALLWAY_STOP) {
1026
// no sense in trying later
1027
errorMsg = "unpriorised junction too close";
1028
} else if ((*link)->getTLLogic() != nullptr && !(*link)->getTLLogic()->getsMajorGreen((*link)->getTLIndex())) {
1029
// traffic light never turns 'G'?
1030
errorMsg = "tlLogic '" + (*link)->getTLLogic()->getID() + "' link " + toString((*link)->getTLIndex()) + " never switches to 'G'";
1031
}
1032
const double laneStopOffset = MAX2(getVehicleStopOffset(aVehicle),
1033
aVehicle->getVehicleType().getParameter().getJMParam(SUMO_ATTR_JM_STOPLINE_CROSSING_GAP, MSPModel::SAFETY_GAP) - (*link)->getDistToFoePedCrossing());
1034
const double remaining = seen - laneStopOffset;
1035
auto dsp = aVehicle->getParameter().departSpeedProcedure;
1036
const bool patchSpeedSpecial = patchSpeed || dsp == DepartSpeedDefinition::DESIRED || dsp == DepartSpeedDefinition::LIMIT;
1037
// patchSpeed depends on the presence of vehicles for these procedures. We never want to abort them here
1038
if (dsp == DepartSpeedDefinition::LAST || dsp == DepartSpeedDefinition::AVG) {
1039
errorMsg = "";
1040
}
1041
if (checkFailure(aVehicle, speed, dist, cfModel.insertionStopSpeed(aVehicle, speed, remaining),
1042
patchSpeedSpecial, errorMsg, InsertionCheck::JUNCTION)) {
1043
// we may not drive with the given velocity - we cannot stop at the junction in time
1044
#ifdef DEBUG_INSERTION
1045
if (DEBUG_COND2(aVehicle) || DEBUG_COND) {
1046
std::cout << SIMTIME << " isInsertionSuccess lane=" << getID()
1047
<< " veh=" << aVehicle->getID()
1048
<< " patchSpeed=" << patchSpeed
1049
<< " speed=" << speed
1050
<< " remaining=" << remaining
1051
<< " leader=" << currentLane->getLastVehicleInformation(aVehicle, 0, 0).toString()
1052
<< " last=" << Named::getIDSecure(getLastAnyVehicle())
1053
<< " meanSpeed=" << getMeanSpeed()
1054
<< " failed (@926)!\n";
1055
}
1056
#endif
1057
return false;
1058
}
1059
#ifdef DEBUG_INSERTION
1060
if (DEBUG_COND2(aVehicle) || DEBUG_COND) {
1061
std::cout << "trying insertion before minor link: "
1062
<< "insertion speed = " << speed << " dist=" << dist
1063
<< "\n";
1064
}
1065
#endif
1066
if (seen >= aVehicle->getVehicleType().getMinGap()) {
1067
break;
1068
}
1069
} else if (nextLane->isInternal()) {
1070
double tmp = 0;
1071
bool dummyReq = true;
1072
#ifdef DEBUG_INSERTION
1073
if (DEBUG_COND2(aVehicle) || DEBUG_COND) {
1074
std::cout << "checking linkLeader for lane '" << nextLane->getID() << "'\n";
1075
gDebugFlag1 = true;
1076
}
1077
#endif
1078
double nSpeed = speed;
1079
aVehicle->checkLinkLeader(nextLane->getLinkCont()[0], nextLane, seen + nextLane->getLength(), nullptr, nSpeed, tmp, tmp, dummyReq);
1080
#ifdef DEBUG_INSERTION
1081
gDebugFlag1 = false;
1082
#endif
1083
if (checkFailure(aVehicle, speed, dist, nSpeed, patchSpeed, "", InsertionCheck::LEADER_GAP)) {
1084
// we may not drive with the given velocity - there is a junction leader
1085
#ifdef DEBUG_INSERTION
1086
if (DEBUG_COND2(aVehicle) || DEBUG_COND) {
1087
std::cout << " linkLeader nSpeed=" << nSpeed << " failed (@1058)!\n";
1088
}
1089
#endif
1090
return false;
1091
}
1092
}
1093
// check how next lane affects the journey
1094
if (nextLane != nullptr) {
1095
1096
// do not insert if the bidirectional edge is occupied before a railSignal has been encountered
1097
if (firstRailSignal == nullptr && nextLane->getBidiLane() != nullptr && nextLane->getBidiLane()->getVehicleNumberWithPartials() > 0) {
1098
if ((insertionChecks & (int)InsertionCheck::ONCOMING_TRAIN) != 0) {
1099
#ifdef DEBUG_INSERTION
1100
if (DEBUG_COND2(aVehicle) || DEBUG_COND) {
1101
std::cout << " nextLane=" << nextLane->getID() << " occupiedBidi\n";
1102
}
1103
#endif
1104
return false;
1105
}
1106
}
1107
1108
// check if there are stops on the next lane that should be regarded
1109
// (this block is duplicated before the loop to deal with the insertion lane)
1110
if (aVehicle->hasStops()) {
1111
const MSStop& nextStop = aVehicle->getNextStop();
1112
if (nextStop.lane == nextLane) {
1113
std::stringstream msg;
1114
msg << "scheduled stop on lane '" << nextStop.lane->getID() << "' too close";
1115
const double distToStop = seen + nextStop.pars.endPos;
1116
if (checkFailure(aVehicle, speed, dist, cfModel.insertionStopSpeed(aVehicle, speed, distToStop),
1117
patchSpeed, msg.str(), InsertionCheck::STOP)) {
1118
// we may not drive with the given velocity - we cannot stop at the stop
1119
return false;
1120
}
1121
}
1122
}
1123
1124
// check leader on next lane
1125
const MSLeaderInfo nextLeaders = nextLane->getLastVehicleInformation(aVehicle, 0, 0);
1126
if (nextLeaders.hasVehicles()) {
1127
const double nextLaneSpeed = nextLane->safeInsertionSpeed(aVehicle, seen, nextLeaders, speed);
1128
#ifdef DEBUG_INSERTION
1129
if (DEBUG_COND2(aVehicle) || DEBUG_COND) {
1130
std::cout << SIMTIME << " leader on lane '" << nextLane->getID() << "': " << nextLeaders.toString() << " nspeed=" << nextLaneSpeed << "\n";
1131
}
1132
#endif
1133
if (nextLaneSpeed == INVALID_SPEED || checkFailure(aVehicle, speed, dist, nextLaneSpeed, patchSpeed, "", InsertionCheck::LEADER_GAP)) {
1134
// we may not drive with the given velocity - we crash into the leader
1135
#ifdef DEBUG_INSERTION
1136
if (DEBUG_COND2(aVehicle) || DEBUG_COND) {
1137
std::cout << " isInsertionSuccess lane=" << getID()
1138
<< " veh=" << aVehicle->getID()
1139
<< " pos=" << pos
1140
<< " posLat=" << posLat
1141
<< " patchSpeed=" << patchSpeed
1142
<< " speed=" << speed
1143
<< " nspeed=" << nextLaneSpeed
1144
<< " nextLane=" << nextLane->getID()
1145
<< " lead=" << nextLeaders.toString()
1146
<< " failed (@641)!\n";
1147
}
1148
#endif
1149
return false;
1150
}
1151
}
1152
if (!nextLane->checkForPedestrians(aVehicle, speed, dist, -seen, patchSpeed)) {
1153
return false;
1154
}
1155
// check next lane's maximum velocity
1156
const double freeSpeed = cfModel.freeSpeed(aVehicle, speed, seen, nextLane->getVehicleMaxSpeed(aVehicle), true, MSCFModel::CalcReason::FUTURE);
1157
if (freeSpeed < speed) {
1158
if (patchSpeed || aVehicle->getParameter().departSpeedProcedure != DepartSpeedDefinition::GIVEN) {
1159
speed = freeSpeed;
1160
dist = cfModel.brakeGap(speed) + aVehicle->getVehicleType().getMinGap();
1161
} else {
1162
if ((insertionChecks & (int)InsertionCheck::SPEED_LIMIT) != 0) {
1163
if (!MSGlobals::gCheckRoutes) {
1164
WRITE_WARNINGF(TL("Vehicle '%' is inserted too fast and will violate the speed limit on a lane '%', time=%."),
1165
aVehicle->getID(), nextLane->getID(), time2string(SIMSTEP));
1166
} else {
1167
// we may not drive with the given velocity - we would be too fast on the next lane
1168
WRITE_ERRORF(TL("Vehicle '%' will not be able to depart using the given velocity (slow lane ahead), time=%."), aVehicle->getID(), time2string(SIMSTEP));
1169
MSNet::getInstance()->getInsertionControl().descheduleDeparture(aVehicle);
1170
return false;
1171
}
1172
}
1173
}
1174
}
1175
// check traffic on next junction
1176
// we cannot use (*link)->opened because a vehicle without priority
1177
// may already be comitted to blocking the link and unable to stop
1178
const SUMOTime leaveTime = (*link)->getLeaveTime(arrivalTime, speed, speed, aVehicle->getVehicleType().getLength());
1179
if ((*link)->hasApproachingFoe(arrivalTime, leaveTime, speed, cfModel.getMaxDecel())) {
1180
if (checkFailure(aVehicle, speed, dist, cfModel.insertionStopSpeed(aVehicle, speed, seen), patchSpeed, "", InsertionCheck::JUNCTION)) {
1181
// we may not drive with the given velocity - we crash at the junction
1182
return false;
1183
}
1184
}
1185
arrivalTime += TIME2STEPS(nextLane->getLength() / MAX2(speed, NUMERICAL_EPS));
1186
seen += nextLane->getLength();
1187
currentLane = nextLane;
1188
if ((*link)->getViaLane() == nullptr) {
1189
nRouteSuccs++;
1190
++ce;
1191
++ri;
1192
}
1193
}
1194
}
1195
1196
const MSLeaderDistanceInfo& followers = getFollowersOnConsecutive(aVehicle, aVehicle->getBackPositionOnLane(), false);
1197
for (int i = 0; i < followers.numSublanes(); ++i) {
1198
const MSVehicle* follower = followers[i].first;
1199
if (follower != nullptr) {
1200
const double backGapNeeded = follower->getCarFollowModel().getSecureGap(follower, aVehicle, follower->getSpeed(), speed, cfModel.getMaxDecel());
1201
if (followers[i].second < backGapNeeded
1202
&& ((insertionChecks & (int)InsertionCheck::FOLLOWER_GAP) != 0
1203
|| (followers[i].second < 0 && (insertionChecks & (int)InsertionCheck::COLLISION) != 0))) {
1204
// too close to the follower on this lane
1205
#ifdef DEBUG_INSERTION
1206
if (DEBUG_COND2(aVehicle) || DEBUG_COND) {
1207
std::cout << SIMTIME << " isInsertionSuccess lane=" << getID()
1208
<< " veh=" << aVehicle->getID()
1209
<< " pos=" << pos
1210
<< " posLat=" << posLat
1211
<< " speed=" << speed
1212
<< " nspeed=" << nspeed
1213
<< " follower=" << follower->getID()
1214
<< " backGapNeeded=" << backGapNeeded
1215
<< " gap=" << followers[i].second
1216
<< " failure (@719)!\n";
1217
}
1218
#endif
1219
return false;
1220
}
1221
}
1222
}
1223
1224
if (!checkForPedestrians(aVehicle, speed, dist, pos, patchSpeed)) {
1225
return false;
1226
}
1227
1228
MSLane* shadowLane = aVehicle->getLaneChangeModel().getShadowLane(this);
1229
#ifdef DEBUG_INSERTION
1230
if (DEBUG_COND2(aVehicle) || DEBUG_COND) {
1231
std::cout << " shadowLane=" << Named::getIDSecure(shadowLane) << "\n";
1232
}
1233
#endif
1234
if (shadowLane != nullptr) {
1235
const MSLeaderDistanceInfo& shadowFollowers = shadowLane->getFollowersOnConsecutive(aVehicle, aVehicle->getBackPositionOnLane(), false);
1236
for (int i = 0; i < shadowFollowers.numSublanes(); ++i) {
1237
const MSVehicle* follower = shadowFollowers[i].first;
1238
if (follower != nullptr) {
1239
const double backGapNeeded = follower->getCarFollowModel().getSecureGap(follower, aVehicle, follower->getSpeed(), speed, cfModel.getMaxDecel());
1240
if (shadowFollowers[i].second < backGapNeeded
1241
&& ((insertionChecks & (int)InsertionCheck::FOLLOWER_GAP) != 0
1242
|| (shadowFollowers[i].second < 0 && (insertionChecks & (int)InsertionCheck::COLLISION) != 0))) {
1243
// too close to the follower on this lane
1244
#ifdef DEBUG_INSERTION
1245
if (DEBUG_COND2(aVehicle) || DEBUG_COND) {
1246
std::cout << SIMTIME
1247
<< " isInsertionSuccess shadowlane=" << shadowLane->getID()
1248
<< " veh=" << aVehicle->getID()
1249
<< " pos=" << pos
1250
<< " posLat=" << posLat
1251
<< " speed=" << speed
1252
<< " nspeed=" << nspeed
1253
<< " follower=" << follower->getID()
1254
<< " backGapNeeded=" << backGapNeeded
1255
<< " gap=" << shadowFollowers[i].second
1256
<< " failure (@812)!\n";
1257
}
1258
#endif
1259
return false;
1260
}
1261
}
1262
}
1263
const MSLeaderInfo& ahead = shadowLane->getLastVehicleInformation(nullptr, 0, aVehicle->getPositionOnLane(), false);
1264
for (int i = 0; i < ahead.numSublanes(); ++i) {
1265
const MSVehicle* veh = ahead[i];
1266
if (veh != nullptr) {
1267
const double gap = veh->getBackPositionOnLane(shadowLane) - aVehicle->getPositionOnLane() - aVehicle->getVehicleType().getMinGap();
1268
const double gapNeeded = aVehicle->getCarFollowModel().getSecureGap(aVehicle, veh, speed, veh->getSpeed(), veh->getCarFollowModel().getMaxDecel());
1269
if (gap < gapNeeded
1270
&& ((insertionChecks & (int)InsertionCheck::LEADER_GAP) != 0
1271
|| (gap < 0 && (insertionChecks & (int)InsertionCheck::COLLISION) != 0))) {
1272
// too close to the shadow leader
1273
#ifdef DEBUG_INSERTION
1274
if (DEBUG_COND2(aVehicle) || DEBUG_COND) {
1275
std::cout << SIMTIME
1276
<< " isInsertionSuccess shadowlane=" << shadowLane->getID()
1277
<< " veh=" << aVehicle->getID()
1278
<< " pos=" << pos
1279
<< " posLat=" << posLat
1280
<< " speed=" << speed
1281
<< " nspeed=" << nspeed
1282
<< " leader=" << veh->getID()
1283
<< " gapNeeded=" << gapNeeded
1284
<< " gap=" << gap
1285
<< " failure (@842)!\n";
1286
}
1287
#endif
1288
return false;
1289
}
1290
}
1291
}
1292
}
1293
if (followers.numFreeSublanes() > 0) {
1294
// check approaching vehicles to prevent rear-end collisions
1295
const double backOffset = pos - aVehicle->getVehicleType().getLength();
1296
const double missingRearGap = getMissingRearGap(aVehicle, backOffset, speed);
1297
if (missingRearGap > 0
1298
&& (insertionChecks & (int)InsertionCheck::LEADER_GAP) != 0) {
1299
// too close to a follower
1300
#ifdef DEBUG_INSERTION
1301
if (DEBUG_COND2(aVehicle) || DEBUG_COND) {
1302
std::cout << SIMTIME
1303
<< " isInsertionSuccess lane=" << getID()
1304
<< " veh=" << aVehicle->getID()
1305
<< " pos=" << pos
1306
<< " posLat=" << posLat
1307
<< " speed=" << speed
1308
<< " nspeed=" << nspeed
1309
<< " missingRearGap=" << missingRearGap
1310
<< " failure (@728)!\n";
1311
}
1312
#endif
1313
return false;
1314
}
1315
}
1316
if (insertionChecks == (int)InsertionCheck::NONE) {
1317
speed = MAX2(0.0, speed);
1318
}
1319
// may got negative while adaptation
1320
if (speed < 0) {
1321
#ifdef DEBUG_INSERTION
1322
if (DEBUG_COND2(aVehicle) || DEBUG_COND) {
1323
std::cout << SIMTIME
1324
<< " isInsertionSuccess lane=" << getID()
1325
<< " veh=" << aVehicle->getID()
1326
<< " pos=" << pos
1327
<< " posLat=" << posLat
1328
<< " speed=" << speed
1329
<< " nspeed=" << nspeed
1330
<< " failed (@733)!\n";
1331
}
1332
#endif
1333
return false;
1334
}
1335
const int bestLaneOffset = aVehicle->getBestLaneOffset();
1336
const double extraReservation = aVehicle->getLaneChangeModel().getExtraReservation(bestLaneOffset);
1337
if (extraReservation > 0) {
1338
std::stringstream msg;
1339
msg << "too many lane changes required on lane '" << myID << "'";
1340
// we need to take into acount one extra actionStep of delay due to #3665
1341
double distToStop = aVehicle->getBestLaneDist() - pos - extraReservation - speed * aVehicle->getActionStepLengthSecs();
1342
if (distToStop >= 0) {
1343
double stopSpeed = cfModel.stopSpeed(aVehicle, speed, distToStop, MSCFModel::CalcReason::FUTURE);
1344
#ifdef DEBUG_INSERTION
1345
if (DEBUG_COND2(aVehicle) || DEBUG_COND) {
1346
std::cout << "\nIS_INSERTION_SUCCESS\n"
1347
<< SIMTIME << " veh=" << aVehicle->getID() << " bestLaneOffset=" << bestLaneOffset << " bestLaneDist=" << aVehicle->getBestLaneDist() << " extraReservation=" << extraReservation
1348
<< " distToStop=" << distToStop << " v=" << speed << " v2=" << stopSpeed << "\n";
1349
}
1350
#endif
1351
if (checkFailure(aVehicle, speed, distToStop, MAX2(0.0, stopSpeed),
1352
patchSpeed, msg.str(), InsertionCheck::LANECHANGE)) {
1353
// we may not drive with the given velocity - we cannot reserve enough space for lane changing
1354
return false;
1355
}
1356
}
1357
}
1358
// enter
1359
incorporateVehicle(aVehicle, pos, speed, posLat, find_if(myVehicles.begin(), myVehicles.end(), [&](MSVehicle * const v) {
1360
return v->getPositionOnLane() >= pos;
1361
}), notification);
1362
#ifdef DEBUG_INSERTION
1363
if (DEBUG_COND2(aVehicle) || DEBUG_COND) {
1364
std::cout << SIMTIME
1365
<< " isInsertionSuccess lane=" << getID()
1366
<< " veh=" << aVehicle->getID()
1367
<< " pos=" << pos
1368
<< " posLat=" << posLat
1369
<< " speed=" << speed
1370
<< " nspeed=" << nspeed
1371
<< "\n myVehicles=" << toString(myVehicles)
1372
<< " myPartial=" << toString(myPartialVehicles)
1373
<< " myManeuverReservations=" << toString(myManeuverReservations)
1374
<< "\n success!\n";
1375
}
1376
#endif
1377
if (isRail) {
1378
unsetParameter("insertionConstraint:" + aVehicle->getID());
1379
unsetParameter("insertionOrder:" + aVehicle->getID());
1380
unsetParameter("insertionBlocked:" + aVehicle->getID());
1381
// rail_signal (not traffic_light) requires approach information for
1382
// switching correctly at the start of the next simulation step
1383
if (firstRailSignal != nullptr && firstRailSignal->getJunction()->getType() == SumoXMLNodeType::RAIL_SIGNAL) {
1384
aVehicle->registerInsertionApproach(firstRailSignal, firstRailSignalDist);
1385
}
1386
}
1387
return true;
1388
}
1389
1390
1391
void
1392
MSLane::forceVehicleInsertion(MSVehicle* veh, double pos, MSMoveReminder::Notification notification, double posLat) {
1393
veh->updateBestLanes(true, this);
1394
bool dummy;
1395
const double speed = veh->hasDeparted() ? veh->getSpeed() : getDepartSpeed(*veh, dummy);
1396
incorporateVehicle(veh, pos, speed, posLat, find_if(myVehicles.begin(), myVehicles.end(), [&](MSVehicle * const v) {
1397
return v->getPositionOnLane() >= pos;
1398
}), notification);
1399
}
1400
1401
1402
double
1403
MSLane::safeInsertionSpeed(const MSVehicle* veh, double seen, const MSLeaderInfo& leaders, double speed) {
1404
double nspeed = speed;
1405
#ifdef DEBUG_INSERTION
1406
if (DEBUG_COND2(veh)) {
1407
std::cout << SIMTIME << " safeInsertionSpeed veh=" << veh->getID() << " speed=" << speed << "\n";
1408
}
1409
#endif
1410
for (int i = 0; i < leaders.numSublanes(); ++i) {
1411
const MSVehicle* leader = leaders[i];
1412
if (leader != nullptr) {
1413
double gap = leader->getBackPositionOnLane(this) + seen - veh->getVehicleType().getMinGap();
1414
if (leader->getLane() == getBidiLane()) {
1415
// use distance to front position and account for movement
1416
gap -= (leader->getLength() + leader->getBrakeGap(true));
1417
}
1418
if (gap < 0) {
1419
#ifdef DEBUG_INSERTION
1420
if (DEBUG_COND2(veh)) {
1421
std::cout << " leader=" << leader->getID() << " bPos=" << leader->getBackPositionOnLane(this) << " gap=" << gap << "\n";
1422
}
1423
#endif
1424
if ((veh->getInsertionChecks() & (int)InsertionCheck::COLLISION) != 0) {
1425
return INVALID_SPEED;
1426
} else {
1427
return 0;
1428
}
1429
}
1430
nspeed = MIN2(nspeed,
1431
veh->getCarFollowModel().insertionFollowSpeed(veh, speed, gap, leader->getSpeed(), leader->getCarFollowModel().getMaxDecel(), leader));
1432
#ifdef DEBUG_INSERTION
1433
if (DEBUG_COND2(veh)) {
1434
std::cout << " leader=" << leader->getID() << " bPos=" << leader->getBackPositionOnLane(this) << " gap=" << gap << " nspeed=" << nspeed << "\n";
1435
}
1436
#endif
1437
}
1438
}
1439
return nspeed;
1440
}
1441
1442
1443
// ------ Handling vehicles lapping into lanes ------
1444
const MSLeaderInfo
1445
MSLane::getLastVehicleInformation(const MSVehicle* ego, double latOffset, double minPos, bool allowCached) const {
1446
if (myLeaderInfoTime < MSNet::getInstance()->getCurrentTimeStep() || ego != nullptr || minPos > 0 || !allowCached) {
1447
MSLeaderInfo leaderTmp(myWidth, ego, latOffset);
1448
AnyVehicleIterator last = anyVehiclesBegin();
1449
int freeSublanes = 1; // number of sublanes for which no leader was found
1450
//if (ego->getID() == "disabled" && SIMTIME == 58) {
1451
// std::cout << "DEBUG\n";
1452
//}
1453
const MSVehicle* veh = *last;
1454
while (freeSublanes > 0 && veh != nullptr) {
1455
#ifdef DEBUG_PLAN_MOVE
1456
if (DEBUG_COND2(ego) || DEBUG_COND) {
1457
gDebugFlag1 = true;
1458
std::cout << " getLastVehicleInformation lane=" << getID() << " minPos=" << minPos << " veh=" << veh->getID() << " pos=" << veh->getPositionOnLane(this) << "\n";
1459
}
1460
#endif
1461
if (veh != ego && MAX2(0.0, veh->getPositionOnLane(this)) >= minPos) {
1462
const double vehLatOffset = veh->getLatOffset(this);
1463
freeSublanes = leaderTmp.addLeader(veh, true, vehLatOffset);
1464
#ifdef DEBUG_PLAN_MOVE
1465
if (DEBUG_COND2(ego) || DEBUG_COND) {
1466
std::cout << " latOffset=" << vehLatOffset << " newLeaders=" << leaderTmp.toString() << "\n";
1467
}
1468
#endif
1469
}
1470
veh = *(++last);
1471
}
1472
if (ego == nullptr && minPos == 0) {
1473
#ifdef HAVE_FOX
1474
ScopedLocker<> lock(myLeaderInfoMutex, MSGlobals::gNumSimThreads > 1);
1475
#endif
1476
// update cached value
1477
myLeaderInfo = leaderTmp;
1478
myLeaderInfoTime = MSNet::getInstance()->getCurrentTimeStep();
1479
}
1480
#ifdef DEBUG_PLAN_MOVE
1481
//if (DEBUG_COND2(ego)) std::cout << SIMTIME
1482
// << " getLastVehicleInformation lane=" << getID()
1483
// << " ego=" << Named::getIDSecure(ego)
1484
// << "\n"
1485
// << " vehicles=" << toString(myVehicles)
1486
// << " partials=" << toString(myPartialVehicles)
1487
// << "\n"
1488
// << " result=" << leaderTmp.toString()
1489
// << " cached=" << myLeaderInfo.toString()
1490
// << " myLeaderInfoTime=" << myLeaderInfoTime
1491
// << "\n";
1492
gDebugFlag1 = false;
1493
#endif
1494
return leaderTmp;
1495
}
1496
return myLeaderInfo;
1497
}
1498
1499
1500
const MSLeaderInfo
1501
MSLane::getFirstVehicleInformation(const MSVehicle* ego, double latOffset, bool onlyFrontOnLane, double maxPos, bool allowCached) const {
1502
#ifdef HAVE_FOX
1503
ScopedLocker<> lock(myFollowerInfoMutex, MSGlobals::gNumSimThreads > 1);
1504
#endif
1505
if (myFollowerInfoTime < MSNet::getInstance()->getCurrentTimeStep() || ego != nullptr || maxPos < myLength || !allowCached || onlyFrontOnLane) {
1506
// XXX separate cache for onlyFrontOnLane = true
1507
MSLeaderInfo followerTmp(myWidth, ego, latOffset);
1508
AnyVehicleIterator first = anyVehiclesUpstreamBegin();
1509
int freeSublanes = 1; // number of sublanes for which no leader was found
1510
const MSVehicle* veh = *first;
1511
while (freeSublanes > 0 && veh != nullptr) {
1512
#ifdef DEBUG_PLAN_MOVE
1513
if (DEBUG_COND2(ego)) {
1514
std::cout << " veh=" << veh->getID() << " pos=" << veh->getPositionOnLane(this) << " maxPos=" << maxPos << "\n";
1515
}
1516
#endif
1517
if (veh != ego && veh->getPositionOnLane(this) <= maxPos
1518
&& (!onlyFrontOnLane || veh->isFrontOnLane(this))) {
1519
//const double vehLatOffset = veh->getLane()->getRightSideOnEdge() - getRightSideOnEdge();
1520
const double vehLatOffset = veh->getLatOffset(this);
1521
#ifdef DEBUG_PLAN_MOVE
1522
if (DEBUG_COND2(ego)) {
1523
std::cout << " veh=" << veh->getID() << " latOffset=" << vehLatOffset << "\n";
1524
}
1525
#endif
1526
freeSublanes = followerTmp.addLeader(veh, true, vehLatOffset);
1527
}
1528
veh = *(++first);
1529
}
1530
if (ego == nullptr && maxPos == std::numeric_limits<double>::max()) {
1531
// update cached value
1532
myFollowerInfo = followerTmp;
1533
myFollowerInfoTime = MSNet::getInstance()->getCurrentTimeStep();
1534
}
1535
#ifdef DEBUG_PLAN_MOVE
1536
//if (DEBUG_COND2(ego)) std::cout << SIMTIME
1537
// << " getFirstVehicleInformation lane=" << getID()
1538
// << " ego=" << Named::getIDSecure(ego)
1539
// << "\n"
1540
// << " vehicles=" << toString(myVehicles)
1541
// << " partials=" << toString(myPartialVehicles)
1542
// << "\n"
1543
// << " result=" << followerTmp.toString()
1544
// //<< " cached=" << myFollowerInfo.toString()
1545
// << " myLeaderInfoTime=" << myLeaderInfoTime
1546
// << "\n";
1547
#endif
1548
return followerTmp;
1549
}
1550
return myFollowerInfo;
1551
}
1552
1553
1554
// ------ ------
1555
void
1556
MSLane::planMovements(SUMOTime t) {
1557
assert(myVehicles.size() != 0);
1558
double cumulatedVehLength = 0.;
1559
MSLeaderInfo leaders(myWidth);
1560
1561
// iterate over myVehicles, myPartialVehicles, and myManeuverReservations merge-sort style
1562
VehCont::reverse_iterator veh = myVehicles.rbegin();
1563
VehCont::reverse_iterator vehPart = myPartialVehicles.rbegin();
1564
VehCont::reverse_iterator vehRes = myManeuverReservations.rbegin();
1565
#ifdef DEBUG_PLAN_MOVE
1566
if (DEBUG_COND) std::cout
1567
<< "\n"
1568
<< SIMTIME
1569
<< " planMovements() lane=" << getID()
1570
<< "\n vehicles=" << toString(myVehicles)
1571
<< "\n partials=" << toString(myPartialVehicles)
1572
<< "\n reservations=" << toString(myManeuverReservations)
1573
<< "\n";
1574
#endif
1575
assert(MSGlobals::gLateralResolution || myManeuverReservations.size() == 0);
1576
for (; veh != myVehicles.rend(); ++veh) {
1577
#ifdef DEBUG_PLAN_MOVE
1578
if (DEBUG_COND2((*veh))) {
1579
std::cout << " plan move for: " << (*veh)->getID();
1580
}
1581
#endif
1582
updateLeaderInfo(*veh, vehPart, vehRes, leaders); // 36ns with 8 threads, 9ns with 1
1583
#ifdef DEBUG_PLAN_MOVE
1584
if (DEBUG_COND2((*veh))) {
1585
std::cout << " leaders=" << leaders.toString() << "\n";
1586
}
1587
#endif
1588
(*veh)->planMove(t, leaders, cumulatedVehLength); // 4800ns with 8 threads, 3100 with 1
1589
cumulatedVehLength += (*veh)->getVehicleType().getLengthWithGap();
1590
leaders.addLeader(*veh, false, 0);
1591
}
1592
}
1593
1594
1595
void
1596
MSLane::setJunctionApproaches() const {
1597
for (MSVehicle* const veh : myVehicles) {
1598
veh->setApproachingForAllLinks();
1599
}
1600
}
1601
1602
1603
void
1604
MSLane::updateLeaderInfo(const MSVehicle* veh, VehCont::reverse_iterator& vehPart, VehCont::reverse_iterator& vehRes, MSLeaderInfo& ahead) const {
1605
bool morePartialVehsAhead = vehPart != myPartialVehicles.rend();
1606
bool moreReservationsAhead = vehRes != myManeuverReservations.rend();
1607
bool nextToConsiderIsPartial;
1608
1609
// Determine relevant leaders for veh
1610
while (moreReservationsAhead || morePartialVehsAhead) {
1611
if ((!moreReservationsAhead || (*vehRes)->getPositionOnLane(this) <= veh->getPositionOnLane())
1612
&& (!morePartialVehsAhead || (*vehPart)->getPositionOnLane(this) <= veh->getPositionOnLane())) {
1613
// All relevant downstream vehicles have been collected.
1614
break;
1615
}
1616
1617
// Check whether next farthest relevant vehicle downstream is a partial vehicle or a maneuver reservation
1618
if (moreReservationsAhead && !morePartialVehsAhead) {
1619
nextToConsiderIsPartial = false;
1620
} else if (morePartialVehsAhead && !moreReservationsAhead) {
1621
nextToConsiderIsPartial = true;
1622
} else {
1623
assert(morePartialVehsAhead && moreReservationsAhead);
1624
// Add farthest downstream vehicle first
1625
nextToConsiderIsPartial = (*vehPart)->getPositionOnLane(this) > (*vehRes)->getPositionOnLane(this);
1626
}
1627
// Add appropriate leader information
1628
if (nextToConsiderIsPartial) {
1629
const double latOffset = (*vehPart)->getLatOffset(this);
1630
#ifdef DEBUG_PLAN_MOVE
1631
if (DEBUG_COND) {
1632
std::cout << " partial ahead: " << (*vehPart)->getID() << " latOffset=" << latOffset << "\n";
1633
}
1634
#endif
1635
if (!(MSGlobals::gLaneChangeDuration > 0 && (*vehPart)->getLaneChangeModel().isOpposite()
1636
&& !(*vehPart)->getLaneChangeModel().isChangingLanes())) {
1637
ahead.addLeader(*vehPart, false, latOffset);
1638
}
1639
++vehPart;
1640
morePartialVehsAhead = vehPart != myPartialVehicles.rend();
1641
} else {
1642
const double latOffset = (*vehRes)->getLatOffset(this);
1643
#ifdef DEBUG_PLAN_MOVE
1644
if (DEBUG_COND) {
1645
std::cout << " reservation ahead: " << (*vehRes)->getID() << " latOffset=" << latOffset << "\n";
1646
}
1647
#endif
1648
ahead.addLeader(*vehRes, false, latOffset);
1649
++vehRes;
1650
moreReservationsAhead = vehRes != myManeuverReservations.rend();
1651
}
1652
}
1653
}
1654
1655
1656
void
1657
MSLane::detectCollisions(SUMOTime timestep, const std::string& stage) {
1658
myNeedsCollisionCheck = false;
1659
#ifdef DEBUG_COLLISIONS
1660
if (DEBUG_COND) {
1661
std::vector<const MSVehicle*> all;
1662
for (AnyVehicleIterator last = anyVehiclesBegin(); last != anyVehiclesEnd(); ++last) {
1663
all.push_back(*last);
1664
}
1665
std::cout << SIMTIME << " detectCollisions stage=" << stage << " lane=" << getID() << ":\n"
1666
<< " vehs=" << toString(myVehicles) << "\n"
1667
<< " part=" << toString(myPartialVehicles) << "\n"
1668
<< " all=" << toString(all) << "\n"
1669
<< "\n";
1670
}
1671
#endif
1672
1673
if (myCollisionAction == COLLISION_ACTION_NONE) {
1674
return;
1675
}
1676
1677
std::set<const MSVehicle*, ComparatorNumericalIdLess> toRemove;
1678
std::set<const MSVehicle*, ComparatorNumericalIdLess> toTeleport;
1679
if (mustCheckJunctionCollisions()) {
1680
myNeedsCollisionCheck = true; // always check
1681
#ifdef DEBUG_JUNCTION_COLLISIONS
1682
if (DEBUG_COND) {
1683
std::cout << SIMTIME << " detect junction Collisions stage=" << stage << " lane=" << getID() << ":\n"
1684
<< " vehs=" << toString(myVehicles) << "\n"
1685
<< " part=" << toString(myPartialVehicles) << "\n"
1686
<< "\n";
1687
}
1688
#endif
1689
assert(myLinks.size() == 1);
1690
const std::vector<const MSLane*>& foeLanes = myLinks.front()->getFoeLanes();
1691
// save the iterator, it might get modified, see #8842
1692
MSLane::AnyVehicleIterator end = anyVehiclesEnd();
1693
for (AnyVehicleIterator veh = anyVehiclesBegin(); veh != end; ++veh) {
1694
const MSVehicle* const collider = *veh;
1695
//std::cout << " collider " << collider->getID() << "\n";
1696
PositionVector colliderBoundary = collider->getBoundingBox(myCheckJunctionCollisionMinGap);
1697
for (const MSLane* const foeLane : foeLanes) {
1698
#ifdef DEBUG_JUNCTION_COLLISIONS
1699
if (DEBUG_COND) {
1700
std::cout << " foeLane " << foeLane->getID()
1701
<< " foeVehs=" << toString(foeLane->myVehicles)
1702
<< " foePart=" << toString(foeLane->myPartialVehicles) << "\n";
1703
}
1704
#endif
1705
MSLane::AnyVehicleIterator foeEnd = foeLane->anyVehiclesEnd();
1706
for (MSLane::AnyVehicleIterator it_veh = foeLane->anyVehiclesBegin(); it_veh != foeEnd; ++it_veh) {
1707
const MSVehicle* const victim = *it_veh;
1708
if (victim == collider) {
1709
// may happen if the vehicles lane and shadow lane are siblings
1710
continue;
1711
}
1712
#ifdef DEBUG_JUNCTION_COLLISIONS
1713
if (DEBUG_COND && DEBUG_COND2(collider)) {
1714
std::cout << SIMTIME << " foe=" << victim->getID()
1715
<< " bound=" << colliderBoundary << " foeBound=" << victim->getBoundingBox()
1716
<< " overlaps=" << colliderBoundary.overlapsWith(victim->getBoundingBox())
1717
<< " poly=" << collider->getBoundingPoly()
1718
<< " foePoly=" << victim->getBoundingPoly()
1719
<< " overlaps2=" << collider->getBoundingPoly().overlapsWith(victim->getBoundingPoly())
1720
<< "\n";
1721
}
1722
#endif
1723
if (MSGlobals::gIgnoreJunctionBlocker < std::numeric_limits<SUMOTime>::max()) {
1724
if (collider->getWaitingTime() >= MSGlobals::gIgnoreJunctionBlocker
1725
|| victim->getWaitingTime() >= MSGlobals::gIgnoreJunctionBlocker) {
1726
// ignored vehicles should not tigger collision
1727
continue;
1728
}
1729
}
1730
1731
if (colliderBoundary.overlapsWith(victim->getBoundingBox())) {
1732
// make a detailed check
1733
PositionVector boundingPoly = collider->getBoundingPoly();
1734
if (collider->getBoundingPoly(myCheckJunctionCollisionMinGap).overlapsWith(victim->getBoundingPoly())) {
1735
// junction leader is the victim (collider must still be on junction)
1736
assert(isInternal());
1737
if (victim->getLane()->isInternal() && victim->isLeader(myLinks.front(), collider, -1)) {
1738
foeLane->handleCollisionBetween(timestep, stage, victim, collider, -1, 0, toRemove, toTeleport);
1739
} else {
1740
handleCollisionBetween(timestep, stage, collider, victim, -1, 0, toRemove, toTeleport);
1741
}
1742
}
1743
}
1744
}
1745
detectPedestrianJunctionCollision(collider, colliderBoundary, foeLane, timestep, stage, toRemove, toTeleport);
1746
}
1747
if (myLinks.front()->getWalkingAreaFoe() != nullptr) {
1748
detectPedestrianJunctionCollision(collider, colliderBoundary, myLinks.front()->getWalkingAreaFoe(), timestep, stage, toRemove, toTeleport);
1749
}
1750
if (myLinks.front()->getWalkingAreaFoeExit() != nullptr) {
1751
detectPedestrianJunctionCollision(collider, colliderBoundary, myLinks.front()->getWalkingAreaFoeExit(), timestep, stage, toRemove, toTeleport);
1752
}
1753
}
1754
}
1755
1756
1757
if (myIntermodalCollisionAction != COLLISION_ACTION_NONE && myEdge->getPersons().size() > 0 && hasPedestrians()) {
1758
#ifdef DEBUG_PEDESTRIAN_COLLISIONS
1759
if (DEBUG_COND) {
1760
std::cout << SIMTIME << " detect pedestrian collisions stage=" << stage << " lane=" << getID() << "\n";
1761
}
1762
#endif
1763
AnyVehicleIterator v_end = anyVehiclesEnd();
1764
for (AnyVehicleIterator it_v = anyVehiclesBegin(); it_v != v_end; ++it_v) {
1765
const MSVehicle* v = *it_v;
1766
double back = v->getBackPositionOnLane(this);
1767
const double length = v->getVehicleType().getLength();
1768
const double right = v->getRightSideOnEdge(this) - getRightSideOnEdge();
1769
if (v->getLane() == getBidiLane()) {
1770
// use the front position for checking
1771
back -= length;
1772
}
1773
PersonDist leader = nextBlocking(back, right, right + v->getVehicleType().getWidth());
1774
#ifdef DEBUG_PEDESTRIAN_COLLISIONS
1775
if (DEBUG_COND && DEBUG_COND2(v)) {
1776
std::cout << SIMTIME << " back=" << back << " right=" << right << " person=" << Named::getIDSecure(leader.first)
1777
<< " dist=" << leader.second << " jammed=" << (leader.first == nullptr ? false : leader.first->isJammed()) << "\n";
1778
}
1779
#endif
1780
if (leader.first != 0 && leader.second < length && !leader.first->isJammed()) {
1781
if (v->getVehicleType().getGuiShape() == SUMOVehicleShape::AIRCRAFT) {
1782
// aircraft wings and body are above walking level
1783
continue;
1784
}
1785
const double gap = leader.second - length;
1786
handleIntermodalCollisionBetween(timestep, stage, v, leader.first, gap, "sharedLane", toRemove, toTeleport);
1787
}
1788
}
1789
}
1790
1791
if (myVehicles.size() == 0) {
1792
return;
1793
}
1794
if (!MSGlobals::gSublane) {
1795
// no sublanes
1796
VehCont::reverse_iterator lastVeh = myVehicles.rend() - 1;
1797
for (VehCont::reverse_iterator pred = myVehicles.rbegin(); pred != lastVeh; ++pred) {
1798
VehCont::reverse_iterator veh = pred + 1;
1799
detectCollisionBetween(timestep, stage, *veh, *pred, toRemove, toTeleport);
1800
}
1801
if (myPartialVehicles.size() > 0) {
1802
detectCollisionBetween(timestep, stage, *lastVeh, myPartialVehicles.front(), toRemove, toTeleport);
1803
}
1804
if (getBidiLane() != nullptr) {
1805
// bidirectional railway
1806
MSLane* bidiLane = getBidiLane();
1807
if (bidiLane->getVehicleNumberWithPartials() > 0) {
1808
for (auto veh = myVehicles.begin(); veh != myVehicles.end(); ++veh) {
1809
double high = (*veh)->getPositionOnLane(this);
1810
double low = (*veh)->getBackPositionOnLane(this);
1811
if (stage == MSNet::STAGE_MOVEMENTS) {
1812
// use previous back position to catch trains that
1813
// "jump" through each other
1814
low -= SPEED2DIST((*veh)->getSpeed());
1815
}
1816
for (AnyVehicleIterator veh2 = bidiLane->anyVehiclesBegin(); veh2 != bidiLane->anyVehiclesEnd(); ++veh2) {
1817
// self-collisions might legitemately occur when a long train loops back on itself
1818
if (*veh == *veh2 && !(*veh)->isRail()) {
1819
continue;
1820
}
1821
if ((*veh)->getLane() == (*veh2)->getLane() ||
1822
(*veh)->getLane() == (*veh2)->getBackLane() ||
1823
(*veh)->getBackLane() == (*veh2)->getLane()) {
1824
// vehicles are not in a bidi relation
1825
continue;
1826
}
1827
double low2 = myLength - (*veh2)->getPositionOnLane(bidiLane);
1828
double high2 = myLength - (*veh2)->getBackPositionOnLane(bidiLane);
1829
if (stage == MSNet::STAGE_MOVEMENTS) {
1830
// use previous back position to catch trains that
1831
// "jump" through each other
1832
high2 += SPEED2DIST((*veh2)->getSpeed());
1833
}
1834
if (!(high < low2 || high2 < low)) {
1835
#ifdef DEBUG_COLLISIONS
1836
if (DEBUG_COND) {
1837
std::cout << SIMTIME << " bidi-collision veh=" << (*veh)->getID() << " bidiVeh=" << (*veh2)->getID()
1838
<< " vehFurther=" << toString((*veh)->getFurtherLanes())
1839
<< " high=" << high << " low=" << low << " high2=" << high2 << " low2=" << low2 << "\n";
1840
}
1841
#endif
1842
// the faster vehicle is at fault
1843
MSVehicle* collider = const_cast<MSVehicle*>(*veh);
1844
MSVehicle* victim = const_cast<MSVehicle*>(*veh2);
1845
if (collider->getSpeed() < victim->getSpeed()) {
1846
std::swap(victim, collider);
1847
}
1848
handleCollisionBetween(timestep, stage, collider, victim, -1, 0, toRemove, toTeleport);
1849
}
1850
}
1851
}
1852
}
1853
}
1854
} else {
1855
// in the sublane-case it is insufficient to check the vehicles ordered
1856
// by their front position as there might be more than 2 vehicles next to each
1857
// other on the same lane
1858
// instead, a moving-window approach is used where all vehicles that
1859
// overlap in the longitudinal direction receive pairwise checks
1860
// XXX for efficiency, all lanes of an edge should be checked together
1861
// (lanechanger-style)
1862
1863
// XXX quick hack: check each in myVehicles against all others
1864
for (AnyVehicleIterator veh = anyVehiclesBegin(); veh != anyVehiclesEnd(); ++veh) {
1865
MSVehicle* follow = (MSVehicle*)*veh;
1866
for (AnyVehicleIterator veh2 = anyVehiclesBegin(); veh2 != anyVehiclesEnd(); ++veh2) {
1867
MSVehicle* lead = (MSVehicle*)*veh2;
1868
if (lead == follow) {
1869
continue;
1870
}
1871
if (lead->getPositionOnLane(this) < follow->getPositionOnLane(this)) {
1872
continue;
1873
}
1874
if (detectCollisionBetween(timestep, stage, follow, lead, toRemove, toTeleport)) {
1875
// XXX what about collisions with multiple leaders at once?
1876
break;
1877
}
1878
}
1879
}
1880
}
1881
1882
1883
for (std::set<const MSVehicle*, ComparatorNumericalIdLess>::iterator it = toRemove.begin(); it != toRemove.end(); ++it) {
1884
MSVehicle* veh = const_cast<MSVehicle*>(*it);
1885
MSLane* vehLane = veh->getMutableLane();
1886
vehLane->removeVehicle(veh, MSMoveReminder::NOTIFICATION_TELEPORT, false);
1887
if (toTeleport.count(veh) > 0) {
1888
MSVehicleTransfer::getInstance()->add(timestep, veh);
1889
} else {
1890
veh->onRemovalFromNet(MSMoveReminder::NOTIFICATION_VAPORIZED_COLLISION);
1891
MSNet::getInstance()->getVehicleControl().scheduleVehicleRemoval(veh);
1892
}
1893
}
1894
}
1895
1896
1897
void
1898
MSLane::detectPedestrianJunctionCollision(const MSVehicle* collider, const PositionVector& colliderBoundary, const MSLane* foeLane,
1899
SUMOTime timestep, const std::string& stage,
1900
std::set<const MSVehicle*, ComparatorNumericalIdLess>& toRemove,
1901
std::set<const MSVehicle*, ComparatorNumericalIdLess>& toTeleport) {
1902
if (myIntermodalCollisionAction != COLLISION_ACTION_NONE && foeLane->getEdge().getPersons().size() > 0 && foeLane->hasPedestrians()) {
1903
#ifdef DEBUG_PEDESTRIAN_COLLISIONS
1904
if (DEBUG_COND) {
1905
std::cout << SIMTIME << " detect pedestrian junction collisions stage=" << stage << " lane=" << getID() << " foeLane=" << foeLane->getID() << "\n";
1906
}
1907
#endif
1908
const std::vector<MSTransportable*>& persons = foeLane->getEdge().getSortedPersons(timestep);
1909
for (std::vector<MSTransportable*>::const_iterator it_p = persons.begin(); it_p != persons.end(); ++it_p) {
1910
#ifdef DEBUG_PEDESTRIAN_COLLISIONS
1911
if (DEBUG_COND) {
1912
std::cout << " collider=" << collider->getID()
1913
<< " ped=" << (*it_p)->getID()
1914
<< " jammed=" << (*it_p)->isJammed()
1915
<< " colliderBoundary=" << colliderBoundary
1916
<< " pedBoundary=" << (*it_p)->getBoundingBox()
1917
<< "\n";
1918
}
1919
#endif
1920
if ((*it_p)->isJammed()) {
1921
continue;
1922
}
1923
if (colliderBoundary.overlapsWith((*it_p)->getBoundingBox())
1924
&& collider->getBoundingPoly().overlapsWith((*it_p)->getBoundingBox())) {
1925
std::string collisionType = "junctionPedestrian";
1926
if (foeLane->isCrossing()) {
1927
collisionType = "crossing";
1928
} else if (foeLane->isWalkingArea()) {
1929
collisionType = "walkingarea";
1930
}
1931
handleIntermodalCollisionBetween(timestep, stage, collider, *it_p, 0, collisionType, toRemove, toTeleport);
1932
}
1933
}
1934
}
1935
}
1936
1937
1938
bool
1939
MSLane::detectCollisionBetween(SUMOTime timestep, const std::string& stage, MSVehicle* collider, MSVehicle* victim,
1940
std::set<const MSVehicle*, ComparatorNumericalIdLess>& toRemove,
1941
std::set<const MSVehicle*, ComparatorNumericalIdLess>& toTeleport) const {
1942
if (myCollisionAction == COLLISION_ACTION_TELEPORT && ((victim->hasInfluencer() && victim->getInfluencer().isRemoteAffected(timestep)) ||
1943
(collider->hasInfluencer() && collider->getInfluencer().isRemoteAffected(timestep)))) {
1944
return false;
1945
}
1946
1947
// No self-collisions! (This is assumed to be ensured at caller side)
1948
if (collider == victim) {
1949
return false;
1950
}
1951
1952
const bool colliderOpposite = collider->getLaneChangeModel().isOpposite() || collider->isBidiOn(this);
1953
const bool victimOpposite = victim->getLaneChangeModel().isOpposite() || victim->isBidiOn(this);
1954
const bool bothOpposite = victimOpposite && colliderOpposite;
1955
if (bothOpposite) {
1956
std::swap(victim, collider);
1957
}
1958
const double colliderPos = colliderOpposite && !bothOpposite ? collider->getBackPositionOnLane(this) : collider->getPositionOnLane(this);
1959
const double minGapFactor = myCollisionMinGapFactor >= 0 ? myCollisionMinGapFactor : collider->getCarFollowModel().getCollisionMinGapFactor();
1960
double victimBack = victimOpposite && !bothOpposite ? victim->getPositionOnLane(this) : victim->getBackPositionOnLane(this);
1961
if (victim->getLateralOverlap() > 0 || collider->getLateralOverlap() > 0) {
1962
if (&collider->getLane()->getEdge() == myEdge && collider->getLane()->getLength() > getLength()) {
1963
// interpret victim position on the longer lane
1964
victimBack *= collider->getLane()->getLength() / getLength();
1965
}
1966
}
1967
double gap = victimBack - colliderPos - minGapFactor * collider->getVehicleType().getMinGap();
1968
if (bothOpposite) {
1969
gap = colliderPos - victimBack - minGapFactor * collider->getVehicleType().getMinGap();
1970
} else if (colliderOpposite) {
1971
// vehicles are back to back so (frontal) minGap doesn't apply
1972
gap += minGapFactor * collider->getVehicleType().getMinGap();
1973
}
1974
#ifdef DEBUG_COLLISIONS
1975
if (DEBUG_COND && (DEBUG_COND2(collider) || DEBUG_COND2(victim))) {
1976
std::cout << SIMTIME
1977
<< " thisLane=" << getID()
1978
<< " collider=" << collider->getID()
1979
<< " victim=" << victim->getID()
1980
<< " colOpposite=" << colliderOpposite
1981
<< " vicOpposite=" << victimOpposite
1982
<< " colLane=" << collider->getLane()->getID()
1983
<< " vicLane=" << victim->getLane()->getID()
1984
<< " colPos=" << colliderPos
1985
<< " vicBack=" << victimBack
1986
<< " colLat=" << collider->getCenterOnEdge(this)
1987
<< " vicLat=" << victim->getCenterOnEdge(this)
1988
<< " minGap=" << collider->getVehicleType().getMinGap()
1989
<< " minGapFactor=" << minGapFactor
1990
<< " gap=" << gap
1991
<< "\n";
1992
}
1993
#endif
1994
if (victimOpposite && gap < -(collider->getLength() + victim->getLength())) {
1995
// already past each other
1996
return false;
1997
}
1998
if (gap < -NUMERICAL_EPS) {
1999
double latGap = 0;
2000
if (MSGlobals::gSublane) {
2001
latGap = (fabs(victim->getCenterOnEdge(this) - collider->getCenterOnEdge(this))
2002
- 0.5 * fabs(victim->getVehicleType().getWidth() + collider->getVehicleType().getWidth()));
2003
if (latGap + NUMERICAL_EPS > 0) {
2004
return false;
2005
}
2006
// account for ambiguous gap computation related to partial
2007
// occupation of lanes with different lengths
2008
if (isInternal() && getEdge().getNumLanes() > 1 && victim->getLane() != collider->getLane()) {
2009
double gapDelta = 0;
2010
const MSVehicle* otherLaneVeh = collider->getLane() == this ? victim : collider;
2011
if (otherLaneVeh->getLaneChangeModel().getShadowLane() == this) {
2012
gapDelta = getLength() - otherLaneVeh->getLane()->getLength();
2013
} else {
2014
for (const MSLane* cand : otherLaneVeh->getFurtherLanes()) {
2015
if (&cand->getEdge() == &getEdge()) {
2016
gapDelta = getLength() - cand->getLength();
2017
break;
2018
}
2019
}
2020
}
2021
if (gap + gapDelta >= 0) {
2022
return false;
2023
}
2024
}
2025
}
2026
if (MSGlobals::gLaneChangeDuration > DELTA_T
2027
&& collider->getLaneChangeModel().isChangingLanes()
2028
&& victim->getLaneChangeModel().isChangingLanes()
2029
&& victim->getLane() != this) {
2030
// synchroneous lane change maneuver
2031
return false;
2032
}
2033
#ifdef DEBUG_COLLISIONS
2034
if (DEBUG_COND && (DEBUG_COND2(collider) || DEBUG_COND2(victim))) {
2035
std::cout << SIMTIME << " detectedCollision gap=" << gap << " latGap=" << latGap << "\n";
2036
}
2037
#endif
2038
handleCollisionBetween(timestep, stage, collider, victim, gap, latGap, toRemove, toTeleport);
2039
return true;
2040
}
2041
return false;
2042
}
2043
2044
2045
void
2046
MSLane::handleCollisionBetween(SUMOTime timestep, const std::string& stage, const MSVehicle* collider, const MSVehicle* victim,
2047
double gap, double latGap, std::set<const MSVehicle*, ComparatorNumericalIdLess>& toRemove,
2048
std::set<const MSVehicle*, ComparatorNumericalIdLess>& toTeleport) const {
2049
if (collider->ignoreCollision() || victim->ignoreCollision()) {
2050
return;
2051
}
2052
std::string collisionType;
2053
std::string collisionText;
2054
if (isFrontalCollision(collider, victim)) {
2055
collisionType = "frontal";
2056
collisionText = TL("frontal collision");
2057
} else if (stage == MSNet::STAGE_LANECHANGE) {
2058
collisionType = "side";
2059
collisionText = TL("side collision");
2060
} else if (isInternal()) {
2061
collisionType = "junction";
2062
collisionText = TL("junction collision");
2063
} else {
2064
collisionType = "collision";
2065
collisionText = TL("collision");
2066
}
2067
2068
// in frontal collisions the opposite vehicle is the collider
2069
if (victim->getLaneChangeModel().isOpposite() && !collider->getLaneChangeModel().isOpposite()) {
2070
std::swap(collider, victim);
2071
}
2072
std::string prefix = TLF("Vehicle '%'; % with vehicle '%", collider->getID(), collisionText, victim->getID());
2073
if (myCollisionStopTime > 0) {
2074
if (collider->collisionStopTime() >= 0 && victim->collisionStopTime() >= 0) {
2075
return;
2076
}
2077
std::string dummyError;
2078
SUMOVehicleParameter::Stop stop;
2079
stop.duration = myCollisionStopTime;
2080
stop.parametersSet |= STOP_DURATION_SET;
2081
const double collisionAngle = RAD2DEG(fabs(GeomHelper::angleDiff(victim->getAngle(), collider->getAngle())));
2082
// determine new speeds from collision angle (@todo account for vehicle mass)
2083
double victimSpeed = victim->getSpeed();
2084
double colliderSpeed = collider->getSpeed();
2085
// double victimOrigSpeed = victim->getSpeed();
2086
// double colliderOrigSpeed = collider->getSpeed();
2087
if (collisionAngle < 45) {
2088
// rear-end collisions
2089
colliderSpeed = MIN2(colliderSpeed, victimSpeed);
2090
} else if (collisionAngle < 135) {
2091
// side collision
2092
colliderSpeed /= 2;
2093
victimSpeed /= 2;
2094
} else {
2095
// frontal collision
2096
colliderSpeed = 0;
2097
victimSpeed = 0;
2098
}
2099
const double victimStopPos = MIN2(victim->getLane()->getLength(),
2100
victim->getPositionOnLane() + victim->getCarFollowModel().brakeGap(victimSpeed, victim->getCarFollowModel().getEmergencyDecel(), 0));
2101
if (victim->collisionStopTime() < 0) {
2102
stop.collision = true;
2103
stop.lane = victim->getLane()->getID();
2104
// @todo: push victim forward?
2105
stop.startPos = victimStopPos;
2106
stop.endPos = stop.startPos;
2107
stop.parametersSet |= STOP_START_SET | STOP_END_SET;
2108
((MSBaseVehicle*)victim)->addStop(stop, dummyError, 0);
2109
}
2110
if (collider->collisionStopTime() < 0) {
2111
stop.collision = true;
2112
stop.lane = collider->getLane()->getID();
2113
stop.startPos = MIN2(collider->getPositionOnLane() + collider->getCarFollowModel().brakeGap(colliderSpeed, collider->getCarFollowModel().getEmergencyDecel(), 0),
2114
MAX3(0.0, victimStopPos - 0.75 * victim->getVehicleType().getLength(),
2115
collider->getPositionOnLane() - SPEED2DIST(collider->getSpeed())));
2116
stop.endPos = stop.startPos;
2117
stop.parametersSet |= STOP_START_SET | STOP_END_SET;
2118
((MSBaseVehicle*)collider)->addStop(stop, dummyError, 0);
2119
}
2120
//std::cout << " collisionAngle=" << collisionAngle
2121
// << "\n vPos=" << victim->getPositionOnLane() << " vStop=" << victimStopPos << " vSpeed=" << victimOrigSpeed << " vSpeed2=" << victimSpeed << " vSpeed3=" << victim->getSpeed()
2122
// << "\n cPos=" << collider->getPositionOnLane() << " cStop=" << stop.startPos << " cSpeed=" << colliderOrigSpeed << " cSpeed2=" << colliderSpeed << " cSpeed3=" << collider->getSpeed()
2123
// << "\n";
2124
} else {
2125
switch (myCollisionAction) {
2126
case COLLISION_ACTION_WARN:
2127
break;
2128
case COLLISION_ACTION_TELEPORT:
2129
prefix = TLF("Teleporting vehicle '%'; % with vehicle '%", collider->getID(), collisionText, victim->getID());
2130
toRemove.insert(collider);
2131
toTeleport.insert(collider);
2132
break;
2133
case COLLISION_ACTION_REMOVE: {
2134
prefix = TLF("Removing % participants: vehicle '%', vehicle '%", collisionText, collider->getID(), victim->getID());
2135
bool removeCollider = true;
2136
bool removeVictim = true;
2137
removeVictim = !(victim->hasInfluencer() && victim->getInfluencer()->isRemoteAffected(timestep));
2138
removeCollider = !(collider->hasInfluencer() && collider->getInfluencer()->isRemoteAffected(timestep));
2139
if (removeVictim) {
2140
toRemove.insert(victim);
2141
}
2142
if (removeCollider) {
2143
toRemove.insert(collider);
2144
}
2145
if (!removeVictim) {
2146
if (!removeCollider) {
2147
prefix = TLF("Keeping remote-controlled % participants: vehicle '%', vehicle '%", collisionText, collider->getID(), victim->getID());
2148
} else {
2149
prefix = TLF("Removing % participant: vehicle '%', keeping remote-controlled vehicle '%", collisionText, collider->getID(), victim->getID());
2150
}
2151
} else if (!removeCollider) {
2152
prefix = TLF("Keeping remote-controlled % participant: vehicle '%', removing vehicle '%", collisionText, collider->getID(), victim->getID());
2153
}
2154
break;
2155
}
2156
default:
2157
break;
2158
}
2159
}
2160
const bool newCollision = MSNet::getInstance()->registerCollision(collider, victim, collisionType, this, collider->getPositionOnLane(this));
2161
if (newCollision) {
2162
WRITE_WARNINGF(prefix + "', lane='%', gap=%%, time=%, stage=%.",
2163
getID(), toString(gap), (MSGlobals::gSublane ? TL(", latGap=") + toString(latGap) : ""),
2164
time2string(timestep), stage);
2165
MSNet::getInstance()->informVehicleStateListener(victim, MSNet::VehicleState::COLLISION);
2166
MSNet::getInstance()->informVehicleStateListener(collider, MSNet::VehicleState::COLLISION);
2167
MSNet::getInstance()->getVehicleControl().countCollision(myCollisionAction == COLLISION_ACTION_TELEPORT);
2168
}
2169
#ifdef DEBUG_COLLISIONS
2170
if (DEBUG_COND2(collider)) {
2171
toRemove.erase(collider);
2172
toTeleport.erase(collider);
2173
}
2174
if (DEBUG_COND2(victim)) {
2175
toRemove.erase(victim);
2176
toTeleport.erase(victim);
2177
}
2178
#endif
2179
}
2180
2181
2182
void
2183
MSLane::handleIntermodalCollisionBetween(SUMOTime timestep, const std::string& stage, const MSVehicle* collider, const MSTransportable* victim,
2184
double gap, const std::string& collisionType,
2185
std::set<const MSVehicle*, ComparatorNumericalIdLess>& toRemove,
2186
std::set<const MSVehicle*, ComparatorNumericalIdLess>& toTeleport) const {
2187
if (collider->ignoreCollision()) {
2188
return;
2189
}
2190
std::string prefix = TLF("Vehicle '%'", collider->getID());
2191
if (myIntermodalCollisionStopTime > 0) {
2192
if (collider->collisionStopTime() >= 0) {
2193
return;
2194
}
2195
std::string dummyError;
2196
SUMOVehicleParameter::Stop stop;
2197
stop.duration = myIntermodalCollisionStopTime;
2198
stop.parametersSet |= STOP_DURATION_SET;
2199
// determine new speeds from collision angle (@todo account for vehicle mass)
2200
double colliderSpeed = collider->getSpeed();
2201
const double victimStopPos = victim->getEdgePos();
2202
// double victimOrigSpeed = victim->getSpeed();
2203
// double colliderOrigSpeed = collider->getSpeed();
2204
if (collider->collisionStopTime() < 0) {
2205
stop.collision = true;
2206
stop.lane = collider->getLane()->getID();
2207
stop.startPos = MIN2(collider->getPositionOnLane() + collider->getCarFollowModel().brakeGap(colliderSpeed, collider->getCarFollowModel().getEmergencyDecel(), 0),
2208
MAX3(0.0, victimStopPos - 0.75 * victim->getVehicleType().getLength(),
2209
collider->getPositionOnLane() - SPEED2DIST(collider->getSpeed())));
2210
stop.endPos = stop.startPos;
2211
stop.parametersSet |= STOP_START_SET | STOP_END_SET;
2212
((MSBaseVehicle*)collider)->addStop(stop, dummyError, 0);
2213
}
2214
} else {
2215
switch (myIntermodalCollisionAction) {
2216
case COLLISION_ACTION_WARN:
2217
break;
2218
case COLLISION_ACTION_TELEPORT:
2219
prefix = TLF("Teleporting vehicle '%' after", collider->getID());
2220
toRemove.insert(collider);
2221
toTeleport.insert(collider);
2222
break;
2223
case COLLISION_ACTION_REMOVE: {
2224
prefix = TLF("Removing vehicle '%' after", collider->getID());
2225
bool removeCollider = true;
2226
removeCollider = !(collider->hasInfluencer() && collider->getInfluencer()->isRemoteAffected(timestep));
2227
if (!removeCollider) {
2228
prefix = TLF("Keeping remote-controlled vehicle '%' after", collider->getID());
2229
} else {
2230
toRemove.insert(collider);
2231
}
2232
break;
2233
}
2234
default:
2235
break;
2236
}
2237
}
2238
const bool newCollision = MSNet::getInstance()->registerCollision(collider, victim, collisionType, this, victim->getEdgePos());
2239
if (newCollision) {
2240
if (gap != 0) {
2241
WRITE_WARNING(prefix + TLF(" collision with person '%', lane='%', gap=%, time=%, stage=%.",
2242
victim->getID(), getID(), gap, time2string(timestep), stage));
2243
} else {
2244
WRITE_WARNING(prefix + TLF(" collision with person '%', lane='%', time=%, stage=%.",
2245
victim->getID(), getID(), time2string(timestep), stage));
2246
}
2247
MSNet::getInstance()->informVehicleStateListener(collider, MSNet::VehicleState::COLLISION);
2248
MSNet::getInstance()->getVehicleControl().countCollision(myIntermodalCollisionAction == COLLISION_ACTION_TELEPORT);
2249
}
2250
#ifdef DEBUG_COLLISIONS
2251
if (DEBUG_COND2(collider)) {
2252
toRemove.erase(collider);
2253
toTeleport.erase(collider);
2254
}
2255
#endif
2256
}
2257
2258
2259
bool
2260
MSLane::isFrontalCollision(const MSVehicle* collider, const MSVehicle* victim) {
2261
if (collider->getLaneChangeModel().isOpposite() != victim->getLaneChangeModel().isOpposite()) {
2262
return true;
2263
} else {
2264
const MSEdge* victimBidi = victim->getLane()->getEdge().getBidiEdge();
2265
if (&collider->getLane()->getEdge() == victimBidi) {
2266
return true;
2267
} else {
2268
for (MSLane* further : collider->getFurtherLanes()) {
2269
if (&further->getEdge() == victimBidi) {
2270
return true;
2271
}
2272
}
2273
}
2274
}
2275
return false;
2276
}
2277
2278
void
2279
MSLane::executeMovements(const SUMOTime t) {
2280
// multithreading: there are concurrent writes to myNeedsCollisionCheck but all of them should set it to true
2281
myNeedsCollisionCheck = true;
2282
MSLane* bidi = getBidiLane();
2283
if (bidi != nullptr && bidi->getVehicleNumber() == 0) {
2284
MSNet::getInstance()->getEdgeControl().checkCollisionForInactive(bidi);
2285
}
2286
MSVehicle* firstNotStopped = nullptr;
2287
// iterate over vehicles in reverse so that move reminders will be called in the correct order
2288
for (VehCont::reverse_iterator i = myVehicles.rbegin(); i != myVehicles.rend();) {
2289
MSVehicle* veh = *i;
2290
// length is needed later when the vehicle may not exist anymore
2291
const double length = veh->getVehicleType().getLengthWithGap();
2292
const double nettoLength = veh->getVehicleType().getLength();
2293
const bool moved = veh->executeMove();
2294
MSLane* const target = veh->getMutableLane();
2295
if (veh->hasArrived()) {
2296
// vehicle has reached its arrival position
2297
#ifdef DEBUG_EXEC_MOVE
2298
if DEBUG_COND2(veh) {
2299
std::cout << SIMTIME << " veh " << veh->getID() << " has arrived." << std::endl;
2300
}
2301
#endif
2302
veh->onRemovalFromNet(MSMoveReminder::NOTIFICATION_ARRIVED);
2303
MSNet::getInstance()->getVehicleControl().scheduleVehicleRemoval(veh);
2304
} else if (target != nullptr && moved) {
2305
if (target->getEdge().isVaporizing()) {
2306
// vehicle has reached a vaporizing edge
2307
veh->onRemovalFromNet(MSMoveReminder::NOTIFICATION_VAPORIZED_VAPORIZER);
2308
MSNet::getInstance()->getVehicleControl().scheduleVehicleRemoval(veh);
2309
} else {
2310
// vehicle has entered a new lane (leaveLane and workOnMoveReminders were already called in MSVehicle::executeMove)
2311
target->myVehBuffer.push_back(veh);
2312
MSNet::getInstance()->getEdgeControl().needsVehicleIntegration(target);
2313
if (MSGlobals::gSublane && veh->getLaneChangeModel().getShadowLane() != nullptr) {
2314
// trigger sorting of partial vehicles as their order may have changed (lane might not be active and only contain partial vehicles)
2315
MSNet::getInstance()->getEdgeControl().needsVehicleIntegration(veh->getLaneChangeModel().getShadowLane());
2316
}
2317
}
2318
} else if (veh->isParking()) {
2319
// vehicle started to park
2320
MSVehicleTransfer::getInstance()->add(t, veh);
2321
myParkingVehicles.insert(veh);
2322
} else if (veh->brokeDown()) {
2323
veh->resumeFromStopping();
2324
WRITE_WARNINGF(TL("Removing vehicle '%' after breaking down, lane='%', time=%."),
2325
veh->getID(), veh->getLane()->getID(), time2string(t));
2326
veh->onRemovalFromNet(MSMoveReminder::NOTIFICATION_VAPORIZED_BREAKDOWN);
2327
MSNet::getInstance()->getVehicleControl().scheduleVehicleRemoval(veh);
2328
} else if (veh->isJumping()) {
2329
// vehicle jumps to next route edge
2330
MSVehicleTransfer::getInstance()->add(t, veh);
2331
} else if (veh->getPositionOnLane() > getLength()) {
2332
// for any reasons the vehicle is beyond its lane...
2333
// this should never happen because it is handled in MSVehicle::executeMove
2334
assert(false);
2335
WRITE_WARNINGF(TL("Teleporting vehicle '%'; beyond end of lane, target lane='%', time=%."),
2336
veh->getID(), getID(), time2string(t));
2337
MSNet::getInstance()->getVehicleControl().countCollision(true);
2338
MSVehicleTransfer::getInstance()->add(t, veh);
2339
2340
} else if (veh->collisionStopTime() == 0) {
2341
veh->resumeFromStopping();
2342
if (getCollisionAction() == COLLISION_ACTION_REMOVE) {
2343
WRITE_WARNINGF(TL("Removing vehicle '%' after earlier collision, lane='%', time=%."),
2344
veh->getID(), veh->getLane()->getID(), time2string(t));
2345
veh->onRemovalFromNet(MSMoveReminder::NOTIFICATION_VAPORIZED_COLLISION);
2346
MSNet::getInstance()->getVehicleControl().scheduleVehicleRemoval(veh);
2347
} else if (getCollisionAction() == COLLISION_ACTION_TELEPORT) {
2348
WRITE_WARNINGF(TL("Teleporting vehicle '%' after earlier collision, lane='%', time=%."),
2349
veh->getID(), veh->getLane()->getID(), time2string(t));
2350
MSVehicleTransfer::getInstance()->add(t, veh);
2351
} else {
2352
if (firstNotStopped == nullptr && !(*i)->isStopped() && (*i)->getLane() == this) {
2353
firstNotStopped = *i;
2354
}
2355
++i;
2356
continue;
2357
}
2358
} else {
2359
if (firstNotStopped == nullptr && !(*i)->isStopped() && (*i)->getLane() == this) {
2360
firstNotStopped = *i;
2361
}
2362
++i;
2363
continue;
2364
}
2365
myBruttoVehicleLengthSumToRemove += length;
2366
myNettoVehicleLengthSumToRemove += nettoLength;
2367
++i;
2368
i = VehCont::reverse_iterator(myVehicles.erase(i.base()));
2369
}
2370
if (firstNotStopped != nullptr) {
2371
const SUMOTime ttt = firstNotStopped->getVehicleType().getParameter().getTimeToTeleport(MSGlobals::gTimeToGridlock);
2372
const SUMOTime tttb = firstNotStopped->getVehicleType().getParameter().getTimeToTeleportBidi(MSGlobals::gTimeToTeleportBidi);
2373
if (ttt > 0 || MSGlobals::gTimeToGridlockHighways > 0 || MSGlobals::gTimeToTeleportDisconnected >= 0 || tttb > 0 || MSGlobals::gTimeToTeleportRSDeadlock > 0) {
2374
const bool wrongLane = !appropriate(firstNotStopped);
2375
const bool disconnected = (MSGlobals::gTimeToTeleportDisconnected >= 0
2376
&& firstNotStopped->succEdge(1) != nullptr
2377
&& firstNotStopped->getEdge()->allowedLanes(*firstNotStopped->succEdge(1), firstNotStopped->getVClass()) == nullptr);
2378
2379
const bool r1 = ttt > 0 && firstNotStopped->getWaitingTime() > ttt && !disconnected
2380
// never teleport a taxi on the last edge of it's route (where it would exit the simulation)
2381
&& (firstNotStopped->getDevice(typeid(MSDevice_Taxi)) == nullptr || firstNotStopped->getRoutePosition() < (firstNotStopped->getRoute().size() - 1));
2382
const bool r2 = !r1 && MSGlobals::gTimeToGridlockHighways > 0
2383
&& firstNotStopped->getWaitingTime() > MSGlobals::gTimeToGridlockHighways
2384
&& getSpeedLimit() > MSGlobals::gGridlockHighwaysSpeed && wrongLane
2385
&& !disconnected;
2386
const bool r3 = disconnected && firstNotStopped->getWaitingTime() > MSGlobals::gTimeToTeleportDisconnected;
2387
const bool r4 = !r1 && !r2 && !r3 && tttb > 0
2388
&& firstNotStopped->getWaitingTime() > tttb && getBidiLane() && !disconnected;
2389
const bool r5 = MSGlobals::gTimeToTeleportRSDeadlock > 0 && MSRailSignalControl::hasInstance() && !r1 && !r2 && !r3 && !r4
2390
&& firstNotStopped->getWaitingTime() > MSGlobals::gTimeToTeleportRSDeadlock && MSRailSignalControl::getInstance().haveDeadlock(firstNotStopped);
2391
if (r1 || r2 || r3 || r4 || r5) {
2392
const std::vector<MSLink*>::const_iterator link = succLinkSec(*firstNotStopped, 1, *this, firstNotStopped->getBestLanesContinuation());
2393
const bool minorLink = !wrongLane && (link != myLinks.end()) && !((*link)->havePriority());
2394
std::string reason = (wrongLane ? " (wrong lane" : (minorLink ? " (yield" : " (jam"));
2395
myBruttoVehicleLengthSumToRemove += firstNotStopped->getVehicleType().getLengthWithGap();
2396
myNettoVehicleLengthSumToRemove += firstNotStopped->getVehicleType().getLength();
2397
if (firstNotStopped == myVehicles.back()) {
2398
myVehicles.pop_back();
2399
} else {
2400
myVehicles.erase(std::find(myVehicles.begin(), myVehicles.end(), firstNotStopped));
2401
reason = " (blocked";
2402
}
2403
WRITE_WARNINGF("Teleporting vehicle '%'; waited too long" + reason
2404
+ (r2 ? ", highway" : "")
2405
+ (r3 ? ", disconnected" : "")
2406
+ (r4 ? ", bidi" : "")
2407
+ (r5 ? ", railSignal" : "")
2408
+ "), lane='%', time=%.", firstNotStopped->getID(), getID(), time2string(t));
2409
if (wrongLane) {
2410
MSNet::getInstance()->getVehicleControl().registerTeleportWrongLane();
2411
} else if (minorLink) {
2412
MSNet::getInstance()->getVehicleControl().registerTeleportYield();
2413
} else {
2414
MSNet::getInstance()->getVehicleControl().registerTeleportJam();
2415
}
2416
if (MSGlobals::gRemoveGridlocked) {
2417
firstNotStopped->onRemovalFromNet(MSMoveReminder::NOTIFICATION_TELEPORT_ARRIVED);
2418
MSNet::getInstance()->getVehicleControl().scheduleVehicleRemoval(firstNotStopped);
2419
} else {
2420
MSVehicleTransfer::getInstance()->add(t, firstNotStopped);
2421
}
2422
}
2423
}
2424
}
2425
if (MSGlobals::gSublane) {
2426
// trigger sorting of vehicles as their order may have changed
2427
MSNet::getInstance()->getEdgeControl().needsVehicleIntegration(this);
2428
}
2429
}
2430
2431
2432
void
2433
MSLane::markRecalculateBruttoSum() {
2434
myRecalculateBruttoSum = true;
2435
}
2436
2437
2438
void
2439
MSLane::updateLengthSum() {
2440
myBruttoVehicleLengthSum -= myBruttoVehicleLengthSumToRemove;
2441
myNettoVehicleLengthSum -= myNettoVehicleLengthSumToRemove;
2442
myBruttoVehicleLengthSumToRemove = 0;
2443
myNettoVehicleLengthSumToRemove = 0;
2444
if (myVehicles.empty()) {
2445
// avoid numerical instability
2446
myBruttoVehicleLengthSum = 0;
2447
myNettoVehicleLengthSum = 0;
2448
} else if (myRecalculateBruttoSum) {
2449
myBruttoVehicleLengthSum = 0;
2450
for (VehCont::const_iterator i = myVehicles.begin(); i != myVehicles.end(); ++i) {
2451
myBruttoVehicleLengthSum += (*i)->getVehicleType().getLengthWithGap();
2452
}
2453
myRecalculateBruttoSum = false;
2454
}
2455
}
2456
2457
2458
void
2459
MSLane::changeLanes(const SUMOTime t) {
2460
myEdge->changeLanes(t);
2461
}
2462
2463
2464
const MSEdge*
2465
MSLane::getNextNormal() const {
2466
return myEdge->getNormalSuccessor();
2467
}
2468
2469
2470
const MSLane*
2471
MSLane::getFirstInternalInConnection(double& offset) const {
2472
if (!this->isInternal()) {
2473
return nullptr;
2474
}
2475
offset = 0.;
2476
const MSLane* firstInternal = this;
2477
MSLane* pred = getCanonicalPredecessorLane();
2478
while (pred != nullptr && pred->isInternal()) {
2479
firstInternal = pred;
2480
offset += pred->getLength();
2481
pred = firstInternal->getCanonicalPredecessorLane();
2482
}
2483
return firstInternal;
2484
}
2485
2486
2487
// ------ Static (sic!) container methods ------
2488
bool
2489
MSLane::dictionary(const std::string& id, MSLane* ptr) {
2490
const DictType::iterator it = myDict.lower_bound(id);
2491
if (it == myDict.end() || it->first != id) {
2492
// id not in myDict
2493
myDict.emplace_hint(it, id, ptr);
2494
return true;
2495
}
2496
return false;
2497
}
2498
2499
2500
MSLane*
2501
MSLane::dictionary(const std::string& id) {
2502
const DictType::iterator it = myDict.find(id);
2503
if (it == myDict.end()) {
2504
// id not in myDict
2505
return nullptr;
2506
}
2507
return it->second;
2508
}
2509
2510
2511
void
2512
MSLane::clear() {
2513
for (DictType::iterator i = myDict.begin(); i != myDict.end(); ++i) {
2514
delete (*i).second;
2515
}
2516
myDict.clear();
2517
}
2518
2519
2520
void
2521
MSLane::insertIDs(std::vector<std::string>& into) {
2522
for (DictType::iterator i = myDict.begin(); i != myDict.end(); ++i) {
2523
into.push_back((*i).first);
2524
}
2525
}
2526
2527
2528
template<class RTREE> void
2529
MSLane::fill(RTREE& into) {
2530
for (DictType::iterator i = myDict.begin(); i != myDict.end(); ++i) {
2531
MSLane* l = (*i).second;
2532
Boundary b = l->getShape().getBoxBoundary();
2533
b.grow(3.);
2534
const float cmin[2] = {(float) b.xmin(), (float) b.ymin()};
2535
const float cmax[2] = {(float) b.xmax(), (float) b.ymax()};
2536
into.Insert(cmin, cmax, l);
2537
}
2538
}
2539
2540
template void MSLane::fill<NamedRTree>(NamedRTree& into);
2541
template void MSLane::fill<LANE_RTREE_QUAL>(LANE_RTREE_QUAL& into);
2542
2543
// ------ ------
2544
bool
2545
MSLane::appropriate(const MSVehicle* veh) const {
2546
if (veh->getLaneChangeModel().isOpposite()) {
2547
return false;
2548
}
2549
if (myEdge->isInternal()) {
2550
return true;
2551
}
2552
if (veh->succEdge(1) == nullptr) {
2553
assert((int)veh->getBestLanes().size() > veh->getLaneIndex());
2554
if (veh->getBestLanes()[veh->getLaneIndex()].bestLaneOffset == 0) {
2555
return true;
2556
} else {
2557
return false;
2558
}
2559
}
2560
std::vector<MSLink*>::const_iterator link = succLinkSec(*veh, 1, *this, veh->getBestLanesContinuation());
2561
return (link != myLinks.end());
2562
}
2563
2564
2565
void
2566
MSLane::integrateNewVehicles() {
2567
myNeedsCollisionCheck = true;
2568
std::vector<MSVehicle*>& buffered = myVehBuffer.getContainer();
2569
sort(buffered.begin(), buffered.end(), vehicle_position_sorter(this));
2570
for (MSVehicle* const veh : buffered) {
2571
assert(veh->getLane() == this);
2572
myVehicles.insert(myVehicles.begin(), veh);
2573
myBruttoVehicleLengthSum += veh->getVehicleType().getLengthWithGap();
2574
myNettoVehicleLengthSum += veh->getVehicleType().getLength();
2575
//if (true) std::cout << SIMTIME << " integrateNewVehicle lane=" << getID() << " veh=" << veh->getID() << " (on lane " << veh->getLane()->getID() << ") into lane=" << getID() << " myBrutto=" << myBruttoVehicleLengthSum << "\n";
2576
myEdge->markDelayed();
2577
}
2578
buffered.clear();
2579
myVehBuffer.unlock();
2580
//std::cout << SIMTIME << " integrateNewVehicle lane=" << getID() << " myVehicles1=" << toString(myVehicles);
2581
if (MSGlobals::gLateralResolution > 0 || myOpposite != nullptr) {
2582
sort(myVehicles.begin(), myVehicles.end(), vehicle_natural_position_sorter(this));
2583
}
2584
sortPartialVehicles();
2585
#ifdef DEBUG_VEHICLE_CONTAINER
2586
if (DEBUG_COND) std::cout << SIMTIME << " integrateNewVehicle lane=" << getID()
2587
<< " vehicles=" << toString(myVehicles) << " partials=" << toString(myPartialVehicles) << "\n";
2588
#endif
2589
}
2590
2591
2592
void
2593
MSLane::sortPartialVehicles() {
2594
if (myPartialVehicles.size() > 1) {
2595
sort(myPartialVehicles.begin(), myPartialVehicles.end(), vehicle_natural_position_sorter(this));
2596
}
2597
}
2598
2599
2600
void
2601
MSLane::sortManeuverReservations() {
2602
if (myManeuverReservations.size() > 1) {
2603
#ifdef DEBUG_CONTEXT
2604
if (DEBUG_COND) {
2605
std::cout << "sortManeuverReservations on lane " << getID()
2606
<< "\nBefore sort: " << toString(myManeuverReservations) << std::endl;
2607
}
2608
#endif
2609
sort(myManeuverReservations.begin(), myManeuverReservations.end(), vehicle_natural_position_sorter(this));
2610
#ifdef DEBUG_CONTEXT
2611
if (DEBUG_COND) {
2612
std::cout << "After sort: " << toString(myManeuverReservations) << std::endl;
2613
}
2614
#endif
2615
}
2616
}
2617
2618
2619
bool
2620
MSLane::isInternal() const {
2621
return myEdge->isInternal();
2622
}
2623
2624
2625
bool
2626
MSLane::isNormal() const {
2627
return myEdge->isNormal();
2628
}
2629
2630
2631
bool
2632
MSLane::isCrossing() const {
2633
return myEdge->isCrossing();
2634
}
2635
2636
bool
2637
MSLane::isWalkingArea() const {
2638
return myEdge->isWalkingArea();
2639
}
2640
2641
2642
MSVehicle*
2643
MSLane::getLastFullVehicle() const {
2644
if (myVehicles.size() == 0) {
2645
return nullptr;
2646
}
2647
return myVehicles.front();
2648
}
2649
2650
2651
MSVehicle*
2652
MSLane::getFirstFullVehicle() const {
2653
if (myVehicles.size() == 0) {
2654
return nullptr;
2655
}
2656
return myVehicles.back();
2657
}
2658
2659
2660
MSVehicle*
2661
MSLane::getLastAnyVehicle() const {
2662
// all vehicles in myVehicles should have positions smaller or equal to
2663
// those in myPartialVehicles (unless we're on a bidi-lane)
2664
if (myVehicles.size() > 0) {
2665
if (myBidiLane != nullptr && myPartialVehicles.size() > 0) {
2666
if (myVehicles.front()->getPositionOnLane() > myPartialVehicles.front()->getPositionOnLane(this)) {
2667
return myPartialVehicles.front();
2668
}
2669
}
2670
return myVehicles.front();
2671
}
2672
if (myPartialVehicles.size() > 0) {
2673
return myPartialVehicles.front();
2674
}
2675
return nullptr;
2676
}
2677
2678
2679
MSVehicle*
2680
MSLane::getFirstAnyVehicle() const {
2681
MSVehicle* result = nullptr;
2682
if (myVehicles.size() > 0) {
2683
result = myVehicles.back();
2684
}
2685
if (myPartialVehicles.size() > 0
2686
&& (result == nullptr || result->getPositionOnLane(this) < myPartialVehicles.back()->getPositionOnLane(this))) {
2687
result = myPartialVehicles.back();
2688
}
2689
return result;
2690
}
2691
2692
2693
std::vector<MSLink*>::const_iterator
2694
MSLane::succLinkSec(const SUMOVehicle& veh, int nRouteSuccs,
2695
const MSLane& succLinkSource, const std::vector<MSLane*>& conts) {
2696
const MSEdge* nRouteEdge = veh.succEdge(nRouteSuccs);
2697
// check whether the vehicle tried to look beyond its route
2698
if (nRouteEdge == nullptr) {
2699
// return end (no succeeding link) if so
2700
return succLinkSource.myLinks.end();
2701
}
2702
// if we are on an internal lane there should only be one link and it must be allowed
2703
if (succLinkSource.isInternal()) {
2704
assert(succLinkSource.myLinks.size() == 1);
2705
// could have been disallowed dynamically with a rerouter or via TraCI
2706
// assert(succLinkSource.myLinks[0]->getLane()->allowsVehicleClass(veh.getVehicleType().getVehicleClass()));
2707
return succLinkSource.myLinks.begin();
2708
}
2709
// a link may be used if
2710
// 1) there is a destination lane ((*link)->getLane()!=0)
2711
// 2) the destination lane belongs to the next edge in route ((*link)->getLane()->myEdge == nRouteEdge)
2712
// 3) the destination lane allows the vehicle's class ((*link)->getLane()->allowsVehicleClass(veh.getVehicleClass()))
2713
2714
// there should be a link which leads to the next desired lane our route in "conts" (built in "getBestLanes")
2715
// "conts" stores the best continuations of our current lane
2716
// we should never return an arbitrary link since this may cause collisions
2717
2718
if (nRouteSuccs < (int)conts.size()) {
2719
// we go through the links in our list and return the matching one
2720
for (std::vector<MSLink*>::const_iterator link = succLinkSource.myLinks.begin(); link != succLinkSource.myLinks.end(); ++link) {
2721
if ((*link)->getLane() != nullptr && (*link)->getLane()->myEdge == nRouteEdge
2722
&& (*link)->getLane()->allowsVehicleClass(veh.getVClass())
2723
&& ((*link)->getViaLane() == nullptr || (*link)->getViaLane()->allowsVehicleClass(veh.getVClass()))) {
2724
// we should use the link if it connects us to the best lane
2725
if ((*link)->getLane() == conts[nRouteSuccs]) {
2726
return link;
2727
}
2728
}
2729
}
2730
} else {
2731
// the source lane is a dead end (no continuations exist)
2732
return succLinkSource.myLinks.end();
2733
}
2734
// the only case where this should happen is for a disconnected route (deliberately ignored)
2735
#ifdef DEBUG_NO_CONNECTION
2736
// the "'" around the ids are missing intentionally in the message below because it slows messaging down, resulting in test timeouts
2737
WRITE_WARNING("Could not find connection between lane " + succLinkSource.getID() + " and lane " + conts[nRouteSuccs]->getID() +
2738
" for vehicle " + veh.getID() + ", time=" + time2string(MSNet::getInstance()->getCurrentTimeStep()) + ".");
2739
#endif
2740
return succLinkSource.myLinks.end();
2741
}
2742
2743
2744
const MSLink*
2745
MSLane::getLinkTo(const MSLane* const target) const {
2746
const bool internal = target->isInternal();
2747
for (const MSLink* const l : myLinks) {
2748
if ((internal && l->getViaLane() == target) || (!internal && l->getLane() == target)) {
2749
return l;
2750
}
2751
}
2752
return nullptr;
2753
}
2754
2755
2756
const MSLane*
2757
MSLane::getInternalFollowingLane(const MSLane* const target) const {
2758
for (const MSLink* const l : myLinks) {
2759
if (l->getLane() == target) {
2760
return l->getViaLane();
2761
}
2762
}
2763
return nullptr;
2764
}
2765
2766
2767
const MSLink*
2768
MSLane::getEntryLink() const {
2769
if (!isInternal()) {
2770
return nullptr;
2771
}
2772
const MSLane* internal = this;
2773
const MSLane* lane = this->getCanonicalPredecessorLane();
2774
assert(lane != nullptr);
2775
while (lane->isInternal()) {
2776
internal = lane;
2777
lane = lane->getCanonicalPredecessorLane();
2778
assert(lane != nullptr);
2779
}
2780
return lane->getLinkTo(internal);
2781
}
2782
2783
2784
void
2785
MSLane::setMaxSpeed(double val, bool byVSS, bool byTraCI, double jamThreshold) {
2786
myMaxSpeed = val;
2787
mySpeedByVSS = byVSS;
2788
mySpeedByTraCI = byTraCI;
2789
myEdge->recalcCache();
2790
if (MSGlobals::gUseMesoSim) {
2791
MESegment* first = MSGlobals::gMesoNet->getSegmentForEdge(*myEdge);
2792
while (first != nullptr) {
2793
first->setSpeed(val, SIMSTEP, jamThreshold, myIndex);
2794
first = first->getNextSegment();
2795
}
2796
}
2797
}
2798
2799
2800
void
2801
MSLane::setFrictionCoefficient(double val) {
2802
myFrictionCoefficient = val;
2803
myEdge->recalcCache();
2804
}
2805
2806
2807
void
2808
MSLane::setLength(double val) {
2809
myLength = val;
2810
myEdge->recalcCache();
2811
}
2812
2813
2814
void
2815
MSLane::swapAfterLaneChange(SUMOTime) {
2816
//if (getID() == "disabled_lane") std::cout << SIMTIME << " swapAfterLaneChange lane=" << getID() << " myVehicles=" << toString(myVehicles) << " myTmpVehicles=" << toString(myTmpVehicles) << "\n";
2817
myVehicles = myTmpVehicles;
2818
myTmpVehicles.clear();
2819
// this needs to be done after finishing lane-changing for all lanes on the
2820
// current edge (MSLaneChanger::updateLanes())
2821
sortPartialVehicles();
2822
if (MSGlobals::gSublane && getOpposite() != nullptr) {
2823
getOpposite()->sortPartialVehicles();
2824
}
2825
if (myBidiLane != nullptr) {
2826
myBidiLane->sortPartialVehicles();
2827
}
2828
}
2829
2830
2831
MSVehicle*
2832
MSLane::removeVehicle(MSVehicle* remVehicle, MSMoveReminder::Notification notification, bool notify) {
2833
assert(remVehicle->getLane() == this);
2834
for (MSLane::VehCont::iterator it = myVehicles.begin(); it < myVehicles.end(); it++) {
2835
if (remVehicle == *it) {
2836
if (notify) {
2837
remVehicle->leaveLane(notification);
2838
}
2839
myVehicles.erase(it);
2840
myBruttoVehicleLengthSum -= remVehicle->getVehicleType().getLengthWithGap();
2841
myNettoVehicleLengthSum -= remVehicle->getVehicleType().getLength();
2842
break;
2843
}
2844
}
2845
return remVehicle;
2846
}
2847
2848
2849
MSLane*
2850
MSLane::getParallelLane(int offset, bool includeOpposite) const {
2851
return myEdge->parallelLane(this, offset, includeOpposite);
2852
}
2853
2854
2855
void
2856
MSLane::addIncomingLane(MSLane* lane, MSLink* viaLink) {
2857
IncomingLaneInfo ili;
2858
ili.lane = lane;
2859
ili.viaLink = viaLink;
2860
ili.length = lane->getLength();
2861
myIncomingLanes.push_back(ili);
2862
}
2863
2864
2865
void
2866
MSLane::addApproachingLane(MSLane* lane, bool warnMultiCon) {
2867
MSEdge* approachingEdge = &lane->getEdge();
2868
if (myApproachingLanes.find(approachingEdge) == myApproachingLanes.end()) {
2869
myApproachingLanes[approachingEdge] = std::vector<MSLane*>();
2870
} else if (!approachingEdge->isInternal() && warnMultiCon) {
2871
// whenever a normal edge connects twice, there is a corresponding
2872
// internal edge wich connects twice, one warning is sufficient
2873
WRITE_WARNINGF(TL("Lane '%' is approached multiple times from edge '%'. This may cause collisions."),
2874
getID(), approachingEdge->getID());
2875
}
2876
myApproachingLanes[approachingEdge].push_back(lane);
2877
}
2878
2879
2880
bool
2881
MSLane::isApproachedFrom(MSEdge* const edge, MSLane* const lane) {
2882
std::map<MSEdge*, std::vector<MSLane*> >::const_iterator i = myApproachingLanes.find(edge);
2883
if (i == myApproachingLanes.end()) {
2884
return false;
2885
}
2886
const std::vector<MSLane*>& lanes = (*i).second;
2887
return std::find(lanes.begin(), lanes.end(), lane) != lanes.end();
2888
}
2889
2890
2891
double MSLane::getMissingRearGap(const MSVehicle* leader, double backOffset, double leaderSpeed) const {
2892
// this follows the same logic as getFollowerOnConsecutive. we do a tree
2893
// search and check for the vehicle with the largest missing rear gap within
2894
// relevant range
2895
double result = 0;
2896
const double leaderDecel = leader->getCarFollowModel().getMaxDecel();
2897
CLeaderDist followerInfo = getFollowersOnConsecutive(leader, backOffset, false)[0];
2898
const MSVehicle* v = followerInfo.first;
2899
if (v != nullptr) {
2900
result = v->getCarFollowModel().getSecureGap(v, leader, v->getSpeed(), leaderSpeed, leaderDecel) - followerInfo.second;
2901
}
2902
return result;
2903
}
2904
2905
2906
double
2907
MSLane::getMaximumBrakeDist() const {
2908
const MSVehicleControl& vc = MSNet::getInstance()->getVehicleControl();
2909
const double maxSpeed = getSpeedLimit() * vc.getMaxSpeedFactor();
2910
// NOTE: For the euler update this is an upper bound on the actual braking distance (see ticket #860)
2911
// impose a hard bound due to visibility / common sense to avoid unnecessary computation if there are strange vehicles in the fleet
2912
const double minDecel = isRailway(myPermissions) ? vc.getMinDecelerationRail() : vc.getMinDeceleration();
2913
return MIN2(maxSpeed * maxSpeed * 0.5 / minDecel,
2914
myPermissions == SVC_SHIP ? 10000.0 : 1000.0);
2915
}
2916
2917
2918
std::pair<MSVehicle* const, double>
2919
MSLane::getLeader(const MSVehicle* veh, const double vehPos, const std::vector<MSLane*>& bestLaneConts, double dist, bool checkTmpVehicles) const {
2920
// get the leading vehicle for (shadow) veh
2921
// XXX this only works as long as all lanes of an edge have equal length
2922
#ifdef DEBUG_CONTEXT
2923
if (DEBUG_COND2(veh)) {
2924
std::cout << " getLeader lane=" << getID() << " ego=" << veh->getID() << " vehs=" << toString(myVehicles) << " tmpVehs=" << toString(myTmpVehicles) << "\n";
2925
}
2926
#endif
2927
if (checkTmpVehicles) {
2928
for (VehCont::const_iterator last = myTmpVehicles.begin(); last != myTmpVehicles.end(); ++last) {
2929
// XXX refactor leaderInfo to use a const vehicle all the way through the call hierarchy
2930
MSVehicle* pred = (MSVehicle*)*last;
2931
if (pred == veh) {
2932
continue;
2933
}
2934
#ifdef DEBUG_CONTEXT
2935
if (DEBUG_COND2(veh)) {
2936
std::cout << std::setprecision(gPrecision) << " getLeader lane=" << getID() << " ego=" << veh->getID() << " egoPos=" << vehPos << " pred=" << pred->getID() << " predPos=" << pred->getPositionOnLane() << "\n";
2937
}
2938
#endif
2939
if (pred->getPositionOnLane() >= vehPos) {
2940
return std::pair<MSVehicle* const, double>(pred, pred->getBackPositionOnLane(this) - veh->getVehicleType().getMinGap() - vehPos);
2941
}
2942
}
2943
} else {
2944
for (AnyVehicleIterator last = anyVehiclesBegin(); last != anyVehiclesEnd(); ++last) {
2945
// XXX refactor leaderInfo to use a const vehicle all the way through the call hierarchy
2946
MSVehicle* pred = (MSVehicle*)*last;
2947
if (pred == veh) {
2948
continue;
2949
}
2950
#ifdef DEBUG_CONTEXT
2951
if (DEBUG_COND2(veh)) {
2952
std::cout << " getLeader lane=" << getID() << " ego=" << veh->getID() << " egoPos=" << vehPos
2953
<< " pred=" << pred->getID() << " predPos=" << pred->getPositionOnLane(this) << " predBack=" << pred->getBackPositionOnLane(this) << "\n";
2954
}
2955
#endif
2956
if (pred->getPositionOnLane(this) >= vehPos) {
2957
if (MSGlobals::gLaneChangeDuration > 0
2958
&& pred->getLaneChangeModel().isOpposite()
2959
&& !pred->getLaneChangeModel().isChangingLanes()
2960
&& pred->getLaneChangeModel().getShadowLane() == this) {
2961
// skip non-overlapping shadow
2962
continue;
2963
}
2964
return std::pair<MSVehicle* const, double>(pred, pred->getBackPositionOnLane(this) - veh->getVehicleType().getMinGap() - vehPos);
2965
}
2966
}
2967
}
2968
// XXX from here on the code mirrors MSLaneChanger::getRealLeader
2969
if (bestLaneConts.size() > 0) {
2970
double seen = getLength() - vehPos;
2971
double speed = veh->getSpeed();
2972
if (dist < 0) {
2973
dist = veh->getCarFollowModel().brakeGap(speed) + veh->getVehicleType().getMinGap();
2974
}
2975
#ifdef DEBUG_CONTEXT
2976
if (DEBUG_COND2(veh)) {
2977
std::cout << " getLeader lane=" << getID() << " seen=" << seen << " dist=" << dist << "\n";
2978
}
2979
#endif
2980
if (seen > dist) {
2981
return std::pair<MSVehicle* const, double>(static_cast<MSVehicle*>(nullptr), -1);
2982
}
2983
return getLeaderOnConsecutive(dist, seen, speed, *veh, bestLaneConts);
2984
} else {
2985
return std::make_pair(static_cast<MSVehicle*>(nullptr), -1);
2986
}
2987
}
2988
2989
2990
std::pair<MSVehicle* const, double>
2991
MSLane::getLeaderOnConsecutive(double dist, double seen, double speed, const MSVehicle& veh,
2992
const std::vector<MSLane*>& bestLaneConts, bool considerCrossingFoes) const {
2993
#ifdef DEBUG_CONTEXT
2994
if (DEBUG_COND2(&veh)) {
2995
std::cout << " getLeaderOnConsecutive lane=" << getID() << " ego=" << veh.getID() << " seen=" << seen << " dist=" << dist << " conts=" << toString(bestLaneConts) << "\n";
2996
}
2997
#endif
2998
if (seen > dist && !isInternal()) {
2999
return std::make_pair(static_cast<MSVehicle*>(nullptr), -1);
3000
}
3001
int view = 1;
3002
// loop over following lanes
3003
if (myPartialVehicles.size() > 0) {
3004
// XXX
3005
MSVehicle* pred = myPartialVehicles.front();
3006
const double gap = seen - (getLength() - pred->getBackPositionOnLane(this)) - veh.getVehicleType().getMinGap();
3007
#ifdef DEBUG_CONTEXT
3008
if (DEBUG_COND2(&veh)) {
3009
std::cout << " predGap=" << gap << " partials=" << toString(myPartialVehicles) << "\n";
3010
}
3011
#endif
3012
// make sure pred is really a leader and not doing continous lane-changing behind ego
3013
if (gap > 0) {
3014
return std::pair<MSVehicle* const, double>(pred, gap);
3015
}
3016
}
3017
#ifdef DEBUG_CONTEXT
3018
if (DEBUG_COND2(&veh)) {
3019
gDebugFlag1 = true;
3020
}
3021
#endif
3022
const MSLane* nextLane = this;
3023
do {
3024
nextLane->getVehiclesSecure(); // lock against running sim when called from GUI for time gap coloring
3025
// get the next link used
3026
std::vector<MSLink*>::const_iterator link = succLinkSec(veh, view, *nextLane, bestLaneConts);
3027
if (nextLane->isLinkEnd(link) && view < veh.getRoute().size() - veh.getRoutePosition()) {
3028
const MSEdge* nextEdge = *(veh.getCurrentRouteEdge() + view);
3029
if (nextEdge->getNumLanes() == 1) {
3030
// lanes are unambiguous on the next route edge, continue beyond bestLaneConts
3031
for (link = nextLane->getLinkCont().begin(); link < nextLane->getLinkCont().end(); link++) {
3032
if ((*link)->getLane() == nextEdge->getLanes().front()) {
3033
break;
3034
}
3035
}
3036
}
3037
}
3038
if (nextLane->isLinkEnd(link)) {
3039
#ifdef DEBUG_CONTEXT
3040
if (DEBUG_COND2(&veh)) {
3041
std::cout << " cannot continue after nextLane=" << nextLane->getID() << "\n";
3042
}
3043
#endif
3044
nextLane->releaseVehicles();
3045
break;
3046
}
3047
// check for link leaders
3048
const bool laneChanging = veh.getLane() != this;
3049
const MSLink::LinkLeaders linkLeaders = (*link)->getLeaderInfo(&veh, seen);
3050
nextLane->releaseVehicles();
3051
if (linkLeaders.size() > 0) {
3052
std::pair<MSVehicle*, double> result;
3053
double shortestGap = std::numeric_limits<double>::max();
3054
for (auto ll : linkLeaders) {
3055
double gap = ll.vehAndGap.second;
3056
MSVehicle* lVeh = ll.vehAndGap.first;
3057
if (lVeh != nullptr) {
3058
// leader is a vehicle, not a pedestrian
3059
gap += lVeh->getCarFollowModel().brakeGap(lVeh->getSpeed(), lVeh->getCarFollowModel().getMaxDecel(), 0);
3060
}
3061
#ifdef DEBUG_CONTEXT
3062
if (DEBUG_COND2(&veh)) {
3063
std::cout << " linkLeader candidate " << Named::getIDSecure(lVeh)
3064
<< " isLeader=" << veh.isLeader(*link, lVeh, ll.vehAndGap.second)
3065
<< " gap=" << ll.vehAndGap.second
3066
<< " gap+brakeing=" << gap
3067
<< "\n";
3068
}
3069
#endif
3070
// skip vehicles which do not share the outgoing edge (to get only real leader vehicles in TraCI #13842)
3071
if (!considerCrossingFoes && !ll.sameTarget()) {
3072
continue;
3073
}
3074
// in the context of lane-changing, all candidates are leaders
3075
if (lVeh != nullptr && !laneChanging && !veh.isLeader(*link, lVeh, ll.vehAndGap.second)) {
3076
continue;
3077
}
3078
if (gap < shortestGap) {
3079
shortestGap = gap;
3080
if (ll.vehAndGap.second < 0 && !MSGlobals::gComputeLC) {
3081
// can always continue up to the stop line or crossing point
3082
// @todo: figure out whether this should also impact lane changing
3083
ll.vehAndGap.second = MAX2(seen - nextLane->getLength(), ll.distToCrossing);
3084
}
3085
result = ll.vehAndGap;
3086
}
3087
}
3088
if (shortestGap != std::numeric_limits<double>::max()) {
3089
#ifdef DEBUG_CONTEXT
3090
if (DEBUG_COND2(&veh)) {
3091
std::cout << " found linkLeader after nextLane=" << nextLane->getID() << "\n";
3092
gDebugFlag1 = false;
3093
}
3094
#endif
3095
return result;
3096
}
3097
}
3098
bool nextInternal = (*link)->getViaLane() != nullptr;
3099
nextLane = (*link)->getViaLaneOrLane();
3100
if (nextLane == nullptr) {
3101
break;
3102
}
3103
nextLane->getVehiclesSecure(); // lock against running sim when called from GUI for time gap coloring
3104
MSVehicle* leader = nextLane->getLastAnyVehicle();
3105
if (leader != nullptr) {
3106
#ifdef DEBUG_CONTEXT
3107
if (DEBUG_COND2(&veh)) {
3108
std::cout << " found leader " << leader->getID() << " on nextLane=" << nextLane->getID() << "\n";
3109
}
3110
#endif
3111
const double leaderDist = seen + leader->getBackPositionOnLane(nextLane) - veh.getVehicleType().getMinGap();
3112
nextLane->releaseVehicles();
3113
return std::make_pair(leader, leaderDist);
3114
}
3115
nextLane->releaseVehicles();
3116
if (nextLane->getVehicleMaxSpeed(&veh) < speed) {
3117
dist = veh.getCarFollowModel().brakeGap(nextLane->getVehicleMaxSpeed(&veh));
3118
}
3119
seen += nextLane->getLength();
3120
if (!nextInternal) {
3121
view++;
3122
}
3123
} while (seen <= dist || nextLane->isInternal());
3124
#ifdef DEBUG_CONTEXT
3125
gDebugFlag1 = false;
3126
#endif
3127
return std::make_pair(static_cast<MSVehicle*>(nullptr), -1);
3128
}
3129
3130
3131
std::pair<MSVehicle* const, double>
3132
MSLane::getCriticalLeader(double dist, double seen, double speed, const MSVehicle& veh) const {
3133
#ifdef DEBUG_CONTEXT
3134
if (DEBUG_COND2(&veh)) {
3135
std::cout << SIMTIME << " getCriticalLeader. lane=" << getID() << " veh=" << veh.getID() << "\n";
3136
}
3137
#endif
3138
const std::vector<MSLane*>& bestLaneConts = veh.getBestLanesContinuation(this);
3139
std::pair<MSVehicle*, double> result = std::make_pair(static_cast<MSVehicle*>(nullptr), -1);
3140
double safeSpeed = std::numeric_limits<double>::max();
3141
int view = 1;
3142
// loop over following lanes
3143
// @note: we don't check the partial occupator for this lane since it was
3144
// already checked in MSLaneChanger::getRealLeader()
3145
const MSLane* nextLane = this;
3146
SUMOTime arrivalTime = MSNet::getInstance()->getCurrentTimeStep() + TIME2STEPS(seen / MAX2(speed, NUMERICAL_EPS));
3147
do {
3148
// get the next link used
3149
std::vector<MSLink*>::const_iterator link = succLinkSec(veh, view, *nextLane, bestLaneConts);
3150
if (nextLane->isLinkEnd(link) || !(*link)->opened(arrivalTime, speed, speed, veh.getVehicleType().getLength(),
3151
veh.getImpatience(), veh.getCarFollowModel().getMaxDecel(), 0, veh.getLateralPositionOnLane(), nullptr, false, &veh) || (*link)->haveRed()) {
3152
return result;
3153
}
3154
// check for link leaders
3155
#ifdef DEBUG_CONTEXT
3156
if (DEBUG_COND2(&veh)) {
3157
gDebugFlag1 = true; // See MSLink::getLeaderInfo
3158
}
3159
#endif
3160
const MSLink::LinkLeaders linkLeaders = (*link)->getLeaderInfo(&veh, seen);
3161
#ifdef DEBUG_CONTEXT
3162
if (DEBUG_COND2(&veh)) {
3163
gDebugFlag1 = false; // See MSLink::getLeaderInfo
3164
}
3165
#endif
3166
for (MSLink::LinkLeaders::const_iterator it = linkLeaders.begin(); it != linkLeaders.end(); ++it) {
3167
const MSVehicle* leader = (*it).vehAndGap.first;
3168
if (leader != nullptr && leader != result.first) {
3169
// XXX ignoring pedestrians here!
3170
// XXX ignoring the fact that the link leader may alread by following us
3171
// XXX ignoring the fact that we may drive up to the crossing point
3172
double tmpSpeed = safeSpeed;
3173
veh.adaptToJunctionLeader((*it).vehAndGap, seen, nullptr, nextLane, tmpSpeed, tmpSpeed, (*it).distToCrossing);
3174
#ifdef DEBUG_CONTEXT
3175
if (DEBUG_COND2(&veh)) {
3176
std::cout << " linkLeader=" << leader->getID() << " gap=" << result.second << " tmpSpeed=" << tmpSpeed << " safeSpeed=" << safeSpeed << "\n";
3177
}
3178
#endif
3179
if (tmpSpeed < safeSpeed) {
3180
safeSpeed = tmpSpeed;
3181
result = (*it).vehAndGap;
3182
}
3183
}
3184
}
3185
bool nextInternal = (*link)->getViaLane() != nullptr;
3186
nextLane = (*link)->getViaLaneOrLane();
3187
if (nextLane == nullptr) {
3188
break;
3189
}
3190
MSVehicle* leader = nextLane->getLastAnyVehicle();
3191
if (leader != nullptr && leader != result.first) {
3192
const double gap = seen + leader->getBackPositionOnLane(nextLane) - veh.getVehicleType().getMinGap();
3193
const double tmpSpeed = veh.getCarFollowModel().insertionFollowSpeed(&veh, speed, gap, leader->getSpeed(), leader->getCarFollowModel().getMaxDecel(), leader);
3194
if (tmpSpeed < safeSpeed) {
3195
safeSpeed = tmpSpeed;
3196
result = std::make_pair(leader, gap);
3197
}
3198
}
3199
if (nextLane->getVehicleMaxSpeed(&veh) < speed) {
3200
dist = veh.getCarFollowModel().brakeGap(nextLane->getVehicleMaxSpeed(&veh));
3201
}
3202
seen += nextLane->getLength();
3203
if (seen <= dist) {
3204
// delaying the update of arrivalTime and making it conditional to avoid possible integer overflows
3205
arrivalTime += TIME2STEPS(nextLane->getLength() / MAX2(speed, NUMERICAL_EPS));
3206
}
3207
if (!nextInternal) {
3208
view++;
3209
}
3210
} while (seen <= dist || nextLane->isInternal());
3211
return result;
3212
}
3213
3214
3215
MSLane*
3216
MSLane::getLogicalPredecessorLane() const {
3217
if (myLogicalPredecessorLane == nullptr) {
3218
MSEdgeVector pred = myEdge->getPredecessors();
3219
// get only those edges which connect to this lane
3220
for (MSEdgeVector::iterator i = pred.begin(); i != pred.end();) {
3221
std::vector<IncomingLaneInfo>::const_iterator j = find_if(myIncomingLanes.begin(), myIncomingLanes.end(), edge_finder(*i));
3222
if (j == myIncomingLanes.end()) {
3223
i = pred.erase(i);
3224
} else {
3225
++i;
3226
}
3227
}
3228
// get the lane with the "straightest" connection
3229
if (pred.size() != 0) {
3230
std::sort(pred.begin(), pred.end(), by_connections_to_sorter(&getEdge()));
3231
MSEdge* best = *pred.begin();
3232
std::vector<IncomingLaneInfo>::const_iterator j = find_if(myIncomingLanes.begin(), myIncomingLanes.end(), edge_finder(best));
3233
myLogicalPredecessorLane = j->lane;
3234
}
3235
}
3236
return myLogicalPredecessorLane;
3237
}
3238
3239
3240
const MSLane*
3241
MSLane::getNormalPredecessorLane() const {
3242
if (isInternal()) {
3243
return getLogicalPredecessorLane()->getNormalPredecessorLane();
3244
} else {
3245
return this;
3246
}
3247
}
3248
3249
3250
const MSLane*
3251
MSLane::getNormalSuccessorLane() const {
3252
if (isInternal()) {
3253
return getCanonicalSuccessorLane()->getNormalSuccessorLane();
3254
} else {
3255
return this;
3256
}
3257
}
3258
3259
3260
MSLane*
3261
MSLane::getLogicalPredecessorLane(const MSEdge& fromEdge) const {
3262
for (const IncomingLaneInfo& cand : myIncomingLanes) {
3263
if (&(cand.lane->getEdge()) == &fromEdge) {
3264
return cand.lane;
3265
}
3266
}
3267
return nullptr;
3268
}
3269
3270
3271
MSLane*
3272
MSLane::getCanonicalPredecessorLane() const {
3273
if (myCanonicalPredecessorLane != nullptr) {
3274
return myCanonicalPredecessorLane;
3275
}
3276
if (myIncomingLanes.empty()) {
3277
return nullptr;
3278
}
3279
// myCanonicalPredecessorLane has not yet been determined and there exist incoming lanes
3280
// get the lane with the priorized (or if this does not apply the "straightest") connection
3281
const auto bestLane = std::min_element(myIncomingLanes.begin(), myIncomingLanes.end(), incoming_lane_priority_sorter(this));
3282
{
3283
#ifdef HAVE_FOX
3284
ScopedLocker<> lock(myLeaderInfoMutex, MSGlobals::gNumSimThreads > 1);
3285
#endif
3286
myCanonicalPredecessorLane = bestLane->lane;
3287
}
3288
#ifdef DEBUG_LANE_SORTER
3289
std::cout << "\nBest predecessor lane for lane '" << myID << "': '" << myCanonicalPredecessorLane->getID() << "'" << std::endl;
3290
#endif
3291
return myCanonicalPredecessorLane;
3292
}
3293
3294
3295
MSLane*
3296
MSLane::getCanonicalSuccessorLane() const {
3297
if (myCanonicalSuccessorLane != nullptr) {
3298
return myCanonicalSuccessorLane;
3299
}
3300
if (myLinks.empty()) {
3301
return nullptr;
3302
}
3303
// myCanonicalSuccessorLane has not yet been determined and there exist outgoing links
3304
std::vector<MSLink*> candidateLinks = myLinks;
3305
// get the lane with the priorized (or if this does not apply the "straightest") connection
3306
std::sort(candidateLinks.begin(), candidateLinks.end(), outgoing_lane_priority_sorter(this));
3307
MSLane* best = (*candidateLinks.begin())->getViaLaneOrLane();
3308
#ifdef DEBUG_LANE_SORTER
3309
std::cout << "\nBest successor lane for lane '" << myID << "': '" << best->getID() << "'" << std::endl;
3310
#endif
3311
myCanonicalSuccessorLane = best;
3312
return myCanonicalSuccessorLane;
3313
}
3314
3315
3316
LinkState
3317
MSLane::getIncomingLinkState() const {
3318
const MSLane* const pred = getLogicalPredecessorLane();
3319
if (pred == nullptr) {
3320
return LINKSTATE_DEADEND;
3321
} else {
3322
return pred->getLinkTo(this)->getState();
3323
}
3324
}
3325
3326
3327
const std::vector<std::pair<const MSLane*, const MSEdge*> >
3328
MSLane::getOutgoingViaLanes() const {
3329
std::vector<std::pair<const MSLane*, const MSEdge*> > result;
3330
for (const MSLink* link : myLinks) {
3331
assert(link->getLane() != nullptr);
3332
result.push_back(std::make_pair(link->getLane(), link->getViaLane() == nullptr ? nullptr : &link->getViaLane()->getEdge()));
3333
}
3334
return result;
3335
}
3336
3337
std::vector<const MSLane*>
3338
MSLane::getNormalIncomingLanes() const {
3339
std::vector<const MSLane*> result = {};
3340
for (std::map<MSEdge*, std::vector<MSLane*> >::const_iterator it = myApproachingLanes.begin(); it != myApproachingLanes.end(); ++it) {
3341
for (std::vector<MSLane*>::const_iterator it_lane = (*it).second.begin(); it_lane != (*it).second.end(); ++it_lane) {
3342
if (!((*it_lane)->isInternal())) {
3343
result.push_back(*it_lane);
3344
}
3345
}
3346
}
3347
return result;
3348
}
3349
3350
3351
void
3352
MSLane::leftByLaneChange(MSVehicle* v) {
3353
myBruttoVehicleLengthSum -= v->getVehicleType().getLengthWithGap();
3354
myNettoVehicleLengthSum -= v->getVehicleType().getLength();
3355
}
3356
3357
3358
void
3359
MSLane::enteredByLaneChange(MSVehicle* v) {
3360
myBruttoVehicleLengthSum += v->getVehicleType().getLengthWithGap();
3361
myNettoVehicleLengthSum += v->getVehicleType().getLength();
3362
}
3363
3364
3365
int
3366
MSLane::getCrossingIndex() const {
3367
for (std::vector<MSLink*>::const_iterator i = myLinks.begin(); i != myLinks.end(); ++i) {
3368
if ((*i)->getLane()->isCrossing()) {
3369
return (int)(i - myLinks.begin());
3370
}
3371
}
3372
return -1;
3373
}
3374
3375
// ------------ Current state retrieval
3376
double
3377
MSLane::getFractionalVehicleLength(bool brutto) const {
3378
double sum = 0;
3379
if (myPartialVehicles.size() > 0) {
3380
const MSLane* bidi = getBidiLane();
3381
for (MSVehicle* cand : myPartialVehicles) {
3382
if (MSGlobals::gSublane && cand->getLaneChangeModel().getShadowLane() == this) {
3383
continue;
3384
}
3385
if (cand->getLane() == bidi) {
3386
sum += (brutto ? cand->getVehicleType().getLengthWithGap() : cand->getVehicleType().getLength());
3387
} else {
3388
sum += myLength - cand->getBackPositionOnLane(this);
3389
}
3390
}
3391
}
3392
return sum;
3393
}
3394
3395
double
3396
MSLane::getBruttoOccupancy() const {
3397
getVehiclesSecure();
3398
double fractions = getFractionalVehicleLength(true);
3399
if (myVehicles.size() != 0) {
3400
MSVehicle* lastVeh = myVehicles.front();
3401
if (lastVeh->getPositionOnLane() < lastVeh->getVehicleType().getLength()) {
3402
fractions -= (lastVeh->getVehicleType().getLength() - lastVeh->getPositionOnLane());
3403
}
3404
}
3405
releaseVehicles();
3406
return MIN2(1., (myBruttoVehicleLengthSum + fractions) / myLength);
3407
}
3408
3409
3410
double
3411
MSLane::getNettoOccupancy() const {
3412
getVehiclesSecure();
3413
double fractions = getFractionalVehicleLength(false);
3414
if (myVehicles.size() != 0) {
3415
MSVehicle* lastVeh = myVehicles.front();
3416
if (lastVeh->getPositionOnLane() < lastVeh->getVehicleType().getLength()) {
3417
fractions -= (lastVeh->getVehicleType().getLength() - lastVeh->getPositionOnLane());
3418
}
3419
}
3420
releaseVehicles();
3421
return (myNettoVehicleLengthSum + fractions) / myLength;
3422
}
3423
3424
3425
double
3426
MSLane::getWaitingSeconds() const {
3427
if (myVehicles.size() == 0) {
3428
return 0;
3429
}
3430
double wtime = 0;
3431
for (VehCont::const_iterator i = myVehicles.begin(); i != myVehicles.end(); ++i) {
3432
wtime += (*i)->getWaitingSeconds();
3433
}
3434
return wtime;
3435
}
3436
3437
3438
double
3439
MSLane::getMeanSpeed() const {
3440
if (myVehicles.size() == 0) {
3441
return myMaxSpeed;
3442
}
3443
double v = 0;
3444
int numVehs = 0;
3445
for (const MSVehicle* const veh : getVehiclesSecure()) {
3446
if (!veh->isStopped() || !myEdge->hasLaneChanger()) {
3447
v += veh->getSpeed();
3448
numVehs++;
3449
}
3450
}
3451
releaseVehicles();
3452
if (numVehs == 0) {
3453
return myMaxSpeed;
3454
}
3455
return v / numVehs;
3456
}
3457
3458
3459
double
3460
MSLane::getMeanSpeedBike() const {
3461
// @note: redundant code with getMeanSpeed to avoid extra checks in a function that is called very often
3462
if (myVehicles.size() == 0) {
3463
return myMaxSpeed;
3464
}
3465
double v = 0;
3466
int numBikes = 0;
3467
for (MSVehicle* veh : getVehiclesSecure()) {
3468
if (veh->getVClass() == SVC_BICYCLE) {
3469
v += veh->getSpeed();
3470
numBikes++;
3471
}
3472
}
3473
double ret;
3474
if (numBikes > 0) {
3475
ret = v / (double) myVehicles.size();
3476
} else {
3477
ret = myMaxSpeed;
3478
}
3479
releaseVehicles();
3480
return ret;
3481
}
3482
3483
3484
double
3485
MSLane::getHarmonoise_NoiseEmissions() const {
3486
double ret = 0;
3487
const MSLane::VehCont& vehs = getVehiclesSecure();
3488
if (vehs.size() == 0) {
3489
releaseVehicles();
3490
return 0;
3491
}
3492
for (MSLane::VehCont::const_iterator i = vehs.begin(); i != vehs.end(); ++i) {
3493
double sv = (*i)->getHarmonoise_NoiseEmissions();
3494
ret += (double) pow(10., (sv / 10.));
3495
}
3496
releaseVehicles();
3497
return HelpersHarmonoise::sum(ret);
3498
}
3499
3500
3501
int
3502
MSLane::vehicle_position_sorter::operator()(MSVehicle* v1, MSVehicle* v2) const {
3503
const double pos1 = v1->getBackPositionOnLane(myLane);
3504
const double pos2 = v2->getBackPositionOnLane(myLane);
3505
if (pos1 != pos2) {
3506
return pos1 > pos2;
3507
} else {
3508
return v1->getNumericalID() > v2->getNumericalID();
3509
}
3510
}
3511
3512
3513
int
3514
MSLane::vehicle_natural_position_sorter::operator()(MSVehicle* v1, MSVehicle* v2) const {
3515
const double pos1 = v1->getBackPositionOnLane(myLane);
3516
const double pos2 = v2->getBackPositionOnLane(myLane);
3517
if (pos1 != pos2) {
3518
return pos1 < pos2;
3519
} else {
3520
return v1->getLateralPositionOnLane() < v2->getLateralPositionOnLane();
3521
}
3522
}
3523
3524
3525
MSLane::by_connections_to_sorter::by_connections_to_sorter(const MSEdge* const e) :
3526
myEdge(e),
3527
myLaneDir(e->getLanes()[0]->getShape().angleAt2D(0)) {
3528
}
3529
3530
3531
int
3532
MSLane::by_connections_to_sorter::operator()(const MSEdge* const e1, const MSEdge* const e2) const {
3533
// std::cout << "\nby_connections_to_sorter()";
3534
3535
const std::vector<MSLane*>* ae1 = e1->allowedLanes(*myEdge);
3536
const std::vector<MSLane*>* ae2 = e2->allowedLanes(*myEdge);
3537
double s1 = 0;
3538
if (ae1 != nullptr && ae1->size() != 0) {
3539
// std::cout << "\nsize 1 = " << ae1->size()
3540
// << " anglediff 1 = " << fabs(GeomHelper::angleDiff((*ae1)[0]->getShape().angleAt2D(0), myLaneDir)) / M_PI / 2.
3541
// << "\nallowed lanes: ";
3542
// for (std::vector<MSLane*>::const_iterator j = ae1->begin(); j != ae1->end(); ++j){
3543
// std::cout << "\n" << (*j)->getID();
3544
// }
3545
s1 = (double) ae1->size() + fabs(GeomHelper::angleDiff((*ae1)[0]->getShape().angleAt2D(0), myLaneDir)) / M_PI / 2.;
3546
}
3547
double s2 = 0;
3548
if (ae2 != nullptr && ae2->size() != 0) {
3549
// std::cout << "\nsize 2 = " << ae2->size()
3550
// << " anglediff 2 = " << fabs(GeomHelper::angleDiff((*ae2)[0]->getShape().angleAt2D(0), myLaneDir)) / M_PI / 2.
3551
// << "\nallowed lanes: ";
3552
// for (std::vector<MSLane*>::const_iterator j = ae2->begin(); j != ae2->end(); ++j){
3553
// std::cout << "\n" << (*j)->getID();
3554
// }
3555
s2 = (double) ae2->size() + fabs(GeomHelper::angleDiff((*ae2)[0]->getShape().angleAt2D(0), myLaneDir)) / M_PI / 2.;
3556
}
3557
3558
// std::cout << "\ne1 = " << e1->getID() << " e2 = " << e2->getID()
3559
// << "\ns1 = " << s1 << " s2 = " << s2
3560
// << std::endl;
3561
3562
return s1 < s2;
3563
}
3564
3565
3566
MSLane::incoming_lane_priority_sorter::incoming_lane_priority_sorter(const MSLane* const targetLane) :
3567
myLane(targetLane),
3568
myLaneDir(targetLane->getShape().angleAt2D(0)) {}
3569
3570
int
3571
MSLane::incoming_lane_priority_sorter::operator()(const IncomingLaneInfo& laneInfo1, const IncomingLaneInfo& laneInfo2) const {
3572
const MSLane* noninternal1 = laneInfo1.lane;
3573
while (noninternal1->isInternal()) {
3574
assert(noninternal1->getIncomingLanes().size() == 1);
3575
noninternal1 = noninternal1->getIncomingLanes()[0].lane;
3576
}
3577
MSLane* noninternal2 = laneInfo2.lane;
3578
while (noninternal2->isInternal()) {
3579
assert(noninternal2->getIncomingLanes().size() == 1);
3580
noninternal2 = noninternal2->getIncomingLanes()[0].lane;
3581
}
3582
3583
const MSLink* link1 = noninternal1->getLinkTo(myLane);
3584
const MSLink* link2 = noninternal2->getLinkTo(myLane);
3585
3586
#ifdef DEBUG_LANE_SORTER
3587
std::cout << "\nincoming_lane_priority sorter()\n"
3588
<< "noninternal predecessor for lane '" << laneInfo1.lane->getID()
3589
<< "': '" << noninternal1->getID() << "'\n"
3590
<< "noninternal predecessor for lane '" << laneInfo2.lane->getID()
3591
<< "': '" << noninternal2->getID() << "'\n";
3592
#endif
3593
3594
assert(laneInfo1.lane->isInternal() || link1 == laneInfo1.viaLink);
3595
assert(link1 != 0);
3596
assert(link2 != 0);
3597
3598
// check priority between links
3599
bool priorized1 = true;
3600
bool priorized2 = true;
3601
3602
#ifdef DEBUG_LANE_SORTER
3603
std::cout << "FoeLinks of '" << noninternal1->getID() << "'" << std::endl;
3604
#endif
3605
for (const MSLink* const foeLink : link1->getFoeLinks()) {
3606
#ifdef DEBUG_LANE_SORTER
3607
std::cout << foeLink->getLaneBefore()->getID() << std::endl;
3608
#endif
3609
if (foeLink == link2) {
3610
priorized1 = false;
3611
break;
3612
}
3613
}
3614
3615
#ifdef DEBUG_LANE_SORTER
3616
std::cout << "FoeLinks of '" << noninternal2->getID() << "'" << std::endl;
3617
#endif
3618
for (const MSLink* const foeLink : link2->getFoeLinks()) {
3619
#ifdef DEBUG_LANE_SORTER
3620
std::cout << foeLink->getLaneBefore()->getID() << std::endl;
3621
#endif
3622
// either link1 is priorized, or it should not appear in link2's foes
3623
if (foeLink == link1) {
3624
priorized2 = false;
3625
break;
3626
}
3627
}
3628
// if one link is subordinate, the other must be priorized (except for
3629
// traffic lights where mutual response is permitted to handle stuck-on-red
3630
// situation)
3631
if (priorized1 != priorized2) {
3632
return priorized1;
3633
}
3634
3635
// both are priorized, compare angle difference
3636
double d1 = fabs(GeomHelper::angleDiff(noninternal1->getShape().angleAt2D(0), myLaneDir));
3637
double d2 = fabs(GeomHelper::angleDiff(noninternal2->getShape().angleAt2D(0), myLaneDir));
3638
3639
return d2 > d1;
3640
}
3641
3642
3643
3644
MSLane::outgoing_lane_priority_sorter::outgoing_lane_priority_sorter(const MSLane* const sourceLane) :
3645
myLaneDir(sourceLane->getShape().angleAt2D(0)) {}
3646
3647
int
3648
MSLane::outgoing_lane_priority_sorter::operator()(const MSLink* link1, const MSLink* link2) const {
3649
const MSLane* target1 = link1->getLane();
3650
const MSLane* target2 = link2->getLane();
3651
if (target2 == nullptr) {
3652
return true;
3653
}
3654
if (target1 == nullptr) {
3655
return false;
3656
}
3657
3658
#ifdef DEBUG_LANE_SORTER
3659
std::cout << "\noutgoing_lane_priority sorter()\n"
3660
<< "noninternal successors for lane '" << myLane->getID()
3661
<< "': '" << target1->getID() << "' and "
3662
<< "'" << target2->getID() << "'\n";
3663
#endif
3664
3665
// priority of targets
3666
int priority1 = target1->getEdge().getPriority();
3667
int priority2 = target2->getEdge().getPriority();
3668
3669
if (priority1 != priority2) {
3670
return priority1 > priority2;
3671
}
3672
3673
// if priority of targets coincides, use angle difference
3674
3675
// both are priorized, compare angle difference
3676
double d1 = fabs(GeomHelper::angleDiff(target1->getShape().angleAt2D(0), myLaneDir));
3677
double d2 = fabs(GeomHelper::angleDiff(target2->getShape().angleAt2D(0), myLaneDir));
3678
3679
return d2 > d1;
3680
}
3681
3682
void
3683
MSLane::addParking(MSBaseVehicle* veh) {
3684
myParkingVehicles.insert(veh);
3685
}
3686
3687
3688
void
3689
MSLane::removeParking(MSBaseVehicle* veh) {
3690
myParkingVehicles.erase(veh);
3691
}
3692
3693
bool
3694
MSLane::hasApproaching() const {
3695
for (const MSLink* link : myLinks) {
3696
if (link->getApproaching().size() > 0) {
3697
return true;
3698
}
3699
}
3700
return false;
3701
}
3702
3703
void
3704
MSLane::saveState(OutputDevice& out) {
3705
const bool toRailJunction = myLinks.size() > 0 && (
3706
myEdge->getToJunction()->getType() == SumoXMLNodeType::RAIL_SIGNAL
3707
|| myEdge->getToJunction()->getType() == SumoXMLNodeType::RAIL_CROSSING);
3708
const bool hasVehicles = myVehicles.size() > 0;
3709
if (hasVehicles || (toRailJunction && hasApproaching())) {
3710
out.openTag(SUMO_TAG_LANE);
3711
out.writeAttr(SUMO_ATTR_ID, getID());
3712
if (hasVehicles) {
3713
out.openTag(SUMO_TAG_VIEWSETTINGS_VEHICLES);
3714
out.writeAttr(SUMO_ATTR_VALUE, myVehicles);
3715
out.closeTag();
3716
}
3717
if (toRailJunction) {
3718
for (const MSLink* link : myLinks) {
3719
if (link->getApproaching().size() > 0) {
3720
out.openTag(SUMO_TAG_LINK);
3721
out.writeAttr(SUMO_ATTR_TO, link->getViaLaneOrLane()->getID());
3722
for (auto item : link->getApproaching()) {
3723
out.openTag(SUMO_TAG_APPROACHING);
3724
out.writeAttr(SUMO_ATTR_ID, item.first->getID());
3725
out.writeAttr(SUMO_ATTR_ARRIVALTIME, item.second.arrivalTime);
3726
out.writeAttr(SUMO_ATTR_ARRIVALSPEED, item.second.arrivalSpeed);
3727
out.writeAttr(SUMO_ATTR_DEPARTSPEED, item.second.leaveSpeed);
3728
out.writeAttr(SUMO_ATTR_REQUEST, item.second.willPass);
3729
out.writeAttr(SUMO_ATTR_ARRIVALSPEEDBRAKING, item.second.arrivalSpeedBraking);
3730
out.writeAttr(SUMO_ATTR_WAITINGTIME, item.second.waitingTime);
3731
out.writeAttr(SUMO_ATTR_DISTANCE, item.second.dist);
3732
if (item.second.latOffset != 0) {
3733
out.writeAttr(SUMO_ATTR_POSITION_LAT, item.second.latOffset);
3734
}
3735
out.closeTag();
3736
}
3737
out.closeTag();
3738
}
3739
}
3740
}
3741
out.closeTag();
3742
}
3743
}
3744
3745
void
3746
MSLane::clearState() {
3747
myVehicles.clear();
3748
myParkingVehicles.clear();
3749
myPartialVehicles.clear();
3750
myManeuverReservations.clear();
3751
myBruttoVehicleLengthSum = 0;
3752
myNettoVehicleLengthSum = 0;
3753
myBruttoVehicleLengthSumToRemove = 0;
3754
myNettoVehicleLengthSumToRemove = 0;
3755
myLeaderInfoTime = SUMOTime_MIN;
3756
myFollowerInfoTime = SUMOTime_MIN;
3757
for (MSLink* link : myLinks) {
3758
link->clearState();
3759
}
3760
}
3761
3762
void
3763
MSLane::loadState(const std::vector<SUMOVehicle*>& vehs) {
3764
for (SUMOVehicle* veh : vehs) {
3765
MSVehicle* v = dynamic_cast<MSVehicle*>(veh);
3766
v->updateBestLanes(false, this);
3767
// incorporateVehicle resets the lastActionTime (which has just been loaded from state) so we must restore it
3768
const SUMOTime lastActionTime = v->getLastActionTime();
3769
incorporateVehicle(v, v->getPositionOnLane(), v->getSpeed(), v->getLateralPositionOnLane(), myVehicles.end(),
3770
MSMoveReminder::NOTIFICATION_LOAD_STATE);
3771
v->resetActionOffset(lastActionTime - MSNet::getInstance()->getCurrentTimeStep());
3772
v->processNextStop(v->getSpeed());
3773
}
3774
}
3775
3776
3777
double
3778
MSLane::getVehicleStopOffset(const MSVehicle* veh) const {
3779
if (!myLaneStopOffset.isDefined()) {
3780
return 0;
3781
}
3782
if ((myLaneStopOffset.getPermissions() & veh->getVClass()) != 0) {
3783
return myLaneStopOffset.getOffset();
3784
} else {
3785
return 0;
3786
}
3787
}
3788
3789
3790
const StopOffset&
3791
MSLane::getLaneStopOffsets() const {
3792
return myLaneStopOffset;
3793
}
3794
3795
3796
void
3797
MSLane::setLaneStopOffset(const StopOffset& stopOffset) {
3798
myLaneStopOffset = stopOffset;
3799
}
3800
3801
3802
MSLeaderDistanceInfo
3803
MSLane::getFollowersOnConsecutive(const MSVehicle* ego, double backOffset,
3804
bool allSublanes, double searchDist, MinorLinkMode mLinkMode) const {
3805
assert(ego != 0);
3806
// get the follower vehicle on the lane to change to
3807
const double egoPos = backOffset + ego->getVehicleType().getLength();
3808
const double egoLatDist = ego->getLane()->getRightSideOnEdge() - getRightSideOnEdge();
3809
const bool getOppositeLeaders = ((ego->getLaneChangeModel().isOpposite() && ego->getLane() == this)
3810
|| (!ego->getLaneChangeModel().isOpposite() && &ego->getLane()->getEdge() != &getEdge()));
3811
#ifdef DEBUG_CONTEXT
3812
if (DEBUG_COND2(ego)) {
3813
std::cout << SIMTIME << " getFollowers lane=" << getID() << " ego=" << ego->getID()
3814
<< " backOffset=" << backOffset << " pos=" << egoPos
3815
<< " allSub=" << allSublanes << " searchDist=" << searchDist << " ignoreMinor=" << mLinkMode
3816
<< " egoLatDist=" << egoLatDist
3817
<< " getOppositeLeaders=" << getOppositeLeaders
3818
<< "\n";
3819
}
3820
#endif
3821
MSCriticalFollowerDistanceInfo result(myWidth, allSublanes ? nullptr : ego, allSublanes ? 0 : egoLatDist, getOppositeLeaders);
3822
if (MSGlobals::gLateralResolution > 0 && egoLatDist == 0) {
3823
// check whether ego is outside lane bounds far enough so that another vehicle might
3824
// be between itself and the first "actual" sublane
3825
// shift the offset so that we "see" this vehicle
3826
if (ego->getLeftSideOnLane() < -MSGlobals::gLateralResolution) {
3827
result.setSublaneOffset(int(-ego->getLeftSideOnLane() / MSGlobals::gLateralResolution));
3828
} else if (ego->getRightSideOnLane() > getWidth() + MSGlobals::gLateralResolution) {
3829
result.setSublaneOffset(-int((ego->getRightSideOnLane() - getWidth()) / MSGlobals::gLateralResolution));
3830
}
3831
#ifdef DEBUG_CONTEXT
3832
if (DEBUG_COND2(ego)) {
3833
std::cout << SIMTIME << " getFollowers lane=" << getID() << " ego=" << ego->getID()
3834
<< " egoPosLat=" << ego->getLateralPositionOnLane()
3835
<< " egoLatDist=" << ego->getLane()->getRightSideOnEdge() - getRightSideOnEdge()
3836
<< " extraOffset=" << result.getSublaneOffset()
3837
<< "\n";
3838
}
3839
#endif
3840
}
3841
/// XXX iterate in reverse and abort when there are no more freeSublanes
3842
for (AnyVehicleIterator last = anyVehiclesBegin(); last != anyVehiclesEnd(); ++last) {
3843
const MSVehicle* veh = *last;
3844
#ifdef DEBUG_CONTEXT
3845
if (DEBUG_COND2(ego)) {
3846
std::cout << " veh=" << veh->getID() << " lane=" << veh->getLane()->getID() << " pos=" << veh->getPositionOnLane(this) << "\n";
3847
}
3848
#endif
3849
if (veh != ego && veh->getPositionOnLane(this) < egoPos) {
3850
//const double latOffset = veh->getLane()->getRightSideOnEdge() - getRightSideOnEdge();
3851
const double latOffset = veh->getLatOffset(this);
3852
double dist = backOffset - veh->getPositionOnLane(this) - veh->getVehicleType().getMinGap();
3853
if (veh->isBidiOn(this)) {
3854
dist -= veh->getLength();
3855
}
3856
result.addFollower(veh, ego, dist, latOffset);
3857
#ifdef DEBUG_CONTEXT
3858
if (DEBUG_COND2(ego)) {
3859
std::cout << " (1) added veh=" << veh->getID() << " latOffset=" << latOffset << " result=" << result.toString() << "\n";
3860
}
3861
#endif
3862
}
3863
}
3864
#ifdef DEBUG_CONTEXT
3865
if (DEBUG_COND2(ego)) {
3866
std::cout << " result.numFreeSublanes=" << result.numFreeSublanes() << "\n";
3867
}
3868
#endif
3869
if (result.numFreeSublanes() > 0) {
3870
// do a tree search among all follower lanes and check for the most
3871
// important vehicle (the one requiring the largest reargap)
3872
// to get a safe bound on the necessary search depth, we need to consider the maximum speed and minimum
3873
// deceleration of potential follower vehicles
3874
if (searchDist == -1) {
3875
searchDist = getMaximumBrakeDist() - backOffset;
3876
#ifdef DEBUG_CONTEXT
3877
if (DEBUG_COND2(ego)) {
3878
std::cout << " computed searchDist=" << searchDist << "\n";
3879
}
3880
#endif
3881
}
3882
std::set<const MSEdge*> egoFurther;
3883
for (MSLane* further : ego->getFurtherLanes()) {
3884
egoFurther.insert(&further->getEdge());
3885
}
3886
if (ego->getPositionOnLane() < ego->getVehicleType().getLength() && egoFurther.size() == 0
3887
&& ego->getLane()->getLogicalPredecessorLane() != nullptr) {
3888
// on insertion
3889
egoFurther.insert(&ego->getLane()->getLogicalPredecessorLane()->getEdge());
3890
}
3891
3892
// avoid loops
3893
std::set<const MSLane*> visited(myEdge->getLanes().begin(), myEdge->getLanes().end());
3894
if (myEdge->getBidiEdge() != nullptr) {
3895
visited.insert(myEdge->getBidiEdge()->getLanes().begin(), myEdge->getBidiEdge()->getLanes().end());
3896
}
3897
std::vector<MSLane::IncomingLaneInfo> newFound;
3898
std::vector<MSLane::IncomingLaneInfo> toExamine = myIncomingLanes;
3899
while (toExamine.size() != 0) {
3900
for (std::vector<MSLane::IncomingLaneInfo>::iterator it = toExamine.begin(); it != toExamine.end(); ++it) {
3901
MSLane* next = (*it).lane;
3902
searchDist = MAX2(searchDist, next->getMaximumBrakeDist() - backOffset);
3903
MSLeaderInfo first = next->getFirstVehicleInformation(nullptr, 0, false, std::numeric_limits<double>::max(), false);
3904
MSLeaderInfo firstFront = next->getFirstVehicleInformation(nullptr, 0, true);
3905
#ifdef DEBUG_CONTEXT
3906
if (DEBUG_COND2(ego)) {
3907
std::cout << " next=" << next->getID() << " seen=" << (*it).length << " first=" << first.toString() << " firstFront=" << firstFront.toString() << " backOffset=" << backOffset << "\n";
3908
gDebugFlag1 = true; // for calling getLeaderInfo
3909
}
3910
#endif
3911
if (backOffset + (*it).length - next->getLength() < 0
3912
&& egoFurther.count(&next->getEdge()) != 0
3913
) {
3914
// check for junction foes that would interfere with lane changing
3915
// @note: we are passing the back of ego as its front position so
3916
// we need to add this back to the returned gap
3917
const MSLink::LinkLeaders linkLeaders = (*it).viaLink->getLeaderInfo(ego, -backOffset);
3918
for (const auto& ll : linkLeaders) {
3919
if (ll.vehAndGap.first != nullptr) {
3920
const bool bidiFoe = (*it).viaLink->getLane() == ll.vehAndGap.first->getLane()->getNormalPredecessorLane()->getBidiLane();
3921
const bool egoIsLeader = !bidiFoe && ll.vehAndGap.first->isLeader((*it).viaLink, ego, ll.vehAndGap.second);
3922
// if ego is leader the returned gap still assumes that ego follows the leader
3923
// if the foe vehicle follows ego we need to deduce that gap
3924
const double gap = (egoIsLeader
3925
? -ll.vehAndGap.second - ll.vehAndGap.first->getVehicleType().getLengthWithGap() - ego->getVehicleType().getMinGap()
3926
: ll.vehAndGap.second + ego->getVehicleType().getLength());
3927
result.addFollower(ll.vehAndGap.first, ego, gap);
3928
#ifdef DEBUG_CONTEXT
3929
if (DEBUG_COND2(ego)) {
3930
std::cout << SIMTIME << " ego=" << ego->getID() << " link=" << (*it).viaLink->getViaLaneOrLane()->getID()
3931
<< " (3) added veh=" << Named::getIDSecure(ll.vehAndGap.first)
3932
<< " gap=" << ll.vehAndGap.second << " dtC=" << ll.distToCrossing
3933
<< " bidiFoe=" << bidiFoe
3934
<< " egoIsLeader=" << egoIsLeader << " gap2=" << gap
3935
<< "\n";
3936
}
3937
#endif
3938
}
3939
}
3940
}
3941
#ifdef DEBUG_CONTEXT
3942
if (DEBUG_COND2(ego)) {
3943
gDebugFlag1 = false;
3944
}
3945
#endif
3946
3947
for (int i = 0; i < first.numSublanes(); ++i) {
3948
const MSVehicle* v = first[i] == ego ? firstFront[i] : first[i];
3949
double agap = 0;
3950
3951
if (v != nullptr && v != ego) {
3952
if (!v->isFrontOnLane(next)) {
3953
// the front of v is already on divergent trajectory from the ego vehicle
3954
// for which this method is called (in the context of MSLaneChanger).
3955
// Therefore, technically v is not a follower but only an obstruction and
3956
// the gap is not between the front of v and the back of ego
3957
// but rather between the flank of v and the back of ego.
3958
agap = (*it).length - next->getLength() + backOffset;
3959
if (MSGlobals::gUsingInternalLanes) {
3960
// ego should have left the intersection still occupied by v
3961
agap -= v->getVehicleType().getMinGap();
3962
}
3963
#ifdef DEBUG_CONTEXT
3964
if (DEBUG_COND2(ego)) {
3965
std::cout << " agap1=" << agap << "\n";
3966
}
3967
#endif
3968
const bool differentEdge = &v->getLane()->getEdge() != &ego->getLane()->getEdge();
3969
if (agap > 0 && differentEdge) {
3970
// Only if ego overlaps we treat v as if it were a real follower
3971
// Otherwise we ignore it and look for another follower
3972
if (!getOppositeLeaders) {
3973
// even if the vehicle is not a real
3974
// follower, it still forms a real
3975
// obstruction in opposite direction driving
3976
v = firstFront[i];
3977
if (v != nullptr && v != ego) {
3978
agap = (*it).length - v->getPositionOnLane() + backOffset - v->getVehicleType().getMinGap();
3979
} else {
3980
v = nullptr;
3981
}
3982
}
3983
} else if (differentEdge && result.hasVehicle(v)) {
3984
// ignore this vehicle as it was already seen on another lane
3985
agap = 0;
3986
}
3987
} else {
3988
if (next->getBidiLane() != nullptr && v->isBidiOn(next)) {
3989
agap = v->getPositionOnLane() + backOffset - v->getVehicleType().getLengthWithGap();
3990
} else {
3991
agap = (*it).length - v->getPositionOnLane() + backOffset - v->getVehicleType().getMinGap();
3992
}
3993
if (!(*it).viaLink->havePriority() && egoFurther.count(&(*it).lane->getEdge()) == 0
3994
&& ego->isOnRoad() // during insertion, this can lead to collisions because ego's further lanes are not set (see #3053)
3995
&& !ego->getLaneChangeModel().isOpposite()
3996
&& v->getSpeed() < SUMO_const_haltingSpeed
3997
) {
3998
// if v is stopped on a minor side road it should not block lane changing
3999
agap = MAX2(agap, 0.0);
4000
}
4001
}
4002
result.addFollower(v, ego, agap, 0, i);
4003
#ifdef DEBUG_CONTEXT
4004
if (DEBUG_COND2(ego)) {
4005
std::cout << " (2) added veh=" << Named::getIDSecure(v) << " agap=" << agap << " next=" << next->getID() << " result=" << result.toString() << "\n";
4006
}
4007
#endif
4008
}
4009
}
4010
if ((*it).length < searchDist) {
4011
const std::vector<MSLane::IncomingLaneInfo>& followers = next->getIncomingLanes();
4012
for (std::vector<MSLane::IncomingLaneInfo>::const_iterator j = followers.begin(); j != followers.end(); ++j) {
4013
if (visited.find((*j).lane) == visited.end() && (((*j).viaLink->havePriority() && !(*j).viaLink->isTurnaround())
4014
|| mLinkMode == MinorLinkMode::FOLLOW_ALWAYS
4015
|| (mLinkMode == MinorLinkMode::FOLLOW_ONCOMING && (*j).viaLink->getDirection() == LinkDirection::STRAIGHT))) {
4016
visited.insert((*j).lane);
4017
MSLane::IncomingLaneInfo ili;
4018
ili.lane = (*j).lane;
4019
ili.length = (*j).length + (*it).length;
4020
ili.viaLink = (*j).viaLink;
4021
newFound.push_back(ili);
4022
}
4023
}
4024
}
4025
}
4026
toExamine.clear();
4027
swap(newFound, toExamine);
4028
}
4029
//return result;
4030
4031
}
4032
return result;
4033
}
4034
4035
4036
void
4037
MSLane::getLeadersOnConsecutive(double dist, double seen, double speed, const MSVehicle* ego,
4038
const std::vector<MSLane*>& bestLaneConts, MSLeaderDistanceInfo& result,
4039
bool oppositeDirection) const {
4040
if (seen > dist && !(isInternal() && MSGlobals::gComputeLC)) {
4041
return;
4042
}
4043
// check partial vehicles (they might be on a different route and thus not
4044
// found when iterating along bestLaneConts)
4045
for (VehCont::const_iterator it = myPartialVehicles.begin(); it != myPartialVehicles.end(); ++it) {
4046
MSVehicle* veh = *it;
4047
if (!veh->isFrontOnLane(this)) {
4048
result.addLeader(veh, seen, veh->getLatOffset(this));
4049
} else {
4050
break;
4051
}
4052
}
4053
#ifdef DEBUG_CONTEXT
4054
if (DEBUG_COND2(ego)) {
4055
gDebugFlag1 = true;
4056
}
4057
#endif
4058
const MSLane* nextLane = this;
4059
int view = 1;
4060
// loop over following lanes
4061
while ((seen < dist || nextLane->isInternal()) && result.numFreeSublanes() > 0) {
4062
// get the next link used
4063
bool nextInternal = false;
4064
if (oppositeDirection) {
4065
if (view >= (int)bestLaneConts.size()) {
4066
break;
4067
}
4068
nextLane = bestLaneConts[view];
4069
} else {
4070
std::vector<MSLink*>::const_iterator link = succLinkSec(*ego, view, *nextLane, bestLaneConts);
4071
if (nextLane->isLinkEnd(link)) {
4072
break;
4073
}
4074
// check for link leaders
4075
const MSLink::LinkLeaders linkLeaders = (*link)->getLeaderInfo(ego, seen);
4076
if (linkLeaders.size() > 0) {
4077
const MSLink::LinkLeader ll = linkLeaders[0];
4078
MSVehicle* veh = ll.vehAndGap.first;
4079
// in the context of lane changing all junction leader candidates must be respected
4080
if (veh != 0 && (ego->isLeader(*link, veh, ll.vehAndGap.second)
4081
|| (MSGlobals::gComputeLC
4082
&& veh->getPosition().distanceTo2D(ego->getPosition()) - veh->getVehicleType().getMinGap() - ego->getVehicleType().getLength()
4083
< veh->getCarFollowModel().brakeGap(veh->getSpeed())))) {
4084
#ifdef DEBUG_CONTEXT
4085
if (DEBUG_COND2(ego)) {
4086
std::cout << " linkleader=" << veh->getID() << " gap=" << ll.vehAndGap.second << " leaderOffset=" << ll.latOffset << " flags=" << ll.llFlags << "\n";
4087
}
4088
#endif
4089
if (ll.sameTarget() || ll.sameSource()) {
4090
result.addLeader(veh, ll.vehAndGap.second, ll.latOffset);
4091
} else {
4092
// add link leader to all sublanes and return
4093
for (int i = 0; i < result.numSublanes(); ++i) {
4094
result.addLeader(veh, ll.vehAndGap.second, 0, i);
4095
}
4096
}
4097
#ifdef DEBUG_CONTEXT
4098
gDebugFlag1 = false;
4099
#endif
4100
return;
4101
} // XXX else, deal with pedestrians
4102
}
4103
nextInternal = (*link)->getViaLane() != nullptr;
4104
nextLane = (*link)->getViaLaneOrLane();
4105
if (nextLane == nullptr) {
4106
break;
4107
}
4108
}
4109
4110
MSLeaderInfo leaders = nextLane->getLastVehicleInformation(nullptr, 0, 0, false);
4111
#ifdef DEBUG_CONTEXT
4112
if (DEBUG_COND2(ego)) {
4113
std::cout << SIMTIME << " getLeadersOnConsecutive lane=" << getID() << " nextLane=" << nextLane->getID() << " leaders=" << leaders.toString() << "\n";
4114
}
4115
#endif
4116
// @todo check alignment issues if the lane width changes
4117
const int iMax = MIN2(leaders.numSublanes(), result.numSublanes());
4118
for (int i = 0; i < iMax; ++i) {
4119
const MSVehicle* veh = leaders[i];
4120
if (veh != nullptr) {
4121
#ifdef DEBUG_CONTEXT
4122
if (DEBUG_COND2(ego)) std::cout << " lead=" << veh->getID()
4123
<< " seen=" << seen
4124
<< " minGap=" << ego->getVehicleType().getMinGap()
4125
<< " backPos=" << veh->getBackPositionOnLane(nextLane)
4126
<< " gap=" << seen - ego->getVehicleType().getMinGap() + veh->getBackPositionOnLane(nextLane)
4127
<< "\n";
4128
#endif
4129
result.addLeader(veh, seen - ego->getVehicleType().getMinGap() + veh->getBackPositionOnLane(nextLane), 0, i);
4130
}
4131
}
4132
4133
if (nextLane->getVehicleMaxSpeed(ego) < speed) {
4134
dist = ego->getCarFollowModel().brakeGap(nextLane->getVehicleMaxSpeed(ego));
4135
}
4136
seen += nextLane->getLength();
4137
if (!nextInternal) {
4138
view++;
4139
}
4140
}
4141
#ifdef DEBUG_CONTEXT
4142
gDebugFlag1 = false;
4143
#endif
4144
}
4145
4146
4147
void
4148
MSLane::addLeaders(const MSVehicle* vehicle, double vehPos, MSLeaderDistanceInfo& result, bool opposite) {
4149
// if there are vehicles on the target lane with the same position as ego,
4150
// they may not have been added to 'ahead' yet
4151
#ifdef DEBUG_SURROUNDING
4152
if (DEBUG_COND || DEBUG_COND2(vehicle)) {
4153
std::cout << " addLeaders lane=" << getID() << " veh=" << vehicle->getID() << " vehPos=" << vehPos << " opposite=" << opposite << "\n";
4154
}
4155
#endif
4156
const MSLeaderInfo& aheadSamePos = getLastVehicleInformation(nullptr, 0, vehPos, false);
4157
for (int i = 0; i < aheadSamePos.numSublanes(); ++i) {
4158
const MSVehicle* veh = aheadSamePos[i];
4159
if (veh != nullptr && veh != vehicle) {
4160
const double gap = veh->getBackPositionOnLane(this) - vehPos - vehicle->getVehicleType().getMinGap();
4161
#ifdef DEBUG_SURROUNDING
4162
if (DEBUG_COND || DEBUG_COND2(vehicle)) {
4163
std::cout << " further lead=" << veh->getID() << " leadBack=" << veh->getBackPositionOnLane(this) << " gap=" << gap << "\n";
4164
}
4165
#endif
4166
result.addLeader(veh, gap, 0, i);
4167
}
4168
}
4169
4170
if (result.numFreeSublanes() > 0) {
4171
double seen = vehicle->getLane()->getLength() - vehPos;
4172
double speed = vehicle->getSpeed();
4173
// leader vehicle could be link leader on the next junction
4174
double dist = MAX2(vehicle->getCarFollowModel().brakeGap(speed), 10.0) + vehicle->getVehicleType().getMinGap();
4175
if (getBidiLane() != nullptr) {
4176
dist = MAX2(dist, myMaxSpeed * 20);
4177
}
4178
// check for link leaders when on internal
4179
if (seen > dist && !(isInternal() && MSGlobals::gComputeLC)) {
4180
#ifdef DEBUG_SURROUNDING
4181
if (DEBUG_COND || DEBUG_COND2(vehicle)) {
4182
std::cout << " aborting forward search. dist=" << dist << " seen=" << seen << "\n";
4183
}
4184
#endif
4185
return;
4186
}
4187
#ifdef DEBUG_SURROUNDING
4188
if (DEBUG_COND || DEBUG_COND2(vehicle)) {
4189
std::cout << " add consecutive before=" << result.toString() << " seen=" << seen << " dist=" << dist;
4190
}
4191
#endif
4192
if (opposite) {
4193
const std::vector<MSLane*> bestLaneConts = vehicle->getUpstreamOppositeLanes();
4194
#ifdef DEBUG_SURROUNDING
4195
if (DEBUG_COND || DEBUG_COND2(vehicle)) {
4196
std::cout << " upstreamOpposite=" << toString(bestLaneConts);
4197
}
4198
#endif
4199
getLeadersOnConsecutive(dist, seen, speed, vehicle, bestLaneConts, result, opposite);
4200
} else {
4201
const std::vector<MSLane*>& bestLaneConts = vehicle->getBestLanesContinuation(this);
4202
getLeadersOnConsecutive(dist, seen, speed, vehicle, bestLaneConts, result);
4203
}
4204
#ifdef DEBUG_SURROUNDING
4205
if (DEBUG_COND || DEBUG_COND2(vehicle)) {
4206
std::cout << " after=" << result.toString() << "\n";
4207
}
4208
#endif
4209
}
4210
}
4211
4212
4213
MSVehicle*
4214
MSLane::getPartialBehind(const MSVehicle* ego) const {
4215
for (VehCont::const_reverse_iterator i = myPartialVehicles.rbegin(); i != myPartialVehicles.rend(); ++i) {
4216
MSVehicle* veh = *i;
4217
if (veh->isFrontOnLane(this)
4218
&& veh != ego
4219
&& veh->getPositionOnLane() <= ego->getPositionOnLane()) {
4220
#ifdef DEBUG_CONTEXT
4221
if (DEBUG_COND2(ego)) {
4222
std::cout << SIMTIME << " getPartialBehind lane=" << getID() << " ego=" << ego->getID() << " found=" << veh->getID() << "\n";
4223
}
4224
#endif
4225
return veh;
4226
}
4227
}
4228
#ifdef DEBUG_CONTEXT
4229
if (DEBUG_COND2(ego)) {
4230
std::cout << SIMTIME << " getPartialBehind lane=" << getID() << " ego=" << ego->getID() << " nothing found. partials=" << toString(myPartialVehicles) << "\n";
4231
}
4232
#endif
4233
return nullptr;
4234
}
4235
4236
MSLeaderInfo
4237
MSLane::getPartialBeyond() const {
4238
MSLeaderInfo result(myWidth);
4239
for (VehCont::const_iterator it = myPartialVehicles.begin(); it != myPartialVehicles.end(); ++it) {
4240
MSVehicle* veh = *it;
4241
if (!veh->isFrontOnLane(this)) {
4242
result.addLeader(veh, false, veh->getLatOffset(this));
4243
} else {
4244
break;
4245
}
4246
}
4247
return result;
4248
}
4249
4250
4251
std::set<MSVehicle*>
4252
MSLane::getSurroundingVehicles(double startPos, double downstreamDist, double upstreamDist, std::shared_ptr<LaneCoverageInfo> checkedLanes) const {
4253
assert(checkedLanes != nullptr);
4254
if (checkedLanes->find(this) != checkedLanes->end()) {
4255
#ifdef DEBUG_SURROUNDING
4256
std::cout << "Skipping previously scanned lane: " << getID() << std::endl;
4257
#endif
4258
return std::set<MSVehicle*>();
4259
} else {
4260
// Add this lane's coverage to the lane coverage info
4261
(*checkedLanes)[this] = std::make_pair(MAX2(0.0, startPos - upstreamDist), MIN2(startPos + downstreamDist, getLength()));
4262
}
4263
#ifdef DEBUG_SURROUNDING
4264
std::cout << "Scanning on lane " << myID << "(downstr. " << downstreamDist << ", upstr. " << upstreamDist << ", startPos " << startPos << "): " << std::endl;
4265
#endif
4266
std::set<MSVehicle*> foundVehicles = getVehiclesInRange(MAX2(0., startPos - upstreamDist), MIN2(myLength, startPos + downstreamDist));
4267
if (startPos < upstreamDist) {
4268
// scan incoming lanes
4269
for (const IncomingLaneInfo& incomingInfo : getIncomingLanes()) {
4270
MSLane* incoming = incomingInfo.lane;
4271
#ifdef DEBUG_SURROUNDING
4272
std::cout << "Checking on incoming: " << incoming->getID() << std::endl;
4273
if (checkedLanes->find(incoming) != checkedLanes->end()) {
4274
std::cout << "Skipping previous: " << incoming->getID() << std::endl;
4275
}
4276
#endif
4277
std::set<MSVehicle*> newVehs = incoming->getSurroundingVehicles(incoming->getLength(), 0.0, upstreamDist - startPos, checkedLanes);
4278
foundVehicles.insert(newVehs.begin(), newVehs.end());
4279
}
4280
}
4281
4282
if (getLength() < startPos + downstreamDist) {
4283
// scan successive lanes
4284
const std::vector<MSLink*>& lc = getLinkCont();
4285
for (MSLink* l : lc) {
4286
#ifdef DEBUG_SURROUNDING
4287
std::cout << "Checking on outgoing: " << l->getViaLaneOrLane()->getID() << std::endl;
4288
#endif
4289
std::set<MSVehicle*> newVehs = l->getViaLaneOrLane()->getSurroundingVehicles(0.0, downstreamDist - (myLength - startPos), upstreamDist, checkedLanes);
4290
foundVehicles.insert(newVehs.begin(), newVehs.end());
4291
}
4292
}
4293
#ifdef DEBUG_SURROUNDING
4294
std::cout << "On lane (2) " << myID << ": \nFound vehicles: " << std::endl;
4295
for (MSVehicle* v : foundVehicles) {
4296
std::cout << v->getID() << " pos = " << v->getPositionOnLane() << std::endl;
4297
}
4298
#endif
4299
return foundVehicles;
4300
}
4301
4302
4303
std::set<MSVehicle*>
4304
MSLane::getVehiclesInRange(const double a, const double b) const {
4305
std::set<MSVehicle*> res;
4306
const VehCont& vehs = getVehiclesSecure();
4307
4308
if (!vehs.empty()) {
4309
for (MSVehicle* const veh : vehs) {
4310
if (veh->getPositionOnLane() >= a) {
4311
if (veh->getBackPositionOnLane() > b) {
4312
break;
4313
}
4314
res.insert(veh);
4315
}
4316
}
4317
}
4318
releaseVehicles();
4319
return res;
4320
}
4321
4322
4323
std::vector<const MSJunction*>
4324
MSLane::getUpcomingJunctions(double pos, double range, const std::vector<MSLane*>& contLanes) const {
4325
// set of upcoming junctions and the corresponding conflict links
4326
std::vector<const MSJunction*> junctions;
4327
for (auto l : getUpcomingLinks(pos, range, contLanes)) {
4328
junctions.insert(junctions.end(), l->getJunction());
4329
}
4330
return junctions;
4331
}
4332
4333
4334
std::vector<const MSLink*>
4335
MSLane::getUpcomingLinks(double pos, double range, const std::vector<MSLane*>& contLanes) const {
4336
#ifdef DEBUG_SURROUNDING
4337
std::cout << "getUpcoming links on lane '" << getID() << "' with pos=" << pos
4338
<< " range=" << range << std::endl;
4339
#endif
4340
// set of upcoming junctions and the corresponding conflict links
4341
std::vector<const MSLink*> links;
4342
4343
// Currently scanned lane
4344
const MSLane* lane = this;
4345
4346
// continuation lanes for the vehicle
4347
std::vector<MSLane*>::const_iterator contLanesIt = contLanes.begin();
4348
// scanned distance so far
4349
double dist = 0.0;
4350
// link to be crossed by the vehicle
4351
const MSLink* link = nullptr;
4352
if (lane->isInternal()) {
4353
assert(*contLanesIt == nullptr); // is called with vehicle's bestLane structure
4354
link = lane->getEntryLink();
4355
links.insert(links.end(), link);
4356
dist += link->getInternalLengthsAfter();
4357
// next non-internal lane behind junction
4358
lane = link->getLane();
4359
pos = 0.0;
4360
assert(*(contLanesIt + 1) == lane);
4361
}
4362
while (++contLanesIt != contLanes.end()) {
4363
assert(!lane->isInternal());
4364
dist += lane->getLength() - pos;
4365
pos = 0.;
4366
#ifdef DEBUG_SURROUNDING
4367
std::cout << "Distance until end of lane '" << lane->getID() << "' is " << dist << "." << std::endl;
4368
#endif
4369
if (dist > range) {
4370
break;
4371
}
4372
link = lane->getLinkTo(*contLanesIt);
4373
if (link != nullptr) {
4374
links.insert(links.end(), link);
4375
}
4376
lane = *contLanesIt;
4377
}
4378
return links;
4379
}
4380
4381
4382
MSLane*
4383
MSLane::getOpposite() const {
4384
return myOpposite;
4385
}
4386
4387
4388
MSLane*
4389
MSLane::getParallelOpposite() const {
4390
return myEdge->getLanes().back()->getOpposite();
4391
}
4392
4393
4394
double
4395
MSLane::getOppositePos(double pos) const {
4396
return MAX2(0., myLength - pos);
4397
}
4398
4399
std::pair<MSVehicle* const, double>
4400
MSLane::getFollower(const MSVehicle* ego, double egoPos, double dist, MinorLinkMode mLinkMode) const {
4401
for (AnyVehicleIterator first = anyVehiclesUpstreamBegin(); first != anyVehiclesUpstreamEnd(); ++first) {
4402
// XXX refactor leaderInfo to use a const vehicle all the way through the call hierarchy
4403
MSVehicle* pred = (MSVehicle*)*first;
4404
#ifdef DEBUG_CONTEXT
4405
if (DEBUG_COND2(ego)) {
4406
std::cout << " getFollower lane=" << getID() << " egoPos=" << egoPos << " pred=" << pred->getID() << " predPos=" << pred->getPositionOnLane(this) << "\n";
4407
}
4408
#endif
4409
if (pred != ego && pred->getPositionOnLane(this) < egoPos) {
4410
return std::pair<MSVehicle* const, double>(pred, egoPos - pred->getPositionOnLane(this) - ego->getVehicleType().getLength() - pred->getVehicleType().getMinGap());
4411
}
4412
}
4413
const double backOffset = egoPos - ego->getVehicleType().getLength();
4414
if (dist > 0 && backOffset > dist) {
4415
return std::make_pair(nullptr, -1);
4416
}
4417
const MSLeaderDistanceInfo followers = getFollowersOnConsecutive(ego, backOffset, true, dist, mLinkMode);
4418
CLeaderDist result = followers.getClosest();
4419
return std::make_pair(const_cast<MSVehicle*>(result.first), result.second);
4420
}
4421
4422
std::pair<MSVehicle* const, double>
4423
MSLane::getOppositeLeader(const MSVehicle* ego, double dist, bool oppositeDir, MinorLinkMode mLinkMode) const {
4424
#ifdef DEBUG_OPPOSITE
4425
if (DEBUG_COND2(ego)) std::cout << SIMTIME << " getOppositeLeader lane=" << getID()
4426
<< " ego=" << ego->getID()
4427
<< " pos=" << ego->getPositionOnLane()
4428
<< " posOnOpposite=" << getOppositePos(ego->getPositionOnLane())
4429
<< " dist=" << dist
4430
<< " oppositeDir=" << oppositeDir
4431
<< "\n";
4432
#endif
4433
if (!oppositeDir) {
4434
return getLeader(ego, getOppositePos(ego->getPositionOnLane()), ego->getBestLanesContinuation(this));
4435
} else {
4436
const double egoLength = ego->getVehicleType().getLength();
4437
const double egoPos = ego->getLaneChangeModel().isOpposite() ? ego->getPositionOnLane() : getOppositePos(ego->getPositionOnLane());
4438
std::pair<MSVehicle* const, double> result = getFollower(ego, egoPos + egoLength, dist, mLinkMode);
4439
if (result.first != nullptr) {
4440
result.second -= ego->getVehicleType().getMinGap();
4441
if (result.first->getLaneChangeModel().isOpposite()) {
4442
result.second -= result.first->getVehicleType().getLength();
4443
}
4444
}
4445
return result;
4446
}
4447
}
4448
4449
4450
std::pair<MSVehicle* const, double>
4451
MSLane::getOppositeFollower(const MSVehicle* ego) const {
4452
#ifdef DEBUG_OPPOSITE
4453
if (DEBUG_COND2(ego)) std::cout << SIMTIME << " getOppositeFollower lane=" << getID()
4454
<< " ego=" << ego->getID()
4455
<< " backPos=" << ego->getBackPositionOnLane()
4456
<< " posOnOpposite=" << getOppositePos(ego->getBackPositionOnLane())
4457
<< "\n";
4458
#endif
4459
if (ego->getLaneChangeModel().isOpposite()) {
4460
std::pair<MSVehicle* const, double> result = getFollower(ego, getOppositePos(ego->getPositionOnLane()), -1, MinorLinkMode::FOLLOW_NEVER);
4461
return result;
4462
} else {
4463
double vehPos = getOppositePos(ego->getPositionOnLane() - ego->getVehicleType().getLength());
4464
std::pair<MSVehicle*, double> result = getLeader(ego, vehPos, std::vector<MSLane*>());
4465
double dist = getMaximumBrakeDist() + getOppositePos(ego->getPositionOnLane() - getLength());
4466
MSLane* next = const_cast<MSLane*>(this);
4467
while (result.first == nullptr && dist > 0) {
4468
// cannot call getLeadersOnConsecutive because succLinkSec doesn't
4469
// uses the vehicle's route and doesn't work on the opposite side
4470
vehPos -= next->getLength();
4471
next = next->getCanonicalSuccessorLane();
4472
if (next == nullptr) {
4473
break;
4474
}
4475
dist -= next->getLength();
4476
result = next->getLeader(ego, vehPos, std::vector<MSLane*>());
4477
}
4478
if (result.first != nullptr) {
4479
if (result.first->getLaneChangeModel().isOpposite()) {
4480
result.second -= result.first->getVehicleType().getLength();
4481
} else {
4482
if (result.second > POSITION_EPS) {
4483
// follower can be safely ignored since it is going the other way
4484
return std::make_pair(static_cast<MSVehicle*>(nullptr), -1);
4485
}
4486
}
4487
}
4488
return result;
4489
}
4490
}
4491
4492
void
4493
MSLane::initCollisionAction(const OptionsCont& oc, const std::string& option, CollisionAction& myAction) {
4494
const std::string action = oc.getString(option);
4495
if (action == "none") {
4496
myAction = COLLISION_ACTION_NONE;
4497
} else if (action == "warn") {
4498
myAction = COLLISION_ACTION_WARN;
4499
} else if (action == "teleport") {
4500
myAction = COLLISION_ACTION_TELEPORT;
4501
} else if (action == "remove") {
4502
myAction = COLLISION_ACTION_REMOVE;
4503
} else {
4504
WRITE_ERROR(TLF("Invalid % '%'.", option, action));
4505
}
4506
}
4507
4508
void
4509
MSLane::initCollisionOptions(const OptionsCont& oc) {
4510
initCollisionAction(oc, "collision.action", myCollisionAction);
4511
initCollisionAction(oc, "intermodal-collision.action", myIntermodalCollisionAction);
4512
myCheckJunctionCollisions = oc.getBool("collision.check-junctions");
4513
myCheckJunctionCollisionMinGap = oc.getFloat("collision.check-junctions.mingap");
4514
myCollisionStopTime = string2time(oc.getString("collision.stoptime"));
4515
myIntermodalCollisionStopTime = string2time(oc.getString("intermodal-collision.stoptime"));
4516
myCollisionMinGapFactor = oc.getFloat("collision.mingap-factor");
4517
myExtrapolateSubstepDepart = oc.getBool("extrapolate-departpos");
4518
}
4519
4520
4521
void
4522
MSLane::setPermissions(SVCPermissions permissions, long long transientID) {
4523
if (transientID == CHANGE_PERMISSIONS_PERMANENT) {
4524
myPermissions = permissions;
4525
myOriginalPermissions = permissions;
4526
} else {
4527
myPermissionChanges[transientID] = permissions;
4528
resetPermissions(CHANGE_PERMISSIONS_PERMANENT);
4529
}
4530
}
4531
4532
4533
void
4534
MSLane::resetPermissions(long long transientID) {
4535
myPermissionChanges.erase(transientID);
4536
if (myPermissionChanges.empty()) {
4537
myPermissions = myOriginalPermissions;
4538
} else {
4539
// combine all permission changes
4540
myPermissions = SVCAll;
4541
for (const auto& item : myPermissionChanges) {
4542
myPermissions &= item.second;
4543
}
4544
}
4545
}
4546
4547
4548
bool
4549
MSLane::hadPermissionChanges() const {
4550
return !myPermissionChanges.empty();
4551
}
4552
4553
4554
void
4555
MSLane::setChangeLeft(SVCPermissions permissions) {
4556
myChangeLeft = permissions;
4557
}
4558
4559
4560
void
4561
MSLane::setChangeRight(SVCPermissions permissions) {
4562
myChangeRight = permissions;
4563
}
4564
4565
4566
bool
4567
MSLane::hasPedestrians() const {
4568
MSNet* const net = MSNet::getInstance();
4569
return net->hasPersons() && net->getPersonControl().getMovementModel()->hasPedestrians(this);
4570
}
4571
4572
4573
PersonDist
4574
MSLane::nextBlocking(double minPos, double minRight, double maxLeft, double stopTime, bool bidi) const {
4575
return MSNet::getInstance()->getPersonControl().getMovementModel()->nextBlocking(this, minPos, minRight, maxLeft, stopTime, bidi);
4576
}
4577
4578
4579
bool
4580
MSLane::checkForPedestrians(const MSVehicle* aVehicle, double& speed, double& dist, double pos, bool patchSpeed) const {
4581
if (getEdge().getPersons().size() > 0 && hasPedestrians()) {
4582
#ifdef DEBUG_INSERTION
4583
if (DEBUG_COND2(aVehicle)) {
4584
std::cout << SIMTIME << " check for pedestrians on lane=" << getID() << " pos=" << pos << "\n";
4585
}
4586
#endif
4587
PersonDist leader = nextBlocking(pos - aVehicle->getVehicleType().getLength(),
4588
aVehicle->getRightSideOnLane(), aVehicle->getRightSideOnLane() + aVehicle->getVehicleType().getWidth(), ceil(speed / aVehicle->getCarFollowModel().getMaxDecel()));
4589
if (leader.first != 0) {
4590
const double gap = leader.second - aVehicle->getVehicleType().getLengthWithGap();
4591
const double stopSpeed = aVehicle->getCarFollowModel().stopSpeed(aVehicle, speed, gap, MSCFModel::CalcReason::FUTURE);
4592
if ((gap < 0 && (aVehicle->getInsertionChecks() & ((int)InsertionCheck::COLLISION | (int)InsertionCheck::PEDESTRIAN)) != 0)
4593
|| checkFailure(aVehicle, speed, dist, stopSpeed, patchSpeed, "", InsertionCheck::PEDESTRIAN)) {
4594
// we may not drive with the given velocity - we crash into the pedestrian
4595
#ifdef DEBUG_INSERTION
4596
if (DEBUG_COND2(aVehicle)) std::cout << SIMTIME
4597
<< " isInsertionSuccess lane=" << getID()
4598
<< " veh=" << aVehicle->getID()
4599
<< " pos=" << pos
4600
<< " posLat=" << aVehicle->getLateralPositionOnLane()
4601
<< " patchSpeed=" << patchSpeed
4602
<< " speed=" << speed
4603
<< " stopSpeed=" << stopSpeed
4604
<< " pedestrianLeader=" << leader.first->getID()
4605
<< " failed (@796)!\n";
4606
#endif
4607
return false;
4608
}
4609
}
4610
}
4611
double backLength = aVehicle->getLength() - pos;
4612
if (backLength > 0 && MSNet::getInstance()->hasPersons()) {
4613
// look upstream for pedestrian crossings
4614
const MSLane* prev = getLogicalPredecessorLane();
4615
const MSLane* cur = this;
4616
while (backLength > 0 && prev != nullptr) {
4617
const MSLink* link = prev->getLinkTo(cur);
4618
if (link->hasFoeCrossing()) {
4619
for (const MSLane* foe : link->getFoeLanes()) {
4620
if (foe->isCrossing() && (foe->hasPedestrians() ||
4621
(foe->getIncomingLanes()[0].viaLink->getApproachingPersons() != nullptr
4622
&& foe->getIncomingLanes()[0].viaLink->getApproachingPersons()->size() > 0))) {
4623
#ifdef DEBUG_INSERTION
4624
if (DEBUG_COND2(aVehicle)) std::cout << SIMTIME
4625
<< " isInsertionSuccess lane=" << getID()
4626
<< " veh=" << aVehicle->getID()
4627
<< " pos=" << pos
4628
<< " backCrossing=" << foe->getID()
4629
<< " peds=" << joinNamedToString(foe->getEdge().getPersons(), " ")
4630
<< " approaching=" << foe->getIncomingLanes()[0].viaLink->getApproachingPersons()->size()
4631
<< " failed (@4550)!\n";
4632
#endif
4633
return false;
4634
}
4635
}
4636
}
4637
backLength -= prev->getLength();
4638
cur = prev;
4639
prev = prev->getLogicalPredecessorLane();
4640
}
4641
}
4642
return true;
4643
}
4644
4645
4646
void
4647
MSLane::initRNGs(const OptionsCont& oc) {
4648
myRNGs.clear();
4649
const int numRNGs = oc.getInt("thread-rngs");
4650
const bool random = oc.getBool("random");
4651
int seed = oc.getInt("seed");
4652
myRNGs.reserve(numRNGs); // this is needed for stable pointers on debugging
4653
for (int i = 0; i < numRNGs; i++) {
4654
myRNGs.push_back(SumoRNG("lanes_" + toString(i)));
4655
RandHelper::initRand(&myRNGs.back(), random, seed++);
4656
}
4657
}
4658
4659
void
4660
MSLane::saveRNGStates(OutputDevice& out) {
4661
for (int i = 0; i < getNumRNGs(); i++) {
4662
out.openTag(SUMO_TAG_RNGLANE);
4663
out.writeAttr(SUMO_ATTR_INDEX, i);
4664
out.writeAttr(SUMO_ATTR_STATE, RandHelper::saveState(&myRNGs[i]));
4665
out.closeTag();
4666
}
4667
}
4668
4669
void
4670
MSLane::loadRNGState(int index, const std::string& state) {
4671
if (index >= getNumRNGs()) {
4672
throw ProcessError(TLF("State was saved with more than % threads. Change the number of threads or do not load RNG state", toString(getNumRNGs())));
4673
}
4674
RandHelper::loadState(state, &myRNGs[index]);
4675
}
4676
4677
4678
MSLane*
4679
MSLane::getBidiLane() const {
4680
return myBidiLane;
4681
}
4682
4683
4684
bool
4685
MSLane::mustCheckJunctionCollisions() const {
4686
return myCheckJunctionCollisions && myEdge->isInternal() && (
4687
myLinks.front()->getFoeLanes().size() > 0
4688
|| myLinks.front()->getWalkingAreaFoe() != nullptr
4689
|| myLinks.front()->getWalkingAreaFoeExit() != nullptr);
4690
}
4691
4692
4693
double
4694
MSLane::getSpaceTillLastStanding(const MSVehicle* ego, bool& foundStopped) const {
4695
/// @todo if ego isn't on this lane, we could use a cached value
4696
double lengths = 0;
4697
for (const MSVehicle* last : myVehicles) {
4698
if (last->getSpeed() < SUMO_const_haltingSpeed && !last->getLane()->getEdge().isRoundabout()
4699
&& last != ego
4700
// @todo recheck
4701
&& last->isFrontOnLane(this)) {
4702
foundStopped = true;
4703
const double lastBrakeGap = last->getCarFollowModel().brakeGap(last->getSpeed());
4704
const double ret = last->getBackPositionOnLane() + lastBrakeGap - lengths;
4705
return ret;
4706
}
4707
if (MSGlobals::gSublane && ego->getVehicleType().getWidth() + last->getVehicleType().getWidth() < getWidth()) {
4708
lengths += last->getVehicleType().getLengthWithGap() * (last->getVehicleType().getWidth() + last->getVehicleType().getMinGapLat()) / getWidth();
4709
} else {
4710
lengths += last->getVehicleType().getLengthWithGap();
4711
}
4712
}
4713
return getLength() - lengths;
4714
}
4715
4716
4717
bool
4718
MSLane::allowsVehicleClass(SUMOVehicleClass vclass, int routingMode) const {
4719
return (((routingMode & libsumo::ROUTING_MODE_IGNORE_TRANSIENT_PERMISSIONS) ? myOriginalPermissions : myPermissions) & vclass) == vclass;
4720
}
4721
4722
4723
const MSJunction*
4724
MSLane::getFromJunction() const {
4725
return myEdge->getFromJunction();
4726
}
4727
4728
4729
const MSJunction*
4730
MSLane::getToJunction() const {
4731
return myEdge->getToJunction();
4732
}
4733
4734
/****************************************************************************/
4735
4736