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