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-2024 German Aerospace Center (DLR) and others.
4// This program and the accompanying materials are made available under the
5// terms of the Eclipse Public License 2.0 which is available at
6// https://www.eclipse.org/legal/epl-2.0/
7// This Source Code may also be made available under the following Secondary
8// Licenses when the conditions for such availability set forth in the Eclipse
9// Public License 2.0 are satisfied: GNU General Public License, version 2
10// or later which is available at
11// https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
12// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
13/****************************************************************************/
21// A base class for vehicle implementations
22/****************************************************************************/
23#include <config.h>
24
25#include <iostream>
26#include <cassert>
34#include <mesosim/MELoop.h>
35#include <mesosim/MEVehicle.h>
49#include "MSGlobals.h"
50#include "MSVehicleControl.h"
51#include "MSVehicleType.h"
52#include "MSEdge.h"
53#include "MSLane.h"
54#include "MSMoveReminder.h"
56#include "MSNet.h"
57#include "MSStop.h"
58#include "MSParkingArea.h"
59#include "MSInsertionControl.h"
60#include "MSBaseVehicle.h"
61
62//#define DEBUG_REROUTE
63//#define DEBUG_ADD_STOP
64//#define DEBUG_COND (getID() == "")
65//#define DEBUG_COND (true)
66//#define DEBUG_REPLACE_ROUTE
67#define DEBUG_COND (isSelected())
68
69// ===========================================================================
70// static members
71// ===========================================================================
73std::vector<MSTransportable*> MSBaseVehicle::myEmptyTransportableVector;
74#ifdef _DEBUG
75std::set<std::string> MSBaseVehicle::myShallTraceMoveReminders;
76#endif
78
79// ===========================================================================
80// Influencer method definitions
81// ===========================================================================
82
85
86// ===========================================================================
87// method definitions
88// ===========================================================================
89
90double
92 throw ProcessError("getPreviousSpeed() is not available for non-MSVehicles.");
93}
94
95
97 MSVehicleType* type, const double speedFactor) :
98 SUMOVehicle(pars->id),
99 myParameter(pars),
100 myRoute(route),
101 myType(type),
102 myCurrEdge(route->begin()),
103 myChosenSpeedFactor(pars->speedFactor < 0 ? speedFactor : pars->speedFactor),
105 myPersonDevice(nullptr),
106 myContainerDevice(nullptr),
107 myEnergyParams(nullptr),
109 myDepartPos(-1),
110 myArrivalPos(-1),
111 myArrivalLane(-1),
114 myOdometer(0.),
116 myRoutingMode(libsumo::ROUTING_MODE_DEFAULT),
118 myEdgeWeights(nullptr)
119#ifdef _DEBUG
120 , myTraceMoveReminders(myShallTraceMoveReminders.count(pars->id) > 0)
121#endif
122{
123 if ((*myRoute->begin())->isTazConnector() || myRoute->getLastEdge()->isTazConnector()) {
125 }
126 if ((pars->parametersSet & VEHPARS_FORCE_REROUTE) == 0) {
128 }
129 if (!pars->wasSet(VEHPARS_FORCE_REROUTE)) {
131 }
133}
134
135
137 delete myEdgeWeights;
138 if (myParameter->repetitionNumber == -1) {
139 // this is not a flow (flows call checkDist in MSInsertionControl::determineCandidates)
141 }
142 for (MSVehicleDevice* dev : myDevices) {
143 delete dev;
144 }
145 delete myEnergyParams;
146 delete myParkingMemory;
147 delete myChargingMemory;
149 delete myParameter;
150}
151
152
153void
155 // the check for an instance is needed for the unit tests which do not construct a network
156 // TODO Optimize for speed and there should be a better way to check whether a vehicle is part of a flow
157 if (MSNet::hasInstance() && !MSNet::getInstance()->hasFlow(getFlowID())) {
158 myRoute->checkRemoval();
159 }
160}
161
162
163std::string
165 return getID().substr(0, getID().rfind('.'));
166}
167
168
169void
172 for (MSVehicleDevice* dev : myDevices) {
173 myMoveReminders.push_back(std::make_pair(dev, 0.));
174 }
176 // ensure we have the emission parameters even if we don't have the device
178 }
179}
180
181
182void
183MSBaseVehicle::setID(const std::string& /*newID*/) {
184 throw ProcessError(TL("Changing a vehicle ID is not permitted"));
185}
186
189 return *myParameter;
190}
191
192
193void
195 delete myParameter;
196 myParameter = newParameter;
197}
198
199
200bool
204
205double
209
210
211const MSEdge*
212MSBaseVehicle::succEdge(int nSuccs) const {
213 if (myCurrEdge + nSuccs < myRoute->end() && std::distance(myCurrEdge, myRoute->begin()) <= nSuccs) {
214 return *(myCurrEdge + nSuccs);
215 } else {
216 return nullptr;
217 }
218}
219
220
221const MSEdge*
223 return *myCurrEdge;
224}
225
226
227const std::set<SUMOTrafficObject::NumericalID>
229 std::set<SUMOTrafficObject::NumericalID> result;
230 for (auto e = myCurrEdge; e != myRoute->end(); ++e) {
231 result.insert((*e)->getNumericalID());
232 }
233 return result;
234}
235
236
237bool
239 if (stop == nullptr) {
240 return false;
241 }
242 for (const MSStop& s : myStops) {
243 if (s.busstop == stop
244 || s.containerstop == stop
245 || s.parkingarea == stop
246 || s.chargingStation == stop) {
247 return true;
248 }
249 }
250 return false;
251}
252
253bool
255 for (const MSStop& s : myStops) {
256 if (&s.lane->getEdge() == edge) {
257 return true;
258 }
259 }
260 return myRoute->getLastEdge() == edge;
261}
262
263
264bool
265MSBaseVehicle::reroute(SUMOTime t, const std::string& info, SUMOAbstractRouter<MSEdge, SUMOVehicle>& router, const bool onInit, const bool withTaz, const bool silent, const MSEdge* sink) {
266 // check whether to reroute
267 const MSEdge* source = withTaz && onInit ? MSEdge::dictionary(myParameter->fromTaz + "-source") : *getRerouteOrigin();
268 if (source == nullptr) {
269 source = *getRerouteOrigin();
270 }
271 if (sink == nullptr) {
272 sink = withTaz ? MSEdge::dictionary(myParameter->toTaz + "-sink") : myRoute->getLastEdge();
273 if (sink == nullptr) {
274 sink = myRoute->getLastEdge();
275 }
276 }
277 ConstMSEdgeVector oldEdgesRemaining(source == *myCurrEdge ? myCurrEdge : myCurrEdge + 1, myRoute->end());
278 ConstMSEdgeVector edges;
279 ConstMSEdgeVector stops;
280 std::set<int> jumps;
281 bool stopAtSink = false;
282 if (myParameter->via.size() == 0) {
283 double firstPos = INVALID_DOUBLE;
284 double lastPos = INVALID_DOUBLE;
285 stops = getStopEdges(firstPos, lastPos, jumps);
286 if (stops.size() > 0) {
287 double sourcePos = onInit ? 0 : getPositionOnLane();
289 sourcePos = getNextStop().pars.endPos;
290 }
291 // avoid superfluous waypoints for first and last edge
292 const bool skipFirst = stops.front() == source && (source != getEdge() || sourcePos + getBrakeGap() <= firstPos + NUMERICAL_EPS);
293 const bool skipLast = (stops.back() == sink
294 && myArrivalPos >= lastPos
295 && (stops.size() < 2 || stops.back() != stops[stops.size() - 2])
296 && (stops.size() > 1 || skipFirst));
297#ifdef DEBUG_REROUTE
298 if (DEBUG_COND) {
299 std::cout << SIMTIME << " reroute " << info << " veh=" << getID() << " lane=" << Named::getIDSecure(getLane())
300 << " source=" << source->getID() << " sourcePos=" << sourcePos << " firstPos=" << firstPos << " arrivalPos=" << myArrivalPos << " lastPos=" << lastPos
301 << " route=" << toString(myRoute->getEdges()) << " stopEdges=" << toString(stops) << " skipFirst=" << skipFirst << " skipLast=" << skipLast << "\n";
302 }
303#endif
304 if (stops.size() == 1 && (skipFirst || skipLast)) {
305 stops.clear();
306 } else {
307 if (skipFirst) {
308 stops.erase(stops.begin());
309 }
310 if (skipLast) {
311 stops.erase(stops.end() - 1);
312 }
313 }
314 stopAtSink = stops.size() > 0 && stops.back() == sink && jumps.size() == 0;
315 }
316 } else {
317 std::set<const MSEdge*> jumpEdges;
318 for (const MSStop& stop : myStops) {
319 if (stop.pars.jump >= 0) {
320 jumpEdges.insert(*stop.edge);
321 }
322 }
323 // via takes precedence over stop edges
324 // there is a consistency check in MSRouteHandler::addStop that warns when a stop edge is not part of the via edges
325 for (std::vector<std::string>::const_iterator it = myParameter->via.begin(); it != myParameter->via.end(); ++it) {
326 MSEdge* viaEdge = MSEdge::dictionary(*it);
327 if ((viaEdge == source && it == myParameter->via.begin()) || (viaEdge == sink && myParameter->via.end() - it == 1)) {
328 continue;
329 }
330 assert(viaEdge != 0);
331 if (!viaEdge->isTazConnector() && viaEdge->allowedLanes(getVClass()) == nullptr) {
332 throw ProcessError(TLF("Vehicle '%' is not allowed on any lane of via edge '%'.", getID(), viaEdge->getID()));
333 }
334 stops.push_back(viaEdge);
335 if (jumpEdges.count(viaEdge) != 0) {
336 jumps.insert((int)stops.size());
337 }
338 }
339 }
340
341 int stopIndex = -1;
342 for (const MSEdge* const stopEdge : stops) {
343 stopIndex++;
344 // !!! need to adapt t here
346 if (jumps.count(stopIndex) != 0) {
347 edges.push_back(source);
348 source = stopEdge;
349 continue;
350 }
351 router.computeLooped(source, stopEdge, this, t, into, silent);
352 //std::cout << SIMTIME << " reroute veh=" << getID() << " source=" << source->getID() << " target=" << (*s)->getID() << " edges=" << toString(into) << "\n";
353 if (into.size() > 0) {
354 into.pop_back();
355 edges.insert(edges.end(), into.begin(), into.end());
356 if (stopEdge->isTazConnector()) {
357 source = into.back();
358 edges.pop_back();
359 } else {
360 source = stopEdge;
361 }
362 } else {
363 if ((source != sink || !stopAtSink)) {
364 std::string error = TLF("Vehicle '%' has no valid route from edge '%' to stop edge '%'.", getID(), source->getID(), stopEdge->getID());
365 if (MSGlobals::gCheckRoutes || silent) {
366 throw ProcessError(error);
367 } else {
368 WRITE_WARNING(error);
369 edges.push_back(source);
370 }
371 }
372 source = stopEdge;
373 }
374 }
375 if (stops.empty() && source == sink && onInit
379 router.computeLooped(source, sink, this, t, edges, silent);
380 } else {
381 if (!router.compute(source, sink, this, t, edges, silent)) {
382 edges.clear();
383 }
384 }
385
386 // router.setHint(myCurrEdge, myRoute->end(), this, t);
387 if (edges.empty() && silent) {
388 return false;
389 }
390 if (!edges.empty() && edges.front()->isTazConnector()) {
391 edges.erase(edges.begin());
392 }
393 if (!edges.empty() && edges.back()->isTazConnector()) {
394 edges.pop_back();
395 }
396 const double routeCost = router.recomputeCosts(edges, this, t);
397 const double previousCost = onInit ? routeCost : router.recomputeCosts(oldEdgesRemaining, this, t);
398 const double savings = previousCost - routeCost;
399 //if (getID() == "43") std::cout << SIMTIME << " pCost=" << previousCost << " cost=" << routeCost
400 // << " onInit=" << onInit
401 // << " prevEdges=" << toString(oldEdgesRemaining)
402 // << " newEdges=" << toString(edges)
403 // << "\n";
404 replaceRouteEdges(edges, routeCost, savings, info, onInit);
405 // this must be called even if the route could not be replaced
406 if (onInit) {
407 if (edges.empty()) {
409 throw ProcessError(TLF("Vehicle '%' has no valid route.", getID()));
410 } else if (source->isTazConnector()) {
411 WRITE_WARNINGF(TL("Removing vehicle '%' which has no valid route."), getID());
413 return false;
414 }
415 }
418 }
419 return !edges.empty();
420}
421
422
423bool
424MSBaseVehicle::replaceRouteEdges(ConstMSEdgeVector& edges, double cost, double savings, const std::string& info, bool onInit, bool check, bool removeStops, std::string* msgReturn) {
425 if (edges.empty()) {
426 WRITE_WARNINGF(TL("No route for vehicle '%' found."), getID());
427 if (msgReturn != nullptr) {
428 *msgReturn = "No route found";
429 }
430 return false;
431 }
432 // build a new id, first
433 std::string id = getID();
434 if (id[0] != '!') {
435 id = "!" + id;
436 }
437 const std::string idSuffix = id + "!var#";
438 int varIndex = 1;
439 id = idSuffix + toString(varIndex);
440 while (MSRoute::hasRoute(id)) {
441 id = idSuffix + toString(++varIndex);
442 }
443 int oldSize = (int)edges.size();
444 if (!onInit) {
445 const MSEdge* const origin = *getRerouteOrigin();
446 if (origin != *myCurrEdge && edges.front() == origin) {
447 edges.insert(edges.begin(), *myCurrEdge);
448 oldSize = (int)edges.size();
449 }
450 edges.insert(edges.begin(), myRoute->begin(), myCurrEdge);
451 }
452 if (edges == myRoute->getEdges() && haveValidStopEdges(true)) {
453 // re-assign stop iterators when rerouting to a new parkingArea / insertStop
454 return true;
455 }
456 const RGBColor& c = myRoute->getColor();
457 MSRoute* newRoute = new MSRoute(id, edges, false, &c == &RGBColor::DEFAULT_COLOR ? nullptr : new RGBColor(c), std::vector<SUMOVehicleParameter::Stop>());
458 newRoute->setCosts(cost);
459 newRoute->setSavings(savings);
460 ConstMSRoutePtr constRoute = std::shared_ptr<MSRoute>(newRoute);
461 if (!MSRoute::dictionary(id, constRoute)) {
462 delete newRoute;
463 if (msgReturn != nullptr) {
464 *msgReturn = "duplicate routeID '" + id + "'";
465 }
466 return false;
467 }
468
469 std::string msg;
470 if (check && !hasValidRoute(msg, constRoute)) {
471 WRITE_WARNINGF(TL("Invalid route replacement for vehicle '%'. %"), getID(), msg);
473 if (msgReturn != nullptr) {
474 *msgReturn = msg;
475 }
476 return false;
477 }
478 }
479 if (!replaceRoute(constRoute, info, onInit, (int)edges.size() - oldSize, false, removeStops, msgReturn)) {
480 return false;
481 }
482 return true;
483}
484
485
486bool
487MSBaseVehicle::replaceRoute(ConstMSRoutePtr newRoute, const std::string& info, bool onInit, int offset, bool addRouteStops, bool removeStops, std::string* msgReturn) {
488 const ConstMSEdgeVector& edges = newRoute->getEdges();
489 // rebuild in-vehicle route information
490 if (onInit) {
491 myCurrEdge = newRoute->begin();
492 } else {
493 MSRouteIterator newCurrEdge = std::find(edges.begin() + offset, edges.end(), *myCurrEdge);
494 if (newCurrEdge == edges.end()) {
495 if (msgReturn != nullptr) {
496 *msgReturn = TLF("current edge '%' not found in new route", (*myCurrEdge)->getID());
497 }
498#ifdef DEBUG_REPLACE_ROUTE
499 if (DEBUG_COND) {
500 std::cout << " newCurrEdge not found\n";
501 }
502#endif
503 return false;
504 }
505 if (getLane() != nullptr) {
506 if (getLane()->getEdge().isInternal() && (
507 (newCurrEdge + 1) == edges.end() || (*(newCurrEdge + 1)) != &(getLane()->getOutgoingViaLanes().front().first->getEdge()))) {
508 if (msgReturn != nullptr) {
509 *msgReturn = TL("Vehicle is on junction-internal edge leading elsewhere");
510 }
511#ifdef DEBUG_REPLACE_ROUTE
512 if (DEBUG_COND) {
513 std::cout << " Vehicle is on junction-internal edge leading elsewhere\n";
514 }
515#endif
516 return false;
517 } else if (getPositionOnLane() > getLane()->getLength()
518 && (myCurrEdge + 1) != myRoute->end()
519 && (newCurrEdge + 1) != edges.end()
520 && *(myCurrEdge + 1) != *(newCurrEdge + 1)) {
521 if (msgReturn != nullptr) {
522 *msgReturn = TL("Vehicle is moving past junction and committed to move to another successor edge");
523 }
524#ifdef DEBUG_REPLACE_ROUTE
525 if (DEBUG_COND) {
526 std::cout << " Vehicle is moving past junction and committed to move to another successor edge\n";
527 }
528#endif
529 return false;
530 }
531 }
532 myCurrEdge = newCurrEdge;
533 }
534 const bool stopsFromScratch = onInit && myRoute->getStops().empty();
535 // assign new route
537 myRoute = newRoute;
538 // update arrival definition
540 // save information that the vehicle was rerouted
542 myStopUntilOffset += myRoute->getPeriod();
544#ifdef DEBUG_REPLACE_ROUTE
545 if (DEBUG_COND) {
546 std::cout << SIMTIME << " veh=" << getID() << " replaceRoute info=" << info << " on " << (*myCurrEdge)->getID()
547 << " lane=" << Named::getIDSecure(getLane())
548 << " stopsFromScratch=" << stopsFromScratch
549 << " newSize=" << newRoute->getEdges().size()
550 << " newIndex=" << (myCurrEdge - newRoute->begin())
551 << " edges=" << toString(newRoute->getEdges())
552 << "\n";
553 }
554#endif
555 // remove past stops which are not on the route anymore
556 for (std::vector<SUMOVehicleParameter::Stop>::iterator it = myPastStops.begin(); it != myPastStops.end();) {
557 const MSEdge* stopEdge = (it->edge.empty()) ? &MSLane::dictionary(it->lane)->getEdge() : MSEdge::dictionary(it->edge);
558 if (std::find(myRoute->begin(), myRoute->end(), stopEdge) == myRoute->end()) {
559 it = myPastStops.erase(it);
560 } else {
561 ++it;
562 }
563 }
564 // if we did not drive yet it may be best to simply reassign the stops from scratch
565 if (stopsFromScratch) {
566 myStops.clear();
568 } else {
569 // recheck old stops
570 MSRouteIterator searchStart = myCurrEdge;
571 double lastPos = getPositionOnLane() + getBrakeGap();
572 if (getLane() != nullptr && getLane()->isInternal()
573 && myStops.size() > 0 && !myStops.front().lane->isInternal()) {
574 // searchStart is still incoming to the intersection so lastPos
575 // relative to that edge must be adapted
576 lastPos += (*myCurrEdge)->getLength();
577 }
578 int stopIndex = 0;
579 for (std::list<MSStop>::iterator iter = myStops.begin(); iter != myStops.end();) {
580 double endPos = iter->getEndPos(*this);
581#ifdef DEBUG_REPLACE_ROUTE
582 if (DEBUG_COND) {
583 std::cout << " stopEdge=" << iter->lane->getEdge().getID() << " start=" << (searchStart - myCurrEdge) << " endPos=" << endPos << " lastPos=" << lastPos << "\n";
584 }
585#endif
586 if (*searchStart != &iter->lane->getEdge()
587 || endPos + NUMERICAL_EPS < lastPos) {
588 if (searchStart != edges.end() && !iter->reached) {
589 searchStart++;
590 }
591 }
592 lastPos = endPos;
593
594 iter->edge = std::find(searchStart, edges.end(), &iter->lane->getEdge());
595#ifdef DEBUG_REPLACE_ROUTE
596 if (DEBUG_COND) {
597 std::cout << " foundIndex=" << (iter->edge - myCurrEdge) << " end=" << (edges.end() - myCurrEdge) << "\n";
598 }
599#endif
600 if (iter->edge == edges.end()) {
601 if (!removeStops) {
602 WRITE_ERRORF(TL("Vehicle '%' could not assign stop '%' after rerouting (%) at time=%."), getID(), iter->getDescription(), info, time2string(SIMSTEP));
603 }
604 iter = myStops.erase(iter);
605 continue;
606 } else {
607 setSkips(*iter, stopIndex);
608 searchStart = iter->edge;
609 }
610 ++iter;
611 stopIndex++;
612 }
613 // add new stops
614 if (addRouteStops) {
615 for (std::vector<SUMOVehicleParameter::Stop>::const_iterator i = newRoute->getStops().begin(); i != newRoute->getStops().end(); ++i) {
616 std::string error;
618 if (error != "") {
619 WRITE_WARNING(error);
620 }
621 }
622 }
623 }
624 return true;
625}
626
627
628double
630 return 0;
631}
632
633
634void
640
641
644 const SUMOTime dep = getParameter().depart;
645 if (dep < 0) {
646 return 0;
647 }
648 return hasDeparted() ? getDeparture() - dep : SIMSTEP - dep;
649}
650
651
652bool
654 return succEdge(1) == nullptr;
655}
656
657
658int
660 return (int) std::distance(myRoute->begin(), myCurrEdge);
661}
662
663
664void
666 myCurrEdge = myRoute->begin() + index;
667 const_cast<SUMOVehicleParameter*>(myParameter)->departLaneProcedure = departLaneProcedure;
668 // !!! hack
669 myArrivalPos = (*(myRoute->end() - 1))->getLanes()[0]->getLength();
670}
671
672double
676
677bool
679 if (t->isPerson() && getPersonNumber() >= getVehicleType().getPersonCapacity()) {
680 return false;
681 } else if (!t->isPerson() && getContainerNumber() >= getVehicleType().getContainerCapacity()) {
682 return false;
683 }
684 if (isStopped() && myStops.begin()->pars.permitted.size() > 0
685 && myStops.begin()->pars.permitted.count(t->getID()) == 0) {
686 return false;
687 }
688 MSDevice_Taxi* taxiDevice = static_cast<MSDevice_Taxi*>(getDevice(typeid(MSDevice_Taxi)));
689 if (taxiDevice != nullptr) {
690 return taxiDevice->allowsBoarding(t);
691 }
692 return true;
693}
694
695
696void
698 if (transportable->isPerson()) {
699 if (myPersonDevice == nullptr) {
701 myMoveReminders.insert(myMoveReminders.begin(), std::make_pair(myPersonDevice, 0.));
704 }
705 }
706 myPersonDevice->addTransportable(transportable);
707 } else {
708 if (myContainerDevice == nullptr) {
710 myMoveReminders.insert(myMoveReminders.begin(), std::make_pair(myContainerDevice, 0.));
713 }
714 }
715 myContainerDevice->addTransportable(transportable);
716 }
717 if (myEnergyParams != nullptr) {
719 }
720}
721
722
723bool
725 for (const MSStop& stop : myStops) {
726 if (stop.edge == it && stop.pars.jump >= 0) {
727 return true;
728 } else if (stop.edge > it) {
729 return false;
730 }
731 }
732 return false;
733}
734
735
736bool
737MSBaseVehicle::hasValidRoute(std::string& msg, ConstMSRoutePtr route) const {
739 if (route == nullptr) {
740 route = myRoute;
741 } else {
742 start = route->begin();
743 }
744 const bool checkJumps = route == myRoute; // the edge iterators in the stops are invalid otherwise
745 MSRouteIterator last = route->end() - 1;
746 // check connectivity, first
747 for (MSRouteIterator e = start; e != last; ++e) {
748 const MSEdge& next = **(e + 1);
749 if ((*e)->allowedLanes(next, myType->getVehicleClass()) == nullptr) {
750 if (!checkJumps || !hasJump(e)) {
752 || (!next.hasTransientPermissions() && !(*e)->hasTransientPermissions())) {
753 msg = TLF("No connection between edge '%' and edge '%'.", (*e)->getID(), (*(e + 1))->getID());
754 return false;
755 }
756 }
757 }
758 }
759 last = route->end();
760 // check usable lanes, then
761 for (MSRouteIterator e = start; e != last; ++e) {
762 if ((*e)->prohibits(this)) {
763 msg = TLF("Edge '%' prohibits.", (*e)->getID());
764 return false;
765 }
766 }
767 return true;
768}
769
770
771bool
773 if (!(*myCurrEdge)->isTazConnector()) {
775 msg = TLF("Departure speed for vehicle '%' is too high for the vehicle type '%'.", getID(), myType->getID());
777 return false;
778 }
779 }
780 if (myRoute->getEdges().size() > 0 && !(*myCurrEdge)->prohibits(this)) {
781 myRouteValidity &= ~ROUTE_START_INVALID_PERMISSIONS;
782 return true;
783 } else {
784 msg = TLF("Vehicle '%' is not allowed to depart on any lane of edge '%'.", getID(), (*myCurrEdge)->getID());
786 return false;
787 }
788}
789
790
791int
792MSBaseVehicle::getRouteValidity(bool update, bool silent, std::string* msgReturn) {
793 if (!update) {
794 return myRouteValidity;
795 }
796 // insertion check must be done in any case
797 std::string msg;
798 if (!hasValidRouteStart(msg)) {
800 throw ProcessError(msg);
801 } else if (!silent) {
802 // vehicle will be discarded
803 WRITE_WARNING(msg);
804 } else if (msgReturn != nullptr) {
805 *msgReturn = msg;
806 }
807 }
810 // we could check after the first rerouting
812 if (!hasValidRoute(msg, myRoute)) {
814 throw ProcessError(TLF("Vehicle '%' has no valid route. %", getID(), msg));
815 }
816 }
817 myRouteValidity &= ~ROUTE_UNCHECKED;
818 return myRouteValidity;
819}
820
821void
823#ifdef _DEBUG
824 if (myTraceMoveReminders) {
825 traceMoveReminder("add", rem, 0, true);
826 }
827#endif
828 myMoveReminders.push_back(std::make_pair(rem, 0.));
829}
830
831
832void
834 for (MoveReminderCont::iterator r = myMoveReminders.begin(); r != myMoveReminders.end(); ++r) {
835 if (r->first == rem) {
836#ifdef _DEBUG
837 if (myTraceMoveReminders) {
838 traceMoveReminder("remove", rem, 0, false);
839 }
840#endif
841 myMoveReminders.erase(r);
842 return;
843 }
844 }
845}
846
847
848void
850 for (MoveReminderCont::iterator rem = myMoveReminders.begin(); rem != myMoveReminders.end();) {
851 // skip the reminder if it is a lane reminder but not for my lane (indicated by rem->second > 0.)
852 if (rem->first->getLane() != nullptr && rem->second > 0.) {
853#ifdef _DEBUG
854 if (myTraceMoveReminders) {
855 traceMoveReminder("notifyEnter_skipped", rem->first, rem->second, true);
856 }
857#endif
858 ++rem;
859 } else {
860 if (rem->first->notifyEnter(*this, reason, enteredLane)) {
861#ifdef _DEBUG
862 if (myTraceMoveReminders) {
863 traceMoveReminder("notifyEnter", rem->first, rem->second, true);
864 }
865#endif
866 ++rem;
867 } else {
868#ifdef _DEBUG
869 if (myTraceMoveReminders) {
870 traceMoveReminder("notifyEnter", rem->first, rem->second, false);
871 }
872#endif
873 rem = myMoveReminders.erase(rem);
874 }
875 }
876 }
877}
878
879
880bool
882 return isRailway(getVClass()) || isRailway(getCurrentEdge()->getPermissions());
883}
884
885void
887 if (myRoute->getLastEdge()->isTazConnector()) {
888 return;
889 }
890 const int arrivalEdgeIndex = MIN2(myParameter->arrivalEdge, (int)myRoute->getEdges().size() - 1);
891 if (arrivalEdgeIndex != myParameter->arrivalEdge) {
892 WRITE_WARNINGF(TL("Vehicle '%' ignores attribute arrivalEdge=% after rerouting at time=% (routeLength=%)"),
893 getID(), myParameter->arrivalEdge, time2string(SIMSTEP), myRoute->getEdges().size() - 1);
894 }
895 const MSEdge* arrivalEdge = myParameter->arrivalEdge >= 0 ? myRoute->getEdges()[arrivalEdgeIndex] : myRoute->getLastEdge();
896 if (!onInit) {
897 arrivalEdge = myRoute->getLastEdge();
898 // ignore arrivalEdge parameter after rerouting
899 const_cast<SUMOVehicleParameter*>(myParameter)->arrivalEdge = -1;
900 }
901 const std::vector<MSLane*>& lanes = arrivalEdge->getLanes();
902 const double lastLaneLength = lanes[0]->getLength();
905 if (fabs(myParameter->arrivalPos) > lastLaneLength) {
906 WRITE_WARNINGF(TL("Vehicle '%' will not be able to arrive at the given position!"), getID());
907 }
908 // Maybe we should warn the user about invalid inputs!
909 myArrivalPos = MIN2(myParameter->arrivalPos, lastLaneLength);
910 if (myArrivalPos < 0) {
911 myArrivalPos = MAX2(myArrivalPos + lastLaneLength, 0.);
912 }
913 break;
915 myArrivalPos = RandHelper::rand(lastLaneLength);
916 break;
918 myArrivalPos = lastLaneLength / 2.;
919 break;
920 default:
921 myArrivalPos = lastLaneLength;
922 break;
923 }
925 if (myParameter->arrivalLane >= (int)lanes.size() || !lanes[myParameter->arrivalLane]->allowsVehicleClass(myType->getVehicleClass())) {
926 WRITE_WARNINGF(TL("Vehicle '%' will not be able to arrive at the given lane '%_%'!"), getID(), arrivalEdge->getID(), toString(myParameter->arrivalLane));
927 }
928 myArrivalLane = MIN2(myParameter->arrivalLane, (int)(lanes.size() - 1));
930 myArrivalLane = -1;
931 for (MSLane* lane : lanes) {
932 if (lane->allowsVehicleClass(myType->getVehicleClass())) {
933 myArrivalLane = lane->getIndex();
934 break;
935 }
936 }
937 if (myArrivalLane == -1) {
938 WRITE_WARNINGF(TL("Vehicle '%' has no usable arrivalLane on edge '%'."), getID(), arrivalEdge->getID());
939 myArrivalLane = 0;
940 }
942 // pick random lane among all usable lanes
943 std::vector<MSLane*> usable;
944 for (MSLane* lane : lanes) {
945 if (lane->allowsVehicleClass(myType->getVehicleClass())) {
946 usable.push_back(lane);
947 }
948 }
949 if (usable.empty()) {
950 WRITE_WARNINGF(TL("Vehicle '%' has no usable arrivalLane on edge '%'."), getID(), arrivalEdge->getID());
951 myArrivalLane = 0;
952 } else {
953 myArrivalLane = usable[RandHelper::rand(0, (int)usable.size())]->getIndex();
954 }
955 }
957 for (std::vector<MSLane*>::const_iterator l = lanes.begin(); l != lanes.end(); ++l) {
958 if (myParameter->arrivalSpeed <= (*l)->getVehicleMaxSpeed(this)) {
959 return;
960 }
961 }
962 WRITE_WARNINGF(TL("Vehicle '%' will not be able to arrive with the given speed!"), getID());
963 }
964}
965
966void
970 const int routeEdges = (int)myRoute->getEdges().size();
972 // write specific edge in vehroute output for reproducibility
973 pars->departEdge = RandHelper::rand(0, routeEdges);
975 }
976 assert(pars->departEdge >= 0);
977 if (pars->departEdge >= routeEdges) {
978 WRITE_WARNINGF(TL("Ignoring departEdge % for vehicle '%' with % route edges"), toString(pars->departEdge), getID(), toString(routeEdges));
979 } else {
980 myCurrEdge += pars->departEdge;
981 }
982 }
984 const int routeEdges = (int)myRoute->getEdges().size();
985 const int begin = (int)(myCurrEdge - myRoute->begin());
986 // write specific edge in vehroute output for reproducibility
987 pars->arrivalEdge = RandHelper::rand(begin, routeEdges);
989 assert(pars->arrivalEdge >= begin);
990 assert(pars->arrivalEdge < routeEdges);
991 }
992}
993
994
995double
997 return MAX2(0., MIN2(1., getVehicleType().getImpatience()
998 + (hasInfluencer() ? getBaseInfluencer()->getExtraImpatience() : 0)
1000}
1001
1002
1003MSDevice*
1004MSBaseVehicle::getDevice(const std::type_info& type) const {
1005 for (MSVehicleDevice* const dev : myDevices) {
1006 if (typeid(*dev) == type) {
1007 return dev;
1008 }
1009 }
1010 return nullptr;
1011}
1012
1013
1014void
1016 // the parameters may hold the name of a vTypeDistribution but we are interested in the actual type
1019 // params and stops must be written in child classes since they may wish to add additional attributes first
1020 out.writeAttr(SUMO_ATTR_ROUTE, myRoute->getID());
1021 std::ostringstream os;
1022 os << myOdometer << " " << myNumberReroutes;
1023 out.writeAttr(SUMO_ATTR_DISTANCE, os.str());
1025 const int precision = out.precision();
1026 out.setPrecision(MAX2(gPrecisionRandom, precision));
1028 out.setPrecision(precision);
1029 }
1031 out.writeAttr(SUMO_ATTR_REROUTE, true);
1032 }
1034 // could be set from stop
1036 }
1037 // here starts the vehicle internal part (see loading)
1038 // @note: remember to close the vehicle tag when calling this in a subclass!
1039}
1040
1041
1042bool
1043MSBaseVehicle::handleCollisionStop(MSStop& stop, const double distToStop) {
1044 UNUSED_PARAMETER(stop);
1045 UNUSED_PARAMETER(distToStop);
1046 return true;
1047}
1048
1049
1050bool
1052 return !myStops.empty() && myStops.begin()->reached /*&& myState.mySpeed < SUMO_const_haltingSpeed @todo #1864#*/;
1053}
1054
1055
1056bool
1058 return (isStopped() && (myStops.begin()->pars.parking == ParkingType::OFFROAD)
1059 && (myStops.begin()->parkingarea == nullptr || !myStops.begin()->parkingarea->parkOnRoad())
1060 && (myStops.begin()->getSpeed() == 0 || getSpeed() < SUMO_const_haltingSpeed));
1061}
1062
1063
1064bool
1066 return myPastStops.size() > 0 && myPastStops.back().jump >= 0 && getEdge()->getID() == myPastStops.back().edge && myPastStops.back().ended == SIMSTEP;
1067}
1068
1069
1070bool
1072 return isStopped() && (myStops.begin()->triggered || myStops.begin()->containerTriggered || myStops.begin()->joinTriggered);
1073}
1074
1075
1076bool
1078 return isStopped() && (myStops.begin()->pars.parking == ParkingType::OFFROAD);
1079}
1080
1081
1082bool
1083MSBaseVehicle::isStoppedInRange(const double pos, const double tolerance, bool checkFuture) const {
1084 if (isStopped() || (checkFuture && hasStops())) {
1085 const MSStop& stop = myStops.front();
1086 return stop.pars.startPos - tolerance <= pos && stop.pars.endPos + tolerance >= pos;
1087 }
1088 return false;
1089}
1090
1091bool
1092MSBaseVehicle::replaceParkingArea(MSParkingArea* parkingArea, std::string& errorMsg) {
1093 // Check if there is a parking area to be replaced
1094 if (parkingArea == 0) {
1095 errorMsg = "new parkingArea is NULL";
1096 return false;
1097 }
1098 if (myStops.size() == 0) {
1099 errorMsg = "vehicle has no stops";
1100 return false;
1101 }
1102 if (myStops.front().parkingarea == 0) {
1103 errorMsg = "first stop is not at parkingArea";
1104 return false;
1105 }
1106 MSStop& first = myStops.front();
1107 SUMOVehicleParameter::Stop& stopPar = const_cast<SUMOVehicleParameter::Stop&>(first.pars);
1108 std::string oldStopEdgeID = first.lane->getEdge().getID();
1109 // merge subsequent duplicate stops equals to parking area
1110 for (std::list<MSStop>::iterator iter = ++myStops.begin(); iter != myStops.end();) {
1111 if (iter->parkingarea == parkingArea) {
1112 stopPar.duration += iter->duration;
1113 myStops.erase(iter++);
1114 } else {
1115 break;
1116 }
1117 }
1118 stopPar.lane = parkingArea->getLane().getID();
1119 stopPar.parkingarea = parkingArea->getID();
1120 stopPar.startPos = parkingArea->getBeginLanePosition();
1121 stopPar.endPos = parkingArea->getEndLanePosition();
1122 first.edge = myRoute->end(); // will be patched in replaceRoute
1123 first.lane = &parkingArea->getLane();
1124 first.parkingarea = parkingArea;
1125
1126 // patch via edges
1127 std::string newStopEdgeID = parkingArea->getLane().getEdge().getID();
1128 if (myParameter->via.size() > 0 && myParameter->via.front() != newStopEdgeID) {
1129 myParameter->via.erase(myParameter->via.begin());
1130 myParameter->via.insert(myParameter->via.begin(), newStopEdgeID);
1131 }
1132 return true;
1133}
1134
1135
1138 MSParkingArea* nextParkingArea = nullptr;
1139 if (!myStops.empty()) {
1141 MSStop stop = myStops.front();
1142 if (!stop.reached && stop.parkingarea != nullptr) {
1143 nextParkingArea = stop.parkingarea;
1144 }
1145 }
1146 return nextParkingArea;
1147}
1148
1149
1152 MSParkingArea* currentParkingArea = nullptr;
1153 if (isParking()) {
1154 currentParkingArea = myStops.begin()->parkingarea;
1155 }
1156 return currentParkingArea;
1157}
1158
1159
1160const std::vector<std::string>&
1163 return myParameter->parkingBadges;
1164 } else {
1166 }
1167}
1168
1169
1170double
1171MSBaseVehicle::basePos(const MSEdge* edge) const {
1172 double result = MIN2(getVehicleType().getLength() + POSITION_EPS, edge->getLength());
1173 if (hasStops()
1174 && myStops.front().edge == myRoute->begin()
1175 && (&myStops.front().lane->getEdge()) == *myStops.front().edge) {
1176 result = MIN2(result, MAX2(0.0, myStops.front().getEndPos(*this)));
1177 }
1178 return result;
1179}
1180
1181
1182MSLane*
1184 const std::string edgeID = SUMOXMLDefinitions::getEdgeIDFromLane(stop.lane);
1185 const MSEdge* edge = MSEdge::dictionary(edgeID);
1186 if (edge == nullptr || edge->getOppositeEdge() == nullptr || stop.lane.find("_") == std::string::npos) {
1187 return nullptr;
1188 }
1189 const int laneIndex = SUMOXMLDefinitions::getIndexFromLane(stop.lane);
1190 if (laneIndex < (edge->getNumLanes() + edge->getOppositeEdge()->getNumLanes())) {
1191 const int oppositeIndex = edge->getOppositeEdge()->getNumLanes() + edge->getNumLanes() - 1 - laneIndex;
1192 stop.edge = edgeID;
1193 return edge->getOppositeEdge()->getLanes()[oppositeIndex];
1194 }
1195 return nullptr;
1196}
1197
1198
1199bool
1200MSBaseVehicle::addStop(const SUMOVehicleParameter::Stop& stopPar, std::string& errorMsg, SUMOTime untilOffset,
1201 MSRouteIterator* searchStart) {
1202 MSStop stop(stopPar);
1203 if (stopPar.lane == "") {
1204 MSEdge* e = MSEdge::dictionary(stopPar.edge);
1205 stop.lane = e->getFirstAllowed(getVClass());
1206 if (stop.lane == nullptr) {
1207 errorMsg = "Vehicle '" + myParameter->id + "' is not allowed to stop on any lane of edge '" + stopPar.edge + "'.";
1208 return false;
1209 }
1210 } else {
1211 stop.lane = MSLane::dictionary(stopPar.lane);
1212 if (stop.lane == nullptr) {
1213 // must be an opposite stop
1214 SUMOVehicleParameter::Stop tmp = stopPar;
1215 stop.lane = interpretOppositeStop(tmp);
1216 assert(stop.lane != nullptr);
1217 }
1219 errorMsg = "Vehicle '" + myParameter->id + "' is not allowed to stop on lane '" + stopPar.lane + "'.";
1220 return false;
1221 }
1222 }
1224 stop.segment = MSGlobals::gMesoNet->getSegmentForEdge(stop.lane->getEdge(), stop.getEndPos(*this));
1225 if (stop.lane->isInternal()) {
1226 errorMsg = "Mesoscopic simulation does not allow stopping on internal edge '" + stopPar.edge + "' for vehicle '" + myParameter->id + "'.";
1227 return false;
1228 }
1229 }
1230 stop.initPars(stopPar);
1231 if (stopPar.until != -1) {
1232 // !!! it would be much cleaner to invent a constructor for stops which takes "until" as an argument
1233 const_cast<SUMOVehicleParameter::Stop&>(stop.pars).until += untilOffset;
1234 }
1235 if (stopPar.arrival != -1) {
1236 const_cast<SUMOVehicleParameter::Stop&>(stop.pars).arrival += untilOffset;
1237 }
1238 std::string stopType = "stop";
1239 std::string stopID = "";
1240 if (stop.busstop != nullptr) {
1241 stopType = "busStop";
1242 stopID = stop.busstop->getID();
1243 } else if (stop.containerstop != nullptr) {
1244 stopType = "containerStop";
1245 stopID = stop.containerstop->getID();
1246 } else if (stop.chargingStation != nullptr) {
1247 stopType = "chargingStation";
1248 stopID = stop.chargingStation->getID();
1249 } else if (stop.overheadWireSegment != nullptr) {
1250 stopType = "overheadWireSegment";
1251 stopID = stop.overheadWireSegment->getID();
1252 } else if (stop.parkingarea != nullptr) {
1253 stopType = "parkingArea";
1254 stopID = stop.parkingarea->getID();
1255 }
1256 const std::string errorMsgStart = stopID == "" ? stopType : stopType + " '" + stopID + "'";
1257
1258 if (stop.pars.startPos < 0 || stop.pars.endPos > stop.lane->getLength()) {
1259 errorMsg = errorMsgStart + " for vehicle '" + myParameter->id + "' on lane '" + stop.lane->getID() + "' has an invalid position.";
1260 return false;
1261 }
1262 if (stopType != "stop" && stopType != "parkingArea" && myType->getLength() / 2. > stop.pars.endPos - stop.pars.startPos
1263 && MSNet::getInstance()->warnOnce(stopType + ":" + stopID)) {
1264 errorMsg = errorMsgStart + " on lane '" + stop.lane->getID() + "' is too short for vehicle '" + myParameter->id + "'.";
1265 }
1266 if (stopType == "parkingArea" && !stop.parkingarea->accepts(this)) {
1267 // forbid access in case the parking requests other badges
1268 errorMsg = errorMsgStart + "on lane '" + stop.lane->getID() + "' forbids access because vehicle '" + myParameter->id + "' does not provide any valid badge.";
1269 return false;
1270 }
1271 const MSEdge* stopLaneEdge = &stop.lane->getEdge();
1272 const MSEdge* stopEdge;
1273 if (stopLaneEdge->getOppositeEdge() != nullptr && stopLaneEdge->getOppositeEdge()->getID() == stopPar.edge) {
1274 // stop lane is on the opposite side
1275 stopEdge = stopLaneEdge->getOppositeEdge();
1276 stop.isOpposite = true;
1277 } else {
1278 // if stop is on an internal edge the normal edge before the intersection is used
1279 stopEdge = stopLaneEdge->getNormalBefore();
1280 }
1281 MSRouteIterator succ = myCurrEdge + 1; // we're using the address but only within the scope of this function (and recursive calls)
1282 if (searchStart == nullptr) {
1283 searchStart = &myCurrEdge;
1284 if (stopLaneEdge->isNormal() && getLane() != nullptr && getLane()->isInternal()) {
1285 // already on the intersection but myCurrEdge is before it
1286 searchStart = &succ;
1287 }
1288 }
1289#ifdef DEBUG_ADD_STOP
1290 if (DEBUG_COND) {
1291 std::cout << "addStop desc=" << stop.getDescription() << " stopEdge=" << stopEdge->getID()
1292 << " searchStart=" << ((*searchStart) == myRoute->end() ? "END" : (**searchStart)->getID())
1293 << " index=" << (int)((*searchStart) - myRoute->begin()) << " route=" << toString(myRoute->getEdges())
1294 << "\n";
1295 }
1296#endif
1297 stop.edge = std::find(*searchStart, myRoute->end(), stopEdge);
1298 MSRouteIterator prevStopEdge = myCurrEdge;
1299 const MSEdge* prevEdge = (getLane() == nullptr ? getEdge() : &getLane()->getEdge());
1300 double prevStopPos = getPositionOnLane();
1301 // where to insert the stop
1302 std::list<MSStop>::iterator iter = myStops.begin();
1303 if (stopPar.index == STOP_INDEX_END || stopPar.index >= static_cast<int>(myStops.size()) || stopPar.index == STOP_INDEX_REPEAT) {
1304 iter = myStops.end();
1305 if (myStops.size() > 0 && myStops.back().edge >= *searchStart) {
1306 prevStopEdge = myStops.back().edge;
1307 prevEdge = &myStops.back().lane->getEdge();
1308 prevStopPos = myStops.back().pars.endPos;
1309 stop.edge = std::find(prevStopEdge, myRoute->end(), stopEdge);
1310 if (prevStopEdge == stop.edge // laneEdge check is insufficient for looped routes
1311 && prevEdge == &stop.lane->getEdge() // route iterator check insufficient for internal lane stops
1312 && (prevStopPos > stop.pars.endPos ||
1313 (prevStopPos == stop.pars.endPos && stopPar.index == STOP_INDEX_REPEAT))) {
1314 stop.edge = std::find(prevStopEdge + 1, myRoute->end(), stopEdge);
1315 }
1316#ifdef DEBUG_ADD_STOP
1317 if (DEBUG_COND) {
1318 std::cout << " (@end) prevStopEdge=" << (*prevStopEdge)->getID() << " prevStopPos=" << prevStopPos << " index=" << (int)(prevStopEdge - myRoute->begin())
1319 << " foundIndex=" << (stop.edge == myRoute->end() ? -1 : (int)(stop.edge - myRoute->begin())) << "\n";
1320 }
1321#endif
1322 }
1323 // skip a number of occurences of stopEdge in looped route
1324 int skipLooped = stopPar.index - static_cast<int>(myStops.size());
1325 for (int j = 0; j < skipLooped; j++) {
1326 auto nextIt = std::find(stop.edge + 1, myRoute->end(), stopEdge);
1327 if (nextIt == myRoute->end()) {
1328 if (std::find(myRoute->begin(), stop.edge, stopEdge) != stop.edge) {
1329 // only warn if the route loops over the stop edge at least once
1330 errorMsg = errorMsgStart + " for vehicle '" + myParameter->id + "' could not skip " + toString(skipLooped) + " occurences of stop edge '" + stopEdge->getID() + "' in looped route.";
1331 }
1332 break;
1333 } else {
1334 stop.edge = nextIt;
1335 }
1336 }
1337 } else {
1338 if (stopPar.index == STOP_INDEX_FIT) {
1339 while (iter != myStops.end() && (iter->edge < stop.edge ||
1340 (iter->pars.endPos < stop.pars.endPos && iter->edge == stop.edge) ||
1341 (stop.lane->getEdge().isInternal() && iter->edge == stop.edge))) {
1342 prevStopEdge = iter->edge;
1343 prevStopPos = iter->pars.endPos;
1344 ++iter;
1345 }
1346 } else {
1347 int index = stopPar.index;
1348 while (index > 0) {
1349 prevStopEdge = iter->edge;
1350 prevStopPos = iter->pars.endPos;
1351 ++iter;
1352 --index;
1353 }
1354#ifdef DEBUG_ADD_STOP
1355 if (DEBUG_COND) {
1356 std::cout << " (@fit) prevStopEdge=" << (*prevStopEdge)->getID() << " index=" << (int)(prevStopEdge - myRoute->begin()) << "\n";
1357 }
1358#endif
1359 stop.edge = std::find(prevStopEdge, myRoute->end(), stopEdge);
1360 }
1361 }
1362 const bool wasTooClose = errorMsg != "" && errorMsg.find("too close") != std::string::npos;
1363 if (stop.edge == myRoute->end()) {
1364 if (!wasTooClose) {
1365 errorMsg = errorMsgStart + " for vehicle '" + myParameter->id + "' on lane '" + stop.lane->getID() + "' is not downstream the current route.";
1366 }
1367 return false;
1368 }
1369
1370 const bool tooClose = (prevStopEdge == stop.edge && prevEdge == &stop.lane->getEdge() &&
1371 prevStopPos + (iter == myStops.begin() ? getBrakeGap() : 0) > stop.pars.endPos + POSITION_EPS);
1372
1373 if (prevStopEdge > stop.edge ||
1374 // a collision-stop happens after vehicle movement and may move the
1375 // vehicle backwards on its lane (prevStopPos is the vehicle position)
1376 (tooClose && !stop.pars.collision)
1377 || (stop.lane->getEdge().isInternal() && stop.lane->getNextNormal() != *(stop.edge + 1))) {
1378 // check if the edge occurs again later in the route
1379 //std::cout << " could not add stop " << errorMsgStart << " prevStops=" << myStops.size() << " searchStart=" << (*searchStart - myRoute->begin()) << " route=" << toString(myRoute->getEdges()) << "\n";
1380 if (tooClose && prevStopPos <= stop.pars.endPos + POSITION_EPS) {
1381 errorMsg = errorMsgStart + " for vehicle '" + myParameter->id + "' on lane '" + stop.pars.lane + "' is too close to brake.";
1382 }
1383 MSRouteIterator next = stop.edge + 1;
1384 return addStop(stopPar, errorMsg, untilOffset, &next);
1385 }
1386 if (wasTooClose) {
1387 errorMsg = "";
1388 }
1389 // David.C:
1390 //if (!stop.parking && (myCurrEdge == stop.edge && myState.myPos > stop.endPos - getCarFollowModel().brakeGap(myState.mySpeed))) {
1391 const double endPosOffset = stop.lane->getEdge().isInternal() ? (*stop.edge)->getLength() : 0;
1392 const double distToStop = stop.pars.endPos + endPosOffset - getPositionOnLane();
1393 if (stop.pars.collision && !handleCollisionStop(stop, distToStop)) {
1394 return false;
1395 }
1396 if (!hasDeparted() && myCurrEdge == stop.edge) {
1397 double pos = -1;
1399 pos = myParameter->departPos;
1400 if (pos < 0.) {
1401 pos += (*myCurrEdge)->getLength();
1402 }
1403 }
1405 pos = MIN2(stop.pars.endPos + endPosOffset, basePos(*myCurrEdge));
1406 }
1407 if (pos > stop.pars.endPos + endPosOffset) {
1408 if (stop.edge != myRoute->end()) {
1409 // check if the edge occurs again later in the route
1410 MSRouteIterator next = stop.edge + 1;
1411 return addStop(stopPar, errorMsg, untilOffset, &next);
1412 }
1413 errorMsg = errorMsgStart + " for vehicle '" + myParameter->id + "' on lane '" + stop.lane->getID() + "' is before departPos.";
1414 return false;
1415 }
1416 }
1417 if (iter != myStops.begin()) {
1418 std::list<MSStop>::iterator iter2 = iter;
1419 iter2--;
1420 if (stop.getUntil() >= 0 && iter2->getUntil() > stop.getUntil()
1421 && (!MSGlobals::gUseStopEnded || iter2->pars.ended < 0 || stop.pars.ended >= 0)) {
1422 errorMsg = errorMsgStart + " for vehicle '" + myParameter->id + "' on lane '" + stop.lane->getID()
1423 + "' set to end at " + time2string(stop.getUntil())
1424 + " earlier than previous stop at " + time2string(iter2->getUntil()) + ".";
1425 }
1426 if (stop.pars.arrival >= 0 && iter2->pars.arrival > stop.pars.arrival) {
1427 errorMsg = errorMsgStart + " for vehicle '" + myParameter->id + "' on lane '" + stop.lane->getID()
1428 + "' set to start at " + time2string(stop.pars.arrival)
1429 + " earlier than previous stop end at " + time2string(iter2->getUntil()) + ".";
1430 }
1431 if (stop.pars.arrival >= 0 && iter2->pars.arrival > stop.pars.arrival) {
1432 errorMsg = errorMsgStart + " for vehicle '" + myParameter->id + "' on lane '" + stop.lane->getID()
1433 + "' set to start at " + time2string(stop.pars.arrival)
1434 + " earlier than previous stop arrival at " + time2string(iter2->pars.arrival) + ".";
1435 }
1436 } else {
1437 if (stop.getUntil() >= 0 && getParameter().depart > stop.getUntil()
1438 && (!MSGlobals::gUseStopEnded || stop.pars.ended < 0)) {
1439 errorMsg = errorMsgStart + " for vehicle '" + myParameter->id + "' on lane '" + stop.lane->getID()
1440 + "' set to end at " + time2string(stop.getUntil())
1441 + " earlier than departure at " + time2string(getParameter().depart) + ".";
1442 }
1443 }
1444 if (stop.getUntil() >= 0 && stop.getArrival() > stop.getUntil() && errorMsg == "") {
1445 errorMsg = errorMsgStart + " for vehicle '" + myParameter->id + "' on lane '" + stop.lane->getID()
1446 + "' set to end at " + time2string(stop.getUntil())
1447 + " earlier than arrival at " + time2string(stop.getArrival()) + ".";
1448 }
1449 setSkips(stop, (int)myStops.size());
1450 myStops.insert(iter, stop);
1451 if (stopPar.tripId != "") {
1453 }
1454 //std::cout << " added stop " << errorMsgStart << " totalStops=" << myStops.size() << " searchStart=" << (*searchStart - myRoute->begin())
1455 // << " routeIndex=" << (stop.edge - myRoute->begin())
1456 // << " stopIndex=" << std::distance(myStops.begin(), iter)
1457 // << " route=" << toString(myRoute->getEdges()) << "\n";
1458 return true;
1459}
1460
1461
1462void
1463MSBaseVehicle::setSkips(MSStop& stop, int prevActiveStops) {
1464 if (hasDeparted() && stop.edge > myRoute->begin()) {
1465 // if the route is looped we must patch the index to ensure that state
1466 // loading (and vehroute-output) encode the correct number of skips
1467 int foundSkips = 0;
1468 MSRouteIterator itPrev;
1469 double prevEndPos;
1470 if (prevActiveStops > 0) {
1471 assert((int)myStops.size() >= prevActiveStops);
1472 auto prevStopIt = myStops.begin();
1473 std::advance(prevStopIt, prevActiveStops - 1);
1474 const MSStop& prev = *prevStopIt;
1475 itPrev = prev.edge;
1476 prevEndPos = prev.pars.endPos;
1477 } else if (myPastStops.size() > 0) {
1478 itPrev = myRoute->begin() + myPastStops.back().routeIndex;
1479 prevEndPos = myPastStops.back().endPos;
1480 } else {
1481 itPrev = myRoute->begin() + myParameter->departEdge;
1482 prevEndPos = myDepartPos;
1483 }
1484 //auto itPrevOrig = itPrev;
1485 if (*itPrev == *stop.edge && prevEndPos > stop.pars.endPos) {
1486 itPrev++;
1487 }
1488 //std::cout << SIMTIME << " veh=" << getID() << " prevActive=" << prevActiveStops << " edge=" << (*stop.edge)->getID() << " routeIndex=" << (stop.edge - myRoute->begin()) << " prevIndex=" << (itPrev - myRoute->begin()) << "\n";
1489 while (itPrev < stop.edge) {
1490 if (*itPrev == *stop.edge) {
1491 foundSkips++;
1492 }
1493 itPrev++;
1494 }
1495 int newIndex = STOP_INDEX_END;
1496 if (foundSkips > 0) {
1497 //if (getID() == "77_0_0") {
1498 // std::cout << SIMTIME << " veh=" << getID() << " past=" << myPastStops.size() << " prevActive=" << prevActiveStops
1499 // << " edge=" << (*stop.edge)->getID() << " routeIndex=" << (stop.edge - myRoute->begin())
1500 // << " prevEdge=" << (*itPrevOrig)->getID()
1501 // << " prevIndex=" << (itPrevOrig - myRoute->begin())
1502 // << " skips=" << foundSkips << "\n";
1503 //}
1504 newIndex = (int)myPastStops.size() + prevActiveStops + foundSkips;
1505 }
1506 const_cast<SUMOVehicleParameter::Stop&>(stop.pars).index = newIndex;
1507 }
1508}
1509
1510
1511void
1512MSBaseVehicle::addStops(const bool ignoreStopErrors, MSRouteIterator* searchStart, bool addRouteStops) {
1513 if (addRouteStops) {
1514 for (const SUMOVehicleParameter::Stop& stop : myRoute->getStops()) {
1515 std::string errorMsg;
1516 if (!addStop(stop, errorMsg, myParameter->depart, searchStart) && !ignoreStopErrors) {
1517 throw ProcessError(errorMsg);
1518 }
1519 if (errorMsg != "") {
1520 WRITE_WARNING(errorMsg);
1521 }
1522 }
1523 }
1525 for (const SUMOVehicleParameter::Stop& stop : myParameter->stops) {
1526 std::string errorMsg;
1527 if (!addStop(stop, errorMsg, untilOffset, searchStart) && !ignoreStopErrors) {
1528 throw ProcessError(errorMsg);
1529 }
1530 if (errorMsg != "") {
1531 WRITE_WARNING(errorMsg);
1532 }
1533 }
1534}
1535
1536
1537bool
1540 int i = 0;
1541 bool ok = true;
1542 for (const MSStop& stop : myStops) {
1543 MSRouteIterator it;
1544 if (stop.lane->isInternal()) {
1545 // find the normal predecessor and ensure that the next route edge
1546 // matches the successor of the internal edge successor
1547 it = std::find(start, myRoute->end(), stop.lane->getEdge().getNormalBefore());
1548 if (it != myRoute->end() && (
1549 it + 1 == myRoute->end() || *(it + 1) != stop.lane->getEdge().getNormalSuccessor())) {
1550 it = myRoute->end(); // signal failure
1551 }
1552 } else {
1553 it = std::find(start, myRoute->end(), &stop.lane->getEdge());
1554 }
1555 if (it == myRoute->end()) {
1556 if (!silent) {
1557 WRITE_ERRORF("Stop % on edge '%' is not found after edge '%' (% after current) for vehicle '%' at time=%.",
1558 i, stop.lane->getEdge().getID(), (*start)->getID(), toString(start - myCurrEdge), getID(), time2string(SIMSTEP));
1559 }
1560 ok = false;
1561 } else {
1562 MSRouteIterator it2;
1563 for (it2 = myRoute->begin(); it2 != myRoute->end(); it2++) {
1564 if (it2 == stop.edge) {
1565 break;
1566 }
1567 }
1568 if (it2 == myRoute->end()) {
1569 if (!silent) {
1570 WRITE_ERRORF("Stop % on edge '%' used invalid route index for vehicle '%' at time=%.",
1571 i, stop.lane->getEdge().getID(), getID(), time2string(SIMSTEP));
1572 }
1573 ok = false;
1574 } else if (it2 < start) {
1575 if (!silent) {
1576 WRITE_ERRORF("Stop % on edge '%' used invalid (relative) route index % expected after % for vehicle '%' at time=%.",
1577 i, stop.lane->getEdge().getID(), toString(it2 - myCurrEdge), toString(start - myCurrEdge), getID(), time2string(SIMSTEP));
1578 }
1579 ok = false;
1580 } else {
1581 start = stop.edge;
1582 }
1583 }
1584 i++;
1585 }
1586 return ok;
1587}
1588
1589
1591MSBaseVehicle::getStopEdges(double& firstPos, double& lastPos, std::set<int>& jumps) const {
1592 assert(haveValidStopEdges());
1593 ConstMSEdgeVector result;
1594 const MSStop* prev = nullptr;
1595 const MSEdge* internalSuccessor = nullptr;
1596 for (const MSStop& stop : myStops) {
1597 if (stop.reached) {
1598 if (stop.pars.jump >= 0) {
1599 jumps.insert((int)result.size());
1600 }
1601 continue;
1602 }
1603 const double stopPos = stop.getEndPos(*this);
1604 if ((prev == nullptr
1605 || prev->edge != stop.edge
1606 || (prev->lane == stop.lane && prev->getEndPos(*this) > stopPos))
1607 && *stop.edge != internalSuccessor) {
1608 result.push_back(*stop.edge);
1609 if (stop.lane->isInternal()) {
1610 internalSuccessor = stop.lane->getNextNormal();
1611 result.push_back(internalSuccessor);
1612 } else {
1613 internalSuccessor = nullptr;
1614 }
1615 }
1616 prev = &stop;
1617 if (firstPos == INVALID_DOUBLE) {
1618 if (stop.parkingarea != nullptr) {
1619 firstPos = MAX2(0., stopPos);
1620 } else {
1621 firstPos = stopPos;
1622 }
1623 }
1624 lastPos = stopPos;
1625 if (stop.pars.jump >= 0) {
1626 jumps.insert((int)result.size() - 1);
1627 }
1628 }
1629 //std::cout << "getStopEdges veh=" << getID() << " result=" << toString(result) << "\n";
1630 return result;
1631}
1632
1633
1634std::vector<std::pair<int, double> >
1636 std::vector<std::pair<int, double> > result;
1637 for (std::list<MSStop>::const_iterator iter = myStops.begin(); iter != myStops.end(); ++iter) {
1638 result.push_back(std::make_pair(
1639 (int)(iter->edge - myRoute->begin()),
1640 iter->getEndPos(*this)));
1641 }
1642 return result;
1643}
1644
1645
1646MSStop&
1648 assert(myStops.size() > 0);
1649 return myStops.front();
1650}
1651
1654 if (isStopped()) {
1655 return myStops.front().duration;
1656 } else {
1657 return 0;
1658 }
1659}
1660
1661
1662MSStop&
1663MSBaseVehicle::getStop(int nextStopIndex) {
1664 if (nextStopIndex < 0 || (int)myStops.size() <= nextStopIndex) {
1665 throw InvalidArgument(TLF("Invalid stop index % (has % stops).", nextStopIndex, myStops.size()));
1666 }
1667 auto stopIt = myStops.begin();
1668 std::advance(stopIt, nextStopIndex);
1669 return *stopIt;
1670}
1671
1672
1675 if (hasStops()) {
1676 return &myStops.front().pars;
1677 }
1678 return nullptr;
1679}
1680
1681
1682bool
1684 //if the stop exists update the duration
1685 for (std::list<MSStop>::iterator iter = myStops.begin(); iter != myStops.end(); iter++) {
1686 if (iter->lane->getID() == stop.lane && fabs(iter->pars.endPos - stop.endPos) < POSITION_EPS) {
1687 // update existing stop
1688 if (stop.duration == 0 && stop.until < 0 && !iter->reached) {
1689 myStops.erase(iter);
1690 } else {
1691 iter->duration = stop.duration;
1692 iter->triggered = stop.triggered;
1693 iter->containerTriggered = stop.containerTriggered;
1694 const_cast<SUMOVehicleParameter::Stop&>(iter->pars).until = stop.until;
1695 const_cast<SUMOVehicleParameter::Stop&>(iter->pars).parking = stop.parking;
1696 }
1697 return true;
1698 }
1699 }
1700 const bool result = addStop(stop, errorMsg);
1701 if (result) {
1703 myParameter->stops.push_back(stop);
1704 }
1705 return result;
1706}
1707
1708
1709void
1716
1717
1718bool
1720 if (hasStops() && nextStopIndex < (int)myStops.size()) {
1721 if (nextStopIndex == 0 && isStopped()) {
1723 } else {
1724 auto stopIt = myStops.begin();
1725 std::advance(stopIt, nextStopIndex);
1726 myStops.erase(stopIt);
1727 }
1728 if (!hasDeparted() && (int)myParameter->stops.size() > nextStopIndex) {
1729 // stops will be rebuilt from scratch on rerouting so we must patch the stops in myParameter
1730 auto stopIt2 = myParameter->stops.begin();
1731 std::advance(stopIt2, nextStopIndex);
1732 const_cast<SUMOVehicleParameter*>(myParameter)->stops.erase(stopIt2);
1733 }
1734 return true;
1735 } else {
1736 return false;
1737 }
1738}
1739
1740
1741bool
1742MSBaseVehicle::replaceStop(int nextStopIndex, SUMOVehicleParameter::Stop stop, const std::string& info, bool teleport, std::string& errorMsg) {
1743 const int n = (int)myStops.size();
1744 if (nextStopIndex < 0 || nextStopIndex >= n) {
1745 errorMsg = TLF("invalid nextStopIndex % for % remaining stops", nextStopIndex, n);
1746 return false;
1747 }
1748 if (nextStopIndex == 0 && isStopped()) {
1749 errorMsg = TL("cannot replace reached stop");
1750 return false;
1751 }
1753 MSLane* stopLane = MSLane::dictionary(stop.lane);
1754 MSEdge* stopEdge = &stopLane->getEdge();
1755
1756 auto itStop = myStops.begin();
1757 std::advance(itStop, nextStopIndex);
1758 MSStop& replacedStop = *itStop;
1759
1760 // check parking access rights
1761 if (stop.parkingarea != "") {
1763 if (pa != nullptr && !pa->accepts(this)) {
1764 errorMsg = TLF("vehicle '%' does not have the right badge to access parkingArea '%'", getID(), stop.parkingarea);
1765 return false;
1766 }
1767 }
1768
1769 if (replacedStop.lane == stopLane && replacedStop.pars.endPos == stop.endPos && !teleport) {
1770 // only replace stop attributes
1771 const_cast<SUMOVehicleParameter::Stop&>(replacedStop.pars) = stop;
1772 replacedStop.initPars(stop);
1773 return true;
1774 }
1775
1776 if (!stopLane->allowsVehicleClass(getVClass(), myRoutingMode)) {
1777 errorMsg = TLF("disallowed stop lane '%'", stopLane->getID());
1778 return false;
1779 }
1780
1781 const ConstMSEdgeVector& oldEdges = getRoute().getEdges();
1782 std::vector<MSStop> stops(myStops.begin(), myStops.end());
1783 const int junctionOffset = getLane() != nullptr && getLane()->isInternal() ? 1 : 0;
1784 MSRouteIterator itStart = nextStopIndex == 0 ? getCurrentRouteEdge() + junctionOffset : stops[nextStopIndex - 1].edge;
1785 double startPos = nextStopIndex == 0 ? getPositionOnLane() : stops[nextStopIndex - 1].pars.endPos;
1786 MSRouteIterator itEnd = nextStopIndex == n - 1 ? oldEdges.end() - 1 : stops[nextStopIndex + 1].edge;
1787 auto endPos = nextStopIndex == n - 1 ? getArrivalPos() : stops[nextStopIndex + 1].pars.endPos;
1789
1790 bool newDestination = nextStopIndex == n - 1 && stops[nextStopIndex].edge == oldEdges.end() - 1;
1791
1792 ConstMSEdgeVector toNewStop;
1793 if (!teleport) {
1794 router.compute(*itStart, startPos, stopEdge, stop.endPos, this, t, toNewStop, true);
1795 if (toNewStop.size() == 0) {
1796 errorMsg = TLF("no route found from edge '%' to stop edge '%'", (*itStart)->getID(), stopEdge->getID());
1797 return false;
1798 }
1799 }
1800
1801 ConstMSEdgeVector fromNewStop;
1802 if (!newDestination) {
1803 router.compute(stopEdge, stop.endPos, *itEnd, endPos, this, t, fromNewStop, true);
1804 if (fromNewStop.size() == 0) {
1805 errorMsg = TLF("no route found from stop edge '%' to edge '%'", stopEdge->getID(), (*itEnd)->getID());
1806 return false;
1807 }
1808 }
1809
1810 const_cast<SUMOVehicleParameter::Stop&>(replacedStop.pars) = stop;
1811 replacedStop.initPars(stop);
1812 replacedStop.edge = myRoute->end(); // will be patched in replaceRoute
1813 replacedStop.lane = stopLane;
1815 replacedStop.segment = MSGlobals::gMesoNet->getSegmentForEdge(replacedStop.lane->getEdge(), replacedStop.getEndPos(*this));
1816 if (replacedStop.lane->isInternal()) {
1817 errorMsg = TLF("Mesoscopic simulation does not allow stopping on internal edge '%' for vehicle '%'.", stop.edge, getID());
1818 return false;
1819 }
1820 }
1821
1822 ConstMSEdgeVector oldRemainingEdges(myCurrEdge, getRoute().end());
1823 ConstMSEdgeVector newEdges; // only remaining
1824 newEdges.insert(newEdges.end(), myCurrEdge, itStart);
1825 if (!teleport) {
1826 newEdges.insert(newEdges.end(), toNewStop.begin(), toNewStop.end() - 1);
1827 } else {
1828 newEdges.push_back(*itStart);
1829 }
1830 if (!newDestination) {
1831 newEdges.insert(newEdges.end(), fromNewStop.begin(), fromNewStop.end() - 1);
1832 newEdges.insert(newEdges.end(), itEnd, oldEdges.end());
1833 } else {
1834 newEdges.push_back(stopEdge);
1835 }
1836 //std::cout << SIMTIME << " replaceStop veh=" << getID()
1837 // << " teleport=" << teleport
1838 // << " busStop=" << stop.busstop
1839 // << " oldEdges=" << oldRemainingEdges.size()
1840 // << " newEdges=" << newEdges.size()
1841 // << " toNewStop=" << toNewStop.size()
1842 // << " fromNewStop=" << fromNewStop.size()
1843 // << "\n";
1844
1845 const double routeCost = router.recomputeCosts(newEdges, this, t);
1846 const double previousCost = router.recomputeCosts(oldRemainingEdges, this, t);
1847 const double savings = previousCost - routeCost;
1848 if (!hasDeparted() && (int)myParameter->stops.size() > nextStopIndex) {
1849 // stops will be rebuilt from scratch so we must patch the stops in myParameter
1850 const_cast<SUMOVehicleParameter*>(myParameter)->stops[nextStopIndex] = stop;
1851 }
1852 if (teleport) {
1853 // let the vehicle jump rather than teleport
1854 // we add a jump-stop at the end of the edge (unless the vehicle is
1855 // already configure to jump before the replaced stop)
1856 if (!insertJump(nextStopIndex, itStart, errorMsg)) {
1857 return false;
1858 };
1859 }
1860 return replaceRouteEdges(newEdges, routeCost, savings, info, !hasDeparted(), false, false, &errorMsg);
1861}
1862
1863
1864bool
1865MSBaseVehicle::rerouteBetweenStops(int nextStopIndex, const std::string& info, bool teleport, std::string& errorMsg) {
1866 const int n = (int)myStops.size();
1867 if (nextStopIndex < 0 || nextStopIndex > n) {
1868 errorMsg = TLF("invalid nextStopIndex % for % remaining stops", nextStopIndex, n);
1869 return false;
1870 }
1871 if (nextStopIndex == 0 && isStopped()) {
1872 errorMsg = TL("cannot reroute towards reached stop");
1873 return false;
1874 }
1876
1877 const ConstMSEdgeVector& oldEdges = getRoute().getEdges();
1878 std::vector<MSStop> stops(myStops.begin(), myStops.end());
1879 const int junctionOffset = getLane() != nullptr && getLane()->isInternal() ? 1 : 0;
1880 MSRouteIterator itStart = nextStopIndex == 0 ? getCurrentRouteEdge() + junctionOffset : stops[nextStopIndex - 1].edge;
1881 double startPos = nextStopIndex == 0 ? getPositionOnLane() : stops[nextStopIndex - 1].pars.endPos;
1882 MSRouteIterator itEnd = nextStopIndex == n ? oldEdges.end() - 1 : stops[nextStopIndex].edge;
1883 auto endPos = nextStopIndex == n ? getArrivalPos() : stops[nextStopIndex].pars.endPos;
1885
1886 ConstMSEdgeVector newBetween;
1887 if (!teleport) {
1888 router.compute(*itStart, startPos, *itEnd, endPos, this, t, newBetween, true);
1889 if (newBetween.size() == 0) {
1890 errorMsg = TLF("no route found from edge '%' to stop edge '%'", (*itStart)->getID(), (*itEnd)->getID());
1891 return false;
1892 }
1893 }
1894
1895 ConstMSEdgeVector oldRemainingEdges(myCurrEdge, getRoute().end());
1896 ConstMSEdgeVector newEdges; // only remaining
1897 newEdges.insert(newEdges.end(), myCurrEdge, itStart);
1898 if (!teleport) {
1899 newEdges.insert(newEdges.end(), newBetween.begin(), newBetween.end() - 1);
1900 } else {
1901 newEdges.push_back(*itStart);
1902 }
1903 newEdges.insert(newEdges.end(), itEnd, oldEdges.end());
1904 //std::cout << SIMTIME << " rerouteBetweenStops veh=" << getID()
1905 // << " oldEdges=" << oldRemainingEdges.size()
1906 // << " newEdges=" << newEdges.size()
1907 // << " toNewStop=" << toNewStop.size()
1908 // << " fromNewStop=" << fromNewStop.size()
1909 // << "\n";
1910
1911 const double routeCost = router.recomputeCosts(newEdges, this, t);
1912 const double previousCost = router.recomputeCosts(oldRemainingEdges, this, t);
1913 const double savings = previousCost - routeCost;
1914
1915 if (teleport) {
1916 // let the vehicle jump rather than teleport
1917 // we add a jump-stop at the end of the edge (unless the vehicle is
1918 // already configure to jump before the replaced stop)
1919 if (!insertJump(nextStopIndex, itStart, errorMsg)) {
1920 return false;
1921 };
1922 }
1923 return replaceRouteEdges(newEdges, routeCost, savings, info, !hasDeparted(), false, false, &errorMsg);
1924}
1925
1926
1927bool
1928MSBaseVehicle::insertJump(int nextStopIndex, MSRouteIterator itStart, std::string& errorMsg) {
1929 bool needJump = true;
1930 if (nextStopIndex > 0) {
1931 auto itPriorStop = myStops.begin();
1932 std::advance(itPriorStop, nextStopIndex - 1);
1933 const MSStop& priorStop = *itPriorStop;
1934 if (priorStop.pars.jump >= 0) {
1935 needJump = false;
1936 }
1937 }
1938 if (needJump) {
1939 SUMOVehicleParameter::Stop jumpStopPars;
1940 jumpStopPars.endPos = (*itStart)->getLength();
1941 jumpStopPars.speed = 1000;
1942 jumpStopPars.jump = 0;
1943 jumpStopPars.edge = (*itStart)->getID();
1945 MSLane* jumpStopLane = nullptr;
1946 for (MSLane* cand : (*itStart)->getLanes()) {
1947 if (cand->allowsVehicleClass(getVClass())) {
1948 jumpStopLane = cand;
1949 break;
1950 }
1951 }
1952 if (jumpStopLane == nullptr) {
1953 errorMsg = TL("unable to replace stop with teleporting");
1954 return false;
1955 }
1956 auto itStop = myStops.begin();
1957 std::advance(itStop, nextStopIndex);
1958 MSStop jumpStop(jumpStopPars);
1959 jumpStop.initPars(jumpStopPars);
1960 jumpStop.lane = jumpStopLane;
1961 jumpStop.edge = myRoute->end(); // will be patched in replaceRoute
1962 myStops.insert(itStop, jumpStop);
1963 if (!hasDeparted() && (int)myParameter->stops.size() > nextStopIndex) {
1964 // stops will be rebuilt from scratch so we must patch the stops in myParameter
1965 auto it = myParameter->stops.begin() + nextStopIndex;
1966 const_cast<SUMOVehicleParameter*>(myParameter)->stops.insert(it, jumpStopPars);
1967 }
1968 }
1969 return true;
1970}
1971
1972
1973bool
1974MSBaseVehicle::insertStop(int nextStopIndex, SUMOVehicleParameter::Stop stop, const std::string& info, bool teleport, std::string& errorMsg) {
1975 const int n = (int)myStops.size();
1976 if (nextStopIndex < 0 || nextStopIndex > n) {
1977 errorMsg = TLF("invalid nextStopIndex % for % remaining stops", nextStopIndex, n);
1978 return false;
1979 }
1980 if (nextStopIndex == 0 && isStopped()) {
1981 errorMsg = TL("cannot insert stop before the currently reached stop");
1982 return false;
1983 }
1985 MSLane* stopLane = MSLane::dictionary(stop.lane);
1986 MSEdge* stopEdge = &stopLane->getEdge();
1987
1988 if (!stopLane->allowsVehicleClass(getVClass(), myRoutingMode)) {
1989 errorMsg = TLF("disallowed stop lane '%'", stopLane->getID());
1990 return false;
1991 }
1992
1993 // check parking access rights
1994 if (stop.parkingarea != "") {
1996 if (pa != nullptr && !pa->accepts(this)) {
1997 errorMsg = TLF("Vehicle '%' does not have the right badge to access parkingArea '%'.", getID(), stop.parkingarea);
1998 return false;
1999 }
2000 }
2001
2002 const ConstMSEdgeVector& oldEdges = getRoute().getEdges();
2003 std::vector<MSStop> stops(myStops.begin(), myStops.end());
2004 const int junctionOffset = getLane() != nullptr && getLane()->isInternal() ? 1 : 0;
2005 MSRouteIterator itStart = nextStopIndex == 0 ? getCurrentRouteEdge() + junctionOffset : stops[nextStopIndex - 1].edge;
2006 double startPos = nextStopIndex == 0 ? getPositionOnLane() : stops[nextStopIndex - 1].pars.endPos;
2007 MSRouteIterator itEnd = nextStopIndex == n ? oldEdges.end() - 1 : stops[nextStopIndex].edge;
2008 auto endPos = nextStopIndex == n ? getArrivalPos() : stops[nextStopIndex].pars.endPos;
2010
2011 bool newDestination = nextStopIndex == n && stopEdge == oldEdges.back();
2012
2013 ConstMSEdgeVector toNewStop;
2014 if (!teleport) {
2015 router.compute(*itStart, startPos, stopEdge, stop.endPos, this, t, toNewStop, true);
2016 if (toNewStop.size() == 0) {
2017 errorMsg = TLF("no route found from edge '%' to stop edge '%'", (*itStart)->getID(), stopEdge->getID());
2018 return false;
2019 }
2020 }
2021
2022 ConstMSEdgeVector fromNewStop;
2023 if (!newDestination) {
2024 router.compute(stopEdge, stop.endPos, *itEnd, endPos, this, t, fromNewStop, true);
2025 if (fromNewStop.size() == 0) {
2026 errorMsg = TLF("no route found from stop edge '%' to edge '%'", stopEdge->getID(), (*itEnd)->getID());
2027 return false;
2028 }
2029 }
2030
2031 auto itStop = myStops.begin();
2032 std::advance(itStop, nextStopIndex);
2033 MSStop newStop(stop);
2034 newStop.initPars(stop);
2035 newStop.edge = myRoute->end(); // will be patched in replaceRoute
2036 newStop.lane = stopLane;
2038 newStop.segment = MSGlobals::gMesoNet->getSegmentForEdge(newStop.lane->getEdge(), newStop.getEndPos(*this));
2039 if (newStop.lane->isInternal()) {
2040 errorMsg = TLF("Mesoscopic simulation does not allow stopping on internal edge '%' for vehicle '%'.", stop.edge, getID());
2041 return false;
2042 }
2043 }
2044 myStops.insert(itStop, newStop);
2045
2046 ConstMSEdgeVector oldRemainingEdges(myCurrEdge, getRoute().end());
2047 ConstMSEdgeVector newEdges; // only remaining
2048 newEdges.insert(newEdges.end(), myCurrEdge, itStart);
2049 if (!teleport) {
2050 newEdges.insert(newEdges.end(), toNewStop.begin(), toNewStop.end() - 1);
2051 } else {
2052 newEdges.push_back(*itStart);
2053 }
2054 if (!newDestination) {
2055 newEdges.insert(newEdges.end(), fromNewStop.begin(), fromNewStop.end() - 1);
2056 newEdges.insert(newEdges.end(), itEnd, oldEdges.end());
2057 } else {
2058 newEdges.push_back(stopEdge);
2059 }
2060 //std::cout << SIMTIME << " insertStop veh=" << getID()
2061 // << " teleport=" << teleport
2062 // << " busStop=" << stop.busstop
2063 // << " oldEdges=" << oldRemainingEdges.size()
2064 // << " newEdges=" << newEdges.size()
2065 // << " toNewStop=" << toNewStop.size()
2066 // << " fromNewStop=" << fromNewStop.size()
2067 // << "\n";
2068
2069 const double routeCost = router.recomputeCosts(newEdges, this, t);
2070 const double previousCost = router.recomputeCosts(oldRemainingEdges, this, t);
2071 const double savings = previousCost - routeCost;
2072
2073 if (!hasDeparted() && (int)myParameter->stops.size() >= nextStopIndex) {
2074 // stops will be rebuilt from scratch so we must patch the stops in myParameter
2075 auto it = myParameter->stops.begin() + nextStopIndex;
2076 const_cast<SUMOVehicleParameter*>(myParameter)->stops.insert(it, stop);
2077 }
2078 return replaceRouteEdges(newEdges, routeCost, savings, info, !hasDeparted(), false, false, &errorMsg);
2079}
2080
2081
2082double
2084 if (static_cast<MSDevice_Battery*>(getDevice(typeid(MSDevice_Battery))) != 0) {
2085 MSDevice_Battery* batteryOfVehicle = dynamic_cast<MSDevice_Battery*>(getDevice(typeid(MSDevice_Battery)));
2086 return batteryOfVehicle->getActualBatteryCapacity();
2087 } else {
2088 if (static_cast<MSDevice_ElecHybrid*>(getDevice(typeid(MSDevice_ElecHybrid))) != 0) {
2089 MSDevice_ElecHybrid* batteryOfVehicle = dynamic_cast<MSDevice_ElecHybrid*>(getDevice(typeid(MSDevice_ElecHybrid)));
2090 return batteryOfVehicle->getActualBatteryCapacity();
2091 }
2092 }
2093 return -1;
2094}
2095
2096
2097double
2099 if (static_cast<MSDevice_Battery*>(getDevice(typeid(MSDevice_Battery))) != 0) {
2100 MSDevice_Battery* batteryOfVehicle = dynamic_cast<MSDevice_Battery*>(getDevice(typeid(MSDevice_Battery)));
2101 return batteryOfVehicle->getActualBatteryCapacity() / batteryOfVehicle->getMaximumBatteryCapacity();
2102 } else {
2103 if (static_cast<MSDevice_ElecHybrid*>(getDevice(typeid(MSDevice_ElecHybrid))) != 0) {
2104 MSDevice_ElecHybrid* batteryOfVehicle = dynamic_cast<MSDevice_ElecHybrid*>(getDevice(typeid(MSDevice_ElecHybrid)));
2105 return batteryOfVehicle->getActualBatteryCapacity() / batteryOfVehicle->getMaximumBatteryCapacity();
2106 }
2107 }
2108 return -1;
2109}
2110
2111
2112double
2114 if (static_cast<MSDevice_Battery*>(getDevice(typeid(MSDevice_Battery))) != 0) {
2115 MSDevice_Battery* batteryOfVehicle = dynamic_cast<MSDevice_Battery*>(getDevice(typeid(MSDevice_Battery)));
2116 return batteryOfVehicle->getEnergyCharged();
2117 } else {
2118 if (static_cast<MSDevice_ElecHybrid*>(getDevice(typeid(MSDevice_ElecHybrid))) != 0) {
2119 MSDevice_ElecHybrid* batteryOfVehicle = dynamic_cast<MSDevice_ElecHybrid*>(getDevice(typeid(MSDevice_ElecHybrid)));
2120 return batteryOfVehicle->getEnergyCharged();
2121 }
2122 }
2123 return -1;
2124}
2125
2126
2127double
2129 if (static_cast<MSDevice_Battery*>(getDevice(typeid(MSDevice_Battery))) != 0) {
2130 MSDevice_Battery* batteryOfVehicle = dynamic_cast<MSDevice_Battery*>(getDevice(typeid(MSDevice_Battery)));
2131 return batteryOfVehicle->getMaximumChargeRate();
2132 }
2133 return -1;
2134}
2135
2136
2137double
2139 if (static_cast<MSDevice_ElecHybrid*>(getDevice(typeid(MSDevice_ElecHybrid))) != 0) {
2140 MSDevice_ElecHybrid* elecHybridDevice = dynamic_cast<MSDevice_ElecHybrid*>(getDevice(typeid(MSDevice_ElecHybrid)));
2141 return elecHybridDevice->getCurrentFromOverheadWire();
2142 }
2143
2144 return NAN;
2145}
2146
2147double
2149 if (isOnRoad() || isIdling()) {
2151 } else {
2152 return 0.;
2153 }
2154}
2155
2156
2161
2162
2167
2168
2171 if (myEdgeWeights == nullptr) {
2173 }
2174 return *myEdgeWeights;
2175}
2176
2177
2178
2179
2180int
2182 int boarded = myPersonDevice == nullptr ? 0 : myPersonDevice->size();
2183 return boarded + myParameter->personNumber;
2184}
2185
2186int
2188 int leavingPersonNumber = 0;
2189 const std::vector<MSTransportable*>& persons = getPersons();
2190 for (std::vector<MSTransportable*>::const_iterator it_p = persons.begin(); it_p != persons.end(); ++it_p) {
2191 MSStageDriving* const stage = dynamic_cast<MSStageDriving*>((*it_p)->getCurrentStage());
2192 const MSStop* stop = &myStops.front();
2193 const MSVehicle* joinVeh = dynamic_cast<MSVehicle*>(MSNet::getInstance()->getVehicleControl().getVehicle((*stop).pars.join));
2194 if (stop && stage->canLeaveVehicle(*it_p, *this, *stop) && !MSDevice_Transportable::willTransferAtJoin(*it_p, joinVeh)) {
2195 leavingPersonNumber++;
2196 }
2197 }
2198 return leavingPersonNumber;
2199}
2200
2201std::vector<std::string>
2203 std::vector<std::string> ret;
2204 const std::vector<MSTransportable*>& persons = getPersons();
2205 for (std::vector<MSTransportable*>::const_iterator it_p = persons.begin(); it_p != persons.end(); ++it_p) {
2206 ret.push_back((*it_p)->getID());
2207 }
2208 return ret;
2209}
2210
2211int
2213 int loaded = myContainerDevice == nullptr ? 0 : myContainerDevice->size();
2214 return loaded + myParameter->containerNumber;
2215}
2216
2217
2218void
2220 // this might be called from the MSTransportable destructor so we cannot do a dynamic cast to determine the type
2221 if (myPersonDevice != nullptr) {
2223 }
2224 if (myContainerDevice != nullptr) {
2226 }
2227 if (myEnergyParams != nullptr) {
2229 }
2230}
2231
2232
2233const std::vector<MSTransportable*>&
2235 if (myPersonDevice == nullptr) {
2237 } else {
2239 }
2240}
2241
2242
2243const std::vector<MSTransportable*>&
2245 if (myContainerDevice == nullptr) {
2247 } else {
2249 }
2250}
2251
2252
2253bool
2254MSBaseVehicle::isLineStop(double position) const {
2255 if (myParameter->line == "") {
2256 // not a public transport line
2257 return false;
2258 }
2259 for (const SUMOVehicleParameter::Stop& stop : myParameter->stops) {
2260 if (stop.startPos <= position && position <= stop.endPos) {
2261 return true;
2262 }
2263 }
2264 for (const SUMOVehicleParameter::Stop& stop : myRoute->getStops()) {
2265 if (stop.startPos <= position && position <= stop.endPos) {
2266 return true;
2267 }
2268 }
2269 return false;
2270}
2271
2272
2273bool
2274MSBaseVehicle::hasDevice(const std::string& deviceName) const {
2275 for (MSDevice* const dev : myDevices) {
2276 if (dev->deviceName() == deviceName) {
2277 return true;
2278 }
2279 }
2280 return false;
2281}
2282
2283
2284void
2285MSBaseVehicle::createDevice(const std::string& deviceName) {
2286 if (!hasDevice(deviceName)) {
2287 if (deviceName == "rerouting") {
2288 ((SUMOVehicleParameter*)myParameter)->setParameter("has." + deviceName + ".device", "true");
2290 if (hasDeparted()) {
2291 // vehicle already departed: disable pre-insertion rerouting and enable regular routing behavior
2292 MSDevice_Routing* routingDevice = static_cast<MSDevice_Routing*>(getDevice(typeid(MSDevice_Routing)));
2293 assert(routingDevice != 0);
2295 }
2296 } else {
2297 throw InvalidArgument(TLF("creating device of type '%' is not supported", deviceName));
2298 }
2299 }
2300}
2301
2302
2303std::string
2304MSBaseVehicle::getDeviceParameter(const std::string& deviceName, const std::string& key) const {
2305 for (MSVehicleDevice* const dev : myDevices) {
2306 if (dev->deviceName() == deviceName) {
2307 return dev->getParameter(key);
2308 }
2309 }
2310 throw InvalidArgument(TLF("no device of type '%' exists", deviceName));
2311}
2312
2313
2314void
2315MSBaseVehicle::setDeviceParameter(const std::string& deviceName, const std::string& key, const std::string& value) {
2316 for (MSVehicleDevice* const dev : myDevices) {
2317 if (dev->deviceName() == deviceName) {
2318 dev->setParameter(key, value);
2319 return;
2320 }
2321 }
2322 throw InvalidArgument(TLF("no device of type '%' exists", deviceName));
2323}
2324
2325
2326void
2327MSBaseVehicle::setJunctionModelParameter(const std::string& key, const std::string& value) {
2330 const_cast<SUMOVehicleParameter&>(getParameter()).setParameter(key, value);
2331 // checked in MSLink::ignoreFoe
2332 } else {
2333 throw InvalidArgument(TLF("Vehicle '%' does not support junctionModel parameter '%'.", getID(), key));
2334 }
2335}
2336
2337
2338void
2339MSBaseVehicle::setCarFollowModelParameter(const std::string& key, const std::string& value) {
2340 // handle some generic params first and then delegate to the carFollowModel itself
2343 const_cast<SUMOVehicleParameter&>(getParameter()).setParameter(key, value);
2344 // checked in MSVehicle::planMove
2345 } else {
2346 MSVehicle* microVeh = dynamic_cast<MSVehicle*>(this);
2347 if (microVeh) {
2348 // remove 'carFollowModel.' prefix
2349 const std::string attrName = key.substr(15);
2350 microVeh->getCarFollowModel().setParameter(microVeh, attrName, value);
2351 }
2352 }
2353}
2354
2355
2356void
2358 /* Design idea for additional junction model parameters:
2359 We can distinguish between 3 levels of parameters
2360 1. typically shared by multiple vehicles -> vType parameter
2361 2. specific to one vehicle but stays constant throughout the simulation -> vehicle parameter
2362 3. specific to one vehicle and expected to change during simulation -> prefixed generic vehicle parameter
2363 */
2364 for (auto item : getParameter().getParametersMap()) {
2365 if (StringUtils::startsWith(item.first, "junctionModel.")) {
2366 setJunctionModelParameter(item.first, item.second);
2367 } else if (StringUtils::startsWith(item.first, "carFollowModel.")) {
2368 setCarFollowModelParameter(item.first, item.second);
2369 }
2370 }
2371 const std::string routingModeStr = getStringParam("device.rerouting.mode");
2372 try {
2373 int routingMode = StringUtils::toInt(routingModeStr);
2374 if (routingMode != libsumo::ROUTING_MODE_DEFAULT) {
2375 setRoutingMode(routingMode);
2376 }
2377 } catch (NumberFormatException&) {
2378 // @todo interpret symbolic constants
2379 throw ProcessError(TLF("could not interpret routing.mode '%'", routingModeStr));
2380 }
2381}
2382
2383
2392
2393
2394void
2396 assert(type != nullptr);
2397 // save old parameters before possible type deletion
2398 const double oldMu = myType->getSpeedFactor().getParameter()[0];
2399 const double oldDev = myType->getSpeedFactor().getParameter()[1];
2400 if (myType->isVehicleSpecific() && type != myType) {
2402 }
2403 // adapt myChosenSpeedFactor to the new type
2404 if (oldDev == 0.) {
2405 // old type had speedDev 0, reroll
2407 } else {
2408 // map old speedFactor onto new distribution
2409 const double distPoint = (myChosenSpeedFactor - oldMu) / oldDev;
2410 const double newMu = type->getSpeedFactor().getParameter()[0];
2411 const double newDev = type->getSpeedFactor().getParameter()[1];
2412 myChosenSpeedFactor = newMu + distPoint * newDev;
2413 // respect distribution limits
2416 }
2417 myType = type;
2418 if (myEnergyParams != nullptr) {
2420 }
2421}
2422
2423
2426 if (myType->isVehicleSpecific()) {
2427 return *myType;
2428 }
2429 MSVehicleType* type = myType->buildSingularType(myType->getID() + "@" + getID());
2430 replaceVehicleType(type);
2431 return *type;
2432}
2433
2434
2435int
2437 const MSLane* const lane = getLane();
2438 if (lane == nullptr) {
2439 return getEdge()->getLanes()[0]->getRNGIndex();
2440 } else {
2441 return lane->getRNGIndex();
2442 }
2443}
2444
2445
2446SumoRNG*
2448 const MSLane* lane = getLane();
2449 if (lane == nullptr) {
2450 return getEdge()->getLanes()[0]->getRNG();
2451 } else {
2452 return lane->getRNG();
2453 }
2454}
2455
2456std::string
2457MSBaseVehicle::getPrefixedParameter(const std::string& key, std::string& error) const {
2458 const MSVehicle* microVeh = dynamic_cast<const MSVehicle*>(this);
2459 if (StringUtils::startsWith(key, "device.")) {
2460 StringTokenizer tok(key, ".");
2461 if (tok.size() < 3) {
2462 error = TLF("Invalid device parameter '%' for vehicle '%'.", key, getID());
2463 return "";
2464 }
2465 try {
2466 return getDeviceParameter(tok.get(1), key.substr(tok.get(0).size() + tok.get(1).size() + 2));
2467 } catch (InvalidArgument& e) {
2468 error = TLF("Vehicle '%' does not support device parameter '%' (%).", getID(), key, e.what());
2469 return "";
2470 }
2471 } else if (StringUtils::startsWith(key, "laneChangeModel.")) {
2472 if (microVeh == nullptr) {
2473 error = TLF("Mesoscopic vehicle '%' does not support laneChangeModel parameters.", getID());
2474 return "";
2475 }
2476 const std::string attrName = key.substr(16);
2477 try {
2478 return microVeh->getLaneChangeModel().getParameter(attrName);
2479 } catch (InvalidArgument& e) {
2480 error = TLF("Vehicle '%' does not support laneChangeModel parameter '%' (%).", getID(), key, e.what());
2481 return "";
2482 }
2483 } else if (StringUtils::startsWith(key, "carFollowModel.")) {
2484 if (microVeh == nullptr) {
2485 error = TLF("Mesoscopic vehicle '%' does not support carFollowModel parameters.", getID());
2486 return "";
2487 }
2488 const std::string attrName = key.substr(15);
2489 try {
2490 return microVeh->getCarFollowModel().getParameter(microVeh, attrName);
2491 } catch (InvalidArgument& e) {
2492 error = TLF("Vehicle '%' does not support carFollowModel parameter '%' (%).", getID(), key, e.what());
2493 return "";
2494 }
2495 } else if (StringUtils::startsWith(key, "has.") && StringUtils::endsWith(key, ".device")) {
2496 StringTokenizer tok(key, ".");
2497 if (tok.size() != 3) {
2498 error = TL("Invalid check for device. Expected format is 'has.DEVICENAME.device'.");
2499 return "";
2500 }
2501 return hasDevice(tok.get(1)) ? "true" : "false";
2502 // parking related parameters start here
2503 } else if (key == "parking.rerouteCount") {
2505 } else if (StringUtils::startsWith(key, "parking.memory.")) {
2506 std::vector<std::string> values;
2507 if (getParkingMemory()) {
2508 if (key == "parking.memory.IDList") {
2509 for (const auto& item : *getParkingMemory()) {
2510 values.push_back(item.first->getID());
2511 }
2512 } else if (key == "parking.memory.score") {
2513 for (const auto& item : *getParkingMemory()) {
2514 values.push_back(item.second.score);
2515 }
2516 } else if (key == "parking.memory.blockedAtTime") {
2517 for (const auto& item : *getParkingMemory()) {
2518 values.push_back(toString(STEPS2TIME(item.second.blockedAtTime)));
2519 }
2520 } else if (key == "parking.memory.blockedAtTimeLocal") {
2521 for (const auto& item : *getParkingMemory()) {
2522 values.push_back(toString(STEPS2TIME(item.second.blockedAtTimeLocal)));
2523 }
2524 } else {
2525 error = TLF("Unsupported parking parameter '%' for vehicle '%'.", key, getID());
2526 }
2527 }
2528 return toString(values);
2529 } else {
2530 // default: custom user parameter
2531 return getParameter().getParameter(key, "");
2532 }
2533}
2534
2535
2536void
2543
2544
2545void
2551
2552
2553void
2555 if (myChargingMemory == nullptr) {
2557 }
2559}
2560
2561
2562void
2568
2569
2570void
2571MSBaseVehicle::rememberParkingAreaScore(const MSStoppingPlace* pa, const std::string& score) {
2572 if (myParkingMemory == nullptr) {
2574 }
2576}
2577
2578
2581 if (myParkingMemory == nullptr) {
2582 return -1;
2583 }
2584 return myParkingMemory->sawBlockedStoppingPlace(pa, local);
2585}
2586
2587
2594
2595
2598 if (myChargingMemory == nullptr) {
2599 return -1;
2600 }
2601 return myChargingMemory->sawBlockedStoppingPlace(cs, local);
2602}
2603
2604
2605#ifdef _DEBUG
2606void
2607MSBaseVehicle::initMoveReminderOutput(const OptionsCont& oc) {
2608 if (oc.isSet("movereminder-output.vehicles")) {
2609 const std::vector<std::string> vehicles = oc.getStringVector("movereminder-output.vehicles");
2610 myShallTraceMoveReminders.insert(vehicles.begin(), vehicles.end());
2611 }
2612}
2613
2614
2615void
2616MSBaseVehicle::traceMoveReminder(const std::string& type, MSMoveReminder* rem, double pos, bool keep) const {
2617 OutputDevice& od = OutputDevice::getDeviceByOption("movereminder-output");
2618 od.openTag("movereminder");
2619 od.writeAttr(SUMO_ATTR_TIME, STEPS2TIME(MSNet::getInstance()->getCurrentTimeStep()));
2620 od.writeAttr("veh", getID());
2622 od.writeAttr("type", type);
2623 od.writeAttr("pos", toString(pos));
2624 od.writeAttr("keep", toString(keep));
2625 od.closeTag();
2626}
2627#endif
2628
2629
2630/****************************************************************************/
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:296
#define WRITE_ERRORF(...)
Definition MsgHandler.h:305
#define WRITE_WARNING(msg)
Definition MsgHandler.h:295
#define TL(string)
Definition MsgHandler.h:315
#define TLF(string,...)
Definition MsgHandler.h:317
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:69
#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
bool isRailway(SVCPermissions permissions)
Returns whether an edge with the given permissions is a 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.
@ 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
@ CONTAINER_TRIGGERED
The departure is container triggered.
@ TRIGGERED
The departure is person triggered.
@ 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_TIME
trigger: the time of the step
int gPrecisionRandom
Definition StdDefs.cpp:28
const double INVALID_DOUBLE
invalid double
Definition StdDefs.h:64
#define UNUSED_PARAMETER(x)
Definition StdDefs.h:30
T MIN2(T a, T b)
Definition StdDefs.h:76
const double SUMO_const_haltingSpeed
the speed threshold at which vehicles are considered as halting
Definition StdDefs.h:58
T MAX2(T a, T b)
Definition StdDefs.h:82
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.
std::vector< double > & getParameter()
Returns the parameters 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
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.
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()
MSVehicleType * myType
This vehicle's type.
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)
double myDepartPos
The real depart position.
const SUMOVehicleParameter & getParameter() const
Returns the vehicle's parameter (including departure definition)
void addReminder(MSMoveReminder *rem)
Adds a MoveReminder dynamically.
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.
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.
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.
virtual void replaceVehicleType(MSVehicleType *type)
Replaces the current vehicle type by the one given.
const MSRouteIterator & getCurrentRouteEdge() const
Returns an iterator pointing to the current edge in this vehicles route.
bool isStoppedParking() const
Returns whether the vehicle is on a parking stop.
void unregisterWaiting()
mark vehicle as active
bool hasValidRoute(std::string &msg, ConstMSRoutePtr route=0) const
Validates the current or given route.
double getLength() const
Returns the vehicle's length.
bool isParking() const
Returns whether the vehicle is parking.
MSParkingArea * getCurrentParkingArea()
get the current parking area stop or nullptr
const MSEdge * getEdge() const
Returns the edge the vehicle is currently at.
double getHarmonoise_NoiseEmissions() const
Returns noise emissions of the current state.
int getPersonNumber() const
Returns the number of persons.
double getRelativeStateOfCharge() const
Returns actual relative state of charge of battery (-)
void setJunctionModelParameter(const std::string &key, const std::string &value)
set individual junction model paramete (not type related)
void setDepartAndArrivalEdge()
apply departEdge and arrivalEdge attributes
void setID(const std::string &newID)
set the id (inherited from Named but forbidden for vehicles)
MSRouteIterator myCurrEdge
Iterator to current route-edge.
static MSLane * interpretOppositeStop(SUMOVehicleParameter::Stop &stop)
interpret stop lane on opposite side of the road
static std::vector< MSTransportable * > myEmptyTransportableVector
const std::vector< std::string > & getParkingBadges() const
get the valid parking access rights (vehicle settings override vehicle type settings)
bool hasDeparted() const
Returns whether this vehicle has already departed.
MSStop & getNextStop()
bool ignoreTransientPermissions() const
Returns whether this object is ignoring transient permission changes (during routing)
ConstMSRoutePtr myRoute
This vehicle's route.
const ConstMSEdgeVector 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.
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
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.
@ 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)
std::vector< SUMOVehicleParameter::Stop > myPastStops
The list of stops that the vehicle has already reached.
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.
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:646
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:659
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 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:112
A road/street connecting two junctions.
Definition MSEdge.h:77
bool hasTransientPermissions() const
Definition MSEdge.cpp:1671
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:1340
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:479
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:685
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:1047
const MSEdge * getNormalBefore() const
if this edge is an internal edge, return its first normal predecessor, otherwise the edge itself
Definition MSEdge.cpp:937
MSLane * getFirstAllowed(SUMOVehicleClass vClass, bool defaultFirst=false) const
Definition MSEdge.cpp:726
A storage for edge travel times and efforts.
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 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:2391
double getLength() const
Returns the lane's length.
Definition MSLane.h:606
bool allowsVehicleClass(SUMOVehicleClass vclass) const
Definition MSLane.h:925
static bool dictionary(const std::string &id, MSLane *lane)
Static (sic!) container methods {.
Definition MSLane.cpp:2415
bool isInternal() const
Definition MSLane.cpp:2546
SumoRNG * getRNG() const
return the associated RNG
Definition MSLane.h:246
MSEdge & getEdge() const
Returns the lane's edge.
Definition MSLane.h:764
Something on a lane to be noticed about vehicle movement.
const std::string & getDescription() const
Notification
Definition of a vehicle state.
@ NOTIFICATION_DEPARTED
The vehicle has departed (was inserted into the network)
bool warnOnce(const std::string &typeAndID)
return whether a warning regarding the given object shall be issued
Definition MSNet.cpp:1636
@ NEWROUTE
The vehicle got a new route.
static MSNet * getInstance()
Returns the pointer to the unique instance of MSNet (singleton).
Definition MSNet.cpp:186
SUMOTime getCurrentTimeStep() const
Returns the current simulation step.
Definition MSNet.h:320
static bool hasInstance()
Returns whether the network was already constructed.
Definition MSNet.h:152
MSStoppingPlace * getStoppingPlace(const std::string &id, const SumoXMLTag category) const
Returns the named stopping place of the given category.
Definition MSNet.cpp:1381
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:1275
MSInsertionControl & getInsertionControl()
Returns the insertion control.
Definition MSNet.h:431
MSVehicleRouter & getRouterTT(const int rngIndex, const MSEdgeVector &prohibited=MSEdgeVector()) const
Definition MSNet.cpp:1508
MSVehicleControl & getVehicleControl()
Returns the vehicle control.
Definition MSNet.h:378
A lane area vehicles can halt at.
bool accepts(MSBaseVehicle *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 MSEdgeVector &prohibited=MSEdgeVector())
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 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.
bool hasVTypeDistribution(const std::string &id) const
Asks for a vehicle type distribution.
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.
int precision()
return precision set on the device
static OutputDevice & getDeviceByOption(const std::string &name)
Returns the device described by the option.
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:199
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
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
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 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,...
#define DEBUG_COND
TRACI_CONST int ROUTING_MODE_AGGREGATED
TRACI_CONST int ROUTING_MODE_DEFAULT
TRACI_CONST int ROUTING_MODE_IGNORE_TRANSIENT_PERMISSIONS