Line data Source code
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 MELSegment.cpp
15 : /// @author Jakob Erdmann
16 : /// @date Tue, July 2026
17 : ///
18 : // A LTM (LIFT)-model segment
19 : /****************************************************************************/
20 : #include <config.h>
21 :
22 : #include <algorithm>
23 : #include <limits>
24 : #include <utils/common/StdDefs.h>
25 : #include <microsim/MSGlobals.h>
26 : #include <microsim/MSEdge.h>
27 : #include <microsim/MSJunction.h>
28 : #include <microsim/MSNet.h>
29 : #include <microsim/MSLane.h>
30 : #include <microsim/MSLink.h>
31 : #include <microsim/MSMoveReminder.h>
32 : #include <microsim/traffic_lights/MSTrafficLightLogic.h>
33 : #include <microsim/traffic_lights/MSDriveWay.h>
34 : #include <microsim/traffic_lights/MSRailSignalControl.h>
35 : #include <microsim/output/MSXMLRawOut.h>
36 : #include <microsim/output/MSDetectorFileOutput.h>
37 : #include <microsim/MSVehicleControl.h>
38 : #include <microsim/devices/MSDevice.h>
39 : #include <utils/common/FileHelpers.h>
40 : #include <utils/common/MsgHandler.h>
41 : #include <utils/iodevices/OutputDevice.h>
42 : #include <utils/common/RandHelper.h>
43 : #include "MEVehicle.h"
44 : #include "MELoop.h"
45 : #include "MELSegment.h"
46 :
47 : #define DEFAULT_VEH_LENGTH_WITH_GAP (SUMOVTypeParameter::getDefault().length + SUMOVTypeParameter::getDefault().minGap)
48 :
49 : //#define DEBUG_OPENED
50 : //#define DEBUG_JAMTHRESHOLD
51 : //#define DEBUG_COND (getID() == "blocker")
52 : //#define DEBUG_COND (true)
53 : #define DEBUG_COND (myEdge.isSelected())
54 : #define DEBUG_COND2(obj) ((obj != 0 && (obj)->isSelected()))
55 :
56 :
57 : // ===========================================================================
58 : // static member definition
59 : // ===========================================================================
60 :
61 :
62 : // ===========================================================================
63 : // MELSegment method definitions
64 : // ===========================================================================
65 0 : MELSegment::MELSegment(const std::string& id,
66 : const MSEdge& parent, MESegment* next,
67 : const double length, const double speed,
68 : const int idx,
69 : const bool multiQueue,
70 0 : const MesoEdgeType& edgeType):
71 0 : MESegment(id, parent, next, length, speed, idx, multiQueue, edgeType)
72 : {
73 0 : myGapTimes.resize(myQueues.size());
74 0 : }
75 :
76 :
77 : SUMOTime
78 0 : MELSegment::computeHeadway(Queue& /*q*/, const Queue& /*qNext*/, const MESegment* const /*next*/, const MEVehicle* veh) const {
79 : // @note: it might seem sensible to check veh->getQueuingTimeLoss() here but
80 : // then the queing state would be "sticky" because queuingTimeLoss is computed with tau_ff
81 : // and every leader car that uses tau_jf applies queing timeLoss to it's followers
82 0 : SUMOTime headway = tauWithVehLength(veh->getWaitingTime() > 0 ? myTau_jf : myTau_ff,
83 0 : veh->getVehicleType().getLengthWithGap(),
84 0 : veh->getVehicleType().getCarFollowModel().getHeadwayTime());
85 0 : if (myTLSPenalty) {
86 0 : const MSLink* const tllink = getLink(veh, true);
87 0 : if (tllink != nullptr && tllink->isTLSControlled()) {
88 : assert(tllink->getGreenFraction() > 0);
89 0 : headway = (SUMOTime)((double)headway / tllink->getGreenFraction());
90 : }
91 : }
92 0 : return headway;
93 : }
94 :
95 :
96 : void
97 0 : MELSegment::send(MEVehicle* veh, MESegment* const next, const int nextQIdx, SUMOTime time, const MSMoveReminder::Notification reason) {
98 0 : GapTimes& gapTimes = myGapTimes[veh->getQueIndex()];
99 : // record time when the gap vacated by ego will reach the upstream end of the segment
100 : // gaps travel quickly in free flow (the number of gaps and vehicles stays below the segment capacity)
101 : // but they travel more slowly when queued (startupDelay)
102 0 : gapTimes.insert(gapTimes.begin(), time + myLength * (veh->getQueuingTimeLoss() > 0 ? myTau_jj : myTau_ff) / DEFAULT_VEH_LENGTH_WITH_GAP);
103 0 : MESegment::send(veh, next, nextQIdx, time, reason);
104 0 : }
105 :
106 :
107 : void
108 0 : MELSegment::updateEntryBlockTime(SUMOTime time) {
109 0 : for (int qIdx = 0; qIdx < (int)myQueues.size(); qIdx++) {
110 0 : Queue& q = myQueues[qIdx];
111 : GapTimes& gapTimes = myGapTimes[qIdx];
112 0 : while (!gapTimes.empty() && gapTimes.back() <= time) {
113 : gapTimes.pop_back();
114 : }
115 0 : if (!gapTimes.empty() && q.getOccupancy() + gapTimes.size() * DEFAULT_VEH_LENGTH_WITH_GAP > myQueueCapacity) {
116 : // segment is jammed because the empty spaces have not yet reached the upstream end.
117 0 : q.setEntryBlockTime(MAX2(q.getEntryBlockTime(), gapTimes.back()));
118 : }
119 : }
120 0 : }
121 :
122 :
123 : bool
124 0 : MELSegment::hasSpaceForInsertion(const Queue& q, int qIdx, double /*newOccupancy*/, SUMOTime entryTime) const {
125 0 : GapTimes& gapTimes = const_cast<GapTimes&>(myGapTimes[qIdx]);
126 0 : while (!gapTimes.empty() && gapTimes.back() <= entryTime) {
127 : gapTimes.pop_back();
128 : }
129 0 : return q.getOccupancy() + gapTimes.size() * DEFAULT_VEH_LENGTH_WITH_GAP < myQueueCapacity;
130 : }
131 :
132 :
133 : /****************************************************************************/
|