Line data Source code
1 : /****************************************************************************/ 2 : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo 3 : // Copyright (C) 2014-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 MSPModel_NonInteracting.cpp 15 : /// @author Jakob Erdmann 16 : /// @date Mon, 13 Jan 2014 17 : /// 18 : // The pedestrian following model (prototype) 19 : /****************************************************************************/ 20 : #include <config.h> 21 : 22 : #include <cmath> 23 : #include <algorithm> 24 : #include <utils/common/RandHelper.h> 25 : #include <utils/geom/GeomHelper.h> 26 : #include <utils/options/OptionsCont.h> 27 : #include <utils/router/IntermodalNetwork.h> 28 : #include <microsim/MSGlobals.h> 29 : #include <microsim/MSNet.h> 30 : #include <microsim/MSEdge.h> 31 : #include <microsim/MSLane.h> 32 : #include <microsim/MSJunction.h> 33 : #include <microsim/MSEventControl.h> 34 : #include "MSPModel_NonInteracting.h" 35 : 36 : 37 : // =========================================================================== 38 : // DEBUGGING HELPERS 39 : // =========================================================================== 40 : #define DEBUG1 "disabled" 41 : #define DEBUG2 "disabled" 42 : #define DEBUGCOND(PEDID) (PEDID == DEBUG1 || PEDID == DEBUG2) 43 : 44 : 45 : // =========================================================================== 46 : // static members 47 : // =========================================================================== 48 : const double MSPModel_NonInteracting::CState::LATERAL_OFFSET(0); 49 : 50 : // =========================================================================== 51 : // MSPModel_NonInteracting method definitions 52 : // =========================================================================== 53 5601 : MSPModel_NonInteracting::MSPModel_NonInteracting(const OptionsCont& oc, MSNet* net) : 54 5601 : myNet(net), 55 5601 : myNumActivePedestrians(0) { 56 : assert(myNet != 0); 57 : UNUSED_PARAMETER(oc); 58 5601 : } 59 : 60 : 61 11166 : MSPModel_NonInteracting::~MSPModel_NonInteracting() { 62 11166 : } 63 : 64 : 65 : MSTransportableStateAdapter* 66 132561 : MSPModel_NonInteracting::add(MSTransportable* transportable, MSStageMoving* stage, SUMOTime now) { 67 132561 : myNumActivePedestrians++; 68 132561 : MoveToNextEdge* const cmd = new MoveToNextEdge(transportable, *stage, this); 69 132561 : PState* const state = transportable->isPerson() ? new PState(cmd) : new CState(cmd); 70 132561 : myNet->getBeginOfTimestepEvents()->addEvent(cmd, now + state->computeDuration(nullptr, *stage, now)); 71 132561 : return state; 72 : } 73 : 74 : 75 : MSTransportableStateAdapter* 76 13 : MSPModel_NonInteracting::loadState(MSTransportable* transportable, MSStageMoving* stage, std::istringstream& in) { 77 13 : myNumActivePedestrians++; 78 13 : MoveToNextEdge* const cmd = new MoveToNextEdge(transportable, *stage, this); 79 13 : PState* const state = transportable->isPerson() ? new PState(cmd, &in) : new CState(cmd, &in); 80 13 : myNet->getBeginOfTimestepEvents()->addEvent(cmd, state->getEventTime()); 81 13 : return state; 82 : } 83 : 84 : void 85 5599 : MSPModel_NonInteracting::clearState() { 86 5599 : myNumActivePedestrians = 0; 87 5599 : } 88 : 89 : void 90 429 : MSPModel_NonInteracting::remove(MSTransportableStateAdapter* state) { 91 429 : myNumActivePedestrians--; 92 429 : dynamic_cast<PState*>(state)->getCommand()->abortWalk(); 93 429 : } 94 : 95 : 96 : // --------------------------------------------------------------------------- 97 : // MSPModel_NonInteracting::MoveToNextEdge method definitions 98 : // --------------------------------------------------------------------------- 99 : SUMOTime 100 143854 : MSPModel_NonInteracting::MoveToNextEdge::execute(SUMOTime currentTime) { 101 143854 : if (myTransportable == nullptr) { 102 : return 0; // descheduled 103 : } 104 143428 : const MSEdge* old = myParent.getEdge(); 105 143428 : const bool arrived = myParent.moveToNextEdge(myTransportable, currentTime, myParent.getPState()->getDirection(myParent, currentTime)); 106 143428 : if (arrived) { 107 131901 : myModel->registerArrived(); 108 131901 : return 0; 109 : } 110 11527 : myParent.activateEntryReminders(myTransportable); 111 11527 : return static_cast<PState*>(myParent.getPState())->computeDuration(old, myParent, currentTime); 112 : } 113 : 114 : 115 : // --------------------------------------------------------------------------- 116 : // MSPModel_NonInteracting::PState method definitions 117 : // --------------------------------------------------------------------------- 118 132574 : MSPModel_NonInteracting::PState::PState(MoveToNextEdge* cmd, std::istringstream* in) : myCommand(cmd) { 119 132574 : if (in != nullptr) { 120 13 : (*in) >> myLastEntryTime >> myCurrentDuration; 121 : } 122 132574 : } 123 : 124 : 125 : SUMOTime 126 34540 : MSPModel_NonInteracting::PState::computeDuration(const MSEdge* prev, const MSStageMoving& stage, SUMOTime currentTime) { 127 34540 : myLastEntryTime = currentTime; 128 34540 : const MSEdge* edge = stage.getEdge(); 129 34540 : const MSEdge* next = stage.getNextRouteEdge(); 130 34540 : int dir = UNDEFINED_DIRECTION; 131 34540 : if (prev == nullptr) { 132 23013 : myCurrentBeginPos = stage.getDepartPos(); 133 : } else { 134 : // default to FORWARD if not connected 135 11527 : dir = (edge->getToJunction() == prev->getToJunction() || edge->getToJunction() == prev->getFromJunction()) ? BACKWARD : FORWARD; 136 14074 : myCurrentBeginPos = dir == FORWARD ? 0 : edge->getLength(); 137 : } 138 34540 : if (next == nullptr) { 139 22487 : myCurrentEndPos = stage.getArrivalPos(); 140 : } else { 141 12053 : if (dir == UNDEFINED_DIRECTION) { 142 : // default to FORWARD if not connected 143 7995 : dir = (edge->getFromJunction() == next->getFromJunction() || edge->getFromJunction() == next->getToJunction()) ? BACKWARD : FORWARD; 144 : } 145 21616 : myCurrentEndPos = dir == FORWARD ? edge->getLength() : 0; 146 : } 147 : // ensure that a result > 0 is returned even if the walk ends immediately 148 : // adding 0.5ms is done to ensure proper rounding 149 34540 : myCurrentDuration = MAX2((SUMOTime)1, TIME2STEPS(fabs(myCurrentEndPos - myCurrentBeginPos) / stage.getMaxSpeed(myCommand->getTransportable()))); 150 : //std::cout << std::setprecision(8) << SIMTIME << " curBeg=" << myCurrentBeginPos << " curEnd=" << myCurrentEndPos << " speed=" << stage.getMaxSpeed(myCommand->getTransportable()) << " dur=" << myCurrentDuration << "\n"; 151 : // round to the next timestep to avoid systematic higher walking speed 152 34540 : if ((myCurrentDuration % DELTA_T) > 0) { 153 28563 : myCurrentDuration += DELTA_T; 154 : } 155 34540 : return myCurrentDuration; 156 : } 157 : 158 : 159 : double 160 946382 : MSPModel_NonInteracting::PState::getEdgePos(const MSStageMoving&, SUMOTime now) const { 161 : //std::cout << SIMTIME << " lastEntryTime=" << myLastEntryTime << " pos=" << (myCurrentBeginPos + (myCurrentEndPos - myCurrentBeginPos) / myCurrentDuration * (now - myLastEntryTime)) << "\n"; 162 946382 : return myCurrentBeginPos + (myCurrentEndPos - myCurrentBeginPos) / (double)myCurrentDuration * (double)(now - myLastEntryTime); 163 : } 164 : 165 : int 166 143428 : MSPModel_NonInteracting::PState::getDirection(const MSStageMoving& /*stage*/, SUMOTime /*now*/) const { 167 143428 : if (myCurrentBeginPos == myCurrentEndPos) { 168 2284 : return UNDEFINED_DIRECTION; 169 : } else { 170 141144 : return myCurrentBeginPos < myCurrentEndPos ? FORWARD : BACKWARD; 171 : } 172 : } 173 : 174 : 175 : Position 176 190918 : MSPModel_NonInteracting::PState::getPosition(const MSStageMoving& stage, SUMOTime now) const { 177 190918 : const MSLane* lane = getSidewalk<MSEdge, MSLane>(stage.getEdge()); 178 190918 : if (lane == nullptr) { 179 : //std::string error = "Pedestrian '" + myCommand->myPerson->getID() + "' could not find sidewalk on edge '" + state.getEdge()->getID() + "', time=" 180 : // + time2string(MSNet::getInstance()->getCurrentTimeStep()) + "."; 181 : //if (!OptionsCont::getOptions().getBool("ignore-route-errors")) { 182 : // throw ProcessError(error); 183 : //} 184 172 : lane = stage.getEdge()->getLanes().front(); 185 : } 186 191090 : const double lateral_offset = (lane->allowsVehicleClass(SVC_PEDESTRIAN) ? 0 : SIDEWALK_OFFSET 187 172 : * (MSGlobals::gLefthand ? -1 : 1)); 188 190918 : return stage.getLanePosition(lane, getEdgePos(stage, now), lateral_offset); 189 : } 190 : 191 : 192 : double 193 117336 : MSPModel_NonInteracting::PState::getAngle(const MSStageMoving& stage, SUMOTime now) const { 194 : //std::cout << SIMTIME << " rawAngle=" << stage.getEdgeAngle(stage.getEdge(), getEdgePos(stage, now)) << " angle=" << stage.getEdgeAngle(stage.getEdge(), getEdgePos(stage, now)) + (myCurrentEndPos < myCurrentBeginPos ? 180 : 0) << "\n"; 195 117336 : double angle = stage.getEdgeAngle(stage.getEdge(), getEdgePos(stage, now)) + (myCurrentEndPos < myCurrentBeginPos ? M_PI : 0); 196 117336 : if (angle > M_PI) { 197 3463 : angle -= 2 * M_PI; 198 : } 199 117336 : return angle; 200 : } 201 : 202 : 203 : SUMOTime 204 2 : MSPModel_NonInteracting::PState::getWaitingTime(const MSStageMoving&, SUMOTime) const { 205 2 : return 0; 206 : } 207 : 208 : 209 : double 210 184586 : MSPModel_NonInteracting::PState::getSpeed(const MSStageMoving& stage) const { 211 184586 : return stage.getMaxSpeed(myCommand->getTransportable()); 212 : } 213 : 214 : 215 : const MSEdge* 216 1 : MSPModel_NonInteracting::PState::getNextEdge(const MSStageMoving& stage) const { 217 1 : return stage.getNextRouteEdge(); 218 : } 219 : 220 : 221 : void 222 13 : MSPModel_NonInteracting::PState::saveState(std::ostringstream& out) { 223 26 : out << " " << myLastEntryTime << " " << myCurrentDuration; 224 13 : } 225 : 226 : 227 : // --------------------------------------------------------------------------- 228 : // MSPModel_NonInteracting::CState method definitions 229 : // --------------------------------------------------------------------------- 230 109548 : MSPModel_NonInteracting::CState::CState(MoveToNextEdge* cmd, std::istringstream* in) : PState(cmd, in) { 231 109548 : } 232 : 233 : 234 : Position 235 67 : MSPModel_NonInteracting::CState::getPosition(const MSStageMoving& stage, SUMOTime now) const { 236 : const double dist = myCurrentBeginPosition.distanceTo2D(myCurrentEndPosition); //distance between begin and end position of this tranship stage 237 67 : double pos = MIN2(STEPS2TIME(now - myLastEntryTime) * stage.getMaxSpeed(), dist); //the container shall not go beyond its end position 238 67 : return PositionVector::positionAtOffset2D(myCurrentBeginPosition, myCurrentEndPosition, pos, 0); 239 : } 240 : 241 : 242 : double 243 67 : MSPModel_NonInteracting::CState::getAngle(const MSStageMoving& stage, SUMOTime now) const { 244 67 : double angle = stage.getEdgeAngle(stage.getEdge(), getEdgePos(stage, now)) + (myCurrentEndPos < myCurrentBeginPos ? 1.5 * M_PI : 0.5 * M_PI); 245 67 : if (angle > M_PI) { 246 19 : angle -= 2 * M_PI; 247 : } 248 67 : return angle; 249 : } 250 : 251 : 252 : SUMOTime 253 109548 : MSPModel_NonInteracting::CState::computeDuration(const MSEdge* /* prev */, const MSStageMoving& stage, SUMOTime currentTime) { 254 109548 : myLastEntryTime = currentTime; 255 : 256 109548 : myCurrentBeginPos = stage.getDepartPos(); 257 109548 : myCurrentEndPos = stage.getArrivalPos(); 258 : 259 109548 : const MSLane* fromLane = stage.getFromEdge()->getLanes().front(); //the lane the container starts from during its tranship stage 260 109548 : myCurrentBeginPosition = stage.getLanePosition(fromLane, myCurrentBeginPos, LATERAL_OFFSET); 261 109548 : const MSLane* toLane = stage.getEdges().back()->getLanes().front(); //the lane the container ends during its tranship stage 262 109548 : myCurrentEndPosition = stage.getLanePosition(toLane, myCurrentEndPos, LATERAL_OFFSET); 263 : 264 109548 : myCurrentDuration = MAX2((SUMOTime)1, TIME2STEPS(fabs(myCurrentEndPosition.distanceTo(myCurrentBeginPosition)) / stage.getMaxSpeed())); 265 109548 : return myCurrentDuration; 266 : } 267 : 268 : 269 : /****************************************************************************/