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