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 "MSBaseVehicle.h"
66
67//#define DEBUG_REROUTE
68//#define DEBUG_ADD_STOP
69//#define DEBUG_COND (getID() == "")
70//#define DEBUG_COND (true)
71//#define DEBUG_REPLACE_ROUTE
72//#define DEBUG_OPTIMIZE_SKIPPED
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 myEdgeWeights(nullptr)
125#ifdef _DEBUG
126 , myTraceMoveReminders(myShallTraceMoveReminders.count(pars->id) > 0)
127#endif
128{
129 if ((*myRoute->begin())->isTazConnector() || myRoute->getLastEdge()->isTazConnector()) {
131 }
132 if ((pars->parametersSet & VEHPARS_FORCE_REROUTE) == 0) {
134 }
135 if (!pars->wasSet(VEHPARS_FORCE_REROUTE)) {
137 }
139}
140
141
143 delete myEdgeWeights;
144 if (myParameter->repetitionNumber == -1) {
145 // this is not a flow (flows call checkDist in MSInsertionControl::determineCandidates)
147 }
148 for (MSVehicleDevice* dev : myDevices) {
149 delete dev;
150 }
151 delete myEnergyParams;
152 delete myParkingMemory;
153 delete myChargingMemory;
155 delete myParameter;
156}
157
158
159void
161 // the check for an instance is needed for the unit tests which do not construct a network
162 // TODO Optimize for speed and there should be a better way to check whether a vehicle is part of a flow
163 if (MSNet::hasInstance() && !MSNet::getInstance()->hasFlow(getFlowID())) {
164 myRoute->checkRemoval();
165 }
166}
167
168
169std::string
171 return getID().substr(0, getID().rfind('.'));
172}
173
174
175void
178 for (MSVehicleDevice* dev : myDevices) {
179 myMoveReminders.push_back(std::make_pair(dev, 0.));
180 }
182 // ensure we have the emission parameters even if we don't have the device
184 }
185}
186
187
188void
189MSBaseVehicle::setID(const std::string& /*newID*/) {
190 throw ProcessError(TL("Changing a vehicle ID is not permitted"));
191}
192
195 return *myParameter;
196}
197
198
199void
201 delete myParameter;
202 myParameter = newParameter;
203}
204
205
206bool
210
211double
215
216
217const MSEdge*
218MSBaseVehicle::succEdge(int nSuccs) const {
219 if (myCurrEdge + nSuccs < myRoute->end() && std::distance(myCurrEdge, myRoute->begin()) <= nSuccs) {
220 return *(myCurrEdge + nSuccs);
221 } else {
222 return nullptr;
223 }
224}
225
226
227const MSEdge*
229 return *myCurrEdge;
230}
231
232
233const std::set<SUMOTrafficObject::NumericalID>
235 std::set<SUMOTrafficObject::NumericalID> result;
236 for (auto e = myCurrEdge; e != myRoute->end(); ++e) {
237 result.insert((*e)->getNumericalID());
238 }
239 return result;
240}
241
242
243bool
245 if (stop == nullptr) {
246 return false;
247 }
248 for (const MSStop& s : myStops) {
249 if (s.busstop == stop
250 || s.containerstop == stop
251 || s.parkingarea == stop
252 || s.chargingStation == stop) {
253 return true;
254 }
255 }
256 return false;
257}
258
259bool
261 for (const MSStop& s : myStops) {
262 if (&s.lane->getEdge() == edge) {
263 return true;
264 }
265 }
266 return myRoute->getLastEdge() == edge;
267}
268
269
270bool
271MSBaseVehicle::reroute(SUMOTime t, const std::string& info, SUMOAbstractRouter<MSEdge, SUMOVehicle>& router, const bool onInit, const bool withTaz, const bool silent, const MSEdge* sink) {
272 // check whether to reroute
273 const MSEdge* source = withTaz && onInit ? MSEdge::dictionary(myParameter->fromTaz + "-source") : *getRerouteOrigin();
274 if (source == nullptr) {
275 source = *getRerouteOrigin();
276 }
277 if (sink == nullptr) {
278 sink = withTaz ? MSEdge::dictionary(myParameter->toTaz + "-sink") : myRoute->getLastEdge();
279 if (sink == nullptr) {
280 sink = myRoute->getLastEdge();
281 }
282 }
283 ConstMSEdgeVector oldEdgesRemaining(source == *myCurrEdge ? myCurrEdge : myCurrEdge + 1, myRoute->end());
284 ConstMSEdgeVector edges;
285 std::vector<StopEdgeInfo> stops;
286 std::set<int> jumps;
287 double sinkPriority = -1;
288 bool stopAtSink = false;
289 double sourcePos = onInit ? 0 : getPositionOnLane();
290 if (myParameter->via.size() == 0) {
291 double firstPos = INVALID_DOUBLE;
292 double lastPos = INVALID_DOUBLE;
293 stops = getStopEdges(firstPos, lastPos, jumps);
294 if (stops.size() > 0) {
296 sourcePos = getNextStop().pars.endPos;
297 }
298 // avoid superfluous waypoints for first and last edge
299 const bool skipFirst = stops.front().edge == source && (source != getEdge() || sourcePos + getBrakeGap() <= firstPos + NUMERICAL_EPS);
300 const bool skipLast = (stops.back().edge == sink
301 && myArrivalPos >= lastPos
302 && (stops.size() < 2 || stops.back() != stops[stops.size() - 2])
303 && (stops.size() > 1 || skipFirst));
304 if (stops.back().edge == sink && myArrivalPos >= lastPos) {
305 sinkPriority = stops.back().priority;
306 }
307#ifdef DEBUG_REROUTE
308 if (DEBUG_COND) {
309 std::cout << SIMTIME << " reroute " << info << " veh=" << getID() << " lane=" << Named::getIDSecure(getLane())
310 << " source=" << source->getID() << " sourcePos=" << sourcePos << " firstPos=" << firstPos << " arrivalPos=" << myArrivalPos << " lastPos=" << lastPos
311 << " route=" << toString(myRoute->getEdges()) << " stopEdges=" << toString(stops) << " skipFirst=" << skipFirst << " skipLast=" << skipLast << "\n";
312 }
313#endif
314 if (stops.size() == 1 && (skipFirst || skipLast)) {
315 stops.clear();
316 } else {
317 if (skipFirst) {
318 stops.erase(stops.begin());
319 }
320 if (skipLast) {
321 stops.erase(stops.end() - 1);
322 }
323 }
324 stopAtSink = stops.size() > 0 && stops.back().edge == sink && jumps.size() == 0;
325 }
326 } else {
327 std::set<const MSEdge*> jumpEdges;
328 std::map<const MSEdge*, StopEdgeInfo> stopsOnVia;
329 for (const MSStop& stop : myStops) {
330 if (stop.pars.jump >= 0) {
331 jumpEdges.insert(*stop.edge);
332 }
333 auto itsov = stopsOnVia.find(*stop.edge);
334 if (itsov == stopsOnVia.end()) {
335 stopsOnVia.insert({*stop.edge, StopEdgeInfo(*stop.edge, stop.pars.priority, stop.getArrivalFallback(), stop.getEndPos(*this))});
336 } else {
337 itsov->second.priority = addStopPriority(itsov->second.priority, stop.pars.priority);
338 }
339 }
340 // via takes precedence over stop edges
341 // there is a consistency check in MSRouteHandler::addStop that warns when a stop edge is not part of the via edges
342 for (std::vector<std::string>::const_iterator it = myParameter->via.begin(); it != myParameter->via.end(); ++it) {
343 MSEdge* viaEdge = MSEdge::dictionary(*it);
344 if ((viaEdge == source && it == myParameter->via.begin()) || (viaEdge == sink && myParameter->via.end() - it == 1)) {
345 continue;
346 }
347 assert(viaEdge != 0);
348 if (!viaEdge->isTazConnector() && viaEdge->allowedLanes(getVClass()) == nullptr) {
349 throw ProcessError(TLF("Vehicle '%' is not allowed on any lane of via edge '%'.", getID(), viaEdge->getID()));
350 }
351 auto itsov = stopsOnVia.find(viaEdge);
352 const double priority = (itsov == stopsOnVia.end() ? -1 : itsov->second.priority);
353 const SUMOTime arrival = (itsov == stopsOnVia.end() ? -1 : itsov->second.arrival);
354 const double pos = (itsov == stopsOnVia.end() ? viaEdge->getLength() : itsov->second.pos);
355 stops.push_back(StopEdgeInfo(viaEdge, priority, arrival, pos));
356 // @todo determine wether the viaEdge is also used by a stop and then use the stop priority here
357 if (jumpEdges.count(viaEdge) != 0) {
358 jumps.insert((int)stops.size());
359 }
360 }
361 }
362
363 int stopIndex = -1;
364 auto stopIt = myStops.begin();
365 SUMOTime startTime = t;
366 bool hasSkipped = false;
367 const double origSourcePos = sourcePos;
368 const MSEdge* origSource = source;
370 for (auto& stopEdgeInfo : stops) {
371 const MSEdge* const stopEdge = stopEdgeInfo.edge;
372 const double priority = stopEdgeInfo.priority;
373 stopIndex++;
375 if (jumps.count(stopIndex) != 0) {
376 edges.push_back(source);
377 source = stopEdge;
378 continue;
379 }
380 // !!! need to adapt t here
381 router.computeLooped(source, stopEdge, this, t, into, silent || priority >= 0);
382 //std::cout << SIMTIME << " reroute veh=" << getID() << " source=" << source->getID() << " target=" << (*s)->getID() << " edges=" << toString(into) << "\n";
383 if (into.size() > 0) {
384 while (stopIt != myStops.end() && stopIt->pars.edge != stopEdge->getID()) {
385 stopIt++;
386 }
387
388 startTime += TIME2STEPS(router.recomputeCostsPos(into, this, sourcePos, stopEdgeInfo.pos, startTime));
389 if (stopIt != myStops.end()) {
390 if (stopIt->pars.priority >= 0 && info != "device.rerouting") {
391 // consider skipping this stop if it cannot be reached in a timely manner
392 if (stopIt != myStops.end()) {
393 SUMOTime arrival = stopEdgeInfo.arrival;
394 if (arrival > 0) {
395 SUMOTime delay = startTime - arrival;
396 //std::cout << " t=" << time2string(t) << " veh=" << getID() << " info=" << info << " stopIndex=" << stopIndex
397 // << " into=" << toString(into) << " sourcePos=" << sourcePos << " stopPos=" << stopPos
398 // << " startTime=" << time2string(startTime) << " arrival=" << time2string(arrival) << " delay=" << time2string(delay) << "\n";
399 if (delay > 0) {
400 if (delay > maxDelay) {
401 stopEdgeInfo.skipped = true;
402 stopEdgeInfo.delay = delay;
403 hasSkipped = true;
404 continue;
405 }
406 }
407 }
408 }
409 }
410 sourcePos = stopEdgeInfo.pos;
411 startTime += stopIt->getMinDuration(startTime);
412 }
413 into.pop_back();
414 edges.insert(edges.end(), into.begin(), into.end());
415 if (stopEdge->isTazConnector()) {
416 source = into.back();
417 edges.pop_back();
418 } else {
419 source = stopEdge;
420 }
421 stopEdgeInfo.routeIndex = (int)edges.size() - 1;
422 } else {
423 if ((source != sink || !stopAtSink)) {
424 if (priority >= 0) {
425 stopEdgeInfo.skipped = true;
426 hasSkipped = true;
427 continue;
428 } else {
429 std::string error = TLF("Vehicle '%' has no valid route from edge '%' to stop edge '%'.", getID(), source->getID(), stopEdge->getID());
430 if (MSGlobals::gCheckRoutes || silent) {
431 throw ProcessError(error);
432 } else {
433 WRITE_WARNING(error);
434 edges.push_back(source);
435 source = stopEdge;
436 }
437 }
438 }
439 }
440 }
441 if (stops.empty() && source == sink && onInit
445 router.computeLooped(source, sink, this, t, edges, silent);
446 } else {
447 if (!router.compute(source, sink, this, t, edges, silent || sinkPriority >= 0)) {
448 if (sinkPriority >= 0) {
449 edges.push_back(source);
450 hasSkipped = true;
451 stops.push_back(StopEdgeInfo(sink, sinkPriority, -1, getArrivalPos()));
452 stops.back().skipped = true;
453 } else {
454 edges.clear();
455 }
456 }
457 }
458 if (hasSkipped) {
459 edges = optimizeSkipped(t, router, origSource, origSourcePos, stops, edges, maxDelay);
460 for (auto stop : stops) {
461 if (stop.skipped) {
462 if (stop.delay > 0) {
463 WRITE_WARNING(TLF("Vehicle '%' skips stop on edge '%' with delay % at time %.", getID(), stop.edge->getID(), time2string(stop.delay), time2string(SIMSTEP)));
464 } else if (stop.backtracked) {
465 WRITE_WARNING(TLF("Vehicle '%' skips stop on edge '%' with priority % at time %.", getID(), stop.edge->getID(), stop.priority, time2string(SIMSTEP)));
466 } else {
467 WRITE_WARNING(TLF("Vehicle '%' skips unreachable stop on edge '%' with priority % at time %.", getID(), stop.edge->getID(), stop.priority, time2string(SIMSTEP)));
468 }
469 }
470 }
471 }
472
473 // router.setHint(myCurrEdge, myRoute->end(), this, t);
474 if (edges.empty() && silent) {
475 return false;
476 }
477 if (!edges.empty() && edges.front()->isTazConnector()) {
478 edges.erase(edges.begin());
479 }
480 if (!edges.empty() && edges.back()->isTazConnector()) {
481 edges.pop_back();
482 }
483 const double routeCost = router.recomputeCosts(edges, this, t);
484 const double previousCost = onInit ? routeCost : router.recomputeCosts(oldEdgesRemaining, this, t);
485 const double savings = previousCost - routeCost;
486 bool savingsOk = onInit || info != "device.rerouting" || gWeightsRandomFactor != 1;
487 if (!savingsOk) {
488 MSDevice_Routing* routingDevice = static_cast<MSDevice_Routing*>(getDevice(typeid(MSDevice_Routing)));
489 assert(routingDevice != 0);
490 savingsOk = routingDevice->sufficientSaving(previousCost, routeCost);
491 if (!savingsOk) {
492 std::string dummyMsg;
493 if (!hasValidRoute(dummyMsg, oldEdgesRemaining.begin(), oldEdgesRemaining.end(), true)) {
494 // the old route is prohibted (i.e. due to temporary permission changes)
495 savingsOk = true;
496 }
497 }
498 }
499 //if (getID() == "43") std::cout << SIMTIME << " pCost=" << previousCost << " cost=" << routeCost
500 // << " onInit=" << onInit
501 // << " prevEdges=" << toString(oldEdgesRemaining)
502 // << " newEdges=" << toString(edges)
503 // << "\n";
504 if (savingsOk) {
505 replaceRouteEdges(edges, routeCost, savings, info, onInit);
506 }
507 // this must be called even if the route could not be replaced
508 if (onInit) {
509 if (edges.empty()) {
511 throw ProcessError(TLF("Vehicle '%' has no valid route.", getID()));
512 } else if (source->isTazConnector()) {
513 WRITE_WARNINGF(TL("Removing vehicle '%' which has no valid route."), getID());
515 return false;
516 }
517 }
520 }
521 return !edges.empty();
522}
523
524
525bool
526MSBaseVehicle::replaceRouteEdges(ConstMSEdgeVector& edges, double cost, double savings, const std::string& info, bool onInit, bool check, bool removeStops, std::string* msgReturn) {
527 if (edges.empty()) {
528 WRITE_WARNINGF(TL("No route for vehicle '%' found."), getID());
529 if (msgReturn != nullptr) {
530 *msgReturn = "No route found";
531 }
532 return false;
533 }
534 // build a new id, first
535 std::string id = getID();
536 if (id[0] != '!') {
537 id = "!" + id;
538 }
539 const std::string idSuffix = id + "!var#";
540 int varIndex = 1;
541 id = idSuffix + toString(varIndex);
542 while (MSRoute::hasRoute(id)) {
543 id = idSuffix + toString(++varIndex);
544 }
545 int oldSize = (int)edges.size();
546 if (!onInit) {
547 const MSEdge* const origin = *getRerouteOrigin();
548 if (origin != *myCurrEdge && edges.front() == origin) {
549 edges.insert(edges.begin(), *myCurrEdge);
550 oldSize = (int)edges.size();
551 }
552 edges.insert(edges.begin(), myRoute->begin(), myCurrEdge);
553 }
554 if (edges == myRoute->getEdges() && haveValidStopEdges(true)) {
555 // re-assign stop iterators when rerouting to a new parkingArea / insertStop
556 return true;
557 }
558 const RGBColor& c = myRoute->getColor();
559 MSRoute* newRoute = new MSRoute(id, edges, false, &c == &RGBColor::DEFAULT_COLOR ? nullptr : new RGBColor(c), StopParVector());
560 newRoute->setCosts(cost);
561 newRoute->setSavings(savings);
562 ConstMSRoutePtr constRoute = std::shared_ptr<MSRoute>(newRoute);
563 if (!MSRoute::dictionary(id, constRoute)) {
564 delete newRoute;
565 if (msgReturn != nullptr) {
566 *msgReturn = "duplicate routeID '" + id + "'";
567 }
568 return false;
569 }
570
571 std::string msg;
572 if (check && !hasValidRoute(msg, constRoute)) {
573 WRITE_WARNINGF(TL("Invalid route replacement for vehicle '%'. %"), getID(), msg);
575 if (msgReturn != nullptr) {
576 *msgReturn = msg;
577 }
578 return false;
579 }
580 }
581 if (!replaceRoute(constRoute, info, onInit, (int)edges.size() - oldSize, false, removeStops, msgReturn)) {
582 return false;
583 }
584 return true;
585}
586
587
588bool
589MSBaseVehicle::replaceRoute(ConstMSRoutePtr newRoute, const std::string& info, bool onInit, int offset, bool addRouteStops, bool removeStops, std::string* msgReturn) {
590 const ConstMSEdgeVector& edges = newRoute->getEdges();
591 // rebuild in-vehicle route information
592 if (onInit) {
593 myCurrEdge = newRoute->begin();
594 } else {
595 MSRouteIterator newCurrEdge = std::find(edges.begin() + offset, edges.end(), *myCurrEdge);
596 if (newCurrEdge == edges.end()) {
597 if (msgReturn != nullptr) {
598 *msgReturn = TLF("current edge '%' not found in new route", (*myCurrEdge)->getID());
599 }
600#ifdef DEBUG_REPLACE_ROUTE
601 if (DEBUG_COND) {
602 std::cout << " newCurrEdge not found\n";
603 }
604#endif
605 return false;
606 }
607 if (getLane() != nullptr) {
608 if (getLane()->getEdge().isInternal() && (
609 (newCurrEdge + 1) == edges.end() || (*(newCurrEdge + 1)) != &(getLane()->getOutgoingViaLanes().front().first->getEdge()))) {
610 if (msgReturn != nullptr) {
611 *msgReturn = TL("Vehicle is on junction-internal edge leading elsewhere");
612 }
613#ifdef DEBUG_REPLACE_ROUTE
614 if (DEBUG_COND) {
615 std::cout << " Vehicle is on junction-internal edge leading elsewhere\n";
616 }
617#endif
618 return false;
619 } else if (getPositionOnLane() > getLane()->getLength()
620 && (myCurrEdge + 1) != myRoute->end()
621 && (newCurrEdge + 1) != edges.end()
622 && *(myCurrEdge + 1) != *(newCurrEdge + 1)) {
623 if (msgReturn != nullptr) {
624 *msgReturn = TL("Vehicle is moving past junction and committed to move to another successor edge");
625 }
626#ifdef DEBUG_REPLACE_ROUTE
627 if (DEBUG_COND) {
628 std::cout << " Vehicle is moving past junction and committed to move to another successor edge\n";
629 }
630#endif
631 return false;
632 }
633 }
634 myCurrEdge = newCurrEdge;
635 }
636 const bool stopsFromScratch = onInit && myRoute->getStops().empty();
637 // assign new route
639 myRoute = newRoute;
640 // update arrival definition
642 // save information that the vehicle was rerouted
644 myStopUntilOffset += myRoute->getPeriod();
646 if (!onInit && isRail() && MSRailSignalControl::hasInstance()) {
647 // we need to update driveways (add/remove reminders) before the next call to MSRailSignalControl::updateSignals
648 //
649 // rerouting may be triggered through
650 // - MoveReminders (executeMove->activateReminders)
651 // - rerouters
652 // - devices (MSDevice_Stationfinder)
653 // - TraCI (changeTarget, replaceStop, ...
654 // - events (MSDevice_Routing::myRerouteCommand, MSDevice_Taxi::triggerDispatch)
655 //
656 // Since activateReminders actively modifies reminders, adding/deleting reminders would create a mess
657 // hence, we use an event to be safe for all case
658
661 }
662#ifdef DEBUG_REPLACE_ROUTE
663 if (DEBUG_COND) {
664 std::cout << SIMTIME << " veh=" << getID() << " replaceRoute info=" << info << " on " << (*myCurrEdge)->getID()
665 << " lane=" << Named::getIDSecure(getLane())
666 << " stopsFromScratch=" << stopsFromScratch
667 << " newSize=" << newRoute->getEdges().size()
668 << " newIndex=" << (myCurrEdge - newRoute->begin())
669 << " edges=" << toString(newRoute->getEdges())
670 << "\n";
671 }
672#endif
673 // remove past stops which are not on the route anymore
674 for (StopParVector::iterator it = myPastStops.begin(); it != myPastStops.end();) {
675 const MSEdge* stopEdge = (it->edge.empty()) ? &MSLane::dictionary(it->lane)->getEdge() : MSEdge::dictionary(it->edge);
676 if (std::find(myRoute->begin(), myRoute->end(), stopEdge) == myRoute->end()) {
677 it = myPastStops.erase(it);
678 } else {
679 ++it;
680 }
681 }
682 // if we did not drive yet it may be best to simply reassign the stops from scratch
683 if (stopsFromScratch) {
684 myStops.clear();
686 } else {
687 // recheck old stops
688 MSRouteIterator searchStart = myCurrEdge;
689 double lastPos = getPositionOnLane() + getBrakeGap();
690 if (getLane() != nullptr && getLane()->isInternal()
691 && myStops.size() > 0 && !myStops.front().lane->isInternal()) {
692 // searchStart is still incoming to the intersection so lastPos
693 // relative to that edge must be adapted
694 lastPos += (*myCurrEdge)->getLength();
695 }
696 int stopIndex = 0;
697 for (std::list<MSStop>::iterator iter = myStops.begin(); iter != myStops.end();) {
698 double endPos = iter->getEndPos(*this);
699#ifdef DEBUG_REPLACE_ROUTE
700 if (DEBUG_COND) {
701 std::cout << " stopEdge=" << iter->lane->getEdge().getID() << " start=" << (searchStart - myCurrEdge) << " endPos=" << endPos << " lastPos=" << lastPos << "\n";
702 }
703#endif
704 if (*searchStart != &iter->lane->getEdge()
705 || endPos + NUMERICAL_EPS < lastPos) {
706 if (searchStart != edges.end() && !iter->reached) {
707 searchStart++;
708 }
709 }
710 lastPos = endPos;
711
712 iter->edge = std::find(searchStart, edges.end(), &iter->lane->getEdge());
713#ifdef DEBUG_REPLACE_ROUTE
714 if (DEBUG_COND) {
715 std::cout << " foundIndex=" << (iter->edge - myCurrEdge) << " end=" << (edges.end() - myCurrEdge) << "\n";
716 }
717#endif
718 if (iter->edge == edges.end()) {
719 if (!removeStops) {
720 WRITE_ERRORF(TL("Vehicle '%' could not assign stop '%' after rerouting (%) at time=%."), getID(), iter->getDescription(), info, time2string(SIMSTEP));
721 }
722 iter = myStops.erase(iter);
723 continue;
724 } else {
725 setSkips(*iter, stopIndex);
726 searchStart = iter->edge;
727 }
728 ++iter;
729 stopIndex++;
730 }
731 // add new stops
732 if (addRouteStops) {
733 for (StopParVector::const_iterator i = newRoute->getStops().begin(); i != newRoute->getStops().end(); ++i) {
734 std::string error;
736 if (error != "") {
737 WRITE_WARNING(error);
738 }
739 }
740 }
741 }
742 return true;
743}
744
745
748 std::vector<StopEdgeInfo>& stops, ConstMSEdgeVector edges, SUMOTime maxDelay) const {
749 double skippedPrio = 0;
750 double minPrio = std::numeric_limits<double>::max();
751 std::vector<int> skipped;
752 for (int i = 0; i < (int)stops.size(); i++) {
753 if (stops[i].skipped) {
754 skipped.push_back(i);
755 }
756 minPrio = MIN2(minPrio, stops[i].priority);
757 }
758 for (int i : skipped) {
759 skippedPrio += stops[i].priority;
760 }
761#ifdef DEBUG_OPTIMIZE_SKIPPED
762 std::cout << SIMTIME << " veh=" << getID() << " optimzeSkipped=" << toString(skipped) << " source=" << source->getID() << "\n";
763 for (int i = 0; i < (int)stops.size(); i++) {
764 const auto& stop = stops[i];
765 std::cout << " " << i << " edge=" << stop.edge->getID() << " routeIndex=" << stop.routeIndex << " prio=" << stop.priority << " skipped=" << stop.skipped << " arrival=" << stop.arrival << "\n";
766 }
767#endif
768 if (skippedPrio == minPrio) {
769 // case A: only one stop was skipped and it had the lowest priority (or multiple stops with prio 0 were skipped): this is already optimal
770#ifdef DEBUG_OPTIMIZE_SKIPPED
771 std::cout << " skippedPrio=" << skippedPrio << " minPrio=" << minPrio << "\n";
772#endif
773 return edges;
774 }
775 // check reachability of skipped stops
776 std::vector<int> skippedReachable;
777 for (int si : skipped) {
779 router.computeLooped(source, stops[si].edge, this, t, into, true);
780 if (into.size() > 0) {
781 SUMOTime arrival = t + TIME2STEPS(router.recomputeCostsPos(into, this, sourcePos, stops[si].pos, t));
782 if (arrival - stops[si].arrival <= maxDelay) {
783 skippedReachable.push_back(si);
784 }
785 }
786 }
787 if (skippedReachable.size() == 0) {
788 // case B: skipped stops are not reachable with backtracking
789#ifdef DEBUG_OPTIMIZE_SKIPPED
790 std::cout << " noneReachable\n";
791#endif
792 return edges;
793 }
794 std::set<int> unskippedBefore;
795 for (int i = 0; i < (int)stops.size(); i++) {
796 if (i < skipped.back()) {
797 unskippedBefore.insert(i);
798 }
799 }
800 for (int i : skipped) {
801 unskippedBefore.erase(i);
802 }
803 // otherwise, skippedReachable should have been empty
804 assert(unskippedBefore.size() > 0);
805 // the unskipped stops may form several non contiguous sequences. We care about the last element of each sequence
806 std::vector<int> unskippedEnds;
807 std::vector<int> skippedStarts;
808 for (int i : unskippedBefore) {
809 if (unskippedBefore.count(i + 1) == 0) {
810 for (int i2 : skippedReachable) {
811 if (i2 >= i + 1) {
812 unskippedEnds.push_back(i);
813 skippedStarts.push_back(i2);
814 break;
815 }
816 }
817 }
818 }
819 std::sort(unskippedEnds.begin(), unskippedEnds.end()); // ascending
820 std::set<int> skippedSet(skipped.begin(), skipped.end());
821#ifdef DEBUG_OPTIMIZE_SKIPPED
822 std::cout << " unskippedEnds=" << toString(unskippedEnds) << " skippedStarts=" << toString(skippedStarts) << "\n";
823#endif
824
825 ConstMSEdgeVector bestEdges = edges;
826 double altSkippedPrio = 0;
827 const MSEdge* firstSkipped = stops[skippedStarts.back()].edge;
828 for (int i = unskippedEnds.back(); i >= 0; i--) {
829 double prio = stops[i].priority;
830 altSkippedPrio += prio;
831 if (skippedSet.count(i) // found start of another skip sequence
832 || prio < 0 // cannot backtrack past unskippable stop
833 || altSkippedPrio >= skippedPrio // backtracking past this stop cannot improve result
834 ) {
835 unskippedEnds.pop_back();
836 skippedStarts.pop_back();
837 if (unskippedEnds.empty()) {
838 return edges;
839 }
840 // try to optimize earlier sequence of skips
841 i = unskippedEnds.back();
842 firstSkipped = stops[skippedStarts.back()].edge;
843 altSkippedPrio = 0;
844 continue;
845 }
846 const MSEdge* prev = i > 0 ? stops[i - 1].edge : source;
847 const double prevPos = i > 0 ? stops[i - 1].pos : sourcePos;
849 SUMOTime start = stops[i - 1].arrival;
850 router.computeLooped(prev, firstSkipped, this, start, into, true);
851 if (into.size() == 0) {
852 // cannot reach firstSkipped and need to backtrack further
853 continue;
854 }
855 start += TIME2STEPS(router.recomputeCostsPos(into, this, prevPos, stops[skippedStarts.back()].pos, start));
856 // initialize skipped priority with stops skipped during backtracking and any skipped before that
857 std::vector<StopEdgeInfo> stops2 = stops;
858 double skippedPrio2 = altSkippedPrio;
859 for (int i2 = 0; i2 < i - 1; i2++) {
860 if (stops[i2].skipped) {
861 skippedPrio2 += stops[i2].priority;
862 }
863 }
864 for (int i2 = i; i2 <= unskippedEnds.back(); i2++) {
865 stops2[i2].skipped = true;
866 stops2[i2].backtracked = true;
867 }
868 int prevRouteIndex = i > 0 ? stops[i - 1].routeIndex : getDepartEdge();
869 assert(prevRouteIndex >= 0 && prevRouteIndex < (int)edges.size());
870 ConstMSEdgeVector edges2(edges.begin(), edges.begin() + prevRouteIndex);
871 stops2[skippedStarts.back()].skipped = false;
872 edges2.insert(edges2.begin(), into.begin(), into.end());
873 edges2 = routeAlongStops(start, router, stops2, edges2, skippedStarts.back(), maxDelay, skippedPrio2);
874 if (skippedPrio2 < skippedPrio) {
875#ifdef DEBUG_OPTIMIZE_SKIPPED
876 std::cout << " skippedPrio=" << skippedPrio << " skippedPrio2=" << skippedPrio2 << "\n";
877#endif
878 bestEdges = edges2;
879 skippedPrio = skippedPrio2;
880 stops = stops2;
881 }
882 }
883 return bestEdges;
884}
885
886
889 std::vector<StopEdgeInfo>& stops, ConstMSEdgeVector edges,
890 int originStop, SUMOTime maxDelay, double& skippedPrio2) const {
891 // originStop was already reached an the edges appended
892 for (int i = originStop + 1; i < (int)stops.size(); i++) {
894 router.computeLooped(edges.back(), stops[i].edge, this, t, into, true);
895 if (into.size() == 0) {
896 if (stops[i].priority < 0) {
897 // failure: cannot reach required stop
898 skippedPrio2 = std::numeric_limits<double>::max();
899 return edges;
900 }
901 skippedPrio2 += stops[i].priority;
902 stops[i].skipped = true;
903 } else {
904 t += TIME2STEPS(router.recomputeCostsPos(into, this, stops[i - 1].pos, stops[i].pos, t));
905 SUMOTime delay = t - stops[i].arrival;
906 if (delay > maxDelay) {
907 if (stops[i].priority < 0) {
908 // failure: cannot reach required stop in time
909 skippedPrio2 = std::numeric_limits<double>::max();
910 return edges;
911 }
912 skippedPrio2 += stops[i].priority;
913 stops[i].skipped = true;
914 stops[i].delay = true;
915 } else {
916 edges.pop_back();
917 edges.insert(edges.end(), into.begin(), into.end());
918 }
919 }
920 }
921 return edges;
922}
923
924
925double
927 return 0;
928}
929
930
931void
937
938
941 const SUMOTime dep = getParameter().depart;
942 if (dep < 0) {
943 return 0;
944 }
945 return hasDeparted() ? getDeparture() - dep : SIMSTEP - dep;
946}
947
948
949bool
951 return succEdge(1) == nullptr;
952}
953
954
955int
957 return (int) std::distance(myRoute->begin(), myCurrEdge);
958}
959
960
961int
963 if (myParameter->arrivalEdge >= 0) {
965 } else {
966 return myRoute->size() - getRoutePosition();
967 }
968}
969
970
971void
973 myCurrEdge = myRoute->begin() + index;
974 const_cast<SUMOVehicleParameter*>(myParameter)->departLaneProcedure = departLaneProcedure;
975 // !!! hack
976 myArrivalPos = (*(myRoute->end() - 1))->getLanes()[0]->getLength();
977}
978
979double
983
984bool
986 if (t->isPerson() && getPersonNumber() >= getVehicleType().getPersonCapacity()) {
987 return false;
988 } else if (!t->isPerson() && getContainerNumber() >= getVehicleType().getContainerCapacity()) {
989 return false;
990 }
991 if (isStopped() && myStops.begin()->pars.permitted.size() > 0
992 && myStops.begin()->pars.permitted.count(t->getID()) == 0) {
993 return false;
994 }
995 MSDevice_Taxi* taxiDevice = static_cast<MSDevice_Taxi*>(getDevice(typeid(MSDevice_Taxi)));
996 if (taxiDevice != nullptr) {
997 return taxiDevice->allowsBoarding(t);
998 }
999 return true;
1000}
1001
1002
1003void
1005 if (transportable->isPerson()) {
1006 if (myPersonDevice == nullptr) {
1008 myMoveReminders.insert(myMoveReminders.begin(), std::make_pair(myPersonDevice, 0.));
1011 }
1012 }
1013 myPersonDevice->addTransportable(transportable);
1014 } else {
1015 if (myContainerDevice == nullptr) {
1017 myMoveReminders.insert(myMoveReminders.begin(), std::make_pair(myContainerDevice, 0.));
1020 }
1021 }
1022 myContainerDevice->addTransportable(transportable);
1023 }
1024 if (myEnergyParams != nullptr) {
1026 }
1027}
1028
1029
1030bool
1032 for (const MSStop& stop : myStops) {
1033 if (stop.edge == it && stop.pars.jump >= 0) {
1034 return true;
1035 } else if (stop.edge > it) {
1036 return false;
1037 }
1038 }
1039 return false;
1040}
1041
1042
1043bool
1044MSBaseVehicle::hasValidRoute(std::string& msg, ConstMSRoutePtr route) const {
1046 if (route == nullptr) {
1047 route = myRoute;
1048 } else {
1049 start = route->begin();
1050 }
1051 const bool checkJumps = route == myRoute; // the edge iterators in the stops are invalid otherwise
1052 return hasValidRoute(msg, start, route->end(), checkJumps);
1053}
1054
1055
1056bool
1057MSBaseVehicle::hasValidRoute(std::string& msg, MSRouteIterator start, MSRouteIterator last, bool checkJumps) const {
1058 MSRouteIterator lastValid = last - 1;
1059 // check connectivity, first
1060 for (MSRouteIterator e = start; e != lastValid; ++e) {
1061 const MSEdge& next = **(e + 1);
1062 if ((*e)->allowedLanes(next, myType->getVehicleClass()) == nullptr) {
1063 if (!checkJumps || !hasJump(e)) {
1065 || (!next.hasTransientPermissions() && !(*e)->hasTransientPermissions())) {
1066 msg = TLF("No connection between edge '%' and edge '%'.", (*e)->getID(), (*(e + 1))->getID());
1067 return false;
1068 }
1069 }
1070 }
1071 }
1072 // check usable lanes, then
1073 for (MSRouteIterator e = start; e != last; ++e) {
1074 if ((*e)->prohibits(this)) {
1075 msg = TLF("Edge '%' prohibits.", (*e)->getID());
1076 return false;
1077 }
1078 }
1079 return true;
1080}
1081
1082
1083bool
1085 if (!(*myCurrEdge)->isTazConnector()) {
1087 msg = TLF("Departure speed for vehicle '%' is too high for the vehicle type '%'.", getID(), myType->getID());
1089 return false;
1090 }
1091 }
1092 if (myRoute->getEdges().size() > 0 && !(*myCurrEdge)->prohibits(this)) {
1093 myRouteValidity &= ~ROUTE_START_INVALID_PERMISSIONS;
1094 return true;
1095 } else {
1096 msg = TLF("Vehicle '%' is not allowed to depart on any lane of edge '%'.", getID(), (*myCurrEdge)->getID());
1098 return false;
1099 }
1100}
1101
1102
1103int
1104MSBaseVehicle::getRouteValidity(bool update, bool silent, std::string* msgReturn) {
1105 if (!update) {
1106 return myRouteValidity;
1107 }
1108 // insertion check must be done in any case
1109 std::string msg;
1110 if (!hasValidRouteStart(msg)) {
1112 throw ProcessError(msg);
1113 } else if (!silent) {
1114 // vehicle will be discarded
1115 WRITE_WARNING(msg);
1116 } else if (msgReturn != nullptr) {
1117 *msgReturn = msg;
1118 }
1119 }
1122 // we could check after the first rerouting
1124 if (!hasValidRoute(msg, myRoute)) {
1126 throw ProcessError(TLF("Vehicle '%' has no valid route. %", getID(), msg));
1127 }
1128 }
1129 myRouteValidity &= ~ROUTE_UNCHECKED;
1130 return myRouteValidity;
1131}
1132
1133
1134bool
1136 for (auto item : myMoveReminders) {
1137 if (item.first == rem) {
1138 return true;
1139 }
1140 }
1141 return false;
1142}
1143
1144
1145void
1147#ifdef _DEBUG
1148 if (myTraceMoveReminders) {
1149 traceMoveReminder("add", rem, pos, true);
1150 }
1151#endif
1152 myMoveReminders.push_back(std::make_pair(rem, pos));
1153}
1154
1155
1156void
1158 for (MoveReminderCont::iterator r = myMoveReminders.begin(); r != myMoveReminders.end(); ++r) {
1159 if (r->first == rem) {
1160#ifdef _DEBUG
1161 if (myTraceMoveReminders) {
1162 traceMoveReminder("remove", rem, 0, false);
1163 }
1164#endif
1165 myMoveReminders.erase(r);
1166 return;
1167 }
1168 }
1169}
1170
1171
1172void
1174 // notifyEnter may cause new reminders to be added so we cannot use an iterator
1175 for (int i = 0; i < (int)myMoveReminders.size();) {
1176 MSMoveReminder* rem = myMoveReminders[i].first;
1177 const double remPos = myMoveReminders[i].second;
1178 // skip the reminder if it is a lane reminder but not for my lane (indicated by rem->second > 0.)
1179 if (rem->getLane() != nullptr && remPos > 0.) {
1180#ifdef _DEBUG
1181 if (myTraceMoveReminders) {
1182 traceMoveReminder("notifyEnter_skipped", rem, remPos, true);
1183 }
1184#endif
1185 ++i;
1186 } else {
1187 if (rem->notifyEnter(*this, reason, enteredLane)) {
1188#ifdef _DEBUG
1189 if (myTraceMoveReminders) {
1190 traceMoveReminder("notifyEnter", rem, remPos, true);
1191 }
1192#endif
1193 ++i;
1194 } else {
1195#ifdef _DEBUG
1196 if (myTraceMoveReminders) {
1197 traceMoveReminder("notifyEnter", rem, remPos, false);
1198 }
1199#endif
1200 myMoveReminders.erase(myMoveReminders.begin() + i);
1201 }
1202 }
1203 }
1204}
1205
1206
1207bool
1209 return isRailway(getVClass()) || isRailway(getCurrentEdge()->getPermissions());
1210}
1211
1212void
1214 if (myRoute->getLastEdge()->isTazConnector()) {
1215 return;
1216 }
1217 const int arrivalEdgeIndex = MIN2(myParameter->arrivalEdge, (int)myRoute->getEdges().size() - 1);
1218 if (arrivalEdgeIndex != myParameter->arrivalEdge) {
1219 WRITE_WARNINGF(TL("Vehicle '%' ignores attribute arrivalEdge=% after rerouting at time=% (routeLength=%)"),
1220 getID(), myParameter->arrivalEdge, time2string(SIMSTEP), myRoute->getEdges().size() - 1);
1221 }
1222 const MSEdge* arrivalEdge = myParameter->arrivalEdge >= 0 ? myRoute->getEdges()[arrivalEdgeIndex] : myRoute->getLastEdge();
1223 if (!onInit) {
1224 arrivalEdge = myRoute->getLastEdge();
1225 // ignore arrivalEdge parameter after rerouting
1226 const_cast<SUMOVehicleParameter*>(myParameter)->arrivalEdge = -1;
1227 }
1228 const std::vector<MSLane*>& lanes = arrivalEdge->getLanes();
1229 const double lastLaneLength = lanes[0]->getLength();
1232 if (fabs(myParameter->arrivalPos) > lastLaneLength) {
1233 WRITE_WARNINGF(TL("Vehicle '%' will not be able to arrive at the given position!"), getID());
1234 }
1235 // Maybe we should warn the user about invalid inputs!
1236 myArrivalPos = MIN2(myParameter->arrivalPos, lastLaneLength);
1237 if (myArrivalPos < 0) {
1238 myArrivalPos = MAX2(myArrivalPos + lastLaneLength, 0.);
1239 }
1240 break;
1242 myArrivalPos = RandHelper::rand(lastLaneLength);
1243 break;
1245 myArrivalPos = lastLaneLength / 2.;
1246 break;
1247 default:
1248 myArrivalPos = lastLaneLength;
1249 break;
1250 }
1252 if (myParameter->arrivalLane >= (int)lanes.size() || !lanes[myParameter->arrivalLane]->allowsVehicleClass(myType->getVehicleClass())) {
1253 WRITE_WARNINGF(TL("Vehicle '%' will not be able to arrive at the given lane '%_%'!"), getID(), arrivalEdge->getID(), toString(myParameter->arrivalLane));
1254 }
1255 myArrivalLane = MIN2(myParameter->arrivalLane, (int)(lanes.size() - 1));
1257 myArrivalLane = -1;
1258 for (MSLane* lane : lanes) {
1259 if (lane->allowsVehicleClass(myType->getVehicleClass())) {
1260 myArrivalLane = lane->getIndex();
1261 break;
1262 }
1263 }
1264 if (myArrivalLane == -1) {
1265 WRITE_WARNINGF(TL("Vehicle '%' has no usable arrivalLane on edge '%'."), getID(), arrivalEdge->getID());
1266 myArrivalLane = 0;
1267 }
1269 // pick random lane among all usable lanes
1270 std::vector<MSLane*> usable;
1271 for (MSLane* lane : lanes) {
1272 if (lane->allowsVehicleClass(myType->getVehicleClass())) {
1273 usable.push_back(lane);
1274 }
1275 }
1276 if (usable.empty()) {
1277 WRITE_WARNINGF(TL("Vehicle '%' has no usable arrivalLane on edge '%'."), getID(), arrivalEdge->getID());
1278 myArrivalLane = 0;
1279 } else {
1280 myArrivalLane = usable[RandHelper::rand(0, (int)usable.size())]->getIndex();
1281 }
1282 }
1284 for (std::vector<MSLane*>::const_iterator l = lanes.begin(); l != lanes.end(); ++l) {
1285 if (myParameter->arrivalSpeed <= (*l)->getVehicleMaxSpeed(this)) {
1286 return;
1287 }
1288 }
1289 WRITE_WARNINGF(TL("Vehicle '%' will not be able to arrive with the given speed!"), getID());
1290 }
1291}
1292
1293void
1297 const int routeEdges = (int)myRoute->getEdges().size();
1299 // write specific edge in vehroute output for reproducibility
1300 pars->departEdge = RandHelper::rand(0, routeEdges);
1302 }
1303 assert(pars->departEdge >= 0);
1304 if (pars->departEdge >= routeEdges) {
1305 WRITE_WARNINGF(TL("Ignoring departEdge % for vehicle '%' with % route edges"), toString(pars->departEdge), getID(), toString(routeEdges));
1306 } else {
1307 myCurrEdge += pars->departEdge;
1308 }
1309 }
1311 const int routeEdges = (int)myRoute->getEdges().size();
1312 const int begin = (int)(myCurrEdge - myRoute->begin());
1313 // write specific edge in vehroute output for reproducibility
1314 pars->arrivalEdge = RandHelper::rand(begin, routeEdges);
1316 assert(pars->arrivalEdge >= begin);
1317 assert(pars->arrivalEdge < routeEdges);
1318 }
1319}
1320
1321int
1325
1326int
1330 } else {
1332 }
1333}
1334
1335double
1337 return MAX2(0., MIN2(1., getVehicleType().getImpatience()
1338 + (hasInfluencer() ? getBaseInfluencer()->getExtraImpatience() : 0)
1340}
1341
1342
1343MSDevice*
1344MSBaseVehicle::getDevice(const std::type_info& type) const {
1345 for (MSVehicleDevice* const dev : myDevices) {
1346 if (typeid(*dev) == type) {
1347 return dev;
1348 }
1349 }
1350 return nullptr;
1351}
1352
1353
1354void
1356 // the parameters may hold the name of a vTypeDistribution but we are interested in the actual type
1357 const std::string& typeID = myParameter->vtypeid != getVehicleType().getID() ? getVehicleType().getID() : "";
1359 // params and stops must be written in child classes since they may wish to add additional attributes first
1360 out.writeAttr(SUMO_ATTR_ROUTE, myRoute->getID());
1361 std::ostringstream os;
1362 os << myOdometer << " " << myNumberReroutes;
1363 out.writeAttr(SUMO_ATTR_DISTANCE, os.str());
1366 }
1368 const int precision = out.getPrecision();
1369 out.setPrecision(MAX2(gPrecisionRandom, precision));
1371 out.setPrecision(precision);
1372 }
1374 out.writeAttr(SUMO_ATTR_REROUTE, true);
1375 }
1377 // could be set from stop
1379 }
1380 // here starts the vehicle internal part (see loading)
1381 // @note: remember to close the vehicle tag when calling this in a subclass!
1382}
1383
1384
1385bool
1386MSBaseVehicle::handleCollisionStop(MSStop& stop, const double distToStop) {
1387 UNUSED_PARAMETER(stop);
1388 UNUSED_PARAMETER(distToStop);
1389 return true;
1390}
1391
1392
1393bool
1395 return !myStops.empty() && myStops.begin()->reached /*&& myState.mySpeed < SUMO_const_haltingSpeed @todo #1864#*/;
1396}
1397
1398
1399bool
1401 return (isStopped() && (myStops.begin()->pars.parking == ParkingType::OFFROAD)
1402 && (myStops.begin()->parkingarea == nullptr || !myStops.begin()->parkingarea->parkOnRoad())
1403 && (myStops.begin()->getSpeed() == 0 || getSpeed() < SUMO_const_haltingSpeed));
1404}
1405
1406
1407bool
1409 return myPastStops.size() > 0 && myPastStops.back().jump >= 0 && getEdge()->getID() == myPastStops.back().edge && myPastStops.back().ended == SIMSTEP;
1410}
1411
1412
1413bool
1415 return isStopped() && (myStops.begin()->triggered || myStops.begin()->containerTriggered || myStops.begin()->joinTriggered);
1416}
1417
1418
1419bool
1421 return isStopped() && (myStops.begin()->pars.parking == ParkingType::OFFROAD);
1422}
1423
1424
1425bool
1426MSBaseVehicle::isStoppedInRange(const double pos, const double tolerance, bool checkFuture) const {
1427 if (isStopped() || (checkFuture && hasStops())) {
1428 const MSStop& stop = myStops.front();
1429 return stop.pars.startPos - tolerance <= pos && stop.pars.endPos + tolerance >= pos;
1430 }
1431 return false;
1432}
1433
1434bool
1435MSBaseVehicle::replaceParkingArea(MSParkingArea* parkingArea, std::string& errorMsg) {
1436 // Check if there is a parking area to be replaced
1437 if (parkingArea == 0) {
1438 errorMsg = "new parkingArea is NULL";
1439 return false;
1440 }
1441 if (myStops.size() == 0) {
1442 errorMsg = "vehicle has no stops";
1443 return false;
1444 }
1445 if (myStops.front().parkingarea == 0) {
1446 errorMsg = "first stop is not at parkingArea";
1447 return false;
1448 }
1449 MSStop& first = myStops.front();
1450 SUMOVehicleParameter::Stop& stopPar = const_cast<SUMOVehicleParameter::Stop&>(first.pars);
1451 std::string oldStopEdgeID = first.lane->getEdge().getID();
1452 // merge subsequent duplicate stops equals to parking area
1453 for (std::list<MSStop>::iterator iter = ++myStops.begin(); iter != myStops.end();) {
1454 if (iter->parkingarea == parkingArea) {
1455 stopPar.duration += iter->duration;
1456 myStops.erase(iter++);
1457 } else {
1458 break;
1459 }
1460 }
1461 stopPar.lane = parkingArea->getLane().getID();
1462 stopPar.parkingarea = parkingArea->getID();
1463 stopPar.startPos = parkingArea->getBeginLanePosition();
1464 stopPar.endPos = parkingArea->getEndLanePosition();
1465 first.edge = myRoute->end(); // will be patched in replaceRoute
1466 first.lane = &parkingArea->getLane();
1467 first.parkingarea = parkingArea;
1468
1469 // patch via edges
1470 std::string newStopEdgeID = parkingArea->getLane().getEdge().getID();
1471 if (myParameter->via.size() > 0 && myParameter->via.front() != newStopEdgeID) {
1472 myParameter->via.erase(myParameter->via.begin());
1473 myParameter->via.insert(myParameter->via.begin(), newStopEdgeID);
1474 }
1475 return true;
1476}
1477
1478
1481 MSParkingArea* nextParkingArea = nullptr;
1482 if (!myStops.empty()) {
1484 MSStop stop = myStops.front();
1485 if (!stop.reached && stop.parkingarea != nullptr) {
1486 nextParkingArea = stop.parkingarea;
1487 }
1488 }
1489 return nextParkingArea;
1490}
1491
1492
1495 MSParkingArea* currentParkingArea = nullptr;
1496 if (isParking()) {
1497 currentParkingArea = myStops.begin()->parkingarea;
1498 }
1499 return currentParkingArea;
1500}
1501
1502
1503const std::vector<std::string>&
1506 return myParameter->parkingBadges;
1507 } else {
1509 }
1510}
1511
1512
1513double
1514MSBaseVehicle::basePos(const MSEdge* edge) const {
1515 double result = MIN2(getVehicleType().getLength() + POSITION_EPS, edge->getLength());
1516 if (hasStops()
1517 && myStops.front().edge == myRoute->begin()
1518 && (&myStops.front().lane->getEdge()) == *myStops.front().edge) {
1519 result = MIN2(result, MAX2(0.0, myStops.front().getEndPos(*this)));
1520 }
1521 return result;
1522}
1523
1524
1525MSLane*
1527 const std::string edgeID = SUMOXMLDefinitions::getEdgeIDFromLane(stop.lane);
1528 const MSEdge* edge = MSEdge::dictionary(edgeID);
1529 if (edge == nullptr || edge->getOppositeEdge() == nullptr || stop.lane.find("_") == std::string::npos) {
1530 return nullptr;
1531 }
1532 const int laneIndex = SUMOXMLDefinitions::getIndexFromLane(stop.lane);
1533 if (laneIndex < (edge->getNumLanes() + edge->getOppositeEdge()->getNumLanes())) {
1534 const int oppositeIndex = edge->getOppositeEdge()->getNumLanes() + edge->getNumLanes() - 1 - laneIndex;
1535 stop.edge = edgeID;
1536 return edge->getOppositeEdge()->getLanes()[oppositeIndex];
1537 }
1538 return nullptr;
1539}
1540
1541
1542bool
1543MSBaseVehicle::addStop(const SUMOVehicleParameter::Stop& stopPar, std::string& errorMsg, SUMOTime untilOffset,
1544 MSRouteIterator* searchStart) {
1545 MSStop stop(stopPar);
1546 if (stopPar.lane == "") {
1547 MSEdge* e = MSEdge::dictionary(stopPar.edge);
1548 stop.lane = e->getFirstAllowed(getVClass());
1549 if (stop.lane == nullptr) {
1550 errorMsg = "Vehicle '" + myParameter->id + "' is not allowed to stop on any lane of edge '" + stopPar.edge + "'.";
1551 return false;
1552 }
1553 } else {
1554 stop.lane = MSLane::dictionary(stopPar.lane);
1555 if (stop.lane == nullptr) {
1556 // must be an opposite stop
1557 SUMOVehicleParameter::Stop tmp = stopPar;
1558 stop.lane = interpretOppositeStop(tmp);
1559 assert(stop.lane != nullptr);
1560 }
1562 errorMsg = "Vehicle '" + myParameter->id + "' is not allowed to stop on lane '" + stopPar.lane + "'.";
1563 return false;
1564 }
1565 }
1567 stop.segment = MSGlobals::gMesoNet->getSegmentForEdge(stop.lane->getEdge(), stop.getEndPos(*this));
1568 if (stop.lane->isInternal()) {
1569 errorMsg = "Mesoscopic simulation does not allow stopping on internal edge '" + stopPar.edge + "' for vehicle '" + myParameter->id + "'.";
1570 return false;
1571 }
1572 }
1573 stop.initPars(stopPar);
1574 if (stopPar.until != -1) {
1575 // !!! it would be much cleaner to invent a constructor for stops which takes "until" as an argument
1576 const_cast<SUMOVehicleParameter::Stop&>(stop.pars).until += untilOffset;
1577 }
1578 if (stopPar.arrival != -1) {
1579 const_cast<SUMOVehicleParameter::Stop&>(stop.pars).arrival += untilOffset;
1580 }
1581 std::string stopType = "stop";
1582 std::string stopID = "";
1583 double parkingLength = stop.pars.endPos - stop.pars.startPos;
1584 if (stop.busstop != nullptr) {
1585 stopType = "busStop";
1586 stopID = stop.busstop->getID();
1587 parkingLength = stop.busstop->getParkingLength();
1588 } else if (stop.containerstop != nullptr) {
1589 stopType = "containerStop";
1590 stopID = stop.containerstop->getID();
1591 parkingLength = stop.containerstop->getParkingLength();
1592 } else if (stop.chargingStation != nullptr) {
1593 stopType = "chargingStation";
1594 stopID = stop.chargingStation->getID();
1595 parkingLength = stop.chargingStation->getParkingLength();
1596 } else if (stop.overheadWireSegment != nullptr) {
1597 stopType = "overheadWireSegment";
1598 stopID = stop.overheadWireSegment->getID();
1599 parkingLength = stop.overheadWireSegment->getParkingLength();
1600 } else if (stop.parkingarea != nullptr) {
1601 stopType = "parkingArea";
1602 stopID = stop.parkingarea->getID();
1603 }
1604 const std::string errorMsgStart = stopID == "" ? stopType : stopType + " '" + stopID + "'";
1605
1606 if (stop.pars.startPos < 0 || stop.pars.endPos > stop.lane->getLength()) {
1607 errorMsg = errorMsgStart + " for vehicle '" + myParameter->id + "' on lane '" + stop.lane->getID() + "' has an invalid position.";
1608 return false;
1609 }
1610 if (stopType != "stop" && stopType != "parkingArea" && myType->getLength() / 2. > parkingLength
1611 // do not warn for stops that fill the whole lane
1612 && parkingLength < stop.lane->getLength()
1613 // do not warn twice for the same stop
1614 && MSNet::getInstance()->warnOnce(stopType + ":" + stopID)) {
1615 errorMsg = errorMsgStart + " on lane '" + stop.lane->getID() + "' is too short for vehicle '" + myParameter->id + "'.";
1616 }
1617 if (stopType == "parkingArea" && !stop.parkingarea->accepts(this)) {
1618 // forbid access in case the parking requests other badges
1619 errorMsg = errorMsgStart + "on lane '" + stop.lane->getID() + "' forbids access because vehicle '" + myParameter->id + "' does not provide any valid badge.";
1620 return false;
1621 }
1622 const MSEdge* stopLaneEdge = &stop.lane->getEdge();
1623 const MSEdge* stopEdge;
1624 if (stopLaneEdge->getOppositeEdge() != nullptr && stopLaneEdge->getOppositeEdge()->getID() == stopPar.edge) {
1625 // stop lane is on the opposite side
1626 stopEdge = stopLaneEdge->getOppositeEdge();
1627 stop.isOpposite = true;
1628 } else {
1629 // if stop is on an internal edge the normal edge before the intersection is used
1630 stopEdge = stopLaneEdge->getNormalBefore();
1631 }
1632 MSRouteIterator succ = myCurrEdge + 1; // we're using the address but only within the scope of this function (and recursive calls)
1633 if (searchStart == nullptr) {
1634 searchStart = &myCurrEdge;
1635 if (stopLaneEdge->isNormal() && getLane() != nullptr && getLane()->isInternal()) {
1636 // already on the intersection but myCurrEdge is before it
1637 searchStart = &succ;
1638 }
1639 }
1640#ifdef DEBUG_ADD_STOP
1641 if (DEBUG_COND) {
1642 std::cout << "addStop desc=" << stop.getDescription() << " stopEdge=" << stopEdge->getID()
1643 << " searchStart=" << ((*searchStart) == myRoute->end() ? "END" : (**searchStart)->getID())
1644 << " index=" << (int)((*searchStart) - myRoute->begin()) << " route=" << toString(myRoute->getEdges())
1645 << "\n";
1646 }
1647#endif
1648 stop.edge = std::find(*searchStart, myRoute->end(), stopEdge);
1649 MSRouteIterator prevStopEdge = myCurrEdge;
1650 const MSEdge* prevEdge = (getLane() == nullptr ? getEdge() : &getLane()->getEdge());
1651 double prevStopPos = getPositionOnLane();
1652 // where to insert the stop
1653 std::list<MSStop>::iterator iter = myStops.begin();
1654 if (stopPar.index == STOP_INDEX_END || stopPar.index >= static_cast<int>(myStops.size()) || stopPar.index == STOP_INDEX_REPEAT) {
1655 iter = myStops.end();
1656 if (myStops.size() > 0 && myStops.back().edge >= *searchStart) {
1657 prevStopEdge = myStops.back().edge;
1658 prevEdge = &myStops.back().lane->getEdge();
1659 prevStopPos = myStops.back().pars.endPos;
1660 stop.edge = std::find(prevStopEdge, myRoute->end(), stopEdge);
1661 if (prevStopEdge == stop.edge // laneEdge check is insufficient for looped routes
1662 && prevEdge == &stop.lane->getEdge() // route iterator check insufficient for internal lane stops
1663 && (prevStopPos > stop.pars.endPos ||
1664 (prevStopPos == stop.pars.endPos && stopPar.index == STOP_INDEX_REPEAT))) {
1665 stop.edge = std::find(prevStopEdge + 1, myRoute->end(), stopEdge);
1666 }
1667#ifdef DEBUG_ADD_STOP
1668 if (DEBUG_COND) {
1669 std::cout << " (@end) prevStopEdge=" << (*prevStopEdge)->getID() << " prevStopPos=" << prevStopPos << " index=" << (int)(prevStopEdge - myRoute->begin())
1670 << " foundIndex=" << (stop.edge == myRoute->end() ? -1 : (int)(stop.edge - myRoute->begin())) << "\n";
1671 }
1672#endif
1673 }
1674 // skip a number of occurences of stopEdge in looped route
1675 int skipLooped = stopPar.index - static_cast<int>(myStops.size());
1676 for (int j = 0; j < skipLooped; j++) {
1677 auto nextIt = std::find(stop.edge + 1, myRoute->end(), stopEdge);
1678 if (nextIt == myRoute->end()) {
1679 if (std::find(myRoute->begin(), stop.edge, stopEdge) != stop.edge) {
1680 // only warn if the route loops over the stop edge at least once
1681 errorMsg = errorMsgStart + " for vehicle '" + myParameter->id + "' could not skip " + toString(skipLooped) + " occurences of stop edge '" + stopEdge->getID() + "' in looped route.";
1682 }
1683 break;
1684 } else {
1685 stop.edge = nextIt;
1686 }
1687 }
1688 } else {
1689 if (stopPar.index == STOP_INDEX_FIT) {
1690 while (iter != myStops.end() && (iter->edge < stop.edge ||
1691 (iter->pars.endPos < stop.pars.endPos && iter->edge == stop.edge) ||
1692 (stop.lane->getEdge().isInternal() && iter->edge == stop.edge))) {
1693 prevStopEdge = iter->edge;
1694 prevStopPos = iter->pars.endPos;
1695 ++iter;
1696 }
1697 } else {
1698 int index = stopPar.index;
1699 while (index > 0) {
1700 prevStopEdge = iter->edge;
1701 prevStopPos = iter->pars.endPos;
1702 ++iter;
1703 --index;
1704 }
1705#ifdef DEBUG_ADD_STOP
1706 if (DEBUG_COND) {
1707 std::cout << " (@fit) prevStopEdge=" << (*prevStopEdge)->getID() << " index=" << (int)(prevStopEdge - myRoute->begin()) << "\n";
1708 }
1709#endif
1710 stop.edge = std::find(prevStopEdge, myRoute->end(), stopEdge);
1711 }
1712 }
1713 const bool wasTooClose = errorMsg != "" && errorMsg.find("too close") != std::string::npos;
1714 if (stop.edge == myRoute->end()) {
1715 if (!wasTooClose) {
1716 errorMsg = errorMsgStart + " for vehicle '" + myParameter->id + "' on lane '" + stop.lane->getID() + "' is not downstream the current route.";
1717 }
1718 return false;
1719 }
1720
1721 const bool tooClose = (prevStopEdge == stop.edge && prevEdge == &stop.lane->getEdge() &&
1722 prevStopPos + (iter == myStops.begin() ? getBrakeGap() : 0) > stop.pars.endPos + POSITION_EPS);
1723
1724 if (prevStopEdge > stop.edge ||
1725 // a collision-stop happens after vehicle movement and may move the
1726 // vehicle backwards on its lane (prevStopPos is the vehicle position)
1727 (tooClose && !stop.pars.collision)
1728 || (stop.lane->getEdge().isInternal() && stop.lane->getNextNormal() != *(stop.edge + 1))) {
1729 // check if the edge occurs again later in the route
1730 //std::cout << " could not add stop " << errorMsgStart << " prevStops=" << myStops.size() << " searchStart=" << (*searchStart - myRoute->begin()) << " route=" << toString(myRoute->getEdges()) << "\n";
1731 if (tooClose && prevStopPos <= stop.pars.endPos + POSITION_EPS) {
1732 errorMsg = errorMsgStart + " for vehicle '" + myParameter->id + "' on lane '" + stop.pars.lane + "' is too close to brake.";
1733 }
1734 MSRouteIterator next = stop.edge + 1;
1735 return addStop(stopPar, errorMsg, untilOffset, &next);
1736 }
1737 if (wasTooClose) {
1738 errorMsg = "";
1739 }
1740 // David.C:
1741 //if (!stop.parking && (myCurrEdge == stop.edge && myState.myPos > stop.endPos - getCarFollowModel().brakeGap(myState.mySpeed))) {
1742 const double endPosOffset = stop.lane->getEdge().isInternal() ? (*stop.edge)->getLength() : 0;
1743 const double distToStop = stop.pars.endPos + endPosOffset - getPositionOnLane();
1744 if (stop.pars.collision && !handleCollisionStop(stop, distToStop)) {
1745 return false;
1746 }
1747 if (!hasDeparted() && myCurrEdge == stop.edge) {
1748 double pos = -1;
1750 pos = myParameter->departPos;
1751 if (pos < 0.) {
1752 pos += (*myCurrEdge)->getLength();
1753 }
1754 }
1756 pos = MIN2(stop.pars.endPos + endPosOffset, basePos(*myCurrEdge));
1757 }
1758 if (pos > stop.pars.endPos + endPosOffset) {
1759 if (stop.edge != myRoute->end()) {
1760 // check if the edge occurs again later in the route
1761 MSRouteIterator next = stop.edge + 1;
1762 return addStop(stopPar, errorMsg, untilOffset, &next);
1763 }
1764 errorMsg = errorMsgStart + " for vehicle '" + myParameter->id + "' on lane '" + stop.lane->getID() + "' is before departPos.";
1765 return false;
1766 }
1767 }
1768 if (iter != myStops.begin()) {
1769 std::list<MSStop>::iterator iter2 = iter;
1770 iter2--;
1771 if (stop.getUntil() >= 0 && iter2->getUntil() > stop.getUntil()
1772 && (!MSGlobals::gUseStopEnded || iter2->pars.ended < 0 || stop.pars.ended >= 0)) {
1773 errorMsg = errorMsgStart + " for vehicle '" + myParameter->id + "' on lane '" + stop.lane->getID()
1774 + "' set to end at " + time2string(stop.getUntil())
1775 + " earlier than previous stop at " + time2string(iter2->getUntil()) + ".";
1776 }
1777 if (stop.pars.arrival >= 0 && iter2->pars.arrival > stop.pars.arrival) {
1778 errorMsg = errorMsgStart + " for vehicle '" + myParameter->id + "' on lane '" + stop.lane->getID()
1779 + "' set to start at " + time2string(stop.pars.arrival)
1780 + " earlier than previous stop end at " + time2string(iter2->getUntil()) + ".";
1781 }
1782 if (stop.pars.arrival >= 0 && iter2->pars.arrival > stop.pars.arrival) {
1783 errorMsg = errorMsgStart + " for vehicle '" + myParameter->id + "' on lane '" + stop.lane->getID()
1784 + "' set to start at " + time2string(stop.pars.arrival)
1785 + " earlier than previous stop arrival at " + time2string(iter2->pars.arrival) + ".";
1786 }
1787 } else {
1788 if (stop.getUntil() >= 0 && getParameter().depart > stop.getUntil()
1789 && (!MSGlobals::gUseStopEnded || stop.pars.ended < 0)) {
1790 errorMsg = errorMsgStart + " for vehicle '" + myParameter->id + "' on lane '" + stop.lane->getID()
1791 + "' set to end at " + time2string(stop.getUntil())
1792 + " earlier than departure at " + time2string(getParameter().depart) + ".";
1793 }
1794 }
1795 if (stop.getUntil() >= 0 && stop.getArrival() > stop.getUntil() && errorMsg == "") {
1796 errorMsg = errorMsgStart + " for vehicle '" + myParameter->id + "' on lane '" + stop.lane->getID()
1797 + "' set to end at " + time2string(stop.getUntil())
1798 + " earlier than arrival at " + time2string(stop.getArrival()) + ".";
1799 }
1800 setSkips(stop, (int)myStops.size());
1801 myStops.insert(iter, stop);
1802 if (stopPar.tripId != "") {
1804 }
1805 //std::cout << " added stop " << errorMsgStart << " totalStops=" << myStops.size() << " searchStart=" << (*searchStart - myRoute->begin())
1806 // << " routeIndex=" << (stop.edge - myRoute->begin())
1807 // << " stopIndex=" << std::distance(myStops.begin(), iter)
1808 // << " route=" << toString(myRoute->getEdges()) << "\n";
1809 return true;
1810}
1811
1812
1813void
1814MSBaseVehicle::setSkips(MSStop& stop, int prevActiveStops) {
1815 if (hasDeparted() && stop.edge > myRoute->begin()) {
1816 // if the route is looped we must patch the index to ensure that state
1817 // loading (and vehroute-output) encode the correct number of skips
1818 int foundSkips = 0;
1819 MSRouteIterator itPrev;
1820 double prevEndPos;
1821 if (prevActiveStops > 0) {
1822 assert((int)myStops.size() >= prevActiveStops);
1823 auto prevStopIt = myStops.begin();
1824 std::advance(prevStopIt, prevActiveStops - 1);
1825 const MSStop& prev = *prevStopIt;
1826 itPrev = prev.edge;
1827 prevEndPos = prev.pars.endPos;
1828 } else if (myPastStops.size() > 0) {
1829 itPrev = myRoute->begin() + myPastStops.back().routeIndex;
1830 prevEndPos = myPastStops.back().endPos;
1831 } else {
1832 itPrev = myRoute->begin() + myParameter->departEdge;
1833 prevEndPos = myDepartPos;
1834 }
1835 //auto itPrevOrig = itPrev;
1836 if (*itPrev == *stop.edge && prevEndPos > stop.pars.endPos) {
1837 itPrev++;
1838 }
1839 //std::cout << SIMTIME << " veh=" << getID() << " prevActive=" << prevActiveStops << " edge=" << (*stop.edge)->getID() << " routeIndex=" << (stop.edge - myRoute->begin()) << " prevIndex=" << (itPrev - myRoute->begin()) << "\n";
1840 while (itPrev < stop.edge) {
1841 if (*itPrev == *stop.edge) {
1842 foundSkips++;
1843 }
1844 itPrev++;
1845 }
1846 int newIndex = STOP_INDEX_END;
1847 if (foundSkips > 0) {
1848 //if (getID() == "77_0_0") {
1849 // std::cout << SIMTIME << " veh=" << getID() << " past=" << myPastStops.size() << " prevActive=" << prevActiveStops
1850 // << " edge=" << (*stop.edge)->getID() << " routeIndex=" << (stop.edge - myRoute->begin())
1851 // << " prevEdge=" << (*itPrevOrig)->getID()
1852 // << " prevIndex=" << (itPrevOrig - myRoute->begin())
1853 // << " skips=" << foundSkips << "\n";
1854 //}
1855 newIndex = (int)myPastStops.size() + prevActiveStops + foundSkips;
1856 }
1857 const_cast<SUMOVehicleParameter::Stop&>(stop.pars).index = newIndex;
1858 }
1859}
1860
1861
1864 for (int i = 0; i < (int)myMoveReminders.size();) {
1865 auto rem = &myMoveReminders[i];
1866 if (rem->first->notifyReroute(*this)) {
1867#ifdef _DEBUG
1868 if (myTraceMoveReminders) {
1869 traceMoveReminder("notifyReroute", rem->first, rem->second, true);
1870 }
1871#endif
1872 ++i;
1873 } else {
1874#ifdef _DEBUG
1875 if (myTraceMoveReminders) {
1876 traceMoveReminder("notifyReroute", rem->first, rem->second, false);
1877 }
1878#endif
1879 myMoveReminders.erase(myMoveReminders.begin() + i);
1880 }
1881 }
1883 // event only called once
1884 return 0;
1885}
1886
1887
1888void
1889MSBaseVehicle::addStops(const bool ignoreStopErrors, MSRouteIterator* searchStart, bool addRouteStops) {
1890 if (addRouteStops) {
1891 for (const SUMOVehicleParameter::Stop& stop : myRoute->getStops()) {
1892 std::string errorMsg;
1893 if (!addStop(stop, errorMsg, myParameter->depart, searchStart) && !ignoreStopErrors) {
1894 throw ProcessError(errorMsg);
1895 }
1896 if (errorMsg != "") {
1897 WRITE_WARNING(errorMsg);
1898 }
1899 }
1900 }
1902 for (const SUMOVehicleParameter::Stop& stop : myParameter->stops) {
1903 std::string errorMsg;
1904 if (!addStop(stop, errorMsg, untilOffset, searchStart) && !ignoreStopErrors) {
1905 throw ProcessError(errorMsg);
1906 }
1907 if (errorMsg != "") {
1908 WRITE_WARNING(errorMsg);
1909 }
1910 }
1911}
1912
1913
1914bool
1917 int i = 0;
1918 bool ok = true;
1919 for (const MSStop& stop : myStops) {
1920 MSRouteIterator it;
1921 if (stop.lane->isInternal()) {
1922 // find the normal predecessor and ensure that the next route edge
1923 // matches the successor of the internal edge successor
1924 it = std::find(start, myRoute->end(), stop.lane->getEdge().getNormalBefore());
1925 if (it != myRoute->end() && (
1926 it + 1 == myRoute->end() || *(it + 1) != stop.lane->getEdge().getNormalSuccessor())) {
1927 it = myRoute->end(); // signal failure
1928 }
1929 } else {
1930 it = std::find(start, myRoute->end(), &stop.lane->getEdge());
1931 }
1932 if (it == myRoute->end()) {
1933 if (!silent) {
1934 WRITE_ERRORF("Stop % on edge '%' is not found after edge '%' (% after current) for vehicle '%' at time=%.",
1935 i, stop.lane->getEdge().getID(), (*start)->getID(), toString(start - myCurrEdge), getID(), time2string(SIMSTEP));
1936 }
1937 ok = false;
1938 } else {
1939 MSRouteIterator it2;
1940 for (it2 = myRoute->begin(); it2 != myRoute->end(); it2++) {
1941 if (it2 == stop.edge) {
1942 break;
1943 }
1944 }
1945 if (it2 == myRoute->end()) {
1946 if (!silent) {
1947 WRITE_ERRORF("Stop % on edge '%' used invalid route index for vehicle '%' at time=%.",
1948 i, stop.lane->getEdge().getID(), getID(), time2string(SIMSTEP));
1949 }
1950 ok = false;
1951 } else if (it2 < start) {
1952 if (!silent) {
1953 WRITE_ERRORF("Stop % on edge '%' used invalid (relative) route index % expected after % for vehicle '%' at time=%.",
1954 i, stop.lane->getEdge().getID(), toString(it2 - myCurrEdge), toString(start - myCurrEdge), getID(), time2string(SIMSTEP));
1955 }
1956 ok = false;
1957 } else {
1958 start = stop.edge;
1959 }
1960 }
1961 i++;
1962 }
1963 return ok;
1964}
1965
1966
1967std::vector<MSBaseVehicle::StopEdgeInfo>
1968MSBaseVehicle::getStopEdges(double& firstPos, double& lastPos, std::set<int>& jumps) const {
1969 assert(haveValidStopEdges());
1970 std::vector<StopEdgeInfo> result;
1971 const MSStop* prev = nullptr;
1972 const MSEdge* internalSuccessor = nullptr;
1973 for (const MSStop& stop : myStops) {
1974 if (stop.reached) {
1975 if (stop.pars.jump >= 0) {
1976 jumps.insert((int)result.size());
1977 }
1978 continue;
1979 }
1980 const double stopPos = stop.getEndPos(*this);
1981 if ((prev == nullptr
1982 || prev->edge != stop.edge
1983 || (prev->lane == stop.lane && prev->getEndPos(*this) > stopPos))
1984 && *stop.edge != internalSuccessor) {
1985 result.push_back(StopEdgeInfo(*stop.edge, stop.pars.priority, stop.getArrivalFallback(), stopPos));
1986 if (stop.lane->isInternal()) {
1987 internalSuccessor = stop.lane->getNextNormal();
1988 result.push_back(StopEdgeInfo(internalSuccessor, stop.pars.priority, stop.getArrivalFallback(), stopPos));
1989 } else {
1990 internalSuccessor = nullptr;
1991 }
1992 } else if (prev != nullptr && prev->edge == stop.edge) {
1993 result.back().priority = addStopPriority(result.back().priority, stop.pars.priority);
1994 }
1995 prev = &stop;
1996 if (firstPos == INVALID_DOUBLE) {
1997 if (stop.parkingarea != nullptr) {
1998 firstPos = MAX2(0., stopPos);
1999 } else {
2000 firstPos = stopPos;
2001 }
2002 }
2003 lastPos = stopPos;
2004 if (stop.pars.jump >= 0) {
2005 jumps.insert((int)result.size() - 1);
2006 }
2007 }
2008 //std::cout << "getStopEdges veh=" << getID() << " result=" << toString(result) << "\n";
2009 return result;
2010}
2011
2012
2013double
2014MSBaseVehicle::addStopPriority(double p1, double p2) {
2015 if (p1 < 0 || p2 < 0) {
2016 return p1;
2017 }
2018 return p1 + p2;
2019}
2020
2021std::vector<std::pair<int, double> >
2023 std::vector<std::pair<int, double> > result;
2024 for (std::list<MSStop>::const_iterator iter = myStops.begin(); iter != myStops.end(); ++iter) {
2025 result.push_back(std::make_pair(
2026 (int)(iter->edge - myRoute->begin()),
2027 iter->getEndPos(*this)));
2028 }
2029 return result;
2030}
2031
2032
2033const MSStop&
2035 assert(myStops.size() > 0);
2036 return myStops.front();
2037}
2038
2039MSStop&
2041 assert(myStops.size() > 0);
2042 return myStops.front();
2043}
2044
2047 if (isStopped()) {
2048 return myStops.front().duration;
2049 } else {
2050 return 0;
2051 }
2052}
2053
2054
2055MSStop&
2056MSBaseVehicle::getStop(int nextStopIndex) {
2057 if (nextStopIndex < 0 || (int)myStops.size() <= nextStopIndex) {
2058 throw InvalidArgument(TLF("Invalid stop index % (has % stops).", nextStopIndex, myStops.size()));
2059 }
2060 auto stopIt = myStops.begin();
2061 std::advance(stopIt, nextStopIndex);
2062 return *stopIt;
2063}
2064
2065
2068 if (hasStops()) {
2069 return &myStops.front().pars;
2070 }
2071 return nullptr;
2072}
2073
2074
2075bool
2077 //if the stop exists update the duration
2078 for (std::list<MSStop>::iterator iter = myStops.begin(); iter != myStops.end(); iter++) {
2079 if (iter->lane->getID() == stop.lane && fabs(iter->pars.endPos - stop.endPos) < POSITION_EPS) {
2080 // update existing stop
2081 if (stop.duration == 0 && stop.until < 0 && !iter->reached) {
2082 myStops.erase(iter);
2083 } else {
2084 iter->duration = stop.duration;
2085 iter->triggered = stop.triggered;
2086 iter->containerTriggered = stop.containerTriggered;
2087 const_cast<SUMOVehicleParameter::Stop&>(iter->pars).until = stop.until;
2088 const_cast<SUMOVehicleParameter::Stop&>(iter->pars).parking = stop.parking;
2089 }
2090 return true;
2091 }
2092 }
2093 const bool result = addStop(stop, errorMsg);
2094 if (result) {
2096 myParameter->stops.push_back(stop);
2097 }
2098 return result;
2099}
2100
2101
2102void
2109
2110
2111bool
2113 if (hasStops() && nextStopIndex < (int)myStops.size()) {
2114 if (nextStopIndex == 0 && isStopped()) {
2116 } else {
2117 auto stopIt = myStops.begin();
2118 std::advance(stopIt, nextStopIndex);
2119 myStops.erase(stopIt);
2120 }
2121 if (!hasDeparted() && (int)myParameter->stops.size() > nextStopIndex) {
2122 // stops will be rebuilt from scratch on rerouting so we must patch the stops in myParameter
2123 auto stopIt2 = myParameter->stops.begin();
2124 std::advance(stopIt2, nextStopIndex);
2125 const_cast<SUMOVehicleParameter*>(myParameter)->stops.erase(stopIt2);
2126 }
2127 return true;
2128 } else {
2129 return false;
2130 }
2131}
2132
2133
2134bool
2135MSBaseVehicle::replaceStop(int nextStopIndex, SUMOVehicleParameter::Stop stop, const std::string& info, bool teleport, std::string& errorMsg) {
2136 const int n = (int)myStops.size();
2137 if (nextStopIndex < 0 || nextStopIndex >= n) {
2138 errorMsg = TLF("invalid nextStopIndex % for % remaining stops", nextStopIndex, n);
2139 return false;
2140 }
2141 if (nextStopIndex == 0 && isStopped()) {
2142 errorMsg = TL("cannot replace reached stop");
2143 return false;
2144 }
2146 MSLane* stopLane = MSLane::dictionary(stop.lane);
2147 MSEdge* stopEdge = &stopLane->getEdge();
2148
2149 auto itStop = myStops.begin();
2150 std::advance(itStop, nextStopIndex);
2151 MSStop& replacedStop = *itStop;
2152
2153 // check parking access rights
2154 if (stop.parkingarea != "") {
2156 if (pa != nullptr && !pa->accepts(this)) {
2157 errorMsg = TLF("vehicle '%' does not have the right badge to access parkingArea '%'", getID(), stop.parkingarea);
2158 return false;
2159 }
2160 }
2161
2162 if (replacedStop.lane == stopLane && replacedStop.pars.endPos == stop.endPos && !teleport) {
2163 // only replace stop attributes
2164 const_cast<SUMOVehicleParameter::Stop&>(replacedStop.pars) = stop;
2165 replacedStop.initPars(stop);
2166 return true;
2167 }
2168
2169 if (!stopLane->allowsVehicleClass(getVClass(), myRoutingMode)) {
2170 errorMsg = TLF("disallowed stop lane '%'", stopLane->getID());
2171 return false;
2172 }
2173
2174 const ConstMSEdgeVector& oldEdges = getRoute().getEdges();
2175 std::vector<MSStop> stops(myStops.begin(), myStops.end());
2176 const int junctionOffset = getLane() != nullptr && getLane()->isInternal() ? 1 : 0;
2177 MSRouteIterator itStart = nextStopIndex == 0 ? getCurrentRouteEdge() + junctionOffset : stops[nextStopIndex - 1].edge;
2178 double startPos = nextStopIndex == 0 ? getPositionOnLane() : stops[nextStopIndex - 1].pars.endPos;
2179 MSRouteIterator itEnd = nextStopIndex == n - 1 ? oldEdges.end() - 1 : stops[nextStopIndex + 1].edge;
2180 auto endPos = nextStopIndex == n - 1 ? getArrivalPos() : stops[nextStopIndex + 1].pars.endPos;
2182
2183 bool newDestination = nextStopIndex == n - 1 && stops[nextStopIndex].edge == oldEdges.end() - 1;
2184
2185 ConstMSEdgeVector toNewStop;
2186 if (!teleport) {
2187 router.compute(*itStart, startPos, stopEdge, stop.endPos, this, t, toNewStop, true);
2188 if (toNewStop.size() == 0) {
2189 errorMsg = TLF("no route found from edge '%' to stop edge '%'", (*itStart)->getID(), stopEdge->getID());
2190 return false;
2191 }
2192 }
2193
2194 ConstMSEdgeVector fromNewStop;
2195 if (!newDestination) {
2196 router.compute(stopEdge, stop.endPos, *itEnd, endPos, this, t, fromNewStop, true);
2197 if (fromNewStop.size() == 0) {
2198 errorMsg = TLF("no route found from stop edge '%' to edge '%'", stopEdge->getID(), (*itEnd)->getID());
2199 return false;
2200 }
2201 }
2202
2203 const_cast<SUMOVehicleParameter::Stop&>(replacedStop.pars) = stop;
2204 replacedStop.initPars(stop);
2205 replacedStop.edge = myRoute->end(); // will be patched in replaceRoute
2206 replacedStop.lane = stopLane;
2208 replacedStop.segment = MSGlobals::gMesoNet->getSegmentForEdge(replacedStop.lane->getEdge(), replacedStop.getEndPos(*this));
2209 if (replacedStop.lane->isInternal()) {
2210 errorMsg = TLF("Mesoscopic simulation does not allow stopping on internal edge '%' for vehicle '%'.", stop.edge, getID());
2211 return false;
2212 }
2213 }
2214
2215 ConstMSEdgeVector oldRemainingEdges(myCurrEdge, getRoute().end());
2216 ConstMSEdgeVector newEdges; // only remaining
2217 newEdges.insert(newEdges.end(), myCurrEdge, itStart);
2218 if (!teleport) {
2219 newEdges.insert(newEdges.end(), toNewStop.begin(), toNewStop.end() - 1);
2220 } else {
2221 newEdges.push_back(*itStart);
2222 }
2223 if (!newDestination) {
2224 newEdges.insert(newEdges.end(), fromNewStop.begin(), fromNewStop.end() - 1);
2225 newEdges.insert(newEdges.end(), itEnd, oldEdges.end());
2226 } else {
2227 newEdges.push_back(stopEdge);
2228 }
2229 //std::cout << SIMTIME << " replaceStop veh=" << getID()
2230 // << " teleport=" << teleport
2231 // << " busStop=" << stop.busstop
2232 // << " oldEdges=" << oldRemainingEdges.size()
2233 // << " newEdges=" << newEdges.size()
2234 // << " toNewStop=" << toNewStop.size()
2235 // << " fromNewStop=" << fromNewStop.size()
2236 // << "\n";
2237
2238 const double routeCost = router.recomputeCosts(newEdges, this, t);
2239 const double previousCost = router.recomputeCosts(oldRemainingEdges, this, t);
2240 const double savings = previousCost - routeCost;
2241 if (!hasDeparted() && (int)myParameter->stops.size() > nextStopIndex) {
2242 // stops will be rebuilt from scratch so we must patch the stops in myParameter
2243 const_cast<SUMOVehicleParameter*>(myParameter)->stops[nextStopIndex] = stop;
2244 }
2245 if (teleport) {
2246 // let the vehicle jump rather than teleport
2247 // we add a jump-stop at the end of the edge (unless the vehicle is
2248 // already configure to jump before the replaced stop)
2249 if (!insertJump(nextStopIndex, itStart, errorMsg)) {
2250 return false;
2251 };
2252 }
2253 return replaceRouteEdges(newEdges, routeCost, savings, info, !hasDeparted(), false, false, &errorMsg);
2254}
2255
2256
2257bool
2258MSBaseVehicle::rerouteBetweenStops(int nextStopIndex, const std::string& info, bool teleport, std::string& errorMsg) {
2259 const int n = (int)myStops.size();
2260 if (nextStopIndex < 0 || nextStopIndex > n) {
2261 errorMsg = TLF("invalid nextStopIndex % for % remaining stops", nextStopIndex, n);
2262 return false;
2263 }
2264 if (nextStopIndex == 0 && isStopped()) {
2265 errorMsg = TL("cannot reroute towards reached stop");
2266 return false;
2267 }
2269
2270 const ConstMSEdgeVector& oldEdges = getRoute().getEdges();
2271 std::vector<MSStop> stops(myStops.begin(), myStops.end());
2272 const int junctionOffset = getLane() != nullptr && getLane()->isInternal() ? 1 : 0;
2273 MSRouteIterator itStart = nextStopIndex == 0 ? getCurrentRouteEdge() + junctionOffset : stops[nextStopIndex - 1].edge;
2274 double startPos = nextStopIndex == 0 ? getPositionOnLane() : stops[nextStopIndex - 1].pars.endPos;
2275 MSRouteIterator itEnd = nextStopIndex == n ? oldEdges.end() - 1 : stops[nextStopIndex].edge;
2276 auto endPos = nextStopIndex == n ? getArrivalPos() : stops[nextStopIndex].pars.endPos;
2278
2279 ConstMSEdgeVector newBetween;
2280 if (!teleport) {
2281 router.compute(*itStart, startPos, *itEnd, endPos, this, t, newBetween, true);
2282 if (newBetween.size() == 0) {
2283 errorMsg = TLF("no route found from edge '%' to stop edge '%'", (*itStart)->getID(), (*itEnd)->getID());
2284 return false;
2285 }
2286 }
2287
2288 ConstMSEdgeVector oldRemainingEdges(myCurrEdge, getRoute().end());
2289 ConstMSEdgeVector newEdges; // only remaining
2290 newEdges.insert(newEdges.end(), myCurrEdge, itStart);
2291 if (!teleport) {
2292 newEdges.insert(newEdges.end(), newBetween.begin(), newBetween.end() - 1);
2293 } else {
2294 newEdges.push_back(*itStart);
2295 }
2296 newEdges.insert(newEdges.end(), itEnd, oldEdges.end());
2297 //std::cout << SIMTIME << " rerouteBetweenStops veh=" << getID()
2298 // << " oldEdges=" << oldRemainingEdges.size()
2299 // << " newEdges=" << newEdges.size()
2300 // << " toNewStop=" << toNewStop.size()
2301 // << " fromNewStop=" << fromNewStop.size()
2302 // << "\n";
2303
2304 const double routeCost = router.recomputeCosts(newEdges, this, t);
2305 const double previousCost = router.recomputeCosts(oldRemainingEdges, this, t);
2306 const double savings = previousCost - routeCost;
2307
2308 if (teleport) {
2309 // let the vehicle jump rather than teleport
2310 // we add a jump-stop at the end of the edge (unless the vehicle is
2311 // already configure to jump before the replaced stop)
2312 if (!insertJump(nextStopIndex, itStart, errorMsg)) {
2313 return false;
2314 };
2315 }
2316 return replaceRouteEdges(newEdges, routeCost, savings, info, !hasDeparted(), false, false, &errorMsg);
2317}
2318
2319
2320bool
2321MSBaseVehicle::insertJump(int nextStopIndex, MSRouteIterator itStart, std::string& errorMsg) {
2322 bool needJump = true;
2323 if (nextStopIndex > 0) {
2324 auto itPriorStop = myStops.begin();
2325 std::advance(itPriorStop, nextStopIndex - 1);
2326 const MSStop& priorStop = *itPriorStop;
2327 if (priorStop.pars.jump >= 0) {
2328 needJump = false;
2329 }
2330 }
2331 if (needJump) {
2332 SUMOVehicleParameter::Stop jumpStopPars;
2333 jumpStopPars.endPos = (*itStart)->getLength();
2334 jumpStopPars.speed = 1000;
2335 jumpStopPars.jump = 0;
2336 jumpStopPars.edge = (*itStart)->getID();
2338 MSLane* jumpStopLane = nullptr;
2339 for (MSLane* cand : (*itStart)->getLanes()) {
2340 if (cand->allowsVehicleClass(getVClass())) {
2341 jumpStopLane = cand;
2342 break;
2343 }
2344 }
2345 if (jumpStopLane == nullptr) {
2346 errorMsg = TL("unable to replace stop with teleporting");
2347 return false;
2348 }
2349 auto itStop = myStops.begin();
2350 std::advance(itStop, nextStopIndex);
2351 MSStop jumpStop(jumpStopPars);
2352 jumpStop.initPars(jumpStopPars);
2353 jumpStop.lane = jumpStopLane;
2354 jumpStop.edge = myRoute->end(); // will be patched in replaceRoute
2355 myStops.insert(itStop, jumpStop);
2356 if (!hasDeparted() && (int)myParameter->stops.size() > nextStopIndex) {
2357 // stops will be rebuilt from scratch so we must patch the stops in myParameter
2358 auto it = myParameter->stops.begin() + nextStopIndex;
2359 const_cast<SUMOVehicleParameter*>(myParameter)->stops.insert(it, jumpStopPars);
2360 }
2361 }
2362 return true;
2363}
2364
2365
2366bool
2367MSBaseVehicle::insertStop(int nextStopIndex, SUMOVehicleParameter::Stop stop, const std::string& info, bool teleport, std::string& errorMsg) {
2368 const int n = (int)myStops.size();
2369 if (nextStopIndex < 0 || nextStopIndex > n) {
2370 errorMsg = TLF("invalid nextStopIndex % for % remaining stops", nextStopIndex, n);
2371 return false;
2372 }
2373 if (nextStopIndex == 0 && isStopped()) {
2374 errorMsg = TL("cannot insert stop before the currently reached stop");
2375 return false;
2376 }
2378 MSLane* stopLane = MSLane::dictionary(stop.lane);
2379 MSEdge* stopEdge = &stopLane->getEdge();
2380
2381 if (!stopLane->allowsVehicleClass(getVClass(), myRoutingMode)) {
2382 errorMsg = TLF("disallowed stop lane '%'", stopLane->getID());
2383 return false;
2384 }
2385
2386 // check parking access rights
2387 if (stop.parkingarea != "") {
2389 if (pa != nullptr && !pa->accepts(this)) {
2390 errorMsg = TLF("Vehicle '%' does not have the right badge to access parkingArea '%'.", getID(), stop.parkingarea);
2391 return false;
2392 }
2393 }
2394
2395 const ConstMSEdgeVector& oldEdges = getRoute().getEdges();
2396 std::vector<MSStop> stops(myStops.begin(), myStops.end());
2397 const int junctionOffset = getLane() != nullptr && getLane()->isInternal() ? 1 : 0;
2398 MSRouteIterator itStart = nextStopIndex == 0 ? getCurrentRouteEdge() + junctionOffset : stops[nextStopIndex - 1].edge;
2399 double startPos = nextStopIndex == 0 ? getPositionOnLane() : stops[nextStopIndex - 1].pars.endPos;
2400 MSRouteIterator itEnd = nextStopIndex == n ? oldEdges.end() - 1 : stops[nextStopIndex].edge;
2401 auto endPos = nextStopIndex == n ? getArrivalPos() : stops[nextStopIndex].pars.endPos;
2403
2404 bool newDestination = nextStopIndex == n && stopEdge == oldEdges.back();
2405
2406 ConstMSEdgeVector toNewStop;
2407 if (!teleport) {
2408 router.compute(*itStart, startPos, stopEdge, stop.endPos, this, t, toNewStop, true);
2409 if (toNewStop.size() == 0) {
2410 errorMsg = TLF("no route found from edge '%' to stop edge '%'", (*itStart)->getID(), stopEdge->getID());
2411 return false;
2412 }
2413 }
2414
2415 ConstMSEdgeVector fromNewStop;
2416 if (!newDestination) {
2417 router.compute(stopEdge, stop.endPos, *itEnd, endPos, this, t, fromNewStop, true);
2418 if (fromNewStop.size() == 0) {
2419 errorMsg = TLF("no route found from stop edge '%' to edge '%'", stopEdge->getID(), (*itEnd)->getID());
2420 return false;
2421 }
2422 }
2423
2424 auto itStop = myStops.begin();
2425 std::advance(itStop, nextStopIndex);
2426 MSStop newStop(stop);
2427 newStop.initPars(stop);
2428 newStop.edge = myRoute->end(); // will be patched in replaceRoute
2429 newStop.lane = stopLane;
2431 newStop.segment = MSGlobals::gMesoNet->getSegmentForEdge(newStop.lane->getEdge(), newStop.getEndPos(*this));
2432 if (newStop.lane->isInternal()) {
2433 errorMsg = TLF("Mesoscopic simulation does not allow stopping on internal edge '%' for vehicle '%'.", stop.edge, getID());
2434 return false;
2435 }
2436 }
2437 myStops.insert(itStop, newStop);
2438
2439 ConstMSEdgeVector oldRemainingEdges(myCurrEdge, getRoute().end());
2440 ConstMSEdgeVector newEdges; // only remaining
2441 newEdges.insert(newEdges.end(), myCurrEdge, itStart);
2442 if (!teleport) {
2443 newEdges.insert(newEdges.end(), toNewStop.begin(), toNewStop.end() - 1);
2444 } else {
2445 newEdges.push_back(*itStart);
2446 }
2447 if (!newDestination) {
2448 newEdges.insert(newEdges.end(), fromNewStop.begin(), fromNewStop.end() - 1);
2449 newEdges.insert(newEdges.end(), itEnd, oldEdges.end());
2450 } else {
2451 newEdges.push_back(stopEdge);
2452 }
2453 //std::cout << SIMTIME << " insertStop veh=" << getID()
2454 // << " teleport=" << teleport
2455 // << " busStop=" << stop.busstop
2456 // << " oldEdges=" << oldRemainingEdges.size()
2457 // << " newEdges=" << newEdges.size()
2458 // << " toNewStop=" << toNewStop.size()
2459 // << " fromNewStop=" << fromNewStop.size()
2460 // << "\n";
2461
2462 const double routeCost = router.recomputeCosts(newEdges, this, t);
2463 const double previousCost = router.recomputeCosts(oldRemainingEdges, this, t);
2464 const double savings = previousCost - routeCost;
2465
2466 if (!hasDeparted() && (int)myParameter->stops.size() >= nextStopIndex) {
2467 // stops will be rebuilt from scratch so we must patch the stops in myParameter
2468 auto it = myParameter->stops.begin() + nextStopIndex;
2469 const_cast<SUMOVehicleParameter*>(myParameter)->stops.insert(it, stop);
2470 }
2471 return replaceRouteEdges(newEdges, routeCost, savings, info, !hasDeparted(), false, false, &errorMsg);
2472}
2473
2474
2475double
2477 if (static_cast<MSDevice_Battery*>(getDevice(typeid(MSDevice_Battery))) != 0) {
2478 MSDevice_Battery* batteryOfVehicle = dynamic_cast<MSDevice_Battery*>(getDevice(typeid(MSDevice_Battery)));
2479 return batteryOfVehicle->getActualBatteryCapacity();
2480 } else {
2481 if (static_cast<MSDevice_ElecHybrid*>(getDevice(typeid(MSDevice_ElecHybrid))) != 0) {
2482 MSDevice_ElecHybrid* batteryOfVehicle = dynamic_cast<MSDevice_ElecHybrid*>(getDevice(typeid(MSDevice_ElecHybrid)));
2483 return batteryOfVehicle->getActualBatteryCapacity();
2484 }
2485 }
2486 return -1;
2487}
2488
2489
2490double
2492 if (static_cast<MSDevice_Battery*>(getDevice(typeid(MSDevice_Battery))) != 0) {
2493 MSDevice_Battery* batteryOfVehicle = dynamic_cast<MSDevice_Battery*>(getDevice(typeid(MSDevice_Battery)));
2494 return batteryOfVehicle->getActualBatteryCapacity() / batteryOfVehicle->getMaximumBatteryCapacity();
2495 } else {
2496 if (static_cast<MSDevice_ElecHybrid*>(getDevice(typeid(MSDevice_ElecHybrid))) != 0) {
2497 MSDevice_ElecHybrid* batteryOfVehicle = dynamic_cast<MSDevice_ElecHybrid*>(getDevice(typeid(MSDevice_ElecHybrid)));
2498 return batteryOfVehicle->getActualBatteryCapacity() / batteryOfVehicle->getMaximumBatteryCapacity();
2499 }
2500 }
2501 return -1;
2502}
2503
2504
2505double
2507 if (static_cast<MSDevice_Battery*>(getDevice(typeid(MSDevice_Battery))) != 0) {
2508 MSDevice_Battery* batteryOfVehicle = dynamic_cast<MSDevice_Battery*>(getDevice(typeid(MSDevice_Battery)));
2509 return batteryOfVehicle->getEnergyCharged();
2510 } else {
2511 if (static_cast<MSDevice_ElecHybrid*>(getDevice(typeid(MSDevice_ElecHybrid))) != 0) {
2512 MSDevice_ElecHybrid* batteryOfVehicle = dynamic_cast<MSDevice_ElecHybrid*>(getDevice(typeid(MSDevice_ElecHybrid)));
2513 return batteryOfVehicle->getEnergyCharged();
2514 }
2515 }
2516 return -1;
2517}
2518
2519
2520double
2522 if (static_cast<MSDevice_Battery*>(getDevice(typeid(MSDevice_Battery))) != 0) {
2523 MSDevice_Battery* batteryOfVehicle = dynamic_cast<MSDevice_Battery*>(getDevice(typeid(MSDevice_Battery)));
2524 return batteryOfVehicle->getMaximumChargeRate();
2525 }
2526 return -1;
2527}
2528
2529
2530double
2532 if (static_cast<MSDevice_ElecHybrid*>(getDevice(typeid(MSDevice_ElecHybrid))) != 0) {
2533 MSDevice_ElecHybrid* elecHybridDevice = dynamic_cast<MSDevice_ElecHybrid*>(getDevice(typeid(MSDevice_ElecHybrid)));
2534 return elecHybridDevice->getCurrentFromOverheadWire();
2535 }
2536
2537 return NAN;
2538}
2539
2540double
2542 if (isOnRoad() || isIdling()) {
2544 } else {
2545 return 0.;
2546 }
2547}
2548
2549
2554
2555
2560
2561
2564 if (myEdgeWeights == nullptr) {
2566 }
2567 return *myEdgeWeights;
2568}
2569
2570
2571
2572
2573int
2575 int boarded = myPersonDevice == nullptr ? 0 : myPersonDevice->size();
2576 return boarded + myParameter->personNumber;
2577}
2578
2579int
2581 int leavingPersonNumber = 0;
2582 const std::vector<MSTransportable*>& persons = getPersons();
2583 for (std::vector<MSTransportable*>::const_iterator it_p = persons.begin(); it_p != persons.end(); ++it_p) {
2584 MSStageDriving* const stage = dynamic_cast<MSStageDriving*>((*it_p)->getCurrentStage());
2585 const MSStop* stop = &myStops.front();
2586 const MSVehicle* joinVeh = dynamic_cast<MSVehicle*>(MSNet::getInstance()->getVehicleControl().getVehicle((*stop).pars.join));
2587 if (stop && stage->canLeaveVehicle(*it_p, *this, *stop) && !MSDevice_Transportable::willTransferAtJoin(*it_p, joinVeh)) {
2588 leavingPersonNumber++;
2589 }
2590 }
2591 return leavingPersonNumber;
2592}
2593
2594std::vector<std::string>
2596 std::vector<std::string> ret;
2597 const std::vector<MSTransportable*>& persons = getPersons();
2598 for (std::vector<MSTransportable*>::const_iterator it_p = persons.begin(); it_p != persons.end(); ++it_p) {
2599 ret.push_back((*it_p)->getID());
2600 }
2601 return ret;
2602}
2603
2604int
2606 int loaded = myContainerDevice == nullptr ? 0 : myContainerDevice->size();
2607 return loaded + myParameter->containerNumber;
2608}
2609
2610
2611void
2613 // this might be called from the MSTransportable destructor so we cannot do a dynamic cast to determine the type
2614 if (myPersonDevice != nullptr) {
2616 }
2617 if (myContainerDevice != nullptr) {
2619 }
2620 if (myEnergyParams != nullptr) {
2622 }
2623}
2624
2625
2626void
2632
2633
2634const std::vector<MSTransportable*>&
2636 if (myPersonDevice == nullptr) {
2638 } else {
2640 }
2641}
2642
2643
2644const std::vector<MSTransportable*>&
2646 if (myContainerDevice == nullptr) {
2648 } else {
2650 }
2651}
2652
2653
2654bool
2655MSBaseVehicle::isLineStop(double position) const {
2656 if (myParameter->line == "") {
2657 // not a public transport line
2658 return false;
2659 }
2660 for (const SUMOVehicleParameter::Stop& stop : myParameter->stops) {
2661 if (stop.startPos <= position && position <= stop.endPos) {
2662 return true;
2663 }
2664 }
2665 for (const SUMOVehicleParameter::Stop& stop : myRoute->getStops()) {
2666 if (stop.startPos <= position && position <= stop.endPos) {
2667 return true;
2668 }
2669 }
2670 return false;
2671}
2672
2673
2674bool
2675MSBaseVehicle::hasDevice(const std::string& deviceName) const {
2676 for (MSDevice* const dev : myDevices) {
2677 if (dev->deviceName() == deviceName) {
2678 return true;
2679 }
2680 }
2681 return false;
2682}
2683
2684
2685void
2686MSBaseVehicle::createDevice(const std::string& deviceName) {
2687 if (!hasDevice(deviceName)) {
2688 if (deviceName == "rerouting") {
2689 ((SUMOVehicleParameter*)myParameter)->setParameter("has." + deviceName + ".device", "true");
2691 if (hasDeparted()) {
2692 // vehicle already departed: disable pre-insertion rerouting and enable regular routing behavior
2693 MSDevice_Routing* routingDevice = static_cast<MSDevice_Routing*>(getDevice(typeid(MSDevice_Routing)));
2694 assert(routingDevice != 0);
2696 }
2697 } else {
2698 throw InvalidArgument(TLF("creating device of type '%' is not supported", deviceName));
2699 }
2700 }
2701}
2702
2703
2704std::string
2705MSBaseVehicle::getDeviceParameter(const std::string& deviceName, const std::string& key) const {
2706 for (MSVehicleDevice* const dev : myDevices) {
2707 if (dev->deviceName() == deviceName) {
2708 return dev->getParameter(key);
2709 }
2710 }
2711 throw InvalidArgument(TLF("no device of type '%' exists", deviceName));
2712}
2713
2714
2715void
2716MSBaseVehicle::setDeviceParameter(const std::string& deviceName, const std::string& key, const std::string& value) {
2717 for (MSVehicleDevice* const dev : myDevices) {
2718 if (dev->deviceName() == deviceName) {
2719 dev->setParameter(key, value);
2720 return;
2721 }
2722 }
2723 throw InvalidArgument(TLF("no device of type '%' exists", deviceName));
2724}
2725
2726
2727void
2728MSBaseVehicle::setJunctionModelParameter(const std::string& key, const std::string& value) {
2731 const_cast<SUMOVehicleParameter&>(getParameter()).setParameter(key, value);
2732 // checked in MSLink::ignoreFoe
2733 } else {
2734 throw InvalidArgument(TLF("Vehicle '%' does not support junctionModel parameter '%'.", getID(), key));
2735 }
2736}
2737
2738
2739void
2740MSBaseVehicle::setCarFollowModelParameter(const std::string& key, const std::string& value) {
2741 // handle some generic params first and then delegate to the carFollowModel itself
2744 const_cast<SUMOVehicleParameter&>(getParameter()).setParameter(key, value);
2745 // checked in MSVehicle::planMove
2746 } else {
2747 MSVehicle* microVeh = dynamic_cast<MSVehicle*>(this);
2748 if (microVeh) {
2749 // remove 'carFollowModel.' prefix
2750 const std::string attrName = key.substr(15);
2751 microVeh->getCarFollowModel().setParameter(microVeh, attrName, value);
2752 }
2753 }
2754}
2755
2756
2757void
2759 /* Design idea for additional junction model parameters:
2760 We can distinguish between 3 levels of parameters
2761 1. typically shared by multiple vehicles -> vType parameter
2762 2. specific to one vehicle but stays constant throughout the simulation -> vehicle parameter
2763 3. specific to one vehicle and expected to change during simulation -> prefixed generic vehicle parameter
2764 */
2765 for (auto item : getParameter().getParametersMap()) {
2766 if (StringUtils::startsWith(item.first, "junctionModel.")) {
2767 setJunctionModelParameter(item.first, item.second);
2768 } else if (StringUtils::startsWith(item.first, "carFollowModel.")) {
2769 setCarFollowModelParameter(item.first, item.second);
2770 }
2771 }
2772 const std::string routingModeStr = getStringParam("device.rerouting.mode");
2773 try {
2774 int routingMode = StringUtils::toInt(routingModeStr);
2775 if (routingMode != libsumo::ROUTING_MODE_DEFAULT) {
2776 setRoutingMode(routingMode);
2777 }
2778 } catch (NumberFormatException&) {
2779 // @todo interpret symbolic constants
2780 throw ProcessError(TLF("could not interpret routing.mode '%'", routingModeStr));
2781 }
2782}
2783
2784
2793
2794
2795void
2797 assert(type != nullptr);
2798 // save old parameters before possible type deletion
2799 const double oldMu = myType->getSpeedFactor().getParameter(0);
2800 const double oldDev = myType->getSpeedFactor().getParameter(1);
2801 if (myType->isVehicleSpecific() && type != myType) {
2803 }
2804 // adapt myChosenSpeedFactor to the new type
2805 if (oldDev == 0.) {
2806 // old type had speedDev 0, reroll
2808 } else {
2809 // map old speedFactor onto new distribution
2810 const double distPoint = (myChosenSpeedFactor - oldMu) / oldDev;
2811 const double newMu = type->getSpeedFactor().getParameter(0);
2812 const double newDev = type->getSpeedFactor().getParameter(1);
2813 myChosenSpeedFactor = newMu + distPoint * newDev;
2814 // respect distribution limits
2817 }
2818 myType = type;
2819 if (myEnergyParams != nullptr) {
2821 }
2822}
2823
2824
2827 if (myType->isVehicleSpecific()) {
2828 return *const_cast<MSVehicleType*>(myType);
2829 }
2830 MSVehicleType* type = myType->buildSingularType(myType->getID() + "@" + getID());
2831 replaceVehicleType(type);
2832 return *type;
2833}
2834
2835
2836int
2838 const MSLane* const lane = getLane();
2839 if (lane == nullptr) {
2840 return getEdge()->getLanes()[0]->getRNGIndex();
2841 } else {
2842 return lane->getRNGIndex();
2843 }
2844}
2845
2846
2847SumoRNG*
2849 const MSLane* lane = getLane();
2850 if (lane == nullptr) {
2851 return getEdge()->getLanes()[0]->getRNG();
2852 } else {
2853 return lane->getRNG();
2854 }
2855}
2856
2857std::string
2858MSBaseVehicle::getPrefixedParameter(const std::string& key, std::string& error) const {
2859 const MSVehicle* microVeh = dynamic_cast<const MSVehicle*>(this);
2860 if (StringUtils::startsWith(key, "device.")) {
2861 StringTokenizer tok(key, ".");
2862 if (tok.size() < 3) {
2863 error = TLF("Invalid device parameter '%' for vehicle '%'.", key, getID());
2864 return "";
2865 }
2866 try {
2867 return getDeviceParameter(tok.get(1), key.substr(tok.get(0).size() + tok.get(1).size() + 2));
2868 } catch (InvalidArgument& e) {
2869 error = TLF("Vehicle '%' does not support device parameter '%' (%).", getID(), key, e.what());
2870 return "";
2871 }
2872 } else if (StringUtils::startsWith(key, "laneChangeModel.")) {
2873 if (microVeh == nullptr) {
2874 error = TLF("Mesoscopic vehicle '%' does not support laneChangeModel parameters.", getID());
2875 return "";
2876 }
2877 const std::string attrName = key.substr(16);
2878 try {
2879 return microVeh->getLaneChangeModel().getParameter(attrName);
2880 } catch (InvalidArgument& e) {
2881 error = TLF("Vehicle '%' does not support laneChangeModel parameter '%' (%).", getID(), key, e.what());
2882 return "";
2883 }
2884 } else if (StringUtils::startsWith(key, "carFollowModel.")) {
2885 if (microVeh == nullptr) {
2886 error = TLF("Mesoscopic vehicle '%' does not support carFollowModel parameters.", getID());
2887 return "";
2888 }
2889 const std::string attrName = key.substr(15);
2890 try {
2891 return microVeh->getCarFollowModel().getParameter(microVeh, attrName);
2892 } catch (InvalidArgument& e) {
2893 error = TLF("Vehicle '%' does not support carFollowModel parameter '%' (%).", getID(), key, e.what());
2894 return "";
2895 }
2896 } else if (StringUtils::startsWith(key, "has.") && StringUtils::endsWith(key, ".device")) {
2897 StringTokenizer tok(key, ".");
2898 if (tok.size() != 3) {
2899 error = TL("Invalid check for device. Expected format is 'has.DEVICENAME.device'.");
2900 return "";
2901 }
2902 return hasDevice(tok.get(1)) ? "true" : "false";
2903 // parking related parameters start here
2904 } else if (key == "parking.rerouteCount") {
2906 } else if (StringUtils::startsWith(key, "parking.memory.")) {
2907 std::vector<std::string> values;
2908 if (getParkingMemory()) {
2909 if (key == "parking.memory.IDList") {
2910 for (const auto& item : *getParkingMemory()) {
2911 values.push_back(item.first->getID());
2912 }
2913 } else if (key == "parking.memory.score") {
2914 for (const auto& item : *getParkingMemory()) {
2915 values.push_back(item.second.score);
2916 }
2917 } else if (key == "parking.memory.blockedAtTime") {
2918 for (const auto& item : *getParkingMemory()) {
2919 values.push_back(toString(STEPS2TIME(item.second.blockedAtTime)));
2920 }
2921 } else if (key == "parking.memory.blockedAtTimeLocal") {
2922 for (const auto& item : *getParkingMemory()) {
2923 values.push_back(toString(STEPS2TIME(item.second.blockedAtTimeLocal)));
2924 }
2925 } else {
2926 error = TLF("Unsupported parking parameter '%' for vehicle '%'.", key, getID());
2927 }
2928 }
2929 return toString(values);
2930 } else {
2931 // default: custom user parameter
2932 return getParameter().getParameter(key, "");
2933 }
2934}
2935
2936
2937void
2944
2945
2946void
2952
2953
2954void
2956 if (myChargingMemory == nullptr) {
2958 }
2960}
2961
2962
2963void
2969
2970
2971void
2972MSBaseVehicle::rememberParkingAreaScore(const MSStoppingPlace* pa, const std::string& score) {
2973 if (myParkingMemory == nullptr) {
2975 }
2977}
2978
2979
2982 if (myParkingMemory == nullptr) {
2983 return -1;
2984 }
2985 return myParkingMemory->sawBlockedStoppingPlace(pa, local);
2986}
2987
2988
2995
2996
2999 if (myChargingMemory == nullptr) {
3000 return -1;
3001 }
3002 return myChargingMemory->sawBlockedStoppingPlace(cs, local);
3003}
3004
3005
3006#ifdef _DEBUG
3007void
3008MSBaseVehicle::initMoveReminderOutput(const OptionsCont& oc) {
3009 if (oc.isSet("movereminder-output.vehicles")) {
3010 const std::vector<std::string> vehicles = oc.getStringVector("movereminder-output.vehicles");
3011 myShallTraceMoveReminders.insert(vehicles.begin(), vehicles.end());
3012 }
3013}
3014
3015
3016void
3017MSBaseVehicle::traceMoveReminder(const std::string& type, MSMoveReminder* rem, double pos, bool keep) const {
3018 OutputDevice& od = OutputDevice::getDeviceByOption("movereminder-output");
3019 od.openTag("movereminder");
3020 od.writeAttr(SUMO_ATTR_TIME, STEPS2TIME(MSNet::getInstance()->getCurrentTimeStep()));
3021 od.writeAttr("veh", getID());
3023 od.writeAttr("type", type);
3024 od.writeAttr("pos", toString(pos));
3025 od.writeAttr("keep", toString(keep));
3026 od.closeTag();
3027}
3028#endif
3029
3030
3031/****************************************************************************/
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 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)
ConstMSEdgeVector routeAlongStops(SUMOTime t, SUMOAbstractRouter< MSEdge, SUMOVehicle > &router, std::vector< StopEdgeInfo > &stops, ConstMSEdgeVector edges, int originStop, SUMOTime maxDelay, double &skippedPrio2) const
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)
ConstMSEdgeVector optimizeSkipped(SUMOTime t, SUMOAbstractRouter< MSEdge, SUMOVehicle > &router, const MSEdge *source, double sourcePos, std::vector< StopEdgeInfo > &stops, ConstMSEdgeVector edges, SUMOTime maxDelay) const
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
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)
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
bool hasTransientPermissions() const
Definition MSEdge.cpp:1681
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:1350
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:482
bool isNormal() const
return whether this edge is an internal edge
Definition MSEdge.h:263
double getLength() const
return the length of the edge
Definition MSEdge.h:693
bool isTazConnector() const
Definition MSEdge.h:291
int getNumLanes() const
Definition MSEdge.h:172
bool isInternal() const
return whether this edge is an internal edge
Definition MSEdge.h:268
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:1057
const MSEdge * getNormalBefore() const
if this edge is an internal edge, return its first normal predecessor, otherwise the edge itself
Definition MSEdge.cpp:947
MSLane * getFirstAllowed(SUMOVehicleClass vClass, bool defaultFirst=false) const
Definition MSEdge.cpp:735
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:2466
double getLength() const
Returns the lane's length.
Definition MSLane.h:611
bool allowsVehicleClass(SUMOVehicleClass vclass) const
Definition MSLane.h:930
static bool dictionary(const std::string &id, MSLane *lane)
Static (sic!) container methods {.
Definition MSLane.cpp:2490
bool isInternal() const
Definition MSLane.cpp:2621
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:1720
@ NEWROUTE
The vehicle got a new route.
static MSNet * getInstance()
Returns the pointer to the unique instance of MSNet (singleton).
Definition MSNet.cpp:186
MSEventControl * getBeginOfTimestepEvents()
Returns the event control for events executed at the begin of a time step.
Definition MSNet.h:485
MSVehicleRouter & getRouterTT(int rngIndex, const Prohibitions &prohibited={}) const
Definition MSNet.cpp:1580
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:1453
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:1335
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:125
void setCosts(double costs)
Sets the costs of the route.
Definition MSRoute.h:206
static bool hasRoute(const std::string &id)
returns whether a route with the given id exists
Definition MSRoute.cpp:152
static bool dictionary(const std::string &id, ConstMSRoutePtr route)
Adds a route to the dictionary.
Definition MSRoute.cpp:109
static void checkDist(const std::string &id)
Checks the distribution whether it is permanent and deletes it if not.
Definition MSRoute.cpp:187
void setSavings(double savings)
Sets the savings of the route.
Definition MSRoute.h:213
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
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:112
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:35
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
std::string getDescription() const
get a short description for showing in the gui
Definition MSStop.cpp:69
SUMOTime getUntil() const
return until / ended time
Definition MSStop.cpp:151
SUMOTime getArrival() const
return arrival / started time
Definition MSStop.cpp:157
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
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
Whether it is a person.
const MSVehicleType & getVehicleType() const
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
static double rand(SumoRNG *rng=nullptr)
Returns a random real number in [0, 1)
bool computeLooped(const E *from, const E *to, const V *const vehicle, SUMOTime msTime, std::vector< const E * > &into, bool silent=false)
Builds the route between the given edges using the minimum effort at the given time if from == to,...
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.
std::vector< std::string > via
List of the via-edges the vehicle must visit.
int repetitionsDone
The number of times the vehicle was already inserted.
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