Eclipse SUMO - Simulation of Urban MObility
MSBaseVehicle.cpp
Go to the documentation of this file.
1/****************************************************************************/
2// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
3// Copyright (C) 2001-2022 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/****************************************************************************/
20// A base class for vehicle implementations
21/****************************************************************************/
22#include <config.h>
23
24#include <iostream>
25#include <cassert>
33#include <mesosim/MELoop.h>
34#include <mesosim/MEVehicle.h>
44#include "MSGlobals.h"
45#include "MSVehicleControl.h"
46#include "MSVehicleType.h"
47#include "MSEdge.h"
48#include "MSLane.h"
49#include "MSMoveReminder.h"
51#include "MSNet.h"
52#include "MSStop.h"
53#include "MSParkingArea.h"
54#include "MSInsertionControl.h"
55#include "MSBaseVehicle.h"
56
57//#define DEBUG_REROUTE
58//#define DEBUG_ADD_STOP
59//#define DEBUG_COND (getID() == "")
60//#define DEBUG_COND (true)
61//#define DEBUG_REPLACE_ROUTE
62#define DEBUG_COND (isSelected())
63
64// ===========================================================================
65// static members
66// ===========================================================================
68std::vector<MSTransportable*> MSBaseVehicle::myEmptyTransportableVector;
69#ifdef _DEBUG
70std::set<std::string> MSBaseVehicle::myShallTraceMoveReminders;
71#endif
73
74// ===========================================================================
75// Influencer method definitions
76// ===========================================================================
77
79 myRoutingMode(libsumo::ROUTING_MODE_DEFAULT)
80{}
81
84 if (myRoutingMode == libsumo::ROUTING_MODE_AGGREGATED) {
85 return MSRoutingEngine::getRouterTT(rngIndex, svc);
86 } else {
87 return MSNet::getInstance()->getRouterTT(rngIndex);
88 }
89}
90
91
92
93// ===========================================================================
94// method definitions
95// ===========================================================================
96
97double
99 throw ProcessError("getPreviousSpeed() is not available for non-MSVehicles.");
100}
101
102
104 MSVehicleType* type, const double speedFactor) :
105 SUMOVehicle(pars->id),
106 myParameter(pars),
107 myRoute(route),
108 myType(type),
109 myCurrEdge(route->begin()),
110 myChosenSpeedFactor(pars->speedFactor < 0 ? speedFactor : pars->speedFactor),
112 myPersonDevice(nullptr),
113 myContainerDevice(nullptr),
114 myEnergyParams(nullptr),
116 myDepartPos(-1),
117 myArrivalPos(-1),
118 myArrivalLane(-1),
121 myOdometer(0.),
124 myEdgeWeights(nullptr)
125#ifdef _DEBUG
126 , myTraceMoveReminders(myShallTraceMoveReminders.count(pars->id) > 0)
127#endif
128{
129 if ((*myRoute->begin())->isTazConnector() || myRoute->getLastEdge()->isTazConnector()) {
131 }
133 if ((pars->parametersSet & VEHPARS_FORCE_REROUTE) == 0) {
135 }
136 if (!pars->wasSet(VEHPARS_FORCE_REROUTE)) {
138 }
140}
141
142
144 delete myEdgeWeights;
145 myRoute->release();
146 if (myParameter->repetitionNumber == 0) {
148 }
149 for (MSVehicleDevice* dev : myDevices) {
150 delete dev;
151 }
152 delete myParameter;
153 delete myEnergyParams;
154 delete myParkingMemory;
155}
156
157
158void
161 for (MSVehicleDevice* dev : myDevices) {
162 myMoveReminders.push_back(std::make_pair(dev, 0.));
163 }
165 // ensure we have the emission parameters even if we don't have the device
167 }
168}
169
170
171void
172MSBaseVehicle::setID(const std::string& /*newID*/) {
173 throw ProcessError("Changing a vehicle ID is not permitted");
174}
175
178 return *myParameter;
179}
180
181
182void
184 delete myParameter;
185 myParameter = newParameter;
186}
187
188double
191}
192
193
194const MSEdge*
195MSBaseVehicle::succEdge(int nSuccs) const {
196 if (myCurrEdge + nSuccs < myRoute->end() && std::distance(myCurrEdge, myRoute->begin()) <= nSuccs) {
197 return *(myCurrEdge + nSuccs);
198 } else {
199 return nullptr;
200 }
201}
202
203
204const MSEdge*
206 return *myCurrEdge;
207}
208
209
210void
211MSBaseVehicle::reroute(SUMOTime t, const std::string& info, SUMOAbstractRouter<MSEdge, SUMOVehicle>& router, const bool onInit, const bool withTaz, const bool silent) {
212 // check whether to reroute
213 const MSEdge* source = withTaz && onInit ? MSEdge::dictionary(myParameter->fromTaz + "-source") : getRerouteOrigin();
214 if (source == nullptr) {
215 source = getRerouteOrigin();
216 }
217 const MSEdge* sink = withTaz ? MSEdge::dictionary(myParameter->toTaz + "-sink") : myRoute->getLastEdge();
218 if (sink == nullptr) {
219 sink = myRoute->getLastEdge();
220 }
221 ConstMSEdgeVector oldEdgesRemaining(source == *myCurrEdge ? myCurrEdge : myCurrEdge + 1, myRoute->end());
222 ConstMSEdgeVector edges;
223 ConstMSEdgeVector stops;
224 if (myParameter->via.size() == 0) {
225 double firstPos = -1;
226 double lastPos = -1;
227 stops = getStopEdges(firstPos, lastPos);
228 if (stops.size() > 0) {
229 const double sourcePos = onInit ? 0 : getPositionOnLane();
230 // avoid superfluous waypoints for first and last edge
231 const bool skipFirst = stops.front() == source && (source != getEdge() || sourcePos + getBrakeGap() <= firstPos);
232 const bool skipLast = stops.back() == sink && myArrivalPos >= lastPos && (
233 stops.size() < 2 || stops.back() != stops[stops.size() - 2]);
234#ifdef DEBUG_REROUTE
235 if (DEBUG_COND) {
236 std::cout << SIMTIME << " reroute " << info << " veh=" << getID() << " lane=" << Named::getIDSecure(getLane())
237 << " source=" << source->getID() << " sourcePos=" << sourcePos << " firstPos=" << firstPos << " arrivalPos=" << myArrivalPos << " lastPos=" << lastPos
238 << " route=" << toString(myRoute->getEdges()) << " stopEdges=" << toString(stops) << " skipFirst=" << skipFirst << " skipLast=" << skipLast << "\n";
239 }
240#endif
241 if (stops.size() == 1 && (skipFirst || skipLast)) {
242 stops.clear();
243 } else {
244 if (skipFirst) {
245 stops.erase(stops.begin());
246 }
247 if (skipLast) {
248 stops.erase(stops.end() - 1);
249 }
250 }
251 }
252 } else {
253 // via takes precedence over stop edges
254 // there is a consistency check in MSRouteHandler::addStop that warns when a stop edge is not part of the via edges
255 for (std::vector<std::string>::const_iterator it = myParameter->via.begin(); it != myParameter->via.end(); ++it) {
256 MSEdge* viaEdge = MSEdge::dictionary(*it);
257 if (viaEdge == source || viaEdge == sink) {
258 continue;
259 }
260 assert(viaEdge != 0);
261 if (!viaEdge->isTazConnector() && viaEdge->allowedLanes(getVClass()) == nullptr) {
262 throw ProcessError(TLF("Vehicle '%' is not allowed on any lane of via edge '%'.", getID(), viaEdge->getID()));
263 }
264 stops.push_back(viaEdge);
265 }
266 }
267
268 for (const MSEdge* const stopEdge : stops) {
269 // !!! need to adapt t here
271 router.computeLooped(source, stopEdge, this, t, into, silent);
272 //std::cout << SIMTIME << " reroute veh=" << getID() << " source=" << source->getID() << " target=" << (*s)->getID() << " edges=" << toString(into) << "\n";
273 if (into.size() > 0) {
274 into.pop_back();
275 edges.insert(edges.end(), into.begin(), into.end());
276 if (stopEdge->isTazConnector()) {
277 source = into.back();
278 edges.pop_back();
279 } else {
280 source = stopEdge;
281 }
282 } else {
283 std::string error = TLF("Vehicle '%' has no valid route from edge '%' to stop edge '%'.", getID(), source->getID(), stopEdge->getID());
284 if (MSGlobals::gCheckRoutes || silent) {
285 throw ProcessError(error);
286 } else {
287 WRITE_WARNING(error);
288 edges.push_back(source);
289 }
290 source = stopEdge;
291 }
292 }
293 if (stops.empty() && source == sink && onInit
297 router.computeLooped(source, sink, this, t, edges, silent);
298 } else {
299 if (!router.compute(source, sink, this, t, edges, silent)) {
300 edges.clear();
301 }
302 }
303
304 // router.setHint(myCurrEdge, myRoute->end(), this, t);
305 if (edges.empty() && silent) {
306 return;
307 }
308 if (!edges.empty() && edges.front()->isTazConnector()) {
309 edges.erase(edges.begin());
310 }
311 if (!edges.empty() && edges.back()->isTazConnector()) {
312 edges.pop_back();
313 }
314 const double routeCost = router.recomputeCosts(edges, this, t);
315 const double previousCost = onInit ? routeCost : router.recomputeCosts(oldEdgesRemaining, this, t);
316 const double savings = previousCost - routeCost;
317 //if (getID() == "43") std::cout << SIMTIME << " pCost=" << previousCost << " cost=" << routeCost
318 // << " onInit=" << onInit
319 // << " prevEdges=" << toString(oldEdgesRemaining)
320 // << " newEdges=" << toString(edges)
321 // << "\n";
322 replaceRouteEdges(edges, routeCost, savings, info, onInit);
323 // this must be called even if the route could not be replaced
324 if (onInit) {
325 if (edges.empty()) {
327 throw ProcessError(TLF("Vehicle '%' has no valid route.", getID()));
328 } else if (source->isTazConnector()) {
329 WRITE_WARNINGF(TL("Removing vehicle '%' which has no valid route."), getID());
331 return;
332 }
333 }
336 }
337}
338
339
340bool
341MSBaseVehicle::replaceRouteEdges(ConstMSEdgeVector& edges, double cost, double savings, const std::string& info, bool onInit, bool check, bool removeStops, std::string* msgReturn) {
342 if (edges.empty()) {
343 WRITE_WARNINGF(TL("No route for vehicle '%' found."), getID());
344 if (msgReturn != nullptr) {
345 *msgReturn = "No route found";
346 }
347 return false;
348 }
349 // build a new id, first
350 std::string id = getID();
351 if (id[0] != '!') {
352 id = "!" + id;
353 }
354 const std::string idSuffix = id + "!var#";
355 int varIndex = 1;
356 id = idSuffix + toString(varIndex);
357 while (MSRoute::hasRoute(id)) {
358 id = idSuffix + toString(++varIndex);
359 }
360 int oldSize = (int)edges.size();
361 if (!onInit) {
362 const MSEdge* const origin = getRerouteOrigin();
363 if (origin != *myCurrEdge && edges.front() == origin) {
364 edges.insert(edges.begin(), *myCurrEdge);
365 oldSize = (int)edges.size();
366 }
367 edges.insert(edges.begin(), myRoute->begin(), myCurrEdge);
368 }
370 // re-assign stop iterators when rerouting to a new parkingArea
371 return true;
372 }
373 const RGBColor& c = myRoute->getColor();
374 MSRoute* newRoute = new MSRoute(id, edges, false, &c == &RGBColor::DEFAULT_COLOR ? nullptr : new RGBColor(c), std::vector<SUMOVehicleParameter::Stop>());
375 newRoute->setCosts(cost);
376 newRoute->setSavings(savings);
377 if (!MSRoute::dictionary(id, newRoute)) {
378 delete newRoute;
379 if (msgReturn != nullptr) {
380 *msgReturn = "duplicate routeID '" + id + "'";
381 }
382 return false;
383 }
384
385 std::string msg;
386 if (check && !hasValidRoute(msg, newRoute)) {
387 WRITE_WARNINGF(TL("Invalid route replacement for vehicle '%'. %"), getID(), msg);
389 newRoute->addReference();
390 newRoute->release();
391 if (msgReturn != nullptr) {
392 *msgReturn = msg;
393 }
394 return false;
395 }
396 }
397 if (!replaceRoute(newRoute, info, onInit, (int)edges.size() - oldSize, false, removeStops, msgReturn)) {
398 newRoute->addReference();
399 newRoute->release();
400 return false;
401 }
402 return true;
403}
404
405
406bool
407MSBaseVehicle::replaceRoute(const MSRoute* newRoute, const std::string& info, bool onInit, int offset, bool addRouteStops, bool removeStops, std::string* msgReturn) {
408 const ConstMSEdgeVector& edges = newRoute->getEdges();
409 // rebuild in-vehicle route information
410 if (onInit) {
411 myCurrEdge = newRoute->begin();
412 } else {
413 MSRouteIterator newCurrEdge = std::find(edges.begin() + offset, edges.end(), *myCurrEdge);
414 if (newCurrEdge == edges.end()) {
415 if (msgReturn != nullptr) {
416 *msgReturn = TLF("current edge '%' not found in new route", (*myCurrEdge)->getID());
417 }
418#ifdef DEBUG_REPLACE_ROUTE
419 if (DEBUG_COND) {
420 std::cout << " newCurrEdge not found\n";
421 }
422#endif
423 return false;
424 }
425 if (getLane() != nullptr) {
426 if (getLane()->getEdge().isInternal() && (
427 (newCurrEdge + 1) == edges.end() || (*(newCurrEdge + 1)) != &(getLane()->getOutgoingViaLanes().front().first->getEdge()))) {
428 if (msgReturn != nullptr) {
429 *msgReturn = TL("Vehicle is on junction-internal edge leading elsewhere");
430 }
431#ifdef DEBUG_REPLACE_ROUTE
432 if (DEBUG_COND) {
433 std::cout << " Vehicle is on junction-internal edge leading elsewhere\n";
434 }
435#endif
436 return false;
437 } else if (getPositionOnLane() > getLane()->getLength()
438 && (myCurrEdge + 1) != myRoute->end()
439 && (newCurrEdge + 1) != edges.end()
440 && *(myCurrEdge + 1) != *(newCurrEdge + 1)) {
441 if (msgReturn != nullptr) {
442 *msgReturn = TL("Vehicle is moving past junction and committed to move to another successor edge");
443 }
444#ifdef DEBUG_REPLACE_ROUTE
445 if (DEBUG_COND) {
446 std::cout << " Vehicle is moving past junction and committed to move to another successor edge\n";
447 }
448#endif
449 return false;
450 }
451 }
452 myCurrEdge = newCurrEdge;
453 }
454 const bool stopsFromScratch = onInit && myRoute->getStops().empty();
455 // check whether the old route may be deleted (is not used by anyone else)
456 newRoute->addReference();
457 myRoute->release();
458 // assign new route
459 myRoute = newRoute;
460 // update arrival definition
462 // save information that the vehicle was rerouted
466#ifdef DEBUG_REPLACE_ROUTE
467 if (DEBUG_COND) {
468 std::cout << SIMTIME << " replaceRoute info=" << info << " on " << (*myCurrEdge)->getID()
469 << " lane=" << Named::getIDSecure(getLane())
470 << " stopsFromScratch=" << stopsFromScratch
471 << " newSize=" << newRoute->getEdges().size()
472 << " newIndex=" << (myCurrEdge - newRoute->begin())
473 << " edges=" << toString(newRoute->getEdges())
474 << "\n";
475 }
476#endif
477 // if we did not drive yet it may be best to simply reassign the stops from scratch
478 if (stopsFromScratch) {
479 myStops.clear();
481 } else {
482 // recheck old stops
483 MSRouteIterator searchStart = myCurrEdge;
484 double lastPos = getPositionOnLane() + getBrakeGap();
485 if (getLane() != nullptr && getLane()->isInternal()
486 && myStops.size() > 0 && !myStops.front().lane->isInternal()) {
487 // searchStart is still incoming to the intersection so lastPos
488 // relative to that edge must be adapted
489 lastPos += (*myCurrEdge)->getLength();
490 }
491 for (std::list<MSStop>::iterator iter = myStops.begin(); iter != myStops.end();) {
492 double endPos = iter->getEndPos(*this);
493#ifdef DEBUG_REPLACE_ROUTE
494 if (DEBUG_COND) {
495 std::cout << " stopEdge=" << iter->lane->getEdge().getID() << " start=" << (searchStart - myCurrEdge) << " endPos=" << endPos << " lastPos=" << lastPos << "\n";
496 }
497#endif
498 if (*searchStart != &iter->lane->getEdge()
499 || endPos + NUMERICAL_EPS < lastPos) {
500 if (searchStart != edges.end() && !iter->reached) {
501 searchStart++;
502 }
503 }
504 lastPos = endPos;
505
506 iter->edge = std::find(searchStart, edges.end(), &iter->lane->getEdge());
507#ifdef DEBUG_REPLACE_ROUTE
508 if (DEBUG_COND) {
509 std::cout << " foundIndex=" << (iter->edge - myCurrEdge) << " end=" << (edges.end() - myCurrEdge) << "\n";
510 }
511#endif
512 if (iter->edge == edges.end()) {
513 if (!removeStops) {
514 WRITE_ERRORF(TL("Vehicle '%' could not assign stop '%' after rerouting (%) at time=%."), getID(), iter->getDescription(), info, time2string(SIMSTEP));
515 }
516 iter = myStops.erase(iter);
517 continue;
518 } else {
519 searchStart = iter->edge;
520 }
521 ++iter;
522 }
523 // add new stops
524 if (addRouteStops) {
525 for (std::vector<SUMOVehicleParameter::Stop>::const_iterator i = newRoute->getStops().begin(); i != newRoute->getStops().end(); ++i) {
526 std::string error;
528 if (error != "") {
529 WRITE_WARNING(error);
530 }
531 }
532 }
533 }
534 return true;
535}
536
537
538double
540 return 0;
541}
542
543
544void
549}
550
551
554 const SUMOTime dep = getParameter().depart;
555 if (dep < 0) {
556 return 0;
557 }
558 return hasDeparted() ? getDeparture() - dep : SIMSTEP - dep;
559}
560
561
562bool
564 return succEdge(1) == nullptr;
565}
566
567
568int
570 return (int) std::distance(myRoute->begin(), myCurrEdge);
571}
572
573
574void
576 myCurrEdge = myRoute->begin() + index;
577 const_cast<SUMOVehicleParameter*>(myParameter)->departLaneProcedure = departLaneProcedure;
578 // !!! hack
579 myArrivalPos = (*(myRoute->end() - 1))->getLanes()[0]->getLength();
580}
581
582double
585}
586
587bool
589 if (t->isPerson() && getPersonNumber() >= getVehicleType().getPersonCapacity()) {
590 return false;
591 } else if (!t->isPerson() && getContainerNumber() >= getVehicleType().getContainerCapacity()) {
592 return false;
593 }
594 if (isStopped() && myStops.begin()->pars.permitted.size() > 0
595 && myStops.begin()->pars.permitted.count(t->getID()) == 0) {
596 return false;
597 }
598 MSDevice_Taxi* taxiDevice = static_cast<MSDevice_Taxi*>(getDevice(typeid(MSDevice_Taxi)));
599 if (taxiDevice != nullptr) {
600 return taxiDevice->allowsBoarding(t);
601 }
602 return true;
603}
604
605
606void
608 if (transportable->isPerson()) {
609 if (myPersonDevice == nullptr) {
611 myMoveReminders.push_back(std::make_pair(myPersonDevice, 0.));
614 }
615 }
616 myPersonDevice->addTransportable(transportable);
617 } else {
618 if (myContainerDevice == nullptr) {
620 myMoveReminders.push_back(std::make_pair(myContainerDevice, 0.));
623 }
624 }
625 myContainerDevice->addTransportable(transportable);
626 }
627}
628
629
630bool
631MSBaseVehicle::hasValidRoute(std::string& msg, const MSRoute* route) const {
633 if (route == nullptr) {
634 route = myRoute;
635 } else {
636 start = route->begin();
637 }
638 MSRouteIterator last = route->end() - 1;
639 // check connectivity, first
640 for (MSRouteIterator e = start; e != last; ++e) {
641 if ((*e)->allowedLanes(**(e + 1), myType->getVehicleClass()) == nullptr) {
642 msg = TLF("No connection between edge '%' and edge '%'.", (*e)->getID(), (*(e + 1))->getID());
643 return false;
644 }
645 }
646 last = route->end();
647 // check usable lanes, then
648 for (MSRouteIterator e = start; e != last; ++e) {
649 if ((*e)->prohibits(this)) {
650 msg = TLF("Edge '%' prohibits.", (*e)->getID());
651 return false;
652 }
653 }
654 return true;
655}
656
657
658bool
660 if (myRoute->getEdges().size() > 0 && !(*myCurrEdge)->prohibits(this)) {
661 myRouteValidity &= ~ROUTE_START_INVALID_PERMISSIONS;
662 return true;
663 } else {
664 msg = TLF("Vehicle '%' is not allowed to depart on its first edge.", getID());
666 return false;
667 }
668}
669
670
671int
672MSBaseVehicle::getRouteValidity(bool update, bool silent, std::string* msgReturn) {
673 if (!update) {
674 return myRouteValidity;
675 }
676 // insertion check must be done in any case
677 std::string msg;
678 if (!hasValidRouteStart(msg)) {
680 throw ProcessError(msg);
681 } else if (!silent) {
682 // vehicle will be discarded
683 WRITE_WARNING(msg);
684 } else if (msgReturn != nullptr) {
685 *msgReturn = msg;
686 }
687 }
690 // we could check after the first rerouting
692 if (!hasValidRoute(msg, myRoute)) {
694 throw ProcessError(TLF("Vehicle '%' has no valid route. %", getID(), msg));
695 }
696 }
697 myRouteValidity &= ~ROUTE_UNCHECKED;
698 return myRouteValidity;
699}
700
701void
703#ifdef _DEBUG
704 if (myTraceMoveReminders) {
705 traceMoveReminder("add", rem, 0, true);
706 }
707#endif
708 myMoveReminders.push_back(std::make_pair(rem, 0.));
709}
710
711
712void
714 for (MoveReminderCont::iterator r = myMoveReminders.begin(); r != myMoveReminders.end(); ++r) {
715 if (r->first == rem) {
716#ifdef _DEBUG
717 if (myTraceMoveReminders) {
718 traceMoveReminder("remove", rem, 0, false);
719 }
720#endif
721 myMoveReminders.erase(r);
722 return;
723 }
724 }
725}
726
727
728void
730 for (MoveReminderCont::iterator rem = myMoveReminders.begin(); rem != myMoveReminders.end();) {
731 if (rem->first->notifyEnter(*this, reason, enteredLane)) {
732#ifdef _DEBUG
733 if (myTraceMoveReminders) {
734 traceMoveReminder("notifyEnter", rem->first, rem->second, true);
735 }
736#endif
737 ++rem;
738 } else {
739#ifdef _DEBUG
740 if (myTraceMoveReminders) {
741 traceMoveReminder("notifyEnter", rem->first, rem->second, false);
742 }
743#endif
744 rem = myMoveReminders.erase(rem);
745 }
746 }
747}
748
749
750void
753 return;
754 }
755 const int arrivalEdgeIndex = MIN2(myParameter->arrivalEdge, (int)myRoute->getEdges().size() - 1);
756 if (arrivalEdgeIndex != myParameter->arrivalEdge) {
757 WRITE_WARNINGF(TL("Vehicle '%' ignores attribute arrivalEdge=% after rerouting at time=% (routeLength=%)"),
759 }
760 const MSEdge* arrivalEdge = myParameter->arrivalEdge >= 0 ? myRoute->getEdges()[arrivalEdgeIndex] : myRoute->getLastEdge();
761 if (!onInit) {
762 arrivalEdge = myRoute->getLastEdge();
763 // ignore arrivalEdge parameter after rerouting
764 const_cast<SUMOVehicleParameter*>(myParameter)->arrivalEdge = -1;
765 }
766 const std::vector<MSLane*>& lanes = arrivalEdge->getLanes();
767 const double lastLaneLength = lanes[0]->getLength();
770 if (fabs(myParameter->arrivalPos) > lastLaneLength) {
771 WRITE_WARNING("Vehicle '" + getID() + "' will not be able to arrive at the given position!");
772 }
773 // Maybe we should warn the user about invalid inputs!
774 myArrivalPos = MIN2(myParameter->arrivalPos, lastLaneLength);
775 if (myArrivalPos < 0) {
776 myArrivalPos = MAX2(myArrivalPos + lastLaneLength, 0.);
777 }
778 break;
780 myArrivalPos = RandHelper::rand(lastLaneLength);
781 break;
783 myArrivalPos = lastLaneLength / 2.;
784 break;
785 default:
786 myArrivalPos = lastLaneLength;
787 break;
788 }
790 if (myParameter->arrivalLane >= (int)lanes.size() || !lanes[myParameter->arrivalLane]->allowsVehicleClass(myType->getVehicleClass())) {
791 WRITE_WARNING("Vehicle '" + getID() + "' will not be able to arrive at the given lane '" + arrivalEdge->getID() + "_" + toString(myParameter->arrivalLane) + "'!");
792 }
793 myArrivalLane = MIN2(myParameter->arrivalLane, (int)(lanes.size() - 1));
795 myArrivalLane = -1;
796 for (MSLane* lane : lanes) {
797 if (lane->allowsVehicleClass(myType->getVehicleClass())) {
798 myArrivalLane = lane->getIndex();
799 break;
800 }
801 }
802 if (myArrivalLane == -1) {
803 WRITE_WARNING("Vehicle '" + getID() + "' has no usable arrivalLane on edge '" + arrivalEdge->getID() + "'.");
804 myArrivalLane = 0;
805 }
807 // pick random lane among all usable lanes
808 std::vector<MSLane*> usable;
809 for (MSLane* lane : lanes) {
810 if (lane->allowsVehicleClass(myType->getVehicleClass())) {
811 usable.push_back(lane);
812 }
813 }
814 if (usable.empty()) {
815 WRITE_WARNING("Vehicle '" + getID() + "' has no usable arrivalLane on edge '" + arrivalEdge->getID() + "'.");
816 myArrivalLane = 0;
817 } else {
818 myArrivalLane = usable[RandHelper::rand(0, (int)usable.size())]->getIndex();
819 }
820 }
822 for (std::vector<MSLane*>::const_iterator l = lanes.begin(); l != lanes.end(); ++l) {
823 if (myParameter->arrivalSpeed <= (*l)->getVehicleMaxSpeed(this)) {
824 return;
825 }
826 }
827 WRITE_WARNING("Vehicle '" + getID() + "' will not be able to arrive with the given speed!");
828 }
829}
830
831void
835 const int routeEdges = (int)myRoute->getEdges().size();
837 // write specific edge in vehroute output for reproducibility
838 pars->departEdge = RandHelper::rand(0, routeEdges);
840 }
841 assert(pars->departEdge >= 0);
842 if (pars->departEdge >= routeEdges) {
843 WRITE_WARNING("Ignoring departEdge " + toString(pars->departEdge) + " for vehicle '" + getID() + " with " + toString(routeEdges) + " route edges");
844 } else {
845 myCurrEdge += pars->departEdge;
846 }
847 }
849 const int routeEdges = (int)myRoute->getEdges().size();
850 const int begin = (int)(myCurrEdge - myRoute->begin());
851 // write specific edge in vehroute output for reproducibility
852 pars->arrivalEdge = RandHelper::rand(begin, routeEdges);
854 assert(pars->arrivalEdge >= begin);
855 assert(pars->arrivalEdge < routeEdges);
856 }
857}
858
859
860double
862 return MAX2(0., MIN2(1., getVehicleType().getImpatience() +
864}
865
866
868MSBaseVehicle::getDevice(const std::type_info& type) const {
869 for (MSVehicleDevice* const dev : myDevices) {
870 if (typeid(*dev) == type) {
871 return dev;
872 }
873 }
874 return nullptr;
875}
876
877
878void
880 // the parameters may hold the name of a vTypeDistribution but we are interested in the actual type
883 // params and stops must be written in child classes since they may wish to add additional attributes first
885 std::ostringstream os;
886 os << myOdometer << " " << myNumberReroutes;
887 out.writeAttr(SUMO_ATTR_DISTANCE, os.str());
889 const int precision = out.precision();
890 out.setPrecision(MAX2(gPrecisionRandom, precision));
892 out.setPrecision(precision);
893 }
895 out.writeAttr(SUMO_ATTR_REROUTE, true);
896 }
898 // could be set from stop
900 }
901 // here starts the vehicle internal part (see loading)
902 // @note: remember to close the vehicle tag when calling this in a subclass!
903}
904
905
906bool
907MSBaseVehicle::handleCollisionStop(MSStop& stop, const double distToStop) {
908 UNUSED_PARAMETER(stop);
909 UNUSED_PARAMETER(distToStop);
910 return true;
911}
912
913
914bool
916 return !myStops.empty() && myStops.begin()->reached /*&& myState.mySpeed < SUMO_const_haltingSpeed @todo #1864#*/;
917}
918
919
920bool
922 return isStopped() && (myStops.begin()->pars.parking == ParkingType::OFFROAD) && (
923 myStops.begin()->parkingarea == nullptr || !myStops.begin()->parkingarea->parkOnRoad());
924}
925
926
927bool
929 return isStopped() && (myStops.begin()->triggered || myStops.begin()->containerTriggered || myStops.begin()->joinTriggered);
930}
931
932
933bool
935 return isStopped() && (myStops.begin()->pars.parking == ParkingType::OFFROAD);
936}
937
938
939bool
940MSBaseVehicle::isStoppedInRange(const double pos, const double tolerance, bool checkFuture) const {
941 if (isStopped() || (checkFuture && hasStops())) {
942 const MSStop& stop = myStops.front();
943 return stop.pars.startPos - tolerance <= pos && stop.pars.endPos + tolerance >= pos;
944 }
945 return false;
946}
947
948
949double
950MSBaseVehicle::basePos(const MSEdge* edge) const {
951 double result = MIN2(getVehicleType().getLength() + POSITION_EPS, edge->getLength());
952 if (hasStops()
953 && myStops.front().edge == myRoute->begin()
954 && (&myStops.front().lane->getEdge()) == *myStops.front().edge) {
955 result = MIN2(result, MAX2(0.0, myStops.front().getEndPos(*this)));
956 }
957 return result;
958}
959
960MSLane*
962 const std::string edgeID = SUMOXMLDefinitions::getEdgeIDFromLane(stop.lane);
963 const int laneIndex = SUMOXMLDefinitions::getIndexFromLane(stop.lane);
964 const MSEdge* edge = MSEdge::dictionary(edgeID);
965 if (edge != nullptr && edge->getOppositeEdge() != nullptr
966 && laneIndex < (edge->getNumLanes() + edge->getOppositeEdge()->getNumLanes())) {
967 const int oppositeIndex = edge->getOppositeEdge()->getNumLanes() + edge->getNumLanes() - 1 - laneIndex;
968 stop.edge = edgeID;
969 return edge->getOppositeEdge()->getLanes()[oppositeIndex];
970 } else {
971 return nullptr;
972 }
973}
974
975bool
976MSBaseVehicle::addStop(const SUMOVehicleParameter::Stop& stopPar, std::string& errorMsg, SUMOTime untilOffset,
977 MSRouteIterator* searchStart) {
978 MSStop stop(stopPar);
979 if (stopPar.lane == "") {
980 // use rightmost allowed lane
981 MSEdge* e = MSEdge::dictionary(stopPar.edge);
982 for (MSLane* cand : e->getLanes()) {
983 if (cand->allowsVehicleClass(getVClass())) {
984 stop.lane = cand;
985 break;
986 }
987 }
988 if (stop.lane == nullptr) {
989 errorMsg = "Vehicle '" + myParameter->id + "' is not allowed to stop on any lane of edge '" + stopPar.edge + "'.";
990 return false;
991 }
992 } else {
993 stop.lane = MSLane::dictionary(stopPar.lane);
994 if (stop.lane == nullptr) {
995 // must be an opposite stop
996 SUMOVehicleParameter::Stop tmp = stopPar;
997 stop.lane = interpretOppositeStop(tmp);
998 assert(stop.lane != nullptr);
999 }
1001 errorMsg = "Vehicle '" + myParameter->id + "' is not allowed to stop on lane '" + stopPar.lane + "'.";
1002 return false;
1003 }
1004 }
1006 stop.segment = MSGlobals::gMesoNet->getSegmentForEdge(stop.lane->getEdge(), stop.getEndPos(*this));
1007 if (stop.lane->isInternal()) {
1008 errorMsg = "Mesoscopic simulation does not allow stopping on internal edge '" + stopPar.edge + "' for vehicle '" + myParameter->id + "'.";
1009 return false;
1010 }
1011 }
1012 stop.initPars(stopPar);
1013 if (stopPar.until != -1) {
1014 // !!! it would be much cleaner to invent a constructor for stops which takes "until" as an argument
1015 const_cast<SUMOVehicleParameter::Stop&>(stop.pars).until += untilOffset;
1016 }
1017 if (stopPar.arrival != -1) {
1018 const_cast<SUMOVehicleParameter::Stop&>(stop.pars).arrival += untilOffset;
1019 }
1020 std::string stopType = "stop";
1021 std::string stopID = "";
1022 if (stop.busstop != nullptr) {
1023 stopType = "busStop";
1024 stopID = stop.busstop->getID();
1025 } else if (stop.containerstop != nullptr) {
1026 stopType = "containerStop";
1027 stopID = stop.containerstop->getID();
1028 } else if (stop.chargingStation != nullptr) {
1029 stopType = "chargingStation";
1030 stopID = stop.chargingStation->getID();
1031 } else if (stop.overheadWireSegment != nullptr) {
1032 stopType = "overheadWireSegment";
1033 stopID = stop.overheadWireSegment->getID();
1034 } else if (stop.parkingarea != nullptr) {
1035 stopType = "parkingArea";
1036 stopID = stop.parkingarea->getID();
1037 }
1038 const std::string errorMsgStart = stopID == "" ? stopType : stopType + " '" + stopID + "'";
1039
1040 if (stop.pars.startPos < 0 || stop.pars.endPos > stop.lane->getLength()) {
1041 errorMsg = errorMsgStart + " for vehicle '" + myParameter->id + "' on lane '" + stop.lane->getID() + "' has an invalid position.";
1042 return false;
1043 }
1044 if (stopType != "stop" && stopType != "parkingArea" && myType->getLength() / 2. > stop.pars.endPos - stop.pars.startPos
1045 && MSNet::getInstance()->warnOnce(stopType + ":" + stopID)) {
1046 errorMsg = errorMsgStart + " on lane '" + stop.lane->getID() + "' is too short for vehicle '" + myParameter->id + "'.";
1047 }
1048 const MSEdge* stopLaneEdge = &stop.lane->getEdge();
1049 const MSEdge* stopEdge;
1050 if (stopLaneEdge->getOppositeEdge() != nullptr && stopLaneEdge->getOppositeEdge()->getID() == stopPar.edge) {
1051 // stop lane is on the opposite side
1052 stopEdge = stopLaneEdge->getOppositeEdge();
1053 stop.isOpposite = true;
1054 } else {
1055 // if stop is on an internal edge the normal edge before the intersection is used
1056 stopEdge = stopLaneEdge->getNormalBefore();
1057 }
1058 MSRouteIterator succ = myCurrEdge + 1; // we're using the address but only within the scope of this function (and recursive calls)
1059 if (searchStart == nullptr) {
1060 searchStart = &myCurrEdge;
1061 if (stopLaneEdge->isNormal() && getLane() != nullptr && getLane()->isInternal()) {
1062 // already on the intersection but myCurrEdge is before it
1063 searchStart = &succ;
1064 }
1065 }
1066#ifdef DEBUG_ADD_STOP
1067 if (DEBUG_COND) {
1068 std::cout << "addStop desc=" << stop.getDescription() << " stopEdge=" << stopEdge->getID()
1069 << " searchStart=" << ((*searchStart) == myRoute->end() ? "END" : (**searchStart)->getID())
1070 << " index=" << (int)((*searchStart) - myRoute->begin()) << " route=" << toString(myRoute->getEdges())
1071 << "\n";
1072 }
1073#endif
1074 stop.edge = std::find(*searchStart, myRoute->end(), stopEdge);
1075 MSRouteIterator prevStopEdge = myCurrEdge;
1076 const MSEdge* prevEdge = (getLane() == nullptr ? getEdge() : &getLane()->getEdge());
1077 double prevStopPos = getPositionOnLane();
1078 // where to insert the stop
1079 std::list<MSStop>::iterator iter = myStops.begin();
1080 if (stopPar.index == STOP_INDEX_END || stopPar.index >= static_cast<int>(myStops.size())) {
1081 iter = myStops.end();
1082 if (myStops.size() > 0 && myStops.back().edge >= *searchStart) {
1083 prevStopEdge = myStops.back().edge;
1084 prevEdge = &myStops.back().lane->getEdge();
1085 prevStopPos = myStops.back().pars.endPos;
1086 stop.edge = std::find(prevStopEdge, myRoute->end(), stopEdge);
1087 if (prevStopEdge == stop.edge // laneEdge check is insufficient for looped routes
1088 && prevEdge == &stop.lane->getEdge() // route iterator check insufficient for internal lane stops
1089 && prevStopPos > stop.pars.endPos) {
1090 stop.edge = std::find(prevStopEdge + 1, myRoute->end(), stopEdge);
1091 }
1092#ifdef DEBUG_ADD_STOP
1093 if (DEBUG_COND) {
1094 std::cout << " (@end) prevStopEdge=" << (*prevStopEdge)->getID() << " index=" << (int)(prevStopEdge - myRoute->begin())
1095 << " foundIndex=" << (stop.edge == myRoute->end() ? -1 : (int)(stop.edge - myRoute->begin())) << "\n";
1096 }
1097#endif
1098 }
1099 } else {
1100 if (stopPar.index == STOP_INDEX_FIT) {
1101 while (iter != myStops.end() && (iter->edge < stop.edge ||
1102 (iter->pars.endPos < stop.pars.endPos && iter->edge == stop.edge))) {
1103 prevStopEdge = iter->edge;
1104 prevStopPos = iter->pars.endPos;
1105 ++iter;
1106 }
1107 } else {
1108 int index = stopPar.index;
1109 while (index > 0) {
1110 prevStopEdge = iter->edge;
1111 prevStopPos = iter->pars.endPos;
1112 ++iter;
1113 --index;
1114 }
1115#ifdef DEBUG_ADD_STOP
1116 if (DEBUG_COND) {
1117 std::cout << " (@fit) prevStopEdge=" << (*prevStopEdge)->getID() << " index=" << (int)(prevStopEdge - myRoute->begin()) << "\n";
1118 }
1119#endif
1120 stop.edge = std::find(prevStopEdge, myRoute->end(), stopEdge);
1121 }
1122 }
1123 const bool wasTooClose = errorMsg != "" && errorMsg.find("too close") != std::string::npos;
1124 if (stop.edge == myRoute->end()) {
1125 if (!wasTooClose) {
1126 errorMsg = errorMsgStart + " for vehicle '" + myParameter->id + "' on lane '" + stop.lane->getID() + "' is not downstream the current route.";
1127 }
1128 return false;
1129 }
1130
1131 const bool tooClose = (prevStopEdge == stop.edge && prevEdge == &stop.lane->getEdge() &&
1132 prevStopPos + (iter == myStops.begin() ? getBrakeGap() : 0) > stop.pars.endPos + POSITION_EPS);
1133
1134 if (prevStopEdge > stop.edge ||
1135 // a collision-stop happens after vehicle movement and may move the
1136 // vehicle backwards on it's lane (prevStopPos is the vehicle position)
1137 (tooClose && !stop.pars.collision)
1138 || (stop.lane->getEdge().isInternal() && stop.lane->getNextNormal() != *(stop.edge + 1))) {
1139 // check if the edge occurs again later in the route
1140 //std::cout << " could not add stop " << errorMsgStart << " prevStops=" << myStops.size() << " searchStart=" << (*searchStart - myRoute->begin()) << " route=" << toString(myRoute->getEdges()) << "\n";
1141 if (tooClose && prevStopPos <= stop.pars.endPos + POSITION_EPS) {
1142 errorMsg = errorMsgStart + " for vehicle '" + myParameter->id + "' on lane '" + stop.pars.lane + "' is too close to brake.";
1143 }
1144 MSRouteIterator next = stop.edge + 1;
1145 return addStop(stopPar, errorMsg, untilOffset, &next);
1146 }
1147 if (wasTooClose) {
1148 errorMsg = "";
1149 }
1150 // David.C:
1151 //if (!stop.parking && (myCurrEdge == stop.edge && myState.myPos > stop.endPos - getCarFollowModel().brakeGap(myState.mySpeed))) {
1152 const double endPosOffset = stop.lane->getEdge().isInternal() ? (*stop.edge)->getLength() : 0;
1153 const double distToStop = stop.pars.endPos + endPosOffset - getPositionOnLane();
1154 if (stop.pars.collision && !handleCollisionStop(stop, distToStop)) {
1155 return false;
1156 }
1157 if (!hasDeparted() && myCurrEdge == stop.edge) {
1158 double pos = -1;
1160 pos = myParameter->departPos;
1161 if (pos < 0.) {
1162 pos += (*myCurrEdge)->getLength();
1163 }
1164 }
1166 pos = MIN2(stop.pars.endPos + endPosOffset, basePos(*myCurrEdge));
1167 }
1168 if (pos > stop.pars.endPos + endPosOffset) {
1169 if (stop.edge != myRoute->end()) {
1170 // check if the edge occurs again later in the route
1171 MSRouteIterator next = stop.edge + 1;
1172 return addStop(stopPar, errorMsg, untilOffset, &next);
1173 }
1174 errorMsg = errorMsgStart + " for vehicle '" + myParameter->id + "' on lane '" + stop.lane->getID() + "' is before departPos.";
1175 return false;
1176 }
1177 }
1178 if (iter != myStops.begin()) {
1179 std::list<MSStop>::iterator iter2 = iter;
1180 iter2--;
1181 if (stop.pars.until >= 0 && iter2->pars.until > stop.pars.until) {
1182 errorMsg = errorMsgStart + " for vehicle '" + myParameter->id + "' on lane '" + stop.lane->getID()
1183 + "' set to end at " + time2string(stop.pars.until)
1184 + " earlier than previous stop at " + time2string(iter2->pars.until) + ".";
1185 }
1186 if (stop.pars.arrival >= 0 && iter2->pars.until > stop.pars.arrival) {
1187 errorMsg = errorMsgStart + " for vehicle '" + myParameter->id + "' on lane '" + stop.lane->getID()
1188 + "' set to start at " + time2string(stop.pars.arrival)
1189 + " earlier than previous stop end at " + time2string(iter2->pars.until) + ".";
1190 }
1191 if (stop.pars.arrival >= 0 && iter2->pars.arrival > stop.pars.arrival) {
1192 errorMsg = errorMsgStart + " for vehicle '" + myParameter->id + "' on lane '" + stop.lane->getID()
1193 + "' set to start at " + time2string(stop.pars.arrival)
1194 + " earlier than previous stop arrival at " + time2string(iter2->pars.arrival) + ".";
1195 }
1196 } else {
1197 if (stop.pars.until >= 0 && getParameter().depart > stop.pars.until) {
1198 errorMsg = errorMsgStart + " for vehicle '" + myParameter->id + "' on lane '" + stop.lane->getID()
1199 + "' set to end at " + time2string(stop.pars.until)
1200 + " earlier than departure at " + time2string(getParameter().depart) + ".";
1201 }
1202 }
1203 if (stop.pars.until >= 0 && stop.pars.arrival > stop.pars.until && errorMsg == "") {
1204 errorMsg = errorMsgStart + " for vehicle '" + myParameter->id + "' on lane '" + stop.lane->getID()
1205 + "' set to end at " + time2string(stop.pars.until)
1206 + " earlier than arrival at " + time2string(stop.pars.arrival) + ".";
1207 }
1208 myStops.insert(iter, stop);
1209 //std::cout << " added stop " << errorMsgStart << " totalStops=" << myStops.size() << " searchStart=" << (*searchStart - myRoute->begin())
1210 // << " routeIndex=" << (stop.edge - myRoute->begin())
1211 // << " stopIndex=" << std::distance(myStops.begin(), iter)
1212 // << " route=" << toString(myRoute->getEdges()) << "\n";
1213 return true;
1214}
1215
1216
1217void
1218MSBaseVehicle::addStops(const bool ignoreStopErrors, MSRouteIterator* searchStart, bool addRouteStops) {
1219 if (addRouteStops) {
1220 for (const SUMOVehicleParameter::Stop& stop : myRoute->getStops()) {
1221 std::string errorMsg;
1222 if (!addStop(stop, errorMsg, myParameter->depart, searchStart) && !ignoreStopErrors) {
1223 throw ProcessError(errorMsg);
1224 }
1225 if (errorMsg != "") {
1226 WRITE_WARNING(errorMsg);
1227 }
1228 }
1229 }
1231 for (const SUMOVehicleParameter::Stop& stop : myParameter->stops) {
1232 std::string errorMsg;
1233 if (!addStop(stop, errorMsg, untilOffset, searchStart) && !ignoreStopErrors) {
1234 throw ProcessError(errorMsg);
1235 }
1236 if (errorMsg != "") {
1237 WRITE_WARNING(errorMsg);
1238 }
1239 }
1240}
1241
1242
1243bool
1246 const std::string err = "for vehicle '" + getID() + "' at time=" + time2string(SIMSTEP);
1247 int i = 0;
1248 bool ok = true;
1249 double lastPos = getPositionOnLane();
1250 if (getLane() != nullptr && getLane()->isInternal()
1251 && myStops.size() > 0 && !myStops.front().lane->isInternal()) {
1252 // start edge is still incoming to the intersection so lastPos
1253 // relative to that edge must be adapted
1254 lastPos += (*myCurrEdge)->getLength();
1255 }
1256 for (const MSStop& stop : myStops) {
1257 const double endPos = stop.getEndPos(*this);
1258 MSRouteIterator it;
1259 const std::string prefix = "Stop " + toString(i) + " on edge '" + stop.lane->getEdge().getID() + "' ";
1260 if (stop.lane->isInternal()) {
1261 // find the normal predecessor and ensure that the next route edge
1262 // matches the successor of the internal edge successor
1263 it = std::find(start, myRoute->end(), stop.lane->getEdge().getNormalBefore());
1264 if (it != myRoute->end() && (
1265 it + 1 == myRoute->end() || *(it + 1) != stop.lane->getEdge().getNormalSuccessor())) {
1266 it = myRoute->end(); // signal failure
1267 }
1268 } else {
1269 const MSEdge* const stopEdge = &stop.lane->getEdge();
1270 it = std::find(start, myRoute->end(), stopEdge);
1271 }
1272 if (it == myRoute->end()) {
1273 WRITE_ERROR(prefix + "is not found after edge '" + (*start)->getID() + "' (" + toString(start - myCurrEdge) + " after current " + err);
1274 ok = false;
1275 } else {
1276 MSRouteIterator it2;
1277 for (it2 = myRoute->begin(); it2 != myRoute->end(); it2++) {
1278 if (it2 == stop.edge) {
1279 break;
1280 }
1281 }
1282 if (it2 == myRoute->end()) {
1283 WRITE_ERROR(prefix + "used invalid route index " + err);
1284 ok = false;
1285 } else if (it2 < start) {
1286 WRITE_ERROR(prefix + "used invalid (relative) route index " + toString(it2 - myCurrEdge) + " expected after " + toString(start - myCurrEdge) + " " + err);
1287 ok = false;
1288 } else {
1289 if (it != stop.edge) {
1290 double brakeGap = i == 0 ? getBrakeGap() : 0;
1291 if (endPos >= lastPos + brakeGap) {
1292 WRITE_WARNING(prefix + "is used in " + toString(stop.edge - myCurrEdge) + " edges but first encounter is in "
1293 + toString(it - myCurrEdge) + " edges " + err);
1294 }
1295 }
1296 start = stop.edge;
1297 }
1298 }
1299 lastPos = endPos;
1300 i++;
1301 }
1302 return ok;
1303}
1304
1305
1307MSBaseVehicle::getStopEdges(double& firstPos, double& lastPos) const {
1308 assert(haveValidStopEdges());
1309 ConstMSEdgeVector result;
1310 const MSStop* prev = nullptr;
1311 const MSEdge* internalSuccessor = nullptr;
1312 for (const MSStop& stop : myStops) {
1313 if (stop.reached) {
1314 continue;
1315 }
1316 const double stopPos = stop.getEndPos(*this);
1317 if ((prev == nullptr
1318 || prev->edge != stop.edge
1319 || (prev->lane == stop.lane && prev->getEndPos(*this) > stopPos))
1320 && *stop.edge != internalSuccessor) {
1321 result.push_back(*stop.edge);
1322 if (stop.lane->isInternal()) {
1323 internalSuccessor = stop.lane->getNextNormal();
1324 result.push_back(internalSuccessor);
1325 } else {
1326 internalSuccessor = nullptr;
1327 }
1328 }
1329 prev = &stop;
1330 if (firstPos < 0) {
1331 firstPos = stopPos;
1332 }
1333 lastPos = stopPos;
1334 }
1335 //std::cout << "getStopEdges veh=" << getID() << " result=" << toString(result) << "\n";
1336 return result;
1337}
1338
1339
1340std::vector<std::pair<int, double> >
1342 std::vector<std::pair<int, double> > result;
1343 for (std::list<MSStop>::const_iterator iter = myStops.begin(); iter != myStops.end(); ++iter) {
1344 result.push_back(std::make_pair(
1345 (int)(iter->edge - myRoute->begin()),
1346 iter->getEndPos(*this)));
1347 }
1348 return result;
1349}
1350
1351
1352MSStop&
1354 assert(myStops.size() > 0);
1355 return myStops.front();
1356}
1357
1360 if (isStopped()) {
1361 return myStops.front().duration;
1362 } else {
1363 return 0;
1364 }
1365}
1366
1367
1368MSStop&
1369MSBaseVehicle::getStop(int nextStopIndex) {
1370 if (nextStopIndex < 0 || (int)myStops.size() <= nextStopIndex) {
1371 throw InvalidArgument("Invalid stop index " + toString(nextStopIndex) + " (has " + toString(myStops.size()) + " stops)");
1372 }
1373 auto stopIt = myStops.begin();
1374 std::advance(stopIt, nextStopIndex);
1375 return *stopIt;
1376}
1377
1378
1381 if (hasStops()) {
1382 return &myStops.front().pars;
1383 }
1384 return nullptr;
1385}
1386
1387
1388bool
1390 //if the stop exists update the duration
1391 for (std::list<MSStop>::iterator iter = myStops.begin(); iter != myStops.end(); iter++) {
1392 if (iter->lane->getID() == stop.lane && fabs(iter->pars.endPos - stop.endPos) < POSITION_EPS) {
1393 // update existing stop
1394 if (stop.duration == 0 && stop.until < 0 && !iter->reached) {
1395 myStops.erase(iter);
1396 } else {
1397 iter->duration = stop.duration;
1398 iter->triggered = stop.triggered;
1399 iter->containerTriggered = stop.containerTriggered;
1400 const_cast<SUMOVehicleParameter::Stop&>(iter->pars).until = stop.until;
1401 const_cast<SUMOVehicleParameter::Stop&>(iter->pars).parking = stop.parking;
1402 }
1403 return true;
1404 }
1405 }
1406 const bool result = addStop(stop, errorMsg);
1407 if (result) {
1409 myParameter->stops.push_back(stop);
1410 }
1411 return result;
1412}
1413
1414
1415bool
1417 if (hasStops() && nextStopIndex < (int)myStops.size()) {
1418 if (nextStopIndex == 0 && isStopped()) {
1420 } else {
1421 auto stopIt = myStops.begin();
1422 std::advance(stopIt, nextStopIndex);
1423 myStops.erase(stopIt);
1424 }
1425 if (!hasDeparted() && (int)myParameter->stops.size() > nextStopIndex) {
1426 // stops will be rebuilt from scratch on rerouting so we must patch the stops in myParameter
1427 auto stopIt2 = myParameter->stops.begin();
1428 std::advance(stopIt2, nextStopIndex);
1429 const_cast<SUMOVehicleParameter*>(myParameter)->stops.erase(stopIt2);
1430 }
1431 return true;
1432 } else {
1433 return false;
1434 }
1435}
1436
1437
1438bool
1439MSBaseVehicle::replaceStop(int nextStopIndex, SUMOVehicleParameter::Stop stop, const std::string& info, bool teleport, std::string& errorMsg) {
1440 const int n = (int)myStops.size();
1441 if (nextStopIndex < 0 || nextStopIndex >= n) {
1442 errorMsg = ("Invalid nextStopIndex '" + toString(nextStopIndex) + "' for " + toString(n) + " remaining stops");
1443 return false;
1444 }
1445 if (nextStopIndex == 0 && isStopped()) {
1446 errorMsg = "Cannot replace reached stop";
1447 return false;
1448 }
1450 MSLane* stopLane = MSLane::dictionary(stop.lane);
1451 MSEdge* stopEdge = &stopLane->getEdge();
1452
1453 auto itStop = myStops.begin();
1454 std::advance(itStop, nextStopIndex);
1455 MSStop& replacedStop = *itStop;
1456
1457 if (replacedStop.lane == stopLane && replacedStop.pars.endPos == stop.endPos && !teleport) {
1458 // only replace stop attributes
1459 const_cast<SUMOVehicleParameter::Stop&>(replacedStop.pars) = stop;
1460 replacedStop.initPars(stop);
1461 return true;
1462 }
1463
1464 if (!stopLane->allowsVehicleClass(getVClass())) {
1465 errorMsg = ("Disallowed stop lane '" + stopLane->getID() + "'");
1466 return false;
1467 }
1468
1469 const ConstMSEdgeVector& oldEdges = getRoute().getEdges();
1470 std::vector<MSStop> stops(myStops.begin(), myStops.end());
1471 const int junctionOffset = getLane() != nullptr && getLane()->isInternal() ? 1 : 0;
1472 MSRouteIterator itStart = nextStopIndex == 0 ? getCurrentRouteEdge() + junctionOffset : stops[nextStopIndex - 1].edge;
1473 double startPos = nextStopIndex == 0 ? getPositionOnLane() : stops[nextStopIndex - 1].pars.endPos;
1474 MSRouteIterator itEnd = nextStopIndex == n - 1 ? oldEdges.end() - 1 : stops[nextStopIndex + 1].edge;
1475 auto endPos = nextStopIndex == n - 1 ? getArrivalPos() : stops[nextStopIndex + 1].pars.endPos;
1477
1478 bool newDestination = nextStopIndex == n - 1 && stops[nextStopIndex].edge == oldEdges.end() - 1;
1479
1480 ConstMSEdgeVector toNewStop;
1481 if (!teleport) {
1482 router.compute(*itStart, startPos, stopEdge, stop.endPos, this, t, toNewStop, true);
1483 if (toNewStop.size() == 0) {
1484 errorMsg = "No route found from edge '" + (*itStart)->getID() + "' to stop edge '" + stopEdge->getID() + "'";
1485 return false;
1486 }
1487 }
1488
1489 ConstMSEdgeVector fromNewStop;
1490 if (!newDestination) {
1491 router.compute(stopEdge, stop.endPos, *itEnd, endPos, this, t, fromNewStop, true);
1492 if (fromNewStop.size() == 0) {
1493 errorMsg = "No route found from stop edge '" + stopEdge->getID() + "' to edge '" + (*itEnd)->getID() + "'";
1494 return false;
1495 }
1496 }
1497
1498 const_cast<SUMOVehicleParameter::Stop&>(replacedStop.pars) = stop;
1499 replacedStop.initPars(stop);
1500 replacedStop.edge = myRoute->end(); // will be patched in replaceRoute
1501 replacedStop.lane = stopLane;
1503 replacedStop.segment = MSGlobals::gMesoNet->getSegmentForEdge(replacedStop.lane->getEdge(), replacedStop.getEndPos(*this));
1504 if (replacedStop.lane->isInternal()) {
1505 errorMsg = "Mesoscopic simulation does not allow stopping on internal edge '" + stop.edge + "' for vehicle '" + getID() + "'.";
1506 return false;
1507 }
1508 }
1509
1510 ConstMSEdgeVector oldRemainingEdges(myCurrEdge, getRoute().end());
1511 ConstMSEdgeVector newEdges; // only remaining
1512 newEdges.insert(newEdges.end(), myCurrEdge, itStart);
1513 if (!teleport) {
1514 newEdges.insert(newEdges.end(), toNewStop.begin(), toNewStop.end() - 1);
1515 } else {
1516 newEdges.push_back(*itStart);
1517 }
1518 if (!newDestination) {
1519 newEdges.insert(newEdges.end(), fromNewStop.begin(), fromNewStop.end() - 1);
1520 newEdges.insert(newEdges.end(), itEnd, oldEdges.end());
1521 } else {
1522 newEdges.push_back(stopEdge);
1523 }
1524 //std::cout << SIMTIME << " replaceStop veh=" << getID()
1525 // << " oldEdges=" << oldRemainingEdges.size()
1526 // << " newEdges=" << newEdges.size()
1527 // << " toNewStop=" << toNewStop.size()
1528 // << " fromNewStop=" << fromNewStop.size()
1529 // << "\n";
1530
1531 const double routeCost = router.recomputeCosts(newEdges, this, t);
1532 const double previousCost = router.recomputeCosts(oldRemainingEdges, this, t);
1533 const double savings = previousCost - routeCost;
1534 if (!hasDeparted() && (int)myParameter->stops.size() > nextStopIndex) {
1535 // stops will be rebuilt from scratch so we must patch the stops in myParameter
1536 const_cast<SUMOVehicleParameter*>(myParameter)->stops[nextStopIndex] = stop;
1537 }
1538 return replaceRouteEdges(newEdges, routeCost, savings, info, !hasDeparted(), false, false, &errorMsg);
1539}
1540
1541
1542bool
1543MSBaseVehicle::rerouteBetweenStops(int nextStopIndex, const std::string& info, bool teleport, std::string& errorMsg) {
1544 const int n = (int)myStops.size();
1545 if (nextStopIndex < 0 || nextStopIndex > n) {
1546 errorMsg = ("Invalid nextStopIndex '" + toString(nextStopIndex) + "' for " + toString(n) + " remaining stops");
1547 return false;
1548 }
1549 if (nextStopIndex == 0 && isStopped()) {
1550 errorMsg = "Cannot reroute towards reached stop";
1551 return false;
1552 }
1554
1555 const ConstMSEdgeVector& oldEdges = getRoute().getEdges();
1556 std::vector<MSStop> stops(myStops.begin(), myStops.end());
1557 const int junctionOffset = getLane() != nullptr && getLane()->isInternal() ? 1 : 0;
1558 MSRouteIterator itStart = nextStopIndex == 0 ? getCurrentRouteEdge() + junctionOffset : stops[nextStopIndex - 1].edge;
1559 double startPos = nextStopIndex == 0 ? getPositionOnLane() : stops[nextStopIndex - 1].pars.endPos;
1560 MSRouteIterator itEnd = nextStopIndex == n ? oldEdges.end() - 1 : stops[nextStopIndex].edge;
1561 auto endPos = nextStopIndex == n ? getArrivalPos() : stops[nextStopIndex].pars.endPos;
1563
1564 ConstMSEdgeVector newBetween;
1565 if (!teleport) {
1566 router.compute(*itStart, startPos, *itEnd, endPos, this, t, newBetween, true);
1567 if (newBetween.size() == 0) {
1568 errorMsg = "No route found from edge '" + (*itStart)->getID() + "' to stop edge '" + (*itEnd)->getID() + "'";
1569 return false;
1570 }
1571 }
1572
1573 ConstMSEdgeVector oldRemainingEdges(myCurrEdge, getRoute().end());
1574 ConstMSEdgeVector newEdges; // only remaining
1575 newEdges.insert(newEdges.end(), myCurrEdge, itStart);
1576 if (!teleport) {
1577 newEdges.insert(newEdges.end(), newBetween.begin(), newBetween.end() - 1);
1578 } else {
1579 newEdges.push_back(*itStart);
1580 }
1581 newEdges.insert(newEdges.end(), itEnd, oldEdges.end());
1582 //std::cout << SIMTIME << " rerouteBetweenStops veh=" << getID()
1583 // << " oldEdges=" << oldRemainingEdges.size()
1584 // << " newEdges=" << newEdges.size()
1585 // << " toNewStop=" << toNewStop.size()
1586 // << " fromNewStop=" << fromNewStop.size()
1587 // << "\n";
1588
1589 const double routeCost = router.recomputeCosts(newEdges, this, t);
1590 const double previousCost = router.recomputeCosts(oldRemainingEdges, this, t);
1591 const double savings = previousCost - routeCost;
1592 return replaceRouteEdges(newEdges, routeCost, savings, info, !hasDeparted(), false, false, &errorMsg);
1593}
1594
1595
1596bool
1597MSBaseVehicle::insertStop(int nextStopIndex, SUMOVehicleParameter::Stop stop, const std::string& info, bool teleport, std::string& errorMsg) {
1598 const int n = (int)myStops.size();
1599 if (nextStopIndex < 0 || nextStopIndex > n) {
1600 errorMsg = ("Invalid nextStopIndex '" + toString(nextStopIndex) + "' for " + toString(n) + " remaining stops");
1601 return false;
1602 }
1603 if (nextStopIndex == 0 && isStopped()) {
1604 errorMsg = "Cannot insert stop before the currently reached stop";
1605 return false;
1606 }
1608 MSLane* stopLane = MSLane::dictionary(stop.lane);
1609 MSEdge* stopEdge = &stopLane->getEdge();
1610
1611 if (!stopLane->allowsVehicleClass(getVClass())) {
1612 errorMsg = ("Disallowed stop lane '" + stopLane->getID() + "'");
1613 return false;
1614 }
1615
1616 const ConstMSEdgeVector& oldEdges = getRoute().getEdges();
1617 std::vector<MSStop> stops(myStops.begin(), myStops.end());
1618 const int junctionOffset = getLane() != nullptr && getLane()->isInternal() ? 1 : 0;
1619 MSRouteIterator itStart = nextStopIndex == 0 ? getCurrentRouteEdge() + junctionOffset : stops[nextStopIndex - 1].edge;
1620 double startPos = nextStopIndex == 0 ? getPositionOnLane() : stops[nextStopIndex - 1].pars.endPos;
1621 MSRouteIterator itEnd = nextStopIndex == n ? oldEdges.end() - 1 : stops[nextStopIndex].edge;
1622 auto endPos = nextStopIndex == n ? getArrivalPos() : stops[nextStopIndex].pars.endPos;
1624
1625 bool newDestination = nextStopIndex == n;
1626
1627 ConstMSEdgeVector toNewStop;
1628 if (!teleport) {
1629 router.compute(*itStart, startPos, stopEdge, stop.endPos, this, t, toNewStop, true);
1630 if (toNewStop.size() == 0) {
1631 errorMsg = "No route found from edge '" + (*itStart)->getID() + "' to stop edge '" + stopEdge->getID() + "'";
1632 return false;
1633 }
1634 }
1635
1636 ConstMSEdgeVector fromNewStop;
1637 if (!newDestination) {
1638 router.compute(stopEdge, stop.endPos, *itEnd, endPos, this, t, fromNewStop, true);
1639 if (fromNewStop.size() == 0) {
1640 errorMsg = "No route found from stop edge '" + stopEdge->getID() + "' to edge '" + (*itEnd)->getID() + "'";
1641 return false;
1642 }
1643 }
1644
1645 auto itStop = myStops.begin();
1646 std::advance(itStop, nextStopIndex);
1647 MSStop newStop(stop);
1648 newStop.initPars(stop);
1649 newStop.edge = myRoute->end(); // will be patched in replaceRoute
1650 newStop.lane = stopLane;
1652 newStop.segment = MSGlobals::gMesoNet->getSegmentForEdge(newStop.lane->getEdge(), newStop.getEndPos(*this));
1653 if (newStop.lane->isInternal()) {
1654 errorMsg = "Mesoscopic simulation does not allow stopping on internal edge '" + stop.edge + "' for vehicle '" + getID() + "'.";
1655 return false;
1656 }
1657 }
1658 myStops.insert(itStop, newStop);
1659
1660 ConstMSEdgeVector oldRemainingEdges(myCurrEdge, getRoute().end());
1661 ConstMSEdgeVector newEdges; // only remaining
1662 newEdges.insert(newEdges.end(), myCurrEdge, itStart);
1663 if (!teleport) {
1664 newEdges.insert(newEdges.end(), toNewStop.begin(), toNewStop.end() - 1);
1665 } else {
1666 newEdges.push_back(*itStart);
1667 }
1668 if (!newDestination) {
1669 newEdges.insert(newEdges.end(), fromNewStop.begin(), fromNewStop.end() - 1);
1670 newEdges.insert(newEdges.end(), itEnd, oldEdges.end());
1671 } else {
1672 newEdges.push_back(stopEdge);
1673 }
1674 //std::cout << SIMTIME << " replaceStop veh=" << getID()
1675 // << " oldEdges=" << oldRemainingEdges.size()
1676 // << " newEdges=" << newEdges.size()
1677 // << " toNewStop=" << toNewStop.size()
1678 // << " fromNewStop=" << fromNewStop.size()
1679 // << "\n";
1680
1681 const double routeCost = router.recomputeCosts(newEdges, this, t);
1682 const double previousCost = router.recomputeCosts(oldRemainingEdges, this, t);
1683 const double savings = previousCost - routeCost;
1684
1685 if (!hasDeparted() && (int)myParameter->stops.size() >= nextStopIndex) {
1686 // stops will be rebuilt from scratch so we must patch the stops in myParameter
1687 auto it = myParameter->stops.begin() + nextStopIndex;
1688 const_cast<SUMOVehicleParameter*>(myParameter)->stops.insert(it, stop);
1689 }
1690 return replaceRouteEdges(newEdges, routeCost, savings, info, !hasDeparted(), false, false, &errorMsg);
1691}
1692
1693
1694double
1696 if (static_cast<MSDevice_Battery*>(getDevice(typeid(MSDevice_Battery))) != 0) {
1697 MSDevice_Battery* batteryOfVehicle = dynamic_cast<MSDevice_Battery*>(getDevice(typeid(MSDevice_Battery)));
1698 return batteryOfVehicle->getActualBatteryCapacity();
1699 } else {
1700 if (static_cast<MSDevice_ElecHybrid*>(getDevice(typeid(MSDevice_ElecHybrid))) != 0) {
1701 MSDevice_ElecHybrid* batteryOfVehicle = dynamic_cast<MSDevice_ElecHybrid*>(getDevice(typeid(MSDevice_ElecHybrid)));
1702 return batteryOfVehicle->getActualBatteryCapacity();
1703 }
1704 }
1705
1706 return -1;
1707}
1708
1709double
1711 if (static_cast<MSDevice_ElecHybrid*>(getDevice(typeid(MSDevice_ElecHybrid))) != 0) {
1712 MSDevice_ElecHybrid* elecHybridDevice = dynamic_cast<MSDevice_ElecHybrid*>(getDevice(typeid(MSDevice_ElecHybrid)));
1713 return elecHybridDevice->getCurrentFromOverheadWire();
1714 }
1715
1716 return NAN;
1717}
1718
1719double
1721 if (isOnRoad() || isIdling()) {
1723 } else {
1724 return 0.;
1725 }
1726}
1727
1728
1731 return _getWeightsStorage();
1732}
1733
1734
1737 return _getWeightsStorage();
1738}
1739
1740
1743 if (myEdgeWeights == nullptr) {
1745 }
1746 return *myEdgeWeights;
1747}
1748
1749
1750
1751
1752int
1754 int boarded = myPersonDevice == nullptr ? 0 : myPersonDevice->size();
1755 return boarded + myParameter->personNumber;
1756}
1757
1758std::vector<std::string>
1760 std::vector<std::string> ret;
1761 const std::vector<MSTransportable*>& persons = getPersons();
1762 for (std::vector<MSTransportable*>::const_iterator it_p = persons.begin(); it_p != persons.end(); ++it_p) {
1763 ret.push_back((*it_p)->getID());
1764 }
1765 return ret;
1766}
1767
1768int
1770 int loaded = myContainerDevice == nullptr ? 0 : myContainerDevice->size();
1771 return loaded + myParameter->containerNumber;
1772}
1773
1774
1775void
1777 // this might be called from the MSTransportable destructor so we cannot do a dynamic cast to determine the type
1778 if (myPersonDevice != nullptr) {
1780 }
1781 if (myContainerDevice != nullptr) {
1783 }
1784}
1785
1786
1787const std::vector<MSTransportable*>&
1789 if (myPersonDevice == nullptr) {
1791 } else {
1793 }
1794}
1795
1796
1797const std::vector<MSTransportable*>&
1799 if (myContainerDevice == nullptr) {
1801 } else {
1803 }
1804}
1805
1806
1807bool
1808MSBaseVehicle::isLineStop(double position) const {
1809 if (myParameter->line == "") {
1810 // not a public transport line
1811 return false;
1812 }
1813 for (const SUMOVehicleParameter::Stop& stop : myParameter->stops) {
1814 if (stop.startPos <= position && position <= stop.endPos) {
1815 return true;
1816 }
1817 }
1818 for (const SUMOVehicleParameter::Stop& stop : myRoute->getStops()) {
1819 if (stop.startPos <= position && position <= stop.endPos) {
1820 return true;
1821 }
1822 }
1823 return false;
1824}
1825
1826
1827bool
1828MSBaseVehicle::hasDevice(const std::string& deviceName) const {
1829 for (MSDevice* const dev : myDevices) {
1830 if (dev->deviceName() == deviceName) {
1831 return true;
1832 }
1833 }
1834 return false;
1835}
1836
1837
1838void
1839MSBaseVehicle::createDevice(const std::string& deviceName) {
1840 if (!hasDevice(deviceName)) {
1841 if (deviceName == "rerouting") {
1842 ((SUMOVehicleParameter*)myParameter)->setParameter("has." + deviceName + ".device", "true");
1844 if (hasDeparted()) {
1845 // vehicle already departed: disable pre-insertion rerouting and enable regular routing behavior
1846 MSDevice_Routing* routingDevice = static_cast<MSDevice_Routing*>(getDevice(typeid(MSDevice_Routing)));
1847 assert(routingDevice != 0);
1849 }
1850 } else {
1851 throw InvalidArgument("Creating device of type '" + deviceName + "' is not supported");
1852 }
1853 }
1854}
1855
1856
1857std::string
1858MSBaseVehicle::getDeviceParameter(const std::string& deviceName, const std::string& key) const {
1859 for (MSVehicleDevice* const dev : myDevices) {
1860 if (dev->deviceName() == deviceName) {
1861 return dev->getParameter(key);
1862 }
1863 }
1864 throw InvalidArgument("No device of type '" + deviceName + "' exists");
1865}
1866
1867
1868void
1869MSBaseVehicle::setDeviceParameter(const std::string& deviceName, const std::string& key, const std::string& value) {
1870 for (MSVehicleDevice* const dev : myDevices) {
1871 if (dev->deviceName() == deviceName) {
1872 dev->setParameter(key, value);
1873 return;
1874 }
1875 }
1876 throw InvalidArgument("No device of type '" + deviceName + "' exists");
1877}
1878
1879
1880void
1881MSBaseVehicle::setJunctionModelParameter(const std::string& key, const std::string& value) {
1884 const_cast<SUMOVehicleParameter&>(getParameter()).setParameter(key, value);
1885 // checked in MSLink::ignoreFoe
1886 } else {
1887 throw InvalidArgument("Vehicle '" + getID() + "' does not support junctionModel parameter '" + key + "'");
1888 }
1889}
1890
1891
1892void
1894 /* Design idea for additional junction model parameters:
1895 We can distinguish between 3 levels of parameters
1896 1. typically shared by multiple vehicles -> vType parameter
1897 2. specific to one vehicle but stays constant throughout the simulation -> vehicle parameter
1898 3. specific to one vehicle and expected to change during simulation -> prefixed generic vehicle parameter
1899 */
1900 for (auto item : getParameter().getParametersMap()) {
1901 if (StringUtils::startsWith(item.first, "junctionModel.")) {
1902 setJunctionModelParameter(item.first, item.second);
1903 }
1904 }
1905}
1906
1907
1908void
1910 assert(type != nullptr);
1911 if (myType->isVehicleSpecific() && type != myType) {
1913 }
1914 myType = type;
1915 if (myEnergyParams != nullptr) {
1917 }
1918}
1919
1920
1923 if (myType->isVehicleSpecific()) {
1924 return *myType;
1925 }
1926 MSVehicleType* type = myType->buildSingularType(myType->getID() + "@" + getID());
1927 replaceVehicleType(type);
1928 return *type;
1929}
1930
1931
1932int
1934 const MSLane* const lane = getLane();
1935 if (lane == nullptr) {
1936 return getEdge()->getLanes()[0]->getRNGIndex();
1937 } else {
1938 return lane->getRNGIndex();
1939 }
1940}
1941
1942
1943SumoRNG*
1945 const MSLane* lane = getLane();
1946 if (lane == nullptr) {
1947 return getEdge()->getLanes()[0]->getRNG();
1948 } else {
1949 return lane->getRNG();
1950 }
1951}
1952
1953std::string
1954MSBaseVehicle::getPrefixedParameter(const std::string& key, std::string& error) const {
1955 const MSVehicle* microVeh = dynamic_cast<const MSVehicle*>(this);
1956 if (StringUtils::startsWith(key, "device.")) {
1957 StringTokenizer tok(key, ".");
1958 if (tok.size() < 3) {
1959 error = "Invalid device parameter '" + key + "' for vehicle '" + getID() + "'.";
1960 return "";
1961 }
1962 try {
1963 return getDeviceParameter(tok.get(1), key.substr(tok.get(0).size() + tok.get(1).size() + 2));
1964 } catch (InvalidArgument& e) {
1965 error = "Vehicle '" + getID() + "' does not support device parameter '" + key + "' (" + e.what() + ").";
1966 return "";
1967 }
1968 } else if (StringUtils::startsWith(key, "laneChangeModel.")) {
1969 if (microVeh == nullptr) {
1970 error = "Meso Vehicle '" + getID() + "' does not support laneChangeModel parameters.";
1971 return "";
1972 }
1973 const std::string attrName = key.substr(16);
1974 try {
1975 return microVeh->getLaneChangeModel().getParameter(attrName);
1976 } catch (InvalidArgument& e) {
1977 error = "Vehicle '" + getID() + "' does not support laneChangeModel parameter '" + key + "' (" + e.what() + ").";
1978 return "";
1979 }
1980 } else if (StringUtils::startsWith(key, "carFollowModel.")) {
1981 if (microVeh == nullptr) {
1982 error = "Meso Vehicle '" + getID() + "' does not support carFollowModel parameters.";
1983 return "";
1984 }
1985 const std::string attrName = key.substr(15);
1986 try {
1987 return microVeh->getCarFollowModel().getParameter(microVeh, attrName);
1988 } catch (InvalidArgument& e) {
1989 error = "Vehicle '" + getID() + "' does not support carFollowModel parameter '" + key + "' (" + e.what() + ").";
1990 return "";
1991 }
1992 } else if (StringUtils::startsWith(key, "has.") && StringUtils::endsWith(key, ".device")) {
1993 StringTokenizer tok(key, ".");
1994 if (tok.size() != 3) {
1995 error = "Invalid check for device. Expected format is 'has.DEVICENAME.device'.";
1996 return "";
1997 }
1998 return hasDevice(tok.get(1)) ? "true" : "false";
1999 // parking related parameters start here
2000 } else if (key == "parking.rerouteCount") {
2002 } else if (StringUtils::startsWith(key, "parking.memory.")) {
2003 std::vector<std::string> values;
2004 if (getParkingMemory()) {
2005 if (key == "parking.memory.IDList") {
2006 for (const auto& item : *getParkingMemory()) {
2007 values.push_back(item.first->getID());
2008 }
2009 } else if (key == "parking.memory.score") {
2010 for (const auto& item : *getParkingMemory()) {
2011 values.push_back(item.second.score);
2012 }
2013 } else if (key == "parking.memory.blockedAtTime") {
2014 for (const auto& item : *getParkingMemory()) {
2015 values.push_back(toString(STEPS2TIME(item.second.blockedAtTime)));
2016 }
2017 } else if (key == "parking.memory.blockedAtTimeLocal") {
2018 for (const auto& item : *getParkingMemory()) {
2019 values.push_back(toString(STEPS2TIME(item.second.blockedAtTimeLocal)));
2020 }
2021 } else {
2022 error = "Unsupported parking parameter '" + key + "'.";
2023 }
2024 }
2025 return toString(values);
2026 } else {
2027 // default: custom user parameter
2028 return getParameter().getParameter(key, "");
2029 }
2030}
2031
2032void
2034 if (myParkingMemory == nullptr) {
2036 }
2037 (*myParkingMemory)[pa].blockedAtTime = SIMSTEP;
2038 if (local) {
2039 (*myParkingMemory)[pa].blockedAtTimeLocal = SIMSTEP;
2040 }
2041}
2042
2043void
2045 if (myParkingMemory != nullptr) {
2046 for (auto& item : *myParkingMemory) {
2047 item.second.score = "";
2048 }
2049 }
2050}
2051
2052void
2053MSBaseVehicle::rememberParkingAreaScore(const MSParkingArea* pa, const std::string& score) {
2054 if (myParkingMemory == nullptr) {
2056 }
2057 (*myParkingMemory)[pa].score = score;
2058}
2059
2060
2063 if (myParkingMemory == nullptr) {
2064 return -1;
2065 }
2066 auto it = myParkingMemory->find(pa);
2067 if (it == myParkingMemory->end()) {
2068 return -1;
2069 } else {
2070 return local ? it->second.blockedAtTimeLocal : it->second.blockedAtTime;
2071 }
2072}
2073
2074#ifdef _DEBUG
2075void
2076MSBaseVehicle::initMoveReminderOutput(const OptionsCont& oc) {
2077 if (oc.isSet("movereminder-output.vehicles")) {
2078 const std::vector<std::string> vehicles = oc.getStringVector("movereminder-output.vehicles");
2079 myShallTraceMoveReminders.insert(vehicles.begin(), vehicles.end());
2080 }
2081}
2082
2083
2084void
2085MSBaseVehicle::traceMoveReminder(const std::string& type, MSMoveReminder* rem, double pos, bool keep) const {
2086 OutputDevice& od = OutputDevice::getDeviceByOption("movereminder-output");
2087 od.openTag("movereminder");
2088 od.writeAttr(SUMO_ATTR_TIME, STEPS2TIME(MSNet::getInstance()->getCurrentTimeStep()));
2089 od.writeAttr("veh", getID());
2091 od.writeAttr("type", type);
2092 od.writeAttr("pos", toString(pos));
2093 od.writeAttr("keep", toString(keep));
2094 od.closeTag();
2095}
2096#endif
2097
2098
2099/****************************************************************************/
long long int SUMOTime
Definition: GUI.h:36
#define DEBUG_COND
std::vector< const MSEdge * > ConstMSEdgeVector
Definition: MSEdge.h:74
ConstMSEdgeVector::const_iterator MSRouteIterator
Definition: MSRoute.h:54
#define WRITE_WARNINGF(...)
Definition: MsgHandler.h:266
#define WRITE_ERRORF(...)
Definition: MsgHandler.h:275
#define WRITE_ERROR(msg)
Definition: MsgHandler.h:274
#define WRITE_WARNING(msg)
Definition: MsgHandler.h:265
#define TL(string)
Definition: MsgHandler.h:282
#define TLF(string,...)
Definition: MsgHandler.h:283
std::string time2string(SUMOTime t)
convert SUMOTime to string
Definition: SUMOTime.cpp:68
#define STEPS2TIME(x)
Definition: SUMOTime.h:54
#define SIMSTEP
Definition: SUMOTime.h:60
#define SUMOTime_MAX
Definition: SUMOTime.h:33
#define SIMTIME
Definition: SUMOTime.h:61
SUMOVehicleClass
Definition of vehicle classes to differ between different lane usage and authority types.
@ RANDOM
The edge is chosen randomly.
@ GIVEN
The edge index is given.
@ DEFAULT
No information given; use default.
const int STOP_INDEX_END
const int VEHPARS_JUNCTIONMODEL_PARAMS_SET
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 VEHPARS_SPEEDFACTOR_SET
@ RANDOM
The lane is chosen randomly.
@ GIVEN
The arrival lane is given.
@ FIRST_ALLOWED
The rightmost lane the vehicle may use.
const int VEHPARS_FORCE_REROUTE
const int STOP_INDEX_FIT
@ RANDOM
The arrival position is chosen randomly.
@ GIVEN
The arrival position is given.
@ CENTER
Half the road length.
const int VEHPARS_LINE_SET
@ CONTAINER_TRIGGERED
The departure is container triggered.
@ TRIGGERED
The departure is person triggered.
@ SUMO_TAG_PARKING_AREA_REROUTE
entry for an alternative parking zone
@ SUMO_TAG_VEHICLE
description of a vehicle
@ 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_TIME
trigger: the time of the step
int gPrecisionRandom
Definition: StdDefs.cpp:27
#define UNUSED_PARAMETER(x)
Definition: StdDefs.h:30
T MIN2(T a, T b)
Definition: StdDefs.h:71
T MAX2(T a, T b)
Definition: StdDefs.h:77
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition: ToString.h:46
void setSecondary(const EnergyParams *secondaryParams)
Set secondary params.
Definition: EnergyParams.h:55
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:314
virtual std::string getParameter(const std::string &key) const
try to retrieve the given parameter from this laneChangeModel. Throw exception for unsupported key
SUMOAbstractRouter< MSEdge, SUMOVehicle > & getRouterTT(const int rngIndex, SUMOVehicleClass svc) const
double getMaxSpeed() const
Returns the maximum speed (the minimum of desired and technical maximum speed)
MSVehicleDevice * getDevice(const std::type_info &type) const
Returns a device of the given type if it exists or 0.
ParkingMemory * myParkingMemory
memory for parking search
void rememberBlockedParkingArea(const MSParkingArea *pa, bool local)
std::list< MSStop > myStops
The vehicle's list of stops.
double getImpatience() const
Returns this vehicles impatience.
const std::vector< MSTransportable * > & getPersons() const
retrieve riding persons
virtual void initDevices()
const MSEdge * succEdge(int nSuccs) const
Returns the nSuccs'th successor of edge the vehicle is currently at.
void initJunctionModelParams()
void resetRoutePosition(int index, DepartLaneDefinition departLaneProcedure)
reset index of edge within route
std::map< const MSParkingArea *, PaMemory, ComparatorIdLess > ParkingMemory
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...
bool replaceStop(int nextStopIndex, SUMOVehicleParameter::Stop stop, const std::string &info, bool teleport, std::string &errorMsg)
virtual const MSEdge * getRerouteOrigin() const
Returns the starting point for reroutes (usually the current edge)
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 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.
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.
void replaceParameter(const SUMOVehicleParameter *newParameter)
replace the vehicle parameter (deleting the old one)
int getNumberParkingReroutes() const
std::vector< MSVehicleDevice * > myDevices
The devices this vehicle has.
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)
double getOdometer() const
Returns the distance that was already driven by this vehicle.
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
MSVehicleType & getSingularType()
Replaces the current vehicle type with a new one used by this vehicle only.
SUMOTime sawBlockedParkingArea(const MSParkingArea *pa, bool local) const
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.
double getLength() const
Returns the vehicle's length.
bool isParking() const
Returns whether the vehicle is parking.
const MSEdge * getEdge() const
Returns the edge the vehicle is currently at.
double getHarmonoise_NoiseEmissions() const
Returns noise emissions of the current state.
bool hasValidRoute(std::string &msg, const MSRoute *route=0) const
Validates the current or given route.
int getPersonNumber() const
Returns the number of persons.
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
bool hasDeparted() const
Returns whether this vehicle has already departed.
MSStop & getNextStop()
MSDevice_Transportable * myContainerDevice
The containers this vehicle may have.
MSBaseVehicle(SUMOVehicleParameter *pars, const MSRoute *route, MSVehicleType *type, const double speedFactor)
Constructor.
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 type
SumoRNG * getRNG() const
SUMOTime getDeparture() const
Returns this vehicle's real departure time.
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.
const MSRoute * myRoute
This vehicle's route.
bool hasStops() const
Returns whether the vehicle has to stop somewhere.
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
Definition: MSBaseVehicle.h:74
@ ROUTE_START_INVALID_PERMISSIONS
Definition: MSBaseVehicle.h:76
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
SUMOVehicleClass getVClass() const
Returns the vehicle's access class.
virtual bool replaceRoute(const MSRoute *route, const std::string &info, bool onInit=false, int offset=0, bool addStops=true, bool removeStops=true, std::string *msgReturn=nullptr)
Replaces the current route by the given one.
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
void rememberParkingAreaScore(const MSParkingArea *pa, const std::string &score)
score only needed when running with gui
bool addStop(const SUMOVehicleParameter::Stop &stopPar, std::string &errorMsg, SUMOTime untilOffset=0, MSRouteIterator *searchStart=nullptr)
Adds a stop.
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
bool haveValidStopEdges() const
check whether all stop.edge MSRouteIterators are valid and in order
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 getRoutePosition() const
return index of edge within route
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...
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
const ConstMSEdgeVector getStopEdges(double &firstPos, double &lastPos) const
Returns the list of still pending stop edges also returns the first and last stop position.
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)
void reroute(SUMOTime t, const std::string &info, SUMOAbstractRouter< MSEdge, SUMOVehicle > &router, const bool onInit=false, const bool withTaz=false, const bool silent=false)
Performs a rerouting using the given router.
const std::vector< MSTransportable * > & getContainers() const
retrieve riding containers
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.
const ParkingMemory * getParkingMemory() const
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.
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.
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:639
Battery device for electric vehicles.
double getActualBatteryCapacity() const
Get the actual vehicle's Battery Capacity in Wh.
A device which collects info on the vehicle trip (mainly on departure and arrival)
double getCurrentFromOverheadWire() const
Get actual current in the overhead wire segment.
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)
Definition: MSDevice_Taxi.h:49
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 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:61
static void buildVehicleDevices(SUMOVehicle &v, std::vector< MSVehicleDevice * > &into)
Build devices for the given vehicle, if needed.
Definition: MSDevice.cpp:105
A road/street connecting two junctions.
Definition: MSEdge.h:77
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:1236
bool isNormal() const
return whether this edge is an internal edge
Definition: MSEdge.h:260
const std::vector< MSLane * > * allowedLanes(const MSEdge &destination, SUMOVehicleClass vclass=SVC_IGNORING) const
Get the allowed lanes to reach the destination-edge.
Definition: MSEdge.cpp:439
double getLength() const
return the length of the edge
Definition: MSEdge.h:658
bool isTazConnector() const
Definition: MSEdge.h:288
int getNumLanes() const
Definition: MSEdge.h:172
bool isInternal() const
return whether this edge is an internal edge
Definition: MSEdge.h:265
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:945
const MSEdge * getNormalBefore() const
if this edge is an internal edge, return its first normal predecessor, otherwise the edge itself
Definition: MSEdge.cpp:835
A storage for edge travel times and efforts.
static bool gUseMesoSim
Definition: MSGlobals.h:103
static bool gCheckRoutes
Definition: MSGlobals.h:88
static MELoop * gMesoNet
mesoscopic simulation infrastructure
Definition: MSGlobals.h:109
static SUMOTime gTimeToImpatience
Definition: MSGlobals.h:75
static bool gHaveEmissions
Whether emission output of some type is needed (files or GUI)
Definition: MSGlobals.h:177
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:240
const MSEdge * getNextNormal() const
Returns the lane's follower if it is an internal lane, the edge of the lane otherwise.
Definition: MSLane.cpp:2175
double getLength() const
Returns the lane's length.
Definition: MSLane.h:575
bool allowsVehicleClass(SUMOVehicleClass vclass) const
Definition: MSLane.h:856
static bool dictionary(const std::string &id, MSLane *lane)
Static (sic!) container methods {.
Definition: MSLane.cpp:2199
bool isInternal() const
Definition: MSLane.cpp:2330
SumoRNG * getRNG() const
return the associated RNG
Definition: MSLane.h:245
MSEdge & getEdge() const
Returns the lane's edge.
Definition: MSLane.h:713
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:1547
@ NEWROUTE
The vehicle got a new route.
static MSNet * getInstance()
Returns the pointer to the unique instance of MSNet (singleton).
Definition: MSNet.cpp:183
SUMOAbstractRouter< MSEdge, SUMOVehicle > & getRouterTT(const int rngIndex, const MSEdgeVector &prohibited=MSEdgeVector()) const
Definition: MSNet.cpp:1389
SUMOTime getCurrentTimeStep() const
Returns the current simulation step.
Definition: MSNet.h:321
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:1181
MSInsertionControl & getInsertionControl()
Returns the insertion control.
Definition: MSNet.h:432
MSVehicleControl & getVehicleControl()
Returns the vehicle control.
Definition: MSNet.h:379
A lane area vehicles can halt at.
Definition: MSParkingArea.h:58
void addReference() const
increments the reference counter for the route
Definition: MSRoute.cpp:99
int size() const
Returns the number of edges to pass.
Definition: MSRoute.cpp:86
const ConstMSEdgeVector & getEdges() const
Definition: MSRoute.h:124
const std::vector< SUMOVehicleParameter::Stop > & getStops() const
Returns the stops.
Definition: MSRoute.cpp:415
MSRouteIterator end() const
Returns the end of the list of edges to pass.
Definition: MSRoute.cpp:80
static bool dictionary(const std::string &id, const MSRoute *route)
Adds a route to the dictionary.
Definition: MSRoute.cpp:118
void setCosts(double costs)
Sets the costs of the route.
Definition: MSRoute.h:199
static bool hasRoute(const std::string &id)
returns whether a route with the given id exists
Definition: MSRoute.cpp:161
void release() const
deletes the route if there are no further references to it
Definition: MSRoute.cpp:105
const MSEdge * getLastEdge() const
returns the destination edge
Definition: MSRoute.cpp:92
const RGBColor & getColor() const
Returns the color.
Definition: MSRoute.cpp:406
MSRouteIterator begin() const
Returns the begin of the list of edges to pass.
Definition: MSRoute.cpp:74
static void checkDist(const std::string &id)
Checks the distribution whether it is permanent and deletes it if not.
Definition: MSRoute.cpp:199
SUMOTime getPeriod() const
returns the period
Definition: MSRoute.h:160
void setSavings(double savings)
Sets the savings of the route.
Definition: MSRoute.h:206
static SUMOAbstractRouter< MSEdge, SUMOVehicle > & getRouterTT(const int rngIndex, SUMOVehicleClass svc, const MSEdgeVector &prohibited=MSEdgeVector())
return the router instance
Definition: MSStop.h:44
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:111
const MESegment * segment
The segment to stop at (mesosim only)
Definition: MSStop.h:52
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
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
bool isPerson() const
Whether it is a person.
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.
void removeVType(const MSVehicleType *vehType)
Abstract in-vehicle device.
Representation of a vehicle in the micro simulation.
Definition: MSVehicle.h:77
MSAbstractLaneChangeModel & getLaneChangeModel()
Definition: MSVehicle.cpp:5367
const MSCFModel & getCarFollowModel() const
Returns the vehicle's car following model definition.
Definition: MSVehicle.h:966
The car-following model and parameter.
Definition: MSVehicleType.h:63
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.
Definition: MSVehicleType.h:91
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].
MSVehicleType * buildSingularType(const std::string &id) const
Duplicates the microsim vehicle type giving the newly created type the given id, marking it as vehicl...
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.
Definition: OptionsCont.cpp:59
Static storage of an output device and its base (abstract) implementation.
Definition: OutputDevice.h:61
OutputDevice & writeAttr(const SumoXMLAttr attr, const T &val)
writes a named attribute
Definition: OutputDevice.h:251
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.
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)
Definition: RandHelper.cpp:94
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,...
double recomputeCosts(const std::vector< const E * > &edges, const V *const v, SUMOTime msTime, double *lengthp=nullptr) const
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 SUMOTime getWaitingTime() const =0
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 double getPositionOnLane() const =0
Get the object's position along the lane.
Representation of a vehicle.
Definition: SUMOVehicle.h:60
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 (used only in NETEDIT)
ParkingType parking
whether the vehicle is removed from the net while stopping
std::string lane
The lane to stop at.
double startPos
The stopping position start.
int index
at which position in the stops list
SUMOTime until
The time at which the vehicle may continue its journey.
bool triggered
whether an arriving person lets the vehicle continue
double endPos
The stopping position end.
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.
int parametersSet
Information for the router which parameter were set, TraCI may modify this (when changing color)
ArrivalSpeedDefinition arrivalSpeedProcedure
Information how the vehicle's end speed shall be chosen.
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.
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.
double departPos
(optional) The position the vehicle shall depart from
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< 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
bool wasSet(int what) const
Returns whether the given parameter was set.
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
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.
TRACI_CONST int ROUTING_MODE_AGGREGATED
TRACI_CONST int ROUTING_MODE_DEFAULT