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-2026 German Aerospace Center (DLR) and others.
4// This program and the accompanying materials are made available under the
5// terms of the Eclipse Public License 2.0 which is available at
6// https://www.eclipse.org/legal/epl-2.0/
7// This Source Code may also be made available under the following Secondary
8// Licenses when the conditions for such availability set forth in the Eclipse
9// Public License 2.0 are satisfied: GNU General Public License, version 2
10// or later which is available at
11// https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
12// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
13/****************************************************************************/
21// A base class for vehicle implementations
22/****************************************************************************/
23#include <config.h>
24
25#include <iostream>
26#include <cassert>
27#include <algorithm>
28#include <functional>
36#include <mesosim/MELoop.h>
37#include <mesosim/MEVehicle.h>
53#include "MSEventControl.h"
54#include "MSGlobals.h"
55#include "MSVehicleControl.h"
56#include "MSVehicleType.h"
57#include "MSEdge.h"
58#include "MSLane.h"
59#include "MSMoveReminder.h"
61#include "MSNet.h"
62#include "MSStop.h"
63#include "MSParkingArea.h"
64#include "MSInsertionControl.h"
65#include "MSStopOptimizer.h"
66#include "MSBaseVehicle.h"
67
68//#define DEBUG_REROUTE
69//#define DEBUG_ADD_STOP
70//#define DEBUG_COND (getID() == "")
71//#define DEBUG_COND (true)
72//#define DEBUG_REPLACE_ROUTE
73#define DEBUG_COND (isSelected())
74
75// ===========================================================================
76// static members
77// ===========================================================================
79std::vector<MSTransportable*> MSBaseVehicle::myEmptyTransportableVector;
80#ifdef _DEBUG
81std::set<std::string> MSBaseVehicle::myShallTraceMoveReminders;
82#endif
84
85// ===========================================================================
86// Influencer method definitions
87// ===========================================================================
88
91
92// ===========================================================================
93// method definitions
94// ===========================================================================
95
96double
98 throw ProcessError("getPreviousSpeed() is not available for non-MSVehicles.");
99}
100
101
103 MSVehicleType* type, const double speedFactor) :
104 SUMOVehicle(pars->id),
105 myParameter(pars),
106 myRoute(route),
107 myType(type),
108 myCurrEdge(route->begin()),
109 myChosenSpeedFactor(pars->speedFactor < 0 ? speedFactor : pars->speedFactor),
111 myPersonDevice(nullptr),
112 myContainerDevice(nullptr),
113 myEnergyParams(nullptr),
115 myDepartPos(-1),
116 myArrivalPos(-1),
117 myArrivalLane(-1),
120 myOdometer(0.),
122 myRoutingMode(libsumo::ROUTING_MODE_DEFAULT),
124 myRandomSeed(RandHelper::murmur3_32(pars->id, RandHelper::getSeed())),
125 myEdgeWeights(nullptr)
126#ifdef _DEBUG
127 , myTraceMoveReminders(myShallTraceMoveReminders.count(pars->id) > 0)
128#endif
129{
130 if ((*myRoute->begin())->isTazConnector() || myRoute->getLastEdge()->isTazConnector()) {
132 }
133 if ((pars->parametersSet & VEHPARS_FORCE_REROUTE) == 0) {
135 }
138}
139
140
142 delete myEdgeWeights;
143 if (myParameter->repetitionNumber == -1) {
144 // this is not a flow (flows call checkDist in MSInsertionControl::determineCandidates)
146 }
147 for (MSVehicleDevice* dev : myDevices) {
148 delete dev;
149 }
150 delete myEnergyParams;
151 delete myParkingMemory;
152 delete myChargingMemory;
154 delete myParameter;
155}
156
157
158void
160 // the check for an instance is needed for the unit tests which do not construct a network
161 // TODO Optimize for speed and there should be a better way to check whether a vehicle is part of a flow
162 if (MSNet::hasInstance() && !MSNet::getInstance()->hasFlow(getFlowID())) {
163 myRoute->checkRemoval();
164 }
165}
166
167
168std::string
170 return getID().substr(0, getID().rfind('.'));
171}
172
173
174void
177 for (MSVehicleDevice* dev : myDevices) {
178 myMoveReminders.push_back(std::make_pair(dev, 0.));
179 }
181 // ensure we have the emission parameters even if we don't have the device
183 }
184}
185
186
187void
188MSBaseVehicle::setID(const std::string& /*newID*/) {
189 throw ProcessError(TL("Changing a vehicle ID is not permitted"));
190}
191
194 return *myParameter;
195}
196
197
198void
200 delete myParameter;
201 myParameter = newParameter;
202}
203
204
205bool
209
210double
214
215
216const MSEdge*
217MSBaseVehicle::succEdge(int nSuccs) const {
218 if (myCurrEdge + nSuccs < myRoute->end() && std::distance(myCurrEdge, myRoute->begin()) <= nSuccs) {
219 return *(myCurrEdge + nSuccs);
220 } else {
221 return nullptr;
222 }
223}
224
225
226const MSEdge*
228 return *myCurrEdge;
229}
230
231
232const std::set<SUMOTrafficObject::NumericalID>
234 std::set<SUMOTrafficObject::NumericalID> result;
235 for (auto e = myCurrEdge; e != myRoute->end(); ++e) {
236 result.insert((*e)->getNumericalID());
237 }
238 return result;
239}
240
241
242bool
244 if (stop == nullptr) {
245 return false;
246 }
247 for (const MSStop& s : myStops) {
248 if (s.busstop == stop
249 || s.containerstop == stop
250 || s.parkingarea == stop
251 || s.chargingStation == stop) {
252 return true;
253 }
254 }
255 return false;
256}
257
258bool
260 for (const MSStop& s : myStops) {
261 if (&s.lane->getEdge() == edge) {
262 return true;
263 }
264 }
265 return myRoute->getLastEdge() == edge;
266}
267
268
269bool
270MSBaseVehicle::reroute(SUMOTime t, const std::string& info, SUMOAbstractRouter<MSEdge, SUMOVehicle>& router, const bool onInit, const bool withTaz, const bool silent, const MSEdge* sink) {
271 // check whether to reroute
272 const MSEdge* source = nullptr;
273 if (onInit) {
274 if (withTaz) {
275 source = MSEdge::dictionary(myParameter->fromTaz + "-source");
276 if (source == nullptr) {
277 source = myRoute->getEdges().front();
278 }
279 } else {
280 source = myRoute->getEdges().front();
281 }
282 } else {
283 source = *getRerouteOrigin();
284 }
285 if (sink == nullptr) {
286 sink = withTaz ? MSEdge::dictionary(myParameter->toTaz + "-sink") : myRoute->getLastEdge();
287 if (sink == nullptr) {
288 sink = myRoute->getLastEdge();
289 }
290 }
291 // on insertion, the new route is compared against the complete loaded route
292 ConstMSEdgeVector oldEdgesRemaining(onInit ? myRoute->begin() : (source == *myCurrEdge ? myCurrEdge : myCurrEdge + 1), myRoute->end());
293 ConstMSEdgeVector edges;
294 if (source != sink || !sink->prohibits(this)) {
295 edges.push_back(source);
296 }
297 std::vector<StopEdgeInfo> stops;
298 std::set<int> jumps;
299
300
301 double sourcePos = getPositionOnLane();
302#ifdef DEBUG_REROUTE
303 if (DEBUG_COND) {
304 std::cout << " curEdge=" << (*myCurrEdge)->getID() << " source=" << source->getID() << " sourcePos=" << sourcePos << " lane=" << Named::getIDSecure(getLane()) << " departPos=" << myParameter->departPos << " oldEdgesRemaining=" << toString(oldEdgesRemaining) << "\n";
305 }
306#endif
308 sourcePos = myParameter->departPos;
309 } else if (getLane() != nullptr && source != &getLane()->getEdge()) {
310 // routing starts on the next edge
311 sourcePos = 0;
312 }
313 if (myParameter->via.size() == 0) {
314 double firstPos = INVALID_DOUBLE;
315 double lastPos = INVALID_DOUBLE;
316 stops = getStopEdges(firstPos, lastPos, jumps);
317 if (stops.size() > 0) {
319 sourcePos = getNextStop().pars.endPos;
320 }
321 if ( !isStopped() && myStops.front().pars.speed == 0) {
322 sourcePos += getBrakeGap();
323 }
324 // avoid superfluous waypoints for first and last edge
325 const bool skipFirst = stops.front().edge == source && (source != getEdge() || sourcePos <= firstPos + NUMERICAL_EPS);
326#ifdef DEBUG_REROUTE
327 if (DEBUG_COND) {
328 std::cout << SIMTIME << " reroute " << info << " veh=" << getID() << " lane=" << Named::getIDSecure(getLane())
329 << " source=" << source->getID() << " sourcePos=" << sourcePos << " firstPos=" << firstPos << " arrivalPos=" << myArrivalPos << " lastPos=" << lastPos
330 << " route=" << toString(myRoute->getEdges()) << " skipFirst=" << skipFirst << "\n";
331 }
332#endif
333 if (stops.size() == 1 && skipFirst) {
334 stops.clear();
335 } else if (skipFirst) {
336 sourcePos = stops.front().pos;
337 stops.erase(stops.begin());
338 }
339 }
340 } else {
341 std::set<const MSEdge*> jumpEdges;
342 std::map<const MSEdge*, StopEdgeInfo> stopsOnVia;
343 for (const MSStop& stop : myStops) {
344 if (stop.pars.jump >= 0) {
345 jumpEdges.insert(*stop.edge);
346 }
347 auto itsov = stopsOnVia.find(*stop.edge);
348 if (itsov == stopsOnVia.end()) {
349 stopsOnVia.insert({*stop.edge, StopEdgeInfo(*stop.edge, stop.pars.priority, stop.getArrivalFallback(), stop.getEndPos(*this))});
350 } else {
351 itsov->second.priority = addStopPriority(itsov->second.priority, stop.pars.priority);
352 }
353 }
354 // via takes precedence over stop edges
355 // there is a consistency check in MSRouteHandler::addStop that warns when a stop edge is not part of the via edges
356 for (std::vector<std::string>::const_iterator it = myParameter->via.begin(); it != myParameter->via.end(); ++it) {
357 MSEdge* viaEdge = MSEdge::dictionary(*it);
358 if ((viaEdge == source && it == myParameter->via.begin()) || (viaEdge == sink && myParameter->via.end() - it == 1)) {
359 continue;
360 }
361 assert(viaEdge != 0);
362 if (!viaEdge->isTazConnector() && viaEdge->allowedLanes(getVClass()) == nullptr) {
363 throw ProcessError(TLF("Vehicle '%' is not allowed on any lane of via edge '%'.", getID(), viaEdge->getID()));
364 }
365 auto itsov = stopsOnVia.find(viaEdge);
366 const double priority = (itsov == stopsOnVia.end() ? -1 : itsov->second.priority);
367 const SUMOTime arrival = (itsov == stopsOnVia.end() ? -1 : itsov->second.arrival);
368 const double pos = (itsov == stopsOnVia.end() ? 0 : itsov->second.pos);
369 stops.push_back(StopEdgeInfo(viaEdge, priority, arrival, pos));
370 // @todo determine whether the viaEdge is also used by a stop and then use the stop priority here
371 if (jumpEdges.count(viaEdge) != 0) {
372 jumps.insert((int)stops.size());
373 }
374 }
375 }
376 if ((stops.size() == 0 && (source != sink || sourcePos > myArrivalPos))
377 || ((stops.size() != 0) && (stops.back().edge != sink || myArrivalPos < stops.back().pos))) {
378 stops.push_back(StopEdgeInfo(sink, -1, -1, myArrivalPos, true));
379 }
380#ifdef DEBUG_REROUTE
381 if (DEBUG_COND) {
382 std::cout << SIMTIME << " reroute veh=" << getID() << " onInit=" << onInit << " source=" << source->getID() << " sink=" << sink->getID() << " sourcePos=" << sourcePos << " arrivalPos=" << myArrivalPos << " stops:\n";
383 for (auto item : stops) {
384 std::cout << " e=" << item.edge->getID() << " pos=" << item.pos << " isSink=" << item.isSink << "\n";
385 }
386 }
387#endif
388 int stopIndex = -1;
389 auto stopIt = myStops.begin();
390 SUMOTime startTime = t;
391 bool hasSkipped = false;
392 const double origSourcePos = sourcePos;
393 const MSEdge* origSource = source;
395 for (auto& stopEdgeInfo : stops) {
396 const MSEdge* const stopEdge = stopEdgeInfo.edge;
397 const double priority = stopEdgeInfo.priority;
398 stopIndex++;
400 if (jumps.count(stopIndex) != 0) {
401 edges.push_back(stopEdge);
402 source = stopEdge;
403 continue;
404 }
405 // !!! need to adapt t here
406 router.compute(source, sourcePos, stopEdge, stopEdgeInfo.pos, this, t, into, silent || priority >= 0);
407#ifdef DEBUG_REROUTE
408 if (DEBUG_COND) {
409 std::cout << SIMTIME << " reroute veh=" << getID() << " source=" << source->getID() << " sourcePos=" << sourcePos << " target=" << stopEdgeInfo.edge->getID() << " targetPos=" << stopEdgeInfo.pos << " edges=" << toString(into) << "\n";
410 }
411#endif
412 if (into.size() > 0) {
413 // stopIt->edge may be invalid when trying to reroute for novel stops
414 while (stopIt != myStops.end() && stopIt->lane->getNextNormal()->getID() != stopEdge->getID()) {
415 stopIt++;
416 }
417
418 startTime += TIME2STEPS(router.recomputeCostsPos(into, this, sourcePos, stopEdgeInfo.pos, startTime));
419 if (stopIt != myStops.end()) {
420 if (stopIt->pars.priority >= 0 && info != "device.rerouting") {
421 // consider skipping this stop if it cannot be reached in a timely manner
422 if (stopIt != myStops.end()) {
423 SUMOTime arrival = stopEdgeInfo.arrival;
424 if (arrival > 0) {
425 SUMOTime delay = startTime - arrival;
426 //std::cout << " t=" << time2string(t) << " veh=" << getID() << " info=" << info << " stopIndex=" << stopIndex
427 // << " into=" << toString(into) << " sourcePos=" << sourcePos << " stopPos=" << stopPos
428 // << " startTime=" << time2string(startTime) << " arrival=" << time2string(arrival) << " delay=" << time2string(delay) << "\n";
429 if (delay > 0) {
430 if (delay > maxDelay) {
431 stopEdgeInfo.skipped = true;
432 stopEdgeInfo.delay = delay;
433 hasSkipped = true;
434 continue;
435 }
436 }
437 }
438 }
439 }
440 sourcePos = stopEdgeInfo.pos;
441 startTime += stopIt->getMinDuration(startTime);
442 }
443 edges.pop_back();
444 edges.insert(edges.end(), into.begin(), into.end());
445 if (edges.back()->isTazConnector()) {
446 edges.pop_back();
447 }
448 source = edges.back();
449 stopEdgeInfo.routeIndex = (int)edges.size() - 1;
450 } else {
451 if (priority >= 0) {
452 stopEdgeInfo.skipped = true;
453 hasSkipped = true;
454 continue;
455 } else if (stopEdgeInfo.isSink) {
456 //error = TLF("Vehicle '%' has no valid route from edge '%' to destination edge '%'.", getID(), source->getID(), stopEdge->getID());
457 edges.clear();
458 if (source == stopEdge && stops.size() == 1 && sourcePos > myArrivalPos) {
459 edges.push_back(stopEdge);
460 WRITE_WARNING(TLF("Vehicle '%' ignores arrivalPos % when driving from edge '%' to edge '%' with departPos %.",
461 getID(), myArrivalPos, source->getID(), stopEdge->getID(), sourcePos));
462 }
463 } else if (source == stopEdge && stopEdgeInfo.stopPar != nullptr && stopEdgeInfo.stopPar->endPos >= sourcePos) {
464 // special case: no failure on dynamically computed stop position
465 edges.clear();
466 } else {
467 std::string error = TLF("Vehicle '%' has no valid route from edge '%' to stop edge '%'.", getID(), source->getID(), stopEdge->getID());
468 if (MSGlobals::gCheckRoutes || silent) {
469 throw ProcessError(error);
470 } else {
471 WRITE_WARNING(error);
472 edges.push_back(source);
473 source = stopEdge;
474 }
475 }
476 }
477 }
478 if (hasSkipped) {
479 MSStopOptimizer opti(this, router, t, maxDelay);
480 edges = opti.optimizeSkipped(origSource, origSourcePos, stops, edges);
481 for (auto stop : stops) {
482 if (stop.skipped || stop.origEdge != nullptr) {
483 const MSEdge* origEdge = stop.origEdge == nullptr ? stop.edge : stop.origEdge;
484 if (stop.delay > 0) {
485 WRITE_WARNING(TLF("Vehicle '%' skips stop on edge '%' with delay % at time %.", getID(), origEdge->getID(), time2string(stop.delay), time2string(SIMSTEP)));
486 } else if (stop.backtracked) {
487 WRITE_WARNING(TLF("Vehicle '%' skips stop on edge '%' with priority % at time %.", getID(), origEdge->getID(), stop.priority, time2string(SIMSTEP)));
488 } else {
489 WRITE_WARNING(TLF("Vehicle '%' skips unreachable stop on edge '%' with priority % at time %.", getID(), origEdge->getID(), stop.priority, time2string(SIMSTEP)));
490 }
491 }
492 }
493 }
494
495 // router.setHint(myCurrEdge, myRoute->end(), this, t);
496 if (edges.empty() && silent) {
497 return false;
498 }
499 if (!edges.empty() && edges.front()->isTazConnector()) {
500 edges.erase(edges.begin());
501 }
502 if (!edges.empty() && edges.back()->isTazConnector()) {
503 edges.pop_back();
504 }
505 const double routeCost = router.recomputeCosts(edges, this, t);
506 // trips have no loaded route to compare against when routed on insertion
507 const bool isTripInit = onInit && myParameter->wasSet(VEHPARS_FORCE_REROUTE);
508 const double previousCost = isTripInit ? routeCost : router.recomputeCosts(oldEdgesRemaining, this, t);
509 const double savings = previousCost - routeCost;
510 bool savingsOk = isTripInit || info != "device.rerouting" || gWeightsRandomFactor != 1;
511 if (!savingsOk) {
512 MSDevice_Routing* routingDevice = static_cast<MSDevice_Routing*>(getDevice(typeid(MSDevice_Routing)));
513 assert(routingDevice != 0);
514 savingsOk = routingDevice->sufficientSaving(previousCost, routeCost);
515 if (!savingsOk) {
516 std::string dummyMsg;
517 if (!hasValidRoute(dummyMsg, oldEdgesRemaining.begin(), oldEdgesRemaining.end(), true)) {
518 // the old route is prohibted (i.e. due to temporary permission changes)
519 savingsOk = true;
520 }
521 }
522 }
523 //if (getID() == "43") std::cout << SIMTIME << " pCost=" << previousCost << " cost=" << routeCost
524 // << " onInit=" << onInit
525 // << " prevEdges=" << toString(oldEdgesRemaining)
526 // << " newEdges=" << toString(edges)
527 // << "\n";
528 if (savingsOk) {
529 replaceRouteEdges(edges, routeCost, savings, info, onInit, false, hasSkipped);
530 }
531 // this must be called even if the route could not be replaced
532 if (onInit) {
533 if (edges.empty()) {
535 throw ProcessError(TLF("Vehicle '%' has no valid route.", getID()));
536 } else if (source->isTazConnector()) {
537 WRITE_WARNINGF(TL("Removing vehicle '%' which has no valid route."), getID());
539 return false;
540 }
541 }
544 }
545 return !edges.empty();
546}
547
548
549bool
550MSBaseVehicle::replaceRouteEdges(ConstMSEdgeVector& edges, double cost, double savings, const std::string& info, bool onInit, bool check, bool removeStops, std::string* msgReturn) {
551 if (edges.empty()) {
552 WRITE_WARNINGF(TL("No route for vehicle '%' found."), getID());
553 if (msgReturn != nullptr) {
554 *msgReturn = "No route found";
555 }
556 return false;
557 }
558 // build a new id, first
559 std::string id = getID();
560 if (id[0] != '!') {
561 id = "!" + id;
562 }
563 const std::string idSuffix = id + "!var#";
564 int varIndex = 1;
565 id = idSuffix + toString(varIndex);
566 while (MSRoute::hasRoute(id)) {
567 id = idSuffix + toString(++varIndex);
568 }
569 int oldSize = (int)edges.size();
570 if (!onInit) {
571 const MSEdge* const origin = *getRerouteOrigin();
572 if (origin != *myCurrEdge && edges.front() == origin) {
573 edges.insert(edges.begin(), *myCurrEdge);
574 oldSize = (int)edges.size();
575 }
576 edges.insert(edges.begin(), myRoute->begin(), myCurrEdge);
577 }
578 if (edges == myRoute->getEdges() && haveValidStopEdges(true)) {
579 // re-assign stop iterators when rerouting to a new parkingArea / insertStop
580 return true;
581 }
582 const RGBColor& c = myRoute->getColor();
583 MSRoute* newRoute = new MSRoute(id, edges, false, &c == &RGBColor::DEFAULT_COLOR ? nullptr : new RGBColor(c), StopParVector());
584 newRoute->setCosts(cost);
585 newRoute->setSavings(savings);
586 ConstMSRoutePtr constRoute = std::shared_ptr<MSRoute>(newRoute);
587 if (!MSRoute::dictionary(id, constRoute)) {
588 delete newRoute;
589 if (msgReturn != nullptr) {
590 *msgReturn = "duplicate routeID '" + id + "'";
591 }
592 return false;
593 }
594
595 std::string msg;
596 if (check && !hasValidRoute(msg, constRoute)) {
597 WRITE_WARNINGF(TL("Invalid route replacement for vehicle '%'. %"), getID(), msg);
599 if (msgReturn != nullptr) {
600 *msgReturn = msg;
601 }
602 return false;
603 }
604 }
605 if (!replaceRoute(constRoute, info, onInit, (int)edges.size() - oldSize, false, removeStops, msgReturn)) {
606 return false;
607 }
608 return true;
609}
610
611
612bool
613MSBaseVehicle::replaceRoute(ConstMSRoutePtr newRoute, const std::string& info, bool onInit, int offset, bool addRouteStops, bool removeStops, std::string* msgReturn) {
614 const ConstMSEdgeVector& edges = newRoute->getEdges();
615 // rebuild in-vehicle route information
616 if (onInit) {
617 myCurrEdge = newRoute->begin();
618 } else {
619 MSRouteIterator newCurrEdge = std::find(edges.begin() + offset, edges.end(), *myCurrEdge);
620 if (newCurrEdge == edges.end()) {
621 if (msgReturn != nullptr) {
622 *msgReturn = TLF("current edge '%' not found in new route", (*myCurrEdge)->getID());
623 }
624#ifdef DEBUG_REPLACE_ROUTE
625 if (DEBUG_COND) {
626 std::cout << " newCurrEdge not found\n";
627 }
628#endif
629 return false;
630 }
631 if (getLane() != nullptr) {
632 if (getLane()->getEdge().isInternal() && (
633 (newCurrEdge + 1) == edges.end() || (*(newCurrEdge + 1)) != &(getLane()->getOutgoingViaLanes().front().first->getEdge()))) {
634 if (msgReturn != nullptr) {
635 *msgReturn = TL("Vehicle is on junction-internal edge leading elsewhere");
636 }
637#ifdef DEBUG_REPLACE_ROUTE
638 if (DEBUG_COND) {
639 std::cout << " Vehicle is on junction-internal edge leading elsewhere\n";
640 }
641#endif
642 return false;
643 } else if (getPositionOnLane() > getLane()->getLength()
644 && (myCurrEdge + 1) != myRoute->end()
645 && (newCurrEdge + 1) != edges.end()
646 && *(myCurrEdge + 1) != *(newCurrEdge + 1)) {
647 if (msgReturn != nullptr) {
648 *msgReturn = TL("Vehicle is moving past junction and committed to move to another successor edge");
649 }
650#ifdef DEBUG_REPLACE_ROUTE
651 if (DEBUG_COND) {
652 std::cout << " Vehicle is moving past junction and committed to move to another successor edge\n";
653 }
654#endif
655 return false;
656 }
657 }
658 myCurrEdge = newCurrEdge;
659 }
660 const bool stopsFromScratch = onInit && myRoute->getStops().empty();
661 // assign new route
663 myRoute = newRoute;
664 // update arrival definition
666 // save information that the vehicle was rerouted
668 myStopUntilOffset += myRoute->getPeriod();
670 if (!onInit && isRail() && MSRailSignalControl::hasInstance()) {
671 // we need to update driveways (add/remove reminders) before the next call to MSRailSignalControl::updateSignals
672 //
673 // rerouting may be triggered through
674 // - MoveReminders (executeMove->activateReminders)
675 // - rerouters
676 // - devices (MSDevice_Stationfinder)
677 // - TraCI (changeTarget, replaceStop, ...
678 // - events (MSDevice_Routing::myRerouteCommand, MSDevice_Taxi::triggerDispatch)
679 //
680 // Since activateReminders actively modifies reminders, adding/deleting reminders would create a mess
681 // hence, we use an event to be safe for all case
682
685 }
686#ifdef DEBUG_REPLACE_ROUTE
687 if (DEBUG_COND) {
688 std::cout << SIMTIME << " veh=" << getID() << " replaceRoute info=" << info << " on " << (*myCurrEdge)->getID()
689 << " lane=" << Named::getIDSecure(getLane())
690 << " stopsFromScratch=" << stopsFromScratch
691 << " newSize=" << newRoute->getEdges().size()
692 << " newIndex=" << (myCurrEdge - newRoute->begin())
693 << " edges=" << toString(newRoute->getEdges())
694 << "\n";
695 }
696#endif
697 // remove past stops which are not on the route anymore
698 for (StopParVector::iterator it = myPastStops.begin(); it != myPastStops.end();) {
699 const MSEdge* stopEdge = (it->edge.empty()) ? &MSLane::dictionary(it->lane)->getEdge() : MSEdge::dictionary(it->edge);
700 if (std::find(myRoute->begin(), myRoute->end(), stopEdge) == myRoute->end()) {
701 it = myPastStops.erase(it);
702 } else {
703 ++it;
704 }
705 }
706 // if we did not drive yet it may be best to simply reassign the stops from scratch
707 if (stopsFromScratch) {
708 myStops.clear();
710 } else {
711 // recheck old stops
712 MSRouteIterator searchStart = myCurrEdge;
713 double lastPos = getPositionOnLane() + getBrakeGap();
714 if (getLane() != nullptr && getLane()->isInternal()
715 && myStops.size() > 0 && !myStops.front().lane->isInternal()) {
716 // searchStart is still incoming to the intersection so lastPos
717 // relative to that edge must be adapted
718 lastPos += (*myCurrEdge)->getLength();
719 }
720 int stopIndex = 0;
721 for (std::list<MSStop>::iterator iter = myStops.begin(); iter != myStops.end();) {
722 int lastToSkip = 0;
723 double endPos = iter->getEndPos(*this);
724#ifdef DEBUG_REPLACE_ROUTE
725 if (DEBUG_COND) {
726 std::cout << " stopEdge=" << iter->lane->getEdge().getID() << " start=" << (searchStart - myCurrEdge) << " endPos=" << endPos << " lastPos=" << lastPos << "\n";
727 }
728#endif
729 if (*searchStart != &iter->lane->getEdge()
730 // loop required to reach upstream position
731 || endPos + NUMERICAL_EPS < lastPos
732 // loop requested at duplicate pos
733 || (endPos == lastPos && iter->pars.index == STOP_INDEX_REPEAT)
734 // index encodes a skip
735 || (iter->pars.index > (int)myPastStops.size() + stopIndex
736 // and we are not already past the skipped edge
737 && lastToSkip < (int)iter->skips.size()
738 && searchStart - myRoute->begin() <= iter->skips[lastToSkip])) {
739 if (searchStart != edges.end() && !iter->reached) {
740#ifdef DEBUG_REPLACE_ROUTE
741 if (DEBUG_COND) {
742 std::cout << " skip " << (*searchStart)->getID() << "\n";
743 }
744#endif
745 lastToSkip++;
746 searchStart++;
747 }
748 }
749 lastPos = endPos;
750
751 iter->edge = std::find(searchStart, edges.end(), &iter->lane->getEdge());
752#ifdef DEBUG_REPLACE_ROUTE
753 if (DEBUG_COND) {
754 std::cout << " foundIndex=" << (iter->edge - myCurrEdge) << " end=" << (edges.end() - myCurrEdge) << "\n";
755 }
756#endif
757 if (iter->edge == edges.end() && iter->pars.priority >= 0) {
758 const std::string oldEdge = iter->pars.edge;
759 const std::string oldName = iter->getStoppingPlaceName().first;
760 if (replaceWithAlternative(iter, searchStart, edges.end())) {
761 WRITE_WARNINGF(TL("Vehicle '%' replaced stop on edge '%' (named '%') and now stops at '%' instead; after rerouting (%) at time=%."),
762 getID(), oldEdge, oldName, iter->getDescription(true), info, time2string(SIMSTEP));
763 }
764 }
765 if (iter->edge == edges.end()) {
766 if (!removeStops) {
767 WRITE_ERRORF(TL("Vehicle '%' could not assign stop '%' after rerouting (%) at time=%."), getID(), iter->getDescription(), info, time2string(SIMSTEP));
768 }
769 iter = myStops.erase(iter);
770 continue;
771 } else {
772 setSkips(*iter, stopIndex);
773 searchStart = iter->edge;
774 }
775 ++iter;
776 stopIndex++;
777 }
778 // add new stops
779 if (addRouteStops) {
780 for (StopParVector::const_iterator i = newRoute->getStops().begin(); i != newRoute->getStops().end(); ++i) {
781 std::string error;
783 if (error != "") {
784 WRITE_WARNING(error);
785 }
786 }
787 }
788 }
789 return true;
790}
791
792
793bool
794MSBaseVehicle::replaceWithAlternative(std::list<MSStop>::iterator iter, const MSRouteIterator searchStart, const MSRouteIterator end) {
795 std::pair<std::string, SumoXMLTag> nameTag = iter->getStoppingPlaceName();
796 if (!nameTag.first.empty()) {
797 const std::vector<MSStoppingPlace*>& alternatives = MSNet::getInstance()->getStoppingPlaceAlternatives(nameTag.first, nameTag.second);
798 for (MSStoppingPlace* alt : alternatives) {
799 //std::cout << SIMTIME << " veh=" << getID() << " name=" << nameTag.first << " alt=" << alt->getID() << "\n";
800 if (&alt->getLane().getEdge() == &iter->lane->getEdge()
801 || !alt->getLane().allowsVehicleClass(getVClass())) {
802 continue;
803 }
804 iter->edge = std::find(searchStart, end, &alt->getLane().getEdge());
805 if (iter->edge != end) {
806 iter->replaceStoppingPlace(alt);
807 return true;
808 }
809 }
810 }
811 return false;
812}
813
814
815double
817 return 0;
818}
819
820
821void
827
828
831 const SUMOTime dep = getParameter().depart;
832 if (dep < 0) {
833 return 0;
834 }
835 return hasDeparted() ? getDeparture() - dep : SIMSTEP - dep;
836}
837
838
839bool
841 return succEdge(1) == nullptr;
842}
843
844
845int
847 return (int) std::distance(myRoute->begin(), myCurrEdge);
848}
849
850
851int
853 if (myParameter->arrivalEdge >= 0) {
855 } else {
856 return myRoute->size() - getRoutePosition();
857 }
858}
859
860
861void
863 myCurrEdge = myRoute->begin() + index;
864 const_cast<SUMOVehicleParameter*>(myParameter)->departLaneProcedure = departLaneProcedure;
865 // !!! hack
866 myArrivalPos = (*(myRoute->end() - 1))->getLanes()[0]->getLength();
867}
868
869double
873
874bool
876 if (t->isPerson() && getPersonNumber() >= getVehicleType().getPersonCapacity()) {
877 return false;
878 } else if (!t->isPerson() && getContainerNumber() >= getVehicleType().getContainerCapacity()) {
879 return false;
880 }
881 if (isStopped() && myStops.begin()->pars.permitted.size() > 0
882 && myStops.begin()->pars.permitted.count(t->getID()) == 0) {
883 return false;
884 }
885 MSDevice_Taxi* taxiDevice = static_cast<MSDevice_Taxi*>(getDevice(typeid(MSDevice_Taxi)));
886 if (taxiDevice != nullptr) {
887 return taxiDevice->allowsBoarding(t);
888 }
889 return true;
890}
891
892
893void
895 if (transportable->isPerson()) {
896 if (myPersonDevice == nullptr) {
900 }
901 }
902 myPersonDevice->addTransportable(transportable);
903 } else {
904 if (myContainerDevice == nullptr) {
908 }
909 }
910 myContainerDevice->addTransportable(transportable);
911 }
912 if (myEnergyParams != nullptr) {
914 }
915}
916
917
918void
920 if (isPerson) {
922 myMoveReminders.insert(myMoveReminders.begin(), std::make_pair(myPersonDevice, 0.));
923 } else {
925 myMoveReminders.insert(myMoveReminders.begin(), std::make_pair(myContainerDevice, 0.));
926 }
927}
928
929
930bool
932 for (const MSStop& stop : myStops) {
933 if (stop.edge == it && stop.pars.jump >= 0) {
934 return true;
935 } else if (stop.edge > it) {
936 return false;
937 }
938 }
939 return false;
940}
941
942
943bool
944MSBaseVehicle::hasValidRoute(std::string& msg, ConstMSRoutePtr route) const {
946 if (route == nullptr) {
947 route = myRoute;
948 } else {
949 start = route->begin();
950 }
951 const bool checkJumps = route == myRoute; // the edge iterators in the stops are invalid otherwise
952 return hasValidRoute(msg, start, route->end(), checkJumps);
953}
954
955
956bool
957MSBaseVehicle::hasValidRoute(std::string& msg, MSRouteIterator start, MSRouteIterator last, bool checkJumps) const {
958 MSRouteIterator lastValid = last - 1;
959 // check connectivity, first
960 for (MSRouteIterator e = start; e != lastValid; ++e) {
961 const MSEdge& next = **(e + 1);
962 if ((*e)->allowedLanes(next, myType->getVehicleClass()) == nullptr) {
963 if (!checkJumps || !hasJump(e)) {
965 || (!next.hasTransientPermissions() && !(*e)->hasTransientPermissions())) {
966 msg = TLF("No connection between edge '%' and edge '%'.", (*e)->getID(), (*(e + 1))->getID());
967 return false;
968 }
969 }
970 }
971 }
972 // check usable lanes, then
973 for (MSRouteIterator e = start; e != last; ++e) {
974 if ((*e)->prohibits(this)) {
975 msg = TLF("Edge '%' prohibits.", (*e)->getID());
976 return false;
977 }
978 }
979 return true;
980}
981
982
983bool
985 if (!(*myCurrEdge)->isTazConnector()) {
987 msg = TLF("Departure speed for vehicle '%' is too high for the vehicle type '%'.", getID(), myType->getID());
989 return false;
990 }
991 }
992 if (myRoute->getEdges().size() > 0 && !(*myCurrEdge)->prohibits(this)) {
993 myRouteValidity &= ~ROUTE_START_INVALID_PERMISSIONS;
994 return true;
995 } else {
996 msg = TLF("Vehicle '%' is not allowed to depart on any lane of edge '%'.", getID(), (*myCurrEdge)->getID());
998 return false;
999 }
1000}
1001
1002
1003int
1004MSBaseVehicle::getRouteValidity(bool update, bool silent, std::string* msgReturn) {
1005 if (!update) {
1006 return myRouteValidity;
1007 }
1008 // insertion check must be done in any case
1009 std::string msg;
1010 if (!hasValidRouteStart(msg)) {
1012 throw ProcessError(msg);
1013 } else if (!silent) {
1014 // vehicle will be discarded
1015 WRITE_WARNING(msg);
1016 } else if (msgReturn != nullptr) {
1017 *msgReturn = msg;
1018 }
1019 }
1020 if ((MSGlobals::gCheckRoutes || myRoute->getFirstEdge()->isInternal())
1022 // we could check after the first rerouting
1024 if (!hasValidRoute(msg, myRoute)) {
1026 throw ProcessError(TLF("Vehicle '%' has no valid route. %", getID(), msg));
1027 }
1028 }
1029 myRouteValidity &= ~ROUTE_UNCHECKED;
1030 return myRouteValidity;
1031}
1032
1033
1034bool
1036 for (auto item : myMoveReminders) {
1037 if (item.first == rem) {
1038 return true;
1039 }
1040 }
1041 return false;
1042}
1043
1044
1045void
1047#ifdef _DEBUG
1048 if (myTraceMoveReminders) {
1049 traceMoveReminder("add", rem, pos, true);
1050 }
1051#endif
1052 myMoveReminders.push_back(std::make_pair(rem, pos));
1053}
1054
1055
1056void
1058 for (MoveReminderCont::iterator r = myMoveReminders.begin(); r != myMoveReminders.end(); ++r) {
1059 if (r->first == rem) {
1060#ifdef _DEBUG
1061 if (myTraceMoveReminders) {
1062 traceMoveReminder("remove", rem, 0, false);
1063 }
1064#endif
1065 myMoveReminders.erase(r);
1066 return;
1067 }
1068 }
1069}
1070
1071
1072void
1074 // notifyEnter may cause new reminders to be added so we cannot use an iterator
1075 for (int i = 0; i < (int)myMoveReminders.size();) {
1076 MSMoveReminder* rem = myMoveReminders[i].first;
1077 const double remPos = myMoveReminders[i].second;
1078 // skip the reminder if it is a lane reminder but not for my lane (indicated by rem->second > 0.)
1079 if (rem->getLane() != nullptr && remPos > 0.) {
1080#ifdef _DEBUG
1081 if (myTraceMoveReminders) {
1082 traceMoveReminder("notifyEnter_skipped", rem, remPos, true);
1083 }
1084#endif
1085 ++i;
1086 } else {
1087 if (rem->notifyEnter(*this, reason, enteredLane)) {
1088#ifdef _DEBUG
1089 if (myTraceMoveReminders) {
1090 traceMoveReminder("notifyEnter", rem, remPos, true);
1091 }
1092#endif
1093 ++i;
1094 } else {
1095#ifdef _DEBUG
1096 if (myTraceMoveReminders) {
1097 traceMoveReminder("notifyEnter", rem, remPos, false);
1098 }
1099#endif
1100 myMoveReminders.erase(myMoveReminders.begin() + i);
1101 }
1102 }
1103 }
1104}
1105
1106
1107bool
1109 return isRailway(getVClass()) || isRailway(getCurrentEdge()->getPermissions());
1110}
1111
1112void
1114 if (myRoute->getLastEdge()->isTazConnector()) {
1115 return;
1116 }
1117 const int arrivalEdgeIndex = MIN2(myParameter->arrivalEdge, (int)myRoute->getEdges().size() - 1);
1118 if (arrivalEdgeIndex != myParameter->arrivalEdge) {
1119 if (!(onInit && myParameter->wasSet(VEHPARS_FORCE_REROUTE))) {
1120 WRITE_WARNINGF(TL("Vehicle '%' ignores attribute arrivalEdge=% after rerouting at time=% (routeLength=%)"),
1121 getID(), myParameter->arrivalEdge, time2string(SIMSTEP), myRoute->getEdges().size() - 1);
1122 }
1123 }
1124 const MSEdge* arrivalEdge = myParameter->arrivalEdge >= 0 ? myRoute->getEdges()[arrivalEdgeIndex] : myRoute->getLastEdge();
1125 if (!onInit) {
1126 arrivalEdge = myRoute->getLastEdge();
1127 // ignore arrivalEdge parameter after rerouting
1128 const_cast<SUMOVehicleParameter*>(myParameter)->arrivalEdge = -1;
1129 }
1130 const std::vector<MSLane*>& lanes = arrivalEdge->getLanes();
1131 const double lastLaneLength = lanes[0]->getLength();
1134 if (fabs(myParameter->arrivalPos) > lastLaneLength) {
1135 WRITE_WARNINGF(TL("Vehicle '%' will not be able to arrive at the given position!"), getID());
1136 }
1137 // Maybe we should warn the user about invalid inputs!
1138 myArrivalPos = MIN2(myParameter->arrivalPos, lastLaneLength);
1139 if (myArrivalPos < 0) {
1140 myArrivalPos = MAX2(myArrivalPos + lastLaneLength, 0.);
1141 }
1142 break;
1144 myArrivalPos = RandHelper::rand(lastLaneLength);
1145 break;
1147 myArrivalPos = lastLaneLength / 2.;
1148 break;
1149 default:
1150 myArrivalPos = lastLaneLength;
1151 break;
1152 }
1154 if (myParameter->arrivalLane >= (int)lanes.size() || !lanes[myParameter->arrivalLane]->allowsVehicleClass(myType->getVehicleClass())) {
1155 WRITE_WARNINGF(TL("Vehicle '%' will not be able to arrive at the given lane '%_%'!"), getID(), arrivalEdge->getID(), toString(myParameter->arrivalLane));
1156 }
1157 myArrivalLane = MIN2(myParameter->arrivalLane, (int)(lanes.size() - 1));
1159 myArrivalLane = -1;
1160 for (MSLane* lane : lanes) {
1161 if (lane->allowsVehicleClass(myType->getVehicleClass())) {
1162 myArrivalLane = lane->getIndex();
1163 break;
1164 }
1165 }
1166 if (myArrivalLane == -1) {
1167 WRITE_WARNINGF(TL("Vehicle '%' has no usable arrivalLane on edge '%'."), getID(), arrivalEdge->getID());
1168 myArrivalLane = 0;
1169 }
1171 // pick random lane among all usable lanes
1172 std::vector<MSLane*> usable;
1173 for (MSLane* lane : lanes) {
1174 if (lane->allowsVehicleClass(myType->getVehicleClass())) {
1175 usable.push_back(lane);
1176 }
1177 }
1178 if (usable.empty()) {
1179 WRITE_WARNINGF(TL("Vehicle '%' has no usable arrivalLane on edge '%'."), getID(), arrivalEdge->getID());
1180 myArrivalLane = 0;
1181 } else {
1182 myArrivalLane = usable[RandHelper::rand(0, (int)usable.size())]->getIndex();
1183 }
1184 }
1186 for (std::vector<MSLane*>::const_iterator l = lanes.begin(); l != lanes.end(); ++l) {
1187 if (myParameter->arrivalSpeed <= (*l)->getVehicleMaxSpeed(this)) {
1188 return;
1189 }
1190 }
1191 WRITE_WARNINGF(TL("Vehicle '%' will not be able to arrive with the given speed!"), getID());
1192 }
1193}
1194
1195void
1199 const int routeEdges = (int)myRoute->getEdges().size();
1201 // write specific edge in vehroute output for reproducibility
1202 pars->departEdge = RandHelper::rand(0, routeEdges);
1204 }
1205 assert(pars->departEdge >= 0);
1206 if (pars->departEdge >= routeEdges) {
1207 WRITE_WARNINGF(TL("Ignoring departEdge % for vehicle '%' with % route edges"), toString(pars->departEdge), getID(), toString(routeEdges));
1208 } else {
1209 myCurrEdge = myRoute->begin() + pars->departEdge;
1210 }
1211 }
1213 const int routeEdges = (int)myRoute->getEdges().size();
1214 const int begin = (int)(myCurrEdge - myRoute->begin());
1215 // write specific edge in vehroute output for reproducibility
1216 pars->arrivalEdge = RandHelper::rand(begin, routeEdges);
1218 assert(pars->arrivalEdge >= begin);
1219 assert(pars->arrivalEdge < routeEdges);
1220 }
1221}
1222
1223int
1227
1228int
1232 } else {
1234 }
1235}
1236
1237double
1239 return MAX2(0., MIN2(1., getVehicleType().getImpatience()
1240 + (hasInfluencer() ? getBaseInfluencer()->getExtraImpatience() : 0)
1242}
1243
1244
1245MSDevice*
1246MSBaseVehicle::getDevice(const std::type_info& type) const {
1247 for (MSVehicleDevice* const dev : myDevices) {
1248 if (typeid(*dev) == type) {
1249 return dev;
1250 }
1251 }
1252 return nullptr;
1253}
1254
1255
1256void
1258 // the parameters may hold the name of a vTypeDistribution but we are interested in the actual type
1259 const std::string& typeID = myParameter->vtypeid != getVehicleType().getID() ? getVehicleType().getID() : "";
1261 // params and stops must be written in child classes since they may wish to add additional attributes first
1262 out.writeAttr(SUMO_ATTR_ROUTE, myRoute->getID());
1263 std::ostringstream os;
1264 os << myOdometer << " " << myNumberReroutes;
1265 out.writeAttr(SUMO_ATTR_DISTANCE, os.str());
1268 }
1270 const int precision = out.getPrecision();
1271 out.setPrecision(MAX2(gPrecisionRandom, precision));
1273 out.setPrecision(precision);
1274 }
1276 out.writeAttr(SUMO_ATTR_REROUTE, true);
1277 }
1279 // could be set from stop
1281 }
1282 // here starts the vehicle internal part (see loading)
1283 // @note: remember to close the vehicle tag when calling this in a subclass!
1284}
1285
1286
1287bool
1288MSBaseVehicle::handleCollisionStop(MSStop& stop, const double distToStop) {
1289 UNUSED_PARAMETER(stop);
1290 UNUSED_PARAMETER(distToStop);
1291 return true;
1292}
1293
1294
1295bool
1297 return !myStops.empty() && myStops.begin()->reached /*&& myState.mySpeed < SUMO_const_haltingSpeed @todo #1864#*/;
1298}
1299
1300
1301bool
1303 return (isStopped() && (myStops.begin()->pars.parking == ParkingType::OFFROAD)
1304 && (myStops.begin()->parkingarea == nullptr || !myStops.begin()->parkingarea->parkOnRoad())
1305 && (myStops.begin()->getSpeed() == 0 || getSpeed() < SUMO_const_haltingSpeed));
1306}
1307
1308
1309bool
1311 return myPastStops.size() > 0 && myPastStops.back().jump >= 0 && getEdge()->getID() == myPastStops.back().edge && myPastStops.back().ended == SIMSTEP;
1312}
1313
1314
1315bool
1317 return isStopped() && (myStops.begin()->triggered || myStops.begin()->containerTriggered || myStops.begin()->joinTriggered);
1318}
1319
1320
1321bool
1323 return isStopped() && (myStops.begin()->pars.parking == ParkingType::OFFROAD);
1324}
1325
1326
1327bool
1328MSBaseVehicle::isStoppedInRange(const double pos, const double tolerance, bool checkFuture) const {
1329 if (isStopped() || (checkFuture && hasStops())) {
1330 const MSStop& stop = myStops.front();
1331 return stop.pars.startPos - tolerance <= pos && stop.pars.endPos + tolerance >= pos;
1332 }
1333 return false;
1334}
1335
1336bool
1337MSBaseVehicle::replaceParkingArea(MSParkingArea* parkingArea, std::string& errorMsg) {
1338 // Check if there is a parking area to be replaced
1339 if (parkingArea == 0) {
1340 errorMsg = "new parkingArea is NULL";
1341 return false;
1342 }
1343 if (myStops.size() == 0) {
1344 errorMsg = "vehicle has no stops";
1345 return false;
1346 }
1347 if (myStops.front().parkingarea == 0) {
1348 errorMsg = "first stop is not at parkingArea";
1349 return false;
1350 }
1351 MSStop& first = myStops.front();
1352 SUMOVehicleParameter::Stop& stopPar = const_cast<SUMOVehicleParameter::Stop&>(first.pars);
1353 std::string oldStopEdgeID = first.lane->getEdge().getID();
1354 // merge subsequent duplicate stops equals to parking area
1355 for (std::list<MSStop>::iterator iter = ++myStops.begin(); iter != myStops.end();) {
1356 if (iter->parkingarea == parkingArea) {
1357 stopPar.duration += iter->duration;
1358 myStops.erase(iter++);
1359 } else {
1360 break;
1361 }
1362 }
1363 stopPar.lane = parkingArea->getLane().getID();
1364 stopPar.parkingarea = parkingArea->getID();
1365 stopPar.startPos = parkingArea->getBeginLanePosition();
1366 stopPar.endPos = parkingArea->getEndLanePosition();
1367 stopPar.index = STOP_INDEX_FIT;
1368 first.edge = myRoute->end(); // will be patched in replaceRoute
1369 first.lane = &parkingArea->getLane();
1370 first.parkingarea = parkingArea;
1371
1372 // patch via edges
1373 std::string newStopEdgeID = parkingArea->getLane().getEdge().getID();
1374 if (myParameter->via.size() > 0 && myParameter->via.front() != newStopEdgeID) {
1375 if (myParameter->via.front() == oldStopEdgeID) {
1376 myParameter->via.erase(myParameter->via.begin());
1377 }
1378 myParameter->via.insert(myParameter->via.begin(), newStopEdgeID);
1379 }
1380 return true;
1381}
1382
1383
1386 MSParkingArea* nextParkingArea = nullptr;
1387 if (!myStops.empty()) {
1389 MSStop stop = myStops.front();
1390 if (!stop.reached && stop.parkingarea != nullptr) {
1391 nextParkingArea = stop.parkingarea;
1392 }
1393 }
1394 return nextParkingArea;
1395}
1396
1397
1400 MSParkingArea* currentParkingArea = nullptr;
1401 if (isParking()) {
1402 currentParkingArea = myStops.begin()->parkingarea;
1403 }
1404 return currentParkingArea;
1405}
1406
1407
1408const std::vector<std::string>&
1411 return myParameter->parkingBadges;
1412 } else {
1414 }
1415}
1416
1417
1418double
1419MSBaseVehicle::basePos(const MSEdge* edge) const {
1420 double result = MIN2(getVehicleType().getLength() + POSITION_EPS, edge->getMinLength());
1421 if (hasStops()
1422 && myStops.front().edge == myRoute->begin()
1423 && (&myStops.front().lane->getEdge()) == *myStops.front().edge) {
1424 result = MIN2(result, MAX2(0.0, myStops.front().getEndPos(*this)));
1425 }
1426 return result;
1427}
1428
1429
1430MSLane*
1432 const std::string edgeID = SUMOXMLDefinitions::getEdgeIDFromLane(stop.lane);
1433 const MSEdge* edge = MSEdge::dictionary(edgeID);
1434 if (edge == nullptr || edge->getOppositeEdge() == nullptr || stop.lane.find("_") == std::string::npos) {
1435 return nullptr;
1436 }
1437 const int laneIndex = SUMOXMLDefinitions::getIndexFromLane(stop.lane);
1438 if (laneIndex < (edge->getNumLanes() + edge->getOppositeEdge()->getNumLanes())) {
1439 const int oppositeIndex = edge->getOppositeEdge()->getNumLanes() + edge->getNumLanes() - 1 - laneIndex;
1440 stop.edge = edgeID;
1441 return edge->getOppositeEdge()->getLanes()[oppositeIndex];
1442 }
1443 return nullptr;
1444}
1445
1446
1447bool
1448MSBaseVehicle::addStop(const SUMOVehicleParameter::Stop& stopPar, std::string& errorMsg, SUMOTime untilOffset,
1449 MSRouteIterator* searchStart) {
1450 MSStop stop(stopPar);
1451 if (stopPar.lane == "") {
1452 MSEdge* e = MSEdge::dictionary(stopPar.edge);
1453 stop.lane = e->getFirstAllowed(getVClass(), false, getRoutingMode());
1454 if (stop.lane == nullptr) {
1455 errorMsg = "Vehicle '" + myParameter->id + "' is not allowed to stop on any lane of edge '" + stopPar.edge + "'.";
1456 return false;
1457 }
1458 } else {
1459 stop.lane = MSLane::dictionary(stopPar.lane);
1460 if (stop.lane == nullptr) {
1461 // must be an opposite stop
1462 SUMOVehicleParameter::Stop tmp = stopPar;
1463 stop.lane = interpretOppositeStop(tmp);
1464 assert(stop.lane != nullptr);
1465 }
1467 errorMsg = "Vehicle '" + myParameter->id + "' is not allowed to stop on lane '" + stopPar.lane + "'.";
1468 return false;
1469 }
1470 }
1472 stop.segment = MSGlobals::gMesoNet->getSegmentForEdge(stop.lane->getEdge(), stop.getEndPos(*this));
1473 if (stop.lane->isInternal()) {
1474 errorMsg = "Mesoscopic simulation does not allow stopping on internal edge '" + stopPar.edge + "' for vehicle '" + myParameter->id + "'.";
1475 return false;
1476 }
1477 }
1478 stop.initPars(stopPar);
1479 if (stopPar.until != -1) {
1480 // !!! it would be much cleaner to invent a constructor for stops which takes "until" as an argument
1481 const_cast<SUMOVehicleParameter::Stop&>(stop.pars).until += untilOffset;
1482 }
1483 if (stopPar.arrival != -1) {
1484 const_cast<SUMOVehicleParameter::Stop&>(stop.pars).arrival += untilOffset;
1485 }
1486 std::string stopType = "stop";
1487 std::string stopID = "";
1488 double parkingLength = stop.pars.endPos - stop.pars.startPos;
1489 if (stop.busstop != nullptr) {
1490 stopType = toString(stop.busstop->getElement());
1491 stopID = stop.busstop->getID();
1492 parkingLength = stop.busstop->getParkingLength();
1493 } else if (stop.containerstop != nullptr) {
1494 stopType = "containerStop";
1495 stopID = stop.containerstop->getID();
1496 parkingLength = stop.containerstop->getParkingLength();
1497 } else if (stop.chargingStation != nullptr) {
1498 stopType = "chargingStation";
1499 stopID = stop.chargingStation->getID();
1500 parkingLength = stop.chargingStation->getParkingLength();
1501 } else if (stop.overheadWireSegment != nullptr) {
1502 stopType = "overheadWireSegment";
1503 stopID = stop.overheadWireSegment->getID();
1504 parkingLength = stop.overheadWireSegment->getParkingLength();
1505 } else if (stop.parkingarea != nullptr) {
1506 stopType = "parkingArea";
1507 stopID = stop.parkingarea->getID();
1508 }
1509 const std::string errorMsgStart = stopID == "" ? stopType : stopType + " '" + stopID + "'";
1510
1511 if (stop.pars.startPos < 0 || stop.pars.endPos > stop.lane->getLength()) {
1512 errorMsg = errorMsgStart + " for vehicle '" + myParameter->id + "' on lane '" + stop.lane->getID() + "' has an invalid position.";
1513 return false;
1514 }
1515 if (stopType != "stop" && stopType != "parkingArea" && myType->getLength() / 2. > parkingLength
1516 // do not warn for stops that fill the whole lane
1517 && parkingLength < stop.lane->getLength()
1518 // do not warn twice for the same stop
1519 && MSNet::getInstance()->warnOnce(stopType + ":" + stopID)) {
1520 errorMsg = errorMsgStart + " on lane '" + stop.lane->getID() + "' is too short for vehicle '" + myParameter->id + "'.";
1521 }
1522 if (stopType == "parkingArea" && !stop.parkingarea->accepts(this)) {
1523 // forbid access in case the parking requests other badges
1524 errorMsg = errorMsgStart + "on lane '" + stop.lane->getID() + "' forbids access because vehicle '" + myParameter->id + "' does not provide any valid badge.";
1525 return false;
1526 }
1527 const MSEdge* stopLaneEdge = &stop.lane->getEdge();
1528 const MSEdge* stopEdge;
1529 if (stopLaneEdge->getOppositeEdge() != nullptr && stopLaneEdge->getOppositeEdge()->getID() == stopPar.edge) {
1530 // stop lane is on the opposite side
1531 stopEdge = stopLaneEdge->getOppositeEdge();
1532 stop.isOpposite = true;
1533 } else {
1534 // if stop is on an internal edge the normal edge before the intersection is used
1535 stopEdge = stopLaneEdge->getNormalBefore();
1536 }
1537 MSRouteIterator succ = myCurrEdge + 1; // we're using the address but only within the scope of this function (and recursive calls)
1538 if (searchStart == nullptr) {
1539 searchStart = &myCurrEdge;
1540 if (stopLaneEdge->isNormal() && getLane() != nullptr && getLane()->isInternal()) {
1541 // already on the intersection but myCurrEdge is before it
1542 searchStart = &succ;
1543 }
1544 }
1545#ifdef DEBUG_ADD_STOP
1546 if (DEBUG_COND) {
1547 std::cout << "addStop desc=" << stop.getDescription() << " stopEdge=" << stopEdge->getID()
1548 << " searchStart=" << ((*searchStart) == myRoute->end() ? "END" : (**searchStart)->getID())
1549 << " index=" << (int)((*searchStart) - myRoute->begin()) << " route=" << toString(myRoute->getEdges())
1550 << " stopParIndex=" << stopPar.index
1551 << "\n";
1552 }
1553#endif
1554 stop.edge = std::find(*searchStart, myRoute->end(), stopEdge);
1555 MSRouteIterator prevStopEdge = myCurrEdge;
1556 const MSEdge* prevEdge = (getLane() == nullptr ? getEdge() : &getLane()->getEdge());
1557 double prevStopPos = getPositionOnLane();
1558 // where to insert the stop
1559 std::list<MSStop>::iterator iter = myStops.begin();
1560 if (stopPar.index == STOP_INDEX_END || stopPar.index >= static_cast<int>(myStops.size()) || stopPar.index == STOP_INDEX_REPEAT) {
1561 iter = myStops.end();
1562 if (myStops.size() > 0 && myStops.back().edge >= *searchStart) {
1563 prevStopEdge = myStops.back().edge;
1564 prevEdge = &myStops.back().lane->getEdge();
1565 prevStopPos = myStops.back().pars.endPos;
1566 stop.edge = std::find(prevStopEdge, myRoute->end(), stopEdge);
1567 if (prevStopEdge == stop.edge // laneEdge check is insufficient for looped routes
1568 && prevEdge == &stop.lane->getEdge() // route iterator check insufficient for internal lane stops
1569 && (prevStopPos > stop.pars.endPos ||
1570 (prevStopPos == stop.pars.endPos && stopPar.index == STOP_INDEX_REPEAT))) {
1571 stop.edge = std::find(prevStopEdge + 1, myRoute->end(), stopEdge);
1572 }
1573#ifdef DEBUG_ADD_STOP
1574 if (DEBUG_COND) {
1575 std::cout << " (@end) prevStopEdge=" << (*prevStopEdge)->getID() << " prevStopPos=" << prevStopPos << " index=" << (int)(prevStopEdge - myRoute->begin())
1576 << " foundIndex=" << (stop.edge == myRoute->end() ? -1 : (int)(stop.edge - myRoute->begin())) << "\n";
1577 }
1578#endif
1579 }
1580 // skip a number of occurences of stopEdge in looped route
1581 int skipLooped = stopPar.index - static_cast<int>(myStops.size());
1582 for (int j = 0; j < skipLooped; j++) {
1583 auto nextIt = std::find(stop.edge + 1, myRoute->end(), stopEdge);
1584 if (nextIt == myRoute->end()) {
1585 if (std::find(myRoute->begin(), stop.edge, stopEdge) != stop.edge) {
1586 // only warn if the route loops over the stop edge at least once
1587 errorMsg = errorMsgStart + " for vehicle '" + myParameter->id + "' could not skip " + toString(skipLooped) + " occurences of stop edge '" + stopEdge->getID() + "' in looped route.";
1588 }
1589 break;
1590 } else {
1591 stop.edge = nextIt;
1592 }
1593 }
1594 } else {
1595 if (stopPar.index == STOP_INDEX_FIT) {
1596 while (iter != myStops.end() && (iter->edge < stop.edge ||
1597 (iter->pars.endPos < stop.pars.endPos && iter->edge == stop.edge) ||
1598 (stop.lane->getEdge().isInternal() && iter->edge == stop.edge))) {
1599 prevStopEdge = iter->edge;
1600 prevStopPos = iter->pars.endPos;
1601 ++iter;
1602 }
1603 } else {
1604 int index = stopPar.index;
1605 while (index > 0) {
1606 prevStopEdge = iter->edge;
1607 prevStopPos = iter->pars.endPos;
1608 ++iter;
1609 --index;
1610 }
1611#ifdef DEBUG_ADD_STOP
1612 if (DEBUG_COND) {
1613 std::cout << " (@fit) prevStopEdge=" << (*prevStopEdge)->getID() << " index=" << (int)(prevStopEdge - myRoute->begin()) << "\n";
1614 }
1615#endif
1616 stop.edge = std::find(prevStopEdge, myRoute->end(), stopEdge);
1617 }
1618 }
1619 const bool wasTooClose = errorMsg != "" && errorMsg.find("too close") != std::string::npos;
1620 if (stop.edge == myRoute->end()) {
1621 if (!wasTooClose) {
1622 errorMsg = errorMsgStart + " for vehicle '" + myParameter->id + "' on lane '" + stop.lane->getID() + "' is not downstream the current route.";
1623 }
1624 return false;
1625 }
1626
1627 const bool tooClose = (prevStopEdge == stop.edge && prevEdge == &stop.lane->getEdge() &&
1628 prevStopPos + (iter == myStops.begin() && !instantStopping() ? getBrakeGap() : 0) > stop.pars.endPos + POSITION_EPS);
1629
1630 if (prevStopEdge > stop.edge ||
1631 // a collision-stop happens after vehicle movement and may move the
1632 // vehicle backwards on its lane (prevStopPos is the vehicle position)
1633 (tooClose && !stop.pars.collision)
1634 || (stop.lane->getEdge().isInternal() && stop.lane->getNextNormal() != *(stop.edge + 1))) {
1635 // check if the edge occurs again later in the route
1636 //std::cout << " could not add stop " << errorMsgStart << " prevStops=" << myStops.size() << " searchStart=" << (*searchStart - myRoute->begin()) << " route=" << toString(myRoute->getEdges()) << "\n";
1637 if (tooClose && prevStopPos <= stop.pars.endPos + POSITION_EPS) {
1638 errorMsg = errorMsgStart + " for vehicle '" + myParameter->id + "' on lane '" + stop.pars.lane + "' is too close to brake.";
1639 }
1640 MSRouteIterator next = stop.edge + 1;
1641 return addStop(stopPar, errorMsg, untilOffset, &next);
1642 }
1643 // David.C:
1644 //if (!stop.parking && (myCurrEdge == stop.edge && myState.myPos > stop.endPos - getCarFollowModel().brakeGap(myState.mySpeed))) {
1645 const double endPosOffset = stop.lane->getEdge().isInternal() ? (*stop.edge)->getLength() : 0;
1646 const double distToStop = stop.pars.endPos + endPosOffset - getPositionOnLane();
1647 if (stop.pars.collision && !handleCollisionStop(stop, distToStop)) {
1648 return false;
1649 }
1650 if (!hasDeparted() && myCurrEdge == stop.edge) {
1651 double pos = -1;
1653 pos = myParameter->departPos;
1654 if (pos < 0.) {
1655 pos += (*myCurrEdge)->getLength();
1656 }
1657 }
1659 pos = MIN2(stop.pars.endPos + endPosOffset, basePos(*myCurrEdge));
1660 }
1661 if (pos > stop.pars.endPos + endPosOffset) {
1662 if (stop.edge != myRoute->end()) {
1663 // check if the edge occurs again later in the route
1664 MSRouteIterator next = stop.edge + 1;
1665 return addStop(stopPar, errorMsg, untilOffset, &next);
1666 }
1667 errorMsg = errorMsgStart + " for vehicle '" + myParameter->id + "' on lane '" + stop.lane->getID() + "' is before departPos.";
1668 return false;
1669 }
1670 }
1671 if (iter != myStops.begin()) {
1672 std::list<MSStop>::iterator iter2 = iter;
1673 iter2--;
1674 if (stop.getUntil() >= 0 && iter2->getUntil() > stop.getUntil()
1675 && (!MSGlobals::gUseStopEnded || iter2->pars.ended < 0 || stop.pars.ended >= 0)) {
1676 errorMsg = errorMsgStart + " for vehicle '" + myParameter->id + "' on lane '" + stop.lane->getID()
1677 + "' set to end at " + time2string(stop.getUntil())
1678 + " earlier than previous stop at " + time2string(iter2->getUntil()) + ".";
1679 }
1680 if (stop.pars.arrival >= 0 && iter2->pars.arrival > stop.pars.arrival) {
1681 errorMsg = errorMsgStart + " for vehicle '" + myParameter->id + "' on lane '" + stop.lane->getID()
1682 + "' set to start at " + time2string(stop.pars.arrival)
1683 + " earlier than previous stop end at " + time2string(iter2->getUntil()) + ".";
1684 }
1685 if (stop.pars.arrival >= 0 && iter2->pars.arrival > stop.pars.arrival) {
1686 errorMsg = errorMsgStart + " for vehicle '" + myParameter->id + "' on lane '" + stop.lane->getID()
1687 + "' set to start at " + time2string(stop.pars.arrival)
1688 + " earlier than previous stop arrival at " + time2string(iter2->pars.arrival) + ".";
1689 }
1690 } else {
1691 if (stop.getUntil() >= 0 && getParameter().depart > stop.getUntil()
1692 && (!MSGlobals::gUseStopEnded || stop.pars.ended < 0)) {
1693 errorMsg = errorMsgStart + " for vehicle '" + myParameter->id + "' on lane '" + stop.lane->getID()
1694 + "' set to end at " + time2string(stop.getUntil())
1695 + " earlier than departure at " + time2string(getParameter().depart) + ".";
1696 }
1697 }
1698 if (stop.getUntil() >= 0 && stop.getArrival() > stop.getUntil() && errorMsg == "") {
1699 errorMsg = errorMsgStart + " for vehicle '" + myParameter->id + "' on lane '" + stop.lane->getID()
1700 + "' set to end at " + time2string(stop.getUntil())
1701 + " earlier than arrival at " + time2string(stop.getArrival()) + ".";
1702 }
1703 setSkips(stop, (int)myStops.size());
1704 myStops.insert(iter, stop);
1705 if (stopPar.tripId != "") {
1707 }
1708#ifdef DEBUG_ADD_STOP
1709 if (DEBUG_COND) {
1710 std::cout << " added stop " << errorMsgStart << " totalStops=" << myStops.size()
1711 << " routeIndex=" << (stop.edge - myRoute->begin())
1712 << " stopIndex=" << std::distance(myStops.begin(), iter)
1713 //<< " searchStart=" << (*searchStart - myRoute->begin())
1714 //<< " route=" << toString(myRoute->getEdges())
1715 << "\n";
1716 }
1717#endif
1718 return true;
1719}
1720
1721
1722void
1723MSBaseVehicle::setSkips(MSStop& stop, int prevActiveStops) {
1724 if (hasDeparted() && stop.edge > myRoute->begin()) {
1725 // if the route is looped we must patch the index to ensure that state
1726 // loading (and vehroute-output) encode the correct number of skips
1727 stop.skips.clear();
1728 MSRouteIterator itPrev;
1729 double prevEndPos;
1730 if (prevActiveStops > 0) {
1731 assert((int)myStops.size() >= prevActiveStops);
1732 auto prevStopIt = myStops.begin();
1733 std::advance(prevStopIt, prevActiveStops - 1);
1734 const MSStop& prev = *prevStopIt;
1735 itPrev = prev.edge;
1736 prevEndPos = prev.pars.endPos;
1737 } else if (myPastStops.size() > 0) {
1738 itPrev = myRoute->begin() + myPastStops.back().routeIndex;
1739 prevEndPos = myPastStops.back().endPos;
1740 } else {
1741 itPrev = myRoute->begin() + myParameter->departEdge;
1742 prevEndPos = myDepartPos;
1743 }
1744 //auto itPrevOrig = itPrev;
1745 if (*itPrev == *stop.edge && prevEndPos > stop.pars.endPos) {
1746 itPrev++;
1747 }
1748 //std::cout << SIMTIME << " veh=" << getID() << " prevActive=" << prevActiveStops << " edge=" << (*stop.edge)->getID() << " routeIndex=" << (stop.edge - myRoute->begin()) << " prevIndex=" << (itPrev - myRoute->begin()) << "\n";
1749 while (itPrev < stop.edge) {
1750 if (*itPrev == *stop.edge) {
1751 stop.skips.push_back((int)(itPrev - myRoute->begin()));
1752 }
1753 itPrev++;
1754 }
1755 int newIndex = STOP_INDEX_END;
1756 if (!stop.skips.empty()) {
1757 //if (getID() == "77_0_0") {
1758 // std::cout << SIMTIME << " veh=" << getID() << " past=" << myPastStops.size() << " prevActive=" << prevActiveStops
1759 // << " edge=" << (*stop.edge)->getID() << " routeIndex=" << (stop.edge - myRoute->begin())
1760 // << " prevEdge=" << (*itPrevOrig)->getID()
1761 // << " prevIndex=" << (itPrevOrig - myRoute->begin())
1762 // << " skips=" << foundSkips << "\n";
1763 //}
1764 newIndex = (int)myPastStops.size() + prevActiveStops + (int)stop.skips.size();
1765 }
1766 const_cast<SUMOVehicleParameter::Stop&>(stop.pars).index = newIndex;
1767 }
1768}
1769
1770
1773 for (int i = 0; i < (int)myMoveReminders.size();) {
1774 auto rem = &myMoveReminders[i];
1775 if (rem->first->notifyReroute(*this)) {
1776#ifdef _DEBUG
1777 if (myTraceMoveReminders) {
1778 traceMoveReminder("notifyReroute", rem->first, rem->second, true);
1779 }
1780#endif
1781 ++i;
1782 } else {
1783#ifdef _DEBUG
1784 if (myTraceMoveReminders) {
1785 traceMoveReminder("notifyReroute", rem->first, rem->second, false);
1786 }
1787#endif
1788 myMoveReminders.erase(myMoveReminders.begin() + i);
1789 }
1790 }
1792 // event only called once
1793 return 0;
1794}
1795
1796
1797void
1798MSBaseVehicle::addStops(const bool ignoreStopErrors, MSRouteIterator* searchStart, bool addRouteStops) {
1799 if (addRouteStops) {
1800 for (const SUMOVehicleParameter::Stop& stop : myRoute->getStops()) {
1801 std::string errorMsg;
1802 if (!addStop(stop, errorMsg, myParameter->depart, searchStart) && !ignoreStopErrors) {
1803 throw ProcessError(errorMsg);
1804 }
1805 if (errorMsg != "") {
1806 WRITE_WARNING(errorMsg);
1807 }
1808 }
1809 }
1811 for (const SUMOVehicleParameter::Stop& stop : myParameter->stops) {
1812 std::string errorMsg;
1813 if (!addStop(stop, errorMsg, untilOffset, searchStart) && !ignoreStopErrors) {
1814 throw ProcessError(errorMsg);
1815 }
1816 if (errorMsg != "") {
1817 WRITE_WARNING(errorMsg);
1818 }
1819 }
1820}
1821
1822
1823bool
1826 int i = 0;
1827 bool ok = true;
1828 for (const MSStop& stop : myStops) {
1829 MSRouteIterator it;
1830 if (stop.lane->isInternal()) {
1831 // find the normal predecessor and ensure that the next route edge
1832 // matches the successor of the internal edge successor
1833 it = std::find(start, myRoute->end(), stop.lane->getEdge().getNormalBefore());
1834 if (it != myRoute->end() && (
1835 it + 1 == myRoute->end() || *(it + 1) != stop.lane->getEdge().getNormalSuccessor())) {
1836 it = myRoute->end(); // signal failure
1837 }
1838 } else {
1839 it = std::find(start, myRoute->end(), &stop.lane->getEdge());
1840 }
1841 if (it == myRoute->end()) {
1842 if (!silent) {
1843 WRITE_ERRORF("Stop % on edge '%' is not found after edge '%' (% after current) for vehicle '%' at time=%.",
1844 i, stop.lane->getEdge().getID(), (*start)->getID(), toString(start - myCurrEdge), getID(), time2string(SIMSTEP));
1845 }
1846 ok = false;
1847 } else {
1848 MSRouteIterator it2;
1849 for (it2 = myRoute->begin(); it2 != myRoute->end(); it2++) {
1850 if (it2 == stop.edge) {
1851 break;
1852 }
1853 }
1854 if (it2 == myRoute->end()) {
1855 if (!silent) {
1856 WRITE_ERRORF("Stop % on edge '%' used invalid route index for vehicle '%' at time=%.",
1857 i, stop.lane->getEdge().getID(), getID(), time2string(SIMSTEP));
1858 }
1859 ok = false;
1860 } else if (it2 < start) {
1861 if (!silent) {
1862 WRITE_ERRORF("Stop % on edge '%' used invalid (relative) route index % expected after % for vehicle '%' at time=%.",
1863 i, stop.lane->getEdge().getID(), toString(it2 - myCurrEdge), toString(start - myCurrEdge), getID(), time2string(SIMSTEP));
1864 }
1865 ok = false;
1866 } else {
1867 start = stop.edge;
1868 }
1869 }
1870 i++;
1871 }
1872 return ok;
1873}
1874
1875
1876std::vector<MSBaseVehicle::StopEdgeInfo>
1877MSBaseVehicle::getStopEdges(double& firstPos, double& lastPos, std::set<int>& jumps) const {
1878 assert(haveValidStopEdges());
1879 std::vector<StopEdgeInfo> result;
1880 const MSStop* prev = nullptr;
1881 const MSEdge* internalSuccessor = nullptr;
1882 for (const MSStop& stop : myStops) {
1883 if (stop.reached) {
1884 if (stop.pars.jump >= 0) {
1885 jumps.insert((int)result.size());
1886 }
1887 continue;
1888 }
1889 double stopPos = stop.getEndPos(*this);
1890 if ((prev == nullptr
1891 || prev->edge != stop.edge
1892 || (prev->lane == stop.lane && prev->getEndPos(*this) > stopPos))
1893 && *stop.edge != internalSuccessor) {
1894 if (stop.lane->isInternal()) {
1895 stopPos = (*stop.edge)->getLength();
1896 }
1897 result.push_back(StopEdgeInfo(*stop.edge, stop.pars.priority, stop.getArrivalFallback(), stopPos));
1898 result.back().nameTag = stop.getStoppingPlaceName();
1899 result.back().stopPar = &stop.pars;
1900 if (stop.lane->isInternal()) {
1901 internalSuccessor = stop.lane->getNextNormal();
1902 result.push_back(StopEdgeInfo(internalSuccessor, stop.pars.priority, stop.getArrivalFallback(), 0));
1903 } else {
1904 internalSuccessor = nullptr;
1905 }
1906 } else if (prev != nullptr && prev->edge == stop.edge) {
1907 result.back().priority = addStopPriority(result.back().priority, stop.pars.priority);
1908 }
1909 prev = &stop;
1910 if (firstPos == INVALID_DOUBLE) {
1911 if (stop.parkingarea != nullptr) {
1912 firstPos = MAX2(0., stopPos);
1913 } else {
1914 firstPos = stopPos;
1915 }
1916 }
1917 lastPos = stopPos;
1918 if (stop.pars.jump >= 0) {
1919 jumps.insert((int)result.size() - 1);
1920 }
1921 }
1922 //std::cout << SIMTIME << " getStopEdges veh=" << getID() << "\n";
1923 //for (auto item : result) {
1924 // std::cout << " e=" << item.edge->getID() << " pos=" << item.pos << "\n";
1925 //}
1926 return result;
1927}
1928
1929
1930double
1931MSBaseVehicle::addStopPriority(double p1, double p2) {
1932 if (p1 < 0 || p2 < 0) {
1933 return p1;
1934 }
1935 return p1 + p2;
1936}
1937
1938std::vector<std::pair<int, double> >
1940 std::vector<std::pair<int, double> > result;
1941 for (std::list<MSStop>::const_iterator iter = myStops.begin(); iter != myStops.end(); ++iter) {
1942 result.push_back(std::make_pair(
1943 (int)(iter->edge - myRoute->begin()),
1944 iter->getEndPos(*this)));
1945 }
1946 return result;
1947}
1948
1949
1950const MSStop&
1952 assert(myStops.size() > 0);
1953 return myStops.front();
1954}
1955
1956MSStop&
1958 assert(myStops.size() > 0);
1959 return myStops.front();
1960}
1961
1964 if (isStopped()) {
1965 return myStops.front().duration;
1966 } else {
1967 return 0;
1968 }
1969}
1970
1971
1972MSStop&
1973MSBaseVehicle::getStop(int nextStopIndex) {
1974 if (nextStopIndex < 0 || (int)myStops.size() <= nextStopIndex) {
1975 throw InvalidArgument(TLF("Invalid stop index % (has % stops).", nextStopIndex, myStops.size()));
1976 }
1977 auto stopIt = myStops.begin();
1978 std::advance(stopIt, nextStopIndex);
1979 return *stopIt;
1980}
1981
1982
1985 if (hasStops()) {
1986 return &myStops.front().pars;
1987 }
1988 return nullptr;
1989}
1990
1991
1992bool
1994 //if the stop exists update the duration
1995 for (std::list<MSStop>::iterator iter = myStops.begin(); iter != myStops.end(); iter++) {
1996 if (iter->lane->getID() == stop.lane && fabs(iter->pars.endPos - stop.endPos) < POSITION_EPS) {
1997 // update existing stop
1998 if (stop.duration == 0 && stop.until < 0 && !iter->reached) {
1999 myStops.erase(iter);
2000 } else {
2001 iter->duration = stop.duration;
2002 iter->triggered = stop.triggered;
2003 iter->containerTriggered = stop.containerTriggered;
2004 const_cast<SUMOVehicleParameter::Stop&>(iter->pars).until = stop.until;
2005 const_cast<SUMOVehicleParameter::Stop&>(iter->pars).parking = stop.parking;
2006 }
2007 return true;
2008 }
2009 }
2010 const bool result = addStop(stop, errorMsg);
2011 if (result) {
2013 myParameter->stops.push_back(stop);
2014 }
2015 return result;
2016}
2017
2018
2019void
2026
2027
2028bool
2030 if (hasStops() && nextStopIndex < (int)myStops.size()) {
2031 if (nextStopIndex == 0 && isStopped()) {
2033 } else {
2034 auto stopIt = myStops.begin();
2035 std::advance(stopIt, nextStopIndex);
2036 if (stopIt->parkingarea != nullptr && stopIt->parkingarea->isReservable()) {
2037 stopIt->parkingarea->removeSpaceReservation(this);
2038 }
2039 myStops.erase(stopIt);
2040 }
2041 if (!hasDeparted() && (int)myParameter->stops.size() > nextStopIndex) {
2042 // stops will be rebuilt from scratch on rerouting so we must patch the stops in myParameter
2043 auto stopIt2 = myParameter->stops.begin();
2044 std::advance(stopIt2, nextStopIndex);
2045 const_cast<SUMOVehicleParameter*>(myParameter)->stops.erase(stopIt2);
2046 }
2047 return true;
2048 } else {
2049 return false;
2050 }
2051}
2052
2053
2054bool
2055MSBaseVehicle::replaceStop(int nextStopIndex, SUMOVehicleParameter::Stop stop, const std::string& info, bool teleport, std::string& errorMsg) {
2056 const int n = (int)myStops.size();
2057 if (nextStopIndex < 0 || nextStopIndex >= n) {
2058 errorMsg = TLF("invalid nextStopIndex % for % remaining stops", nextStopIndex, n);
2059 return false;
2060 }
2061 if (nextStopIndex == 0 && isStopped()) {
2062 errorMsg = TL("cannot replace reached stop");
2063 return false;
2064 }
2066 MSLane* stopLane = MSLane::dictionary(stop.lane);
2067 MSEdge* stopEdge = &stopLane->getEdge();
2068
2069 auto itStop = myStops.begin();
2070 std::advance(itStop, nextStopIndex);
2071 MSStop& replacedStop = *itStop;
2072
2073 // check parking access rights
2074 if (stop.parkingarea != "") {
2076 if (pa != nullptr && !pa->accepts(this)) {
2077 errorMsg = TLF("vehicle '%' does not have the right badge to access parkingArea '%'", getID(), stop.parkingarea);
2078 return false;
2079 }
2080 }
2081
2082 if (replacedStop.lane == stopLane && replacedStop.pars.endPos == stop.endPos && !teleport) {
2083 // only replace stop attributes
2084 const_cast<SUMOVehicleParameter::Stop&>(replacedStop.pars) = stop;
2085 replacedStop.initPars(stop);
2086 return true;
2087 }
2088
2089 if (!stopLane->allowsVehicleClass(getVClass(), myRoutingMode)) {
2090 errorMsg = TLF("disallowed stop lane '%'", stopLane->getID());
2091 return false;
2092 }
2093
2094 const ConstMSEdgeVector& oldEdges = getRoute().getEdges();
2095 std::vector<MSStop> stops(myStops.begin(), myStops.end());
2096 const int junctionOffset = getLane() != nullptr && getLane()->isInternal() ? 1 : 0;
2097 MSRouteIterator itStart = nextStopIndex == 0 ? getCurrentRouteEdge() + junctionOffset : stops[nextStopIndex - 1].edge;
2098 double startPos = nextStopIndex == 0 ? getPositionOnLane() : stops[nextStopIndex - 1].pars.endPos;
2099 MSRouteIterator itEnd = nextStopIndex == n - 1 ? oldEdges.end() - 1 : stops[nextStopIndex + 1].edge;
2100 auto endPos = nextStopIndex == n - 1 ? getArrivalPos() : stops[nextStopIndex + 1].pars.endPos;
2102
2103 bool newDestination = nextStopIndex == n - 1 && stops[nextStopIndex].edge == oldEdges.end() - 1;
2104
2105 ConstMSEdgeVector toNewStop;
2106 if (!teleport) {
2107 router.compute(*itStart, startPos, stopEdge, stop.endPos, this, t, toNewStop, true);
2108 if (toNewStop.size() == 0) {
2109 errorMsg = TLF("no route found from edge '%' to stop edge '%'", (*itStart)->getID(), stopEdge->getID());
2110 return false;
2111 }
2112 }
2113
2114 ConstMSEdgeVector fromNewStop;
2115 if (!newDestination) {
2116 router.compute(stopEdge, stop.endPos, *itEnd, endPos, this, t, fromNewStop, true);
2117 if (fromNewStop.size() == 0) {
2118 errorMsg = TLF("no route found from stop edge '%' to edge '%'", stopEdge->getID(), (*itEnd)->getID());
2119 return false;
2120 }
2121 }
2122
2124 const_cast<SUMOVehicleParameter::Stop&>(replacedStop.pars) = stop;
2125 replacedStop.initPars(stop);
2126 replacedStop.edge = myRoute->end(); // will be patched in replaceRoute
2127 replacedStop.lane = stopLane;
2129 replacedStop.segment = MSGlobals::gMesoNet->getSegmentForEdge(replacedStop.lane->getEdge(), replacedStop.getEndPos(*this));
2130 if (replacedStop.lane->isInternal()) {
2131 errorMsg = TLF("Mesoscopic simulation does not allow stopping on internal edge '%' for vehicle '%'.", stop.edge, getID());
2132 return false;
2133 }
2134 }
2135
2136 ConstMSEdgeVector oldRemainingEdges(myCurrEdge, getRoute().end());
2137 ConstMSEdgeVector newEdges; // only remaining
2138 newEdges.insert(newEdges.end(), myCurrEdge, itStart);
2139 if (!teleport) {
2140 newEdges.insert(newEdges.end(), toNewStop.begin(), toNewStop.end() - 1);
2141 } else {
2142 newEdges.push_back(*itStart);
2143 }
2144 if (!newDestination) {
2145 newEdges.insert(newEdges.end(), fromNewStop.begin(), fromNewStop.end() - 1);
2146 newEdges.insert(newEdges.end(), itEnd, oldEdges.end());
2147 } else {
2148 newEdges.push_back(stopEdge);
2149 }
2150 //std::cout << SIMTIME << " replaceStop veh=" << getID()
2151 // << " teleport=" << teleport
2152 // << " busStop=" << stop.busstop
2153 // << " oldEdges=" << oldRemainingEdges.size()
2154 // << " newEdges=" << newEdges.size()
2155 // << " toNewStop=" << toNewStop.size()
2156 // << " fromNewStop=" << fromNewStop.size()
2157 // << "\n";
2158
2159 const double routeCost = router.recomputeCosts(newEdges, this, t);
2160 const double previousCost = router.recomputeCosts(oldRemainingEdges, this, t);
2161 const double savings = previousCost - routeCost;
2162 if (!hasDeparted() && (int)myParameter->stops.size() > nextStopIndex) {
2163 // stops will be rebuilt from scratch so we must patch the stops in myParameter
2164 const_cast<SUMOVehicleParameter*>(myParameter)->stops[nextStopIndex] = stop;
2165 }
2166 if (teleport) {
2167 // let the vehicle jump rather than teleport
2168 // we add a jump-stop at the end of the edge (unless the vehicle is
2169 // already configure to jump before the replaced stop)
2170 if (!insertJump(nextStopIndex, itStart, errorMsg)) {
2171 return false;
2172 };
2173 }
2174 return replaceRouteEdges(newEdges, routeCost, savings, info, !hasDeparted(), false, false, &errorMsg);
2175}
2176
2177
2178bool
2179MSBaseVehicle::rerouteBetweenStops(int nextStopIndex, const std::string& info, bool teleport, std::string& errorMsg) {
2180 const int n = (int)myStops.size();
2181 if (nextStopIndex < 0 || nextStopIndex > n) {
2182 errorMsg = TLF("invalid nextStopIndex % for % remaining stops", nextStopIndex, n);
2183 return false;
2184 }
2185 if (nextStopIndex == 0 && isStopped()) {
2186 errorMsg = TL("cannot reroute towards reached stop");
2187 return false;
2188 }
2190
2191 const ConstMSEdgeVector& oldEdges = getRoute().getEdges();
2192 std::vector<MSStop> stops(myStops.begin(), myStops.end());
2193 const int junctionOffset = getLane() != nullptr && getLane()->isInternal() ? 1 : 0;
2194 MSRouteIterator itStart = nextStopIndex == 0 ? getCurrentRouteEdge() + junctionOffset : stops[nextStopIndex - 1].edge;
2195 double startPos = nextStopIndex == 0 ? getPositionOnLane() : stops[nextStopIndex - 1].pars.endPos;
2196 MSRouteIterator itEnd = nextStopIndex == n ? oldEdges.end() - 1 : stops[nextStopIndex].edge;
2197 auto endPos = nextStopIndex == n ? getArrivalPos() : stops[nextStopIndex].pars.endPos;
2199
2200 ConstMSEdgeVector newBetween;
2201 if (!teleport) {
2202 router.compute(*itStart, startPos, *itEnd, endPos, this, t, newBetween, true);
2203 if (newBetween.size() == 0) {
2204 errorMsg = TLF("no route found from edge '%' to stop edge '%'", (*itStart)->getID(), (*itEnd)->getID());
2205 return false;
2206 }
2207 }
2208
2209 ConstMSEdgeVector oldRemainingEdges(myCurrEdge, getRoute().end());
2210 ConstMSEdgeVector newEdges; // only remaining
2211 newEdges.insert(newEdges.end(), myCurrEdge, itStart);
2212 if (!teleport) {
2213 newEdges.insert(newEdges.end(), newBetween.begin(), newBetween.end() - 1);
2214 } else {
2215 newEdges.push_back(*itStart);
2216 }
2217 newEdges.insert(newEdges.end(), itEnd, oldEdges.end());
2218 //std::cout << SIMTIME << " rerouteBetweenStops veh=" << getID()
2219 // << " oldEdges=" << oldRemainingEdges.size()
2220 // << " newEdges=" << newEdges.size()
2221 // << " toNewStop=" << toNewStop.size()
2222 // << " fromNewStop=" << fromNewStop.size()
2223 // << "\n";
2224
2225 const double routeCost = router.recomputeCosts(newEdges, this, t);
2226 const double previousCost = router.recomputeCosts(oldRemainingEdges, this, t);
2227 const double savings = previousCost - routeCost;
2228
2229 if (teleport) {
2230 // let the vehicle jump rather than teleport
2231 // we add a jump-stop at the end of the edge (unless the vehicle is
2232 // already configure to jump before the replaced stop)
2233 if (!insertJump(nextStopIndex, itStart, errorMsg)) {
2234 return false;
2235 };
2236 }
2237 return replaceRouteEdges(newEdges, routeCost, savings, info, !hasDeparted(), false, false, &errorMsg);
2238}
2239
2240
2241bool
2242MSBaseVehicle::insertJump(int nextStopIndex, MSRouteIterator itStart, std::string& errorMsg) {
2243 bool needJump = true;
2244 if (nextStopIndex > 0) {
2245 auto itPriorStop = myStops.begin();
2246 std::advance(itPriorStop, nextStopIndex - 1);
2247 const MSStop& priorStop = *itPriorStop;
2248 if (priorStop.pars.jump >= 0) {
2249 needJump = false;
2250 }
2251 }
2252 if (needJump) {
2253 SUMOVehicleParameter::Stop jumpStopPars;
2254 jumpStopPars.endPos = (*itStart)->getLength();
2255 jumpStopPars.speed = 1000;
2256 jumpStopPars.jump = 0;
2257 jumpStopPars.edge = (*itStart)->getID();
2259 MSLane* jumpStopLane = nullptr;
2260 for (MSLane* cand : (*itStart)->getLanes()) {
2261 if (cand->allowsVehicleClass(getVClass())) {
2262 jumpStopLane = cand;
2263 break;
2264 }
2265 }
2266 if (jumpStopLane == nullptr) {
2267 errorMsg = TL("unable to replace stop with teleporting");
2268 return false;
2269 }
2270 auto itStop = myStops.begin();
2271 std::advance(itStop, nextStopIndex);
2272 MSStop jumpStop(jumpStopPars);
2273 jumpStop.initPars(jumpStopPars);
2274 jumpStop.lane = jumpStopLane;
2275 jumpStop.edge = myRoute->end(); // will be patched in replaceRoute
2276 myStops.insert(itStop, jumpStop);
2277 if (!hasDeparted() && (int)myParameter->stops.size() > nextStopIndex) {
2278 // stops will be rebuilt from scratch so we must patch the stops in myParameter
2279 auto it = myParameter->stops.begin() + nextStopIndex;
2280 const_cast<SUMOVehicleParameter*>(myParameter)->stops.insert(it, jumpStopPars);
2281 }
2282 }
2283 return true;
2284}
2285
2286
2287bool
2288MSBaseVehicle::insertStop(int nextStopIndex, SUMOVehicleParameter::Stop stop, const std::string& info, bool teleport, std::string& errorMsg) {
2289 const int n = (int)myStops.size();
2290 if (nextStopIndex < 0 || nextStopIndex > n) {
2291 errorMsg = TLF("invalid nextStopIndex % for % remaining stops", nextStopIndex, n);
2292 return false;
2293 }
2294 if (nextStopIndex == 0 && isStopped()) {
2295 errorMsg = TL("cannot insert stop before the currently reached stop");
2296 return false;
2297 }
2299 MSLane* stopLane = MSLane::dictionary(stop.lane);
2300 MSEdge* stopEdge = &stopLane->getEdge();
2301
2302 if (!stopLane->allowsVehicleClass(getVClass(), myRoutingMode)) {
2303 errorMsg = TLF("disallowed stop lane '%'", stopLane->getID());
2304 return false;
2305 }
2306
2307 // check parking access rights
2308 if (stop.parkingarea != "") {
2310 if (pa != nullptr && !pa->accepts(this)) {
2311 errorMsg = TLF("Vehicle '%' does not have the right badge to access parkingArea '%'.", getID(), stop.parkingarea);
2312 return false;
2313 }
2314 }
2315
2316 const ConstMSEdgeVector& oldEdges = getRoute().getEdges();
2317 std::vector<MSStop> stops(myStops.begin(), myStops.end());
2318 const int junctionOffset = ((getLane() != nullptr && getLane()->isInternal())
2319 || getRerouteOrigin() != getCurrentRouteEdge()) ? 1 : 0;
2320 MSRouteIterator itStart = nextStopIndex == 0 ? getCurrentRouteEdge() + junctionOffset : stops[nextStopIndex - 1].edge;
2321 double startPos = nextStopIndex == 0 ? getPositionOnLane() : stops[nextStopIndex - 1].pars.endPos;
2322 MSRouteIterator itEnd = nextStopIndex == n ? oldEdges.end() - 1 : stops[nextStopIndex].edge;
2323 auto endPos = nextStopIndex == n ? getArrivalPos() : stops[nextStopIndex].pars.endPos;
2325
2326 const bool newDestination = nextStopIndex == n && stopEdge == oldEdges.back();
2327 const bool needLoop = nextStopIndex > 0 && *itStart == stopEdge && startPos >= stop.endPos;
2328 if (needLoop && startPos == stop.endPos) {
2329 // assume that two stops at the same position indicate a looped route
2330 startPos += POSITION_EPS;
2331 stop.index = STOP_INDEX_REPEAT;
2332 } else if (!hasDeparted()) {
2333 stop.index = STOP_INDEX_END;
2334 }
2335
2336 MSRouteIterator itSentintel = itEnd + 1;
2337 MSRouteIterator onRouteStart = itStart + (needLoop ? 1 : 0);
2338 const bool onRoute = std::find(onRouteStart, itSentintel, stopEdge) != itSentintel;
2339 if (onRoute) {
2340 if (!hasDeparted() && (int)myParameter->stops.size() >= nextStopIndex) {
2341 // stops will be rebuilt from scratch so we must patch the stops in myParameter
2342 auto it = myParameter->stops.begin() + nextStopIndex;
2343 const_cast<SUMOVehicleParameter*>(myParameter)->stops.insert(it, stop);
2344 }
2345 const bool ok = addStop(stop, errorMsg, 0, &onRouteStart);
2346 if (ok) {
2347 updateBestLanes(true, !hasDeparted() ? (*myCurrEdge)->getLanes().front() : 0);
2348 }
2349 return ok;
2350 }
2351
2352 ConstMSEdgeVector toNewStop;
2353 if (!teleport) {
2354 router.compute(*itStart, startPos, stopEdge, stop.endPos, this, t, toNewStop, true);
2355 if (toNewStop.size() == 0) {
2356 errorMsg = TLF("no route found from edge '%' to stop edge '%'", (*itStart)->getID(), stopEdge->getID());
2357 return false;
2358 }
2359 }
2360
2361 ConstMSEdgeVector fromNewStop;
2362 if (!newDestination) {
2363 router.compute(stopEdge, stop.endPos, *itEnd, endPos, this, t, fromNewStop, true);
2364 if (fromNewStop.size() == 0) {
2365 errorMsg = TLF("no route found from stop edge '%' to edge '%'", stopEdge->getID(), (*itEnd)->getID());
2366 return false;
2367 }
2368 }
2369
2370 auto itStop = myStops.begin();
2371 std::advance(itStop, nextStopIndex);
2372 MSStop newStop(stop);
2373 newStop.initPars(stop);
2374 newStop.edge = myRoute->end(); // will be patched in replaceRoute
2375 newStop.lane = stopLane;
2377 newStop.segment = MSGlobals::gMesoNet->getSegmentForEdge(newStop.lane->getEdge(), newStop.getEndPos(*this));
2378 if (newStop.lane->isInternal()) {
2379 errorMsg = TLF("Mesoscopic simulation does not allow stopping on internal edge '%' for vehicle '%'.", stop.edge, getID());
2380 return false;
2381 }
2382 }
2383 myStops.insert(itStop, newStop);
2384
2385 ConstMSEdgeVector oldRemainingEdges(myCurrEdge, getRoute().end());
2386 ConstMSEdgeVector newEdges; // only remaining
2387 newEdges.insert(newEdges.end(), myCurrEdge, itStart);
2388 if (!teleport) {
2389 newEdges.insert(newEdges.end(), toNewStop.begin(), toNewStop.end() - 1);
2390 } else {
2391 newEdges.push_back(*itStart);
2392 }
2393 if (!newDestination) {
2394 newEdges.insert(newEdges.end(), fromNewStop.begin(), fromNewStop.end() - 1);
2395 newEdges.insert(newEdges.end(), itEnd, oldEdges.end());
2396 } else {
2397 newEdges.push_back(stopEdge);
2398 }
2399 //std::cout << SIMTIME << " insertStop veh=" << getID()
2400 // << " teleport=" << teleport
2401 // << " busStop=" << stop.busstop
2402 // << " oldEdges=" << oldRemainingEdges.size()
2403 // << " newEdges=" << newEdges.size()
2404 // << " toNewStop=" << toNewStop.size()
2405 // << " fromNewStop=" << fromNewStop.size()
2406 // << "\n";
2407
2408 const double routeCost = router.recomputeCosts(newEdges, this, t);
2409 const double previousCost = router.recomputeCosts(oldRemainingEdges, this, t);
2410 const double savings = previousCost - routeCost;
2411
2412 if (!hasDeparted() && (int)myParameter->stops.size() >= nextStopIndex) {
2413 // stops will be rebuilt from scratch so we must patch the stops in myParameter
2414 auto it = myParameter->stops.begin() + nextStopIndex;
2415 const_cast<SUMOVehicleParameter*>(myParameter)->stops.insert(it, stop);
2416 }
2417 return replaceRouteEdges(newEdges, routeCost, savings, info, !hasDeparted(), false, false, &errorMsg);
2418}
2419
2420
2423 if (myEnergyParams == nullptr) {
2425 double tMass = 0;
2426 if (myPersonDevice != nullptr) {
2428 tMass += t->getVehicleType().getMass();
2429 }
2430 }
2431 if (myContainerDevice != nullptr) {
2433 tMass += t->getVehicleType().getMass();
2434 }
2435 }
2437 }
2438 return myEnergyParams;
2439}
2440
2441
2442double
2444 if (static_cast<MSDevice_Battery*>(getDevice(typeid(MSDevice_Battery))) != 0) {
2445 MSDevice_Battery* batteryOfVehicle = dynamic_cast<MSDevice_Battery*>(getDevice(typeid(MSDevice_Battery)));
2446 return batteryOfVehicle->getActualBatteryCapacity();
2447 } else {
2448 if (static_cast<MSDevice_ElecHybrid*>(getDevice(typeid(MSDevice_ElecHybrid))) != 0) {
2449 MSDevice_ElecHybrid* batteryOfVehicle = dynamic_cast<MSDevice_ElecHybrid*>(getDevice(typeid(MSDevice_ElecHybrid)));
2450 return batteryOfVehicle->getActualBatteryCapacity();
2451 }
2452 }
2453 return -1;
2454}
2455
2456
2457double
2459 if (static_cast<MSDevice_Battery*>(getDevice(typeid(MSDevice_Battery))) != 0) {
2460 MSDevice_Battery* batteryOfVehicle = dynamic_cast<MSDevice_Battery*>(getDevice(typeid(MSDevice_Battery)));
2461 return batteryOfVehicle->getActualBatteryCapacity() / batteryOfVehicle->getMaximumBatteryCapacity();
2462 } else {
2463 if (static_cast<MSDevice_ElecHybrid*>(getDevice(typeid(MSDevice_ElecHybrid))) != 0) {
2464 MSDevice_ElecHybrid* batteryOfVehicle = dynamic_cast<MSDevice_ElecHybrid*>(getDevice(typeid(MSDevice_ElecHybrid)));
2465 return batteryOfVehicle->getActualBatteryCapacity() / batteryOfVehicle->getMaximumBatteryCapacity();
2466 }
2467 }
2468 return -1;
2469}
2470
2471
2472double
2474 if (static_cast<MSDevice_Battery*>(getDevice(typeid(MSDevice_Battery))) != 0) {
2475 MSDevice_Battery* batteryOfVehicle = dynamic_cast<MSDevice_Battery*>(getDevice(typeid(MSDevice_Battery)));
2476 return batteryOfVehicle->getEnergyCharged();
2477 } else {
2478 if (static_cast<MSDevice_ElecHybrid*>(getDevice(typeid(MSDevice_ElecHybrid))) != 0) {
2479 MSDevice_ElecHybrid* batteryOfVehicle = dynamic_cast<MSDevice_ElecHybrid*>(getDevice(typeid(MSDevice_ElecHybrid)));
2480 return batteryOfVehicle->getEnergyCharged();
2481 }
2482 }
2483 return -1;
2484}
2485
2486
2487double
2489 if (static_cast<MSDevice_Battery*>(getDevice(typeid(MSDevice_Battery))) != 0) {
2490 MSDevice_Battery* batteryOfVehicle = dynamic_cast<MSDevice_Battery*>(getDevice(typeid(MSDevice_Battery)));
2491 return batteryOfVehicle->getMaximumChargeRate();
2492 }
2493 return -1;
2494}
2495
2496
2497double
2499 if (static_cast<MSDevice_ElecHybrid*>(getDevice(typeid(MSDevice_ElecHybrid))) != 0) {
2500 MSDevice_ElecHybrid* elecHybridDevice = dynamic_cast<MSDevice_ElecHybrid*>(getDevice(typeid(MSDevice_ElecHybrid)));
2501 return elecHybridDevice->getCurrentFromOverheadWire();
2502 }
2503
2504 return NAN;
2505}
2506
2507double
2509 if (isOnRoad() || isIdling()) {
2511 } else {
2512 return 0.;
2513 }
2514}
2515
2516
2521
2522
2527
2528
2531 if (myEdgeWeights == nullptr) {
2533 }
2534 return *myEdgeWeights;
2535}
2536
2537
2538
2539
2540int
2542 int boarded = myPersonDevice == nullptr ? 0 : myPersonDevice->size();
2543 return boarded + myParameter->personNumber;
2544}
2545
2546int
2548 int leavingPersonNumber = 0;
2549 const std::vector<MSTransportable*>& persons = getPersons();
2550 for (std::vector<MSTransportable*>::const_iterator it_p = persons.begin(); it_p != persons.end(); ++it_p) {
2551 MSStageDriving* const stage = dynamic_cast<MSStageDriving*>((*it_p)->getCurrentStage());
2552 const MSStop* stop = &myStops.front();
2553 const MSVehicle* joinVeh = dynamic_cast<MSVehicle*>(MSNet::getInstance()->getVehicleControl().getVehicle((*stop).pars.join));
2554 if (stop && stage->canLeaveVehicle(*it_p, *this, *stop) && !MSDevice_Transportable::willTransferAtJoin(*it_p, joinVeh)) {
2555 leavingPersonNumber++;
2556 }
2557 }
2558 return leavingPersonNumber;
2559}
2560
2561std::vector<std::string>
2563 std::vector<std::string> ret;
2564 const std::vector<MSTransportable*>& persons = getPersons();
2565 for (std::vector<MSTransportable*>::const_iterator it_p = persons.begin(); it_p != persons.end(); ++it_p) {
2566 ret.push_back((*it_p)->getID());
2567 }
2568 return ret;
2569}
2570
2571int
2573 int loaded = myContainerDevice == nullptr ? 0 : myContainerDevice->size();
2574 return loaded + myParameter->containerNumber;
2575}
2576
2577
2578void
2580 // this might be called from the MSTransportable destructor so we cannot do a dynamic cast to determine the type
2581 if (myPersonDevice != nullptr) {
2583 }
2584 if (myContainerDevice != nullptr) {
2586 }
2587 if (myEnergyParams != nullptr) {
2589 }
2590}
2591
2592
2593void
2599
2600
2601const std::vector<MSTransportable*>&
2603 if (myPersonDevice == nullptr) {
2605 } else {
2607 }
2608}
2609
2610
2611const std::vector<MSTransportable*>&
2613 if (myContainerDevice == nullptr) {
2615 } else {
2617 }
2618}
2619
2620
2621bool
2622MSBaseVehicle::isLineStop(double position) const {
2623 if (myParameter->line == "") {
2624 // not a public transport line
2625 return false;
2626 }
2627 for (const SUMOVehicleParameter::Stop& stop : myParameter->stops) {
2628 if (stop.startPos <= position && position <= stop.endPos) {
2629 return true;
2630 }
2631 }
2632 for (const SUMOVehicleParameter::Stop& stop : myRoute->getStops()) {
2633 if (stop.startPos <= position && position <= stop.endPos) {
2634 return true;
2635 }
2636 }
2637 return false;
2638}
2639
2640
2641bool
2642MSBaseVehicle::hasDevice(const std::string& deviceName) const {
2643 for (MSDevice* const dev : myDevices) {
2644 if (dev->deviceName() == deviceName) {
2645 return true;
2646 }
2647 }
2648 return false;
2649}
2650
2651
2652void
2653MSBaseVehicle::createDevice(const std::string& deviceName) {
2654 if (!hasDevice(deviceName)) {
2655 if (deviceName == "rerouting") {
2656 ((SUMOVehicleParameter*)myParameter)->setParameter("has." + deviceName + ".device", "true");
2658 if (hasDeparted()) {
2659 // vehicle already departed: disable pre-insertion rerouting and enable regular routing behavior
2660 MSDevice_Routing* routingDevice = static_cast<MSDevice_Routing*>(getDevice(typeid(MSDevice_Routing)));
2661 assert(routingDevice != 0);
2663 }
2664 } else {
2665 throw InvalidArgument(TLF("creating device of type '%' is not supported", deviceName));
2666 }
2667 }
2668}
2669
2670
2671std::string
2672MSBaseVehicle::getDeviceParameter(const std::string& deviceName, const std::string& key) const {
2673 for (MSVehicleDevice* const dev : myDevices) {
2674 if (dev->deviceName() == deviceName) {
2675 return dev->getParameter(key);
2676 }
2677 }
2678 throw InvalidArgument(TLF("no device of type '%' exists", deviceName));
2679}
2680
2681
2682void
2683MSBaseVehicle::setDeviceParameter(const std::string& deviceName, const std::string& key, const std::string& value) {
2684 for (MSVehicleDevice* const dev : myDevices) {
2685 if (dev->deviceName() == deviceName) {
2686 dev->setParameter(key, value);
2687 return;
2688 }
2689 }
2690 throw InvalidArgument(TLF("no device of type '%' exists", deviceName));
2691}
2692
2693
2694void
2695MSBaseVehicle::setJunctionModelParameter(const std::string& key, const std::string& value) {
2698 const_cast<SUMOVehicleParameter&>(getParameter()).setParameter(key, value);
2699 // checked in MSLink::ignoreFoe
2700 } else {
2701 throw InvalidArgument(TLF("Vehicle '%' does not support junctionModel parameter '%'.", getID(), key));
2702 }
2703}
2704
2705
2706void
2707MSBaseVehicle::setCarFollowModelParameter(const std::string& key, const std::string& value) {
2708 // handle some generic params first and then delegate to the carFollowModel itself
2711 const_cast<SUMOVehicleParameter&>(getParameter()).setParameter(key, value);
2712 // checked in MSVehicle::planMove
2713 } else {
2714 MSVehicle* microVeh = dynamic_cast<MSVehicle*>(this);
2715 if (microVeh) {
2716 // remove 'carFollowModel.' prefix
2717 const std::string attrName = key.substr(15);
2718 microVeh->getCarFollowModel().setParameter(microVeh, attrName, value);
2719 }
2720 }
2721}
2722
2723
2724void
2726 /* Design idea for additional junction model parameters:
2727 We can distinguish between 3 levels of parameters
2728 1. typically shared by multiple vehicles -> vType parameter
2729 2. specific to one vehicle but stays constant throughout the simulation -> vehicle parameter
2730 3. specific to one vehicle and expected to change during simulation -> prefixed generic vehicle parameter
2731 */
2732 for (auto item : getParameter().getParametersMap()) {
2733 if (StringUtils::startsWith(item.first, "junctionModel.")) {
2734 setJunctionModelParameter(item.first, item.second);
2735 } else if (StringUtils::startsWith(item.first, "carFollowModel.")) {
2736 setCarFollowModelParameter(item.first, item.second);
2737 }
2738 }
2739 const std::string routingModeStr = getStringParam("device.rerouting.mode");
2740 try {
2741 int routingMode = StringUtils::toInt(routingModeStr);
2742 if (routingMode != libsumo::ROUTING_MODE_DEFAULT) {
2743 setRoutingMode(routingMode);
2745 // vehicles wishes to use traffic-dependent routing weights on triggere rerouting
2746 // (initWeightUpdate would be triggered anyway when equipped with device.rerouting)
2749 }
2750 }
2751 } catch (NumberFormatException&) {
2752 // @todo interpret symbolic constants
2753 throw ProcessError(TLF("could not interpret routing.mode '%'", routingModeStr));
2754 }
2755}
2756
2757
2766
2767
2768void
2770 assert(type != nullptr);
2771 // save old parameters before possible type deletion
2772 const double oldMu = myType->getSpeedFactor().getParameter(0);
2773 const double oldDev = myType->getSpeedFactor().getParameter(1);
2774 if (myType->isVehicleSpecific() && type != myType) {
2776 }
2777 // adapt myChosenSpeedFactor to the new type
2778 if (oldDev == 0.) {
2779 // old type had speedDev 0, reroll
2781 } else {
2782 // map old speedFactor onto new distribution
2783 const double distPoint = (myChosenSpeedFactor - oldMu) / oldDev;
2784 const double newMu = type->getSpeedFactor().getParameter(0);
2785 const double newDev = type->getSpeedFactor().getParameter(1);
2786 myChosenSpeedFactor = newMu + distPoint * newDev;
2787 // respect distribution limits
2790 }
2791 myType = type;
2792 if (myEnergyParams != nullptr) {
2794 }
2795}
2796
2797
2800 if (myType->isVehicleSpecific()) {
2801 return *const_cast<MSVehicleType*>(myType);
2802 }
2803 MSVehicleType* type = myType->buildSingularType(myType->getID() + "@" + getID());
2804 replaceVehicleType(type);
2805 return *type;
2806}
2807
2808
2809int
2811 const MSLane* const lane = getLane();
2812 if (lane == nullptr) {
2813 return getEdge()->getLanes()[0]->getRNGIndex();
2814 } else {
2815 return lane->getRNGIndex();
2816 }
2817}
2818
2819
2820SumoRNG*
2822 const MSLane* lane = getLane();
2823 if (lane == nullptr) {
2824 return getEdge()->getLanes()[0]->getRNG();
2825 } else {
2826 return lane->getRNG();
2827 }
2828}
2829
2830std::string
2831MSBaseVehicle::getPrefixedParameter(const std::string& key, std::string& error) const {
2832 const MSVehicle* microVeh = dynamic_cast<const MSVehicle*>(this);
2833 if (StringUtils::startsWith(key, "device.")) {
2834 StringTokenizer tok(key, ".");
2835 if (tok.size() < 3) {
2836 error = TLF("Invalid device parameter '%' for vehicle '%'.", key, getID());
2837 return "";
2838 }
2839 try {
2840 return getDeviceParameter(tok.get(1), key.substr(tok.get(0).size() + tok.get(1).size() + 2));
2841 } catch (InvalidArgument& e) {
2842 error = TLF("Vehicle '%' does not support device parameter '%' (%).", getID(), key, e.what());
2843 return "";
2844 }
2845 } else if (StringUtils::startsWith(key, "laneChangeModel.")) {
2846 if (microVeh == nullptr) {
2847 error = TLF("Mesoscopic vehicle '%' does not support laneChangeModel parameters.", getID());
2848 return "";
2849 }
2850 const std::string attrName = key.substr(16);
2851 try {
2852 return microVeh->getLaneChangeModel().getParameter(attrName);
2853 } catch (InvalidArgument& e) {
2854 error = TLF("Vehicle '%' does not support laneChangeModel parameter '%' (%).", getID(), key, e.what());
2855 return "";
2856 }
2857 } else if (StringUtils::startsWith(key, "carFollowModel.")) {
2858 if (microVeh == nullptr) {
2859 error = TLF("Mesoscopic vehicle '%' does not support carFollowModel parameters.", getID());
2860 return "";
2861 }
2862 const std::string attrName = key.substr(15);
2863 try {
2864 return microVeh->getCarFollowModel().getParameter(microVeh, attrName);
2865 } catch (InvalidArgument& e) {
2866 error = TLF("Vehicle '%' does not support carFollowModel parameter '%' (%).", getID(), key, e.what());
2867 return "";
2868 }
2869 } else if (StringUtils::startsWith(key, "has.") && StringUtils::endsWith(key, ".device")) {
2870 StringTokenizer tok(key, ".");
2871 if (tok.size() != 3) {
2872 error = TL("Invalid check for device. Expected format is 'has.DEVICENAME.device'.");
2873 return "";
2874 }
2875 return hasDevice(tok.get(1)) ? "true" : "false";
2876 // parking related parameters start here
2877 } else if (key == "parking.rerouteCount") {
2879 } else if (StringUtils::startsWith(key, "parking.memory.")) {
2880 std::vector<std::string> values;
2881 if (getParkingMemory()) {
2882 if (key == "parking.memory.IDList") {
2883 for (const auto& item : *getParkingMemory()) {
2884 values.push_back(item.first->getID());
2885 }
2886 } else if (key == "parking.memory.score") {
2887 for (const auto& item : *getParkingMemory()) {
2888 values.push_back(item.second.score);
2889 }
2890 } else if (key == "parking.memory.blockedAtTime") {
2891 for (const auto& item : *getParkingMemory()) {
2892 values.push_back(toString(STEPS2TIME(item.second.blockedAtTime)));
2893 }
2894 } else if (key == "parking.memory.blockedAtTimeLocal") {
2895 for (const auto& item : *getParkingMemory()) {
2896 values.push_back(toString(STEPS2TIME(item.second.blockedAtTimeLocal)));
2897 }
2898 } else {
2899 error = TLF("Unsupported parking parameter '%' for vehicle '%'.", key, getID());
2900 }
2901 }
2902 return toString(values);
2903 } else {
2904 // default: custom user parameter
2905 return getParameter().getParameter(key, "");
2906 }
2907}
2908
2909
2910void
2917
2918
2919void
2925
2926
2927void
2929 if (myChargingMemory == nullptr) {
2931 }
2933}
2934
2935
2936void
2942
2943
2944void
2945MSBaseVehicle::rememberParkingAreaScore(const MSStoppingPlace* pa, const std::string& score) {
2946 if (myParkingMemory == nullptr) {
2948 }
2950}
2951
2952
2955 if (myParkingMemory == nullptr) {
2956 return -1;
2957 }
2958 return myParkingMemory->sawBlockedStoppingPlace(pa, local);
2959}
2960
2961
2968
2969
2972 if (myChargingMemory == nullptr) {
2973 return -1;
2974 }
2975 return myChargingMemory->sawBlockedStoppingPlace(cs, local);
2976}
2977
2978
2979void
2981 if (hasStops() && myStops.front().parkingarea != nullptr && myStops.front().parkingarea->isReservable()) {
2982 myStops.front().parkingarea->removeSpaceReservation(this);
2983 }
2984}
2985
2986
2987#ifdef _DEBUG
2988void
2989MSBaseVehicle::initMoveReminderOutput(const OptionsCont& oc) {
2990 if (oc.isSet("movereminder-output.vehicles")) {
2991 const std::vector<std::string> vehicles = oc.getStringVector("movereminder-output.vehicles");
2992 myShallTraceMoveReminders.insert(vehicles.begin(), vehicles.end());
2993 }
2994}
2995
2996
2997void
2998MSBaseVehicle::traceMoveReminder(const std::string& type, MSMoveReminder* rem, double pos, bool keep) const {
2999 OutputDevice& od = OutputDevice::getDeviceByOption("movereminder-output");
3000 od.openTag("movereminder");
3001 od.writeAttr(SUMO_ATTR_TIME, STEPS2TIME(MSNet::getInstance()->getCurrentTimeStep()));
3002 od.writeAttr("veh", getID());
3004 od.writeAttr("type", type);
3005 od.writeAttr("pos", toString(pos));
3006 od.writeAttr("keep", toString(keep));
3007 od.closeTag();
3008}
3009#endif
3010
3011
3012/****************************************************************************/
long long int SUMOTime
Definition GUI.h:36
std::vector< const MSEdge * > ConstMSEdgeVector
Definition MSEdge.h:75
ConstMSEdgeVector::const_iterator MSRouteIterator
Definition MSRoute.h:57
#define WRITE_WARNINGF(...)
Definition MsgHandler.h:287
#define WRITE_ERRORF(...)
Definition MsgHandler.h:296
#define WRITE_WARNING(msg)
Definition MsgHandler.h:286
#define TL(string)
Definition MsgHandler.h:304
#define TLF(string,...)
Definition MsgHandler.h:306
std::shared_ptr< const MSRoute > ConstMSRoutePtr
Definition Route.h:32
std::string time2string(SUMOTime t, bool humanReadable)
convert SUMOTime to string (independently of global format setting)
Definition SUMOTime.cpp:107
#define STEPS2TIME(x)
Definition SUMOTime.h:58
#define SIMSTEP
Definition SUMOTime.h:69
constexpr SUMOTime TIME2STEPS(double x)
Definition SUMOTime.h:60
#define SUMOTime_MAX
Definition SUMOTime.h:34
#define SIMTIME
Definition SUMOTime.h:70
bool isRailway(SVCPermissions permissions)
Returns whether an edge with the given permissions is a (exclusive) railway edge.
@ RANDOM
The edge is chosen randomly.
@ GIVEN
The edge index is given.
@ DEFAULT
No information given; use default.
const int STOP_INDEX_END
const long long int VEHPARS_FORCE_REROUTE
DepartLaneDefinition
Possible ways to choose a lane on depart.
@ GIVEN
The speed is given.
@ GIVEN
The position is given.
@ DEFAULT
No information given; use default.
@ BASE
Back-at-zero position.
const int STOP_SPEED_SET
const long long int VEHPARS_CFMODEL_PARAMS_SET
@ RANDOM
The lane is chosen randomly.
@ GIVEN
The arrival lane is given.
@ FIRST_ALLOWED
The rightmost lane the vehicle may use.
std::vector< SUMOVehicleParameter::Stop > StopParVector
@ GIVEN
The speed is given.
const int STOP_INDEX_REPEAT
const long long int VEHPARS_PARKING_BADGES_SET
const int STOP_INDEX_FIT
const long long int VEHPARS_JUNCTIONMODEL_PARAMS_SET
const long long int VEHPARS_SPEEDFACTOR_SET
@ RANDOM
The arrival position is chosen randomly.
@ GIVEN
The arrival position is given.
@ CENTER
Half the road length.
const int STOP_JUMP_SET
const long long int VEHPARS_LINE_SET
const long long int VEHPARS_INSERTION_CHECKS_SET
@ CONTAINER_TRIGGERED
The departure is container triggered.
@ TRIGGERED
The departure is person triggered.
@ SUMO_TAG_CLOSING_REROUTE
reroute of type closing
@ SUMO_TAG_VEHICLE
description of a vehicle
@ SUMO_TAG_PARKING_AREA
A parking area.
@ SUMO_ATTR_CF_IGNORE_IDS
@ SUMO_ATTR_JM_IGNORE_IDS
@ SUMO_ATTR_JM_IGNORE_TYPES
@ SUMO_ATTR_LINE
@ SUMO_ATTR_REROUTE
@ SUMO_ATTR_DISTANCE
@ SUMO_ATTR_SPEEDFACTOR
@ SUMO_ATTR_ROUTE
@ SUMO_ATTR_ID
@ SUMO_ATTR_CF_IGNORE_TYPES
@ SUMO_ATTR_ARRIVALPOS_RANDOMIZED
@ SUMO_ATTR_TIME
trigger: the time of the step
double gWeightsRandomFactor
Definition StdDefs.cpp:35
int gPrecisionRandom
Definition StdDefs.cpp:30
const double INVALID_DOUBLE
invalid double
Definition StdDefs.h:68
T MIN2(T a, T b)
Definition StdDefs.h:80
const double SUMO_const_haltingSpeed
the speed threshold at which vehicles are considered as halting
Definition StdDefs.h:62
T MAX2(T a, T b)
Definition StdDefs.h:86
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition ToString.h:57
double getMax() const
Returns the maximum value of this distribution.
double getMin() const
Returns the minimum value of this distribution.
double getParameter(const int index) const
Returns the nth parameter of this distribution.
An upper class for objects with additional parameters.
double getTransportableMass() const
Returns the mass of all transportables in the vehicle.
void setSecondary(const EnergyParams *secondaryParams)
Set secondary params.
void setTransportableMass(const double mass)
Sets the mass of all transportables in the vehicle.
static double computeNoise(SUMOEmissionClass c, double v, double a)
Returns the noise produced by the a vehicle of the given type at the given speed.
MESegment * getSegmentForEdge(const MSEdge &e, double pos=0)
Get the segment for a given edge at a given position.
Definition MELoop.cpp:397
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 whether the vehicle has jump at the given part of its route
bool hasReminder(MSMoveReminder *rem) const
Checks whether the vehicle has the given MoveReminder.
static double addStopPriority(double p1, double p2)
std::list< MSStop > myStops
The vehicle's list of stops.
StoppingPlaceMemory * myParkingMemory
memory for parking search
double getImpatience() const
Returns this vehicles impatience.
void setSkips(MSStop &stop, int prevActiveStops)
patch stop.pars.index to record the number of skipped candidate edges before stop....
virtual ConstMSEdgeVector::const_iterator getRerouteOrigin() const
Returns the starting point for reroutes (usually the current edge)
const StoppingPlaceMemory * getParkingMemory() const
const std::vector< MSTransportable * > & getPersons() const
retrieve riding persons
virtual void initDevices()
void rememberParkingAreaScore(const MSStoppingPlace *pa, const std::string &score)
score only needed when running with gui
const long long int myRandomSeed
const MSEdge * succEdge(int nSuccs) const
Returns the nSuccs'th successor of edge the vehicle is currently at.
int getDepartEdge() const
Returns the edge on which this vehicle shall depart.
void resetRoutePosition(int index, DepartLaneDefinition departLaneProcedure)
reset index of edge within route
std::string getDeviceParameter(const std::string &deviceName, const std::string &key) const
try to retrieve the given parameter from any of the vehicles devices, raise InvalidArgument if no dev...
StoppingPlaceMemory * myChargingMemory
bool replaceStop(int nextStopIndex, SUMOVehicleParameter::Stop stop, const std::string &info, bool teleport, std::string &errorMsg)
int getLeavingPersonNumber() const
Returns the number of leaving persons.
MSBaseVehicle(SUMOVehicleParameter *pars, ConstMSRoutePtr route, MSVehicleType *type, const double speedFactor)
Constructor.
void calculateArrivalParams(bool onInit)
(Re-)Calculates the arrival position and lane from the vehicle parameters
virtual double getArrivalPos() const
Returns this vehicle's desired arrivalPos for its current route (may change on reroute)
void setCarFollowModelParameter(const std::string &key, const std::string &value)
set individual carFollow model parameters (not type related)
void setRoutingMode(int value)
Sets routing behavior.
void resetParkingAreaScores()
static NumericalID myCurrentNumericalIndex
bool rerouteBetweenStops(int nextStopIndex, const std::string &info, bool teleport, std::string &errorMsg)
MoveReminderCont myMoveReminders
Currently relevant move reminders.
void rememberChargingStationScore(const MSStoppingPlace *cs, const std::string &score)
int getInsertionChecks() const
double myDepartPos
The real depart position.
const SUMOVehicleParameter & getParameter() const
Returns the vehicle's parameter (including departure definition)
double getMaxChargeRate() const
Returns the maximum charge rate allowed by the battery in the current time step (W)
void replaceParameter(const SUMOVehicleParameter *newParameter)
replace the vehicle parameter (deleting the old one)
void rememberBlockedParkingArea(const MSStoppingPlace *pa, bool local)
int getNumberParkingReroutes() const
std::vector< MSVehicleDevice * > myDevices
The devices this vehicle has.
virtual const MSEdge * getCurrentEdge() const
Returns the edge the vehicle is currently at (possibly an internal edge)
double getPreviousSpeed() const
Returns the vehicle's previous speed.
void removeTransportableMass(MSTransportable *t)
removes a person or containers mass
MSStop & getNextStopMutable()
virtual void updateBestLanes(bool forceRebuild=false, const MSLane *startLane=0)
virtual void addTransportable(MSTransportable *transportable)
Adds a person or container to this vehicle.
virtual BaseInfluencer & getBaseInfluencer()=0
Returns the velocity/lane influencer.
const SUMOVehicleParameter::Stop * getNextStopParameter() const
return parameters for the next stop (SUMOVehicle Interface)
void rememberBlockedChargingStation(const MSStoppingPlace *cs, bool local)
virtual bool replaceRoute(ConstMSRoutePtr route, const std::string &info, bool onInit=false, int offset=0, bool addRouteStops=true, bool removeStops=true, std::string *msgReturn=nullptr)
Replaces the current route by the given one.
SUMOTime activateRemindersOnReroute(SUMOTime currentTime)
remove outdated driveways on reroute
int getNumRemainingEdges() const
return the number of edges remaining in the route (include the current)
double getOdometer() const
Returns the distance that was already driven by this vehicle.
bool isRail() const
virtual bool hasArrived() const
Returns whether this vehicle has already arrived (by default this is true if the vehicle has reached ...
const NumericalID myNumericalID
bool isStoppedInRange(const double pos, const double tolerance, bool checkFuture=false) const
return whether the given position is within range of the current stop
bool isJumping() const
Returns whether the vehicle is perform a jump.
void checkRouteRemoval()
remove route at the end of the simulation
MSVehicleType & getSingularType()
Replaces the current vehicle type with a new one used by this vehicle only.
const MSVehicleType * myType
This vehicle's type.
const MSRouteIterator & getCurrentRouteEdge() const
Returns an iterator pointing to the current edge in this vehicles route.
bool isStoppedParking() const
Returns whether the vehicle is on a parking stop.
void unregisterWaiting()
mark vehicle as active
bool hasValidRoute(std::string &msg, ConstMSRoutePtr route=0) const
Validates the current or given route.
void cleanupParkingReservation()
unregisters from a parking reservation when changing or skipping stops
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 parameter (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
StopParVector myPastStops
The list of stops that the vehicle has already reached.
static std::vector< MSTransportable * > myEmptyTransportableVector
const std::vector< std::string > & getParkingBadges() const
get the valid parking access rights (vehicle settings override vehicle type settings)
bool hasDeparted() const
Returns whether this vehicle has already departed.
bool ignoreTransientPermissions() const
Returns whether this object is ignoring transient permission changes (during routing)
virtual void resetApproachOnReroute()
reset rail signal approach information
ConstMSRoutePtr myRoute
This vehicle's route.
MSDevice_Transportable * myContainerDevice
The containers this vehicle may have.
void resetChargingStationScores()
bool allowsBoarding(const MSTransportable *t) const
whether the given transportable is allowed to board this vehicle
double getStateOfCharge() const
Returns actual state of charge of battery (Wh) RICE_CHECK: This may be a misnomer,...
MSEdgeWeightsStorage & _getWeightsStorage() const
virtual bool handleCollisionStop(MSStop &stop, const double distToStop)
bool hasDevice(const std::string &deviceName) const
check whether the vehicle is equipped with a device of the given name
void addReminder(MSMoveReminder *rem, double pos=0)
Adds a MoveReminder dynamically.
SumoRNG * getRNG() const
SUMOTime getDeparture() const
Returns this vehicle's real departure time.
SUMOTime sawBlockedChargingStation(const MSStoppingPlace *cs, bool local) const
EnergyParams * getEmissionParameters() const
retrieve parameters for the energy consumption model
double basePos(const MSEdge *edge) const
departure position where the vehicle fits fully onto the edge (if possible)
void setDeviceParameter(const std::string &deviceName, const std::string &key, const std::string &value)
try to set the given parameter from any of the vehicles devices, raise InvalidArgument if no device p...
MSDevice_Transportable * myPersonDevice
The passengers this vehicle may have.
bool hasStops() const
Returns whether the vehicle has to stop somewhere.
std::string getFlowID() const
reconstruct flow id from vehicle id
virtual void activateReminders(const MSMoveReminder::Notification reason, const MSLane *enteredLane=0)
"Activates" all current move reminder
bool isLineStop(double position) const
returns whether the vehicle serves a public transport line that serves the given stop
double myChosenSpeedFactor
A precomputed factor by which the driver wants to be faster than the speed limit.
const MSStop & getNextStop() const
@ ROUTE_INVALID
route was checked and is valid
@ ROUTE_START_INVALID_PERMISSIONS
std::string getPrefixedParameter(const std::string &key, std::string &error) const
retrieve parameters of devices, models and the vehicle itself
bool replaceWithAlternative(std::list< MSStop >::iterator iter, const MSRouteIterator searchStart, const MSRouteIterator end)
replace stop with a same-name alternative that is on the route and return success
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)
virtual bool instantStopping() const
whether instant stopping is permitted
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
void initTransportableDevice(bool isPerson)
init device during state loading
bool stopsAtEdge(const MSEdge *edge) const
Returns whether the vehicle stops at the given edge.
bool addStop(const SUMOVehicleParameter::Stop &stopPar, std::string &errorMsg, SUMOTime untilOffset=0, MSRouteIterator *searchStart=nullptr)
Adds a stop.
double getChargedEnergy() const
Returns the energy charged to the battery in the current time step (Wh)
void onDepart()
Called when the vehicle is inserted into the network.
void removeReminder(MSMoveReminder *rem)
Removes a MoveReminder dynamically.
SUMOTime getStopDuration() const
get remaining stop duration or 0 if the vehicle isn't stopped
virtual double getAcceleration() const
Returns the vehicle's acceleration.
virtual bool addTraciStop(SUMOVehicleParameter::Stop stop, std::string &errorMsg)
const MSRoute & getRoute() const
Returns the current route.
int getRoutingMode() const
return routing mode (configures router choice but also handling of transient permission changes)
int getRoutePosition() const
return index of edge within route
bool replaceParkingArea(MSParkingArea *parkingArea, std::string &errorMsg)
replace the current parking area stop with a new stop with merge duration
static const SUMOTime NOT_YET_DEPARTED
SUMOTime getDepartDelay() const
Returns the depart delay.
double getElecHybridCurrent() const
Returns actual current (A) of ElecHybrid device RICE_CHECK: Is this the current consumed from the ove...
bool myAmRegisteredAsWaiting
Whether this vehicle is registered as waiting for a person or container (for deadlock-recognition)
SUMOAbstractRouter< MSEdge, SUMOVehicle > & getRouterTT() const
returns the router according to the current routing mode of the vehicle
EnergyParams * myEnergyParams
The emission parameters this vehicle may have.
const SUMOVehicleParameter * myParameter
This vehicle's parameter.
virtual bool hasValidRouteStart(std::string &msg)
checks whether the vehicle can depart on the first edge
int myRouteValidity
status of the current vehicle route
std::vector< std::pair< int, double > > getStopIndices() const
return list of route indices for the remaining stops
SUMOTime myStopUntilOffset
The offset when adding route stops with 'until' on route replacement.
virtual bool isOnRoad() const
Returns the information whether the vehicle is on a road (is simulated)
const std::vector< MSTransportable * > & getContainers() const
retrieve riding containers
bool reroute(SUMOTime t, const std::string &info, SUMOAbstractRouter< MSEdge, SUMOVehicle > &router, const bool onInit=false, const bool withTaz=false, const bool silent=false, const MSEdge *sink=nullptr)
Performs a rerouting using the given router.
bool stopsAt(MSStoppingPlace *stop) const
Returns whether the vehicle stops at the given stopping place.
int getRNGIndex() const
MSEdgeWeightsStorage * myEdgeWeights
const MSVehicleType & getVehicleType() const
Returns the vehicle's type definition.
void createDevice(const std::string &deviceName)
create device of the given type
bool isStopped() const
Returns whether the vehicle is at a stop.
MSDevice * getDevice(const std::type_info &type) const
Returns a device of the given type if it exists, nullptr otherwise.
bool abortNextStop(int nextStopIndex=0)
deletes the next stop at the given index if it exists
int myNumberReroutes
The number of reroutings.
double myArrivalPos
The position on the destination lane where the vehicle stops.
bool insertJump(int nextStopIndex, MSRouteIterator itStart, std::string &errorMsg)
helper function
virtual void saveState(OutputDevice &out)
Saves the (common) state of a vehicle.
virtual void replaceVehicleType(const MSVehicleType *type)
Replaces the current vehicle type by the one given.
std::vector< StopEdgeInfo > getStopEdges(double &firstPos, double &lastPos, std::set< int > &jumps) const
Returns the list of still pending stop edges also returns the first and last stop position.
double myOdometer
A simple odometer to keep track of the length of the route already driven.
void initTransientModelParams()
init model parameters from generic params
int getContainerNumber() const
Returns the number of containers.
bool replaceRouteEdges(ConstMSEdgeVector &edges, double cost, double savings, const std::string &info, bool onInit=false, bool check=false, bool removeStops=true, std::string *msgReturn=nullptr)
Replaces the current route by the given edges.
virtual std::string getParameter(const MSVehicle *veh, const std::string &key) const
try to get the given parameter for this carFollowingModel
Definition MSCFModel.h:707
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:720
Battery device for electric vehicles.
double getActualBatteryCapacity() const
Get the actual vehicle's Battery Capacity in Wh.
double getMaximumChargeRate() const
Get current charge rate in W depending on the state of charge.
double getMaximumBatteryCapacity() const
Get the total vehicle's Battery Capacity in Wh.
double getEnergyCharged() const
Get charged energy.
A device which collects info on the vehicle trip (mainly on departure and arrival)
double getMaximumBatteryCapacity() const
Get the total vehicle's Battery Capacity in kWh.
double getCurrentFromOverheadWire() const
Get actual current in the overhead wire segment.
double getEnergyCharged() const
Get charged energy.
double getActualBatteryCapacity() const
Get the actual vehicle's Battery Capacity in kWh.
A device that performs vehicle rerouting based on current edge speeds.
bool sufficientSaving(double oldCost, double newCost)
whether the change in saving is enough to trigger rerouting
bool notifyEnter(SUMOTrafficObject &veh, MSMoveReminder::Notification reason, const MSLane *enteredLane=0)
Computes a new route on vehicle insertion.
static void buildVehicleDevices(SUMOVehicle &v, std::vector< MSVehicleDevice * > &into)
Build devices for the given vehicle, if needed.
A device which collects info on the vehicle trip (mainly on departure and arrival)
bool allowsBoarding(const MSTransportable *t) const
whether the given person is allowed to board this taxi
const std::vector< MSTransportable * > & getTransportables() const
Returns the list of transportables using this vehicle.
static bool willTransferAtJoin(const MSTransportable *t, const MSBaseVehicle *joinVeh)
check if boardingDuration should be applied
static MSDevice_Transportable * buildVehicleDevices(SUMOVehicle &v, std::vector< MSVehicleDevice * > &into, const bool isContainer)
Build devices for the given vehicle, if needed.
int size() const
Return the number of passengers / containers.
void addTransportable(MSTransportable *transportable)
Add a passenger.
void removeTransportable(MSTransportable *transportable)
Remove a passenger (TraCI)
Abstract in-vehicle / in-person device.
Definition MSDevice.h:62
static void buildVehicleDevices(SUMOVehicle &v, std::vector< MSVehicleDevice * > &into)
Build devices for the given vehicle, if needed.
Definition MSDevice.cpp:115
A road/street connecting two junctions.
Definition MSEdge.h:78
static void clear()
Clears the dictionary.
Definition MSEdge.cpp:1163
bool hasTransientPermissions() const
Definition MSEdge.cpp:1754
const std::vector< MSLane * > & getLanes() const
Returns this edge's lanes.
Definition MSEdge.h:169
const MSEdge * getOppositeEdge() const
Returns the opposite direction edge if on exists else a nullptr.
Definition MSEdge.cpp:1423
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:516
bool isNormal() const
return whether this edge is an internal edge
Definition MSEdge.h:265
bool isTazConnector() const
Definition MSEdge.h:293
int getNumLanes() const
Definition MSEdge.h:173
bool isInternal() const
return whether this edge is an internal edge
Definition MSEdge.h:270
bool prohibits(const SUMOVehicle *const vehicle) const
Returns whether the vehicle (class) is not allowed on the edge.
Definition MSEdge.h:637
double getMinLength() const
return the minimum length of all lanes (only differs from getLength for curved internal lanes)
Definition MSEdge.cpp:1838
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:1117
const MSEdge * getNormalBefore() const
if this edge is an internal edge, return its first normal predecessor, otherwise the edge itself
Definition MSEdge.cpp:1007
MSLane * getFirstAllowed(SUMOVehicleClass vClass, bool defaultFirst=false, int routingMode=0) const
Definition MSEdge.cpp:791
A storage for edge travel times and efforts.
virtual void addEvent(Command *operation, SUMOTime execTimeStep=-1)
Adds an Event.
static bool gUseMesoSim
Definition MSGlobals.h:106
static bool gCheckRoutes
Definition MSGlobals.h:91
static MELoop * gMesoNet
mesoscopic simulation infrastructure
Definition MSGlobals.h:115
static int gInsertionChecks
The default value for insertion checks.
Definition MSGlobals.h:189
static SUMOTime gTimeToImpatience
Definition MSGlobals.h:78
static bool gHaveEmissions
Whether emission output of some type is needed (files or GUI)
Definition MSGlobals.h:186
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:2514
double getLength() const
Returns the lane's length.
Definition MSLane.h:632
bool allowsVehicleClass(SUMOVehicleClass vclass) const
Definition MSLane.h:959
static bool dictionary(const std::string &id, MSLane *lane)
Static (sic!) container methods {.
Definition MSLane.cpp:2538
bool isInternal() const
Definition MSLane.cpp:2669
SumoRNG * getRNG() const
return the associated RNG
Definition MSLane.h:246
MSEdge & getEdge() const
Returns the lane's edge.
Definition MSLane.h:790
Something on a lane to be noticed about vehicle movement.
virtual bool notifyEnter(SUMOTrafficObject &veh, Notification reason, const MSLane *enteredLane)
Checks whether the reminder is activated by a vehicle entering the lane.
const std::string & getDescription() const
Notification
Definition of a vehicle state.
@ NOTIFICATION_DEPARTED
The vehicle has departed (was inserted into the network)
const MSLane * getLane() const
Returns the lane the reminder works on.
@ NEWROUTE
The vehicle got a new route.
static MSNet * getInstance()
Returns the pointer to the unique instance of MSNet (singleton).
Definition MSNet.cpp:201
MSEventControl * getBeginOfTimestepEvents()
Returns the event control for events executed at the begin of a time step.
Definition MSNet.h:495
const std::vector< MSStoppingPlace * > & getStoppingPlaceAlternatives(const std::string &name, SumoXMLTag category) const
Definition MSNet.cpp:1562
MSVehicleRouter & getRouterTT(int rngIndex, const Prohibitions &prohibited={}) const
Definition MSNet.cpp:1659
SUMOTime getCurrentTimeStep() const
Returns the current simulation step.
Definition MSNet.h:334
static bool hasInstance()
Returns whether the network was already constructed.
Definition MSNet.h:158
MSStoppingPlace * getStoppingPlace(const std::string &id, const SumoXMLTag category) const
Returns the named stopping place of the given category.
Definition MSNet.cpp:1527
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:1402
MSInsertionControl & getInsertionControl()
Returns the insertion control.
Definition MSNet.h:455
MSVehicleControl & getVehicleControl()
Returns the vehicle control.
Definition MSNet.h:402
A lane area vehicles can halt at.
bool accepts(SUMOVehicle *veh) const override
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:128
void setCosts(double costs)
Sets the costs of the route.
Definition MSRoute.h:209
static bool hasRoute(const std::string &id)
returns whether a route with the given id exists
Definition MSRoute.cpp:159
static bool dictionary(const std::string &id, ConstMSRoutePtr route)
Adds a route to the dictionary.
Definition MSRoute.cpp:116
static void checkDist(const std::string &id)
Checks the distribution whether it is permanent and deletes it if not.
Definition MSRoute.cpp:194
void setSavings(double savings)
Sets the savings of the route.
Definition MSRoute.h:216
static void initEdgeWeights(SUMOVehicleClass svc, SUMOTime lastAdaption=-1, int index=-1)
initialize the edge weights if not done before
static void initWeightUpdate(SUMOTime lastAdaption=- 1)
intialize period edge weight update
static MSVehicleRouter & getRouterTT(const int rngIndex, SUMOVehicleClass svc, const Prohibitions &prohibited={})
return the vehicle router instance
bool canLeaveVehicle(const MSTransportable *t, const SUMOVehicle &veh, const MSStop &stop)
checks whether the person may exit at the current vehicle position
const MSLane * lane
The lane to stop at (microsim only)
Definition MSStop.h:50
MSStoppingPlace * containerstop
(Optional) container stop if one is assigned to the stop
Definition MSStop.h:56
std::string getDescription(bool nameOnly=false) const
get a short description for showing in the gui
Definition MSStop.cpp:72
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:151
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
std::vector< int > skips
route indices on looped route that were skipped before this stop (after pior stop or depart edge)
Definition MSStop.h:95
double getEndPos(const SUMOVehicle &veh) const
return halting position for upcoming stop;
Definition MSStop.cpp:38
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
SUMOTime getUntil() const
return until / ended time
Definition MSStop.cpp:190
SUMOTime getArrival() const
return arrival / started time
Definition MSStop.cpp:196
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
Finds a sequence of skips and stop alternatives to maximize priority of reached stops.
ConstMSEdgeVector optimizeSkipped(const MSEdge *source, double sourcePos, std::vector< StopEdgeInfo > &stops, ConstMSEdgeVector edges) const
A lane area vehicles can halt at.
double getBeginLanePosition() const
Returns the begin position of this stop.
double getParkingLength() const
SumoXMLTag getElement() const
return the type of this stopping place
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 override
Whether it is a person.
const MSVehicleType & getVehicleType() const override
Returns the object's "vehicle" type.
static const double DEFAULT_MAXDELAY
void vehicleDeparted(const SUMOVehicle &v)
Informs this control about a vehicle's departure.
SUMOVehicle * getVehicle(const std::string &id) const
Returns the vehicle with the given id.
void removeVType(const MSVehicleType *vehType)
void unregisterOneWaiting()
decreases the count of vehicles waiting for a transport to allow recognition of person / container re...
Abstract in-vehicle device.
Representation of a vehicle in the micro simulation.
Definition MSVehicle.h:77
MSAbstractLaneChangeModel & getLaneChangeModel()
const MSCFModel & getCarFollowModel() const
Returns the vehicle's car following model definition.
Definition MSVehicle.h:973
The car-following model and parameter.
const EnergyParams * getEmissionParameters() const
retrieve parameters for the energy consumption model
SUMOVehicleClass getVehicleClass() const
Get this vehicle type's vehicle class.
double getMaxSpeed() const
Get vehicle's (technical) maximum speed [m/s].
double getDesiredMaxSpeed() const
Returns the vehicles's desired maximum speed.
const std::string & getID() const
Returns the name of the vehicle type.
const Distribution_Parameterized & getSpeedFactor() const
Returns this type's speed factor.
bool isVehicleSpecific() const
Returns whether this type belongs to a single vehicle only (was modified)
SUMOEmissionClass getEmissionClass() const
Get this vehicle type's emission class.
double getLength() const
Get vehicle's length [m].
double getMass() const
Get this vehicle type's mass.
double computeChosenSpeedDeviation(double speedFactorOverride, 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:66
const std::string & getID() const
Returns the id.
Definition Named.h:73
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 & openTag(const std::string &xmlElement)
Opens an XML tag.
OutputDevice & writeAttr(const ATTR_TYPE &attr, const T &val, const bool isNull=false, const bool escape=false)
writes a named attribute
static OutputDevice & getDeviceByOption(const std::string &name)
Returns the device described by the option.
int getPrecision()
Returns the precision of the underlying stream.
bool closeTag(const std::string &comment="")
Closes the most recently opened tag and optionally adds a comment.
void setPrecision(int precision=gPrecision)
Sets the precision or resets it to default.
virtual const std::string getParameter(const std::string &key, const std::string defaultValue="") const
Returns the value for a given key.
const Parameterised::Map & getParametersMap() const
Returns the inner key/value map.
static const RGBColor DEFAULT_COLOR
The default color (for vehicle types and vehicles)
Definition RGBColor.h:218
Utility functions for using a global, resetable random number generator.
Definition RandHelper.h:133
static double rand(SumoRNG *rng=nullptr)
Returns a random real number in [0, 1)
virtual bool compute(const E *from, const E *to, const V *const vehicle, SUMOTime msTime, std::vector< const E * > &into, bool silent=false)=0
Builds the route between the given edges using the minimum effort at the given time The definition of...
virtual double recomputeCosts(const std::vector< const E * > &edges, const V *const v, SUMOTime msTime, double *lengthp=nullptr) const
double recomputeCostsPos(const std::vector< const E * > &edges, const V *const v, double fromPos, double toPos, SUMOTime msTime, double *lengthp=nullptr) const
std::string getStringParam(const std::string &paramName, const bool required=false, const std::string &deflt="") const
Retrieve a string parameter for the traffic object.
virtual const MSLane * getLane() const =0
Returns the lane the object is currently at.
long long int NumericalID
virtual double getSpeed() const =0
Returns the object's current speed.
virtual SUMOTime getWaitingTime(const bool accumulated=false) const =0
virtual bool isPerson() const
Whether it is a person.
double getFloatParam(const std::string &paramName, const bool required=false, const double deflt=INVALID_DOUBLE, bool checkDist=true) const
Retrieve a floating point parameter for the traffic object.
virtual double getPositionOnLane() const =0
Get the object's position along the lane.
Representation of a vehicle.
Definition SUMOVehicle.h:63
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.
long long int repetitionsDone
The number of times the vehicle was already inserted.
std::vector< std::string > via
List of the via-edges the vehicle must visit.
ArrivalLaneDefinition arrivalLaneProcedure
Information how the vehicle shall choose the lane to arrive on.
long long int parametersSet
Information for the router which parameter were set, TraCI may modify this (when changing color)
void write(OutputDevice &dev, const OptionsCont &oc, const SumoXMLTag altTag=SUMO_TAG_VEHICLE, const std::string &typeID="") const
Writes the parameters as a beginning element.
int personNumber
The static number of persons in the vehicle when it departs (not including boarding persons)
RouteIndexDefinition arrivalEdgeProcedure
Information how the vehicle's final edge shall be chosen.
bool wasSet(long long int what) const
Returns whether the given parameter was set.
double departPos
(optional) The position the vehicle shall depart from
DepartSpeedDefinition departSpeedProcedure
Information how the vehicle's initial speed shall be chosen.
double arrivalPos
(optional) The position the vehicle shall arrive on
std::string routeid
The vehicle's route id.
std::string id
The vehicle's id.
std::vector< std::string > parkingBadges
The parking access rights.
std::vector< Stop > stops
List of the stops the vehicle will make, TraCI may add entries here.
int departEdge
(optional) The initial edge within the route of the vehicle
ArrivalPosDefinition arrivalPosProcedure
Information how the vehicle shall choose the arrival position.
std::string toTaz
The vehicle's destination zone (district)
double arrivalSpeed
(optional) The final speed of the vehicle (not used yet)
DepartDefinition departProcedure
Information how the vehicle shall choose the depart time.
int insertionChecks
bitset of InsertionCheck
int arrivalEdge
(optional) The final edge within the route of the vehicle
std::string fromTaz
The vehicle's origin zone (district)
DepartPosDefinition departPosProcedure
Information how the vehicle shall choose the departure position.
std::string line
The vehicle's line (mainly for public transport)
int containerNumber
The static number of containers in the vehicle when it departs.
RouteIndexDefinition departEdgeProcedure
Information how the vehicle's initial edge shall be chosen.
static std::string getEdgeIDFromLane(const std::string laneID)
return edge id when given the lane ID
static int getIndexFromLane(const std::string laneID)
return lane index when given the lane ID
SUMOTime sawBlockedStoppingPlace(const MSStoppingPlace *stoppingPlace, bool local) const
Get the time the StoppingPlace was confirmed to be blocked.
void rememberStoppingPlaceScore(const MSStoppingPlace *stoppingPlace, const std::string &score)
score only needed when running with gui
void rememberBlockedStoppingPlace(const MSStoppingPlace *stoppingPlace, bool local)
Store the time the StoppingPlace was confirmed to be blocked.
int size() const
returns the number of existing substrings
std::string get(int pos) const
returns the item at the given position
static bool startsWith(const std::string &str, const std::string prefix)
Checks whether a given string starts with the prefix.
static bool endsWith(const std::string &str, const std::string suffix)
Checks whether a given string ends with the suffix.
static int toInt(const std::string &sData)
converts a string into the integer value described by it by calling the char-type converter,...
A wrapper for a Command function.
#define UNUSED_PARAMETER(x)
#define DEBUG_COND
TRACI_CONST int ROUTING_MODE_AGGREGATED
TRACI_CONST int ROUTING_MODE_DEFAULT
TRACI_CONST int ROUTING_MODE_AGGREGATED_CUSTOM
TRACI_CONST int ROUTING_MODE_IGNORE_TRANSIENT_PERMISSIONS