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 : } 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 : } 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 : } 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 : } 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 : }