Line data Source code
1 : /****************************************************************************/
2 : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3 : // Copyright (C) 2010-2024 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 MSPushButton.cpp
15 : /// @author Federico Caselli
16 : /// @date 2015-07-15
17 : ///
18 : // The class for a PushButton
19 : /****************************************************************************/
20 :
21 : #include <microsim/MSEdge.h>
22 : #include <microsim/MSLane.h>
23 : #include <microsim/MSVehicle.h>
24 : #include <microsim/transportables/MSPerson.h>
25 : #include "MSPushButton.h"
26 : #include "MSPhaseDefinition.h"
27 : //#define SWARM_DEBUG
28 :
29 :
30 : // ===========================================================================
31 : // static members
32 : // ===========================================================================
33 : std::map<std::string, std::vector<std::string> > MSPedestrianPushButton::m_crossingEdgeMap;
34 : bool MSPedestrianPushButton::m_crossingEdgeMapLoaded = false;
35 :
36 : // ===========================================================================
37 : // method definitions
38 : // ===========================================================================
39 0 : MSPushButton::MSPushButton(const MSEdge* edge, const MSEdge* crossingEdge) {
40 0 : m_edge = edge;
41 0 : m_crossingEdge = crossingEdge;
42 0 : }
43 :
44 0 : MSPushButton::~MSPushButton() {
45 : /// do not delete the MSEdge here
46 0 : }
47 :
48 0 : bool MSPushButton::anyActive(const std::vector<MSPushButton*>& pushButtons) {
49 0 : for (std::vector<MSPushButton*>::const_iterator it = pushButtons.begin(); it != pushButtons.end(); ++it) {
50 0 : if (it.operator * ()->isActivated()) {
51 : return true;
52 : }
53 : }
54 : return false;
55 : }
56 :
57 :
58 0 : MSPedestrianPushButton::MSPedestrianPushButton(const MSEdge* walkingEdge, const MSEdge* crossingEdge)
59 0 : : MSPushButton(walkingEdge, crossingEdge) {
60 : assert(walkingEdge->isWalkingArea() || ((walkingEdge->getPermissions() & SVC_PEDESTRIAN) != 0));
61 : assert(crossingEdge->isCrossing());
62 0 : }
63 :
64 0 : bool MSPedestrianPushButton::isActivated() const {
65 0 : return isActiveForEdge(m_edge, m_crossingEdge);
66 : }
67 :
68 0 : bool MSPedestrianPushButton::isActiveForEdge(const MSEdge* walkingEdge, const MSEdge* crossing) {
69 0 : const std::set<MSTransportable*, ComparatorNumericalIdLess> persons = walkingEdge->getPersons();
70 0 : if (persons.size() > 0) {
71 0 : for (std::set<MSTransportable*>::const_iterator pIt = persons.begin(); pIt != persons.end(); ++pIt) {
72 0 : const MSPerson* person = (MSPerson*)*pIt;
73 0 : const MSEdge* nextEdge = person->getNextEdgePtr();
74 : ///TODO keep using >= 1 or switch to ==1. Should change return value from always active to active only when pressed?
75 : ///TODO If changed the swarm logic must be changed since it relies on this behavior that keeps it active
76 0 : if (person->getWaitingSeconds() >= 1 && nextEdge && nextEdge->getID() == crossing->getID()) {
77 : #ifdef SWARM_DEBUG
78 : std::ostringstream oss;
79 : oss << "MSPedestrianPushButton::isActiveForEdge Pushbutton active for edge " << walkingEdge->getID() << " crossing " << crossing->getID()
80 : << " for " << person->getID() << " wait " << person->getWaitingSeconds();
81 : WRITE_MESSAGE(oss.str());
82 : #endif
83 : return true;
84 : }
85 : }
86 : } else {
87 : //No person currently on the edge. But there may be some vehicles of class pedestrian
88 0 : for (std::vector<MSLane*>::const_iterator laneIt = walkingEdge->getLanes().begin();
89 0 : laneIt != walkingEdge->getLanes().end(); ++laneIt) {
90 0 : MSLane* lane = *laneIt;
91 0 : MSLane::VehCont vehicles = lane->getVehiclesSecure();
92 0 : for (MSLane::VehCont::const_iterator vehicleIt = vehicles.begin(); vehicleIt != vehicles.end(); ++vehicleIt) {
93 0 : MSVehicle* vehicle = *vehicleIt;
94 0 : if (vehicle->getVClass() == SVC_PEDESTRIAN) {
95 : // It's a pedestrian
96 0 : const MSEdge* nextEdge = vehicle->succEdge(1);
97 0 : if (vehicle->getWaitingSeconds() >= 1 && nextEdge) {
98 : // Next edge is not internal. Try to find if between the current vehicle edge and the next is the crossing.
99 : // To do that check if between the successors (or predecessor) of crossing is the next edge and walking precedes (or ensue) it.
100 0 : if ((std::find(crossing->getPredecessors().begin(), crossing->getPredecessors().end(), walkingEdge) != crossing->getPredecessors().end()
101 0 : && std::find(crossing->getSuccessors().begin(), crossing->getSuccessors().end(), nextEdge) != crossing->getSuccessors().end())
102 0 : || (std::find(crossing->getSuccessors().begin(), crossing->getSuccessors().end(), walkingEdge) != crossing->getSuccessors().end()
103 0 : && std::find(crossing->getPredecessors().begin(), crossing->getPredecessors().end(), nextEdge) != crossing->getPredecessors().end())) {
104 : #ifdef SWARM_DEBUG
105 : std::ostringstream oss;
106 : oss << "MSPedestrianPushButton::isActiveForEdge Pushbutton active for edge " << walkingEdge->getID() << " crossing " << crossing->getID()
107 : << " for " << vehicle->getID() << " wait " << vehicle->getWaitingSeconds();
108 : WRITE_MESSAGE(oss.str());
109 : #endif
110 : // Also release the vehicles here
111 0 : lane->releaseVehicles();
112 0 : return true;
113 : }
114 : }
115 : }
116 : }
117 0 : lane->releaseVehicles();
118 0 : }
119 : }
120 : #ifdef SWARM_DEBUG
121 : std::ostringstream oss;
122 : oss << "MSPedestrianPushButton::isActiveForEdge Pushbutton not active for edge " << walkingEdge->getID() << " crossing " << crossing->getID()
123 : << " num Persons " << persons.size();
124 : WRITE_MESSAGE(oss.str());
125 : #endif
126 : return false;
127 : }
128 :
129 :
130 : ///@brief Checks if any of the edges is a walking area
131 0 : void getWalking(const std::vector<MSEdge*>& edges, std::vector< MSEdge*>& walkingEdges) {
132 0 : for (std::vector<MSEdge*>::const_iterator it = edges.begin(); it != edges.end(); ++it) {
133 0 : MSEdge* edge = *it;
134 0 : if (edge->isWalkingArea() || ((edge->getPermissions() & SVC_PEDESTRIAN) != 0)) {
135 0 : walkingEdges.push_back(edge);
136 : }
137 : }
138 0 : }
139 :
140 : ///@brief Get the walking areas adjacent to the crossing
141 0 : const std::vector<MSEdge*> getWalkingAreas(const MSEdge* crossing) {
142 : std::vector<MSEdge*> walkingEdges;
143 0 : getWalking(crossing->getSuccessors(), walkingEdges);
144 0 : getWalking(crossing->getPredecessors(), walkingEdges);
145 0 : return walkingEdges;
146 :
147 0 : }
148 :
149 0 : bool MSPedestrianPushButton::isActiveOnAnySideOfTheRoad(const MSEdge* crossing) {
150 0 : const std::vector<MSEdge*> walkingList = getWalkingAreas(crossing);
151 0 : for (std::vector<MSEdge*>::const_iterator wIt = walkingList.begin(); wIt != walkingList.end(); ++wIt) {
152 0 : MSEdge* walking = *wIt;
153 0 : if (isActiveForEdge(walking, crossing)) {
154 : #ifdef SWARM_DEBUG
155 : WRITE_MESSAGE("MSPedestrianPushButton::isActiveOnAnySideOfTheRoad crossing edge " + crossing->getID() + " walking edge" + walking->getID());
156 : #endif
157 : return true;
158 : }
159 : }
160 : return false;
161 0 : }
162 :
163 0 : std::vector<MSPushButton*> MSPedestrianPushButton::loadPushButtons(const MSPhaseDefinition* phase) {
164 0 : loadCrossingEdgeMap();
165 : std::vector<MSPushButton*> pushButtons;
166 0 : const std::vector<std::string> lanes = phase->getTargetLaneSet();
167 : // Multiple lane can be of the same edge, so I avoid readding them
168 : std::set<std::string> controlledEdges;
169 0 : for (std::vector<std::string>::const_iterator lIt = lanes.begin(); lIt != lanes.end(); ++lIt) {
170 0 : MSLane* lane = MSLane::dictionary(*lIt);
171 0 : if (lane) {
172 : MSEdge* laneEdge = &lane->getEdge();
173 0 : if (controlledEdges.count(laneEdge->getID()) != 0) {
174 0 : continue;
175 : }
176 : controlledEdges.insert(laneEdge->getID());
177 0 : if (m_crossingEdgeMap.find(laneEdge->getID()) != m_crossingEdgeMap.end()) {
178 : //For every crossing edge that crosses this edge
179 0 : for (std::vector<std::string>::const_iterator cIt = m_crossingEdgeMap[laneEdge->getID()].begin();
180 0 : cIt != m_crossingEdgeMap[laneEdge->getID()].end(); ++cIt) {
181 0 : MSEdge* crossing = MSEdge::dictionary(*cIt);
182 0 : const std::vector<MSEdge*> walkingList = getWalkingAreas(crossing);
183 0 : for (std::vector<MSEdge*>::const_iterator wIt = walkingList.begin(); wIt != walkingList.end(); ++wIt) {
184 0 : MSEdge* walking = *wIt;
185 : #ifdef SWARM_DEBUG
186 : WRITE_MESSAGE("MSPedestrianPushButton::loadPushButtons Added pushButton for walking edge " + walking->getID() + " crossing edge "
187 : + crossing->getID() + " crossed edge " + laneEdge->getID() + ". Phase state " + phase->getState());
188 : #endif
189 0 : pushButtons.push_back(new MSPedestrianPushButton(walking, crossing));
190 : }
191 0 : }
192 : }
193 : }
194 : }
195 0 : return pushButtons;
196 0 : }
197 :
198 0 : void MSPedestrianPushButton::loadCrossingEdgeMap() {
199 0 : if (!m_crossingEdgeMapLoaded) {
200 0 : m_crossingEdgeMapLoaded = true;
201 0 : for (MSEdgeVector::const_iterator eIt = MSEdge::getAllEdges().begin(); eIt != MSEdge::getAllEdges().end(); ++eIt) {
202 0 : const MSEdge* edge = *eIt;
203 0 : if (edge->isCrossing()) {
204 0 : for (std::vector<std::string>::const_iterator cIt = edge->getCrossingEdges().begin();
205 0 : cIt != edge->getCrossingEdges().end(); ++cIt) {
206 0 : m_crossingEdgeMap[*cIt].push_back(edge->getID());
207 : }
208 : }
209 : }
210 : }
211 0 : }
|