Eclipse SUMO - Simulation of Urban MObility
Loading...
Searching...
No Matches
MSBaseVehicle.cpp
Go to the documentation of this file.
1/****************************************************************************/
2// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3// Copyright (C) 2001-2025 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/****************************************************************************/
21// A base class for vehicle implementations
22/****************************************************************************/
23#include <config.h>
24
25#include <iostream>
26#include <cassert>
27#include <algorithm>
28#include <functional>
36#include <mesosim/MELoop.h>
37#include <mesosim/MEVehicle.h>
53#include "MSEventControl.h"
54#include "MSGlobals.h"
55#include "MSVehicleControl.h"
56#include "MSVehicleType.h"
57#include "MSEdge.h"
58#include "MSLane.h"
59#include "MSMoveReminder.h"
61#include "MSNet.h"
62#include "MSStop.h"
63#include "MSParkingArea.h"
64#include "MSInsertionControl.h"
65#include "MSStopOptimizer.h"
66#include "MSBaseVehicle.h"
67
68//#define DEBUG_REROUTE
69//#define DEBUG_ADD_STOP
70//#define DEBUG_COND (getID() == "")
71//#define DEBUG_COND (true)
72//#define DEBUG_REPLACE_ROUTE
73#define DEBUG_COND (isSelected())
74
75// ===========================================================================
76// static members
77// ===========================================================================
79std::vector<MSTransportable*> MSBaseVehicle::myEmptyTransportableVector;
80#ifdef _DEBUG
81std::set<std::string> MSBaseVehicle::myShallTraceMoveReminders;
82#endif
84
85// ===========================================================================
86// Influencer method definitions
87// ===========================================================================
88
91
92// ===========================================================================
93// method definitions
94// ===========================================================================
95
96double
98 throw ProcessError("getPreviousSpeed() is not available for non-MSVehicles.");
99}
100
101
103 MSVehicleType* type, const double speedFactor) :
104 SUMOVehicle(pars->id),
105 myParameter(pars),
106 myRoute(route),
107 myType(type),
108 myCurrEdge(route->begin()),
109 myChosenSpeedFactor(pars->speedFactor < 0 ? speedFactor : pars->speedFactor),
111 myPersonDevice(nullptr),
112 myContainerDevice(nullptr),
113 myEnergyParams(nullptr),
115 myDepartPos(-1),
116 myArrivalPos(-1),
117 myArrivalLane(-1),
120 myOdometer(0.),
122 myRoutingMode(libsumo::ROUTING_MODE_DEFAULT),
124 myRandomSeed(RandHelper::murmur3_32(pars->id, RandHelper::getSeed())),
125 myEdgeWeights(nullptr)
126#ifdef _DEBUG
127 , myTraceMoveReminders(myShallTraceMoveReminders.count(pars->id) > 0)
128#endif
129{
130 if ((*myRoute->begin())->isTazConnector() || myRoute->getLastEdge()->isTazConnector()) {
132 }
133 if ((pars->parametersSet & VEHPARS_FORCE_REROUTE) == 0) {
135 }
138}
139
140
142 delete myEdgeWeights;
143 if (myParameter->repetitionNumber == -1) {
144 // this is not a flow (flows call checkDist in MSInsertionControl::determineCandidates)
146 }
147 for (MSVehicleDevice* dev : myDevices) {
148 delete dev;
149 }
150 delete myEnergyParams;
151 delete myParkingMemory;
152 delete myChargingMemory;
154 delete myParameter;
155}
156
157
158void
160 // the check for an instance is needed for the unit tests which do not construct a network
161 // TODO Optimize for speed and there should be a better way to check whether a vehicle is part of a flow
162 if (MSNet::hasInstance() && !MSNet::getInstance()->hasFlow(getFlowID())) {
163 myRoute->checkRemoval();
164 }
165}
166
167
168std::string
170 return getID().substr(0, getID().rfind('.'));
171}
172
173
174void
177 for (MSVehicleDevice* dev : myDevices) {
178 myMoveReminders.push_back(std::make_pair(dev, 0.));
179 }
181 // ensure we have the emission parameters even if we don't have the device
183 }
184}
185
186
187void
188MSBaseVehicle::setID(const std::string& /*newID*/) {
189 throw ProcessError(TL("Changing a vehicle ID is not permitted"));
190}
191
194 return *myParameter;
195}
196
197
198void
200 delete myParameter;
201 myParameter = newParameter;
202}
203
204
205bool
209
210double
214
215
216const MSEdge*
217MSBaseVehicle::succEdge(int nSuccs) const {
218 if (myCurrEdge + nSuccs < myRoute->end() && std::distance(myCurrEdge, myRoute->begin()) <= nSuccs) {
219 return *(myCurrEdge + nSuccs);
220 } else {
221 return nullptr;
222 }
223}
224
225
226const MSEdge*
228 return *myCurrEdge;
229}
230
231
232const std::set<SUMOTrafficObject::NumericalID>
234 std::set<SUMOTrafficObject::NumericalID> result;
235 for (auto e = myCurrEdge; e != myRoute->end(); ++e) {
236 result.insert((*e)->getNumericalID());
237 }
238 return result;
239}
240
241
242bool
244 if (stop == nullptr) {
245 return false;
246 }
247 for (const MSStop& s : myStops) {
248 if (s.busstop == stop
249 || s.containerstop == stop
250 || s.parkingarea == stop
251 || s.chargingStation == stop) {
252 return true;
253 }
254 }
255 return false;
256}
257
258bool
260 for (const MSStop& s : myStops) {
261 if (&s.lane->getEdge() == edge) {
262 return true;
263 }
264 }
265 return myRoute->getLastEdge() == edge;
266}
267
268
269bool
270MSBaseVehicle::reroute(SUMOTime t, const std::string& info, SUMOAbstractRouter<MSEdge, SUMOVehicle>& router, const bool onInit, const bool withTaz, const bool silent, const MSEdge* sink) {
271 // check whether to reroute
272 const MSEdge* source = nullptr;
273 if (onInit) {
274 if (withTaz) {
275 source = MSEdge::dictionary(myParameter->fromTaz + "-source");
276 if (source == nullptr) {
277 source = myRoute->getEdges().front();
278 }
279 } else {
280 source = myRoute->getEdges().front();
281 }
282 } else {
283 source = *getRerouteOrigin();
284 }
285 if (sink == nullptr) {
286 sink = withTaz ? MSEdge::dictionary(myParameter->toTaz + "-sink") : myRoute->getLastEdge();
287 if (sink == nullptr) {
288 sink = myRoute->getLastEdge();
289 }
290 }
291 ConstMSEdgeVector oldEdgesRemaining(source == *myCurrEdge ? myCurrEdge : myCurrEdge + 1, myRoute->end());
292 ConstMSEdgeVector edges;
293 if (source != sink || !sink->prohibits(this)) {
294 edges.push_back(source);
295 }
296 std::vector<StopEdgeInfo> stops;
297 std::set<int> jumps;
298
299
300 double sourcePos = onInit ? 0 : getPositionOnLane();
301#ifdef DEBUG_REROUTE
302 if (DEBUG_COND) {
303 std::cout << " curEdge=" << (*myCurrEdge)->getID() << " source=" << source->getID() << " sourcePos=" << sourcePos << " lane=" << Named::getIDSecure(getLane()) << " departPos=" << myParameter->departPos << " oldEdgesRemaining=" << toString(oldEdgesRemaining) << "\n";
304 }
305#endif
307 sourcePos = myParameter->departPos;
308 } else if (getLane() != nullptr && source != &getLane()->getEdge()) {
309 // routing starts on the next edge
310 sourcePos = 0;
311 }
312 if (myParameter->via.size() == 0) {
313 double firstPos = INVALID_DOUBLE;
314 double lastPos = INVALID_DOUBLE;
315 stops = getStopEdges(firstPos, lastPos, jumps);
316 if (stops.size() > 0) {
318 sourcePos = getNextStop().pars.endPos;
319 }
320 if ( !isStopped() && myStops.front().pars.speed == 0) {
321 sourcePos += getBrakeGap();
322 }
323 // avoid superfluous waypoints for first and last edge
324 const bool skipFirst = stops.front().edge == source && (source != getEdge() || sourcePos <= firstPos + NUMERICAL_EPS);
325#ifdef DEBUG_REROUTE
326 if (DEBUG_COND) {
327 std::cout << SIMTIME << " reroute " << info << " veh=" << getID() << " lane=" << Named::getIDSecure(getLane())
328 << " source=" << source->getID() << " sourcePos=" << sourcePos << " firstPos=" << firstPos << " arrivalPos=" << myArrivalPos << " lastPos=" << lastPos
329 << " route=" << toString(myRoute->getEdges()) << " skipFirst=" << skipFirst << "\n";
330 }
331#endif
332 if (stops.size() == 1 && skipFirst) {
333 stops.clear();
334 } else if (skipFirst) {
335 sourcePos = stops.front().pos;
336 stops.erase(stops.begin());
337 }
338 }
339 } else {
340 std::set<const MSEdge*> jumpEdges;
341 std::map<const MSEdge*, StopEdgeInfo> stopsOnVia;
342 for (const MSStop& stop : myStops) {
343 if (stop.pars.jump >= 0) {
344 jumpEdges.insert(*stop.edge);
345 }
346 auto itsov = stopsOnVia.find(*stop.edge);
347 if (itsov == stopsOnVia.end()) {
348 stopsOnVia.insert({*stop.edge, StopEdgeInfo(*stop.edge, stop.pars.priority, stop.getArrivalFallback(), stop.getEndPos(*this))});
349 } else {
350 itsov->second.priority = addStopPriority(itsov->second.priority, stop.pars.priority);
351 }
352 }
353 // via takes precedence over stop edges
354 // there is a consistency check in MSRouteHandler::addStop that warns when a stop edge is not part of the via edges
355 for (std::vector<std::string>::const_iterator it = myParameter->via.begin(); it != myParameter->via.end(); ++it) {
356 MSEdge* viaEdge = MSEdge::dictionary(*it);
357 if ((viaEdge == source && it == myParameter->via.begin()) || (viaEdge == sink && myParameter->via.end() - it == 1)) {
358 continue;
359 }
360 assert(viaEdge != 0);
361 if (!viaEdge->isTazConnector() && viaEdge->allowedLanes(getVClass()) == nullptr) {
362 throw ProcessError(TLF("Vehicle '%' is not allowed on any lane of via edge '%'.", getID(), viaEdge->getID()));
363 }
364 auto itsov = stopsOnVia.find(viaEdge);
365 const double priority = (itsov == stopsOnVia.end() ? -1 : itsov->second.priority);
366 const SUMOTime arrival = (itsov == stopsOnVia.end() ? -1 : itsov->second.arrival);
367 const double pos = (itsov == stopsOnVia.end() ? 0 : itsov->second.pos);
368 stops.push_back(StopEdgeInfo(viaEdge, priority, arrival, pos));
369 // @todo determine wether the viaEdge is also used by a stop and then use the stop priority here
370 if (jumpEdges.count(viaEdge) != 0) {
371 jumps.insert((int)stops.size());
372 }
373 }
374 }
375 if ((stops.size() == 0 && (source != sink || sourcePos > myArrivalPos))
376 || ((stops.size() != 0) && (stops.back().edge != sink || myArrivalPos < stops.back().pos))) {
377 stops.push_back(StopEdgeInfo(sink, -1, -1, myArrivalPos, true));
378 }
379#ifdef DEBUG_REROUTE
380 if (DEBUG_COND) {
381 std::cout << SIMTIME << " reroute veh=" << getID() << " onInit=" << onInit << " source=" << source->getID() << " sink=" << sink->getID() << " sourcePos=" << sourcePos << " arrivalPos=" << myArrivalPos << " stops:\n";
382 for (auto item : stops) {
383 std::cout << " e=" << item.edge->getID() << " pos=" << item.pos << " isSink=" << item.isSink << "\n";
384 }
385 }
386#endif
387 int stopIndex = -1;
388 auto stopIt = myStops.begin();
389 SUMOTime startTime = t;
390 bool hasSkipped = false;
391 const double origSourcePos = sourcePos;
392 const MSEdge* origSource = source;
394 for (auto& stopEdgeInfo : stops) {
395 const MSEdge* const stopEdge = stopEdgeInfo.edge;
396 const double priority = stopEdgeInfo.priority;
397 stopIndex++;
399 if (jumps.count(stopIndex) != 0) {
400 edges.push_back(stopEdge);
401 source = stopEdge;
402 continue;
403 }
404 // !!! need to adapt t here
405 router.compute(source, sourcePos, stopEdge, stopEdgeInfo.pos, this, t, into, silent || priority >= 0);
406#ifdef DEBUG_REROUTE
407 if (DEBUG_COND) {
408 std::cout << SIMTIME << " reroute veh=" << getID() << " source=" << source->getID() << " sourcePos=" << sourcePos << " target=" << stopEdgeInfo.edge->getID() << " targetPos=" << stopEdgeInfo.pos << " edges=" << toString(into) << "\n";
409 }
410#endif
411 if (into.size() > 0) {
412 while (stopIt != myStops.end() && stopIt->pars.edge != stopEdge->getID()) {
413 stopIt++;
414 }
415
416 startTime += TIME2STEPS(router.recomputeCostsPos(into, this, sourcePos, stopEdgeInfo.pos, startTime));
417 if (stopIt != myStops.end()) {
418 if (stopIt->pars.priority >= 0 && info != "device.rerouting") {
419 // consider skipping this stop if it cannot be reached in a timely manner
420 if (stopIt != myStops.end()) {
421 SUMOTime arrival = stopEdgeInfo.arrival;
422 if (arrival > 0) {
423 SUMOTime delay = startTime - arrival;
424 //std::cout << " t=" << time2string(t) << " veh=" << getID() << " info=" << info << " stopIndex=" << stopIndex
425 // << " into=" << toString(into) << " sourcePos=" << sourcePos << " stopPos=" << stopPos
426 // << " startTime=" << time2string(startTime) << " arrival=" << time2string(arrival) << " delay=" << time2string(delay) << "\n";
427 if (delay > 0) {
428 if (delay > maxDelay) {
429 stopEdgeInfo.skipped = true;
430 stopEdgeInfo.delay = delay;
431 hasSkipped = true;
432 continue;
433 }
434 }
435 }
436 }
437 }
438 sourcePos = stopEdgeInfo.pos;
439 startTime += stopIt->getMinDuration(startTime);
440 }
441 edges.pop_back();
442 edges.insert(edges.end(), into.begin(), into.end());
443 if (edges.back()->isTazConnector()) {
444 edges.pop_back();
445 }
446 source = edges.back();
447 stopEdgeInfo.routeIndex = (int)edges.size() - 1;
448 } else {
449 if (priority >= 0) {
450 stopEdgeInfo.skipped = true;
451 hasSkipped = true;
452 continue;
453 } else if (stopEdgeInfo.isSink) {
454 //error = TLF("Vehicle '%' has no valid route from edge '%' to destination edge '%'.", getID(), source->getID(), stopEdge->getID());
455 edges.clear();
456 if (onInit && source == stopEdge && stops.size() == 1 && sourcePos > myArrivalPos) {
457 edges.push_back(stopEdge);
458 WRITE_WARNING(TLF("Vehicle '%' ignores arrivalPos % when driving from edge '%' to edge '%'.", getID(), myArrivalPos, source->getID(), stopEdge->getID()));
459 }
460 } else if (source == stopEdge && stopEdgeInfo.stopPar != nullptr && stopEdgeInfo.stopPar->endPos >= sourcePos) {
461 // special case: no failure on dynamically computed stop position
462 edges.clear();
463 } else {
464 std::string error = TLF("Vehicle '%' has no valid route from edge '%' to stop edge '%'.", getID(), source->getID(), stopEdge->getID());
465 if (MSGlobals::gCheckRoutes || silent) {
466 throw ProcessError(error);
467 } else {
468 WRITE_WARNING(error);
469 edges.push_back(source);
470 source = stopEdge;
471 }
472 }
473 }
474 }
475 if (hasSkipped) {
476 MSStopOptimizer opti(this, router, t, maxDelay);
477 edges = opti.optimizeSkipped(origSource, origSourcePos, stops, edges);
478 for (auto stop : stops) {
479 if (stop.skipped || stop.origEdge != nullptr) {
480 const MSEdge* origEdge = stop.origEdge == nullptr ? stop.edge : stop.origEdge;
481 if (stop.delay > 0) {
482 WRITE_WARNING(TLF("Vehicle '%' skips stop on edge '%' with delay % at time %.", getID(), origEdge->getID(), time2string(stop.delay), time2string(SIMSTEP)));
483 } else if (stop.backtracked) {
484 WRITE_WARNING(TLF("Vehicle '%' skips stop on edge '%' with priority % at time %.", getID(), origEdge->getID(), stop.priority, time2string(SIMSTEP)));
485 } else {
486 WRITE_WARNING(TLF("Vehicle '%' skips unreachable stop on edge '%' with priority % at time %.", getID(), origEdge->getID(), stop.priority, time2string(SIMSTEP)));
487 }
488 }
489 }
490 }
491
492 // router.setHint(myCurrEdge, myRoute->end(), this, t);
493 if (edges.empty() && silent) {
494 return false;
495 }
496 if (!edges.empty() && edges.front()->isTazConnector()) {
497 edges.erase(edges.begin());
498 }
499 if (!edges.empty() && edges.back()->isTazConnector()) {
500 edges.pop_back();
501 }
502 const double routeCost = router.recomputeCosts(edges, this, t);
503 const double previousCost = onInit ? routeCost : router.recomputeCosts(oldEdgesRemaining, this, t);
504 const double savings = previousCost - routeCost;
505 bool savingsOk = onInit || info != "device.rerouting" || gWeightsRandomFactor != 1;
506 if (!savingsOk) {
507 MSDevice_Routing* routingDevice = static_cast<MSDevice_Routing*>(getDevice(typeid(MSDevice_Routing)));
508 assert(routingDevice != 0);
509 savingsOk = routingDevice->sufficientSaving(previousCost, routeCost);
510 if (!savingsOk) {
511 std::string dummyMsg;
512 if (!hasValidRoute(dummyMsg, oldEdgesRemaining.begin(), oldEdgesRemaining.end(), true)) {
513 // the old route is prohibted (i.e. due to temporary permission changes)
514 savingsOk = true;
515 }
516 }
517 }
518 //if (getID() == "43") std::cout << SIMTIME << " pCost=" << previousCost << " cost=" << routeCost
519 // << " onInit=" << onInit
520 // << " prevEdges=" << toString(oldEdgesRemaining)
521 // << " newEdges=" << toString(edges)
522 // << "\n";
523 if (savingsOk) {
524 replaceRouteEdges(edges, routeCost, savings, info, onInit);
525 }
526 // this must be called even if the route could not be replaced
527 if (onInit) {
528 if (edges.empty()) {
530 throw ProcessError(TLF("Vehicle '%' has no valid route.", getID()));
531 } else if (source->isTazConnector()) {
532 WRITE_WARNINGF(TL("Removing vehicle '%' which has no valid route."), getID());
534 return false;
535 }
536 }
539 }
540 return !edges.empty();
541}
542
543
544bool
545MSBaseVehicle::replaceRouteEdges(ConstMSEdgeVector& edges, double cost, double savings, const std::string& info, bool onInit, bool check, bool removeStops, std::string* msgReturn) {
546 if (edges.empty()) {
547 WRITE_WARNINGF(TL("No route for vehicle '%' found."), getID());
548 if (msgReturn != nullptr) {
549 *msgReturn = "No route found";
550 }
551 return false;
552 }
553 // build a new id, first
554 std::string id = getID();
555 if (id[0] != '!') {
556 id = "!" + id;
557 }
558 const std::string idSuffix = id + "!var#";
559 int varIndex = 1;
560 id = idSuffix + toString(varIndex);
561 while (MSRoute::hasRoute(id)) {
562 id = idSuffix + toString(++varIndex);
563 }
564 int oldSize = (int)edges.size();
565 if (!onInit) {
566 const MSEdge* const origin = *getRerouteOrigin();
567 if (origin != *myCurrEdge && edges.front() == origin) {
568 edges.insert(edges.begin(), *myCurrEdge);
569 oldSize = (int)edges.size();
570 }
571 edges.insert(edges.begin(), myRoute->begin(), myCurrEdge);
572 }
573 if (edges == myRoute->getEdges() && haveValidStopEdges(true)) {
574 // re-assign stop iterators when rerouting to a new parkingArea / insertStop
575 return true;
576 }
577 const RGBColor& c = myRoute->getColor();
578 MSRoute* newRoute = new MSRoute(id, edges, false, &c == &RGBColor::DEFAULT_COLOR ? nullptr : new RGBColor(c), StopParVector());
579 newRoute->setCosts(cost);
580 newRoute->setSavings(savings);
581 ConstMSRoutePtr constRoute = std::shared_ptr<MSRoute>(newRoute);
582 if (!MSRoute::dictionary(id, constRoute)) {
583 delete newRoute;
584 if (msgReturn != nullptr) {
585 *msgReturn = "duplicate routeID '" + id + "'";
586 }
587 return false;
588 }
589
590 std::string msg;
591 if (check && !hasValidRoute(msg, constRoute)) {
592 WRITE_WARNINGF(TL("Invalid route replacement for vehicle '%'. %"), getID(), msg);
594 if (msgReturn != nullptr) {
595 *msgReturn = msg;
596 }
597 return false;
598 }
599 }
600 if (!replaceRoute(constRoute, info, onInit, (int)edges.size() - oldSize, false, removeStops, msgReturn)) {
601 return false;
602 }
603 return true;
604}
605
606
607bool
608MSBaseVehicle::replaceRoute(ConstMSRoutePtr newRoute, const std::string& info, bool onInit, int offset, bool addRouteStops, bool removeStops, std::string* msgReturn) {
609 const ConstMSEdgeVector& edges = newRoute->getEdges();
610 // rebuild in-vehicle route information
611 if (onInit) {
612 myCurrEdge = newRoute->begin();
613 } else {
614 MSRouteIterator newCurrEdge = std::find(edges.begin() + offset, edges.end(), *myCurrEdge);
615 if (newCurrEdge == edges.end()) {
616 if (msgReturn != nullptr) {
617 *msgReturn = TLF("current edge '%' not found in new route", (*myCurrEdge)->getID());
618 }
619#ifdef DEBUG_REPLACE_ROUTE
620 if (DEBUG_COND) {
621 std::cout << " newCurrEdge not found\n";
622 }
623#endif
624 return false;
625 }
626 if (getLane() != nullptr) {
627 if (getLane()->getEdge().isInternal() && (
628 (newCurrEdge + 1) == edges.end() || (*(newCurrEdge + 1)) != &(getLane()->getOutgoingViaLanes().front().first->getEdge()))) {
629 if (msgReturn != nullptr) {
630 *msgReturn = TL("Vehicle is on junction-internal edge leading elsewhere");
631 }
632#ifdef DEBUG_REPLACE_ROUTE
633 if (DEBUG_COND) {
634 std::cout << " Vehicle is on junction-internal edge leading elsewhere\n";
635 }
636#endif
637 return false;
638 } else if (getPositionOnLane() > getLane()->getLength()
639 && (myCurrEdge + 1) != myRoute->end()
640 && (newCurrEdge + 1) != edges.end()
641 && *(myCurrEdge + 1) != *(newCurrEdge + 1)) {
642 if (msgReturn != nullptr) {
643 *msgReturn = TL("Vehicle is moving past junction and committed to move to another successor edge");
644 }
645#ifdef DEBUG_REPLACE_ROUTE
646 if (DEBUG_COND) {
647 std::cout << " Vehicle is moving past junction and committed to move to another successor edge\n";
648 }
649#endif
650 return false;
651 }
652 }
653 myCurrEdge = newCurrEdge;
654 }
655 const bool stopsFromScratch = onInit && myRoute->getStops().empty();
656 // assign new route
658 myRoute = newRoute;
659 // update arrival definition
661 // save information that the vehicle was rerouted
663 myStopUntilOffset += myRoute->getPeriod();
665 if (!onInit && isRail() && MSRailSignalControl::hasInstance()) {
666 // we need to update driveways (add/remove reminders) before the next call to MSRailSignalControl::updateSignals
667 //
668 // rerouting may be triggered through
669 // - MoveReminders (executeMove->activateReminders)
670 // - rerouters
671 // - devices (MSDevice_Stationfinder)
672 // - TraCI (changeTarget, replaceStop, ...
673 // - events (MSDevice_Routing::myRerouteCommand, MSDevice_Taxi::triggerDispatch)
674 //
675 // Since activateReminders actively modifies reminders, adding/deleting reminders would create a mess
676 // hence, we use an event to be safe for all case
677
680 }
681#ifdef DEBUG_REPLACE_ROUTE
682 if (DEBUG_COND) {
683 std::cout << SIMTIME << " veh=" << getID() << " replaceRoute info=" << info << " on " << (*myCurrEdge)->getID()
684 << " lane=" << Named::getIDSecure(getLane())
685 << " stopsFromScratch=" << stopsFromScratch
686 << " newSize=" << newRoute->getEdges().size()
687 << " newIndex=" << (myCurrEdge - newRoute->begin())
688 << " edges=" << toString(newRoute->getEdges())
689 << "\n";
690 }
691#endif
692 // remove past stops which are not on the route anymore
693 for (StopParVector::iterator it = myPastStops.begin(); it != myPastStops.end();) {
694 const MSEdge* stopEdge = (it->edge.empty()) ? &MSLane::dictionary(it->lane)->getEdge() : MSEdge::dictionary(it->edge);
695 if (std::find(myRoute->begin(), myRoute->end(), stopEdge) == myRoute->end()) {
696 it = myPastStops.erase(it);
697 } else {
698 ++it;
699 }
700 }
701 // if we did not drive yet it may be best to simply reassign the stops from scratch
702 if (stopsFromScratch) {
703 myStops.clear();
705 } else {
706 // recheck old stops
707 MSRouteIterator searchStart = myCurrEdge;
708 double lastPos = getPositionOnLane() + getBrakeGap();
709 if (getLane() != nullptr && getLane()->isInternal()
710 && myStops.size() > 0 && !myStops.front().lane->isInternal()) {
711 // searchStart is still incoming to the intersection so lastPos
712 // relative to that edge must be adapted
713 lastPos += (*myCurrEdge)->getLength();
714 }
715 int stopIndex = 0;
716 for (std::list<MSStop>::iterator iter = myStops.begin(); iter != myStops.end();) {
717 double endPos = iter->getEndPos(*this);
718#ifdef DEBUG_REPLACE_ROUTE
719 if (DEBUG_COND) {
720 std::cout << " stopEdge=" << iter->lane->getEdge().getID() << " start=" << (searchStart - myCurrEdge) << " endPos=" << endPos << " lastPos=" << lastPos << "\n";
721 }
722#endif
723 if (*searchStart != &iter->lane->getEdge()
724 || endPos + NUMERICAL_EPS < lastPos) {
725 if (searchStart != edges.end() && !iter->reached) {
726 searchStart++;
727 }
728 }
729 lastPos = endPos;
730
731 iter->edge = std::find(searchStart, edges.end(), &iter->lane->getEdge());
732#ifdef DEBUG_REPLACE_ROUTE
733 if (DEBUG_COND) {
734 std::cout << " foundIndex=" << (iter->edge - myCurrEdge) << " end=" << (edges.end() - myCurrEdge) << "\n";
735 }
736#endif
737 if (iter->edge == edges.end() && iter->pars.priority >= 0) {
738 const std::string oldEdge = iter->pars.edge;
739 const std::string oldName = iter->getStoppingPlaceName().first;
740 if (replaceWithAlternative(iter, searchStart, edges.end())) {
741 WRITE_WARNINGF(TL("Vehicle '%' replaced stop on edge '%' (named '%') and now stops at '%' instead; after rerouting (%) at time=%."),
742 getID(), oldEdge, oldName, iter->getDescription(true), info, time2string(SIMSTEP));
743 }
744 }
745 if (iter->edge == edges.end()) {
746 if (!removeStops) {
747 WRITE_ERRORF(TL("Vehicle '%' could not assign stop '%' after rerouting (%) at time=%."), getID(), iter->getDescription(), info, time2string(SIMSTEP));
748 }
749 iter = myStops.erase(iter);
750 continue;
751 } else {
752 setSkips(*iter, stopIndex);
753 searchStart = iter->edge;
754 }
755 ++iter;
756 stopIndex++;
757 }
758 // add new stops
759 if (addRouteStops) {
760 for (StopParVector::const_iterator i = newRoute->getStops().begin(); i != newRoute->getStops().end(); ++i) {
761 std::string error;
763 if (error != "") {
764 WRITE_WARNING(error);
765 }
766 }
767 }
768 }
769 return true;
770}
771
772
773bool
774MSBaseVehicle::replaceWithAlternative(std::list<MSStop>::iterator iter, const MSRouteIterator searchStart, const MSRouteIterator end) {
775 std::pair<std::string, SumoXMLTag> nameTag = iter->getStoppingPlaceName();
776 if (!nameTag.first.empty()) {
777 const std::vector<MSStoppingPlace*>& alternatives = MSNet::getInstance()->getStoppingPlaceAlternatives(nameTag.first, nameTag.second);
778 for (MSStoppingPlace* alt : alternatives) {
779 //std::cout << SIMTIME << " veh=" << getID() << " name=" << nameTag.first << " alt=" << alt->getID() << "\n";
780 if (&alt->getLane().getEdge() == &iter->lane->getEdge()
781 || !alt->getLane().allowsVehicleClass(getVClass())) {
782 continue;
783 }
784 iter->edge = std::find(searchStart, end, &alt->getLane().getEdge());
785 if (iter->edge != end) {
786 iter->replaceStoppingPlace(alt);
787 return true;
788 }
789 }
790 }
791 return false;
792}
793
794
795double
797 return 0;
798}
799
800
801void
807
808
811 const SUMOTime dep = getParameter().depart;
812 if (dep < 0) {
813 return 0;
814 }
815 return hasDeparted() ? getDeparture() - dep : SIMSTEP - dep;
816}
817
818
819bool
821 return succEdge(1) == nullptr;
822}
823
824
825int
827 return (int) std::distance(myRoute->begin(), myCurrEdge);
828}
829
830
831int
833 if (myParameter->arrivalEdge >= 0) {
835 } else {
836 return myRoute->size() - getRoutePosition();
837 }
838}
839
840
841void
843 myCurrEdge = myRoute->begin() + index;
844 const_cast<SUMOVehicleParameter*>(myParameter)->departLaneProcedure = departLaneProcedure;
845 // !!! hack
846 myArrivalPos = (*(myRoute->end() - 1))->getLanes()[0]->getLength();
847}
848
849double
853
854bool
856 if (t->isPerson() && getPersonNumber() >= getVehicleType().getPersonCapacity()) {
857 return false;
858 } else if (!t->isPerson() && getContainerNumber() >= getVehicleType().getContainerCapacity()) {
859 return false;
860 }
861 if (isStopped() && myStops.begin()->pars.permitted.size() > 0
862 && myStops.begin()->pars.permitted.count(t->getID()) == 0) {
863 return false;
864 }
865 MSDevice_Taxi* taxiDevice = static_cast<MSDevice_Taxi*>(getDevice(typeid(MSDevice_Taxi)));
866 if (taxiDevice != nullptr) {
867 return taxiDevice->allowsBoarding(t);
868 }
869 return true;
870}
871
872
873void
875 if (transportable->isPerson()) {
876 if (myPersonDevice == nullptr) {
878 myMoveReminders.insert(myMoveReminders.begin(), std::make_pair(myPersonDevice, 0.));
881 }
882 }
883 myPersonDevice->addTransportable(transportable);
884 } else {
885 if (myContainerDevice == nullptr) {
887 myMoveReminders.insert(myMoveReminders.begin(), std::make_pair(myContainerDevice, 0.));
890 }
891 }
892 myContainerDevice->addTransportable(transportable);
893 }
894 if (myEnergyParams != nullptr) {
896 }
897}
898
899
900bool
902 for (const MSStop& stop : myStops) {
903 if (stop.edge == it && stop.pars.jump >= 0) {
904 return true;
905 } else if (stop.edge > it) {
906 return false;
907 }
908 }
909 return false;
910}
911
912
913bool
914MSBaseVehicle::hasValidRoute(std::string& msg, ConstMSRoutePtr route) const {
916 if (route == nullptr) {
917 route = myRoute;
918 } else {
919 start = route->begin();
920 }
921 const bool checkJumps = route == myRoute; // the edge iterators in the stops are invalid otherwise
922 return hasValidRoute(msg, start, route->end(), checkJumps);
923}
924
925
926bool
927MSBaseVehicle::hasValidRoute(std::string& msg, MSRouteIterator start, MSRouteIterator last, bool checkJumps) const {
928 MSRouteIterator lastValid = last - 1;
929 // check connectivity, first
930 for (MSRouteIterator e = start; e != lastValid; ++e) {
931 const MSEdge& next = **(e + 1);
932 if ((*e)->allowedLanes(next, myType->getVehicleClass()) == nullptr) {
933 if (!checkJumps || !hasJump(e)) {
935 || (!next.hasTransientPermissions() && !(*e)->hasTransientPermissions())) {
936 msg = TLF("No connection between edge '%' and edge '%'.", (*e)->getID(), (*(e + 1))->getID());
937 return false;
938 }
939 }
940 }
941 }
942 // check usable lanes, then
943 for (MSRouteIterator e = start; e != last; ++e) {
944 if ((*e)->prohibits(this)) {
945 msg = TLF("Edge '%' prohibits.", (*e)->getID());
946 return false;
947 }
948 }
949 return true;
950}
951
952
953bool
955 if (!(*myCurrEdge)->isTazConnector()) {
957 msg = TLF("Departure speed for vehicle '%' is too high for the vehicle type '%'.", getID(), myType->getID());
959 return false;
960 }
961 }
962 if (myRoute->getEdges().size() > 0 && !(*myCurrEdge)->prohibits(this)) {
963 myRouteValidity &= ~ROUTE_START_INVALID_PERMISSIONS;
964 return true;
965 } else {
966 msg = TLF("Vehicle '%' is not allowed to depart on any lane of edge '%'.", getID(), (*myCurrEdge)->getID());
968 return false;
969 }
970}
971
972
973int
974MSBaseVehicle::getRouteValidity(bool update, bool silent, std::string* msgReturn) {
975 if (!update) {
976 return myRouteValidity;
977 }
978 // insertion check must be done in any case
979 std::string msg;
980 if (!hasValidRouteStart(msg)) {
982 throw ProcessError(msg);
983 } else if (!silent) {
984 // vehicle will be discarded
985 WRITE_WARNING(msg);
986 } else if (msgReturn != nullptr) {
987 *msgReturn = msg;
988 }
989 }
990 if ((MSGlobals::gCheckRoutes || myRoute->getFirstEdge()->isInternal())
992 // we could check after the first rerouting
994 if (!hasValidRoute(msg, myRoute)) {
996 throw ProcessError(TLF("Vehicle '%' has no valid route. %", getID(), msg));
997 }
998 }
999 myRouteValidity &= ~ROUTE_UNCHECKED;
1000 return myRouteValidity;
1001}
1002
1003
1004bool
1006 for (auto item : myMoveReminders) {
1007 if (item.first == rem) {
1008 return true;
1009 }
1010 }
1011 return false;
1012}
1013
1014
1015void
1017#ifdef _DEBUG
1018 if (myTraceMoveReminders) {
1019 traceMoveReminder("add", rem, pos, true);
1020 }
1021#endif
1022 myMoveReminders.push_back(std::make_pair(rem, pos));
1023}
1024
1025
1026void
1028 for (MoveReminderCont::iterator r = myMoveReminders.begin(); r != myMoveReminders.end(); ++r) {
1029 if (r->first == rem) {
1030#ifdef _DEBUG
1031 if (myTraceMoveReminders) {
1032 traceMoveReminder("remove", rem, 0, false);
1033 }
1034#endif
1035 myMoveReminders.erase(r);
1036 return;
1037 }
1038 }
1039}
1040
1041
1042void
1044 // notifyEnter may cause new reminders to be added so we cannot use an iterator
1045 for (int i = 0; i < (int)myMoveReminders.size();) {
1046 MSMoveReminder* rem = myMoveReminders[i].first;
1047 const double remPos = myMoveReminders[i].second;
1048 // skip the reminder if it is a lane reminder but not for my lane (indicated by rem->second > 0.)
1049 if (rem->getLane() != nullptr && remPos > 0.) {
1050#ifdef _DEBUG
1051 if (myTraceMoveReminders) {
1052 traceMoveReminder("notifyEnter_skipped", rem, remPos, true);
1053 }
1054#endif
1055 ++i;
1056 } else {
1057 if (rem->notifyEnter(*this, reason, enteredLane)) {
1058#ifdef _DEBUG
1059 if (myTraceMoveReminders) {
1060 traceMoveReminder("notifyEnter", rem, remPos, true);
1061 }
1062#endif
1063 ++i;
1064 } else {
1065#ifdef _DEBUG
1066 if (myTraceMoveReminders) {
1067 traceMoveReminder("notifyEnter", rem, remPos, false);
1068 }
1069#endif
1070 myMoveReminders.erase(myMoveReminders.begin() + i);
1071 }
1072 }
1073 }
1074}
1075
1076
1077bool
1079 return isRailway(getVClass()) || isRailway(getCurrentEdge()->getPermissions());
1080}
1081
1082void
1084 if (myRoute->getLastEdge()->isTazConnector()) {
1085 return;
1086 }
1087 const int arrivalEdgeIndex = MIN2(myParameter->arrivalEdge, (int)myRoute->getEdges().size() - 1);
1088 if (arrivalEdgeIndex != myParameter->arrivalEdge) {
1089 if (!(onInit && myParameter->wasSet(VEHPARS_FORCE_REROUTE))) {
1090 WRITE_WARNINGF(TL("Vehicle '%' ignores attribute arrivalEdge=% after rerouting at time=% (routeLength=%)"),
1091 getID(), myParameter->arrivalEdge, time2string(SIMSTEP), myRoute->getEdges().size() - 1);
1092 }
1093 }
1094 const MSEdge* arrivalEdge = myParameter->arrivalEdge >= 0 ? myRoute->getEdges()[arrivalEdgeIndex] : myRoute->getLastEdge();
1095 if (!onInit) {
1096 arrivalEdge = myRoute->getLastEdge();
1097 // ignore arrivalEdge parameter after rerouting
1098 const_cast<SUMOVehicleParameter*>(myParameter)->arrivalEdge = -1;
1099 }
1100 const std::vector<MSLane*>& lanes = arrivalEdge->getLanes();
1101 const double lastLaneLength = lanes[0]->getLength();
1104 if (fabs(myParameter->arrivalPos) > lastLaneLength) {
1105 WRITE_WARNINGF(TL("Vehicle '%' will not be able to arrive at the given position!"), getID());
1106 }
1107 // Maybe we should warn the user about invalid inputs!
1108 myArrivalPos = MIN2(myParameter->arrivalPos, lastLaneLength);
1109 if (myArrivalPos < 0) {
1110 myArrivalPos = MAX2(myArrivalPos + lastLaneLength, 0.);
1111 }
1112 break;
1114 myArrivalPos = RandHelper::rand(lastLaneLength);
1115 break;
1117 myArrivalPos = lastLaneLength / 2.;
1118 break;
1119 default:
1120 myArrivalPos = lastLaneLength;
1121 break;
1122 }
1124 if (myParameter->arrivalLane >= (int)lanes.size() || !lanes[myParameter->arrivalLane]->allowsVehicleClass(myType->getVehicleClass())) {
1125 WRITE_WARNINGF(TL("Vehicle '%' will not be able to arrive at the given lane '%_%'!"), getID(), arrivalEdge->getID(), toString(myParameter->arrivalLane));
1126 }
1127 myArrivalLane = MIN2(myParameter->arrivalLane, (int)(lanes.size() - 1));
1129 myArrivalLane = -1;
1130 for (MSLane* lane : lanes) {
1131 if (lane->allowsVehicleClass(myType->getVehicleClass())) {
1132 myArrivalLane = lane->getIndex();
1133 break;
1134 }
1135 }
1136 if (myArrivalLane == -1) {
1137 WRITE_WARNINGF(TL("Vehicle '%' has no usable arrivalLane on edge '%'."), getID(), arrivalEdge->getID());
1138 myArrivalLane = 0;
1139 }
1141 // pick random lane among all usable lanes
1142 std::vector<MSLane*> usable;
1143 for (MSLane* lane : lanes) {
1144 if (lane->allowsVehicleClass(myType->getVehicleClass())) {
1145 usable.push_back(lane);
1146 }
1147 }
1148 if (usable.empty()) {
1149 WRITE_WARNINGF(TL("Vehicle '%' has no usable arrivalLane on edge '%'."), getID(), arrivalEdge->getID());
1150 myArrivalLane = 0;
1151 } else {
1152 myArrivalLane = usable[RandHelper::rand(0, (int)usable.size())]->getIndex();
1153 }
1154 }
1156 for (std::vector<MSLane*>::const_iterator l = lanes.begin(); l != lanes.end(); ++l) {
1157 if (myParameter->arrivalSpeed <= (*l)->getVehicleMaxSpeed(this)) {
1158 return;
1159 }
1160 }
1161 WRITE_WARNINGF(TL("Vehicle '%' will not be able to arrive with the given speed!"), getID());
1162 }
1163}
1164
1165void
1169 const int routeEdges = (int)myRoute->getEdges().size();
1171 // write specific edge in vehroute output for reproducibility
1172 pars->departEdge = RandHelper::rand(0, routeEdges);
1174 }
1175 assert(pars->departEdge >= 0);
1176 if (pars->departEdge >= routeEdges) {
1177 WRITE_WARNINGF(TL("Ignoring departEdge % for vehicle '%' with % route edges"), toString(pars->departEdge), getID(), toString(routeEdges));
1178 } else {
1179 myCurrEdge += pars->departEdge;
1180 }
1181 }
1183 const int routeEdges = (int)myRoute->getEdges().size();
1184 const int begin = (int)(myCurrEdge - myRoute->begin());
1185 // write specific edge in vehroute output for reproducibility
1186 pars->arrivalEdge = RandHelper::rand(begin, routeEdges);
1188 assert(pars->arrivalEdge >= begin);
1189 assert(pars->arrivalEdge < routeEdges);
1190 }
1191}
1192
1193int
1197
1198int
1202 } else {
1204 }
1205}
1206
1207double
1209 return MAX2(0., MIN2(1., getVehicleType().getImpatience()
1210 + (hasInfluencer() ? getBaseInfluencer()->getExtraImpatience() : 0)
1212}
1213
1214
1215MSDevice*
1216MSBaseVehicle::getDevice(const std::type_info& type) const {
1217 for (MSVehicleDevice* const dev : myDevices) {
1218 if (typeid(*dev) == type) {
1219 return dev;
1220 }
1221 }
1222 return nullptr;
1223}
1224
1225
1226void
1228 // the parameters may hold the name of a vTypeDistribution but we are interested in the actual type
1229 const std::string& typeID = myParameter->vtypeid != getVehicleType().getID() ? getVehicleType().getID() : "";
1231 // params and stops must be written in child classes since they may wish to add additional attributes first
1232 out.writeAttr(SUMO_ATTR_ROUTE, myRoute->getID());
1233 std::ostringstream os;
1234 os << myOdometer << " " << myNumberReroutes;
1235 out.writeAttr(SUMO_ATTR_DISTANCE, os.str());
1238 }
1240 const int precision = out.getPrecision();
1241 out.setPrecision(MAX2(gPrecisionRandom, precision));
1243 out.setPrecision(precision);
1244 }
1246 out.writeAttr(SUMO_ATTR_REROUTE, true);
1247 }
1249 // could be set from stop
1251 }
1252 // here starts the vehicle internal part (see loading)
1253 // @note: remember to close the vehicle tag when calling this in a subclass!
1254}
1255
1256
1257bool
1258MSBaseVehicle::handleCollisionStop(MSStop& stop, const double distToStop) {
1259 UNUSED_PARAMETER(stop);
1260 UNUSED_PARAMETER(distToStop);
1261 return true;
1262}
1263
1264
1265bool
1267 return !myStops.empty() && myStops.begin()->reached /*&& myState.mySpeed < SUMO_const_haltingSpeed @todo #1864#*/;
1268}
1269
1270
1271bool
1273 return (isStopped() && (myStops.begin()->pars.parking == ParkingType::OFFROAD)
1274 && (myStops.begin()->parkingarea == nullptr || !myStops.begin()->parkingarea->parkOnRoad())
1275 && (myStops.begin()->getSpeed() == 0 || getSpeed() < SUMO_const_haltingSpeed));
1276}
1277
1278
1279bool
1281 return myPastStops.size() > 0 && myPastStops.back().jump >= 0 && getEdge()->getID() == myPastStops.back().edge && myPastStops.back().ended == SIMSTEP;
1282}
1283
1284
1285bool
1287 return isStopped() && (myStops.begin()->triggered || myStops.begin()->containerTriggered || myStops.begin()->joinTriggered);
1288}
1289
1290
1291bool
1293 return isStopped() && (myStops.begin()->pars.parking == ParkingType::OFFROAD);
1294}
1295
1296
1297bool
1298MSBaseVehicle::isStoppedInRange(const double pos, const double tolerance, bool checkFuture) const {
1299 if (isStopped() || (checkFuture && hasStops())) {
1300 const MSStop& stop = myStops.front();
1301 return stop.pars.startPos - tolerance <= pos && stop.pars.endPos + tolerance >= pos;
1302 }
1303 return false;
1304}
1305
1306bool
1307MSBaseVehicle::replaceParkingArea(MSParkingArea* parkingArea, std::string& errorMsg) {
1308 // Check if there is a parking area to be replaced
1309 if (parkingArea == 0) {
1310 errorMsg = "new parkingArea is NULL";
1311 return false;
1312 }
1313 if (myStops.size() == 0) {
1314 errorMsg = "vehicle has no stops";
1315 return false;
1316 }
1317 if (myStops.front().parkingarea == 0) {
1318 errorMsg = "first stop is not at parkingArea";
1319 return false;
1320 }
1321 MSStop& first = myStops.front();
1322 SUMOVehicleParameter::Stop& stopPar = const_cast<SUMOVehicleParameter::Stop&>(first.pars);
1323 std::string oldStopEdgeID = first.lane->getEdge().getID();
1324 // merge subsequent duplicate stops equals to parking area
1325 for (std::list<MSStop>::iterator iter = ++myStops.begin(); iter != myStops.end();) {
1326 if (iter->parkingarea == parkingArea) {
1327 stopPar.duration += iter->duration;
1328 myStops.erase(iter++);
1329 } else {
1330 break;
1331 }
1332 }
1333 stopPar.lane = parkingArea->getLane().getID();
1334 stopPar.parkingarea = parkingArea->getID();
1335 stopPar.startPos = parkingArea->getBeginLanePosition();
1336 stopPar.endPos = parkingArea->getEndLanePosition();
1337 first.edge = myRoute->end(); // will be patched in replaceRoute
1338 first.lane = &parkingArea->getLane();
1339 first.parkingarea = parkingArea;
1340
1341 // patch via edges
1342 std::string newStopEdgeID = parkingArea->getLane().getEdge().getID();
1343 if (myParameter->via.size() > 0 && myParameter->via.front() != newStopEdgeID) {
1344 myParameter->via.erase(myParameter->via.begin());
1345 myParameter->via.insert(myParameter->via.begin(), newStopEdgeID);
1346 }
1347 return true;
1348}
1349
1350
1353 MSParkingArea* nextParkingArea = nullptr;
1354 if (!myStops.empty()) {
1356 MSStop stop = myStops.front();
1357 if (!stop.reached && stop.parkingarea != nullptr) {
1358 nextParkingArea = stop.parkingarea;
1359 }
1360 }
1361 return nextParkingArea;
1362}
1363
1364
1367 MSParkingArea* currentParkingArea = nullptr;
1368 if (isParking()) {
1369 currentParkingArea = myStops.begin()->parkingarea;
1370 }
1371 return currentParkingArea;
1372}
1373
1374
1375const std::vector<std::string>&
1378 return myParameter->parkingBadges;
1379 } else {
1381 }
1382}
1383
1384
1385double
1386MSBaseVehicle::basePos(const MSEdge* edge) const {
1387 double result = MIN2(getVehicleType().getLength() + POSITION_EPS, edge->getLength());
1388 if (hasStops()
1389 && myStops.front().edge == myRoute->begin()
1390 && (&myStops.front().lane->getEdge()) == *myStops.front().edge) {
1391 result = MIN2(result, MAX2(0.0, myStops.front().getEndPos(*this)));
1392 }
1393 return result;
1394}
1395
1396
1397MSLane*
1399 const std::string edgeID = SUMOXMLDefinitions::getEdgeIDFromLane(stop.lane);
1400 const MSEdge* edge = MSEdge::dictionary(edgeID);
1401 if (edge == nullptr || edge->getOppositeEdge() == nullptr || stop.lane.find("_") == std::string::npos) {
1402 return nullptr;
1403 }
1404 const int laneIndex = SUMOXMLDefinitions::getIndexFromLane(stop.lane);
1405 if (laneIndex < (edge->getNumLanes() + edge->getOppositeEdge()->getNumLanes())) {
1406 const int oppositeIndex = edge->getOppositeEdge()->getNumLanes() + edge->getNumLanes() - 1 - laneIndex;
1407 stop.edge = edgeID;
1408 return edge->getOppositeEdge()->getLanes()[oppositeIndex];
1409 }
1410 return nullptr;
1411}
1412
1413
1414bool
1415MSBaseVehicle::addStop(const SUMOVehicleParameter::Stop& stopPar, std::string& errorMsg, SUMOTime untilOffset,
1416 MSRouteIterator* searchStart) {
1417 MSStop stop(stopPar);
1418 if (stopPar.lane == "") {
1419 MSEdge* e = MSEdge::dictionary(stopPar.edge);
1421 if (stop.lane == nullptr) {
1422 errorMsg = "Vehicle '" + myParameter->id + "' is not allowed to stop on any lane of edge '" + stopPar.edge + "'.";
1423 return false;
1424 }
1425 } else {
1426 stop.lane = MSLane::dictionary(stopPar.lane);
1427 if (stop.lane == nullptr) {
1428 // must be an opposite stop
1429 SUMOVehicleParameter::Stop tmp = stopPar;
1430 stop.lane = interpretOppositeStop(tmp);
1431 assert(stop.lane != nullptr);
1432 }
1434 errorMsg = "Vehicle '" + myParameter->id + "' is not allowed to stop on lane '" + stopPar.lane + "'.";
1435 return false;
1436 }
1437 }
1439 stop.segment = MSGlobals::gMesoNet->getSegmentForEdge(stop.lane->getEdge(), stop.getEndPos(*this));
1440 if (stop.lane->isInternal()) {
1441 errorMsg = "Mesoscopic simulation does not allow stopping on internal edge '" + stopPar.edge + "' for vehicle '" + myParameter->id + "'.";
1442 return false;
1443 }
1444 }
1445 stop.initPars(stopPar);
1446 if (stopPar.until != -1) {
1447 // !!! it would be much cleaner to invent a constructor for stops which takes "until" as an argument
1448 const_cast<SUMOVehicleParameter::Stop&>(stop.pars).until += untilOffset;
1449 }
1450 if (stopPar.arrival != -1) {
1451 const_cast<SUMOVehicleParameter::Stop&>(stop.pars).arrival += untilOffset;
1452 }
1453 std::string stopType = "stop";
1454 std::string stopID = "";
1455 double parkingLength = stop.pars.endPos - stop.pars.startPos;
1456 if (stop.busstop != nullptr) {
1457 stopType = "busStop";
1458 stopID = stop.busstop->getID();
1459 parkingLength = stop.busstop->getParkingLength();
1460 } else if (stop.containerstop != nullptr) {
1461 stopType = "containerStop";
1462 stopID = stop.containerstop->getID();
1463 parkingLength = stop.containerstop->getParkingLength();
1464 } else if (stop.chargingStation != nullptr) {
1465 stopType = "chargingStation";
1466 stopID = stop.chargingStation->getID();
1467 parkingLength = stop.chargingStation->getParkingLength();
1468 } else if (stop.overheadWireSegment != nullptr) {
1469 stopType = "overheadWireSegment";
1470 stopID = stop.overheadWireSegment->getID();
1471 parkingLength = stop.overheadWireSegment->getParkingLength();
1472 } else if (stop.parkingarea != nullptr) {
1473 stopType = "parkingArea";
1474 stopID = stop.parkingarea->getID();
1475 }
1476 const std::string errorMsgStart = stopID == "" ? stopType : stopType + " '" + stopID + "'";
1477
1478 if (stop.pars.startPos < 0 || stop.pars.endPos > stop.lane->getLength()) {
1479 errorMsg = errorMsgStart + " for vehicle '" + myParameter->id + "' on lane '" + stop.lane->getID() + "' has an invalid position.";
1480 return false;
1481 }
1482 if (stopType != "stop" && stopType != "parkingArea" && myType->getLength() / 2. > parkingLength
1483 // do not warn for stops that fill the whole lane
1484 && parkingLength < stop.lane->getLength()
1485 // do not warn twice for the same stop
1486 && MSNet::getInstance()->warnOnce(stopType + ":" + stopID)) {
1487 errorMsg = errorMsgStart + " on lane '" + stop.lane->getID() + "' is too short for vehicle '" + myParameter->id + "'.";
1488 }
1489 if (stopType == "parkingArea" && !stop.parkingarea->accepts(this)) {
1490 // forbid access in case the parking requests other badges
1491 errorMsg = errorMsgStart + "on lane '" + stop.lane->getID() + "' forbids access because vehicle '" + myParameter->id + "' does not provide any valid badge.";
1492 return false;
1493 }
1494 const MSEdge* stopLaneEdge = &stop.lane->getEdge();
1495 const MSEdge* stopEdge;
1496 if (stopLaneEdge->getOppositeEdge() != nullptr && stopLaneEdge->getOppositeEdge()->getID() == stopPar.edge) {
1497 // stop lane is on the opposite side
1498 stopEdge = stopLaneEdge->getOppositeEdge();
1499 stop.isOpposite = true;
1500 } else {
1501 // if stop is on an internal edge the normal edge before the intersection is used
1502 stopEdge = stopLaneEdge->getNormalBefore();
1503 }
1504 MSRouteIterator succ = myCurrEdge + 1; // we're using the address but only within the scope of this function (and recursive calls)
1505 if (searchStart == nullptr) {
1506 searchStart = &myCurrEdge;
1507 if (stopLaneEdge->isNormal() && getLane() != nullptr && getLane()->isInternal()) {
1508 // already on the intersection but myCurrEdge is before it
1509 searchStart = &succ;
1510 }
1511 }
1512#ifdef DEBUG_ADD_STOP
1513 if (DEBUG_COND) {
1514 std::cout << "addStop desc=" << stop.getDescription() << " stopEdge=" << stopEdge->getID()
1515 << " searchStart=" << ((*searchStart) == myRoute->end() ? "END" : (**searchStart)->getID())
1516 << " index=" << (int)((*searchStart) - myRoute->begin()) << " route=" << toString(myRoute->getEdges())
1517 << "\n";
1518 }
1519#endif
1520 stop.edge = std::find(*searchStart, myRoute->end(), stopEdge);
1521 MSRouteIterator prevStopEdge = myCurrEdge;
1522 const MSEdge* prevEdge = (getLane() == nullptr ? getEdge() : &getLane()->getEdge());
1523 double prevStopPos = getPositionOnLane();
1524 // where to insert the stop
1525 std::list<MSStop>::iterator iter = myStops.begin();
1526 if (stopPar.index == STOP_INDEX_END || stopPar.index >= static_cast<int>(myStops.size()) || stopPar.index == STOP_INDEX_REPEAT) {
1527 iter = myStops.end();
1528 if (myStops.size() > 0 && myStops.back().edge >= *searchStart) {
1529 prevStopEdge = myStops.back().edge;
1530 prevEdge = &myStops.back().lane->getEdge();
1531 prevStopPos = myStops.back().pars.endPos;
1532 stop.edge = std::find(prevStopEdge, myRoute->end(), stopEdge);
1533 if (prevStopEdge == stop.edge // laneEdge check is insufficient for looped routes
1534 && prevEdge == &stop.lane->getEdge() // route iterator check insufficient for internal lane stops
1535 && (prevStopPos > stop.pars.endPos ||
1536 (prevStopPos == stop.pars.endPos && stopPar.index == STOP_INDEX_REPEAT))) {
1537 stop.edge = std::find(prevStopEdge + 1, myRoute->end(), stopEdge);
1538 }
1539#ifdef DEBUG_ADD_STOP
1540 if (DEBUG_COND) {
1541 std::cout << " (@end) prevStopEdge=" << (*prevStopEdge)->getID() << " prevStopPos=" << prevStopPos << " index=" << (int)(prevStopEdge - myRoute->begin())
1542 << " foundIndex=" << (stop.edge == myRoute->end() ? -1 : (int)(stop.edge - myRoute->begin())) << "\n";
1543 }
1544#endif
1545 }
1546 // skip a number of occurences of stopEdge in looped route
1547 int skipLooped = stopPar.index - static_cast<int>(myStops.size());
1548 for (int j = 0; j < skipLooped; j++) {
1549 auto nextIt = std::find(stop.edge + 1, myRoute->end(), stopEdge);
1550 if (nextIt == myRoute->end()) {
1551 if (std::find(myRoute->begin(), stop.edge, stopEdge) != stop.edge) {
1552 // only warn if the route loops over the stop edge at least once
1553 errorMsg = errorMsgStart + " for vehicle '" + myParameter->id + "' could not skip " + toString(skipLooped) + " occurences of stop edge '" + stopEdge->getID() + "' in looped route.";
1554 }
1555 break;
1556 } else {
1557 stop.edge = nextIt;
1558 }
1559 }
1560 } else {
1561 if (stopPar.index == STOP_INDEX_FIT) {
1562 while (iter != myStops.end() && (iter->edge < stop.edge ||
1563 (iter->pars.endPos < stop.pars.endPos && iter->edge == stop.edge) ||
1564 (stop.lane->getEdge().isInternal() && iter->edge == stop.edge))) {
1565 prevStopEdge = iter->edge;
1566 prevStopPos = iter->pars.endPos;
1567 ++iter;
1568 }
1569 } else {
1570 int index = stopPar.index;
1571 while (index > 0) {
1572 prevStopEdge = iter->edge;
1573 prevStopPos = iter->pars.endPos;
1574 ++iter;
1575 --index;
1576 }
1577#ifdef DEBUG_ADD_STOP
1578 if (DEBUG_COND) {
1579 std::cout << " (@fit) prevStopEdge=" << (*prevStopEdge)->getID() << " index=" << (int)(prevStopEdge - myRoute->begin()) << "\n";
1580 }
1581#endif
1582 stop.edge = std::find(prevStopEdge, myRoute->end(), stopEdge);
1583 }
1584 }
1585 const bool wasTooClose = errorMsg != "" && errorMsg.find("too close") != std::string::npos;
1586 if (stop.edge == myRoute->end()) {
1587 if (!wasTooClose) {
1588 errorMsg = errorMsgStart + " for vehicle '" + myParameter->id + "' on lane '" + stop.lane->getID() + "' is not downstream the current route.";
1589 }
1590 return false;
1591 }
1592
1593 const bool tooClose = (prevStopEdge == stop.edge && prevEdge == &stop.lane->getEdge() &&
1594 prevStopPos + (iter == myStops.begin() && !instantStopping() ? getBrakeGap() : 0) > stop.pars.endPos + POSITION_EPS);
1595
1596 if (prevStopEdge > stop.edge ||
1597 // a collision-stop happens after vehicle movement and may move the
1598 // vehicle backwards on its lane (prevStopPos is the vehicle position)
1599 (tooClose && !stop.pars.collision)
1600 || (stop.lane->getEdge().isInternal() && stop.lane->getNextNormal() != *(stop.edge + 1))) {
1601 // check if the edge occurs again later in the route
1602 //std::cout << " could not add stop " << errorMsgStart << " prevStops=" << myStops.size() << " searchStart=" << (*searchStart - myRoute->begin()) << " route=" << toString(myRoute->getEdges()) << "\n";
1603 if (tooClose && prevStopPos <= stop.pars.endPos + POSITION_EPS) {
1604 errorMsg = errorMsgStart + " for vehicle '" + myParameter->id + "' on lane '" + stop.pars.lane + "' is too close to brake.";
1605 }
1606 MSRouteIterator next = stop.edge + 1;
1607 return addStop(stopPar, errorMsg, untilOffset, &next);
1608 }
1609 if (wasTooClose) {
1610 errorMsg = "";
1611 }
1612 // David.C:
1613 //if (!stop.parking && (myCurrEdge == stop.edge && myState.myPos > stop.endPos - getCarFollowModel().brakeGap(myState.mySpeed))) {
1614 const double endPosOffset = stop.lane->getEdge().isInternal() ? (*stop.edge)->getLength() : 0;
1615 const double distToStop = stop.pars.endPos + endPosOffset - getPositionOnLane();
1616 if (stop.pars.collision && !handleCollisionStop(stop, distToStop)) {
1617 return false;
1618 }
1619 if (!hasDeparted() && myCurrEdge == stop.edge) {
1620 double pos = -1;
1622 pos = myParameter->departPos;
1623 if (pos < 0.) {
1624 pos += (*myCurrEdge)->getLength();
1625 }
1626 }
1628 pos = MIN2(stop.pars.endPos + endPosOffset, basePos(*myCurrEdge));
1629 }
1630 if (pos > stop.pars.endPos + endPosOffset) {
1631 if (stop.edge != myRoute->end()) {
1632 // check if the edge occurs again later in the route
1633 MSRouteIterator next = stop.edge + 1;
1634 return addStop(stopPar, errorMsg, untilOffset, &next);
1635 }
1636 errorMsg = errorMsgStart + " for vehicle '" + myParameter->id + "' on lane '" + stop.lane->getID() + "' is before departPos.";
1637 return false;
1638 }
1639 }
1640 if (iter != myStops.begin()) {
1641 std::list<MSStop>::iterator iter2 = iter;
1642 iter2--;
1643 if (stop.getUntil() >= 0 && iter2->getUntil() > stop.getUntil()
1644 && (!MSGlobals::gUseStopEnded || iter2->pars.ended < 0 || stop.pars.ended >= 0)) {
1645 errorMsg = errorMsgStart + " for vehicle '" + myParameter->id + "' on lane '" + stop.lane->getID()
1646 + "' set to end at " + time2string(stop.getUntil())
1647 + " earlier than previous stop at " + time2string(iter2->getUntil()) + ".";
1648 }
1649 if (stop.pars.arrival >= 0 && iter2->pars.arrival > stop.pars.arrival) {
1650 errorMsg = errorMsgStart + " for vehicle '" + myParameter->id + "' on lane '" + stop.lane->getID()
1651 + "' set to start at " + time2string(stop.pars.arrival)
1652 + " earlier than previous stop end at " + time2string(iter2->getUntil()) + ".";
1653 }
1654 if (stop.pars.arrival >= 0 && iter2->pars.arrival > stop.pars.arrival) {
1655 errorMsg = errorMsgStart + " for vehicle '" + myParameter->id + "' on lane '" + stop.lane->getID()
1656 + "' set to start at " + time2string(stop.pars.arrival)
1657 + " earlier than previous stop arrival at " + time2string(iter2->pars.arrival) + ".";
1658 }
1659 } else {
1660 if (stop.getUntil() >= 0 && getParameter().depart > stop.getUntil()
1661 && (!MSGlobals::gUseStopEnded || stop.pars.ended < 0)) {
1662 errorMsg = errorMsgStart + " for vehicle '" + myParameter->id + "' on lane '" + stop.lane->getID()
1663 + "' set to end at " + time2string(stop.getUntil())
1664 + " earlier than departure at " + time2string(getParameter().depart) + ".";
1665 }
1666 }
1667 if (stop.getUntil() >= 0 && stop.getArrival() > stop.getUntil() && errorMsg == "") {
1668 errorMsg = errorMsgStart + " for vehicle '" + myParameter->id + "' on lane '" + stop.lane->getID()
1669 + "' set to end at " + time2string(stop.getUntil())
1670 + " earlier than arrival at " + time2string(stop.getArrival()) + ".";
1671 }
1672 setSkips(stop, (int)myStops.size());
1673 myStops.insert(iter, stop);
1674 if (stopPar.tripId != "") {
1676 }
1677 //std::cout << " added stop " << errorMsgStart << " totalStops=" << myStops.size() << " searchStart=" << (*searchStart - myRoute->begin())
1678 // << " routeIndex=" << (stop.edge - myRoute->begin())
1679 // << " stopIndex=" << std::distance(myStops.begin(), iter)
1680 // << " route=" << toString(myRoute->getEdges()) << "\n";
1681 return true;
1682}
1683
1684
1685void
1686MSBaseVehicle::setSkips(MSStop& stop, int prevActiveStops) {
1687 if (hasDeparted() && stop.edge > myRoute->begin()) {
1688 // if the route is looped we must patch the index to ensure that state
1689 // loading (and vehroute-output) encode the correct number of skips
1690 int foundSkips = 0;
1691 MSRouteIterator itPrev;
1692 double prevEndPos;
1693 if (prevActiveStops > 0) {
1694 assert((int)myStops.size() >= prevActiveStops);
1695 auto prevStopIt = myStops.begin();
1696 std::advance(prevStopIt, prevActiveStops - 1);
1697 const MSStop& prev = *prevStopIt;
1698 itPrev = prev.edge;
1699 prevEndPos = prev.pars.endPos;
1700 } else if (myPastStops.size() > 0) {
1701 itPrev = myRoute->begin() + myPastStops.back().routeIndex;
1702 prevEndPos = myPastStops.back().endPos;
1703 } else {
1704 itPrev = myRoute->begin() + myParameter->departEdge;
1705 prevEndPos = myDepartPos;
1706 }
1707 //auto itPrevOrig = itPrev;
1708 if (*itPrev == *stop.edge && prevEndPos > stop.pars.endPos) {
1709 itPrev++;
1710 }
1711 //std::cout << SIMTIME << " veh=" << getID() << " prevActive=" << prevActiveStops << " edge=" << (*stop.edge)->getID() << " routeIndex=" << (stop.edge - myRoute->begin()) << " prevIndex=" << (itPrev - myRoute->begin()) << "\n";
1712 while (itPrev < stop.edge) {
1713 if (*itPrev == *stop.edge) {
1714 foundSkips++;
1715 }
1716 itPrev++;
1717 }
1718 int newIndex = STOP_INDEX_END;
1719 if (foundSkips > 0) {
1720 //if (getID() == "77_0_0") {
1721 // std::cout << SIMTIME << " veh=" << getID() << " past=" << myPastStops.size() << " prevActive=" << prevActiveStops
1722 // << " edge=" << (*stop.edge)->getID() << " routeIndex=" << (stop.edge - myRoute->begin())
1723 // << " prevEdge=" << (*itPrevOrig)->getID()
1724 // << " prevIndex=" << (itPrevOrig - myRoute->begin())
1725 // << " skips=" << foundSkips << "\n";
1726 //}
1727 newIndex = (int)myPastStops.size() + prevActiveStops + foundSkips;
1728 }
1729 const_cast<SUMOVehicleParameter::Stop&>(stop.pars).index = newIndex;
1730 }
1731}
1732
1733
1736 for (int i = 0; i < (int)myMoveReminders.size();) {
1737 auto rem = &myMoveReminders[i];
1738 if (rem->first->notifyReroute(*this)) {
1739#ifdef _DEBUG
1740 if (myTraceMoveReminders) {
1741 traceMoveReminder("notifyReroute", rem->first, rem->second, true);
1742 }
1743#endif
1744 ++i;
1745 } else {
1746#ifdef _DEBUG
1747 if (myTraceMoveReminders) {
1748 traceMoveReminder("notifyReroute", rem->first, rem->second, false);
1749 }
1750#endif
1751 myMoveReminders.erase(myMoveReminders.begin() + i);
1752 }
1753 }
1755 // event only called once
1756 return 0;
1757}
1758
1759
1760void
1761MSBaseVehicle::addStops(const bool ignoreStopErrors, MSRouteIterator* searchStart, bool addRouteStops) {
1762 if (addRouteStops) {
1763 for (const SUMOVehicleParameter::Stop& stop : myRoute->getStops()) {
1764 std::string errorMsg;
1765 if (!addStop(stop, errorMsg, myParameter->depart, searchStart) && !ignoreStopErrors) {
1766 throw ProcessError(errorMsg);
1767 }
1768 if (errorMsg != "") {
1769 WRITE_WARNING(errorMsg);
1770 }
1771 }
1772 }
1774 for (const SUMOVehicleParameter::Stop& stop : myParameter->stops) {
1775 std::string errorMsg;
1776 if (!addStop(stop, errorMsg, untilOffset, searchStart) && !ignoreStopErrors) {
1777 throw ProcessError(errorMsg);
1778 }
1779 if (errorMsg != "") {
1780 WRITE_WARNING(errorMsg);
1781 }
1782 }
1783}
1784
1785
1786bool
1789 int i = 0;
1790 bool ok = true;
1791 for (const MSStop& stop : myStops) {
1792 MSRouteIterator it;
1793 if (stop.lane->isInternal()) {
1794 // find the normal predecessor and ensure that the next route edge
1795 // matches the successor of the internal edge successor
1796 it = std::find(start, myRoute->end(), stop.lane->getEdge().getNormalBefore());
1797 if (it != myRoute->end() && (
1798 it + 1 == myRoute->end() || *(it + 1) != stop.lane->getEdge().getNormalSuccessor())) {
1799 it = myRoute->end(); // signal failure
1800 }
1801 } else {
1802 it = std::find(start, myRoute->end(), &stop.lane->getEdge());
1803 }
1804 if (it == myRoute->end()) {
1805 if (!silent) {
1806 WRITE_ERRORF("Stop % on edge '%' is not found after edge '%' (% after current) for vehicle '%' at time=%.",
1807 i, stop.lane->getEdge().getID(), (*start)->getID(), toString(start - myCurrEdge), getID(), time2string(SIMSTEP));
1808 }
1809 ok = false;
1810 } else {
1811 MSRouteIterator it2;
1812 for (it2 = myRoute->begin(); it2 != myRoute->end(); it2++) {
1813 if (it2 == stop.edge) {
1814 break;
1815 }
1816 }
1817 if (it2 == myRoute->end()) {
1818 if (!silent) {
1819 WRITE_ERRORF("Stop % on edge '%' used invalid route index for vehicle '%' at time=%.",
1820 i, stop.lane->getEdge().getID(), getID(), time2string(SIMSTEP));
1821 }
1822 ok = false;
1823 } else if (it2 < start) {
1824 if (!silent) {
1825 WRITE_ERRORF("Stop % on edge '%' used invalid (relative) route index % expected after % for vehicle '%' at time=%.",
1826 i, stop.lane->getEdge().getID(), toString(it2 - myCurrEdge), toString(start - myCurrEdge), getID(), time2string(SIMSTEP));
1827 }
1828 ok = false;
1829 } else {
1830 start = stop.edge;
1831 }
1832 }
1833 i++;
1834 }
1835 return ok;
1836}
1837
1838
1839std::vector<MSBaseVehicle::StopEdgeInfo>
1840MSBaseVehicle::getStopEdges(double& firstPos, double& lastPos, std::set<int>& jumps) const {
1841 assert(haveValidStopEdges());
1842 std::vector<StopEdgeInfo> result;
1843 const MSStop* prev = nullptr;
1844 const MSEdge* internalSuccessor = nullptr;
1845 for (const MSStop& stop : myStops) {
1846 if (stop.reached) {
1847 if (stop.pars.jump >= 0) {
1848 jumps.insert((int)result.size());
1849 }
1850 continue;
1851 }
1852 double stopPos = stop.getEndPos(*this);
1853 if ((prev == nullptr
1854 || prev->edge != stop.edge
1855 || (prev->lane == stop.lane && prev->getEndPos(*this) > stopPos))
1856 && *stop.edge != internalSuccessor) {
1857 if (stop.lane->isInternal()) {
1858 stopPos = (*stop.edge)->getLength();
1859 }
1860 result.push_back(StopEdgeInfo(*stop.edge, stop.pars.priority, stop.getArrivalFallback(), stopPos));
1861 result.back().nameTag = stop.getStoppingPlaceName();
1862 result.back().stopPar = &stop.pars;
1863 if (stop.lane->isInternal()) {
1864 internalSuccessor = stop.lane->getNextNormal();
1865 result.push_back(StopEdgeInfo(internalSuccessor, stop.pars.priority, stop.getArrivalFallback(), 0));
1866 } else {
1867 internalSuccessor = nullptr;
1868 }
1869 } else if (prev != nullptr && prev->edge == stop.edge) {
1870 result.back().priority = addStopPriority(result.back().priority, stop.pars.priority);
1871 }
1872 prev = &stop;
1873 if (firstPos == INVALID_DOUBLE) {
1874 if (stop.parkingarea != nullptr) {
1875 firstPos = MAX2(0., stopPos);
1876 } else {
1877 firstPos = stopPos;
1878 }
1879 }
1880 lastPos = stopPos;
1881 if (stop.pars.jump >= 0) {
1882 jumps.insert((int)result.size() - 1);
1883 }
1884 }
1885 //std::cout << SIMTIME << " getStopEdges veh=" << getID() << "\n";
1886 //for (auto item : result) {
1887 // std::cout << " e=" << item.edge->getID() << " pos=" << item.pos << "\n";
1888 //}
1889 return result;
1890}
1891
1892
1893double
1894MSBaseVehicle::addStopPriority(double p1, double p2) {
1895 if (p1 < 0 || p2 < 0) {
1896 return p1;
1897 }
1898 return p1 + p2;
1899}
1900
1901std::vector<std::pair<int, double> >
1903 std::vector<std::pair<int, double> > result;
1904 for (std::list<MSStop>::const_iterator iter = myStops.begin(); iter != myStops.end(); ++iter) {
1905 result.push_back(std::make_pair(
1906 (int)(iter->edge - myRoute->begin()),
1907 iter->getEndPos(*this)));
1908 }
1909 return result;
1910}
1911
1912
1913const MSStop&
1915 assert(myStops.size() > 0);
1916 return myStops.front();
1917}
1918
1919MSStop&
1921 assert(myStops.size() > 0);
1922 return myStops.front();
1923}
1924
1927 if (isStopped()) {
1928 return myStops.front().duration;
1929 } else {
1930 return 0;
1931 }
1932}
1933
1934
1935MSStop&
1936MSBaseVehicle::getStop(int nextStopIndex) {
1937 if (nextStopIndex < 0 || (int)myStops.size() <= nextStopIndex) {
1938 throw InvalidArgument(TLF("Invalid stop index % (has % stops).", nextStopIndex, myStops.size()));
1939 }
1940 auto stopIt = myStops.begin();
1941 std::advance(stopIt, nextStopIndex);
1942 return *stopIt;
1943}
1944
1945
1948 if (hasStops()) {
1949 return &myStops.front().pars;
1950 }
1951 return nullptr;
1952}
1953
1954
1955bool
1957 //if the stop exists update the duration
1958 for (std::list<MSStop>::iterator iter = myStops.begin(); iter != myStops.end(); iter++) {
1959 if (iter->lane->getID() == stop.lane && fabs(iter->pars.endPos - stop.endPos) < POSITION_EPS) {
1960 // update existing stop
1961 if (stop.duration == 0 && stop.until < 0 && !iter->reached) {
1962 myStops.erase(iter);
1963 } else {
1964 iter->duration = stop.duration;
1965 iter->triggered = stop.triggered;
1966 iter->containerTriggered = stop.containerTriggered;
1967 const_cast<SUMOVehicleParameter::Stop&>(iter->pars).until = stop.until;
1968 const_cast<SUMOVehicleParameter::Stop&>(iter->pars).parking = stop.parking;
1969 }
1970 return true;
1971 }
1972 }
1973 const bool result = addStop(stop, errorMsg);
1974 if (result) {
1976 myParameter->stops.push_back(stop);
1977 }
1978 return result;
1979}
1980
1981
1982void
1989
1990
1991bool
1993 if (hasStops() && nextStopIndex < (int)myStops.size()) {
1994 if (nextStopIndex == 0 && isStopped()) {
1996 } else {
1997 auto stopIt = myStops.begin();
1998 std::advance(stopIt, nextStopIndex);
1999 myStops.erase(stopIt);
2000 }
2001 if (!hasDeparted() && (int)myParameter->stops.size() > nextStopIndex) {
2002 // stops will be rebuilt from scratch on rerouting so we must patch the stops in myParameter
2003 auto stopIt2 = myParameter->stops.begin();
2004 std::advance(stopIt2, nextStopIndex);
2005 const_cast<SUMOVehicleParameter*>(myParameter)->stops.erase(stopIt2);
2006 }
2007 return true;
2008 } else {
2009 return false;
2010 }
2011}
2012
2013
2014bool
2015MSBaseVehicle::replaceStop(int nextStopIndex, SUMOVehicleParameter::Stop stop, const std::string& info, bool teleport, std::string& errorMsg) {
2016 const int n = (int)myStops.size();
2017 if (nextStopIndex < 0 || nextStopIndex >= n) {
2018 errorMsg = TLF("invalid nextStopIndex % for % remaining stops", nextStopIndex, n);
2019 return false;
2020 }
2021 if (nextStopIndex == 0 && isStopped()) {
2022 errorMsg = TL("cannot replace reached stop");
2023 return false;
2024 }
2026 MSLane* stopLane = MSLane::dictionary(stop.lane);
2027 MSEdge* stopEdge = &stopLane->getEdge();
2028
2029 auto itStop = myStops.begin();
2030 std::advance(itStop, nextStopIndex);
2031 MSStop& replacedStop = *itStop;
2032
2033 // check parking access rights
2034 if (stop.parkingarea != "") {
2036 if (pa != nullptr && !pa->accepts(this)) {
2037 errorMsg = TLF("vehicle '%' does not have the right badge to access parkingArea '%'", getID(), stop.parkingarea);
2038 return false;
2039 }
2040 }
2041
2042 if (replacedStop.lane == stopLane && replacedStop.pars.endPos == stop.endPos && !teleport) {
2043 // only replace stop attributes
2044 const_cast<SUMOVehicleParameter::Stop&>(replacedStop.pars) = stop;
2045 replacedStop.initPars(stop);
2046 return true;
2047 }
2048
2049 if (!stopLane->allowsVehicleClass(getVClass(), myRoutingMode)) {
2050 errorMsg = TLF("disallowed stop lane '%'", stopLane->getID());
2051 return false;
2052 }
2053
2054 const ConstMSEdgeVector& oldEdges = getRoute().getEdges();
2055 std::vector<MSStop> stops(myStops.begin(), myStops.end());
2056 const int junctionOffset = getLane() != nullptr && getLane()->isInternal() ? 1 : 0;
2057 MSRouteIterator itStart = nextStopIndex == 0 ? getCurrentRouteEdge() + junctionOffset : stops[nextStopIndex - 1].edge;
2058 double startPos = nextStopIndex == 0 ? getPositionOnLane() : stops[nextStopIndex - 1].pars.endPos;
2059 MSRouteIterator itEnd = nextStopIndex == n - 1 ? oldEdges.end() - 1 : stops[nextStopIndex + 1].edge;
2060 auto endPos = nextStopIndex == n - 1 ? getArrivalPos() : stops[nextStopIndex + 1].pars.endPos;
2062
2063 bool newDestination = nextStopIndex == n - 1 && stops[nextStopIndex].edge == oldEdges.end() - 1;
2064
2065 ConstMSEdgeVector toNewStop;
2066 if (!teleport) {
2067 router.compute(*itStart, startPos, stopEdge, stop.endPos, this, t, toNewStop, true);
2068 if (toNewStop.size() == 0) {
2069 errorMsg = TLF("no route found from edge '%' to stop edge '%'", (*itStart)->getID(), stopEdge->getID());
2070 return false;
2071 }
2072 }
2073
2074 ConstMSEdgeVector fromNewStop;
2075 if (!newDestination) {
2076 router.compute(stopEdge, stop.endPos, *itEnd, endPos, this, t, fromNewStop, true);
2077 if (fromNewStop.size() == 0) {
2078 errorMsg = TLF("no route found from stop edge '%' to edge '%'", stopEdge->getID(), (*itEnd)->getID());
2079 return false;
2080 }
2081 }
2082
2083 const_cast<SUMOVehicleParameter::Stop&>(replacedStop.pars) = stop;
2084 replacedStop.initPars(stop);
2085 replacedStop.edge = myRoute->end(); // will be patched in replaceRoute
2086 replacedStop.lane = stopLane;
2088 replacedStop.segment = MSGlobals::gMesoNet->getSegmentForEdge(replacedStop.lane->getEdge(), replacedStop.getEndPos(*this));
2089 if (replacedStop.lane->isInternal()) {
2090 errorMsg = TLF("Mesoscopic simulation does not allow stopping on internal edge '%' for vehicle '%'.", stop.edge, getID());
2091 return false;
2092 }
2093 }
2094
2095 ConstMSEdgeVector oldRemainingEdges(myCurrEdge, getRoute().end());
2096 ConstMSEdgeVector newEdges; // only remaining
2097 newEdges.insert(newEdges.end(), myCurrEdge, itStart);
2098 if (!teleport) {
2099 newEdges.insert(newEdges.end(), toNewStop.begin(), toNewStop.end() - 1);
2100 } else {
2101 newEdges.push_back(*itStart);
2102 }
2103 if (!newDestination) {
2104 newEdges.insert(newEdges.end(), fromNewStop.begin(), fromNewStop.end() - 1);
2105 newEdges.insert(newEdges.end(), itEnd, oldEdges.end());
2106 } else {
2107 newEdges.push_back(stopEdge);
2108 }
2109 //std::cout << SIMTIME << " replaceStop veh=" << getID()
2110 // << " teleport=" << teleport
2111 // << " busStop=" << stop.busstop
2112 // << " oldEdges=" << oldRemainingEdges.size()
2113 // << " newEdges=" << newEdges.size()
2114 // << " toNewStop=" << toNewStop.size()
2115 // << " fromNewStop=" << fromNewStop.size()
2116 // << "\n";
2117
2118 const double routeCost = router.recomputeCosts(newEdges, this, t);
2119 const double previousCost = router.recomputeCosts(oldRemainingEdges, this, t);
2120 const double savings = previousCost - routeCost;
2121 if (!hasDeparted() && (int)myParameter->stops.size() > nextStopIndex) {
2122 // stops will be rebuilt from scratch so we must patch the stops in myParameter
2123 const_cast<SUMOVehicleParameter*>(myParameter)->stops[nextStopIndex] = stop;
2124 }
2125 if (teleport) {
2126 // let the vehicle jump rather than teleport
2127 // we add a jump-stop at the end of the edge (unless the vehicle is
2128 // already configure to jump before the replaced stop)
2129 if (!insertJump(nextStopIndex, itStart, errorMsg)) {
2130 return false;
2131 };
2132 }
2133 return replaceRouteEdges(newEdges, routeCost, savings, info, !hasDeparted(), false, false, &errorMsg);
2134}
2135
2136
2137bool
2138MSBaseVehicle::rerouteBetweenStops(int nextStopIndex, const std::string& info, bool teleport, std::string& errorMsg) {
2139 const int n = (int)myStops.size();
2140 if (nextStopIndex < 0 || nextStopIndex > n) {
2141 errorMsg = TLF("invalid nextStopIndex % for % remaining stops", nextStopIndex, n);
2142 return false;
2143 }
2144 if (nextStopIndex == 0 && isStopped()) {
2145 errorMsg = TL("cannot reroute towards reached stop");
2146 return false;
2147 }
2149
2150 const ConstMSEdgeVector& oldEdges = getRoute().getEdges();
2151 std::vector<MSStop> stops(myStops.begin(), myStops.end());
2152 const int junctionOffset = getLane() != nullptr && getLane()->isInternal() ? 1 : 0;
2153 MSRouteIterator itStart = nextStopIndex == 0 ? getCurrentRouteEdge() + junctionOffset : stops[nextStopIndex - 1].edge;
2154 double startPos = nextStopIndex == 0 ? getPositionOnLane() : stops[nextStopIndex - 1].pars.endPos;
2155 MSRouteIterator itEnd = nextStopIndex == n ? oldEdges.end() - 1 : stops[nextStopIndex].edge;
2156 auto endPos = nextStopIndex == n ? getArrivalPos() : stops[nextStopIndex].pars.endPos;
2158
2159 ConstMSEdgeVector newBetween;
2160 if (!teleport) {
2161 router.compute(*itStart, startPos, *itEnd, endPos, this, t, newBetween, true);
2162 if (newBetween.size() == 0) {
2163 errorMsg = TLF("no route found from edge '%' to stop edge '%'", (*itStart)->getID(), (*itEnd)->getID());
2164 return false;
2165 }
2166 }
2167
2168 ConstMSEdgeVector oldRemainingEdges(myCurrEdge, getRoute().end());
2169 ConstMSEdgeVector newEdges; // only remaining
2170 newEdges.insert(newEdges.end(), myCurrEdge, itStart);
2171 if (!teleport) {
2172 newEdges.insert(newEdges.end(), newBetween.begin(), newBetween.end() - 1);
2173 } else {
2174 newEdges.push_back(*itStart);
2175 }
2176 newEdges.insert(newEdges.end(), itEnd, oldEdges.end());
2177 //std::cout << SIMTIME << " rerouteBetweenStops veh=" << getID()
2178 // << " oldEdges=" << oldRemainingEdges.size()
2179 // << " newEdges=" << newEdges.size()
2180 // << " toNewStop=" << toNewStop.size()
2181 // << " fromNewStop=" << fromNewStop.size()
2182 // << "\n";
2183
2184 const double routeCost = router.recomputeCosts(newEdges, this, t);
2185 const double previousCost = router.recomputeCosts(oldRemainingEdges, this, t);
2186 const double savings = previousCost - routeCost;
2187
2188 if (teleport) {
2189 // let the vehicle jump rather than teleport
2190 // we add a jump-stop at the end of the edge (unless the vehicle is
2191 // already configure to jump before the replaced stop)
2192 if (!insertJump(nextStopIndex, itStart, errorMsg)) {
2193 return false;
2194 };
2195 }
2196 return replaceRouteEdges(newEdges, routeCost, savings, info, !hasDeparted(), false, false, &errorMsg);
2197}
2198
2199
2200bool
2201MSBaseVehicle::insertJump(int nextStopIndex, MSRouteIterator itStart, std::string& errorMsg) {
2202 bool needJump = true;
2203 if (nextStopIndex > 0) {
2204 auto itPriorStop = myStops.begin();
2205 std::advance(itPriorStop, nextStopIndex - 1);
2206 const MSStop& priorStop = *itPriorStop;
2207 if (priorStop.pars.jump >= 0) {
2208 needJump = false;
2209 }
2210 }
2211 if (needJump) {
2212 SUMOVehicleParameter::Stop jumpStopPars;
2213 jumpStopPars.endPos = (*itStart)->getLength();
2214 jumpStopPars.speed = 1000;
2215 jumpStopPars.jump = 0;
2216 jumpStopPars.edge = (*itStart)->getID();
2218 MSLane* jumpStopLane = nullptr;
2219 for (MSLane* cand : (*itStart)->getLanes()) {
2220 if (cand->allowsVehicleClass(getVClass())) {
2221 jumpStopLane = cand;
2222 break;
2223 }
2224 }
2225 if (jumpStopLane == nullptr) {
2226 errorMsg = TL("unable to replace stop with teleporting");
2227 return false;
2228 }
2229 auto itStop = myStops.begin();
2230 std::advance(itStop, nextStopIndex);
2231 MSStop jumpStop(jumpStopPars);
2232 jumpStop.initPars(jumpStopPars);
2233 jumpStop.lane = jumpStopLane;
2234 jumpStop.edge = myRoute->end(); // will be patched in replaceRoute
2235 myStops.insert(itStop, jumpStop);
2236 if (!hasDeparted() && (int)myParameter->stops.size() > nextStopIndex) {
2237 // stops will be rebuilt from scratch so we must patch the stops in myParameter
2238 auto it = myParameter->stops.begin() + nextStopIndex;
2239 const_cast<SUMOVehicleParameter*>(myParameter)->stops.insert(it, jumpStopPars);
2240 }
2241 }
2242 return true;
2243}
2244
2245
2246bool
2247MSBaseVehicle::insertStop(int nextStopIndex, SUMOVehicleParameter::Stop stop, const std::string& info, bool teleport, std::string& errorMsg) {
2248 const int n = (int)myStops.size();
2249 if (nextStopIndex < 0 || nextStopIndex > n) {
2250 errorMsg = TLF("invalid nextStopIndex % for % remaining stops", nextStopIndex, n);
2251 return false;
2252 }
2253 if (nextStopIndex == 0 && isStopped()) {
2254 errorMsg = TL("cannot insert stop before the currently reached stop");
2255 return false;
2256 }
2258 MSLane* stopLane = MSLane::dictionary(stop.lane);
2259 MSEdge* stopEdge = &stopLane->getEdge();
2260
2261 if (!stopLane->allowsVehicleClass(getVClass(), myRoutingMode)) {
2262 errorMsg = TLF("disallowed stop lane '%'", stopLane->getID());
2263 return false;
2264 }
2265
2266 // check parking access rights
2267 if (stop.parkingarea != "") {
2269 if (pa != nullptr && !pa->accepts(this)) {
2270 errorMsg = TLF("Vehicle '%' does not have the right badge to access parkingArea '%'.", getID(), stop.parkingarea);
2271 return false;
2272 }
2273 }
2274
2275 const ConstMSEdgeVector& oldEdges = getRoute().getEdges();
2276 std::vector<MSStop> stops(myStops.begin(), myStops.end());
2277 const int junctionOffset = getLane() != nullptr && getLane()->isInternal() ? 1 : 0;
2278 MSRouteIterator itStart = nextStopIndex == 0 ? getCurrentRouteEdge() + junctionOffset : stops[nextStopIndex - 1].edge;
2279 double startPos = nextStopIndex == 0 ? getPositionOnLane() : stops[nextStopIndex - 1].pars.endPos;
2280 MSRouteIterator itEnd = nextStopIndex == n ? oldEdges.end() - 1 : stops[nextStopIndex].edge;
2281 auto endPos = nextStopIndex == n ? getArrivalPos() : stops[nextStopIndex].pars.endPos;
2283
2284 bool newDestination = nextStopIndex == n && stopEdge == oldEdges.back();
2285
2286 ConstMSEdgeVector toNewStop;
2287 if (!teleport) {
2288 router.compute(*itStart, startPos, stopEdge, stop.endPos, this, t, toNewStop, true);
2289 if (toNewStop.size() == 0) {
2290 errorMsg = TLF("no route found from edge '%' to stop edge '%'", (*itStart)->getID(), stopEdge->getID());
2291 return false;
2292 }
2293 }
2294
2295 ConstMSEdgeVector fromNewStop;
2296 if (!newDestination) {
2297 router.compute(stopEdge, stop.endPos, *itEnd, endPos, this, t, fromNewStop, true);
2298 if (fromNewStop.size() == 0) {
2299 errorMsg = TLF("no route found from stop edge '%' to edge '%'", stopEdge->getID(), (*itEnd)->getID());
2300 return false;
2301 }
2302 }
2303
2304 auto itStop = myStops.begin();
2305 std::advance(itStop, nextStopIndex);
2306 MSStop newStop(stop);
2307 newStop.initPars(stop);
2308 newStop.edge = myRoute->end(); // will be patched in replaceRoute
2309 newStop.lane = stopLane;
2311 newStop.segment = MSGlobals::gMesoNet->getSegmentForEdge(newStop.lane->getEdge(), newStop.getEndPos(*this));
2312 if (newStop.lane->isInternal()) {
2313 errorMsg = TLF("Mesoscopic simulation does not allow stopping on internal edge '%' for vehicle '%'.", stop.edge, getID());
2314 return false;
2315 }
2316 }
2317 myStops.insert(itStop, newStop);
2318
2319 ConstMSEdgeVector oldRemainingEdges(myCurrEdge, getRoute().end());
2320 ConstMSEdgeVector newEdges; // only remaining
2321 newEdges.insert(newEdges.end(), myCurrEdge, itStart);
2322 if (!teleport) {
2323 newEdges.insert(newEdges.end(), toNewStop.begin(), toNewStop.end() - 1);
2324 } else {
2325 newEdges.push_back(*itStart);
2326 }
2327 if (!newDestination) {
2328 newEdges.insert(newEdges.end(), fromNewStop.begin(), fromNewStop.end() - 1);
2329 newEdges.insert(newEdges.end(), itEnd, oldEdges.end());
2330 } else {
2331 newEdges.push_back(stopEdge);
2332 }
2333 //std::cout << SIMTIME << " insertStop veh=" << getID()
2334 // << " teleport=" << teleport
2335 // << " busStop=" << stop.busstop
2336 // << " oldEdges=" << oldRemainingEdges.size()
2337 // << " newEdges=" << newEdges.size()
2338 // << " toNewStop=" << toNewStop.size()
2339 // << " fromNewStop=" << fromNewStop.size()
2340 // << "\n";
2341
2342 const double routeCost = router.recomputeCosts(newEdges, this, t);
2343 const double previousCost = router.recomputeCosts(oldRemainingEdges, this, t);
2344 const double savings = previousCost - routeCost;
2345
2346 if (!hasDeparted() && (int)myParameter->stops.size() >= nextStopIndex) {
2347 // stops will be rebuilt from scratch so we must patch the stops in myParameter
2348 auto it = myParameter->stops.begin() + nextStopIndex;
2349 const_cast<SUMOVehicleParameter*>(myParameter)->stops.insert(it, stop);
2350 }
2351 return replaceRouteEdges(newEdges, routeCost, savings, info, !hasDeparted(), false, false, &errorMsg);
2352}
2353
2354
2355double
2357 if (static_cast<MSDevice_Battery*>(getDevice(typeid(MSDevice_Battery))) != 0) {
2358 MSDevice_Battery* batteryOfVehicle = dynamic_cast<MSDevice_Battery*>(getDevice(typeid(MSDevice_Battery)));
2359 return batteryOfVehicle->getActualBatteryCapacity();
2360 } else {
2361 if (static_cast<MSDevice_ElecHybrid*>(getDevice(typeid(MSDevice_ElecHybrid))) != 0) {
2362 MSDevice_ElecHybrid* batteryOfVehicle = dynamic_cast<MSDevice_ElecHybrid*>(getDevice(typeid(MSDevice_ElecHybrid)));
2363 return batteryOfVehicle->getActualBatteryCapacity();
2364 }
2365 }
2366 return -1;
2367}
2368
2369
2370double
2372 if (static_cast<MSDevice_Battery*>(getDevice(typeid(MSDevice_Battery))) != 0) {
2373 MSDevice_Battery* batteryOfVehicle = dynamic_cast<MSDevice_Battery*>(getDevice(typeid(MSDevice_Battery)));
2374 return batteryOfVehicle->getActualBatteryCapacity() / batteryOfVehicle->getMaximumBatteryCapacity();
2375 } else {
2376 if (static_cast<MSDevice_ElecHybrid*>(getDevice(typeid(MSDevice_ElecHybrid))) != 0) {
2377 MSDevice_ElecHybrid* batteryOfVehicle = dynamic_cast<MSDevice_ElecHybrid*>(getDevice(typeid(MSDevice_ElecHybrid)));
2378 return batteryOfVehicle->getActualBatteryCapacity() / batteryOfVehicle->getMaximumBatteryCapacity();
2379 }
2380 }
2381 return -1;
2382}
2383
2384
2385double
2387 if (static_cast<MSDevice_Battery*>(getDevice(typeid(MSDevice_Battery))) != 0) {
2388 MSDevice_Battery* batteryOfVehicle = dynamic_cast<MSDevice_Battery*>(getDevice(typeid(MSDevice_Battery)));
2389 return batteryOfVehicle->getEnergyCharged();
2390 } else {
2391 if (static_cast<MSDevice_ElecHybrid*>(getDevice(typeid(MSDevice_ElecHybrid))) != 0) {
2392 MSDevice_ElecHybrid* batteryOfVehicle = dynamic_cast<MSDevice_ElecHybrid*>(getDevice(typeid(MSDevice_ElecHybrid)));
2393 return batteryOfVehicle->getEnergyCharged();
2394 }
2395 }
2396 return -1;
2397}
2398
2399
2400double
2402 if (static_cast<MSDevice_Battery*>(getDevice(typeid(MSDevice_Battery))) != 0) {
2403 MSDevice_Battery* batteryOfVehicle = dynamic_cast<MSDevice_Battery*>(getDevice(typeid(MSDevice_Battery)));
2404 return batteryOfVehicle->getMaximumChargeRate();
2405 }
2406 return -1;
2407}
2408
2409
2410double
2412 if (static_cast<MSDevice_ElecHybrid*>(getDevice(typeid(MSDevice_ElecHybrid))) != 0) {
2413 MSDevice_ElecHybrid* elecHybridDevice = dynamic_cast<MSDevice_ElecHybrid*>(getDevice(typeid(MSDevice_ElecHybrid)));
2414 return elecHybridDevice->getCurrentFromOverheadWire();
2415 }
2416
2417 return NAN;
2418}
2419
2420double
2422 if (isOnRoad() || isIdling()) {
2424 } else {
2425 return 0.;
2426 }
2427}
2428
2429
2434
2435
2440
2441
2444 if (myEdgeWeights == nullptr) {
2446 }
2447 return *myEdgeWeights;
2448}
2449
2450
2451
2452
2453int
2455 int boarded = myPersonDevice == nullptr ? 0 : myPersonDevice->size();
2456 return boarded + myParameter->personNumber;
2457}
2458
2459int
2461 int leavingPersonNumber = 0;
2462 const std::vector<MSTransportable*>& persons = getPersons();
2463 for (std::vector<MSTransportable*>::const_iterator it_p = persons.begin(); it_p != persons.end(); ++it_p) {
2464 MSStageDriving* const stage = dynamic_cast<MSStageDriving*>((*it_p)->getCurrentStage());
2465 const MSStop* stop = &myStops.front();
2466 const MSVehicle* joinVeh = dynamic_cast<MSVehicle*>(MSNet::getInstance()->getVehicleControl().getVehicle((*stop).pars.join));
2467 if (stop && stage->canLeaveVehicle(*it_p, *this, *stop) && !MSDevice_Transportable::willTransferAtJoin(*it_p, joinVeh)) {
2468 leavingPersonNumber++;
2469 }
2470 }
2471 return leavingPersonNumber;
2472}
2473
2474std::vector<std::string>
2476 std::vector<std::string> ret;
2477 const std::vector<MSTransportable*>& persons = getPersons();
2478 for (std::vector<MSTransportable*>::const_iterator it_p = persons.begin(); it_p != persons.end(); ++it_p) {
2479 ret.push_back((*it_p)->getID());
2480 }
2481 return ret;
2482}
2483
2484int
2486 int loaded = myContainerDevice == nullptr ? 0 : myContainerDevice->size();
2487 return loaded + myParameter->containerNumber;
2488}
2489
2490
2491void
2493 // this might be called from the MSTransportable destructor so we cannot do a dynamic cast to determine the type
2494 if (myPersonDevice != nullptr) {
2496 }
2497 if (myContainerDevice != nullptr) {
2499 }
2500 if (myEnergyParams != nullptr) {
2502 }
2503}
2504
2505
2506void
2512
2513
2514const std::vector<MSTransportable*>&
2516 if (myPersonDevice == nullptr) {
2518 } else {
2520 }
2521}
2522
2523
2524const std::vector<MSTransportable*>&
2526 if (myContainerDevice == nullptr) {
2528 } else {
2530 }
2531}
2532
2533
2534bool
2535MSBaseVehicle::isLineStop(double position) const {
2536 if (myParameter->line == "") {
2537 // not a public transport line
2538 return false;
2539 }
2540 for (const SUMOVehicleParameter::Stop& stop : myParameter->stops) {
2541 if (stop.startPos <= position && position <= stop.endPos) {
2542 return true;
2543 }
2544 }
2545 for (const SUMOVehicleParameter::Stop& stop : myRoute->getStops()) {
2546 if (stop.startPos <= position && position <= stop.endPos) {
2547 return true;
2548 }
2549 }
2550 return false;
2551}
2552
2553
2554bool
2555MSBaseVehicle::hasDevice(const std::string& deviceName) const {
2556 for (MSDevice* const dev : myDevices) {
2557 if (dev->deviceName() == deviceName) {
2558 return true;
2559 }
2560 }
2561 return false;
2562}
2563
2564
2565void
2566MSBaseVehicle::createDevice(const std::string& deviceName) {
2567 if (!hasDevice(deviceName)) {
2568 if (deviceName == "rerouting") {
2569 ((SUMOVehicleParameter*)myParameter)->setParameter("has." + deviceName + ".device", "true");
2571 if (hasDeparted()) {
2572 // vehicle already departed: disable pre-insertion rerouting and enable regular routing behavior
2573 MSDevice_Routing* routingDevice = static_cast<MSDevice_Routing*>(getDevice(typeid(MSDevice_Routing)));
2574 assert(routingDevice != 0);
2576 }
2577 } else {
2578 throw InvalidArgument(TLF("creating device of type '%' is not supported", deviceName));
2579 }
2580 }
2581}
2582
2583
2584std::string
2585MSBaseVehicle::getDeviceParameter(const std::string& deviceName, const std::string& key) const {
2586 for (MSVehicleDevice* const dev : myDevices) {
2587 if (dev->deviceName() == deviceName) {
2588 return dev->getParameter(key);
2589 }
2590 }
2591 throw InvalidArgument(TLF("no device of type '%' exists", deviceName));
2592}
2593
2594
2595void
2596MSBaseVehicle::setDeviceParameter(const std::string& deviceName, const std::string& key, const std::string& value) {
2597 for (MSVehicleDevice* const dev : myDevices) {
2598 if (dev->deviceName() == deviceName) {
2599 dev->setParameter(key, value);
2600 return;
2601 }
2602 }
2603 throw InvalidArgument(TLF("no device of type '%' exists", deviceName));
2604}
2605
2606
2607void
2608MSBaseVehicle::setJunctionModelParameter(const std::string& key, const std::string& value) {
2611 const_cast<SUMOVehicleParameter&>(getParameter()).setParameter(key, value);
2612 // checked in MSLink::ignoreFoe
2613 } else {
2614 throw InvalidArgument(TLF("Vehicle '%' does not support junctionModel parameter '%'.", getID(), key));
2615 }
2616}
2617
2618
2619void
2620MSBaseVehicle::setCarFollowModelParameter(const std::string& key, const std::string& value) {
2621 // handle some generic params first and then delegate to the carFollowModel itself
2624 const_cast<SUMOVehicleParameter&>(getParameter()).setParameter(key, value);
2625 // checked in MSVehicle::planMove
2626 } else {
2627 MSVehicle* microVeh = dynamic_cast<MSVehicle*>(this);
2628 if (microVeh) {
2629 // remove 'carFollowModel.' prefix
2630 const std::string attrName = key.substr(15);
2631 microVeh->getCarFollowModel().setParameter(microVeh, attrName, value);
2632 }
2633 }
2634}
2635
2636
2637void
2639 /* Design idea for additional junction model parameters:
2640 We can distinguish between 3 levels of parameters
2641 1. typically shared by multiple vehicles -> vType parameter
2642 2. specific to one vehicle but stays constant throughout the simulation -> vehicle parameter
2643 3. specific to one vehicle and expected to change during simulation -> prefixed generic vehicle parameter
2644 */
2645 for (auto item : getParameter().getParametersMap()) {
2646 if (StringUtils::startsWith(item.first, "junctionModel.")) {
2647 setJunctionModelParameter(item.first, item.second);
2648 } else if (StringUtils::startsWith(item.first, "carFollowModel.")) {
2649 setCarFollowModelParameter(item.first, item.second);
2650 }
2651 }
2652 const std::string routingModeStr = getStringParam("device.rerouting.mode");
2653 try {
2654 int routingMode = StringUtils::toInt(routingModeStr);
2655 if (routingMode != libsumo::ROUTING_MODE_DEFAULT) {
2656 setRoutingMode(routingMode);
2657 }
2658 } catch (NumberFormatException&) {
2659 // @todo interpret symbolic constants
2660 throw ProcessError(TLF("could not interpret routing.mode '%'", routingModeStr));
2661 }
2662}
2663
2664
2673
2674
2675void
2677 assert(type != nullptr);
2678 // save old parameters before possible type deletion
2679 const double oldMu = myType->getSpeedFactor().getParameter(0);
2680 const double oldDev = myType->getSpeedFactor().getParameter(1);
2681 if (myType->isVehicleSpecific() && type != myType) {
2683 }
2684 // adapt myChosenSpeedFactor to the new type
2685 if (oldDev == 0.) {
2686 // old type had speedDev 0, reroll
2688 } else {
2689 // map old speedFactor onto new distribution
2690 const double distPoint = (myChosenSpeedFactor - oldMu) / oldDev;
2691 const double newMu = type->getSpeedFactor().getParameter(0);
2692 const double newDev = type->getSpeedFactor().getParameter(1);
2693 myChosenSpeedFactor = newMu + distPoint * newDev;
2694 // respect distribution limits
2697 }
2698 myType = type;
2699 if (myEnergyParams != nullptr) {
2701 }
2702}
2703
2704
2707 if (myType->isVehicleSpecific()) {
2708 return *const_cast<MSVehicleType*>(myType);
2709 }
2710 MSVehicleType* type = myType->buildSingularType(myType->getID() + "@" + getID());
2711 replaceVehicleType(type);
2712 return *type;
2713}
2714
2715
2716int
2718 const MSLane* const lane = getLane();
2719 if (lane == nullptr) {
2720 return getEdge()->getLanes()[0]->getRNGIndex();
2721 } else {
2722 return lane->getRNGIndex();
2723 }
2724}
2725
2726
2727SumoRNG*
2729 const MSLane* lane = getLane();
2730 if (lane == nullptr) {
2731 return getEdge()->getLanes()[0]->getRNG();
2732 } else {
2733 return lane->getRNG();
2734 }
2735}
2736
2737std::string
2738MSBaseVehicle::getPrefixedParameter(const std::string& key, std::string& error) const {
2739 const MSVehicle* microVeh = dynamic_cast<const MSVehicle*>(this);
2740 if (StringUtils::startsWith(key, "device.")) {
2741 StringTokenizer tok(key, ".");
2742 if (tok.size() < 3) {
2743 error = TLF("Invalid device parameter '%' for vehicle '%'.", key, getID());
2744 return "";
2745 }
2746 try {
2747 return getDeviceParameter(tok.get(1), key.substr(tok.get(0).size() + tok.get(1).size() + 2));
2748 } catch (InvalidArgument& e) {
2749 error = TLF("Vehicle '%' does not support device parameter '%' (%).", getID(), key, e.what());
2750 return "";
2751 }
2752 } else if (StringUtils::startsWith(key, "laneChangeModel.")) {
2753 if (microVeh == nullptr) {
2754 error = TLF("Mesoscopic vehicle '%' does not support laneChangeModel parameters.", getID());
2755 return "";
2756 }
2757 const std::string attrName = key.substr(16);
2758 try {
2759 return microVeh->getLaneChangeModel().getParameter(attrName);
2760 } catch (InvalidArgument& e) {
2761 error = TLF("Vehicle '%' does not support laneChangeModel parameter '%' (%).", getID(), key, e.what());
2762 return "";
2763 }
2764 } else if (StringUtils::startsWith(key, "carFollowModel.")) {
2765 if (microVeh == nullptr) {
2766 error = TLF("Mesoscopic vehicle '%' does not support carFollowModel parameters.", getID());
2767 return "";
2768 }
2769 const std::string attrName = key.substr(15);
2770 try {
2771 return microVeh->getCarFollowModel().getParameter(microVeh, attrName);
2772 } catch (InvalidArgument& e) {
2773 error = TLF("Vehicle '%' does not support carFollowModel parameter '%' (%).", getID(), key, e.what());
2774 return "";
2775 }
2776 } else if (StringUtils::startsWith(key, "has.") && StringUtils::endsWith(key, ".device")) {
2777 StringTokenizer tok(key, ".");
2778 if (tok.size() != 3) {
2779 error = TL("Invalid check for device. Expected format is 'has.DEVICENAME.device'.");
2780 return "";
2781 }
2782 return hasDevice(tok.get(1)) ? "true" : "false";
2783 // parking related parameters start here
2784 } else if (key == "parking.rerouteCount") {
2786 } else if (StringUtils::startsWith(key, "parking.memory.")) {
2787 std::vector<std::string> values;
2788 if (getParkingMemory()) {
2789 if (key == "parking.memory.IDList") {
2790 for (const auto& item : *getParkingMemory()) {
2791 values.push_back(item.first->getID());
2792 }
2793 } else if (key == "parking.memory.score") {
2794 for (const auto& item : *getParkingMemory()) {
2795 values.push_back(item.second.score);
2796 }
2797 } else if (key == "parking.memory.blockedAtTime") {
2798 for (const auto& item : *getParkingMemory()) {
2799 values.push_back(toString(STEPS2TIME(item.second.blockedAtTime)));
2800 }
2801 } else if (key == "parking.memory.blockedAtTimeLocal") {
2802 for (const auto& item : *getParkingMemory()) {
2803 values.push_back(toString(STEPS2TIME(item.second.blockedAtTimeLocal)));
2804 }
2805 } else {
2806 error = TLF("Unsupported parking parameter '%' for vehicle '%'.", key, getID());
2807 }
2808 }
2809 return toString(values);
2810 } else {
2811 // default: custom user parameter
2812 return getParameter().getParameter(key, "");
2813 }
2814}
2815
2816
2817void
2824
2825
2826void
2832
2833
2834void
2836 if (myChargingMemory == nullptr) {
2838 }
2840}
2841
2842
2843void
2849
2850
2851void
2852MSBaseVehicle::rememberParkingAreaScore(const MSStoppingPlace* pa, const std::string& score) {
2853 if (myParkingMemory == nullptr) {
2855 }
2857}
2858
2859
2862 if (myParkingMemory == nullptr) {
2863 return -1;
2864 }
2865 return myParkingMemory->sawBlockedStoppingPlace(pa, local);
2866}
2867
2868
2875
2876
2879 if (myChargingMemory == nullptr) {
2880 return -1;
2881 }
2882 return myChargingMemory->sawBlockedStoppingPlace(cs, local);
2883}
2884
2885
2886#ifdef _DEBUG
2887void
2888MSBaseVehicle::initMoveReminderOutput(const OptionsCont& oc) {
2889 if (oc.isSet("movereminder-output.vehicles")) {
2890 const std::vector<std::string> vehicles = oc.getStringVector("movereminder-output.vehicles");
2891 myShallTraceMoveReminders.insert(vehicles.begin(), vehicles.end());
2892 }
2893}
2894
2895
2896void
2897MSBaseVehicle::traceMoveReminder(const std::string& type, MSMoveReminder* rem, double pos, bool keep) const {
2898 OutputDevice& od = OutputDevice::getDeviceByOption("movereminder-output");
2899 od.openTag("movereminder");
2900 od.writeAttr(SUMO_ATTR_TIME, STEPS2TIME(MSNet::getInstance()->getCurrentTimeStep()));
2901 od.writeAttr("veh", getID());
2903 od.writeAttr("type", type);
2904 od.writeAttr("pos", toString(pos));
2905 od.writeAttr("keep", toString(keep));
2906 od.closeTag();
2907}
2908#endif
2909
2910
2911/****************************************************************************/
long long int SUMOTime
Definition GUI.h:36
std::vector< const MSEdge * > ConstMSEdgeVector
Definition MSEdge.h:74
ConstMSEdgeVector::const_iterator MSRouteIterator
Definition MSRoute.h:57
#define WRITE_WARNINGF(...)
Definition MsgHandler.h:287
#define WRITE_ERRORF(...)
Definition MsgHandler.h:296
#define WRITE_WARNING(msg)
Definition MsgHandler.h:286
#define TL(string)
Definition MsgHandler.h:304
#define TLF(string,...)
Definition MsgHandler.h:306
std::shared_ptr< const MSRoute > ConstMSRoutePtr
Definition Route.h:32
std::string time2string(SUMOTime t, bool humanReadable)
convert SUMOTime to string (independently of global format setting)
Definition SUMOTime.cpp:91
#define STEPS2TIME(x)
Definition SUMOTime.h:55
#define SIMSTEP
Definition SUMOTime.h:61
#define SUMOTime_MAX
Definition SUMOTime.h:34
#define SIMTIME
Definition SUMOTime.h:62
#define TIME2STEPS(x)
Definition SUMOTime.h:57
bool isRailway(SVCPermissions permissions)
Returns whether an edge with the given permissions is a (exclusive) railway edge.
@ RANDOM
The edge is chosen randomly.
@ GIVEN
The edge index is given.
@ DEFAULT
No information given; use default.
const int STOP_INDEX_END
const long long int VEHPARS_FORCE_REROUTE
DepartLaneDefinition
Possible ways to choose a lane on depart.
@ GIVEN
The speed is given.
@ GIVEN
The position is given.
@ DEFAULT
No information given; use default.
@ BASE
Back-at-zero position.
const int STOP_SPEED_SET
const long long int VEHPARS_CFMODEL_PARAMS_SET
@ RANDOM
The lane is chosen randomly.
@ GIVEN
The arrival lane is given.
@ FIRST_ALLOWED
The rightmost lane the vehicle may use.
std::vector< SUMOVehicleParameter::Stop > StopParVector
@ GIVEN
The speed is given.
const int STOP_INDEX_REPEAT
const long long int VEHPARS_PARKING_BADGES_SET
const int STOP_INDEX_FIT
const long long int VEHPARS_JUNCTIONMODEL_PARAMS_SET
const long long int VEHPARS_SPEEDFACTOR_SET
@ RANDOM
The arrival position is chosen randomly.
@ GIVEN
The arrival position is given.
@ CENTER
Half the road length.
const int STOP_JUMP_SET
const long long int VEHPARS_LINE_SET
const long long int VEHPARS_INSERTION_CHECKS_SET
@ CONTAINER_TRIGGERED
The departure is container triggered.
@ TRIGGERED
The departure is person triggered.
@ SUMO_TAG_CLOSING_REROUTE
reroute of type closing
@ SUMO_TAG_VEHICLE
description of a vehicle
@ SUMO_TAG_PARKING_AREA
A parking area.
@ SUMO_ATTR_CF_IGNORE_IDS
@ SUMO_ATTR_JM_IGNORE_IDS
@ SUMO_ATTR_JM_IGNORE_TYPES
@ SUMO_ATTR_LINE
@ SUMO_ATTR_REROUTE
@ SUMO_ATTR_DISTANCE
@ SUMO_ATTR_SPEEDFACTOR
@ SUMO_ATTR_ROUTE
@ SUMO_ATTR_ID
@ SUMO_ATTR_CF_IGNORE_TYPES
@ SUMO_ATTR_ARRIVALPOS_RANDOMIZED
@ SUMO_ATTR_TIME
trigger: the time of the step
double gWeightsRandomFactor
Definition StdDefs.cpp:35
int gPrecisionRandom
Definition StdDefs.cpp:30
const double INVALID_DOUBLE
invalid double
Definition StdDefs.h:68
T MIN2(T a, T b)
Definition StdDefs.h:80
const double SUMO_const_haltingSpeed
the speed threshold at which vehicles are considered as halting
Definition StdDefs.h:62
T MAX2(T a, T b)
Definition StdDefs.h:86
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition ToString.h:46
double getMax() const
Returns the maximum value of this distribution.
double getMin() const
Returns the minimum value of this distribution.
double getParameter(const int index) const
Returns the nth parameter of this distribution.
double getTransportableMass() const
Returns the mass of all transportables in the vehicle.
void setSecondary(const EnergyParams *secondaryParams)
Set secondary params.
void setTransportableMass(const double mass)
Sets the mass of all transportables in the vehicle.
static double computeNoise(SUMOEmissionClass c, double v, double a)
Returns the noise produced by the a vehicle of the given type at the given speed.
MESegment * getSegmentForEdge(const MSEdge &e, double pos=0)
Get the segment for a given edge at a given position.
Definition MELoop.cpp:340
virtual std::string getParameter(const std::string &key) const
try to retrieve the given parameter from this laneChangeModel. Throw exception for unsupported key
double getMaxSpeed() const
Returns the maximum speed (the minimum of desired and technical maximum speed)
bool haveValidStopEdges(bool silent=false) const
check whether all stop.edge MSRouteIterators are valid and in order
int myRoutingMode
routing mode (see TraCIConstants.h)
bool hasJump(const MSRouteIterator &it) const
check wether the vehicle has jump at the given part of its route
bool hasReminder(MSMoveReminder *rem) const
Checks whether the vehilce has the given MoveReminder.
static double addStopPriority(double p1, double p2)
std::list< MSStop > myStops
The vehicle's list of stops.
StoppingPlaceMemory * myParkingMemory
memory for parking search
double getImpatience() const
Returns this vehicles impatience.
void setSkips(MSStop &stop, int prevActiveStops)
patch stop.pars.index to record the number of skipped candidate edges before stop....
virtual ConstMSEdgeVector::const_iterator getRerouteOrigin() const
Returns the starting point for reroutes (usually the current edge)
const StoppingPlaceMemory * getParkingMemory() const
const std::vector< MSTransportable * > & getPersons() const
retrieve riding persons
virtual void initDevices()
void rememberParkingAreaScore(const MSStoppingPlace *pa, const std::string &score)
score only needed when running with gui
const long long int myRandomSeed
const MSEdge * succEdge(int nSuccs) const
Returns the nSuccs'th successor of edge the vehicle is currently at.
int getDepartEdge() const
Returns the edge on which this vehicle shall depart.
void resetRoutePosition(int index, DepartLaneDefinition departLaneProcedure)
reset index of edge within route
std::string getDeviceParameter(const std::string &deviceName, const std::string &key) const
try to retrieve the given parameter from any of the vehicles devices, raise InvalidArgument if no dev...
StoppingPlaceMemory * myChargingMemory
bool replaceStop(int nextStopIndex, SUMOVehicleParameter::Stop stop, const std::string &info, bool teleport, std::string &errorMsg)
int getLeavingPersonNumber() const
Returns the number of leaving persons.
MSBaseVehicle(SUMOVehicleParameter *pars, ConstMSRoutePtr route, MSVehicleType *type, const double speedFactor)
Constructor.
void calculateArrivalParams(bool onInit)
(Re-)Calculates the arrival position and lane from the vehicle parameters
virtual double getArrivalPos() const
Returns this vehicle's desired arrivalPos for its current route (may change on reroute)
void setCarFollowModelParameter(const std::string &key, const std::string &value)
set individual carFollow model parameters (not type related)
void setRoutingMode(int value)
Sets routing behavior.
void resetParkingAreaScores()
static NumericalID myCurrentNumericalIndex
bool rerouteBetweenStops(int nextStopIndex, const std::string &info, bool teleport, std::string &errorMsg)
MoveReminderCont myMoveReminders
Currently relevant move reminders.
void rememberChargingStationScore(const MSStoppingPlace *cs, const std::string &score)
int getInsertionChecks() const
double myDepartPos
The real depart position.
const SUMOVehicleParameter & getParameter() const
Returns the vehicle's parameter (including departure definition)
double getMaxChargeRate() const
Returns the maximum charge rate allowed by the battery in the current time step (W)
void replaceParameter(const SUMOVehicleParameter *newParameter)
replace the vehicle parameter (deleting the old one)
void rememberBlockedParkingArea(const MSStoppingPlace *pa, bool local)
int getNumberParkingReroutes() const
std::vector< MSVehicleDevice * > myDevices
The devices this vehicle has.
virtual const MSEdge * getCurrentEdge() const
Returns the edge the vehicle is currently at (possibly an internal edge)
double getPreviousSpeed() const
Returns the vehicle's previous speed.
void removeTransportableMass(MSTransportable *t)
removes a person or containers mass
MSStop & getNextStopMutable()
virtual void addTransportable(MSTransportable *transportable)
Adds a person or container to this vehicle.
virtual BaseInfluencer & getBaseInfluencer()=0
Returns the velocity/lane influencer.
const SUMOVehicleParameter::Stop * getNextStopParameter() const
return parameters for the next stop (SUMOVehicle Interface)
void rememberBlockedChargingStation(const MSStoppingPlace *cs, bool local)
virtual bool replaceRoute(ConstMSRoutePtr route, const std::string &info, bool onInit=false, int offset=0, bool addRouteStops=true, bool removeStops=true, std::string *msgReturn=nullptr)
Replaces the current route by the given one.
SUMOTime activateRemindersOnReroute(SUMOTime currentTime)
remove outdated driveways on reroute
int getNumRemainingEdges() const
return the number of edges remaining in the route (include the current)
double getOdometer() const
Returns the distance that was already driven by this vehicle.
bool isRail() const
virtual bool hasArrived() const
Returns whether this vehicle has already arived (by default this is true if the vehicle has reached i...
const NumericalID myNumericalID
bool isStoppedInRange(const double pos, const double tolerance, bool checkFuture=false) const
return whether the given position is within range of the current stop
bool isJumping() const
Returns whether the vehicle is perform a jump.
void checkRouteRemoval()
remove route at the end of the simulation
MSVehicleType & getSingularType()
Replaces the current vehicle type with a new one used by this vehicle only.
const MSVehicleType * myType
This vehicle's type.
const MSRouteIterator & getCurrentRouteEdge() const
Returns an iterator pointing to the current edge in this vehicles route.
bool isStoppedParking() const
Returns whether the vehicle is on a parking stop.
void unregisterWaiting()
mark vehicle as active
bool hasValidRoute(std::string &msg, ConstMSRoutePtr route=0) const
Validates the current or given route.
double getLength() const
Returns the vehicle's length.
bool isParking() const
Returns whether the vehicle is parking.
MSParkingArea * getCurrentParkingArea()
get the current parking area stop or nullptr
const MSEdge * getEdge() const
Returns the edge the vehicle is currently at.
double getHarmonoise_NoiseEmissions() const
Returns noise emissions of the current state.
int getPersonNumber() const
Returns the number of persons.
double getRelativeStateOfCharge() const
Returns actual relative state of charge of battery (-)
void setJunctionModelParameter(const std::string &key, const std::string &value)
set individual junction model paramete (not type related)
void setDepartAndArrivalEdge()
apply departEdge and arrivalEdge attributes
void setID(const std::string &newID)
set the id (inherited from Named but forbidden for vehicles)
MSRouteIterator myCurrEdge
Iterator to current route-edge.
static MSLane * interpretOppositeStop(SUMOVehicleParameter::Stop &stop)
interpret stop lane on opposite side of the road
StopParVector myPastStops
The list of stops that the vehicle has already reached.
static std::vector< MSTransportable * > myEmptyTransportableVector
const std::vector< std::string > & getParkingBadges() const
get the valid parking access rights (vehicle settings override vehicle type settings)
bool hasDeparted() const
Returns whether this vehicle has already departed.
bool ignoreTransientPermissions() const
Returns whether this object is ignoring transient permission changes (during routing)
virtual void resetApproachOnReroute()
reset rail signal approach information
ConstMSRoutePtr myRoute
This vehicle's route.
MSDevice_Transportable * myContainerDevice
The containers this vehicle may have.
void resetChargingStationScores()
bool allowsBoarding(const MSTransportable *t) const
whether the given transportable is allowed to board this vehicle
double getStateOfCharge() const
Returns actual state of charge of battery (Wh) RICE_CHECK: This may be a misnomer,...
MSEdgeWeightsStorage & _getWeightsStorage() const
virtual bool handleCollisionStop(MSStop &stop, const double distToStop)
bool hasDevice(const std::string &deviceName) const
check whether the vehicle is equiped with a device of the given name
void addReminder(MSMoveReminder *rem, double pos=0)
Adds a MoveReminder dynamically.
SumoRNG * getRNG() const
SUMOTime getDeparture() const
Returns this vehicle's real departure time.
SUMOTime sawBlockedChargingStation(const MSStoppingPlace *cs, bool local) const
EnergyParams * getEmissionParameters() const
retrieve parameters for the energy consumption model
double basePos(const MSEdge *edge) const
departure position where the vehicle fits fully onto the edge (if possible)
void setDeviceParameter(const std::string &deviceName, const std::string &key, const std::string &value)
try to set the given parameter from any of the vehicles devices, raise InvalidArgument if no device p...
MSDevice_Transportable * myPersonDevice
The passengers this vehicle may have.
bool hasStops() const
Returns whether the vehicle has to stop somewhere.
std::string getFlowID() const
reconstruct flow id from vehicle id
virtual void activateReminders(const MSMoveReminder::Notification reason, const MSLane *enteredLane=0)
"Activates" all current move reminder
bool isLineStop(double position) const
returns whether the vehicle serves a public transport line that serves the given stop
double myChosenSpeedFactor
A precomputed factor by which the driver wants to be faster than the speed limit.
const MSStop & getNextStop() const
@ ROUTE_INVALID
route was checked and is valid
@ ROUTE_START_INVALID_PERMISSIONS
std::string getPrefixedParameter(const std::string &key, std::string &error) const
retrieve parameters of devices, models and the vehicle itself
bool replaceWithAlternative(std::list< MSStop >::iterator iter, const MSRouteIterator searchStart, const MSRouteIterator end)
replace stop with a same-name alternative that is on the route and return success
void addStops(const bool ignoreStopErrors, MSRouteIterator *searchStart=nullptr, bool addRouteStops=true)
Adds stops to the built vehicle.
void removeTransportable(MSTransportable *t)
removes a person or container
SUMOTime sawBlockedParkingArea(const MSStoppingPlace *pa, bool local) const
SUMOVehicleClass getVClass() const
Returns the vehicle's access class.
MSParkingArea * getNextParkingArea()
get the upcoming parking area stop or nullptr
int myArrivalLane
The destination lane where the vehicle stops.
int getRouteValidity(bool update=true, bool silent=false, std::string *msgReturn=nullptr)
check for route validity at first insertion attempt
MSStop & getStop(int nextStopIndex)
virtual ~MSBaseVehicle()
Destructor.
bool insertStop(int nextStopIndex, SUMOVehicleParameter::Stop stop, const std::string &info, bool teleport, std::string &errorMsg)
virtual bool instantStopping() const
whether instant stopping is permitted
SUMOTime myDeparture
The real departure time.
std::vector< std::string > getPersonIDList() const
Returns the list of persons.
const MSEdgeWeightsStorage & getWeightsStorage() const
Returns the vehicle's internal edge travel times/efforts container.
bool isStoppedTriggered() const
Returns whether the vehicle is on a triggered stop.
virtual bool resumeFromStopping()=0
virtual bool hasInfluencer() const =0
whether the vehicle is individually influenced (via TraCI or special parameters)
const std::set< SUMOTrafficObject::NumericalID > getUpcomingEdgeIDs() const
returns the numerical ids of edges to travel
bool stopsAtEdge(const MSEdge *edge) const
Returns whether the vehicle stops at the given edge.
bool addStop(const SUMOVehicleParameter::Stop &stopPar, std::string &errorMsg, SUMOTime untilOffset=0, MSRouteIterator *searchStart=nullptr)
Adds a stop.
double getChargedEnergy() const
Returns the energy charged to the battery in the current time step (Wh)
void onDepart()
Called when the vehicle is inserted into the network.
void removeReminder(MSMoveReminder *rem)
Removes a MoveReminder dynamically.
SUMOTime getStopDuration() const
get remaining stop duration or 0 if the vehicle isn't stopped
virtual double getAcceleration() const
Returns the vehicle's acceleration.
virtual bool addTraciStop(SUMOVehicleParameter::Stop stop, std::string &errorMsg)
const MSRoute & getRoute() const
Returns the current route.
int getRoutingMode() const
return routing mode (configures router choice but also handling of transient permission changes)
int getRoutePosition() const
return index of edge within route
bool replaceParkingArea(MSParkingArea *parkingArea, std::string &errorMsg)
replace the current parking area stop with a new stop with merge duration
static const SUMOTime NOT_YET_DEPARTED
SUMOTime getDepartDelay() const
Returns the depart delay.
double getElecHybridCurrent() const
Returns actual current (A) of ElecHybrid device RICE_CHECK: Is this the current consumed from the ove...
bool myAmRegisteredAsWaiting
Whether this vehicle is registered as waiting for a person or container (for deadlock-recognition)
SUMOAbstractRouter< MSEdge, SUMOVehicle > & getRouterTT() const
EnergyParams * myEnergyParams
The emission parameters this vehicle may have.
const SUMOVehicleParameter * myParameter
This vehicle's parameter.
virtual bool hasValidRouteStart(std::string &msg)
checks wether the vehicle can depart on the first edge
int myRouteValidity
status of the current vehicle route
std::vector< std::pair< int, double > > getStopIndices() const
return list of route indices for the remaining stops
SUMOTime myStopUntilOffset
The offset when adding route stops with 'until' on route replacement.
virtual bool isOnRoad() const
Returns the information whether the vehicle is on a road (is simulated)
const std::vector< MSTransportable * > & getContainers() const
retrieve riding containers
bool reroute(SUMOTime t, const std::string &info, SUMOAbstractRouter< MSEdge, SUMOVehicle > &router, const bool onInit=false, const bool withTaz=false, const bool silent=false, const MSEdge *sink=nullptr)
Performs a rerouting using the given router.
bool stopsAt(MSStoppingPlace *stop) const
Returns whether the vehicle stops at the given stopping place.
int getRNGIndex() const
MSEdgeWeightsStorage * myEdgeWeights
const MSVehicleType & getVehicleType() const
Returns the vehicle's type definition.
void createDevice(const std::string &deviceName)
create device of the given type
bool isStopped() const
Returns whether the vehicle is at a stop.
MSDevice * getDevice(const std::type_info &type) const
Returns a device of the given type if it exists, nullptr otherwise.
bool abortNextStop(int nextStopIndex=0)
deletes the next stop at the given index if it exists
int myNumberReroutes
The number of reroutings.
double myArrivalPos
The position on the destination lane where the vehicle stops.
bool insertJump(int nextStopIndex, MSRouteIterator itStart, std::string &errorMsg)
helper function
virtual void saveState(OutputDevice &out)
Saves the (common) state of a vehicle.
virtual void replaceVehicleType(const MSVehicleType *type)
Replaces the current vehicle type by the one given.
std::vector< StopEdgeInfo > getStopEdges(double &firstPos, double &lastPos, std::set< int > &jumps) const
Returns the list of still pending stop edges also returns the first and last stop position.
double myOdometer
A simple odometer to keep track of the length of the route already driven.
void initTransientModelParams()
init model parameters from generic params
int getContainerNumber() const
Returns the number of containers.
bool replaceRouteEdges(ConstMSEdgeVector &edges, double cost, double savings, const std::string &info, bool onInit=false, bool check=false, bool removeStops=true, std::string *msgReturn=nullptr)
Replaces the current route by the given edges.
virtual std::string getParameter(const MSVehicle *veh, const std::string &key) const
try to get the given parameter for this carFollowingModel
Definition MSCFModel.h:691
virtual void setParameter(MSVehicle *veh, const std::string &key, const std::string &value) const
try to set the given parameter for this carFollowingModel
Definition MSCFModel.h:704
Battery device for electric vehicles.
double getActualBatteryCapacity() const
Get the actual vehicle's Battery Capacity in Wh.
double getMaximumChargeRate() const
Get current charge rate in W depending on the state of charge.
double getMaximumBatteryCapacity() const
Get the total vehicle's Battery Capacity in Wh.
double getEnergyCharged() const
Get charged energy.
A device which collects info on the vehicle trip (mainly on departure and arrival)
double getMaximumBatteryCapacity() const
Get the total vehicle's Battery Capacity in kWh.
double getCurrentFromOverheadWire() const
Get actual current in the overhead wire segment.
double getEnergyCharged() const
Get charged energy.
double getActualBatteryCapacity() const
Get the actual vehicle's Battery Capacity in kWh.
A device that performs vehicle rerouting based on current edge speeds.
bool sufficientSaving(double oldCost, double newCost)
whether the change in saving is enough to trigger rerouting
bool notifyEnter(SUMOTrafficObject &veh, MSMoveReminder::Notification reason, const MSLane *enteredLane=0)
Computes a new route on vehicle insertion.
static void buildVehicleDevices(SUMOVehicle &v, std::vector< MSVehicleDevice * > &into)
Build devices for the given vehicle, if needed.
A device which collects info on the vehicle trip (mainly on departure and arrival)
bool allowsBoarding(const MSTransportable *t) const
whether the given person is allowed to board this taxi
const std::vector< MSTransportable * > & getTransportables() const
Returns the list of transportables using this vehicle.
static bool willTransferAtJoin(const MSTransportable *t, const MSBaseVehicle *joinVeh)
check if boardingDuration should be applied
static MSDevice_Transportable * buildVehicleDevices(SUMOVehicle &v, std::vector< MSVehicleDevice * > &into, const bool isContainer)
Build devices for the given vehicle, if needed.
int size() const
Return the number of passengers / containers.
void addTransportable(MSTransportable *transportable)
Add a passenger.
void removeTransportable(MSTransportable *transportable)
Remove a passenger (TraCI)
Abstract in-vehicle / in-person device.
Definition MSDevice.h:62
static void buildVehicleDevices(SUMOVehicle &v, std::vector< MSVehicleDevice * > &into)
Build devices for the given vehicle, if needed.
Definition MSDevice.cpp:114
A road/street connecting two junctions.
Definition MSEdge.h:77
static void clear()
Clears the dictionary.
Definition MSEdge.cpp:1128
bool hasTransientPermissions() const
Definition MSEdge.cpp:1707
const std::vector< MSLane * > & getLanes() const
Returns this edge's lanes.
Definition MSEdge.h:168
const MSEdge * getOppositeEdge() const
Returns the opposite direction edge if on exists else a nullptr.
Definition MSEdge.cpp:1376
const std::vector< MSLane * > * allowedLanes(const MSEdge &destination, SUMOVehicleClass vclass=SVC_IGNORING, bool ignoreTransientPermissions=false) const
Get the allowed lanes to reach the destination-edge.
Definition MSEdge.cpp:488
bool isNormal() const
return whether this edge is an internal edge
Definition MSEdge.h:264
double getLength() const
return the length of the edge
Definition MSEdge.h:694
bool isTazConnector() const
Definition MSEdge.h:292
int getNumLanes() const
Definition MSEdge.h:172
bool isInternal() const
return whether this edge is an internal edge
Definition MSEdge.h:269
bool prohibits(const SUMOVehicle *const vehicle) const
Returns whether the vehicle (class) is not allowed on the edge.
Definition MSEdge.h:636
static bool dictionary(const std::string &id, MSEdge *edge)
Inserts edge into the static dictionary Returns true if the key id isn't already in the dictionary....
Definition MSEdge.cpp:1083
const MSEdge * getNormalBefore() const
if this edge is an internal edge, return its first normal predecessor, otherwise the edge itself
Definition MSEdge.cpp:973
MSLane * getFirstAllowed(SUMOVehicleClass vClass, bool defaultFirst=false, int routingMode=0) const
Definition MSEdge.cpp:761
A storage for edge travel times and efforts.
virtual void addEvent(Command *operation, SUMOTime execTimeStep=-1)
Adds an Event.
static bool gUseMesoSim
Definition MSGlobals.h:106
static bool gCheckRoutes
Definition MSGlobals.h:91
static MELoop * gMesoNet
mesoscopic simulation infrastructure
Definition MSGlobals.h:112
static int gInsertionChecks
The default value for insertion checks.
Definition MSGlobals.h:186
static SUMOTime gTimeToImpatience
Definition MSGlobals.h:78
static bool gHaveEmissions
Whether emission output of some type is needed (files or GUI)
Definition MSGlobals.h:183
static bool gUseStopEnded
whether the simulation should replay previous stop times
Definition MSGlobals.h:133
void descheduleDeparture(const SUMOVehicle *veh)
stops trying to emit the given vehicle (and delete it)
Representation of a lane in the micro simulation.
Definition MSLane.h:84
int getRNGIndex() const
returns the associated RNG index
Definition MSLane.h:241
const MSEdge * getNextNormal() const
Returns the lane's follower if it is an internal lane, the edge of the lane otherwise.
Definition MSLane.cpp:2465
double getLength() const
Returns the lane's length.
Definition MSLane.h:611
bool allowsVehicleClass(SUMOVehicleClass vclass) const
Definition MSLane.h:935
static bool dictionary(const std::string &id, MSLane *lane)
Static (sic!) container methods {.
Definition MSLane.cpp:2489
bool isInternal() const
Definition MSLane.cpp:2620
SumoRNG * getRNG() const
return the associated RNG
Definition MSLane.h:246
MSEdge & getEdge() const
Returns the lane's edge.
Definition MSLane.h:769
Something on a lane to be noticed about vehicle movement.
virtual bool notifyEnter(SUMOTrafficObject &veh, Notification reason, const MSLane *enteredLane)
Checks whether the reminder is activated by a vehicle entering the lane.
const std::string & getDescription() const
Notification
Definition of a vehicle state.
@ NOTIFICATION_DEPARTED
The vehicle has departed (was inserted into the network)
const MSLane * getLane() const
Returns the lane the reminder works on.
bool warnOnce(const std::string &typeAndID)
return whether a warning regarding the given object shall be issued
Definition MSNet.cpp:1750
@ NEWROUTE
The vehicle got a new route.
static MSNet * getInstance()
Returns the pointer to the unique instance of MSNet (singleton).
Definition MSNet.cpp:187
MSEventControl * getBeginOfTimestepEvents()
Returns the event control for events executed at the begin of a time step.
Definition MSNet.h:485
const std::vector< MSStoppingPlace * > & getStoppingPlaceAlternatives(const std::string &name, SumoXMLTag category) const
Definition MSNet.cpp:1502
MSVehicleRouter & getRouterTT(int rngIndex, const Prohibitions &prohibited={}) const
Definition MSNet.cpp:1610
SUMOTime getCurrentTimeStep() const
Returns the current simulation step.
Definition MSNet.h:334
static bool hasInstance()
Returns whether the network was already constructed.
Definition MSNet.h:158
MSStoppingPlace * getStoppingPlace(const std::string &id, const SumoXMLTag category) const
Returns the named stopping place of the given category.
Definition MSNet.cpp:1467
void informVehicleStateListener(const SUMOVehicle *const vehicle, VehicleState to, const std::string &info="")
Informs all added listeners about a vehicle's state change.
Definition MSNet.cpp:1342
MSInsertionControl & getInsertionControl()
Returns the insertion control.
Definition MSNet.h:445
MSVehicleControl & getVehicleControl()
Returns the vehicle control.
Definition MSNet.h:392
A lane area vehicles can halt at.
bool accepts(SUMOVehicle *veh) const
Return the parking accepts the vehicle (due to its given badges)
static void storeTripId(const std::string &tripId, const std::string &vehID)
const ConstMSEdgeVector & getEdges() const
Definition MSRoute.h:128
void setCosts(double costs)
Sets the costs of the route.
Definition MSRoute.h:209
static bool hasRoute(const std::string &id)
returns whether a route with the given id exists
Definition MSRoute.cpp:159
static bool dictionary(const std::string &id, ConstMSRoutePtr route)
Adds a route to the dictionary.
Definition MSRoute.cpp:116
static void checkDist(const std::string &id)
Checks the distribution whether it is permanent and deletes it if not.
Definition MSRoute.cpp:194
void setSavings(double savings)
Sets the savings of the route.
Definition MSRoute.h:216
static MSVehicleRouter & getRouterTT(const int rngIndex, SUMOVehicleClass svc, const Prohibitions &prohibited={})
return the vehicle router instance
bool canLeaveVehicle(const MSTransportable *t, const SUMOVehicle &veh, const MSStop &stop)
checks whether the person may exit at the current vehicle position
const MSLane * lane
The lane to stop at (microsim only)
Definition MSStop.h:50
MSStoppingPlace * containerstop
(Optional) container stop if one is assigned to the stop
Definition MSStop.h:56
std::string getDescription(bool nameOnly=false) const
get a short description for showing in the gui
Definition MSStop.cpp:70
bool isOpposite
whether this an opposite-direction stop
Definition MSStop.h:87
void initPars(const SUMOVehicleParameter::Stop &stopPar)
initialize attributes from the given stop parameters
Definition MSStop.cpp:148
const MESegment * segment
The segment to stop at (mesosim only)
Definition MSStop.h:52
bool reached
Information whether the stop has been reached.
Definition MSStop.h:75
MSRouteIterator edge
The edge in the route to stop at.
Definition MSStop.h:48
double getEndPos(const SUMOVehicle &veh) const
return halting position for upcoming stop;
Definition MSStop.cpp:36
MSParkingArea * parkingarea
(Optional) parkingArea if one is assigned to the stop
Definition MSStop.h:58
MSStoppingPlace * chargingStation
(Optional) charging station if one is assigned to the stop
Definition MSStop.h:60
SUMOTime getUntil() const
return until / ended time
Definition MSStop.cpp:187
SUMOTime getArrival() const
return arrival / started time
Definition MSStop.cpp:193
const SUMOVehicleParameter::Stop pars
The stop parameter.
Definition MSStop.h:65
MSStoppingPlace * busstop
(Optional) bus stop if one is assigned to the stop
Definition MSStop.h:54
MSStoppingPlace * overheadWireSegment
(Optional) overhead wire segment if one is assigned to the stop
Definition MSStop.h:63
Finds a sequence of skips and stop alternatives to maximize priority of reached stops.
ConstMSEdgeVector optimizeSkipped(const MSEdge *source, double sourcePos, std::vector< StopEdgeInfo > &stops, ConstMSEdgeVector edges) const
A lane area vehicles can halt at.
double getBeginLanePosition() const
Returns the begin position of this stop.
double getParkingLength() const
double getEndLanePosition() const
Returns the end position of this stop.
const MSLane & getLane() const
Returns the lane this stop is located at.
bool isPerson() const override
Whether it is a person.
const MSVehicleType & getVehicleType() const override
Returns the object's "vehicle" type.
static const double DEFAULT_MAXDELAY
void vehicleDeparted(const SUMOVehicle &v)
Informs this control about a vehicle's departure.
SUMOVehicle * getVehicle(const std::string &id) const
Returns the vehicle with the given id.
void removeVType(const MSVehicleType *vehType)
void unregisterOneWaiting()
decreases the count of vehicles waiting for a transport to allow recognition of person / container re...
Abstract in-vehicle device.
Representation of a vehicle in the micro simulation.
Definition MSVehicle.h:77
MSAbstractLaneChangeModel & getLaneChangeModel()
const MSCFModel & getCarFollowModel() const
Returns the vehicle's car following model definition.
Definition MSVehicle.h:969
The car-following model and parameter.
const EnergyParams * getEmissionParameters() const
retrieve parameters for the energy consumption model
SUMOVehicleClass getVehicleClass() const
Get this vehicle type's vehicle class.
double getMaxSpeed() const
Get vehicle's (technical) maximum speed [m/s].
double getDesiredMaxSpeed() const
Returns the vehicles's desired maximum speed.
const std::string & getID() const
Returns the name of the vehicle type.
const Distribution_Parameterized & getSpeedFactor() const
Returns this type's speed factor.
bool isVehicleSpecific() const
Returns whether this type belongs to a single vehicle only (was modified)
SUMOEmissionClass getEmissionClass() const
Get this vehicle type's emission class.
double getLength() const
Get vehicle's length [m].
double getMass() const
Get this vehicle type's mass.
double computeChosenSpeedDeviation(SumoRNG *rng, const double minDev=-1.) const
Computes and returns the speed deviation.
MSVehicleType * buildSingularType(const std::string &id) const
Duplicates the microsim vehicle type giving the newly created type the given id, marking it as vehicl...
const std::vector< std::string > & getParkingBadges() const
Returns the parking access rights of this type.
static std::string getIDSecure(const T *obj, const std::string &fallBack="NULL")
get an identifier for Named-like object which may be Null
Definition Named.h:67
const std::string & getID() const
Returns the id.
Definition Named.h:74
A storage for options typed value containers)
Definition OptionsCont.h:89
bool isSet(const std::string &name, bool failOnNonExistant=true) const
Returns the information whether the named option is set.
const StringVector & getStringVector(const std::string &name) const
Returns the list of string-value of the named option (only for Option_StringVector)
static OptionsCont & getOptions()
Retrieves the options.
Static storage of an output device and its base (abstract) implementation.
OutputDevice & writeAttr(const SumoXMLAttr attr, const T &val)
writes a named attribute
OutputDevice & openTag(const std::string &xmlElement)
Opens an XML tag.
static OutputDevice & getDeviceByOption(const std::string &name)
Returns the device described by the option.
int getPrecision()
Returns the precision of the underlying stream.
bool closeTag(const std::string &comment="")
Closes the most recently opened tag and optionally adds a comment.
void setPrecision(int precision=gPrecision)
Sets the precision or resets it to default.
virtual const std::string getParameter(const std::string &key, const std::string defaultValue="") const
Returns the value for a given key.
const Parameterised::Map & getParametersMap() const
Returns the inner key/value map.
static const RGBColor DEFAULT_COLOR
The default color (for vehicle types and vehicles)
Definition RGBColor.h:202
Utility functions for using a global, resetable random number generator.
Definition RandHelper.h:133
static double rand(SumoRNG *rng=nullptr)
Returns a random real number in [0, 1)
virtual bool compute(const E *from, const E *to, const V *const vehicle, SUMOTime msTime, std::vector< const E * > &into, bool silent=false)=0
Builds the route between the given edges using the minimum effort at the given time The definition of...
virtual double recomputeCosts(const std::vector< const E * > &edges, const V *const v, SUMOTime msTime, double *lengthp=nullptr) const
double recomputeCostsPos(const std::vector< const E * > &edges, const V *const v, double fromPos, double toPos, SUMOTime msTime, double *lengthp=nullptr) const
std::string getStringParam(const std::string &paramName, const bool required=false, const std::string &deflt="") const
Retrieve a string parameter for the traffic object.
virtual const MSLane * getLane() const =0
Returns the lane the object is currently at.
long long int NumericalID
virtual double getSpeed() const =0
Returns the object's current speed.
virtual SUMOTime getWaitingTime(const bool accumulated=false) const =0
double getFloatParam(const std::string &paramName, const bool required=false, const double deflt=INVALID_DOUBLE, bool checkDist=true) const
Retrieve a floating point parameter for the traffic object.
virtual double getPositionOnLane() const =0
Get the object's position along the lane.
Representation of a vehicle.
Definition SUMOVehicle.h:62
virtual bool isIdling() const =0
Returns whether the vehicle is idling (waiting to re-enter the net.
virtual double getBrakeGap(bool delayed=false) const =0
get distance for coming to a stop (used for rerouting checks)
Definition of vehicle stop (position and duration)
std::string edge
The edge to stop at.
ParkingType parking
whether the vehicle is removed from the net while stopping
std::string lane
The lane to stop at.
double speed
the speed at which this stop counts as reached (waypoint mode)
std::string parkingarea
(Optional) parking area if one is assigned to the stop
double startPos
The stopping position start.
int parametersSet
Information for the output which parameter were set.
int index
at which position in the stops list
SUMOTime jump
transfer time if there shall be a jump from this stop to the next route edge
SUMOTime until
The time at which the vehicle may continue its journey.
bool triggered
whether an arriving person lets the vehicle continue
SUMOTime ended
the time at which this stop was ended
double endPos
The stopping position end.
std::string tripId
id of the trip within a cyclical public transport route
bool containerTriggered
whether an arriving container lets the vehicle continue
bool collision
Whether this stop was triggered by a collision.
SUMOTime arrival
The (expected) time at which the vehicle reaches the stop.
SUMOTime duration
The stopping duration.
Structure representing possible vehicle parameter.
ArrivalSpeedDefinition arrivalSpeedProcedure
Information how the vehicle's end speed shall be chosen.
double departSpeed
(optional) The initial speed of the vehicle
std::string vtypeid
The vehicle's type id.
SUMOTime repetitionOffset
The time offset between vehicle reinsertions.
long long int repetitionsDone
The number of times the vehicle was already inserted.
std::vector< std::string > via
List of the via-edges the vehicle must visit.
ArrivalLaneDefinition arrivalLaneProcedure
Information how the vehicle shall choose the lane to arrive on.
long long int parametersSet
Information for the router which parameter were set, TraCI may modify this (when changing color)
void write(OutputDevice &dev, const OptionsCont &oc, const SumoXMLTag altTag=SUMO_TAG_VEHICLE, const std::string &typeID="") const
Writes the parameters as a beginning element.
int personNumber
The static number of persons in the vehicle when it departs (not including boarding persons)
RouteIndexDefinition arrivalEdgeProcedure
Information how the vehicle's final edge shall be chosen.
bool wasSet(long long int what) const
Returns whether the given parameter was set.
double departPos
(optional) The position the vehicle shall depart from
DepartSpeedDefinition departSpeedProcedure
Information how the vehicle's initial speed shall be chosen.
double arrivalPos
(optional) The position the vehicle shall arrive on
std::string routeid
The vehicle's route id.
std::string id
The vehicle's id.
std::vector< std::string > parkingBadges
The parking access rights.
std::vector< Stop > stops
List of the stops the vehicle will make, TraCI may add entries here.
int departEdge
(optional) The initial edge within the route of the vehicle
ArrivalPosDefinition arrivalPosProcedure
Information how the vehicle shall choose the arrival position.
std::string toTaz
The vehicle's destination zone (district)
double arrivalSpeed
(optional) The final speed of the vehicle (not used yet)
DepartDefinition departProcedure
Information how the vehicle shall choose the depart time.
int insertionChecks
bitset of InsertionCheck
int arrivalEdge
(optional) The final edge within the route of the vehicle
std::string fromTaz
The vehicle's origin zone (district)
DepartPosDefinition departPosProcedure
Information how the vehicle shall choose the departure position.
std::string line
The vehicle's line (mainly for public transport)
int containerNumber
The static number of containers in the vehicle when it departs.
RouteIndexDefinition departEdgeProcedure
Information how the vehicle's initial edge shall be chosen.
static std::string getEdgeIDFromLane(const std::string laneID)
return edge id when given the lane ID
static int getIndexFromLane(const std::string laneID)
return lane index when given the lane ID
SUMOTime sawBlockedStoppingPlace(const MSStoppingPlace *stoppingPlace, bool local) const
Get the time the StoppingPlace was confirmed to be blocked.
void rememberStoppingPlaceScore(const MSStoppingPlace *stoppingPlace, const std::string &score)
score only needed when running with gui
void rememberBlockedStoppingPlace(const MSStoppingPlace *stoppingPlace, bool local)
Store the time the StoppingPlace was confirmed to be blocked.
int size() const
returns the number of existing substrings
std::string get(int pos) const
returns the item at the given position
static bool startsWith(const std::string &str, const std::string prefix)
Checks whether a given string starts with the prefix.
static bool endsWith(const std::string &str, const std::string suffix)
Checks whether a given string ends with the suffix.
static int toInt(const std::string &sData)
converts a string into the integer value described by it by calling the char-type converter,...
A wrapper for a Command function.
#define UNUSED_PARAMETER(x)
#define DEBUG_COND
TRACI_CONST int ROUTING_MODE_AGGREGATED
TRACI_CONST int ROUTING_MODE_DEFAULT
TRACI_CONST int ROUTING_MODE_IGNORE_TRANSIENT_PERMISSIONS