1 /****************************************************************************/
2 // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
3 // Copyright (C) 2001-2019 German Aerospace Center (DLR) and others.
4 // This program and the accompanying materials
5 // are made available under the terms of the Eclipse Public License v2.0
6 // which accompanies this distribution, and is available at
7 // http://www.eclipse.org/legal/epl-v20.html
8 // SPDX-License-Identifier: EPL-2.0
9 /****************************************************************************/
10 /// @file    MSRailCrossing.cpp
11 /// @author  Jakob Erdmann
12 /// @date    Dez 2015
13 /// @version $Id$
14 ///
15 // A rail signal logic
16 /****************************************************************************/
17 
18 
19 // ===========================================================================
20 // included modules
21 // ===========================================================================
22 #include <config.h>
23 
24 #include <cassert>
25 #include <utility>
26 #include <vector>
27 #include <bitset>
28 #include <microsim/MSEventControl.h>
29 #include <microsim/MSNet.h>
30 #include <microsim/MSEdge.h>
31 #include "MSTrafficLightLogic.h"
32 #include "MSRailCrossing.h"
33 #include <microsim/MSLane.h>
34 #include "MSPhaseDefinition.h"
35 #include "MSTLLogicControl.h"
36 
37 
38 // ===========================================================================
39 // method definitions
40 // ===========================================================================
MSRailCrossing(MSTLLogicControl & tlcontrol,const std::string & id,const std::string & programID,const std::map<std::string,std::string> & parameters)41 MSRailCrossing::MSRailCrossing(MSTLLogicControl& tlcontrol,
42                                const std::string& id, const std::string& programID,
43                                const std::map<std::string, std::string>& parameters) :
44     MSSimpleTrafficLightLogic(tlcontrol, id, programID, TLTYPE_RAIL_CROSSING, Phases(), 0, DELTA_T, parameters),
45     // XXX make this configurable
46     mySecurityGap(TIME2STEPS(15)),
47     myMinGreenTime(TIME2STEPS(5)),
48     /// XXX compute reasonable time depending on link length
49     myYellowTime(TIME2STEPS(5)) {
50     // dummy phase, used to avoid crashing in MSTrafficLightLogic::setTrafficLightSignals()
51     myPhases.push_back(new MSPhaseDefinition(1, std::string(SUMO_MAX_CONNECTIONS, 'X')));
52 }
53 
54 void
init(NLDetectorBuilder &)55 MSRailCrossing::init(NLDetectorBuilder&) {
56     delete myPhases.front();
57     myPhases.clear();
58     myPhases.push_back(new MSPhaseDefinition(1, std::string(myLinks.size(), 'G')));
59     myPhases.push_back(new MSPhaseDefinition(myYellowTime, std::string(myLinks.size(), 'y')));
60     myPhases.push_back(new MSPhaseDefinition(1, std::string(myLinks.size(), 'r')));
61     // init phases
62     updateCurrentPhase();
63     setTrafficLightSignals(MSNet::getInstance()->getCurrentTimeStep());
64 }
65 
66 
~MSRailCrossing()67 MSRailCrossing::~MSRailCrossing() {}
68 
69 
70 // ----------- Handling of controlled links
71 void
adaptLinkInformationFrom(const MSTrafficLightLogic & logic)72 MSRailCrossing::adaptLinkInformationFrom(const MSTrafficLightLogic& logic) {
73     MSTrafficLightLogic::adaptLinkInformationFrom(logic);
74     updateCurrentPhase();
75 }
76 
77 
78 // ------------ Switching and setting current rows
79 SUMOTime
trySwitch()80 MSRailCrossing::trySwitch() {
81     SUMOTime nextTry = updateCurrentPhase();
82     setTrafficLightSignals(MSNet::getInstance()->getCurrentTimeStep());
83     //if (getID() == "cluster_1088529493_1260626727") std::cout << " myStep=" << myStep << " nextTry=" << nextTry << "\n";
84     return nextTry;
85 }
86 
87 
88 SUMOTime
updateCurrentPhase()89 MSRailCrossing::updateCurrentPhase() {
90     const SUMOTime now = MSNet::getInstance()->getCurrentTimeStep();
91     SUMOTime stayRedUntil = now;
92     // check rail links for approaching foes to determine whether and how long
93     // the crossing must remain closed
94     for (std::vector<MSLink*>::const_iterator it_link = myIncomingRailLinks.begin(); it_link != myIncomingRailLinks.end(); ++it_link) {
95 
96         for (auto it_avi : (*it_link)->getApproaching()) {
97             const MSLink::ApproachingVehicleInformation& avi = it_avi.second;
98             if (avi.arrivalTime - myYellowTime - now < mySecurityGap) {
99                 stayRedUntil = MAX2(stayRedUntil, avi.leavingTime);
100             }
101         }
102         if ((*it_link)->getViaLane() != nullptr && (*it_link)->getViaLane()->getVehicleNumberWithPartials() > 0) {
103             // do not open if there is still a train on the crossing
104             stayRedUntil = MAX2(stayRedUntil, now + DELTA_T);
105         }
106     }
107     //if (getID() == "cluster_1088529493_1260626727") std::cout << SIMTIME << " stayRedUntil=" << stayRedUntil;
108     const SUMOTime wait = stayRedUntil - now;
109 
110     if (myStep == 0) {
111         // 'G': check whether the crossing can stay open
112         if (wait == 0) {
113             return DELTA_T;
114         } else {
115             myStep++;
116             return myYellowTime;
117         }
118     } else if (myStep == 1) {
119         // 'y': yellow time is over. switch to red
120         myStep++;
121         return MAX2(DELTA_T, wait);
122     } else {
123         // 'r': check whether we may open again
124         if (wait == 0) {
125             myStep = 0;
126             return myMinGreenTime;
127         } else {
128             return wait;
129         }
130     }
131 }
132 
133 
134 // ------------ Conversion between time and phase
135 SUMOTime
getPhaseIndexAtTime(SUMOTime) const136 MSRailCrossing::getPhaseIndexAtTime(SUMOTime) const {
137     return 0;
138 }
139 
140 SUMOTime
getOffsetFromIndex(int) const141 MSRailCrossing::getOffsetFromIndex(int) const {
142     return 0;
143 }
144 
145 int
getIndexFromOffset(SUMOTime) const146 MSRailCrossing::getIndexFromOffset(SUMOTime) const {
147     return 0;
148 }
149 
150 
151 void
addLink(MSLink * link,MSLane * lane,int pos)152 MSRailCrossing::addLink(MSLink* link, MSLane* lane, int pos) {
153     if (pos >= 0) {
154         MSTrafficLightLogic::addLink(link, lane, pos);
155     } else {
156         myIncomingRailLinks.push_back(link);
157     }
158 }
159 
160 
161 /****************************************************************************/
162 
163