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-2023 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 }
132 if ((pars->parametersSet & VEHPARS_FORCE_REROUTE) == 0) {
134 }
135 if (!pars->wasSet(VEHPARS_FORCE_REROUTE)) {
137 }
139}
140
141
143 delete myEdgeWeights;
144 if (myParameter->repetitionNumber == 0) {
146 }
147 for (MSVehicleDevice* dev : myDevices) {
148 delete dev;
149 }
150 delete myParameter;
151 delete myEnergyParams;
152 delete myParkingMemory;
153 myRoute->checkRemoval();
154}
155
156
157void
160 for (MSVehicleDevice* dev : myDevices) {
161 myMoveReminders.push_back(std::make_pair(dev, 0.));
162 }
164 // ensure we have the emission parameters even if we don't have the device
166 }
167}
168
169
170void
171MSBaseVehicle::setID(const std::string& /*newID*/) {
172 throw ProcessError(TL("Changing a vehicle ID is not permitted"));
173}
174
177 return *myParameter;
178}
179
180
181void
183 delete myParameter;
184 myParameter = newParameter;
185}
186
187double
190}
191
192
193const MSEdge*
194MSBaseVehicle::succEdge(int nSuccs) const {
195 if (myCurrEdge + nSuccs < myRoute->end() && std::distance(myCurrEdge, myRoute->begin()) <= nSuccs) {
196 return *(myCurrEdge + nSuccs);
197 } else {
198 return nullptr;
199 }
200}
201
202
203const MSEdge*
205 return *myCurrEdge;
206}
207
208
209bool
211 if (stop == nullptr) {
212 return false;
213 }
214 for (const MSStop& s : myStops) {
215 if (s.busstop == stop
216 || s.containerstop == stop
217 || s.parkingarea == stop
218 || s.chargingStation == stop) {
219 return true;
220 }
221 }
222 return false;
223}
224
225bool
227 for (const MSStop& s : myStops) {
228 if (&s.lane->getEdge() == edge) {
229 return true;
230 }
231 }
232 return false;
233}
234
235
236void
237MSBaseVehicle::reroute(SUMOTime t, const std::string& info, SUMOAbstractRouter<MSEdge, SUMOVehicle>& router, const bool onInit, const bool withTaz, const bool silent) {
238 // check whether to reroute
239 const MSEdge* source = withTaz && onInit ? MSEdge::dictionary(myParameter->fromTaz + "-source") : *getRerouteOrigin();
240 if (source == nullptr) {
241 source = *getRerouteOrigin();
242 }
243 const MSEdge* sink = withTaz ? MSEdge::dictionary(myParameter->toTaz + "-sink") : myRoute->getLastEdge();
244 if (sink == nullptr) {
245 sink = myRoute->getLastEdge();
246 }
247 ConstMSEdgeVector oldEdgesRemaining(source == *myCurrEdge ? myCurrEdge : myCurrEdge + 1, myRoute->end());
248 ConstMSEdgeVector edges;
249 ConstMSEdgeVector stops;
250 std::set<int> jumps;
251 if (myParameter->via.size() == 0) {
252 double firstPos = -1;
253 double lastPos = -1;
254 stops = getStopEdges(firstPos, lastPos, jumps);
255 if (stops.size() > 0) {
256 const double sourcePos = onInit ? 0 : getPositionOnLane();
257 // avoid superfluous waypoints for first and last edge
258 const bool skipFirst = stops.front() == source && (source != getEdge() || sourcePos + getBrakeGap() <= firstPos);
259 const bool skipLast = stops.back() == sink && myArrivalPos >= lastPos && (
260 stops.size() < 2 || stops.back() != stops[stops.size() - 2]);
261#ifdef DEBUG_REROUTE
262 if (DEBUG_COND) {
263 std::cout << SIMTIME << " reroute " << info << " veh=" << getID() << " lane=" << Named::getIDSecure(getLane())
264 << " source=" << source->getID() << " sourcePos=" << sourcePos << " firstPos=" << firstPos << " arrivalPos=" << myArrivalPos << " lastPos=" << lastPos
265 << " route=" << toString(myRoute->getEdges()) << " stopEdges=" << toString(stops) << " skipFirst=" << skipFirst << " skipLast=" << skipLast << "\n";
266 }
267#endif
268 if (stops.size() == 1 && (skipFirst || skipLast)) {
269 stops.clear();
270 } else {
271 if (skipFirst) {
272 stops.erase(stops.begin());
273 }
274 if (skipLast) {
275 stops.erase(stops.end() - 1);
276 }
277 }
278 }
279 } else {
280 // via takes precedence over stop edges
281 // there is a consistency check in MSRouteHandler::addStop that warns when a stop edge is not part of the via edges
282 for (std::vector<std::string>::const_iterator it = myParameter->via.begin(); it != myParameter->via.end(); ++it) {
283 MSEdge* viaEdge = MSEdge::dictionary(*it);
284 if (viaEdge == source || viaEdge == sink) {
285 continue;
286 }
287 assert(viaEdge != 0);
288 if (!viaEdge->isTazConnector() && viaEdge->allowedLanes(getVClass()) == nullptr) {
289 throw ProcessError(TLF("Vehicle '%' is not allowed on any lane of via edge '%'.", getID(), viaEdge->getID()));
290 }
291 stops.push_back(viaEdge);
292 }
293 }
294
295 int stopIndex = -1;
296 for (const MSEdge* const stopEdge : stops) {
297 stopIndex++;
298 // !!! need to adapt t here
300 if (jumps.count(stopIndex) != 0) {
301 edges.push_back(source);
302 source = stopEdge;
303 continue;
304 }
305 router.computeLooped(source, stopEdge, this, t, into, silent);
306 //std::cout << SIMTIME << " reroute veh=" << getID() << " source=" << source->getID() << " target=" << (*s)->getID() << " edges=" << toString(into) << "\n";
307 if (into.size() > 0) {
308 into.pop_back();
309 edges.insert(edges.end(), into.begin(), into.end());
310 if (stopEdge->isTazConnector()) {
311 source = into.back();
312 edges.pop_back();
313 } else {
314 source = stopEdge;
315 }
316 } else {
317 std::string error = TLF("Vehicle '%' has no valid route from edge '%' to stop edge '%'.", getID(), source->getID(), stopEdge->getID());
318 if (MSGlobals::gCheckRoutes || silent) {
319 throw ProcessError(error);
320 } else {
321 WRITE_WARNING(error);
322 edges.push_back(source);
323 }
324 source = stopEdge;
325 }
326 }
327 if (stops.empty() && source == sink && onInit
331 router.computeLooped(source, sink, this, t, edges, silent);
332 } else {
333 if (!router.compute(source, sink, this, t, edges, silent)) {
334 edges.clear();
335 }
336 }
337
338 // router.setHint(myCurrEdge, myRoute->end(), this, t);
339 if (edges.empty() && silent) {
340 return;
341 }
342 if (!edges.empty() && edges.front()->isTazConnector()) {
343 edges.erase(edges.begin());
344 }
345 if (!edges.empty() && edges.back()->isTazConnector()) {
346 edges.pop_back();
347 }
348 const double routeCost = router.recomputeCosts(edges, this, t);
349 const double previousCost = onInit ? routeCost : router.recomputeCosts(oldEdgesRemaining, this, t);
350 const double savings = previousCost - routeCost;
351 //if (getID() == "43") std::cout << SIMTIME << " pCost=" << previousCost << " cost=" << routeCost
352 // << " onInit=" << onInit
353 // << " prevEdges=" << toString(oldEdgesRemaining)
354 // << " newEdges=" << toString(edges)
355 // << "\n";
356 replaceRouteEdges(edges, routeCost, savings, info, onInit);
357 // this must be called even if the route could not be replaced
358 if (onInit) {
359 if (edges.empty()) {
361 throw ProcessError(TLF("Vehicle '%' has no valid route.", getID()));
362 } else if (source->isTazConnector()) {
363 WRITE_WARNINGF(TL("Removing vehicle '%' which has no valid route."), getID());
365 return;
366 }
367 }
370 }
371}
372
373
374bool
375MSBaseVehicle::replaceRouteEdges(ConstMSEdgeVector& edges, double cost, double savings, const std::string& info, bool onInit, bool check, bool removeStops, std::string* msgReturn) {
376 if (edges.empty()) {
377 WRITE_WARNINGF(TL("No route for vehicle '%' found."), getID());
378 if (msgReturn != nullptr) {
379 *msgReturn = "No route found";
380 }
381 return false;
382 }
383 // build a new id, first
384 std::string id = getID();
385 if (id[0] != '!') {
386 id = "!" + id;
387 }
388 const std::string idSuffix = id + "!var#";
389 int varIndex = 1;
390 id = idSuffix + toString(varIndex);
391 while (MSRoute::hasRoute(id)) {
392 id = idSuffix + toString(++varIndex);
393 }
394 int oldSize = (int)edges.size();
395 if (!onInit) {
396 const MSEdge* const origin = *getRerouteOrigin();
397 if (origin != *myCurrEdge && edges.front() == origin) {
398 edges.insert(edges.begin(), *myCurrEdge);
399 oldSize = (int)edges.size();
400 }
401 edges.insert(edges.begin(), myRoute->begin(), myCurrEdge);
402 }
403 if (edges == myRoute->getEdges() && haveValidStopEdges(true)) {
404 // re-assign stop iterators when rerouting to a new parkingArea / insertStop
405 return true;
406 }
407 const RGBColor& c = myRoute->getColor();
408 MSRoute* newRoute = new MSRoute(id, edges, false, &c == &RGBColor::DEFAULT_COLOR ? nullptr : new RGBColor(c), std::vector<SUMOVehicleParameter::Stop>());
409 newRoute->setCosts(cost);
410 newRoute->setSavings(savings);
411 ConstMSRoutePtr constRoute = std::shared_ptr<MSRoute>(newRoute);
412 if (!MSRoute::dictionary(id, constRoute)) {
413 delete newRoute;
414 if (msgReturn != nullptr) {
415 *msgReturn = "duplicate routeID '" + id + "'";
416 }
417 return false;
418 }
419
420 std::string msg;
421 if (check && !hasValidRoute(msg, constRoute)) {
422 WRITE_WARNINGF(TL("Invalid route replacement for vehicle '%'. %"), getID(), msg);
424 if (msgReturn != nullptr) {
425 *msgReturn = msg;
426 }
427 return false;
428 }
429 }
430 if (!replaceRoute(constRoute, info, onInit, (int)edges.size() - oldSize, false, removeStops, msgReturn)) {
431 return false;
432 }
433 return true;
434}
435
436
437bool
438MSBaseVehicle::replaceRoute(ConstMSRoutePtr newRoute, const std::string& info, bool onInit, int offset, bool addRouteStops, bool removeStops, std::string* msgReturn) {
439 const ConstMSEdgeVector& edges = newRoute->getEdges();
440 // rebuild in-vehicle route information
441 if (onInit) {
442 myCurrEdge = newRoute->begin();
443 } else {
444 MSRouteIterator newCurrEdge = std::find(edges.begin() + offset, edges.end(), *myCurrEdge);
445 if (newCurrEdge == edges.end()) {
446 if (msgReturn != nullptr) {
447 *msgReturn = TLF("current edge '%' not found in new route", (*myCurrEdge)->getID());
448 }
449#ifdef DEBUG_REPLACE_ROUTE
450 if (DEBUG_COND) {
451 std::cout << " newCurrEdge not found\n";
452 }
453#endif
454 return false;
455 }
456 if (getLane() != nullptr) {
457 if (getLane()->getEdge().isInternal() && (
458 (newCurrEdge + 1) == edges.end() || (*(newCurrEdge + 1)) != &(getLane()->getOutgoingViaLanes().front().first->getEdge()))) {
459 if (msgReturn != nullptr) {
460 *msgReturn = TL("Vehicle is on junction-internal edge leading elsewhere");
461 }
462#ifdef DEBUG_REPLACE_ROUTE
463 if (DEBUG_COND) {
464 std::cout << " Vehicle is on junction-internal edge leading elsewhere\n";
465 }
466#endif
467 return false;
468 } else if (getPositionOnLane() > getLane()->getLength()
469 && (myCurrEdge + 1) != myRoute->end()
470 && (newCurrEdge + 1) != edges.end()
471 && *(myCurrEdge + 1) != *(newCurrEdge + 1)) {
472 if (msgReturn != nullptr) {
473 *msgReturn = TL("Vehicle is moving past junction and committed to move to another successor edge");
474 }
475#ifdef DEBUG_REPLACE_ROUTE
476 if (DEBUG_COND) {
477 std::cout << " Vehicle is moving past junction and committed to move to another successor edge\n";
478 }
479#endif
480 return false;
481 }
482 }
483 myCurrEdge = newCurrEdge;
484 }
485 const bool stopsFromScratch = onInit && myRoute->getStops().empty();
486 // assign new route
487 myRoute->checkRemoval();
488 myRoute = newRoute;
489 // update arrival definition
491 // save information that the vehicle was rerouted
493 myStopUntilOffset += myRoute->getPeriod();
495#ifdef DEBUG_REPLACE_ROUTE
496 if (DEBUG_COND) {
497 std::cout << SIMTIME << " replaceRoute info=" << info << " on " << (*myCurrEdge)->getID()
498 << " lane=" << Named::getIDSecure(getLane())
499 << " stopsFromScratch=" << stopsFromScratch
500 << " newSize=" << newRoute->getEdges().size()
501 << " newIndex=" << (myCurrEdge - newRoute->begin())
502 << " edges=" << toString(newRoute->getEdges())
503 << "\n";
504 }
505#endif
506 // if we did not drive yet it may be best to simply reassign the stops from scratch
507 if (stopsFromScratch) {
508 myStops.clear();
510 } else {
511 // recheck old stops
512 MSRouteIterator searchStart = myCurrEdge;
513 double lastPos = getPositionOnLane() + getBrakeGap();
514 if (getLane() != nullptr && getLane()->isInternal()
515 && myStops.size() > 0 && !myStops.front().lane->isInternal()) {
516 // searchStart is still incoming to the intersection so lastPos
517 // relative to that edge must be adapted
518 lastPos += (*myCurrEdge)->getLength();
519 }
520 for (std::list<MSStop>::iterator iter = myStops.begin(); iter != myStops.end();) {
521 double endPos = iter->getEndPos(*this);
522#ifdef DEBUG_REPLACE_ROUTE
523 if (DEBUG_COND) {
524 std::cout << " stopEdge=" << iter->lane->getEdge().getID() << " start=" << (searchStart - myCurrEdge) << " endPos=" << endPos << " lastPos=" << lastPos << "\n";
525 }
526#endif
527 if (*searchStart != &iter->lane->getEdge()
528 || endPos + NUMERICAL_EPS < lastPos) {
529 if (searchStart != edges.end() && !iter->reached) {
530 searchStart++;
531 }
532 }
533 lastPos = endPos;
534
535 iter->edge = std::find(searchStart, edges.end(), &iter->lane->getEdge());
536#ifdef DEBUG_REPLACE_ROUTE
537 if (DEBUG_COND) {
538 std::cout << " foundIndex=" << (iter->edge - myCurrEdge) << " end=" << (edges.end() - myCurrEdge) << "\n";
539 }
540#endif
541 if (iter->edge == edges.end()) {
542 if (!removeStops) {
543 WRITE_ERRORF(TL("Vehicle '%' could not assign stop '%' after rerouting (%) at time=%."), getID(), iter->getDescription(), info, time2string(SIMSTEP));
544 }
545 iter = myStops.erase(iter);
546 continue;
547 } else {
548 searchStart = iter->edge;
549 }
550 ++iter;
551 }
552 // add new stops
553 if (addRouteStops) {
554 for (std::vector<SUMOVehicleParameter::Stop>::const_iterator i = newRoute->getStops().begin(); i != newRoute->getStops().end(); ++i) {
555 std::string error;
557 if (error != "") {
558 WRITE_WARNING(error);
559 }
560 }
561 }
562 }
563 return true;
564}
565
566
567double
569 return 0;
570}
571
572
573void
578}
579
580
583 const SUMOTime dep = getParameter().depart;
584 if (dep < 0) {
585 return 0;
586 }
587 return hasDeparted() ? getDeparture() - dep : SIMSTEP - dep;
588}
589
590
591bool
593 return succEdge(1) == nullptr;
594}
595
596
597int
599 return (int) std::distance(myRoute->begin(), myCurrEdge);
600}
601
602
603void
605 myCurrEdge = myRoute->begin() + index;
606 const_cast<SUMOVehicleParameter*>(myParameter)->departLaneProcedure = departLaneProcedure;
607 // !!! hack
608 myArrivalPos = (*(myRoute->end() - 1))->getLanes()[0]->getLength();
609}
610
611double
614}
615
616bool
618 if (t->isPerson() && getPersonNumber() >= getVehicleType().getPersonCapacity()) {
619 return false;
620 } else if (!t->isPerson() && getContainerNumber() >= getVehicleType().getContainerCapacity()) {
621 return false;
622 }
623 if (isStopped() && myStops.begin()->pars.permitted.size() > 0
624 && myStops.begin()->pars.permitted.count(t->getID()) == 0) {
625 return false;
626 }
627 MSDevice_Taxi* taxiDevice = static_cast<MSDevice_Taxi*>(getDevice(typeid(MSDevice_Taxi)));
628 if (taxiDevice != nullptr) {
629 return taxiDevice->allowsBoarding(t);
630 }
631 return true;
632}
633
634
635void
637 if (transportable->isPerson()) {
638 if (myPersonDevice == nullptr) {
640 myMoveReminders.push_back(std::make_pair(myPersonDevice, 0.));
643 }
644 }
645 myPersonDevice->addTransportable(transportable);
646 } else {
647 if (myContainerDevice == nullptr) {
649 myMoveReminders.push_back(std::make_pair(myContainerDevice, 0.));
652 }
653 }
654 myContainerDevice->addTransportable(transportable);
655 }
656}
657
658
659bool
661 for (const MSStop& stop : myStops) {
662 if (stop.edge == it) {
663 return stop.pars.jump >= 0;
664 }
665 }
666 return false;
667}
668
669
670bool
671MSBaseVehicle::hasValidRoute(std::string& msg, ConstMSRoutePtr route) const {
673 if (route == nullptr) {
674 route = myRoute;
675 } else {
676 start = route->begin();
677 }
678 MSRouteIterator last = route->end() - 1;
679 // check connectivity, first
680 for (MSRouteIterator e = start; e != last; ++e) {
681 if ((*e)->allowedLanes(**(e + 1), myType->getVehicleClass()) == nullptr) {
682 if (!hasJump(e)) {
683 msg = TLF("No connection between edge '%' and edge '%'.", (*e)->getID(), (*(e + 1))->getID());
684 return false;
685 }
686 }
687 }
688 last = route->end();
689 // check usable lanes, then
690 for (MSRouteIterator e = start; e != last; ++e) {
691 if ((*e)->prohibits(this)) {
692 msg = TLF("Edge '%' prohibits.", (*e)->getID());
693 return false;
694 }
695 }
696 return true;
697}
698
699
700bool
702 if (myRoute->getEdges().size() > 0 && !(*myCurrEdge)->prohibits(this)) {
703 myRouteValidity &= ~ROUTE_START_INVALID_PERMISSIONS;
704 return true;
705 } else {
706 msg = TLF("Vehicle '%' is not allowed to depart on its first edge.", getID());
708 return false;
709 }
710}
711
712
713int
714MSBaseVehicle::getRouteValidity(bool update, bool silent, std::string* msgReturn) {
715 if (!update) {
716 return myRouteValidity;
717 }
718 // insertion check must be done in any case
719 std::string msg;
720 if (!hasValidRouteStart(msg)) {
722 throw ProcessError(msg);
723 } else if (!silent) {
724 // vehicle will be discarded
725 WRITE_WARNING(msg);
726 } else if (msgReturn != nullptr) {
727 *msgReturn = msg;
728 }
729 }
732 // we could check after the first rerouting
734 if (!hasValidRoute(msg, myRoute)) {
736 throw ProcessError(TLF("Vehicle '%' has no valid route. %", getID(), msg));
737 }
738 }
739 myRouteValidity &= ~ROUTE_UNCHECKED;
740 return myRouteValidity;
741}
742
743void
745#ifdef _DEBUG
746 if (myTraceMoveReminders) {
747 traceMoveReminder("add", rem, 0, true);
748 }
749#endif
750 myMoveReminders.push_back(std::make_pair(rem, 0.));
751}
752
753
754void
756 for (MoveReminderCont::iterator r = myMoveReminders.begin(); r != myMoveReminders.end(); ++r) {
757 if (r->first == rem) {
758#ifdef _DEBUG
759 if (myTraceMoveReminders) {
760 traceMoveReminder("remove", rem, 0, false);
761 }
762#endif
763 myMoveReminders.erase(r);
764 return;
765 }
766 }
767}
768
769
770void
772 for (MoveReminderCont::iterator rem = myMoveReminders.begin(); rem != myMoveReminders.end();) {
773 if (rem->first->notifyEnter(*this, reason, enteredLane)) {
774#ifdef _DEBUG
775 if (myTraceMoveReminders) {
776 traceMoveReminder("notifyEnter", rem->first, rem->second, true);
777 }
778#endif
779 ++rem;
780 } else {
781#ifdef _DEBUG
782 if (myTraceMoveReminders) {
783 traceMoveReminder("notifyEnter", rem->first, rem->second, false);
784 }
785#endif
786 rem = myMoveReminders.erase(rem);
787 }
788 }
789}
790
791
792void
794 if (myRoute->getLastEdge()->isTazConnector()) {
795 return;
796 }
797 const int arrivalEdgeIndex = MIN2(myParameter->arrivalEdge, (int)myRoute->getEdges().size() - 1);
798 if (arrivalEdgeIndex != myParameter->arrivalEdge) {
799 WRITE_WARNINGF(TL("Vehicle '%' ignores attribute arrivalEdge=% after rerouting at time=% (routeLength=%)"),
800 getID(), myParameter->arrivalEdge, time2string(SIMSTEP), myRoute->getEdges().size() - 1);
801 }
802 const MSEdge* arrivalEdge = myParameter->arrivalEdge >= 0 ? myRoute->getEdges()[arrivalEdgeIndex] : myRoute->getLastEdge();
803 if (!onInit) {
804 arrivalEdge = myRoute->getLastEdge();
805 // ignore arrivalEdge parameter after rerouting
806 const_cast<SUMOVehicleParameter*>(myParameter)->arrivalEdge = -1;
807 }
808 const std::vector<MSLane*>& lanes = arrivalEdge->getLanes();
809 const double lastLaneLength = lanes[0]->getLength();
812 if (fabs(myParameter->arrivalPos) > lastLaneLength) {
813 WRITE_WARNINGF(TL("Vehicle '%' will not be able to arrive at the given position!"), getID());
814 }
815 // Maybe we should warn the user about invalid inputs!
816 myArrivalPos = MIN2(myParameter->arrivalPos, lastLaneLength);
817 if (myArrivalPos < 0) {
818 myArrivalPos = MAX2(myArrivalPos + lastLaneLength, 0.);
819 }
820 break;
822 myArrivalPos = RandHelper::rand(lastLaneLength);
823 break;
825 myArrivalPos = lastLaneLength / 2.;
826 break;
827 default:
828 myArrivalPos = lastLaneLength;
829 break;
830 }
832 if (myParameter->arrivalLane >= (int)lanes.size() || !lanes[myParameter->arrivalLane]->allowsVehicleClass(myType->getVehicleClass())) {
833 WRITE_WARNINGF(TL("Vehicle '%' will not be able to arrive at the given lane '%_%'!"), getID(), arrivalEdge->getID(), toString(myParameter->arrivalLane));
834 }
835 myArrivalLane = MIN2(myParameter->arrivalLane, (int)(lanes.size() - 1));
837 myArrivalLane = -1;
838 for (MSLane* lane : lanes) {
839 if (lane->allowsVehicleClass(myType->getVehicleClass())) {
840 myArrivalLane = lane->getIndex();
841 break;
842 }
843 }
844 if (myArrivalLane == -1) {
845 WRITE_WARNINGF(TL("Vehicle '%' has no usable arrivalLane on edge '%'."), getID(), arrivalEdge->getID());
846 myArrivalLane = 0;
847 }
849 // pick random lane among all usable lanes
850 std::vector<MSLane*> usable;
851 for (MSLane* lane : lanes) {
852 if (lane->allowsVehicleClass(myType->getVehicleClass())) {
853 usable.push_back(lane);
854 }
855 }
856 if (usable.empty()) {
857 WRITE_WARNINGF(TL("Vehicle '%' has no usable arrivalLane on edge '%'."), getID(), arrivalEdge->getID());
858 myArrivalLane = 0;
859 } else {
860 myArrivalLane = usable[RandHelper::rand(0, (int)usable.size())]->getIndex();
861 }
862 }
864 for (std::vector<MSLane*>::const_iterator l = lanes.begin(); l != lanes.end(); ++l) {
865 if (myParameter->arrivalSpeed <= (*l)->getVehicleMaxSpeed(this)) {
866 return;
867 }
868 }
869 WRITE_WARNINGF(TL("Vehicle '%' will not be able to arrive with the given speed!"), getID());
870 }
871}
872
873void
877 const int routeEdges = (int)myRoute->getEdges().size();
879 // write specific edge in vehroute output for reproducibility
880 pars->departEdge = RandHelper::rand(0, routeEdges);
882 }
883 assert(pars->departEdge >= 0);
884 if (pars->departEdge >= routeEdges) {
885 WRITE_WARNINGF(TL("Ignoring departEdge % for vehicle '% with % route edges"), toString(pars->departEdge), getID(), toString(routeEdges));
886 } else {
887 myCurrEdge += pars->departEdge;
888 }
889 }
891 const int routeEdges = (int)myRoute->getEdges().size();
892 const int begin = (int)(myCurrEdge - myRoute->begin());
893 // write specific edge in vehroute output for reproducibility
894 pars->arrivalEdge = RandHelper::rand(begin, routeEdges);
896 assert(pars->arrivalEdge >= begin);
897 assert(pars->arrivalEdge < routeEdges);
898 }
899}
900
901
902double
904 return MAX2(0., MIN2(1., getVehicleType().getImpatience() +
906}
907
908
910MSBaseVehicle::getDevice(const std::type_info& type) const {
911 for (MSVehicleDevice* const dev : myDevices) {
912 if (typeid(*dev) == type) {
913 return dev;
914 }
915 }
916 return nullptr;
917}
918
919
920void
922 // the parameters may hold the name of a vTypeDistribution but we are interested in the actual type
925 // params and stops must be written in child classes since they may wish to add additional attributes first
926 out.writeAttr(SUMO_ATTR_ROUTE, myRoute->getID());
927 std::ostringstream os;
928 os << myOdometer << " " << myNumberReroutes;
929 out.writeAttr(SUMO_ATTR_DISTANCE, os.str());
931 const int precision = out.precision();
932 out.setPrecision(MAX2(gPrecisionRandom, precision));
934 out.setPrecision(precision);
935 }
937 out.writeAttr(SUMO_ATTR_REROUTE, true);
938 }
940 // could be set from stop
942 }
943 // here starts the vehicle internal part (see loading)
944 // @note: remember to close the vehicle tag when calling this in a subclass!
945}
946
947
948bool
949MSBaseVehicle::handleCollisionStop(MSStop& stop, const double distToStop) {
950 UNUSED_PARAMETER(stop);
951 UNUSED_PARAMETER(distToStop);
952 return true;
953}
954
955
956bool
958 return !myStops.empty() && myStops.begin()->reached /*&& myState.mySpeed < SUMO_const_haltingSpeed @todo #1864#*/;
959}
960
961
962bool
964 return (isStopped() && (myStops.begin()->pars.parking == ParkingType::OFFROAD)
965 && (myStops.begin()->parkingarea == nullptr || !myStops.begin()->parkingarea->parkOnRoad())
966 && (myStops.begin()->getSpeed() == 0 || getSpeed() < SUMO_const_haltingSpeed));
967}
968
969
970bool
972 return myPastStops.size() > 0 && myPastStops.back().jump >= 0 && getEdge()->getID() == myPastStops.back().edge;
973}
974
975
976bool
978 return isStopped() && (myStops.begin()->triggered || myStops.begin()->containerTriggered || myStops.begin()->joinTriggered);
979}
980
981
982bool
984 return isStopped() && (myStops.begin()->pars.parking == ParkingType::OFFROAD);
985}
986
987
988bool
989MSBaseVehicle::isStoppedInRange(const double pos, const double tolerance, bool checkFuture) const {
990 if (isStopped() || (checkFuture && hasStops())) {
991 const MSStop& stop = myStops.front();
992 return stop.pars.startPos - tolerance <= pos && stop.pars.endPos + tolerance >= pos;
993 }
994 return false;
995}
996
997
998double
999MSBaseVehicle::basePos(const MSEdge* edge) const {
1000 double result = MIN2(getVehicleType().getLength() + POSITION_EPS, edge->getLength());
1001 if (hasStops()
1002 && myStops.front().edge == myRoute->begin()
1003 && (&myStops.front().lane->getEdge()) == *myStops.front().edge) {
1004 result = MIN2(result, MAX2(0.0, myStops.front().getEndPos(*this)));
1005 }
1006 return result;
1007}
1008
1009MSLane*
1011 const std::string edgeID = SUMOXMLDefinitions::getEdgeIDFromLane(stop.lane);
1012 const int laneIndex = SUMOXMLDefinitions::getIndexFromLane(stop.lane);
1013 const MSEdge* edge = MSEdge::dictionary(edgeID);
1014 if (edge != nullptr && edge->getOppositeEdge() != nullptr
1015 && laneIndex < (edge->getNumLanes() + edge->getOppositeEdge()->getNumLanes())) {
1016 const int oppositeIndex = edge->getOppositeEdge()->getNumLanes() + edge->getNumLanes() - 1 - laneIndex;
1017 stop.edge = edgeID;
1018 return edge->getOppositeEdge()->getLanes()[oppositeIndex];
1019 } else {
1020 return nullptr;
1021 }
1022}
1023
1024bool
1025MSBaseVehicle::addStop(const SUMOVehicleParameter::Stop& stopPar, std::string& errorMsg, SUMOTime untilOffset,
1026 MSRouteIterator* searchStart) {
1027 MSStop stop(stopPar);
1028 if (stopPar.lane == "") {
1029 // use rightmost allowed lane
1030 MSEdge* e = MSEdge::dictionary(stopPar.edge);
1031 for (MSLane* cand : e->getLanes()) {
1032 if (cand->allowsVehicleClass(getVClass())) {
1033 stop.lane = cand;
1034 break;
1035 }
1036 }
1037 if (stop.lane == nullptr) {
1038 errorMsg = "Vehicle '" + myParameter->id + "' is not allowed to stop on any lane of edge '" + stopPar.edge + "'.";
1039 return false;
1040 }
1041 } else {
1042 stop.lane = MSLane::dictionary(stopPar.lane);
1043 if (stop.lane == nullptr) {
1044 // must be an opposite stop
1045 SUMOVehicleParameter::Stop tmp = stopPar;
1046 stop.lane = interpretOppositeStop(tmp);
1047 assert(stop.lane != nullptr);
1048 }
1050 errorMsg = "Vehicle '" + myParameter->id + "' is not allowed to stop on lane '" + stopPar.lane + "'.";
1051 return false;
1052 }
1053 }
1055 stop.segment = MSGlobals::gMesoNet->getSegmentForEdge(stop.lane->getEdge(), stop.getEndPos(*this));
1056 if (stop.lane->isInternal()) {
1057 errorMsg = "Mesoscopic simulation does not allow stopping on internal edge '" + stopPar.edge + "' for vehicle '" + myParameter->id + "'.";
1058 return false;
1059 }
1060 }
1061 stop.initPars(stopPar);
1062 if (stopPar.until != -1) {
1063 // !!! it would be much cleaner to invent a constructor for stops which takes "until" as an argument
1064 const_cast<SUMOVehicleParameter::Stop&>(stop.pars).until += untilOffset;
1065 }
1066 if (stopPar.arrival != -1) {
1067 const_cast<SUMOVehicleParameter::Stop&>(stop.pars).arrival += untilOffset;
1068 }
1069 std::string stopType = "stop";
1070 std::string stopID = "";
1071 if (stop.busstop != nullptr) {
1072 stopType = "busStop";
1073 stopID = stop.busstop->getID();
1074 } else if (stop.containerstop != nullptr) {
1075 stopType = "containerStop";
1076 stopID = stop.containerstop->getID();
1077 } else if (stop.chargingStation != nullptr) {
1078 stopType = "chargingStation";
1079 stopID = stop.chargingStation->getID();
1080 } else if (stop.overheadWireSegment != nullptr) {
1081 stopType = "overheadWireSegment";
1082 stopID = stop.overheadWireSegment->getID();
1083 } else if (stop.parkingarea != nullptr) {
1084 stopType = "parkingArea";
1085 stopID = stop.parkingarea->getID();
1086 }
1087 const std::string errorMsgStart = stopID == "" ? stopType : stopType + " '" + stopID + "'";
1088
1089 if (stop.pars.startPos < 0 || stop.pars.endPos > stop.lane->getLength()) {
1090 errorMsg = errorMsgStart + " for vehicle '" + myParameter->id + "' on lane '" + stop.lane->getID() + "' has an invalid position.";
1091 return false;
1092 }
1093 if (stopType != "stop" && stopType != "parkingArea" && myType->getLength() / 2. > stop.pars.endPos - stop.pars.startPos
1094 && MSNet::getInstance()->warnOnce(stopType + ":" + stopID)) {
1095 errorMsg = errorMsgStart + " on lane '" + stop.lane->getID() + "' is too short for vehicle '" + myParameter->id + "'.";
1096 }
1097 const MSEdge* stopLaneEdge = &stop.lane->getEdge();
1098 const MSEdge* stopEdge;
1099 if (stopLaneEdge->getOppositeEdge() != nullptr && stopLaneEdge->getOppositeEdge()->getID() == stopPar.edge) {
1100 // stop lane is on the opposite side
1101 stopEdge = stopLaneEdge->getOppositeEdge();
1102 stop.isOpposite = true;
1103 } else {
1104 // if stop is on an internal edge the normal edge before the intersection is used
1105 stopEdge = stopLaneEdge->getNormalBefore();
1106 }
1107 MSRouteIterator succ = myCurrEdge + 1; // we're using the address but only within the scope of this function (and recursive calls)
1108 if (searchStart == nullptr) {
1109 searchStart = &myCurrEdge;
1110 if (stopLaneEdge->isNormal() && getLane() != nullptr && getLane()->isInternal()) {
1111 // already on the intersection but myCurrEdge is before it
1112 searchStart = &succ;
1113 }
1114 }
1115#ifdef DEBUG_ADD_STOP
1116 if (DEBUG_COND) {
1117 std::cout << "addStop desc=" << stop.getDescription() << " stopEdge=" << stopEdge->getID()
1118 << " searchStart=" << ((*searchStart) == myRoute->end() ? "END" : (**searchStart)->getID())
1119 << " index=" << (int)((*searchStart) - myRoute->begin()) << " route=" << toString(myRoute->getEdges())
1120 << "\n";
1121 }
1122#endif
1123 stop.edge = std::find(*searchStart, myRoute->end(), stopEdge);
1124 MSRouteIterator prevStopEdge = myCurrEdge;
1125 const MSEdge* prevEdge = (getLane() == nullptr ? getEdge() : &getLane()->getEdge());
1126 double prevStopPos = getPositionOnLane();
1127 // where to insert the stop
1128 std::list<MSStop>::iterator iter = myStops.begin();
1129 if (stopPar.index == STOP_INDEX_END || stopPar.index >= static_cast<int>(myStops.size())) {
1130 iter = myStops.end();
1131 if (myStops.size() > 0 && myStops.back().edge >= *searchStart) {
1132 prevStopEdge = myStops.back().edge;
1133 prevEdge = &myStops.back().lane->getEdge();
1134 prevStopPos = myStops.back().pars.endPos;
1135 stop.edge = std::find(prevStopEdge, myRoute->end(), stopEdge);
1136 if (prevStopEdge == stop.edge // laneEdge check is insufficient for looped routes
1137 && prevEdge == &stop.lane->getEdge() // route iterator check insufficient for internal lane stops
1138 && prevStopPos > stop.pars.endPos) {
1139 stop.edge = std::find(prevStopEdge + 1, myRoute->end(), stopEdge);
1140 }
1141#ifdef DEBUG_ADD_STOP
1142 if (DEBUG_COND) {
1143 std::cout << " (@end) prevStopEdge=" << (*prevStopEdge)->getID() << " index=" << (int)(prevStopEdge - myRoute->begin())
1144 << " foundIndex=" << (stop.edge == myRoute->end() ? -1 : (int)(stop.edge - myRoute->begin())) << "\n";
1145 }
1146#endif
1147 }
1148 } else {
1149 if (stopPar.index == STOP_INDEX_FIT) {
1150 while (iter != myStops.end() && (iter->edge < stop.edge ||
1151 (iter->pars.endPos < stop.pars.endPos && iter->edge == stop.edge) ||
1152 (stop.lane->getEdge().isInternal() && iter->edge == stop.edge))) {
1153 prevStopEdge = iter->edge;
1154 prevStopPos = iter->pars.endPos;
1155 ++iter;
1156 }
1157 } else {
1158 int index = stopPar.index;
1159 while (index > 0) {
1160 prevStopEdge = iter->edge;
1161 prevStopPos = iter->pars.endPos;
1162 ++iter;
1163 --index;
1164 }
1165#ifdef DEBUG_ADD_STOP
1166 if (DEBUG_COND) {
1167 std::cout << " (@fit) prevStopEdge=" << (*prevStopEdge)->getID() << " index=" << (int)(prevStopEdge - myRoute->begin()) << "\n";
1168 }
1169#endif
1170 stop.edge = std::find(prevStopEdge, myRoute->end(), stopEdge);
1171 }
1172 }
1173 const bool wasTooClose = errorMsg != "" && errorMsg.find("too close") != std::string::npos;
1174 if (stop.edge == myRoute->end()) {
1175 if (!wasTooClose) {
1176 errorMsg = errorMsgStart + " for vehicle '" + myParameter->id + "' on lane '" + stop.lane->getID() + "' is not downstream the current route.";
1177 }
1178 return false;
1179 }
1180
1181 const bool tooClose = (prevStopEdge == stop.edge && prevEdge == &stop.lane->getEdge() &&
1182 prevStopPos + (iter == myStops.begin() ? getBrakeGap() : 0) > stop.pars.endPos + POSITION_EPS);
1183
1184 if (prevStopEdge > stop.edge ||
1185 // a collision-stop happens after vehicle movement and may move the
1186 // vehicle backwards on it's lane (prevStopPos is the vehicle position)
1187 (tooClose && !stop.pars.collision)
1188 || (stop.lane->getEdge().isInternal() && stop.lane->getNextNormal() != *(stop.edge + 1))) {
1189 // check if the edge occurs again later in the route
1190 //std::cout << " could not add stop " << errorMsgStart << " prevStops=" << myStops.size() << " searchStart=" << (*searchStart - myRoute->begin()) << " route=" << toString(myRoute->getEdges()) << "\n";
1191 if (tooClose && prevStopPos <= stop.pars.endPos + POSITION_EPS) {
1192 errorMsg = errorMsgStart + " for vehicle '" + myParameter->id + "' on lane '" + stop.pars.lane + "' is too close to brake.";
1193 }
1194 MSRouteIterator next = stop.edge + 1;
1195 return addStop(stopPar, errorMsg, untilOffset, &next);
1196 }
1197 if (wasTooClose) {
1198 errorMsg = "";
1199 }
1200 // David.C:
1201 //if (!stop.parking && (myCurrEdge == stop.edge && myState.myPos > stop.endPos - getCarFollowModel().brakeGap(myState.mySpeed))) {
1202 const double endPosOffset = stop.lane->getEdge().isInternal() ? (*stop.edge)->getLength() : 0;
1203 const double distToStop = stop.pars.endPos + endPosOffset - getPositionOnLane();
1204 if (stop.pars.collision && !handleCollisionStop(stop, distToStop)) {
1205 return false;
1206 }
1207 if (!hasDeparted() && myCurrEdge == stop.edge) {
1208 double pos = -1;
1210 pos = myParameter->departPos;
1211 if (pos < 0.) {
1212 pos += (*myCurrEdge)->getLength();
1213 }
1214 }
1216 pos = MIN2(stop.pars.endPos + endPosOffset, basePos(*myCurrEdge));
1217 }
1218 if (pos > stop.pars.endPos + endPosOffset) {
1219 if (stop.edge != myRoute->end()) {
1220 // check if the edge occurs again later in the route
1221 MSRouteIterator next = stop.edge + 1;
1222 return addStop(stopPar, errorMsg, untilOffset, &next);
1223 }
1224 errorMsg = errorMsgStart + " for vehicle '" + myParameter->id + "' on lane '" + stop.lane->getID() + "' is before departPos.";
1225 return false;
1226 }
1227 }
1228 if (iter != myStops.begin()) {
1229 std::list<MSStop>::iterator iter2 = iter;
1230 iter2--;
1231 if (stop.getUntil() >= 0 && iter2->getUntil() > stop.getUntil()
1232 && (!MSGlobals::gUseStopEnded || iter2->pars.ended < 0 || stop.pars.ended >= 0)) {
1233 errorMsg = errorMsgStart + " for vehicle '" + myParameter->id + "' on lane '" + stop.lane->getID()
1234 + "' set to end at " + time2string(stop.getUntil())
1235 + " earlier than previous stop at " + time2string(iter2->getUntil()) + ".";
1236 }
1237 if (stop.pars.arrival >= 0 && iter2->pars.arrival > stop.pars.arrival) {
1238 errorMsg = errorMsgStart + " for vehicle '" + myParameter->id + "' on lane '" + stop.lane->getID()
1239 + "' set to start at " + time2string(stop.pars.arrival)
1240 + " earlier than previous stop end at " + time2string(iter2->getUntil()) + ".";
1241 }
1242 if (stop.pars.arrival >= 0 && iter2->pars.arrival > stop.pars.arrival) {
1243 errorMsg = errorMsgStart + " for vehicle '" + myParameter->id + "' on lane '" + stop.lane->getID()
1244 + "' set to start at " + time2string(stop.pars.arrival)
1245 + " earlier than previous stop arrival at " + time2string(iter2->pars.arrival) + ".";
1246 }
1247 } else {
1248 if (stop.getUntil() >= 0 && getParameter().depart > stop.getUntil()) {
1249 errorMsg = errorMsgStart + " for vehicle '" + myParameter->id + "' on lane '" + stop.lane->getID()
1250 + "' set to end at " + time2string(stop.getUntil())
1251 + " earlier than departure at " + time2string(getParameter().depart) + ".";
1252 }
1253 }
1254 if (stop.getUntil() >= 0 && stop.pars.arrival > stop.getUntil() && errorMsg == "") {
1255 errorMsg = errorMsgStart + " for vehicle '" + myParameter->id + "' on lane '" + stop.lane->getID()
1256 + "' set to end at " + time2string(stop.getUntil())
1257 + " earlier than arrival at " + time2string(stop.pars.arrival) + ".";
1258 }
1259 myStops.insert(iter, stop);
1260 //std::cout << " added stop " << errorMsgStart << " totalStops=" << myStops.size() << " searchStart=" << (*searchStart - myRoute->begin())
1261 // << " routeIndex=" << (stop.edge - myRoute->begin())
1262 // << " stopIndex=" << std::distance(myStops.begin(), iter)
1263 // << " route=" << toString(myRoute->getEdges()) << "\n";
1264 return true;
1265}
1266
1267
1268void
1269MSBaseVehicle::addStops(const bool ignoreStopErrors, MSRouteIterator* searchStart, bool addRouteStops) {
1270 if (addRouteStops) {
1271 for (const SUMOVehicleParameter::Stop& stop : myRoute->getStops()) {
1272 std::string errorMsg;
1273 if (!addStop(stop, errorMsg, myParameter->depart, searchStart) && !ignoreStopErrors) {
1274 throw ProcessError(errorMsg);
1275 }
1276 if (errorMsg != "") {
1277 WRITE_WARNING(errorMsg);
1278 }
1279 }
1280 }
1282 for (const SUMOVehicleParameter::Stop& stop : myParameter->stops) {
1283 std::string errorMsg;
1284 if (!addStop(stop, errorMsg, untilOffset, searchStart) && !ignoreStopErrors) {
1285 throw ProcessError(errorMsg);
1286 }
1287 if (errorMsg != "") {
1288 WRITE_WARNING(errorMsg);
1289 }
1290 }
1291}
1292
1293
1294bool
1297 const std::string err = "for vehicle '" + getID() + "' at time=" + time2string(SIMSTEP);
1298 int i = 0;
1299 bool ok = true;
1300 double lastPos = getPositionOnLane();
1301 if (getLane() != nullptr && getLane()->isInternal()
1302 && myStops.size() > 0 && !myStops.front().lane->isInternal()) {
1303 // start edge is still incoming to the intersection so lastPos
1304 // relative to that edge must be adapted
1305 lastPos += (*myCurrEdge)->getLength();
1306 }
1307 for (const MSStop& stop : myStops) {
1308 const double endPos = stop.getEndPos(*this);
1309 MSRouteIterator it;
1310 const std::string prefix = "Stop " + toString(i) + " on edge '" + stop.lane->getEdge().getID() + "' ";
1311 if (stop.lane->isInternal()) {
1312 // find the normal predecessor and ensure that the next route edge
1313 // matches the successor of the internal edge successor
1314 it = std::find(start, myRoute->end(), stop.lane->getEdge().getNormalBefore());
1315 if (it != myRoute->end() && (
1316 it + 1 == myRoute->end() || *(it + 1) != stop.lane->getEdge().getNormalSuccessor())) {
1317 it = myRoute->end(); // signal failure
1318 }
1319 } else {
1320 const MSEdge* const stopEdge = &stop.lane->getEdge();
1321 it = std::find(start, myRoute->end(), stopEdge);
1322 }
1323 if (it == myRoute->end()) {
1324 if (!silent) {
1325 WRITE_ERROR(prefix + "is not found after edge '" + (*start)->getID() + "' (" + toString(start - myCurrEdge) + " after current " + err);
1326 }
1327 ok = false;
1328 } else {
1329 MSRouteIterator it2;
1330 for (it2 = myRoute->begin(); it2 != myRoute->end(); it2++) {
1331 if (it2 == stop.edge) {
1332 break;
1333 }
1334 }
1335 if (it2 == myRoute->end()) {
1336 if (!silent) {
1337 WRITE_ERROR(prefix + "used invalid route index " + err);
1338 }
1339 ok = false;
1340 } else if (it2 < start) {
1341 if (!silent) {
1342 WRITE_ERROR(prefix + "used invalid (relative) route index " + toString(it2 - myCurrEdge) + " expected after " + toString(start - myCurrEdge) + " " + err);
1343 }
1344 ok = false;
1345 } else {
1346 if (it != stop.edge) {
1347 double brakeGap = i == 0 ? getBrakeGap() : 0;
1348 if (endPos >= lastPos + brakeGap) {
1349 if (!silent) {
1350 WRITE_WARNING(prefix + "is used in " + toString(stop.edge - myCurrEdge) + " edges but first encounter is in "
1351 + toString(it - myCurrEdge) + " edges " + err);
1352 }
1353 }
1354 }
1355 start = stop.edge;
1356 }
1357 }
1358 lastPos = endPos;
1359 i++;
1360 }
1361 return ok;
1362}
1363
1364
1366MSBaseVehicle::getStopEdges(double& firstPos, double& lastPos, std::set<int>& jumps) const {
1367 assert(haveValidStopEdges());
1368 ConstMSEdgeVector result;
1369 const MSStop* prev = nullptr;
1370 const MSEdge* internalSuccessor = nullptr;
1371 for (const MSStop& stop : myStops) {
1372 if (stop.reached) {
1373 if (stop.pars.jump >= 0) {
1374 jumps.insert((int)result.size());
1375 }
1376 continue;
1377 }
1378 const double stopPos = stop.getEndPos(*this);
1379 if ((prev == nullptr
1380 || prev->edge != stop.edge
1381 || (prev->lane == stop.lane && prev->getEndPos(*this) > stopPos))
1382 && *stop.edge != internalSuccessor) {
1383 result.push_back(*stop.edge);
1384 if (stop.lane->isInternal()) {
1385 internalSuccessor = stop.lane->getNextNormal();
1386 result.push_back(internalSuccessor);
1387 } else {
1388 internalSuccessor = nullptr;
1389 }
1390 }
1391 prev = &stop;
1392 if (firstPos < 0) {
1393 firstPos = stopPos;
1394 }
1395 lastPos = stopPos;
1396 if (stop.pars.jump >= 0) {
1397 jumps.insert((int)result.size() - 1);
1398 }
1399 }
1400 //std::cout << "getStopEdges veh=" << getID() << " result=" << toString(result) << "\n";
1401 return result;
1402}
1403
1404
1405std::vector<std::pair<int, double> >
1407 std::vector<std::pair<int, double> > result;
1408 for (std::list<MSStop>::const_iterator iter = myStops.begin(); iter != myStops.end(); ++iter) {
1409 result.push_back(std::make_pair(
1410 (int)(iter->edge - myRoute->begin()),
1411 iter->getEndPos(*this)));
1412 }
1413 return result;
1414}
1415
1416
1417MSStop&
1419 assert(myStops.size() > 0);
1420 return myStops.front();
1421}
1422
1425 if (isStopped()) {
1426 return myStops.front().duration;
1427 } else {
1428 return 0;
1429 }
1430}
1431
1432
1433MSStop&
1434MSBaseVehicle::getStop(int nextStopIndex) {
1435 if (nextStopIndex < 0 || (int)myStops.size() <= nextStopIndex) {
1436 throw InvalidArgument("Invalid stop index " + toString(nextStopIndex) + " (has " + toString(myStops.size()) + " stops)");
1437 }
1438 auto stopIt = myStops.begin();
1439 std::advance(stopIt, nextStopIndex);
1440 return *stopIt;
1441}
1442
1443
1446 if (hasStops()) {
1447 return &myStops.front().pars;
1448 }
1449 return nullptr;
1450}
1451
1452
1453bool
1455 //if the stop exists update the duration
1456 for (std::list<MSStop>::iterator iter = myStops.begin(); iter != myStops.end(); iter++) {
1457 if (iter->lane->getID() == stop.lane && fabs(iter->pars.endPos - stop.endPos) < POSITION_EPS) {
1458 // update existing stop
1459 if (stop.duration == 0 && stop.until < 0 && !iter->reached) {
1460 myStops.erase(iter);
1461 } else {
1462 iter->duration = stop.duration;
1463 iter->triggered = stop.triggered;
1464 iter->containerTriggered = stop.containerTriggered;
1465 const_cast<SUMOVehicleParameter::Stop&>(iter->pars).until = stop.until;
1466 const_cast<SUMOVehicleParameter::Stop&>(iter->pars).parking = stop.parking;
1467 }
1468 return true;
1469 }
1470 }
1471 const bool result = addStop(stop, errorMsg);
1472 if (result) {
1474 myParameter->stops.push_back(stop);
1475 }
1476 return result;
1477}
1478
1479
1480bool
1482 if (hasStops() && nextStopIndex < (int)myStops.size()) {
1483 if (nextStopIndex == 0 && isStopped()) {
1485 } else {
1486 auto stopIt = myStops.begin();
1487 std::advance(stopIt, nextStopIndex);
1488 myStops.erase(stopIt);
1489 }
1490 if (!hasDeparted() && (int)myParameter->stops.size() > nextStopIndex) {
1491 // stops will be rebuilt from scratch on rerouting so we must patch the stops in myParameter
1492 auto stopIt2 = myParameter->stops.begin();
1493 std::advance(stopIt2, nextStopIndex);
1494 const_cast<SUMOVehicleParameter*>(myParameter)->stops.erase(stopIt2);
1495 }
1496 return true;
1497 } else {
1498 return false;
1499 }
1500}
1501
1502
1503bool
1504MSBaseVehicle::replaceStop(int nextStopIndex, SUMOVehicleParameter::Stop stop, const std::string& info, bool teleport, std::string& errorMsg) {
1505 const int n = (int)myStops.size();
1506 if (nextStopIndex < 0 || nextStopIndex >= n) {
1507 errorMsg = ("Invalid nextStopIndex '" + toString(nextStopIndex) + "' for " + toString(n) + " remaining stops");
1508 return false;
1509 }
1510 if (nextStopIndex == 0 && isStopped()) {
1511 errorMsg = "Cannot replace reached stop";
1512 return false;
1513 }
1515 MSLane* stopLane = MSLane::dictionary(stop.lane);
1516 MSEdge* stopEdge = &stopLane->getEdge();
1517
1518 auto itStop = myStops.begin();
1519 std::advance(itStop, nextStopIndex);
1520 MSStop& replacedStop = *itStop;
1521
1522 if (replacedStop.lane == stopLane && replacedStop.pars.endPos == stop.endPos && !teleport) {
1523 // only replace stop attributes
1524 const_cast<SUMOVehicleParameter::Stop&>(replacedStop.pars) = stop;
1525 replacedStop.initPars(stop);
1526 return true;
1527 }
1528
1529 if (!stopLane->allowsVehicleClass(getVClass())) {
1530 errorMsg = ("Disallowed stop lane '" + stopLane->getID() + "'");
1531 return false;
1532 }
1533
1534 const ConstMSEdgeVector& oldEdges = getRoute().getEdges();
1535 std::vector<MSStop> stops(myStops.begin(), myStops.end());
1536 const int junctionOffset = getLane() != nullptr && getLane()->isInternal() ? 1 : 0;
1537 MSRouteIterator itStart = nextStopIndex == 0 ? getCurrentRouteEdge() + junctionOffset : stops[nextStopIndex - 1].edge;
1538 double startPos = nextStopIndex == 0 ? getPositionOnLane() : stops[nextStopIndex - 1].pars.endPos;
1539 MSRouteIterator itEnd = nextStopIndex == n - 1 ? oldEdges.end() - 1 : stops[nextStopIndex + 1].edge;
1540 auto endPos = nextStopIndex == n - 1 ? getArrivalPos() : stops[nextStopIndex + 1].pars.endPos;
1542
1543 bool newDestination = nextStopIndex == n - 1 && stops[nextStopIndex].edge == oldEdges.end() - 1;
1544
1545 ConstMSEdgeVector toNewStop;
1546 if (!teleport) {
1547 router.compute(*itStart, startPos, stopEdge, stop.endPos, this, t, toNewStop, true);
1548 if (toNewStop.size() == 0) {
1549 errorMsg = "No route found from edge '" + (*itStart)->getID() + "' to stop edge '" + stopEdge->getID() + "'";
1550 return false;
1551 }
1552 }
1553
1554 ConstMSEdgeVector fromNewStop;
1555 if (!newDestination) {
1556 router.compute(stopEdge, stop.endPos, *itEnd, endPos, this, t, fromNewStop, true);
1557 if (fromNewStop.size() == 0) {
1558 errorMsg = "No route found from stop edge '" + stopEdge->getID() + "' to edge '" + (*itEnd)->getID() + "'";
1559 return false;
1560 }
1561 }
1562
1563 const_cast<SUMOVehicleParameter::Stop&>(replacedStop.pars) = stop;
1564 replacedStop.initPars(stop);
1565 replacedStop.edge = myRoute->end(); // will be patched in replaceRoute
1566 replacedStop.lane = stopLane;
1568 replacedStop.segment = MSGlobals::gMesoNet->getSegmentForEdge(replacedStop.lane->getEdge(), replacedStop.getEndPos(*this));
1569 if (replacedStop.lane->isInternal()) {
1570 errorMsg = "Mesoscopic simulation does not allow stopping on internal edge '" + stop.edge + "' for vehicle '" + getID() + "'.";
1571 return false;
1572 }
1573 }
1574
1575 ConstMSEdgeVector oldRemainingEdges(myCurrEdge, getRoute().end());
1576 ConstMSEdgeVector newEdges; // only remaining
1577 newEdges.insert(newEdges.end(), myCurrEdge, itStart);
1578 if (!teleport) {
1579 newEdges.insert(newEdges.end(), toNewStop.begin(), toNewStop.end() - 1);
1580 } else {
1581 newEdges.push_back(*itStart);
1582 }
1583 if (!newDestination) {
1584 newEdges.insert(newEdges.end(), fromNewStop.begin(), fromNewStop.end() - 1);
1585 newEdges.insert(newEdges.end(), itEnd, oldEdges.end());
1586 } else {
1587 newEdges.push_back(stopEdge);
1588 }
1589 //std::cout << SIMTIME << " replaceStop veh=" << getID()
1590 // << " teleport=" << teleport
1591 // << " busStop=" << stop.busstop
1592 // << " oldEdges=" << oldRemainingEdges.size()
1593 // << " newEdges=" << newEdges.size()
1594 // << " toNewStop=" << toNewStop.size()
1595 // << " fromNewStop=" << fromNewStop.size()
1596 // << "\n";
1597
1598 const double routeCost = router.recomputeCosts(newEdges, this, t);
1599 const double previousCost = router.recomputeCosts(oldRemainingEdges, this, t);
1600 const double savings = previousCost - routeCost;
1601 if (!hasDeparted() && (int)myParameter->stops.size() > nextStopIndex) {
1602 // stops will be rebuilt from scratch so we must patch the stops in myParameter
1603 const_cast<SUMOVehicleParameter*>(myParameter)->stops[nextStopIndex] = stop;
1604 }
1605 return replaceRouteEdges(newEdges, routeCost, savings, info, !hasDeparted(), false, false, &errorMsg);
1606}
1607
1608
1609bool
1610MSBaseVehicle::rerouteBetweenStops(int nextStopIndex, const std::string& info, bool teleport, std::string& errorMsg) {
1611 const int n = (int)myStops.size();
1612 if (nextStopIndex < 0 || nextStopIndex > n) {
1613 errorMsg = ("Invalid nextStopIndex '" + toString(nextStopIndex) + "' for " + toString(n) + " remaining stops");
1614 return false;
1615 }
1616 if (nextStopIndex == 0 && isStopped()) {
1617 errorMsg = "Cannot reroute towards reached stop";
1618 return false;
1619 }
1621
1622 const ConstMSEdgeVector& oldEdges = getRoute().getEdges();
1623 std::vector<MSStop> stops(myStops.begin(), myStops.end());
1624 const int junctionOffset = getLane() != nullptr && getLane()->isInternal() ? 1 : 0;
1625 MSRouteIterator itStart = nextStopIndex == 0 ? getCurrentRouteEdge() + junctionOffset : stops[nextStopIndex - 1].edge;
1626 double startPos = nextStopIndex == 0 ? getPositionOnLane() : stops[nextStopIndex - 1].pars.endPos;
1627 MSRouteIterator itEnd = nextStopIndex == n ? oldEdges.end() - 1 : stops[nextStopIndex].edge;
1628 auto endPos = nextStopIndex == n ? getArrivalPos() : stops[nextStopIndex].pars.endPos;
1630
1631 ConstMSEdgeVector newBetween;
1632 if (!teleport) {
1633 router.compute(*itStart, startPos, *itEnd, endPos, this, t, newBetween, true);
1634 if (newBetween.size() == 0) {
1635 errorMsg = "No route found from edge '" + (*itStart)->getID() + "' to stop edge '" + (*itEnd)->getID() + "'";
1636 return false;
1637 }
1638 }
1639
1640 ConstMSEdgeVector oldRemainingEdges(myCurrEdge, getRoute().end());
1641 ConstMSEdgeVector newEdges; // only remaining
1642 newEdges.insert(newEdges.end(), myCurrEdge, itStart);
1643 if (!teleport) {
1644 newEdges.insert(newEdges.end(), newBetween.begin(), newBetween.end() - 1);
1645 } else {
1646 newEdges.push_back(*itStart);
1647 }
1648 newEdges.insert(newEdges.end(), itEnd, oldEdges.end());
1649 //std::cout << SIMTIME << " rerouteBetweenStops veh=" << getID()
1650 // << " oldEdges=" << oldRemainingEdges.size()
1651 // << " newEdges=" << newEdges.size()
1652 // << " toNewStop=" << toNewStop.size()
1653 // << " fromNewStop=" << fromNewStop.size()
1654 // << "\n";
1655
1656 const double routeCost = router.recomputeCosts(newEdges, this, t);
1657 const double previousCost = router.recomputeCosts(oldRemainingEdges, this, t);
1658 const double savings = previousCost - routeCost;
1659 return replaceRouteEdges(newEdges, routeCost, savings, info, !hasDeparted(), false, false, &errorMsg);
1660}
1661
1662
1663bool
1664MSBaseVehicle::insertStop(int nextStopIndex, SUMOVehicleParameter::Stop stop, const std::string& info, bool teleport, std::string& errorMsg) {
1665 const int n = (int)myStops.size();
1666 if (nextStopIndex < 0 || nextStopIndex > n) {
1667 errorMsg = ("Invalid nextStopIndex '" + toString(nextStopIndex) + "' for " + toString(n) + " remaining stops");
1668 return false;
1669 }
1670 if (nextStopIndex == 0 && isStopped()) {
1671 errorMsg = "Cannot insert stop before the currently reached stop";
1672 return false;
1673 }
1675 MSLane* stopLane = MSLane::dictionary(stop.lane);
1676 MSEdge* stopEdge = &stopLane->getEdge();
1677
1678 if (!stopLane->allowsVehicleClass(getVClass())) {
1679 errorMsg = ("Disallowed stop lane '" + stopLane->getID() + "'");
1680 return false;
1681 }
1682
1683 const ConstMSEdgeVector& oldEdges = getRoute().getEdges();
1684 std::vector<MSStop> stops(myStops.begin(), myStops.end());
1685 const int junctionOffset = getLane() != nullptr && getLane()->isInternal() ? 1 : 0;
1686 MSRouteIterator itStart = nextStopIndex == 0 ? getCurrentRouteEdge() + junctionOffset : stops[nextStopIndex - 1].edge;
1687 double startPos = nextStopIndex == 0 ? getPositionOnLane() : stops[nextStopIndex - 1].pars.endPos;
1688 MSRouteIterator itEnd = nextStopIndex == n ? oldEdges.end() - 1 : stops[nextStopIndex].edge;
1689 auto endPos = nextStopIndex == n ? getArrivalPos() : stops[nextStopIndex].pars.endPos;
1691
1692 bool newDestination = nextStopIndex == n;
1693
1694 ConstMSEdgeVector toNewStop;
1695 if (!teleport) {
1696 router.compute(*itStart, startPos, stopEdge, stop.endPos, this, t, toNewStop, true);
1697 if (toNewStop.size() == 0) {
1698 errorMsg = "No route found from edge '" + (*itStart)->getID() + "' to stop edge '" + stopEdge->getID() + "'";
1699 return false;
1700 }
1701 }
1702
1703 ConstMSEdgeVector fromNewStop;
1704 if (!newDestination) {
1705 router.compute(stopEdge, stop.endPos, *itEnd, endPos, this, t, fromNewStop, true);
1706 if (fromNewStop.size() == 0) {
1707 errorMsg = "No route found from stop edge '" + stopEdge->getID() + "' to edge '" + (*itEnd)->getID() + "'";
1708 return false;
1709 }
1710 }
1711
1712 auto itStop = myStops.begin();
1713 std::advance(itStop, nextStopIndex);
1714 MSStop newStop(stop);
1715 newStop.initPars(stop);
1716 newStop.edge = myRoute->end(); // will be patched in replaceRoute
1717 newStop.lane = stopLane;
1719 newStop.segment = MSGlobals::gMesoNet->getSegmentForEdge(newStop.lane->getEdge(), newStop.getEndPos(*this));
1720 if (newStop.lane->isInternal()) {
1721 errorMsg = "Mesoscopic simulation does not allow stopping on internal edge '" + stop.edge + "' for vehicle '" + getID() + "'.";
1722 return false;
1723 }
1724 }
1725 myStops.insert(itStop, newStop);
1726
1727 ConstMSEdgeVector oldRemainingEdges(myCurrEdge, getRoute().end());
1728 ConstMSEdgeVector newEdges; // only remaining
1729 newEdges.insert(newEdges.end(), myCurrEdge, itStart);
1730 if (!teleport) {
1731 newEdges.insert(newEdges.end(), toNewStop.begin(), toNewStop.end() - 1);
1732 } else {
1733 newEdges.push_back(*itStart);
1734 }
1735 if (!newDestination) {
1736 newEdges.insert(newEdges.end(), fromNewStop.begin(), fromNewStop.end() - 1);
1737 newEdges.insert(newEdges.end(), itEnd, oldEdges.end());
1738 } else {
1739 newEdges.push_back(stopEdge);
1740 }
1741 //std::cout << SIMTIME << " insertStop veh=" << getID()
1742 // << " teleport=" << teleport
1743 // << " busStop=" << stop.busstop
1744 // << " oldEdges=" << oldRemainingEdges.size()
1745 // << " newEdges=" << newEdges.size()
1746 // << " toNewStop=" << toNewStop.size()
1747 // << " fromNewStop=" << fromNewStop.size()
1748 // << "\n";
1749
1750 const double routeCost = router.recomputeCosts(newEdges, this, t);
1751 const double previousCost = router.recomputeCosts(oldRemainingEdges, this, t);
1752 const double savings = previousCost - routeCost;
1753
1754 if (!hasDeparted() && (int)myParameter->stops.size() >= nextStopIndex) {
1755 // stops will be rebuilt from scratch so we must patch the stops in myParameter
1756 auto it = myParameter->stops.begin() + nextStopIndex;
1757 const_cast<SUMOVehicleParameter*>(myParameter)->stops.insert(it, stop);
1758 }
1759 return replaceRouteEdges(newEdges, routeCost, savings, info, !hasDeparted(), false, false, &errorMsg);
1760}
1761
1762
1763double
1765 if (static_cast<MSDevice_Battery*>(getDevice(typeid(MSDevice_Battery))) != 0) {
1766 MSDevice_Battery* batteryOfVehicle = dynamic_cast<MSDevice_Battery*>(getDevice(typeid(MSDevice_Battery)));
1767 return batteryOfVehicle->getActualBatteryCapacity();
1768 } else {
1769 if (static_cast<MSDevice_ElecHybrid*>(getDevice(typeid(MSDevice_ElecHybrid))) != 0) {
1770 MSDevice_ElecHybrid* batteryOfVehicle = dynamic_cast<MSDevice_ElecHybrid*>(getDevice(typeid(MSDevice_ElecHybrid)));
1771 return batteryOfVehicle->getActualBatteryCapacity();
1772 }
1773 }
1774
1775 return -1;
1776}
1777
1778double
1780 if (static_cast<MSDevice_ElecHybrid*>(getDevice(typeid(MSDevice_ElecHybrid))) != 0) {
1781 MSDevice_ElecHybrid* elecHybridDevice = dynamic_cast<MSDevice_ElecHybrid*>(getDevice(typeid(MSDevice_ElecHybrid)));
1782 return elecHybridDevice->getCurrentFromOverheadWire();
1783 }
1784
1785 return NAN;
1786}
1787
1788double
1790 if (isOnRoad() || isIdling()) {
1792 } else {
1793 return 0.;
1794 }
1795}
1796
1797
1800 return _getWeightsStorage();
1801}
1802
1803
1806 return _getWeightsStorage();
1807}
1808
1809
1812 if (myEdgeWeights == nullptr) {
1814 }
1815 return *myEdgeWeights;
1816}
1817
1818
1819
1820
1821int
1823 int boarded = myPersonDevice == nullptr ? 0 : myPersonDevice->size();
1824 return boarded + myParameter->personNumber;
1825}
1826
1827std::vector<std::string>
1829 std::vector<std::string> ret;
1830 const std::vector<MSTransportable*>& persons = getPersons();
1831 for (std::vector<MSTransportable*>::const_iterator it_p = persons.begin(); it_p != persons.end(); ++it_p) {
1832 ret.push_back((*it_p)->getID());
1833 }
1834 return ret;
1835}
1836
1837int
1839 int loaded = myContainerDevice == nullptr ? 0 : myContainerDevice->size();
1840 return loaded + myParameter->containerNumber;
1841}
1842
1843
1844void
1846 // this might be called from the MSTransportable destructor so we cannot do a dynamic cast to determine the type
1847 if (myPersonDevice != nullptr) {
1849 }
1850 if (myContainerDevice != nullptr) {
1852 }
1853}
1854
1855
1856const std::vector<MSTransportable*>&
1858 if (myPersonDevice == nullptr) {
1860 } else {
1862 }
1863}
1864
1865
1866const std::vector<MSTransportable*>&
1868 if (myContainerDevice == nullptr) {
1870 } else {
1872 }
1873}
1874
1875
1876bool
1877MSBaseVehicle::isLineStop(double position) const {
1878 if (myParameter->line == "") {
1879 // not a public transport line
1880 return false;
1881 }
1882 for (const SUMOVehicleParameter::Stop& stop : myParameter->stops) {
1883 if (stop.startPos <= position && position <= stop.endPos) {
1884 return true;
1885 }
1886 }
1887 for (const SUMOVehicleParameter::Stop& stop : myRoute->getStops()) {
1888 if (stop.startPos <= position && position <= stop.endPos) {
1889 return true;
1890 }
1891 }
1892 return false;
1893}
1894
1895
1896bool
1897MSBaseVehicle::hasDevice(const std::string& deviceName) const {
1898 for (MSDevice* const dev : myDevices) {
1899 if (dev->deviceName() == deviceName) {
1900 return true;
1901 }
1902 }
1903 return false;
1904}
1905
1906
1907void
1908MSBaseVehicle::createDevice(const std::string& deviceName) {
1909 if (!hasDevice(deviceName)) {
1910 if (deviceName == "rerouting") {
1911 ((SUMOVehicleParameter*)myParameter)->setParameter("has." + deviceName + ".device", "true");
1913 if (hasDeparted()) {
1914 // vehicle already departed: disable pre-insertion rerouting and enable regular routing behavior
1915 MSDevice_Routing* routingDevice = static_cast<MSDevice_Routing*>(getDevice(typeid(MSDevice_Routing)));
1916 assert(routingDevice != 0);
1918 }
1919 } else {
1920 throw InvalidArgument("Creating device of type '" + deviceName + "' is not supported");
1921 }
1922 }
1923}
1924
1925
1926std::string
1927MSBaseVehicle::getDeviceParameter(const std::string& deviceName, const std::string& key) const {
1928 for (MSVehicleDevice* const dev : myDevices) {
1929 if (dev->deviceName() == deviceName) {
1930 return dev->getParameter(key);
1931 }
1932 }
1933 throw InvalidArgument("No device of type '" + deviceName + "' exists");
1934}
1935
1936
1937void
1938MSBaseVehicle::setDeviceParameter(const std::string& deviceName, const std::string& key, const std::string& value) {
1939 for (MSVehicleDevice* const dev : myDevices) {
1940 if (dev->deviceName() == deviceName) {
1941 dev->setParameter(key, value);
1942 return;
1943 }
1944 }
1945 throw InvalidArgument("No device of type '" + deviceName + "' exists");
1946}
1947
1948
1949void
1950MSBaseVehicle::setJunctionModelParameter(const std::string& key, const std::string& value) {
1953 const_cast<SUMOVehicleParameter&>(getParameter()).setParameter(key, value);
1954 // checked in MSLink::ignoreFoe
1955 } else {
1956 throw InvalidArgument("Vehicle '" + getID() + "' does not support junctionModel parameter '" + key + "'");
1957 }
1958}
1959
1960
1961void
1963 /* Design idea for additional junction model parameters:
1964 We can distinguish between 3 levels of parameters
1965 1. typically shared by multiple vehicles -> vType parameter
1966 2. specific to one vehicle but stays constant throughout the simulation -> vehicle parameter
1967 3. specific to one vehicle and expected to change during simulation -> prefixed generic vehicle parameter
1968 */
1969 for (auto item : getParameter().getParametersMap()) {
1970 if (StringUtils::startsWith(item.first, "junctionModel.")) {
1971 setJunctionModelParameter(item.first, item.second);
1972 }
1973 }
1974}
1975
1976
1977void
1979 assert(type != nullptr);
1980 if (myType->isVehicleSpecific() && type != myType) {
1982 }
1983 myType = type;
1984 if (myEnergyParams != nullptr) {
1986 }
1987}
1988
1989
1992 if (myType->isVehicleSpecific()) {
1993 return *myType;
1994 }
1995 MSVehicleType* type = myType->buildSingularType(myType->getID() + "@" + getID());
1996 replaceVehicleType(type);
1997 return *type;
1998}
1999
2000
2001int
2003 const MSLane* const lane = getLane();
2004 if (lane == nullptr) {
2005 return getEdge()->getLanes()[0]->getRNGIndex();
2006 } else {
2007 return lane->getRNGIndex();
2008 }
2009}
2010
2011
2012SumoRNG*
2014 const MSLane* lane = getLane();
2015 if (lane == nullptr) {
2016 return getEdge()->getLanes()[0]->getRNG();
2017 } else {
2018 return lane->getRNG();
2019 }
2020}
2021
2022std::string
2023MSBaseVehicle::getPrefixedParameter(const std::string& key, std::string& error) const {
2024 const MSVehicle* microVeh = dynamic_cast<const MSVehicle*>(this);
2025 if (StringUtils::startsWith(key, "device.")) {
2026 StringTokenizer tok(key, ".");
2027 if (tok.size() < 3) {
2028 error = "Invalid device parameter '" + key + "' for vehicle '" + getID() + "'.";
2029 return "";
2030 }
2031 try {
2032 return getDeviceParameter(tok.get(1), key.substr(tok.get(0).size() + tok.get(1).size() + 2));
2033 } catch (InvalidArgument& e) {
2034 error = "Vehicle '" + getID() + "' does not support device parameter '" + key + "' (" + e.what() + ").";
2035 return "";
2036 }
2037 } else if (StringUtils::startsWith(key, "laneChangeModel.")) {
2038 if (microVeh == nullptr) {
2039 error = "Meso Vehicle '" + getID() + "' does not support laneChangeModel parameters.";
2040 return "";
2041 }
2042 const std::string attrName = key.substr(16);
2043 try {
2044 return microVeh->getLaneChangeModel().getParameter(attrName);
2045 } catch (InvalidArgument& e) {
2046 error = "Vehicle '" + getID() + "' does not support laneChangeModel parameter '" + key + "' (" + e.what() + ").";
2047 return "";
2048 }
2049 } else if (StringUtils::startsWith(key, "carFollowModel.")) {
2050 if (microVeh == nullptr) {
2051 error = "Meso Vehicle '" + getID() + "' does not support carFollowModel parameters.";
2052 return "";
2053 }
2054 const std::string attrName = key.substr(15);
2055 try {
2056 return microVeh->getCarFollowModel().getParameter(microVeh, attrName);
2057 } catch (InvalidArgument& e) {
2058 error = "Vehicle '" + getID() + "' does not support carFollowModel parameter '" + key + "' (" + e.what() + ").";
2059 return "";
2060 }
2061 } else if (StringUtils::startsWith(key, "has.") && StringUtils::endsWith(key, ".device")) {
2062 StringTokenizer tok(key, ".");
2063 if (tok.size() != 3) {
2064 error = "Invalid check for device. Expected format is 'has.DEVICENAME.device'.";
2065 return "";
2066 }
2067 return hasDevice(tok.get(1)) ? "true" : "false";
2068 // parking related parameters start here
2069 } else if (key == "parking.rerouteCount") {
2071 } else if (StringUtils::startsWith(key, "parking.memory.")) {
2072 std::vector<std::string> values;
2073 if (getParkingMemory()) {
2074 if (key == "parking.memory.IDList") {
2075 for (const auto& item : *getParkingMemory()) {
2076 values.push_back(item.first->getID());
2077 }
2078 } else if (key == "parking.memory.score") {
2079 for (const auto& item : *getParkingMemory()) {
2080 values.push_back(item.second.score);
2081 }
2082 } else if (key == "parking.memory.blockedAtTime") {
2083 for (const auto& item : *getParkingMemory()) {
2084 values.push_back(toString(STEPS2TIME(item.second.blockedAtTime)));
2085 }
2086 } else if (key == "parking.memory.blockedAtTimeLocal") {
2087 for (const auto& item : *getParkingMemory()) {
2088 values.push_back(toString(STEPS2TIME(item.second.blockedAtTimeLocal)));
2089 }
2090 } else {
2091 error = "Unsupported parking parameter '" + key + "'.";
2092 }
2093 }
2094 return toString(values);
2095 } else {
2096 // default: custom user parameter
2097 return getParameter().getParameter(key, "");
2098 }
2099}
2100
2101void
2103 if (myParkingMemory == nullptr) {
2105 }
2106 (*myParkingMemory)[pa].blockedAtTime = SIMSTEP;
2107 if (local) {
2108 (*myParkingMemory)[pa].blockedAtTimeLocal = SIMSTEP;
2109 }
2110}
2111
2112void
2114 if (myParkingMemory != nullptr) {
2115 for (auto& item : *myParkingMemory) {
2116 item.second.score = "";
2117 }
2118 }
2119}
2120
2121void
2122MSBaseVehicle::rememberParkingAreaScore(const MSParkingArea* pa, const std::string& score) {
2123 if (myParkingMemory == nullptr) {
2125 }
2126 (*myParkingMemory)[pa].score = score;
2127}
2128
2129
2132 if (myParkingMemory == nullptr) {
2133 return -1;
2134 }
2135 auto it = myParkingMemory->find(pa);
2136 if (it == myParkingMemory->end()) {
2137 return -1;
2138 } else {
2139 return local ? it->second.blockedAtTimeLocal : it->second.blockedAtTime;
2140 }
2141}
2142
2143#ifdef _DEBUG
2144void
2145MSBaseVehicle::initMoveReminderOutput(const OptionsCont& oc) {
2146 if (oc.isSet("movereminder-output.vehicles")) {
2147 const std::vector<std::string> vehicles = oc.getStringVector("movereminder-output.vehicles");
2148 myShallTraceMoveReminders.insert(vehicles.begin(), vehicles.end());
2149 }
2150}
2151
2152
2153void
2154MSBaseVehicle::traceMoveReminder(const std::string& type, MSMoveReminder* rem, double pos, bool keep) const {
2155 OutputDevice& od = OutputDevice::getDeviceByOption("movereminder-output");
2156 od.openTag("movereminder");
2157 od.writeAttr(SUMO_ATTR_TIME, STEPS2TIME(MSNet::getInstance()->getCurrentTimeStep()));
2158 od.writeAttr("veh", getID());
2160 od.writeAttr("type", type);
2161 od.writeAttr("pos", toString(pos));
2162 od.writeAttr("keep", toString(keep));
2163 od.closeTag();
2164}
2165#endif
2166
2167
2168/****************************************************************************/
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:56
#define WRITE_WARNINGF(...)
Definition: MsgHandler.h:268
#define WRITE_ERRORF(...)
Definition: MsgHandler.h:277
#define WRITE_ERROR(msg)
Definition: MsgHandler.h:276
#define WRITE_WARNING(msg)
Definition: MsgHandler.h:267
#define TL(string)
Definition: MsgHandler.h:284
#define TLF(string,...)
Definition: MsgHandler.h:285
std::shared_ptr< const MSRoute > ConstMSRoutePtr
Definition: Route.h:32
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_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:28
#define UNUSED_PARAMETER(x)
Definition: StdDefs.h:30
T MIN2(T a, T b)
Definition: StdDefs.h:76
const double SUMO_const_haltingSpeed
the speed threshold at which vehicles are considered as halting
Definition: StdDefs.h:58
T MAX2(T a, T b)
Definition: StdDefs.h:82
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition: ToString.h:46
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:325
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, nullptr otherwise.
bool haveValidStopEdges(bool silent=false) const
check whether all stop.edge MSRouteIterators are valid and in order
bool hasJump(const MSRouteIterator &it) const
check wether the vehicle has jump at the given part of it's route
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.
virtual ConstMSEdgeVector::const_iterator getRerouteOrigin() const
Returns the starting point for reroutes (usually the current edge)
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)
MSBaseVehicle(SUMOVehicleParameter *pars, ConstMSRoutePtr route, MSVehicleType *type, const double speedFactor)
Constructor.
void calculateArrivalParams(bool onInit)
(Re-)Calculates the arrival position and lane from the vehicle parameters
virtual double getArrivalPos() const
Returns this vehicle's desired arrivalPos for its current route (may change on reroute)
void 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
bool isJumping() const
Returns whether the vehicle is perform a jump.
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.
bool hasValidRoute(std::string &msg, ConstMSRoutePtr route=0) const
Validates the current or given route.
double getLength() const
Returns the vehicle's length.
bool isParking() const
Returns whether the vehicle is parking.
const MSEdge * getEdge() const
Returns the edge the vehicle is currently at.
double getHarmonoise_NoiseEmissions() const
Returns noise emissions of the current state.
int getPersonNumber() const
Returns the number of persons.
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()
ConstMSRoutePtr myRoute
This vehicle's route.
const ConstMSEdgeVector getStopEdges(double &firstPos, double &lastPos, std::set< int > &jumps) const
Returns the list of still pending stop edges also returns the first and last stop position.
MSDevice_Transportable * myContainerDevice
The containers this vehicle may have.
bool allowsBoarding(const MSTransportable *t) const
whether the given transportable is allowed to board this vehicle
double getStateOfCharge() const
Returns actual state of charge of battery (Wh) RICE_CHECK: This may be a misnomer,...
MSEdgeWeightsStorage & _getWeightsStorage() const
virtual bool handleCollisionStop(MSStop &stop, const double distToStop)
bool hasDevice(const std::string &deviceName) const
check whether the vehicle is equiped with a device of the given name
SumoRNG * getRNG() const
SUMOTime getDeparture() const
Returns this vehicle's real departure time.
EnergyParams * getEmissionParameters() const
retrieve parameters for the energy consumption model
double basePos(const MSEdge *edge) const
departure position where the vehicle fits fully onto the edge (if possible)
void setDeviceParameter(const std::string &deviceName, const std::string &key, const std::string &value)
try to set the given parameter from any of the vehicles devices, raise InvalidArgument if no device p...
MSDevice_Transportable * myPersonDevice
The passengers this vehicle may have.
bool hasStops() const
Returns whether the vehicle has to stop somewhere.
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.
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
bool stopsAtEdge(const MSEdge *edge) const
Returns whether the vehicle stops at the given edge.
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.
std::vector< SUMOVehicleParameter::Stop > myPastStops
The list of stops that the vehicle has already reached.
void onDepart()
Called when the vehicle is inserted into the network.
void removeReminder(MSMoveReminder *rem)
Removes a MoveReminder dynamically.
SUMOTime getStopDuration() const
get remaining stop duration or 0 if the vehicle isn't stopped
virtual double getAcceleration() const
Returns the vehicle's acceleration.
virtual bool addTraciStop(SUMOVehicleParameter::Stop stop, std::string &errorMsg)
const MSRoute & getRoute() const
Returns the current route.
int 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
SUMOTime myStopUntilOffset
The offset when adding route stops with 'until' on route replacement.
virtual bool replaceRoute(ConstMSRoutePtr 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.
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
bool stopsAt(MSStoppingPlace *stop) const
Returns whether the vehicle stops at the given stopping place.
int getRNGIndex() const
MSEdgeWeightsStorage * myEdgeWeights
const MSVehicleType & getVehicleType() const
Returns the vehicle's type definition.
void createDevice(const std::string &deviceName)
create device of the given type
bool isStopped() const
Returns whether the vehicle is at a stop.
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:1237
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:178
static bool gUseStopEnded
whether the simulation should replay previous stop times
Definition: MSGlobals.h:130
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:2210
double getLength() const
Returns the lane's length.
Definition: MSLane.h:593
bool allowsVehicleClass(SUMOVehicleClass vclass) const
Definition: MSLane.h:900
static bool dictionary(const std::string &id, MSLane *lane)
Static (sic!) container methods {.
Definition: MSLane.cpp:2234
bool isInternal() const
Definition: MSLane.cpp:2365
SumoRNG * getRNG() const
return the associated RNG
Definition: MSLane.h:245
MSEdge & getEdge() const
Returns the lane's edge.
Definition: MSLane.h:745
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:1610
@ 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:1452
SUMOTime getCurrentTimeStep() const
Returns the current simulation step.
Definition: MSNet.h:320
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:1244
MSInsertionControl & getInsertionControl()
Returns the insertion control.
Definition: MSNet.h:431
MSVehicleControl & getVehicleControl()
Returns the vehicle control.
Definition: MSNet.h:378
A lane area vehicles can halt at.
Definition: MSParkingArea.h:58
const ConstMSEdgeVector & getEdges() const
Definition: MSRoute.h:124
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:152
static bool dictionary(const std::string &id, ConstMSRoutePtr route)
Adds a route to the dictionary.
Definition: MSRoute.cpp:109
static void checkDist(const std::string &id)
Checks the distribution whether it is permanent and deletes it if not.
Definition: MSRoute.cpp:187
void setSavings(double savings)
Sets the savings of the route.
Definition: MSRoute.h: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
SUMOTime getUntil() const
return until / ended time
Definition: MSStop.cpp:150
const SUMOVehicleParameter::Stop pars
The stop parameter.
Definition: MSStop.h:65
MSStoppingPlace * busstop
(Optional) bus stop if one is assigned to the stop
Definition: MSStop.h:54
MSStoppingPlace * overheadWireSegment
(Optional) overhead wire segment if one is assigned to the stop
Definition: MSStop.h:63
A lane area vehicles can halt at.
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:5510
const MSCFModel & getCarFollowModel() const
Returns the vehicle's car following model definition.
Definition: MSVehicle.h:973
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:254
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:62
virtual bool isIdling() const =0
Returns whether the vehicle is idling (waiting to re-enter the net.
virtual double getBrakeGap(bool delayed=false) const =0
get distance for coming to a stop (used for rerouting checks)
Definition of vehicle stop (position and duration)
std::string edge
The edge to stop at (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
SUMOTime ended
the time at which this stop was ended
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