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 MSStageTrip.cpp
15 : /// @author Melanie Weber
16 : /// @author Andreas Kendziorra
17 : /// @author Michael Behrisch
18 : /// @author Jakob Erdmann
19 : /// @date Wed, 1 Jun 2022
20 : ///
21 : // An intermodal routing request (to be transformed into a sequence of walks and rides)
22 : /****************************************************************************/
23 : #include <config.h>
24 :
25 : #include <utils/common/StringTokenizer.h>
26 : #include <utils/geom/GeomHelper.h>
27 : #include <utils/options/OptionsCont.h>
28 : #include <utils/vehicle/SUMOVehicleParameter.h>
29 : #include <utils/router/PedestrianRouter.h>
30 : #include <utils/router/IntermodalRouter.h>
31 : #include <microsim/MSEdge.h>
32 : #include <microsim/MSEdgeControl.h>
33 : #include <microsim/devices/MSRoutingEngine.h>
34 : #include <microsim/MSLane.h>
35 : #include <microsim/MSNet.h>
36 : #include <microsim/MSStoppingPlace.h>
37 : #include <microsim/MSVehicleControl.h>
38 : #include <microsim/devices/MSDevice_Taxi.h>
39 : #include <microsim/transportables/MSStageDriving.h>
40 : #include <microsim/transportables/MSStageWaiting.h>
41 : #include <microsim/transportables/MSStageWalking.h>
42 : #include <microsim/transportables/MSTransportable.h>
43 : #include <microsim/transportables/MSTransportableControl.h>
44 : #include <microsim/transportables/MSPerson.h>
45 : #include <microsim/transportables/MSStageTrip.h>
46 :
47 :
48 : // ===========================================================================
49 : // static members
50 : // ===========================================================================
51 : #ifndef THREAD_POOL
52 : #ifdef HAVE_FOX
53 : FXMutex MSStageTrip::myVehCtrlMutex;
54 : #endif
55 : #endif
56 :
57 :
58 : // ===========================================================================
59 : // method definitions
60 : // ===========================================================================
61 :
62 : /* -------------------------------------------------------------------------
63 : * MSStageTrip - methods
64 : * ----------------------------------------------------------------------- */
65 187292 : MSStageTrip::MSStageTrip(const MSEdge* origin, MSStoppingPlace* fromStop,
66 : const MSEdge* destination, MSStoppingPlace* toStop,
67 : const SUMOTime duration, const SVCPermissions modeSet,
68 : const std::string& vTypes, const double speed, const double walkFactor,
69 : const std::string& group,
70 187292 : const double departPosLat, const bool hasArrivalPos, const double arrivalPos):
71 : MSStage(MSStageType::TRIP, destination, toStop, arrivalPos, 0.0, group),
72 187292 : myOrigin(origin),
73 187292 : myOriginStop(fromStop),
74 187292 : myDuration(duration),
75 187292 : myModeSet(modeSet),
76 187292 : myVTypes(vTypes),
77 187292 : mySpeed(speed),
78 187292 : myWalkFactor(walkFactor),
79 187292 : myDepartPosLat(departPosLat),
80 374584 : myHaveArrivalPos(hasArrivalPos) {
81 187292 : }
82 :
83 :
84 374574 : MSStageTrip::~MSStageTrip() {}
85 :
86 : MSStage*
87 178451 : MSStageTrip::clone() const {
88 178451 : MSStage* const clon = new MSStageTrip(myOrigin, const_cast<MSStoppingPlace*>(myOriginStop),
89 178451 : myDestination, myDestinationStop, myDuration,
90 178451 : myModeSet, myVTypes, mySpeed, myWalkFactor, myGroup,
91 178451 : myDepartPosLat, myHaveArrivalPos, myArrivalPos);
92 178451 : clon->setParameters(*this);
93 178451 : return clon;
94 : }
95 :
96 :
97 : Position
98 0 : MSStageTrip::getPosition(SUMOTime /* now */) const {
99 : // may be called concurrently while the trip is still being routed
100 0 : return getEdgePosition(myOrigin, myDepartPos, ROADSIDE_OFFSET * (MSGlobals::gLefthand ? -1 : 1));
101 : }
102 :
103 :
104 : double
105 0 : MSStageTrip::getAngle(SUMOTime /* now */) const {
106 : // may be called concurrently while the trip is still being routed
107 0 : return getEdgeAngle(myOrigin, myDepartPos) + M_PI / 2 * (MSGlobals::gLefthand ? -1 : 1);
108 : }
109 :
110 :
111 : const MSEdge*
112 343429 : MSStageTrip::getEdge() const {
113 343429 : return myOrigin;
114 : }
115 :
116 :
117 : double
118 330030 : MSStageTrip::getEdgePos(SUMOTime /* now */) const {
119 330030 : return myDepartPos;
120 : }
121 :
122 :
123 : std::vector<SUMOVehicle*>
124 166578 : MSStageTrip::getVehicles(MSVehicleControl& vehControl, MSTransportable* transportable, const MSEdge* origin) {
125 : std::vector<SUMOVehicleParameter*> pars;
126 333282 : for (StringTokenizer st(myVTypes); st.hasNext();) {
127 126 : pars.push_back(new SUMOVehicleParameter());
128 252 : pars.back()->vtypeid = st.next();
129 126 : pars.back()->parametersSet |= VEHPARS_VTYPE_SET;
130 126 : pars.back()->departProcedure = DepartDefinition::TRIGGERED;
131 252 : pars.back()->id = transportable->getID() + "_" + toString(pars.size() - 1);
132 166578 : }
133 166578 : if (pars.empty()) {
134 166457 : if ((myModeSet & SVC_PASSENGER) != 0) {
135 1852 : pars.push_back(new SUMOVehicleParameter());
136 3704 : pars.back()->id = transportable->getID() + "_0";
137 1852 : pars.back()->departProcedure = DepartDefinition::TRIGGERED;
138 : }
139 166457 : if ((myModeSet & SVC_TAXI) != 0) {
140 502 : for (const auto& item : MSDevice_Taxi::getTaxiTypes()) {
141 277 : pars.push_back(new SUMOVehicleParameter());
142 277 : pars.back()->vtypeid = item.second;
143 831 : pars.back()->id = transportable->getID() + "_taxi_" + item.second;
144 277 : pars.back()->line = "taxi";
145 : }
146 : }
147 166457 : if ((myModeSet & SVC_BICYCLE) != 0) {
148 37 : pars.push_back(new SUMOVehicleParameter());
149 37 : pars.back()->vtypeid = DEFAULT_BIKETYPE_ID;
150 74 : pars.back()->id = transportable->getID() + "_b0";
151 37 : pars.back()->departProcedure = DepartDefinition::TRIGGERED;
152 : }
153 : }
154 333156 : ConstMSRoutePtr const routeDummy = std::make_shared<MSRoute>(transportable->getID() + "_0", ConstMSEdgeVector({ origin }), false, nullptr, StopParVector());
155 : std::vector<SUMOVehicle*> result;
156 168870 : for (SUMOVehicleParameter* vehPar : pars) {
157 2292 : const bool isTaxi = vehPar->line == "taxi" && (myModeSet & SVC_TAXI) != 0;
158 2292 : if (myDepartPos != 0) {
159 156 : vehPar->departPosProcedure = DepartPosDefinition::GIVEN;
160 156 : vehPar->departPos = myDepartPos;
161 156 : vehPar->parametersSet |= VEHPARS_DEPARTPOS_SET;
162 : }
163 2292 : vehPar->parametersSet |= VEHPARS_ARRIVALPOS_SET;
164 2292 : vehPar->arrivalPosProcedure = ArrivalPosDefinition::GIVEN;
165 2292 : vehPar->parametersSet |= VEHPARS_ARRIVALSPEED_SET;
166 2292 : vehPar->arrivalSpeedProcedure = ArrivalSpeedDefinition::GIVEN;
167 2292 : vehPar->arrivalSpeed = 0;
168 2292 : MSVehicleType* type = vehControl.getVType(vehPar->vtypeid);
169 2292 : if (type->getVehicleClass() != SVC_IGNORING && (origin->getPermissions() & type->getVehicleClass()) == 0 && !isTaxi) {
170 120 : WRITE_WARNINGF(TL("Ignoring vehicle type '%' when routing person '%' because it is not allowed on the start edge."), type->getID(), transportable->getID());
171 40 : delete vehPar;
172 : } else {
173 4504 : result.push_back(vehControl.buildVehicle(vehPar, routeDummy, type, !MSGlobals::gCheckRoutes));
174 : }
175 : }
176 166578 : if (result.empty()) {
177 : // walking only but may use access infrastructure
178 164413 : result.push_back(nullptr);
179 : }
180 166578 : return result;
181 166578 : }
182 :
183 :
184 : const std::string
185 166578 : MSStageTrip::reroute(const SUMOTime time, MSTransportableRouter& router, MSTransportable* const transportable,
186 : MSStage* previous, const MSEdge* origin, const MSEdge* destination, std::vector<MSStage*>& stages) {
187 166578 : if (origin->isTazConnector() && origin->getSuccessors().size() == 0) {
188 : // previous stage ended at a taz sink-edge
189 296 : origin = transportable->getNextStage(-1)->getDestination();
190 : }
191 166578 : MSVehicleControl& vehControl = MSNet::getInstance()->getVehicleControl();
192 : double minCost = std::numeric_limits<double>::max();
193 : std::vector<MSTransportableRouter::TripItem> minResult;
194 : SUMOVehicle* minVehicle = nullptr;
195 : // pre-collect candidate vehicles under lock (buildVehicle touches shared counters)
196 : #ifndef THREAD_POOL
197 : #ifdef HAVE_FOX
198 166578 : myVehCtrlMutex.lock();
199 : #endif
200 : #endif
201 166578 : std::vector<SUMOVehicle*> vehicles = getVehicles(vehControl, transportable, origin);
202 : #ifndef THREAD_POOL
203 : #ifdef HAVE_FOX
204 166578 : myVehCtrlMutex.unlock();
205 : #endif
206 : #endif
207 333243 : for (SUMOVehicle* vehicle : vehicles) {
208 : std::vector<MSTransportableRouter::TripItem> result;
209 166665 : double departPos = previous->getArrivalPos();
210 : MSStoppingPlace* const prevStop = previous->getDestinationStop();
211 166665 : if (MSGlobals::gUseMesoSim && prevStop != nullptr) {
212 207 : departPos = (prevStop->getBeginLanePosition() + prevStop->getEndLanePosition()) / 2.;
213 : }
214 352951 : if (router.compute(origin, destination, departPos, prevStop == nullptr ? "" : prevStop->getID(),
215 302730 : myArrivalPos, myDestinationStop == nullptr ? "" : myDestinationStop->getID(),
216 166665 : transportable->getMaxSpeed() * myWalkFactor, vehicle, transportable->getVTypeParameter(), myModeSet, time, result)) {
217 : double totalCost = 0;
218 358789 : for (const MSTransportableRouter::TripItem& item : result) {
219 192215 : totalCost += item.cost;
220 : }
221 166574 : if (totalCost < minCost) {
222 : minCost = totalCost;
223 : minResult.swap(result);
224 : std::swap(minVehicle, vehicle);
225 : }
226 : }
227 166665 : if (vehicle != nullptr) {
228 : #ifndef THREAD_POOL
229 : #ifdef HAVE_FOX
230 94 : myVehCtrlMutex.lock();
231 : #endif
232 : #endif
233 94 : vehControl.deleteVehicle(vehicle, true);
234 : vehControl.discountRoutingVehicle();
235 : #ifndef THREAD_POOL
236 : #ifdef HAVE_FOX
237 94 : myVehCtrlMutex.unlock();
238 : #endif
239 : #endif
240 : }
241 166665 : }
242 166578 : if (minCost != std::numeric_limits<double>::max()) {
243 166499 : const bool isTaxi = minVehicle != nullptr && (myModeSet & SVC_TAXI) != 0 && minVehicle->getParameter().line == "taxi";
244 : bool carUsed = false;
245 358590 : for (std::vector<MSTransportableRouter::TripItem>::iterator it = minResult.begin(); it != minResult.end(); ++it) {
246 192091 : if (!it->edges.empty()) {
247 172495 : MSStoppingPlace* bs = MSNet::getInstance()->getStoppingPlace(it->destStop);
248 172495 : double localArrivalPos = bs != nullptr ? bs->getAccessPos(it->edges.back()) : it->arrivalPos;
249 172495 : const MSEdge* const first = it->edges.front();
250 172495 : const MSEdge* const rideOrigin = origin->isTazConnector() && stages.empty() ? first : nullptr;
251 172495 : if (it + 1 == minResult.end() && myHaveArrivalPos) {
252 5569 : localArrivalPos = myArrivalPos;
253 : }
254 172495 : if (it->line == "") {
255 : // determine walk departPos
256 167488 : double depPos = previous->getArrivalPos();
257 167488 : if (previous->getDestinationStop() != nullptr) {
258 22413 : depPos = previous->getDestinationStop()->getAccessPos(first, first->getLanes()[0]->getRNG());
259 145075 : } else if (origin->isTazConnector()) {
260 : // walk the whole length of the first edge
261 90 : if (std::find(first->getPredecessors().begin(), first->getPredecessors().end(), origin) != first->getPredecessors().end()) {
262 : depPos = 0;
263 : } else {
264 : depPos = first->getLength();
265 : }
266 144985 : } else if (previous->getDestination() != first) {
267 54 : if ((previous->getDestination()->getToJunction() == first->getToJunction())
268 54 : || (previous->getDestination()->getFromJunction() == first->getToJunction())) {
269 : depPos = first->getLength();
270 : } else {
271 : depPos = 0.;
272 : }
273 : }
274 167488 : if (destination->isTazConnector()) {
275 : // walk the whole length of the last edge
276 897 : const MSEdge* last = it->edges.back();
277 897 : if (std::find(last->getSuccessors().begin(), last->getSuccessors().end(), destination) != last->getSuccessors().end()) {
278 : localArrivalPos = last->getLength();
279 : } else {
280 : localArrivalPos = 0;
281 : }
282 : }
283 167488 : previous = new MSStageWalking(transportable->getID(), it->edges, bs, myDuration, mySpeed, depPos, localArrivalPos, myDepartPosLat);
284 167488 : previous->setParameters(*this);
285 167488 : previous->setCosts(it->cost);
286 : previous->setTrip(this);
287 167488 : stages.push_back(previous);
288 5007 : } else if (isTaxi && it->line == minVehicle->getID()) {
289 228 : const ConstMSEdgeVector& prevEdges = previous->getEdges();
290 228 : if (prevEdges.size() >= 2 && previous->getDestinationStop() == nullptr) {
291 : // determine walking direction and let the previous
292 : // stage end after entering its final edge
293 6 : const MSEdge* last = prevEdges.back();
294 6 : const MSEdge* prev = prevEdges[prevEdges.size() - 2];
295 6 : if (last->getFromJunction() == prev->getToJunction() || prev->getFromJunction() == last->getFromJunction()) {
296 : previous->setArrivalPos(MIN2(last->getLength(), 10.0));
297 : } else {
298 6 : previous->setArrivalPos(MAX2(0.0, last->getLength() - 10));
299 : }
300 : }
301 684 : previous = new MSStageDriving(rideOrigin, it->edges.back(), bs, localArrivalPos, 0.0, std::vector<std::string>({ "taxi" }), myGroup);
302 228 : previous->setParameters(*this);
303 228 : previous->setCosts(it->cost);
304 : previous->setTrip(this);
305 228 : stages.push_back(previous);
306 5007 : } else if (minVehicle != nullptr && it->line == minVehicle->getID()) {
307 5415 : previous = new MSStageDriving(rideOrigin, it->edges.back(), bs, localArrivalPos, 0.0, std::vector<std::string>({ it->line }));
308 1805 : previous->setParameters(*this);
309 1805 : previous->setCosts(it->cost);
310 : previous->setTrip(this);
311 1805 : stages.push_back(previous);
312 1805 : minVehicle->replaceRouteEdges(it->edges, -1, 0, "person:" + transportable->getID(), true);
313 1805 : minVehicle->setArrivalPos(localArrivalPos);
314 1805 : const_cast<SUMOVehicleParameter&>(minVehicle->getParameter()).arrivalPos = localArrivalPos;
315 : // defer addVehicle to main thread (called from setArrived after parallel routing completes)
316 1805 : myVehicleToAdd = minVehicle;
317 : carUsed = true;
318 : } else {
319 2974 : const std::string line = OptionsCont::getOptions().getBool("persontrip.ride-public-line") ? it->line : LINE_ANY;
320 8922 : previous = new MSStageDriving(rideOrigin, it->edges.back(), bs, localArrivalPos, 0.0, std::vector<std::string>({ line }), myGroup, it->intended, TIME2STEPS(it->depart));
321 2974 : previous->setParameters(*this);
322 2974 : previous->setCosts(it->cost);
323 : previous->setTrip(this);
324 2974 : stages.push_back(previous);
325 : }
326 : }
327 : }
328 166499 : if (wasSet(VEHPARS_ARRIVALPOS_SET) && !stages.empty()) {
329 : // mark the last stage
330 1181 : stages.back()->markSet(VEHPARS_ARRIVALPOS_SET);
331 : }
332 : setCosts(minCost);
333 166499 : if (minVehicle != nullptr && (isTaxi || !carUsed)) {
334 : #ifndef THREAD_POOL
335 : #ifdef HAVE_FOX
336 353 : myVehCtrlMutex.lock();
337 : #endif
338 : #endif
339 353 : vehControl.deleteVehicle(minVehicle, true);
340 : vehControl.discountRoutingVehicle();
341 : #ifndef THREAD_POOL
342 : #ifdef HAVE_FOX
343 353 : myVehCtrlMutex.unlock();
344 : #endif
345 : #endif
346 : }
347 : } else {
348 : // append stage so the GUI won't crash due to inconsistent state
349 79 : previous = new MSStageWalking(transportable->getID(), ConstMSEdgeVector({ origin, destination }), myDestinationStop, myDuration, mySpeed, previous->getArrivalPos(), myArrivalPos, myDepartPosLat);
350 79 : previous->setParameters(*this);
351 79 : stages.push_back(previous);
352 79 : if (MSGlobals::gCheckRoutes) { // if not pedestrians will teleport
353 159 : return "No connection found between " + getOriginDescription() + " and " + getDestinationDescription() + " for person '" + transportable->getID() + "'.";
354 : }
355 : }
356 166525 : if (stages.empty()) {
357 : // append stage so the GUI won't crash due to inconsistent state
358 14 : if (myOriginStop != nullptr && myOriginStop == myDestinationStop) {
359 28 : stages.push_back(new MSStageWaiting(destination, myDestinationStop, 0, -1, previous->getArrivalPos(), "sameStop", false));
360 : } else {
361 0 : stages.push_back(new MSStageWalking(transportable->getID(), ConstMSEdgeVector({ origin, destination }), myDestinationStop, myDuration, mySpeed, previous->getArrivalPos(), myArrivalPos, myDepartPosLat));
362 0 : if (MSGlobals::gCheckRoutes) { // if not pedestrians will teleport
363 0 : return "Empty route between " + getOriginDescription() + " and " + getDestinationDescription() + " for person '" + transportable->getID() + "'.";
364 : }
365 : }
366 : }
367 166525 : return "";
368 167034 : }
369 :
370 :
371 : const std::string
372 166497 : MSStageTrip::setArrived(MSNet* net, MSTransportable* transportable, SUMOTime now, const bool vehicleArrived) {
373 332994 : MSStage::setArrived(net, transportable, now, vehicleArrived);
374 : std::vector<MSStage*> stages;
375 : std::string result;
376 166497 : if (!myComputedStages.empty()) {
377 : // routing was done in proceed() (serial or parallel)
378 : stages.swap(myComputedStages);
379 166497 : result = myRoutingError;
380 : myRoutingError = "";
381 : } else {
382 : // TRIP is at index 0 with no preceding stage, so proceed() was never called
383 0 : myDepartPos = transportable->getParameter().departPos;
384 0 : if (transportable->getParameter().departPosProcedure == DepartPosDefinition::RANDOM) {
385 : // TODO we should probably use the rng of the lane here
386 0 : myDepartPos = RandHelper::rand(myOrigin->getLength());
387 : }
388 0 : MSStageWaiting start(myOrigin, myOriginStop, -1, transportable->getParameter().depart, myDepartPos, "start", true);
389 0 : result = reroute(transportable->getParameter().depart, net->getIntermodalRouter(0), transportable, &start, myOrigin, myDestination, stages);
390 0 : }
391 166497 : if (myVehicleToAdd != nullptr) {
392 1805 : net->getVehicleControl().addVehicle(myVehicleToAdd->getID(), myVehicleToAdd);
393 1805 : myVehicleToAdd = nullptr;
394 : }
395 : int idx = 1;
396 338960 : for (MSStage* stage : stages) {
397 172463 : transportable->appendStage(stage, idx++);
398 : }
399 166497 : return result;
400 166497 : }
401 :
402 :
403 : void
404 166498 : MSStageTrip::proceed(MSNet* net, MSTransportable* transportable, SUMOTime now, MSStage* previous) {
405 166498 : myDepartPos = previous->getArrivalPos();
406 : #ifndef THREAD_POOL
407 : #ifdef HAVE_FOX
408 166498 : MFXWorkerThread::Pool& threadPool = MSNet::getInstance()->getEdgeControl().getThreadPool();
409 166498 : if (threadPool.size() > 0) {
410 4512 : MSRoutingEngine::getIntermodalRouterTT(transportable->getRNGIndex());
411 4512 : threadPool.add(new TripRoutingTask(*this, transportable, now, previous));
412 4512 : net->getPersonControl().addPendingRouting(transportable);
413 4512 : return;
414 : }
415 : #endif
416 : #endif
417 161986 : myRoutingError = reroute(now, net->getIntermodalRouter(0), transportable, previous, myOrigin, myDestination, myComputedStages);
418 161986 : transportable->proceed(net, now);
419 : }
420 :
421 :
422 : std::string
423 53 : MSStageTrip::getOriginDescription() const {
424 53 : return (myOriginStop != nullptr
425 113 : ? toString(myOriginStop->getElement()) + " '" + myOriginStop->getID()
426 99 : : "edge '" + myOrigin->getID()) + "'";
427 : }
428 :
429 : std::string
430 53 : MSStageTrip::getDestinationDescription() const {
431 53 : return (myDestinationStop != nullptr
432 121 : ? toString(myDestinationStop->getElement()) + " '" + myDestinationStop->getID()
433 91 : : "edge '" + myDestination->getID()) + "'";
434 : }
435 :
436 : std::string
437 0 : MSStageTrip::getStageSummary(const bool) const {
438 0 : return "trip from " + getOriginDescription() + " to " + getDestinationDescription();
439 : }
440 :
441 : void
442 1623 : MSStageTrip::routeOutput(const bool /*isPerson*/, OutputDevice& os, const bool /*withRouteLength*/, const MSStage* const previous, const bool /*withTiming*/, const bool /*saveState*/) const {
443 1623 : if (myArrived < 0) {
444 10 : const bool walkFactorSet = myWalkFactor != OptionsCont::getOptions().getFloat("persontrip.walkfactor");
445 10 : const bool groupSet = myGroup != OptionsCont::getOptions().getString("persontrip.default.group");
446 : // could still be a persontrip but most likely it was a walk in the input
447 10 : SumoXMLTag tag = myModeSet == 0 && !walkFactorSet && !groupSet ? SUMO_TAG_WALK : SUMO_TAG_PERSONTRIP;
448 10 : os.openTag(tag);
449 10 : if (previous == nullptr || previous->getStageType() == MSStageType::WAITING_FOR_DEPART) {
450 4 : os.writeAttr(SUMO_ATTR_FROM, myOrigin->getID());
451 : }
452 10 : if (myDestinationStop == nullptr) {
453 10 : os.writeAttr(SUMO_ATTR_TO, myDestination->getID());
454 10 : if (wasSet(VEHPARS_ARRIVALPOS_SET)) {
455 6 : os.writeAttr(SUMO_ATTR_ARRIVALPOS, myArrivalPos);
456 : }
457 : } else {
458 0 : os.writeAttr(toString(myDestinationStop->getElement()), myDestinationStop->getID());
459 : }
460 : std::vector<std::string> modes;
461 10 : if ((myModeSet & SVC_PASSENGER) != 0) {
462 4 : modes.push_back("car");
463 : }
464 10 : if ((myModeSet & SVC_BICYCLE) != 0) {
465 0 : modes.push_back("bicycle");
466 : }
467 10 : if ((myModeSet & SVC_TAXI) != 0) {
468 0 : modes.push_back("taxi");
469 : }
470 10 : if ((myModeSet & SVC_BUS) != 0) {
471 0 : modes.push_back("public");
472 : }
473 10 : if (modes.size() > 0) {
474 2 : os.writeAttr(SUMO_ATTR_MODES, modes);
475 : }
476 10 : if (myVTypes.size() > 0) {
477 0 : os.writeAttr(SUMO_ATTR_VTYPES, myVTypes);
478 : }
479 10 : if (groupSet) {
480 0 : os.writeAttr(SUMO_ATTR_GROUP, myGroup);
481 : }
482 10 : if (walkFactorSet) {
483 0 : os.writeAttr(SUMO_ATTR_WALKFACTOR, myWalkFactor);
484 : }
485 20 : if (OptionsCont::getOptions().getBool("vehroute-output.cost")) {
486 0 : os.writeAttr(SUMO_ATTR_COST, getCosts());
487 : }
488 10 : os.closeTag();
489 10 : }
490 1623 : }
491 :
492 :
493 : /* -------------------------------------------------------------------------
494 : * MSStageTrip::TripRoutingTask - methods
495 : * ----------------------------------------------------------------------- */
496 : #ifndef THREAD_POOL
497 : #ifdef HAVE_FOX
498 : void
499 4512 : MSStageTrip::TripRoutingTask::run(MFXWorkerThread* context) {
500 : MSTransportableRouter& router = static_cast<MSEdgeControl::WorkerThread*>(context)->getIntermodalRouter();
501 4512 : myStage.myRoutingError = myStage.reroute(myTime, router, myTransportable, myPrevious, myStage.myOrigin, myStage.myDestination, myStage.myComputedStages);
502 4512 : }
503 : #endif
504 : #endif
505 :
506 :
507 : /****************************************************************************/
|