Eclipse SUMO - Simulation of Urban MObility
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
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-2025 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 "MSBaseVehicle.h"
66
67//#define DEBUG_REROUTE
68//#define DEBUG_ADD_STOP
69//#define DEBUG_COND (getID() == "")
70//#define DEBUG_COND (true)
71//#define DEBUG_REPLACE_ROUTE
72//#define DEBUG_OPTIMIZE_SKIPPED
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 myEdgeWeights(nullptr)
125#ifdef _DEBUG
126 , myTraceMoveReminders(myShallTraceMoveReminders.count(pars->id) > 0)
127#endif
128{
129 if ((*myRoute->begin())->isTazConnector() || myRoute->getLastEdge()->isTazConnector()) {
131 }
132 if ((pars->parametersSet & VEHPARS_FORCE_REROUTE) == 0) {
134 }
135 if (!pars->wasSet(VEHPARS_FORCE_REROUTE)) {
137 }
139}
140
141
143 delete myEdgeWeights;
144 if (myParameter->repetitionNumber == -1) {
145 // this is not a flow (flows call checkDist in MSInsertionControl::determineCandidates)
147 }
148 for (MSVehicleDevice* dev : myDevices) {
149 delete dev;
150 }
151 delete myEnergyParams;
152 delete myParkingMemory;
153 delete myChargingMemory;
155 delete myParameter;
156}
157
158
159void
161 // the check for an instance is needed for the unit tests which do not construct a network
162 // TODO Optimize for speed and there should be a better way to check whether a vehicle is part of a flow
163 if (MSNet::hasInstance() && !MSNet::getInstance()->hasFlow(getFlowID())) {
164 myRoute->checkRemoval();
165 }
166}
167
168
169std::string
171 return getID().substr(0, getID().rfind('.'));
172}
173
174
175void
178 for (MSVehicleDevice* dev : myDevices) {
179 myMoveReminders.push_back(std::make_pair(dev, 0.));
180 }
182 // ensure we have the emission parameters even if we don't have the device
184 }
185}
186
187
188void
189MSBaseVehicle::setID(const std::string& /*newID*/) {
190 throw ProcessError(TL("Changing a vehicle ID is not permitted"));
191}
192
195 return *myParameter;
196}
197
198
199void
201 delete myParameter;
202 myParameter = newParameter;
203}
204
205
206bool
210
211double
215
216
217const MSEdge*
218MSBaseVehicle::succEdge(int nSuccs) const {
219 if (myCurrEdge + nSuccs < myRoute->end() && std::distance(myCurrEdge, myRoute->begin()) <= nSuccs) {
220 return *(myCurrEdge + nSuccs);
221 } else {
222 return nullptr;
223 }
224}
225
226
227const MSEdge*
229 return *myCurrEdge;
230}
231
232
233const std::set<SUMOTrafficObject::NumericalID>
235 std::set<SUMOTrafficObject::NumericalID> result;
236 for (auto e = myCurrEdge; e != myRoute->end(); ++e) {
237 result.insert((*e)->getNumericalID());
238 }
239 return result;
240}
241
242
243bool
245 if (stop == nullptr) {
246 return false;
247 }
248 for (const MSStop& s : myStops) {
249 if (s.busstop == stop
250 || s.containerstop == stop
251 || s.parkingarea == stop
252 || s.chargingStation == stop) {
253 return true;
254 }
255 }
256 return false;
257}
258
259bool
261 for (const MSStop& s : myStops) {
262 if (&s.lane->getEdge() == edge) {
263 return true;
264 }
265 }
266 return myRoute->getLastEdge() == edge;
267}
268
269
270bool
271MSBaseVehicle::reroute(SUMOTime t, const std::string& info, SUMOAbstractRouter<MSEdge, SUMOVehicle>& router, const bool onInit, const bool withTaz, const bool silent, const MSEdge* sink) {
272 // check whether to reroute
273 const MSEdge* source = withTaz && onInit ? MSEdge::dictionary(myParameter->fromTaz + "-source") : *getRerouteOrigin();
274 if (source == nullptr) {
275 source = *getRerouteOrigin();
276 }
277 if (sink == nullptr) {
278 sink = withTaz ? MSEdge::dictionary(myParameter->toTaz + "-sink") : myRoute->getLastEdge();
279 if (sink == nullptr) {
280 sink = myRoute->getLastEdge();
281 }
282 }
283 ConstMSEdgeVector oldEdgesRemaining(source == *myCurrEdge ? myCurrEdge : myCurrEdge + 1, myRoute->end());
284 ConstMSEdgeVector edges;
285 std::vector<StopEdgeInfo> stops;
286 std::set<int> jumps;
287 double sinkPriority = -1;
288 bool stopAtSink = false;
289 double sourcePos = onInit ? 0 : getPositionOnLane();
290 if (myParameter->via.size() == 0) {
291 double firstPos = INVALID_DOUBLE;
292 double lastPos = INVALID_DOUBLE;
293 stops = getStopEdges(firstPos, lastPos, jumps);
294 if (stops.size() > 0) {
296 sourcePos = getNextStop().pars.endPos;
297 }
298 // avoid superfluous waypoints for first and last edge
299 const bool skipFirst = stops.front().edge == source && (source != getEdge() || sourcePos + getBrakeGap() <= firstPos + NUMERICAL_EPS);
300 const bool skipLast = (stops.back().edge == sink
301 && myArrivalPos >= lastPos
302 && (stops.size() < 2 || stops.back() != stops[stops.size() - 2])
303 && (stops.size() > 1 || skipFirst));
304 if (stops.back().edge == sink && myArrivalPos >= lastPos) {
305 sinkPriority = stops.back().priority;
306 }
307#ifdef DEBUG_REROUTE
308 if (DEBUG_COND) {
309 std::cout << SIMTIME << " reroute " << info << " veh=" << getID() << " lane=" << Named::getIDSecure(getLane())
310 << " source=" << source->getID() << " sourcePos=" << sourcePos << " firstPos=" << firstPos << " arrivalPos=" << myArrivalPos << " lastPos=" << lastPos
311 << " route=" << toString(myRoute->getEdges()) << " stopEdges=" << toString(stops) << " skipFirst=" << skipFirst << " skipLast=" << skipLast << "\n";
312 }
313#endif
314 if (stops.size() == 1 && (skipFirst || skipLast)) {
315 stops.clear();
316 } else {
317 if (skipFirst) {
318 stops.erase(stops.begin());
319 }
320 if (skipLast) {
321 stops.erase(stops.end() - 1);
322 }
323 }
324 stopAtSink = stops.size() > 0 && stops.back().edge == sink && jumps.size() == 0;
325 }
326 } else {
327 std::set<const MSEdge*> jumpEdges;
328 std::map<const MSEdge*, StopEdgeInfo> stopsOnVia;
329 for (const MSStop& stop : myStops) {
330 if (stop.pars.jump >= 0) {
331 jumpEdges.insert(*stop.edge);
332 }
333 auto itsov = stopsOnVia.find(*stop.edge);
334 if (itsov == stopsOnVia.end()) {
335 stopsOnVia.insert({*stop.edge, StopEdgeInfo(*stop.edge, stop.pars.priority, stop.getArrivalFallback(), stop.getEndPos(*this))});
336 } else {
337 itsov->second.priority = addStopPriority(itsov->second.priority, stop.pars.priority);
338 }
339 }
340 // via takes precedence over stop edges
341 // there is a consistency check in MSRouteHandler::addStop that warns when a stop edge is not part of the via edges
342 for (std::vector<std::string>::const_iterator it = myParameter->via.begin(); it != myParameter->via.end(); ++it) {
343 MSEdge* viaEdge = MSEdge::dictionary(*it);
344 if ((viaEdge == source && it == myParameter->via.begin()) || (viaEdge == sink && myParameter->via.end() - it == 1)) {
345 continue;
346 }
347 assert(viaEdge != 0);
348 if (!viaEdge->isTazConnector() && viaEdge->allowedLanes(getVClass()) == nullptr) {
349 throw ProcessError(TLF("Vehicle '%' is not allowed on any lane of via edge '%'.", getID(), viaEdge->getID()));
350 }
351 auto itsov = stopsOnVia.find(viaEdge);
352 const double priority = (itsov == stopsOnVia.end() ? -1 : itsov->second.priority);
353 const SUMOTime arrival = (itsov == stopsOnVia.end() ? -1 : itsov->second.arrival);
354 const double pos = (itsov == stopsOnVia.end() ? viaEdge->getLength() : itsov->second.pos);
355 stops.push_back(StopEdgeInfo(viaEdge, priority, arrival, pos));
356 // @todo determine wether the viaEdge is also used by a stop and then use the stop priority here
357 if (jumpEdges.count(viaEdge) != 0) {
358 jumps.insert((int)stops.size());
359 }
360 }
361 }
362
363 int stopIndex = -1;
364 auto stopIt = myStops.begin();
365 SUMOTime startTime = t;
366 bool hasSkipped = false;
367 const double origSourcePos = sourcePos;
368 const MSEdge* origSource = source;
370 for (auto& stopEdgeInfo : stops) {
371 const MSEdge* const stopEdge = stopEdgeInfo.edge;
372 const double priority = stopEdgeInfo.priority;
373 stopIndex++;
375 if (jumps.count(stopIndex) != 0) {
376 edges.push_back(source);
377 source = stopEdge;
378 continue;
379 }
380 // !!! need to adapt t here
381 router.computeLooped(source, stopEdge, this, t, into, silent || priority >= 0);
382 //std::cout << SIMTIME << " reroute veh=" << getID() << " source=" << source->getID() << " target=" << (*s)->getID() << " edges=" << toString(into) << "\n";
383 if (into.size() > 0) {
384 while (stopIt != myStops.end() && stopIt->pars.edge != stopEdge->getID()) {
385 stopIt++;
386 }
387
388 startTime += TIME2STEPS(router.recomputeCostsPos(into, this, sourcePos, stopEdgeInfo.pos, startTime));
389 if (stopIt != myStops.end()) {
390 if (stopIt->pars.priority >= 0 && info != "device.rerouting") {
391 // consider skipping this stop if it cannot be reached in a timely manner
392 if (stopIt != myStops.end()) {
393 SUMOTime arrival = stopEdgeInfo.arrival;
394 if (arrival > 0) {
395 SUMOTime delay = startTime - arrival;
396 //std::cout << " t=" << time2string(t) << " veh=" << getID() << " info=" << info << " stopIndex=" << stopIndex
397 // << " into=" << toString(into) << " sourcePos=" << sourcePos << " stopPos=" << stopPos
398 // << " startTime=" << time2string(startTime) << " arrival=" << time2string(arrival) << " delay=" << time2string(delay) << "\n";
399 if (delay > 0) {
400 if (delay > maxDelay) {
401 stopEdgeInfo.skipped = true;
402 stopEdgeInfo.delay = delay;
403 hasSkipped = true;
404 continue;
405 }
406 }
407 }
408 }
409 }
410 sourcePos = stopEdgeInfo.pos;
411 startTime += stopIt->getMinDuration(startTime);
412 }
413 into.pop_back();
414 edges.insert(edges.end(), into.begin(), into.end());
415 if (stopEdge->isTazConnector()) {
416 source = into.back();
417 edges.pop_back();
418 } else {
419 source = stopEdge;
420 }
421 stopEdgeInfo.routeIndex = edges.size() - 1;
422 } else {
423 if ((source != sink || !stopAtSink)) {
424 if (priority >= 0) {
425 stopEdgeInfo.skipped = true;
426 hasSkipped = true;
427 continue;
428 } else {
429 std::string error = TLF("Vehicle '%' has no valid route from edge '%' to stop edge '%'.", getID(), source->getID(), stopEdge->getID());
430 if (MSGlobals::gCheckRoutes || silent) {
431 throw ProcessError(error);
432 } else {
433 WRITE_WARNING(error);
434 edges.push_back(source);
435 source = stopEdge;
436 }
437 }
438 }
439 }
440 }
441 if (stops.empty() && source == sink && onInit
445 router.computeLooped(source, sink, this, t, edges, silent);
446 } else {
447 if (!router.compute(source, sink, this, t, edges, silent || sinkPriority >= 0)) {
448 if (sinkPriority >= 0) {
449 edges.push_back(source);
450 hasSkipped = true;
451 stops.push_back(StopEdgeInfo(sink, sinkPriority, -1, getArrivalPos()));
452 stops.back().skipped = true;
453 } else {
454 edges.clear();
455 }
456 }
457 }
458 if (hasSkipped) {
459 edges = optimizeSkipped(t, router, origSource, origSourcePos, stops, edges, maxDelay);
460 for (auto stop : stops) {
461 if (stop.skipped) {
462 if (stop.delay > 0) {
463 WRITE_WARNING(TLF("Vehicle '%' skips stop on edge '%' with delay % at time %.", getID(), stop.edge->getID(), time2string(stop.delay), time2string(SIMSTEP)));
464 } else if (stop.backtracked) {
465 WRITE_WARNING(TLF("Vehicle '%' skips stop on edge '%' with priority % at time %.", getID(), stop.edge->getID(), stop.priority, time2string(SIMSTEP)));
466 } else {
467 WRITE_WARNING(TLF("Vehicle '%' skips unreachable stop on edge '%' with priority % at time %.", getID(), stop.edge->getID(), stop.priority, time2string(SIMSTEP)));
468 }
469 }
470 }
471 }
472
473 // router.setHint(myCurrEdge, myRoute->end(), this, t);
474 if (edges.empty() && silent) {
475 return false;
476 }
477 if (!edges.empty() && edges.front()->isTazConnector()) {
478 edges.erase(edges.begin());
479 }
480 if (!edges.empty() && edges.back()->isTazConnector()) {
481 edges.pop_back();
482 }
483 const double routeCost = router.recomputeCosts(edges, this, t);
484 const double previousCost = onInit ? routeCost : router.recomputeCosts(oldEdgesRemaining, this, t);
485 const double savings = previousCost - routeCost;
486 //if (getID() == "43") std::cout << SIMTIME << " pCost=" << previousCost << " cost=" << routeCost
487 // << " onInit=" << onInit
488 // << " prevEdges=" << toString(oldEdgesRemaining)
489 // << " newEdges=" << toString(edges)
490 // << "\n";
491 replaceRouteEdges(edges, routeCost, savings, info, onInit);
492 // this must be called even if the route could not be replaced
493 if (onInit) {
494 if (edges.empty()) {
496 throw ProcessError(TLF("Vehicle '%' has no valid route.", getID()));
497 } else if (source->isTazConnector()) {
498 WRITE_WARNINGF(TL("Removing vehicle '%' which has no valid route."), getID());
500 return false;
501 }
502 }
505 }
506 return !edges.empty();
507}
508
509
510bool
511MSBaseVehicle::replaceRouteEdges(ConstMSEdgeVector& edges, double cost, double savings, const std::string& info, bool onInit, bool check, bool removeStops, std::string* msgReturn) {
512 if (edges.empty()) {
513 WRITE_WARNINGF(TL("No route for vehicle '%' found."), getID());
514 if (msgReturn != nullptr) {
515 *msgReturn = "No route found";
516 }
517 return false;
518 }
519 // build a new id, first
520 std::string id = getID();
521 if (id[0] != '!') {
522 id = "!" + id;
523 }
524 const std::string idSuffix = id + "!var#";
525 int varIndex = 1;
526 id = idSuffix + toString(varIndex);
527 while (MSRoute::hasRoute(id)) {
528 id = idSuffix + toString(++varIndex);
529 }
530 int oldSize = (int)edges.size();
531 if (!onInit) {
532 const MSEdge* const origin = *getRerouteOrigin();
533 if (origin != *myCurrEdge && edges.front() == origin) {
534 edges.insert(edges.begin(), *myCurrEdge);
535 oldSize = (int)edges.size();
536 }
537 edges.insert(edges.begin(), myRoute->begin(), myCurrEdge);
538 }
539 if (edges == myRoute->getEdges() && haveValidStopEdges(true)) {
540 // re-assign stop iterators when rerouting to a new parkingArea / insertStop
541 return true;
542 }
543 const RGBColor& c = myRoute->getColor();
544 MSRoute* newRoute = new MSRoute(id, edges, false, &c == &RGBColor::DEFAULT_COLOR ? nullptr : new RGBColor(c), StopParVector());
545 newRoute->setCosts(cost);
546 newRoute->setSavings(savings);
547 ConstMSRoutePtr constRoute = std::shared_ptr<MSRoute>(newRoute);
548 if (!MSRoute::dictionary(id, constRoute)) {
549 delete newRoute;
550 if (msgReturn != nullptr) {
551 *msgReturn = "duplicate routeID '" + id + "'";
552 }
553 return false;
554 }
555
556 std::string msg;
557 if (check && !hasValidRoute(msg, constRoute)) {
558 WRITE_WARNINGF(TL("Invalid route replacement for vehicle '%'. %"), getID(), msg);
560 if (msgReturn != nullptr) {
561 *msgReturn = msg;
562 }
563 return false;
564 }
565 }
566 if (!replaceRoute(constRoute, info, onInit, (int)edges.size() - oldSize, false, removeStops, msgReturn)) {
567 return false;
568 }
569 return true;
570}
571
572
573bool
574MSBaseVehicle::replaceRoute(ConstMSRoutePtr newRoute, const std::string& info, bool onInit, int offset, bool addRouteStops, bool removeStops, std::string* msgReturn) {
575 const ConstMSEdgeVector& edges = newRoute->getEdges();
576 // rebuild in-vehicle route information
577 if (onInit) {
578 myCurrEdge = newRoute->begin();
579 } else {
580 MSRouteIterator newCurrEdge = std::find(edges.begin() + offset, edges.end(), *myCurrEdge);
581 if (newCurrEdge == edges.end()) {
582 if (msgReturn != nullptr) {
583 *msgReturn = TLF("current edge '%' not found in new route", (*myCurrEdge)->getID());
584 }
585#ifdef DEBUG_REPLACE_ROUTE
586 if (DEBUG_COND) {
587 std::cout << " newCurrEdge not found\n";
588 }
589#endif
590 return false;
591 }
592 if (getLane() != nullptr) {
593 if (getLane()->getEdge().isInternal() && (
594 (newCurrEdge + 1) == edges.end() || (*(newCurrEdge + 1)) != &(getLane()->getOutgoingViaLanes().front().first->getEdge()))) {
595 if (msgReturn != nullptr) {
596 *msgReturn = TL("Vehicle is on junction-internal edge leading elsewhere");
597 }
598#ifdef DEBUG_REPLACE_ROUTE
599 if (DEBUG_COND) {
600 std::cout << " Vehicle is on junction-internal edge leading elsewhere\n";
601 }
602#endif
603 return false;
604 } else if (getPositionOnLane() > getLane()->getLength()
605 && (myCurrEdge + 1) != myRoute->end()
606 && (newCurrEdge + 1) != edges.end()
607 && *(myCurrEdge + 1) != *(newCurrEdge + 1)) {
608 if (msgReturn != nullptr) {
609 *msgReturn = TL("Vehicle is moving past junction and committed to move to another successor edge");
610 }
611#ifdef DEBUG_REPLACE_ROUTE
612 if (DEBUG_COND) {
613 std::cout << " Vehicle is moving past junction and committed to move to another successor edge\n";
614 }
615#endif
616 return false;
617 }
618 }
619 myCurrEdge = newCurrEdge;
620 }
621 const bool stopsFromScratch = onInit && myRoute->getStops().empty();
622 // assign new route
624 myRoute = newRoute;
625 // update arrival definition
627 // save information that the vehicle was rerouted
629 myStopUntilOffset += myRoute->getPeriod();
631 if (!onInit && isRail() && MSRailSignalControl::hasInstance()) {
632 // we need to update driveways (add/remove reminders) before the next call to MSRailSignalControl::updateSignals
633 //
634 // rerouting may be triggered through
635 // - MoveReminders (executeMove->activateReminders)
636 // - rerouters
637 // - devices (MSDevice_Stationfinder)
638 // - TraCI (changeTarget, replaceStop, ...
639 // - events (MSDevice_Routing::myRerouteCommand, MSDevice_Taxi::triggerDispatch)
640 //
641 // Since activateReminders actively modifies reminders, adding/deleting reminders would create a mess
642 // hence, we use an event to be safe for all case
643
646 }
647#ifdef DEBUG_REPLACE_ROUTE
648 if (DEBUG_COND) {
649 std::cout << SIMTIME << " veh=" << getID() << " replaceRoute info=" << info << " on " << (*myCurrEdge)->getID()
650 << " lane=" << Named::getIDSecure(getLane())
651 << " stopsFromScratch=" << stopsFromScratch
652 << " newSize=" << newRoute->getEdges().size()
653 << " newIndex=" << (myCurrEdge - newRoute->begin())
654 << " edges=" << toString(newRoute->getEdges())
655 << "\n";
656 }
657#endif
658 // remove past stops which are not on the route anymore
659 for (StopParVector::iterator it = myPastStops.begin(); it != myPastStops.end();) {
660 const MSEdge* stopEdge = (it->edge.empty()) ? &MSLane::dictionary(it->lane)->getEdge() : MSEdge::dictionary(it->edge);
661 if (std::find(myRoute->begin(), myRoute->end(), stopEdge) == myRoute->end()) {
662 it = myPastStops.erase(it);
663 } else {
664 ++it;
665 }
666 }
667 // if we did not drive yet it may be best to simply reassign the stops from scratch
668 if (stopsFromScratch) {
669 myStops.clear();
671 } else {
672 // recheck old stops
673 MSRouteIterator searchStart = myCurrEdge;
674 double lastPos = getPositionOnLane() + getBrakeGap();
675 if (getLane() != nullptr && getLane()->isInternal()
676 && myStops.size() > 0 && !myStops.front().lane->isInternal()) {
677 // searchStart is still incoming to the intersection so lastPos
678 // relative to that edge must be adapted
679 lastPos += (*myCurrEdge)->getLength();
680 }
681 int stopIndex = 0;
682 for (std::list<MSStop>::iterator iter = myStops.begin(); iter != myStops.end();) {
683 double endPos = iter->getEndPos(*this);
684#ifdef DEBUG_REPLACE_ROUTE
685 if (DEBUG_COND) {
686 std::cout << " stopEdge=" << iter->lane->getEdge().getID() << " start=" << (searchStart - myCurrEdge) << " endPos=" << endPos << " lastPos=" << lastPos << "\n";
687 }
688#endif
689 if (*searchStart != &iter->lane->getEdge()
690 || endPos + NUMERICAL_EPS < lastPos) {
691 if (searchStart != edges.end() && !iter->reached) {
692 searchStart++;
693 }
694 }
695 lastPos = endPos;
696
697 iter->edge = std::find(searchStart, edges.end(), &iter->lane->getEdge());
698#ifdef DEBUG_REPLACE_ROUTE
699 if (DEBUG_COND) {
700 std::cout << " foundIndex=" << (iter->edge - myCurrEdge) << " end=" << (edges.end() - myCurrEdge) << "\n";
701 }
702#endif
703 if (iter->edge == edges.end()) {
704 if (!removeStops) {
705 WRITE_ERRORF(TL("Vehicle '%' could not assign stop '%' after rerouting (%) at time=%."), getID(), iter->getDescription(), info, time2string(SIMSTEP));
706 }
707 iter = myStops.erase(iter);
708 continue;
709 } else {
710 setSkips(*iter, stopIndex);
711 searchStart = iter->edge;
712 }
713 ++iter;
714 stopIndex++;
715 }
716 // add new stops
717 if (addRouteStops) {
718 for (StopParVector::const_iterator i = newRoute->getStops().begin(); i != newRoute->getStops().end(); ++i) {
719 std::string error;
721 if (error != "") {
722 WRITE_WARNING(error);
723 }
724 }
725 }
726 }
727 return true;
728}
729
730
733 std::vector<StopEdgeInfo>& stops, ConstMSEdgeVector edges, SUMOTime maxDelay) const {
734 double skippedPrio = 0;
735 double minPrio = std::numeric_limits<double>::max();
736 std::vector<int> skipped;
737 for (int i = 0; i < (int)stops.size(); i++) {
738 if (stops[i].skipped) {
739 skipped.push_back(i);
740 }
741 minPrio = MIN2(minPrio, stops[i].priority);
742 }
743 for (int i : skipped) {
744 skippedPrio += stops[i].priority;
745 }
746#ifdef DEBUG_OPTIMIZE_SKIPPED
747 std::cout << SIMTIME << " veh=" << getID() << " optimzeSkipped=" << toString(skipped) << " source=" << source->getID() << "\n";
748 for (int i = 0; i < (int)stops.size(); i++) {
749 const auto& stop = stops[i];
750 std::cout << " " << i << " edge=" << stop.edge->getID() << " routeIndex=" << stop.routeIndex << " prio=" << stop.priority << " skipped=" << stop.skipped << " arrival=" << stop.arrival << "\n";
751 }
752#endif
753 if (skippedPrio == minPrio) {
754 // case A: only one stop was skipped and it had the lowest priority (or multiple stops with prio 0 were skipped): this is already optimal
755#ifdef DEBUG_OPTIMIZE_SKIPPED
756 std::cout << " skippedPrio=" << skippedPrio << " minPrio=" << minPrio << "\n";
757#endif
758 return edges;
759 }
760 // check reachability of skipped stops
761 std::vector<int> skippedReachable;
762 for (int si : skipped) {
764 router.computeLooped(source, stops[si].edge, this, t, into, true);
765 if (into.size() > 0) {
766 SUMOTime arrival = t + TIME2STEPS(router.recomputeCostsPos(into, this, sourcePos, stops[si].pos, t));
767 if (arrival - stops[si].arrival <= maxDelay) {
768 skippedReachable.push_back(si);
769 }
770 }
771 }
772 if (skippedReachable.size() == 0) {
773 // case B: skipped stops are not reachable with backtracking
774#ifdef DEBUG_OPTIMIZE_SKIPPED
775 std::cout << " noneReachable\n";
776#endif
777 return edges;
778 }
779 std::set<int> unskippedBefore;
780 for (int i = 0; i < (int)stops.size(); i++) {
781 if (i < skipped.back()) {
782 unskippedBefore.insert(i);
783 }
784 }
785 for (int i : skipped) {
786 unskippedBefore.erase(i);
787 }
788 // otherwise, skippedReachable should have been empty
789 assert(unskippedBefore.size() > 0);
790 // the unskipped stops may form several non contiguous sequences. We care about the last element of each sequence
791 std::vector<int> unskippedEnds;
792 std::vector<int> skippedStarts;
793 for (int i : unskippedBefore) {
794 if (unskippedBefore.count(i + 1) == 0) {
795 for (int i2 : skippedReachable) {
796 if (i2 >= i + 1) {
797 unskippedEnds.push_back(i);
798 skippedStarts.push_back(i2);
799 break;
800 }
801 }
802 }
803 }
804 std::sort(unskippedEnds.begin(), unskippedEnds.end()); // ascending
805 std::set<int> skippedSet(skipped.begin(), skipped.end());
806#ifdef DEBUG_OPTIMIZE_SKIPPED
807 std::cout << " unskippedEnds=" << toString(unskippedEnds) << " skippedStarts=" << toString(skippedStarts) << "\n";
808#endif
809
810 ConstMSEdgeVector bestEdges = edges;
811 double altSkippedPrio = 0;
812 const MSEdge* firstSkipped = stops[skippedStarts.back()].edge;
813 for (int i = unskippedEnds.back(); i >= 0; i--) {
814 double prio = stops[i].priority;
815 altSkippedPrio += prio;
816 if (skippedSet.count(i) // found start of another skip sequence
817 || prio < 0 // cannot backtrack past unskippable stop
818 || altSkippedPrio >= skippedPrio // backtracking past this stop cannot improve result
819 ) {
820 unskippedEnds.pop_back();
821 skippedStarts.pop_back();
822 if (unskippedEnds.empty()) {
823 return edges;
824 }
825 // try to optimize earlier sequence of skips
826 i = unskippedEnds.back();
827 firstSkipped = stops[skippedStarts.back()].edge;
828 altSkippedPrio = 0;
829 continue;
830 }
831 const MSEdge* prev = i > 0 ? stops[i - 1].edge : source;
832 const double prevPos = i > 0 ? stops[i - 1].pos : sourcePos;
834 SUMOTime start = stops[i - 1].arrival;
835 router.computeLooped(prev, firstSkipped, this, start, into, true);
836 if (into.size() == 0) {
837 // cannot reach firstSkipped and need to backtrack further
838 continue;
839 }
840 start += TIME2STEPS(router.recomputeCostsPos(into, this, prevPos, stops[skippedStarts.back()].pos, start));
841 // initialize skipped priority with stops skipped during backtracking and any skipped before that
842 std::vector<StopEdgeInfo> stops2 = stops;
843 double skippedPrio2 = altSkippedPrio;
844 for (int i2 = 0; i2 < i - 1; i2++) {
845 if (stops[i2].skipped) {
846 skippedPrio2 += stops[i2].priority;
847 }
848 }
849 for (int i2 = i; i2 <= unskippedEnds.back(); i2++) {
850 stops2[i2].skipped = true;
851 stops2[i2].backtracked = true;
852 }
853 int prevRouteIndex = i > 0 ? stops[i - 1].routeIndex : getDepartEdge();
854 assert(prevRouteIndex >= 0 && prevRouteIndex < edges.size());
855 ConstMSEdgeVector edges2(edges.begin(), edges.begin() + prevRouteIndex);
856 stops2[skippedStarts.back()].skipped = false;
857 edges2.insert(edges2.begin(), into.begin(), into.end());
858 edges2 = routeAlongStops(start, router, stops2, edges2, skippedStarts.back(), maxDelay, skippedPrio2);
859 if (skippedPrio2 < skippedPrio) {
860#ifdef DEBUG_OPTIMIZE_SKIPPED
861 std::cout << " skippedPrio=" << skippedPrio << " skippedPrio2=" << skippedPrio2 << "\n";
862#endif
863 bestEdges = edges2;
864 skippedPrio = skippedPrio2;
865 stops = stops2;
866 }
867 }
868 return bestEdges;
869}
870
871
874 std::vector<StopEdgeInfo>& stops, ConstMSEdgeVector edges,
875 int originStop, SUMOTime maxDelay, double& skippedPrio2) const {
876 // originStop was already reached an the edges appended
877 for (int i = originStop + 1; i < (int)stops.size(); i++) {
879 router.computeLooped(edges.back(), stops[i].edge, this, t, into, true);
880 if (into.size() == 0) {
881 if (stops[i].priority < 0) {
882 // failure: cannot reach required stop
883 skippedPrio2 = std::numeric_limits<double>::max();
884 return edges;
885 }
886 skippedPrio2 += stops[i].priority;
887 stops[i].skipped = true;
888 } else {
889 t += TIME2STEPS(router.recomputeCostsPos(into, this, stops[i - 1].pos, stops[i].pos, t));
890 SUMOTime delay = t - stops[i].arrival;
891 if (delay > maxDelay) {
892 if (stops[i].priority < 0) {
893 // failure: cannot reach required stop in time
894 skippedPrio2 = std::numeric_limits<double>::max();
895 return edges;
896 }
897 skippedPrio2 += stops[i].priority;
898 stops[i].skipped = true;
899 stops[i].delay = true;
900 } else {
901 edges.pop_back();
902 edges.insert(edges.end(), into.begin(), into.end());
903 }
904 }
905 }
906 return edges;
907}
908
909
910double
912 return 0;
913}
914
915
916void
922
923
926 const SUMOTime dep = getParameter().depart;
927 if (dep < 0) {
928 return 0;
929 }
930 return hasDeparted() ? getDeparture() - dep : SIMSTEP - dep;
931}
932
933
934bool
936 return succEdge(1) == nullptr;
937}
938
939
940int
942 return (int) std::distance(myRoute->begin(), myCurrEdge);
943}
944
945
946void
948 myCurrEdge = myRoute->begin() + index;
949 const_cast<SUMOVehicleParameter*>(myParameter)->departLaneProcedure = departLaneProcedure;
950 // !!! hack
951 myArrivalPos = (*(myRoute->end() - 1))->getLanes()[0]->getLength();
952}
953
954double
958
959bool
961 if (t->isPerson() && getPersonNumber() >= getVehicleType().getPersonCapacity()) {
962 return false;
963 } else if (!t->isPerson() && getContainerNumber() >= getVehicleType().getContainerCapacity()) {
964 return false;
965 }
966 if (isStopped() && myStops.begin()->pars.permitted.size() > 0
967 && myStops.begin()->pars.permitted.count(t->getID()) == 0) {
968 return false;
969 }
970 MSDevice_Taxi* taxiDevice = static_cast<MSDevice_Taxi*>(getDevice(typeid(MSDevice_Taxi)));
971 if (taxiDevice != nullptr) {
972 return taxiDevice->allowsBoarding(t);
973 }
974 return true;
975}
976
977
978void
980 if (transportable->isPerson()) {
981 if (myPersonDevice == nullptr) {
983 myMoveReminders.insert(myMoveReminders.begin(), std::make_pair(myPersonDevice, 0.));
986 }
987 }
988 myPersonDevice->addTransportable(transportable);
989 } else {
990 if (myContainerDevice == nullptr) {
992 myMoveReminders.insert(myMoveReminders.begin(), std::make_pair(myContainerDevice, 0.));
995 }
996 }
997 myContainerDevice->addTransportable(transportable);
998 }
999 if (myEnergyParams != nullptr) {
1001 }
1002}
1003
1004
1005bool
1007 for (const MSStop& stop : myStops) {
1008 if (stop.edge == it && stop.pars.jump >= 0) {
1009 return true;
1010 } else if (stop.edge > it) {
1011 return false;
1012 }
1013 }
1014 return false;
1015}
1016
1017
1018bool
1019MSBaseVehicle::hasValidRoute(std::string& msg, ConstMSRoutePtr route) const {
1021 if (route == nullptr) {
1022 route = myRoute;
1023 } else {
1024 start = route->begin();
1025 }
1026 const bool checkJumps = route == myRoute; // the edge iterators in the stops are invalid otherwise
1027 MSRouteIterator last = route->end() - 1;
1028 // check connectivity, first
1029 for (MSRouteIterator e = start; e != last; ++e) {
1030 const MSEdge& next = **(e + 1);
1031 if ((*e)->allowedLanes(next, myType->getVehicleClass()) == nullptr) {
1032 if (!checkJumps || !hasJump(e)) {
1034 || (!next.hasTransientPermissions() && !(*e)->hasTransientPermissions())) {
1035 msg = TLF("No connection between edge '%' and edge '%'.", (*e)->getID(), (*(e + 1))->getID());
1036 return false;
1037 }
1038 }
1039 }
1040 }
1041 last = route->end();
1042 // check usable lanes, then
1043 for (MSRouteIterator e = start; e != last; ++e) {
1044 if ((*e)->prohibits(this)) {
1045 msg = TLF("Edge '%' prohibits.", (*e)->getID());
1046 return false;
1047 }
1048 }
1049 return true;
1050}
1051
1052
1053bool
1055 if (!(*myCurrEdge)->isTazConnector()) {
1057 msg = TLF("Departure speed for vehicle '%' is too high for the vehicle type '%'.", getID(), myType->getID());
1059 return false;
1060 }
1061 }
1062 if (myRoute->getEdges().size() > 0 && !(*myCurrEdge)->prohibits(this)) {
1063 myRouteValidity &= ~ROUTE_START_INVALID_PERMISSIONS;
1064 return true;
1065 } else {
1066 msg = TLF("Vehicle '%' is not allowed to depart on any lane of edge '%'.", getID(), (*myCurrEdge)->getID());
1068 return false;
1069 }
1070}
1071
1072
1073int
1074MSBaseVehicle::getRouteValidity(bool update, bool silent, std::string* msgReturn) {
1075 if (!update) {
1076 return myRouteValidity;
1077 }
1078 // insertion check must be done in any case
1079 std::string msg;
1080 if (!hasValidRouteStart(msg)) {
1082 throw ProcessError(msg);
1083 } else if (!silent) {
1084 // vehicle will be discarded
1085 WRITE_WARNING(msg);
1086 } else if (msgReturn != nullptr) {
1087 *msgReturn = msg;
1088 }
1089 }
1092 // we could check after the first rerouting
1094 if (!hasValidRoute(msg, myRoute)) {
1096 throw ProcessError(TLF("Vehicle '%' has no valid route. %", getID(), msg));
1097 }
1098 }
1099 myRouteValidity &= ~ROUTE_UNCHECKED;
1100 return myRouteValidity;
1101}
1102
1103
1104bool
1106 for (auto item : myMoveReminders) {
1107 if (item.first == rem) {
1108 return true;
1109 }
1110 }
1111 return false;
1112}
1113
1114
1115void
1117#ifdef _DEBUG
1118 if (myTraceMoveReminders) {
1119 traceMoveReminder("add", rem, pos, true);
1120 }
1121#endif
1122 myMoveReminders.push_back(std::make_pair(rem, pos));
1123}
1124
1125
1126void
1128 for (MoveReminderCont::iterator r = myMoveReminders.begin(); r != myMoveReminders.end(); ++r) {
1129 if (r->first == rem) {
1130#ifdef _DEBUG
1131 if (myTraceMoveReminders) {
1132 traceMoveReminder("remove", rem, 0, false);
1133 }
1134#endif
1135 myMoveReminders.erase(r);
1136 return;
1137 }
1138 }
1139}
1140
1141
1142void
1144 // notifyEnter may cause new reminders to be added so we cannot use an iterator
1145 for (int i = 0; i < (int)myMoveReminders.size();) {
1146 MSMoveReminder* rem = myMoveReminders[i].first;
1147 const double remPos = myMoveReminders[i].second;
1148 // skip the reminder if it is a lane reminder but not for my lane (indicated by rem->second > 0.)
1149 if (rem->getLane() != nullptr && remPos > 0.) {
1150#ifdef _DEBUG
1151 if (myTraceMoveReminders) {
1152 traceMoveReminder("notifyEnter_skipped", rem, remPos, true);
1153 }
1154#endif
1155 ++i;
1156 } else {
1157 if (rem->notifyEnter(*this, reason, enteredLane)) {
1158#ifdef _DEBUG
1159 if (myTraceMoveReminders) {
1160 traceMoveReminder("notifyEnter", rem, remPos, true);
1161 }
1162#endif
1163 ++i;
1164 } else {
1165#ifdef _DEBUG
1166 if (myTraceMoveReminders) {
1167 traceMoveReminder("notifyEnter", rem, remPos, false);
1168 }
1169#endif
1170 myMoveReminders.erase(myMoveReminders.begin() + i);
1171 }
1172 }
1173 }
1174}
1175
1176
1177bool
1179 return isRailway(getVClass()) || isRailway(getCurrentEdge()->getPermissions());
1180}
1181
1182void
1184 if (myRoute->getLastEdge()->isTazConnector()) {
1185 return;
1186 }
1187 const int arrivalEdgeIndex = MIN2(myParameter->arrivalEdge, (int)myRoute->getEdges().size() - 1);
1188 if (arrivalEdgeIndex != myParameter->arrivalEdge) {
1189 WRITE_WARNINGF(TL("Vehicle '%' ignores attribute arrivalEdge=% after rerouting at time=% (routeLength=%)"),
1190 getID(), myParameter->arrivalEdge, time2string(SIMSTEP), myRoute->getEdges().size() - 1);
1191 }
1192 const MSEdge* arrivalEdge = myParameter->arrivalEdge >= 0 ? myRoute->getEdges()[arrivalEdgeIndex] : myRoute->getLastEdge();
1193 if (!onInit) {
1194 arrivalEdge = myRoute->getLastEdge();
1195 // ignore arrivalEdge parameter after rerouting
1196 const_cast<SUMOVehicleParameter*>(myParameter)->arrivalEdge = -1;
1197 }
1198 const std::vector<MSLane*>& lanes = arrivalEdge->getLanes();
1199 const double lastLaneLength = lanes[0]->getLength();
1202 if (fabs(myParameter->arrivalPos) > lastLaneLength) {
1203 WRITE_WARNINGF(TL("Vehicle '%' will not be able to arrive at the given position!"), getID());
1204 }
1205 // Maybe we should warn the user about invalid inputs!
1206 myArrivalPos = MIN2(myParameter->arrivalPos, lastLaneLength);
1207 if (myArrivalPos < 0) {
1208 myArrivalPos = MAX2(myArrivalPos + lastLaneLength, 0.);
1209 }
1210 break;
1212 myArrivalPos = RandHelper::rand(lastLaneLength);
1213 break;
1215 myArrivalPos = lastLaneLength / 2.;
1216 break;
1217 default:
1218 myArrivalPos = lastLaneLength;
1219 break;
1220 }
1222 if (myParameter->arrivalLane >= (int)lanes.size() || !lanes[myParameter->arrivalLane]->allowsVehicleClass(myType->getVehicleClass())) {
1223 WRITE_WARNINGF(TL("Vehicle '%' will not be able to arrive at the given lane '%_%'!"), getID(), arrivalEdge->getID(), toString(myParameter->arrivalLane));
1224 }
1225 myArrivalLane = MIN2(myParameter->arrivalLane, (int)(lanes.size() - 1));
1227 myArrivalLane = -1;
1228 for (MSLane* lane : lanes) {
1229 if (lane->allowsVehicleClass(myType->getVehicleClass())) {
1230 myArrivalLane = lane->getIndex();
1231 break;
1232 }
1233 }
1234 if (myArrivalLane == -1) {
1235 WRITE_WARNINGF(TL("Vehicle '%' has no usable arrivalLane on edge '%'."), getID(), arrivalEdge->getID());
1236 myArrivalLane = 0;
1237 }
1239 // pick random lane among all usable lanes
1240 std::vector<MSLane*> usable;
1241 for (MSLane* lane : lanes) {
1242 if (lane->allowsVehicleClass(myType->getVehicleClass())) {
1243 usable.push_back(lane);
1244 }
1245 }
1246 if (usable.empty()) {
1247 WRITE_WARNINGF(TL("Vehicle '%' has no usable arrivalLane on edge '%'."), getID(), arrivalEdge->getID());
1248 myArrivalLane = 0;
1249 } else {
1250 myArrivalLane = usable[RandHelper::rand(0, (int)usable.size())]->getIndex();
1251 }
1252 }
1254 for (std::vector<MSLane*>::const_iterator l = lanes.begin(); l != lanes.end(); ++l) {
1255 if (myParameter->arrivalSpeed <= (*l)->getVehicleMaxSpeed(this)) {
1256 return;
1257 }
1258 }
1259 WRITE_WARNINGF(TL("Vehicle '%' will not be able to arrive with the given speed!"), getID());
1260 }
1261}
1262
1263void
1267 const int routeEdges = (int)myRoute->getEdges().size();
1269 // write specific edge in vehroute output for reproducibility
1270 pars->departEdge = RandHelper::rand(0, routeEdges);
1272 }
1273 assert(pars->departEdge >= 0);
1274 if (pars->departEdge >= routeEdges) {
1275 WRITE_WARNINGF(TL("Ignoring departEdge % for vehicle '%' with % route edges"), toString(pars->departEdge), getID(), toString(routeEdges));
1276 } else {
1277 myCurrEdge += pars->departEdge;
1278 }
1279 }
1281 const int routeEdges = (int)myRoute->getEdges().size();
1282 const int begin = (int)(myCurrEdge - myRoute->begin());
1283 // write specific edge in vehroute output for reproducibility
1284 pars->arrivalEdge = RandHelper::rand(begin, routeEdges);
1286 assert(pars->arrivalEdge >= begin);
1287 assert(pars->arrivalEdge < routeEdges);
1288 }
1289}
1290
1291int
1295
1296int
1300 } else {
1302 }
1303}
1304
1305double
1307 return MAX2(0., MIN2(1., getVehicleType().getImpatience()
1308 + (hasInfluencer() ? getBaseInfluencer()->getExtraImpatience() : 0)
1310}
1311
1312
1313MSDevice*
1314MSBaseVehicle::getDevice(const std::type_info& type) const {
1315 for (MSVehicleDevice* const dev : myDevices) {
1316 if (typeid(*dev) == type) {
1317 return dev;
1318 }
1319 }
1320 return nullptr;
1321}
1322
1323
1324void
1326 // the parameters may hold the name of a vTypeDistribution but we are interested in the actual type
1327 const std::string& typeID = myParameter->vtypeid != getVehicleType().getID() ? getVehicleType().getID() : "";
1329 // params and stops must be written in child classes since they may wish to add additional attributes first
1330 out.writeAttr(SUMO_ATTR_ROUTE, myRoute->getID());
1331 std::ostringstream os;
1332 os << myOdometer << " " << myNumberReroutes;
1333 out.writeAttr(SUMO_ATTR_DISTANCE, os.str());
1336 }
1338 const int precision = out.getPrecision();
1339 out.setPrecision(MAX2(gPrecisionRandom, precision));
1341 out.setPrecision(precision);
1342 }
1344 out.writeAttr(SUMO_ATTR_REROUTE, true);
1345 }
1347 // could be set from stop
1349 }
1350 // here starts the vehicle internal part (see loading)
1351 // @note: remember to close the vehicle tag when calling this in a subclass!
1352}
1353
1354
1355bool
1356MSBaseVehicle::handleCollisionStop(MSStop& stop, const double distToStop) {
1357 UNUSED_PARAMETER(stop);
1358 UNUSED_PARAMETER(distToStop);
1359 return true;
1360}
1361
1362
1363bool
1365 return !myStops.empty() && myStops.begin()->reached /*&& myState.mySpeed < SUMO_const_haltingSpeed @todo #1864#*/;
1366}
1367
1368
1369bool
1371 return (isStopped() && (myStops.begin()->pars.parking == ParkingType::OFFROAD)
1372 && (myStops.begin()->parkingarea == nullptr || !myStops.begin()->parkingarea->parkOnRoad())
1373 && (myStops.begin()->getSpeed() == 0 || getSpeed() < SUMO_const_haltingSpeed));
1374}
1375
1376
1377bool
1379 return myPastStops.size() > 0 && myPastStops.back().jump >= 0 && getEdge()->getID() == myPastStops.back().edge && myPastStops.back().ended == SIMSTEP;
1380}
1381
1382
1383bool
1385 return isStopped() && (myStops.begin()->triggered || myStops.begin()->containerTriggered || myStops.begin()->joinTriggered);
1386}
1387
1388
1389bool
1391 return isStopped() && (myStops.begin()->pars.parking == ParkingType::OFFROAD);
1392}
1393
1394
1395bool
1396MSBaseVehicle::isStoppedInRange(const double pos, const double tolerance, bool checkFuture) const {
1397 if (isStopped() || (checkFuture && hasStops())) {
1398 const MSStop& stop = myStops.front();
1399 return stop.pars.startPos - tolerance <= pos && stop.pars.endPos + tolerance >= pos;
1400 }
1401 return false;
1402}
1403
1404bool
1405MSBaseVehicle::replaceParkingArea(MSParkingArea* parkingArea, std::string& errorMsg) {
1406 // Check if there is a parking area to be replaced
1407 if (parkingArea == 0) {
1408 errorMsg = "new parkingArea is NULL";
1409 return false;
1410 }
1411 if (myStops.size() == 0) {
1412 errorMsg = "vehicle has no stops";
1413 return false;
1414 }
1415 if (myStops.front().parkingarea == 0) {
1416 errorMsg = "first stop is not at parkingArea";
1417 return false;
1418 }
1419 MSStop& first = myStops.front();
1420 SUMOVehicleParameter::Stop& stopPar = const_cast<SUMOVehicleParameter::Stop&>(first.pars);
1421 std::string oldStopEdgeID = first.lane->getEdge().getID();
1422 // merge subsequent duplicate stops equals to parking area
1423 for (std::list<MSStop>::iterator iter = ++myStops.begin(); iter != myStops.end();) {
1424 if (iter->parkingarea == parkingArea) {
1425 stopPar.duration += iter->duration;
1426 myStops.erase(iter++);
1427 } else {
1428 break;
1429 }
1430 }
1431 stopPar.lane = parkingArea->getLane().getID();
1432 stopPar.parkingarea = parkingArea->getID();
1433 stopPar.startPos = parkingArea->getBeginLanePosition();
1434 stopPar.endPos = parkingArea->getEndLanePosition();
1435 first.edge = myRoute->end(); // will be patched in replaceRoute
1436 first.lane = &parkingArea->getLane();
1437 first.parkingarea = parkingArea;
1438
1439 // patch via edges
1440 std::string newStopEdgeID = parkingArea->getLane().getEdge().getID();
1441 if (myParameter->via.size() > 0 && myParameter->via.front() != newStopEdgeID) {
1442 myParameter->via.erase(myParameter->via.begin());
1443 myParameter->via.insert(myParameter->via.begin(), newStopEdgeID);
1444 }
1445 return true;
1446}
1447
1448
1451 MSParkingArea* nextParkingArea = nullptr;
1452 if (!myStops.empty()) {
1454 MSStop stop = myStops.front();
1455 if (!stop.reached && stop.parkingarea != nullptr) {
1456 nextParkingArea = stop.parkingarea;
1457 }
1458 }
1459 return nextParkingArea;
1460}
1461
1462
1465 MSParkingArea* currentParkingArea = nullptr;
1466 if (isParking()) {
1467 currentParkingArea = myStops.begin()->parkingarea;
1468 }
1469 return currentParkingArea;
1470}
1471
1472
1473const std::vector<std::string>&
1476 return myParameter->parkingBadges;
1477 } else {
1479 }
1480}
1481
1482
1483double
1484MSBaseVehicle::basePos(const MSEdge* edge) const {
1485 double result = MIN2(getVehicleType().getLength() + POSITION_EPS, edge->getLength());
1486 if (hasStops()
1487 && myStops.front().edge == myRoute->begin()
1488 && (&myStops.front().lane->getEdge()) == *myStops.front().edge) {
1489 result = MIN2(result, MAX2(0.0, myStops.front().getEndPos(*this)));
1490 }
1491 return result;
1492}
1493
1494
1495MSLane*
1497 const std::string edgeID = SUMOXMLDefinitions::getEdgeIDFromLane(stop.lane);
1498 const MSEdge* edge = MSEdge::dictionary(edgeID);
1499 if (edge == nullptr || edge->getOppositeEdge() == nullptr || stop.lane.find("_") == std::string::npos) {
1500 return nullptr;
1501 }
1502 const int laneIndex = SUMOXMLDefinitions::getIndexFromLane(stop.lane);
1503 if (laneIndex < (edge->getNumLanes() + edge->getOppositeEdge()->getNumLanes())) {
1504 const int oppositeIndex = edge->getOppositeEdge()->getNumLanes() + edge->getNumLanes() - 1 - laneIndex;
1505 stop.edge = edgeID;
1506 return edge->getOppositeEdge()->getLanes()[oppositeIndex];
1507 }
1508 return nullptr;
1509}
1510
1511
1512bool
1513MSBaseVehicle::addStop(const SUMOVehicleParameter::Stop& stopPar, std::string& errorMsg, SUMOTime untilOffset,
1514 MSRouteIterator* searchStart) {
1515 MSStop stop(stopPar);
1516 if (stopPar.lane == "") {
1517 MSEdge* e = MSEdge::dictionary(stopPar.edge);
1518 stop.lane = e->getFirstAllowed(getVClass());
1519 if (stop.lane == nullptr) {
1520 errorMsg = "Vehicle '" + myParameter->id + "' is not allowed to stop on any lane of edge '" + stopPar.edge + "'.";
1521 return false;
1522 }
1523 } else {
1524 stop.lane = MSLane::dictionary(stopPar.lane);
1525 if (stop.lane == nullptr) {
1526 // must be an opposite stop
1527 SUMOVehicleParameter::Stop tmp = stopPar;
1528 stop.lane = interpretOppositeStop(tmp);
1529 assert(stop.lane != nullptr);
1530 }
1532 errorMsg = "Vehicle '" + myParameter->id + "' is not allowed to stop on lane '" + stopPar.lane + "'.";
1533 return false;
1534 }
1535 }
1537 stop.segment = MSGlobals::gMesoNet->getSegmentForEdge(stop.lane->getEdge(), stop.getEndPos(*this));
1538 if (stop.lane->isInternal()) {
1539 errorMsg = "Mesoscopic simulation does not allow stopping on internal edge '" + stopPar.edge + "' for vehicle '" + myParameter->id + "'.";
1540 return false;
1541 }
1542 }
1543 stop.initPars(stopPar);
1544 if (stopPar.until != -1) {
1545 // !!! it would be much cleaner to invent a constructor for stops which takes "until" as an argument
1546 const_cast<SUMOVehicleParameter::Stop&>(stop.pars).until += untilOffset;
1547 }
1548 if (stopPar.arrival != -1) {
1549 const_cast<SUMOVehicleParameter::Stop&>(stop.pars).arrival += untilOffset;
1550 }
1551 std::string stopType = "stop";
1552 std::string stopID = "";
1553 double parkingLength = stop.pars.endPos - stop.pars.startPos;
1554 if (stop.busstop != nullptr) {
1555 stopType = "busStop";
1556 stopID = stop.busstop->getID();
1557 parkingLength = stop.busstop->getParkingLength();
1558 } else if (stop.containerstop != nullptr) {
1559 stopType = "containerStop";
1560 stopID = stop.containerstop->getID();
1561 parkingLength = stop.containerstop->getParkingLength();
1562 } else if (stop.chargingStation != nullptr) {
1563 stopType = "chargingStation";
1564 stopID = stop.chargingStation->getID();
1565 parkingLength = stop.chargingStation->getParkingLength();
1566 } else if (stop.overheadWireSegment != nullptr) {
1567 stopType = "overheadWireSegment";
1568 stopID = stop.overheadWireSegment->getID();
1569 parkingLength = stop.overheadWireSegment->getParkingLength();
1570 } else if (stop.parkingarea != nullptr) {
1571 stopType = "parkingArea";
1572 stopID = stop.parkingarea->getID();
1573 }
1574 const std::string errorMsgStart = stopID == "" ? stopType : stopType + " '" + stopID + "'";
1575
1576 if (stop.pars.startPos < 0 || stop.pars.endPos > stop.lane->getLength()) {
1577 errorMsg = errorMsgStart + " for vehicle '" + myParameter->id + "' on lane '" + stop.lane->getID() + "' has an invalid position.";
1578 return false;
1579 }
1580 if (stopType != "stop" && stopType != "parkingArea" && myType->getLength() / 2. > parkingLength
1581 // do not warn for stops that fill the whole lane
1582 && parkingLength < stop.lane->getLength()
1583 // do not warn twice for the same stop
1584 && MSNet::getInstance()->warnOnce(stopType + ":" + stopID)) {
1585 errorMsg = errorMsgStart + " on lane '" + stop.lane->getID() + "' is too short for vehicle '" + myParameter->id + "'.";
1586 }
1587 if (stopType == "parkingArea" && !stop.parkingarea->accepts(this)) {
1588 // forbid access in case the parking requests other badges
1589 errorMsg = errorMsgStart + "on lane '" + stop.lane->getID() + "' forbids access because vehicle '" + myParameter->id + "' does not provide any valid badge.";
1590 return false;
1591 }
1592 const MSEdge* stopLaneEdge = &stop.lane->getEdge();
1593 const MSEdge* stopEdge;
1594 if (stopLaneEdge->getOppositeEdge() != nullptr && stopLaneEdge->getOppositeEdge()->getID() == stopPar.edge) {
1595 // stop lane is on the opposite side
1596 stopEdge = stopLaneEdge->getOppositeEdge();
1597 stop.isOpposite = true;
1598 } else {
1599 // if stop is on an internal edge the normal edge before the intersection is used
1600 stopEdge = stopLaneEdge->getNormalBefore();
1601 }
1602 MSRouteIterator succ = myCurrEdge + 1; // we're using the address but only within the scope of this function (and recursive calls)
1603 if (searchStart == nullptr) {
1604 searchStart = &myCurrEdge;
1605 if (stopLaneEdge->isNormal() && getLane() != nullptr && getLane()->isInternal()) {
1606 // already on the intersection but myCurrEdge is before it
1607 searchStart = &succ;
1608 }
1609 }
1610#ifdef DEBUG_ADD_STOP
1611 if (DEBUG_COND) {
1612 std::cout << "addStop desc=" << stop.getDescription() << " stopEdge=" << stopEdge->getID()
1613 << " searchStart=" << ((*searchStart) == myRoute->end() ? "END" : (**searchStart)->getID())
1614 << " index=" << (int)((*searchStart) - myRoute->begin()) << " route=" << toString(myRoute->getEdges())
1615 << "\n";
1616 }
1617#endif
1618 stop.edge = std::find(*searchStart, myRoute->end(), stopEdge);
1619 MSRouteIterator prevStopEdge = myCurrEdge;
1620 const MSEdge* prevEdge = (getLane() == nullptr ? getEdge() : &getLane()->getEdge());
1621 double prevStopPos = getPositionOnLane();
1622 // where to insert the stop
1623 std::list<MSStop>::iterator iter = myStops.begin();
1624 if (stopPar.index == STOP_INDEX_END || stopPar.index >= static_cast<int>(myStops.size()) || stopPar.index == STOP_INDEX_REPEAT) {
1625 iter = myStops.end();
1626 if (myStops.size() > 0 && myStops.back().edge >= *searchStart) {
1627 prevStopEdge = myStops.back().edge;
1628 prevEdge = &myStops.back().lane->getEdge();
1629 prevStopPos = myStops.back().pars.endPos;
1630 stop.edge = std::find(prevStopEdge, myRoute->end(), stopEdge);
1631 if (prevStopEdge == stop.edge // laneEdge check is insufficient for looped routes
1632 && prevEdge == &stop.lane->getEdge() // route iterator check insufficient for internal lane stops
1633 && (prevStopPos > stop.pars.endPos ||
1634 (prevStopPos == stop.pars.endPos && stopPar.index == STOP_INDEX_REPEAT))) {
1635 stop.edge = std::find(prevStopEdge + 1, myRoute->end(), stopEdge);
1636 }
1637#ifdef DEBUG_ADD_STOP
1638 if (DEBUG_COND) {
1639 std::cout << " (@end) prevStopEdge=" << (*prevStopEdge)->getID() << " prevStopPos=" << prevStopPos << " index=" << (int)(prevStopEdge - myRoute->begin())
1640 << " foundIndex=" << (stop.edge == myRoute->end() ? -1 : (int)(stop.edge - myRoute->begin())) << "\n";
1641 }
1642#endif
1643 }
1644 // skip a number of occurences of stopEdge in looped route
1645 int skipLooped = stopPar.index - static_cast<int>(myStops.size());
1646 for (int j = 0; j < skipLooped; j++) {
1647 auto nextIt = std::find(stop.edge + 1, myRoute->end(), stopEdge);
1648 if (nextIt == myRoute->end()) {
1649 if (std::find(myRoute->begin(), stop.edge, stopEdge) != stop.edge) {
1650 // only warn if the route loops over the stop edge at least once
1651 errorMsg = errorMsgStart + " for vehicle '" + myParameter->id + "' could not skip " + toString(skipLooped) + " occurences of stop edge '" + stopEdge->getID() + "' in looped route.";
1652 }
1653 break;
1654 } else {
1655 stop.edge = nextIt;
1656 }
1657 }
1658 } else {
1659 if (stopPar.index == STOP_INDEX_FIT) {
1660 while (iter != myStops.end() && (iter->edge < stop.edge ||
1661 (iter->pars.endPos < stop.pars.endPos && iter->edge == stop.edge) ||
1662 (stop.lane->getEdge().isInternal() && iter->edge == stop.edge))) {
1663 prevStopEdge = iter->edge;
1664 prevStopPos = iter->pars.endPos;
1665 ++iter;
1666 }
1667 } else {
1668 int index = stopPar.index;
1669 while (index > 0) {
1670 prevStopEdge = iter->edge;
1671 prevStopPos = iter->pars.endPos;
1672 ++iter;
1673 --index;
1674 }
1675#ifdef DEBUG_ADD_STOP
1676 if (DEBUG_COND) {
1677 std::cout << " (@fit) prevStopEdge=" << (*prevStopEdge)->getID() << " index=" << (int)(prevStopEdge - myRoute->begin()) << "\n";
1678 }
1679#endif
1680 stop.edge = std::find(prevStopEdge, myRoute->end(), stopEdge);
1681 }
1682 }
1683 const bool wasTooClose = errorMsg != "" && errorMsg.find("too close") != std::string::npos;
1684 if (stop.edge == myRoute->end()) {
1685 if (!wasTooClose) {
1686 errorMsg = errorMsgStart + " for vehicle '" + myParameter->id + "' on lane '" + stop.lane->getID() + "' is not downstream the current route.";
1687 }
1688 return false;
1689 }
1690
1691 const bool tooClose = (prevStopEdge == stop.edge && prevEdge == &stop.lane->getEdge() &&
1692 prevStopPos + (iter == myStops.begin() ? getBrakeGap() : 0) > stop.pars.endPos + POSITION_EPS);
1693
1694 if (prevStopEdge > stop.edge ||
1695 // a collision-stop happens after vehicle movement and may move the
1696 // vehicle backwards on its lane (prevStopPos is the vehicle position)
1697 (tooClose && !stop.pars.collision)
1698 || (stop.lane->getEdge().isInternal() && stop.lane->getNextNormal() != *(stop.edge + 1))) {
1699 // check if the edge occurs again later in the route
1700 //std::cout << " could not add stop " << errorMsgStart << " prevStops=" << myStops.size() << " searchStart=" << (*searchStart - myRoute->begin()) << " route=" << toString(myRoute->getEdges()) << "\n";
1701 if (tooClose && prevStopPos <= stop.pars.endPos + POSITION_EPS) {
1702 errorMsg = errorMsgStart + " for vehicle '" + myParameter->id + "' on lane '" + stop.pars.lane + "' is too close to brake.";
1703 }
1704 MSRouteIterator next = stop.edge + 1;
1705 return addStop(stopPar, errorMsg, untilOffset, &next);
1706 }
1707 if (wasTooClose) {
1708 errorMsg = "";
1709 }
1710 // David.C:
1711 //if (!stop.parking && (myCurrEdge == stop.edge && myState.myPos > stop.endPos - getCarFollowModel().brakeGap(myState.mySpeed))) {
1712 const double endPosOffset = stop.lane->getEdge().isInternal() ? (*stop.edge)->getLength() : 0;
1713 const double distToStop = stop.pars.endPos + endPosOffset - getPositionOnLane();
1714 if (stop.pars.collision && !handleCollisionStop(stop, distToStop)) {
1715 return false;
1716 }
1717 if (!hasDeparted() && myCurrEdge == stop.edge) {
1718 double pos = -1;
1720 pos = myParameter->departPos;
1721 if (pos < 0.) {
1722 pos += (*myCurrEdge)->getLength();
1723 }
1724 }
1726 pos = MIN2(stop.pars.endPos + endPosOffset, basePos(*myCurrEdge));
1727 }
1728 if (pos > stop.pars.endPos + endPosOffset) {
1729 if (stop.edge != myRoute->end()) {
1730 // check if the edge occurs again later in the route
1731 MSRouteIterator next = stop.edge + 1;
1732 return addStop(stopPar, errorMsg, untilOffset, &next);
1733 }
1734 errorMsg = errorMsgStart + " for vehicle '" + myParameter->id + "' on lane '" + stop.lane->getID() + "' is before departPos.";
1735 return false;
1736 }
1737 }
1738 if (iter != myStops.begin()) {
1739 std::list<MSStop>::iterator iter2 = iter;
1740 iter2--;
1741 if (stop.getUntil() >= 0 && iter2->getUntil() > stop.getUntil()
1742 && (!MSGlobals::gUseStopEnded || iter2->pars.ended < 0 || stop.pars.ended >= 0)) {
1743 errorMsg = errorMsgStart + " for vehicle '" + myParameter->id + "' on lane '" + stop.lane->getID()
1744 + "' set to end at " + time2string(stop.getUntil())
1745 + " earlier than previous stop at " + time2string(iter2->getUntil()) + ".";
1746 }
1747 if (stop.pars.arrival >= 0 && iter2->pars.arrival > stop.pars.arrival) {
1748 errorMsg = errorMsgStart + " for vehicle '" + myParameter->id + "' on lane '" + stop.lane->getID()
1749 + "' set to start at " + time2string(stop.pars.arrival)
1750 + " earlier than previous stop end at " + time2string(iter2->getUntil()) + ".";
1751 }
1752 if (stop.pars.arrival >= 0 && iter2->pars.arrival > stop.pars.arrival) {
1753 errorMsg = errorMsgStart + " for vehicle '" + myParameter->id + "' on lane '" + stop.lane->getID()
1754 + "' set to start at " + time2string(stop.pars.arrival)
1755 + " earlier than previous stop arrival at " + time2string(iter2->pars.arrival) + ".";
1756 }
1757 } else {
1758 if (stop.getUntil() >= 0 && getParameter().depart > stop.getUntil()
1759 && (!MSGlobals::gUseStopEnded || stop.pars.ended < 0)) {
1760 errorMsg = errorMsgStart + " for vehicle '" + myParameter->id + "' on lane '" + stop.lane->getID()
1761 + "' set to end at " + time2string(stop.getUntil())
1762 + " earlier than departure at " + time2string(getParameter().depart) + ".";
1763 }
1764 }
1765 if (stop.getUntil() >= 0 && stop.getArrival() > stop.getUntil() && errorMsg == "") {
1766 errorMsg = errorMsgStart + " for vehicle '" + myParameter->id + "' on lane '" + stop.lane->getID()
1767 + "' set to end at " + time2string(stop.getUntil())
1768 + " earlier than arrival at " + time2string(stop.getArrival()) + ".";
1769 }
1770 setSkips(stop, (int)myStops.size());
1771 myStops.insert(iter, stop);
1772 if (stopPar.tripId != "") {
1774 }
1775 //std::cout << " added stop " << errorMsgStart << " totalStops=" << myStops.size() << " searchStart=" << (*searchStart - myRoute->begin())
1776 // << " routeIndex=" << (stop.edge - myRoute->begin())
1777 // << " stopIndex=" << std::distance(myStops.begin(), iter)
1778 // << " route=" << toString(myRoute->getEdges()) << "\n";
1779 return true;
1780}
1781
1782
1783void
1784MSBaseVehicle::setSkips(MSStop& stop, int prevActiveStops) {
1785 if (hasDeparted() && stop.edge > myRoute->begin()) {
1786 // if the route is looped we must patch the index to ensure that state
1787 // loading (and vehroute-output) encode the correct number of skips
1788 int foundSkips = 0;
1789 MSRouteIterator itPrev;
1790 double prevEndPos;
1791 if (prevActiveStops > 0) {
1792 assert((int)myStops.size() >= prevActiveStops);
1793 auto prevStopIt = myStops.begin();
1794 std::advance(prevStopIt, prevActiveStops - 1);
1795 const MSStop& prev = *prevStopIt;
1796 itPrev = prev.edge;
1797 prevEndPos = prev.pars.endPos;
1798 } else if (myPastStops.size() > 0) {
1799 itPrev = myRoute->begin() + myPastStops.back().routeIndex;
1800 prevEndPos = myPastStops.back().endPos;
1801 } else {
1802 itPrev = myRoute->begin() + myParameter->departEdge;
1803 prevEndPos = myDepartPos;
1804 }
1805 //auto itPrevOrig = itPrev;
1806 if (*itPrev == *stop.edge && prevEndPos > stop.pars.endPos) {
1807 itPrev++;
1808 }
1809 //std::cout << SIMTIME << " veh=" << getID() << " prevActive=" << prevActiveStops << " edge=" << (*stop.edge)->getID() << " routeIndex=" << (stop.edge - myRoute->begin()) << " prevIndex=" << (itPrev - myRoute->begin()) << "\n";
1810 while (itPrev < stop.edge) {
1811 if (*itPrev == *stop.edge) {
1812 foundSkips++;
1813 }
1814 itPrev++;
1815 }
1816 int newIndex = STOP_INDEX_END;
1817 if (foundSkips > 0) {
1818 //if (getID() == "77_0_0") {
1819 // std::cout << SIMTIME << " veh=" << getID() << " past=" << myPastStops.size() << " prevActive=" << prevActiveStops
1820 // << " edge=" << (*stop.edge)->getID() << " routeIndex=" << (stop.edge - myRoute->begin())
1821 // << " prevEdge=" << (*itPrevOrig)->getID()
1822 // << " prevIndex=" << (itPrevOrig - myRoute->begin())
1823 // << " skips=" << foundSkips << "\n";
1824 //}
1825 newIndex = (int)myPastStops.size() + prevActiveStops + foundSkips;
1826 }
1827 const_cast<SUMOVehicleParameter::Stop&>(stop.pars).index = newIndex;
1828 }
1829}
1830
1831
1834 for (int i = 0; i < (int)myMoveReminders.size();) {
1835 auto rem = &myMoveReminders[i];
1836 if (rem->first->notifyReroute(*this)) {
1837#ifdef _DEBUG
1838 if (myTraceMoveReminders) {
1839 traceMoveReminder("notifyReroute", rem->first, rem->second, true);
1840 }
1841#endif
1842 ++i;
1843 } else {
1844#ifdef _DEBUG
1845 if (myTraceMoveReminders) {
1846 traceMoveReminder("notifyReroute", rem->first, rem->second, false);
1847 }
1848#endif
1849 myMoveReminders.erase(myMoveReminders.begin() + i);
1850 }
1851 }
1853 // event only called once
1854 return 0;
1855}
1856
1857
1858void
1859MSBaseVehicle::addStops(const bool ignoreStopErrors, MSRouteIterator* searchStart, bool addRouteStops) {
1860 if (addRouteStops) {
1861 for (const SUMOVehicleParameter::Stop& stop : myRoute->getStops()) {
1862 std::string errorMsg;
1863 if (!addStop(stop, errorMsg, myParameter->depart, searchStart) && !ignoreStopErrors) {
1864 throw ProcessError(errorMsg);
1865 }
1866 if (errorMsg != "") {
1867 WRITE_WARNING(errorMsg);
1868 }
1869 }
1870 }
1872 for (const SUMOVehicleParameter::Stop& stop : myParameter->stops) {
1873 std::string errorMsg;
1874 if (!addStop(stop, errorMsg, untilOffset, searchStart) && !ignoreStopErrors) {
1875 throw ProcessError(errorMsg);
1876 }
1877 if (errorMsg != "") {
1878 WRITE_WARNING(errorMsg);
1879 }
1880 }
1881}
1882
1883
1884bool
1887 int i = 0;
1888 bool ok = true;
1889 for (const MSStop& stop : myStops) {
1890 MSRouteIterator it;
1891 if (stop.lane->isInternal()) {
1892 // find the normal predecessor and ensure that the next route edge
1893 // matches the successor of the internal edge successor
1894 it = std::find(start, myRoute->end(), stop.lane->getEdge().getNormalBefore());
1895 if (it != myRoute->end() && (
1896 it + 1 == myRoute->end() || *(it + 1) != stop.lane->getEdge().getNormalSuccessor())) {
1897 it = myRoute->end(); // signal failure
1898 }
1899 } else {
1900 it = std::find(start, myRoute->end(), &stop.lane->getEdge());
1901 }
1902 if (it == myRoute->end()) {
1903 if (!silent) {
1904 WRITE_ERRORF("Stop % on edge '%' is not found after edge '%' (% after current) for vehicle '%' at time=%.",
1905 i, stop.lane->getEdge().getID(), (*start)->getID(), toString(start - myCurrEdge), getID(), time2string(SIMSTEP));
1906 }
1907 ok = false;
1908 } else {
1909 MSRouteIterator it2;
1910 for (it2 = myRoute->begin(); it2 != myRoute->end(); it2++) {
1911 if (it2 == stop.edge) {
1912 break;
1913 }
1914 }
1915 if (it2 == myRoute->end()) {
1916 if (!silent) {
1917 WRITE_ERRORF("Stop % on edge '%' used invalid route index for vehicle '%' at time=%.",
1918 i, stop.lane->getEdge().getID(), getID(), time2string(SIMSTEP));
1919 }
1920 ok = false;
1921 } else if (it2 < start) {
1922 if (!silent) {
1923 WRITE_ERRORF("Stop % on edge '%' used invalid (relative) route index % expected after % for vehicle '%' at time=%.",
1924 i, stop.lane->getEdge().getID(), toString(it2 - myCurrEdge), toString(start - myCurrEdge), getID(), time2string(SIMSTEP));
1925 }
1926 ok = false;
1927 } else {
1928 start = stop.edge;
1929 }
1930 }
1931 i++;
1932 }
1933 return ok;
1934}
1935
1936
1937std::vector<MSBaseVehicle::StopEdgeInfo>
1938MSBaseVehicle::getStopEdges(double& firstPos, double& lastPos, std::set<int>& jumps) const {
1939 assert(haveValidStopEdges());
1940 std::vector<StopEdgeInfo> result;
1941 const MSStop* prev = nullptr;
1942 const MSEdge* internalSuccessor = nullptr;
1943 for (const MSStop& stop : myStops) {
1944 if (stop.reached) {
1945 if (stop.pars.jump >= 0) {
1946 jumps.insert((int)result.size());
1947 }
1948 continue;
1949 }
1950 const double stopPos = stop.getEndPos(*this);
1951 if ((prev == nullptr
1952 || prev->edge != stop.edge
1953 || (prev->lane == stop.lane && prev->getEndPos(*this) > stopPos))
1954 && *stop.edge != internalSuccessor) {
1955 result.push_back(StopEdgeInfo(*stop.edge, stop.pars.priority, stop.getArrivalFallback(), stopPos));
1956 if (stop.lane->isInternal()) {
1957 internalSuccessor = stop.lane->getNextNormal();
1958 result.push_back(StopEdgeInfo(internalSuccessor, stop.pars.priority, stop.getArrivalFallback(), stopPos));
1959 } else {
1960 internalSuccessor = nullptr;
1961 }
1962 } else if (prev != nullptr && prev->edge == stop.edge) {
1963 result.back().priority = addStopPriority(result.back().priority, stop.pars.priority);
1964 }
1965 prev = &stop;
1966 if (firstPos == INVALID_DOUBLE) {
1967 if (stop.parkingarea != nullptr) {
1968 firstPos = MAX2(0., stopPos);
1969 } else {
1970 firstPos = stopPos;
1971 }
1972 }
1973 lastPos = stopPos;
1974 if (stop.pars.jump >= 0) {
1975 jumps.insert((int)result.size() - 1);
1976 }
1977 }
1978 //std::cout << "getStopEdges veh=" << getID() << " result=" << toString(result) << "\n";
1979 return result;
1980}
1981
1982
1983double
1984MSBaseVehicle::addStopPriority(double p1, double p2) {
1985 if (p1 < 0 || p2 < 0) {
1986 return p1;
1987 }
1988 return p1 + p2;
1989}
1990
1991std::vector<std::pair<int, double> >
1993 std::vector<std::pair<int, double> > result;
1994 for (std::list<MSStop>::const_iterator iter = myStops.begin(); iter != myStops.end(); ++iter) {
1995 result.push_back(std::make_pair(
1996 (int)(iter->edge - myRoute->begin()),
1997 iter->getEndPos(*this)));
1998 }
1999 return result;
2000}
2001
2002
2003const MSStop&
2005 assert(myStops.size() > 0);
2006 return myStops.front();
2007}
2008
2009MSStop&
2011 assert(myStops.size() > 0);
2012 return myStops.front();
2013}
2014
2017 if (isStopped()) {
2018 return myStops.front().duration;
2019 } else {
2020 return 0;
2021 }
2022}
2023
2024
2025MSStop&
2026MSBaseVehicle::getStop(int nextStopIndex) {
2027 if (nextStopIndex < 0 || (int)myStops.size() <= nextStopIndex) {
2028 throw InvalidArgument(TLF("Invalid stop index % (has % stops).", nextStopIndex, myStops.size()));
2029 }
2030 auto stopIt = myStops.begin();
2031 std::advance(stopIt, nextStopIndex);
2032 return *stopIt;
2033}
2034
2035
2038 if (hasStops()) {
2039 return &myStops.front().pars;
2040 }
2041 return nullptr;
2042}
2043
2044
2045bool
2047 //if the stop exists update the duration
2048 for (std::list<MSStop>::iterator iter = myStops.begin(); iter != myStops.end(); iter++) {
2049 if (iter->lane->getID() == stop.lane && fabs(iter->pars.endPos - stop.endPos) < POSITION_EPS) {
2050 // update existing stop
2051 if (stop.duration == 0 && stop.until < 0 && !iter->reached) {
2052 myStops.erase(iter);
2053 } else {
2054 iter->duration = stop.duration;
2055 iter->triggered = stop.triggered;
2056 iter->containerTriggered = stop.containerTriggered;
2057 const_cast<SUMOVehicleParameter::Stop&>(iter->pars).until = stop.until;
2058 const_cast<SUMOVehicleParameter::Stop&>(iter->pars).parking = stop.parking;
2059 }
2060 return true;
2061 }
2062 }
2063 const bool result = addStop(stop, errorMsg);
2064 if (result) {
2066 myParameter->stops.push_back(stop);
2067 }
2068 return result;
2069}
2070
2071
2072void
2079
2080
2081bool
2083 if (hasStops() && nextStopIndex < (int)myStops.size()) {
2084 if (nextStopIndex == 0 && isStopped()) {
2086 } else {
2087 auto stopIt = myStops.begin();
2088 std::advance(stopIt, nextStopIndex);
2089 myStops.erase(stopIt);
2090 }
2091 if (!hasDeparted() && (int)myParameter->stops.size() > nextStopIndex) {
2092 // stops will be rebuilt from scratch on rerouting so we must patch the stops in myParameter
2093 auto stopIt2 = myParameter->stops.begin();
2094 std::advance(stopIt2, nextStopIndex);
2095 const_cast<SUMOVehicleParameter*>(myParameter)->stops.erase(stopIt2);
2096 }
2097 return true;
2098 } else {
2099 return false;
2100 }
2101}
2102
2103
2104bool
2105MSBaseVehicle::replaceStop(int nextStopIndex, SUMOVehicleParameter::Stop stop, const std::string& info, bool teleport, std::string& errorMsg) {
2106 const int n = (int)myStops.size();
2107 if (nextStopIndex < 0 || nextStopIndex >= n) {
2108 errorMsg = TLF("invalid nextStopIndex % for % remaining stops", nextStopIndex, n);
2109 return false;
2110 }
2111 if (nextStopIndex == 0 && isStopped()) {
2112 errorMsg = TL("cannot replace reached stop");
2113 return false;
2114 }
2116 MSLane* stopLane = MSLane::dictionary(stop.lane);
2117 MSEdge* stopEdge = &stopLane->getEdge();
2118
2119 auto itStop = myStops.begin();
2120 std::advance(itStop, nextStopIndex);
2121 MSStop& replacedStop = *itStop;
2122
2123 // check parking access rights
2124 if (stop.parkingarea != "") {
2126 if (pa != nullptr && !pa->accepts(this)) {
2127 errorMsg = TLF("vehicle '%' does not have the right badge to access parkingArea '%'", getID(), stop.parkingarea);
2128 return false;
2129 }
2130 }
2131
2132 if (replacedStop.lane == stopLane && replacedStop.pars.endPos == stop.endPos && !teleport) {
2133 // only replace stop attributes
2134 const_cast<SUMOVehicleParameter::Stop&>(replacedStop.pars) = stop;
2135 replacedStop.initPars(stop);
2136 return true;
2137 }
2138
2139 if (!stopLane->allowsVehicleClass(getVClass(), myRoutingMode)) {
2140 errorMsg = TLF("disallowed stop lane '%'", stopLane->getID());
2141 return false;
2142 }
2143
2144 const ConstMSEdgeVector& oldEdges = getRoute().getEdges();
2145 std::vector<MSStop> stops(myStops.begin(), myStops.end());
2146 const int junctionOffset = getLane() != nullptr && getLane()->isInternal() ? 1 : 0;
2147 MSRouteIterator itStart = nextStopIndex == 0 ? getCurrentRouteEdge() + junctionOffset : stops[nextStopIndex - 1].edge;
2148 double startPos = nextStopIndex == 0 ? getPositionOnLane() : stops[nextStopIndex - 1].pars.endPos;
2149 MSRouteIterator itEnd = nextStopIndex == n - 1 ? oldEdges.end() - 1 : stops[nextStopIndex + 1].edge;
2150 auto endPos = nextStopIndex == n - 1 ? getArrivalPos() : stops[nextStopIndex + 1].pars.endPos;
2152
2153 bool newDestination = nextStopIndex == n - 1 && stops[nextStopIndex].edge == oldEdges.end() - 1;
2154
2155 ConstMSEdgeVector toNewStop;
2156 if (!teleport) {
2157 router.compute(*itStart, startPos, stopEdge, stop.endPos, this, t, toNewStop, true);
2158 if (toNewStop.size() == 0) {
2159 errorMsg = TLF("no route found from edge '%' to stop edge '%'", (*itStart)->getID(), stopEdge->getID());
2160 return false;
2161 }
2162 }
2163
2164 ConstMSEdgeVector fromNewStop;
2165 if (!newDestination) {
2166 router.compute(stopEdge, stop.endPos, *itEnd, endPos, this, t, fromNewStop, true);
2167 if (fromNewStop.size() == 0) {
2168 errorMsg = TLF("no route found from stop edge '%' to edge '%'", stopEdge->getID(), (*itEnd)->getID());
2169 return false;
2170 }
2171 }
2172
2173 const_cast<SUMOVehicleParameter::Stop&>(replacedStop.pars) = stop;
2174 replacedStop.initPars(stop);
2175 replacedStop.edge = myRoute->end(); // will be patched in replaceRoute
2176 replacedStop.lane = stopLane;
2178 replacedStop.segment = MSGlobals::gMesoNet->getSegmentForEdge(replacedStop.lane->getEdge(), replacedStop.getEndPos(*this));
2179 if (replacedStop.lane->isInternal()) {
2180 errorMsg = TLF("Mesoscopic simulation does not allow stopping on internal edge '%' for vehicle '%'.", stop.edge, getID());
2181 return false;
2182 }
2183 }
2184
2185 ConstMSEdgeVector oldRemainingEdges(myCurrEdge, getRoute().end());
2186 ConstMSEdgeVector newEdges; // only remaining
2187 newEdges.insert(newEdges.end(), myCurrEdge, itStart);
2188 if (!teleport) {
2189 newEdges.insert(newEdges.end(), toNewStop.begin(), toNewStop.end() - 1);
2190 } else {
2191 newEdges.push_back(*itStart);
2192 }
2193 if (!newDestination) {
2194 newEdges.insert(newEdges.end(), fromNewStop.begin(), fromNewStop.end() - 1);
2195 newEdges.insert(newEdges.end(), itEnd, oldEdges.end());
2196 } else {
2197 newEdges.push_back(stopEdge);
2198 }
2199 //std::cout << SIMTIME << " replaceStop veh=" << getID()
2200 // << " teleport=" << teleport
2201 // << " busStop=" << stop.busstop
2202 // << " oldEdges=" << oldRemainingEdges.size()
2203 // << " newEdges=" << newEdges.size()
2204 // << " toNewStop=" << toNewStop.size()
2205 // << " fromNewStop=" << fromNewStop.size()
2206 // << "\n";
2207
2208 const double routeCost = router.recomputeCosts(newEdges, this, t);
2209 const double previousCost = router.recomputeCosts(oldRemainingEdges, this, t);
2210 const double savings = previousCost - routeCost;
2211 if (!hasDeparted() && (int)myParameter->stops.size() > nextStopIndex) {
2212 // stops will be rebuilt from scratch so we must patch the stops in myParameter
2213 const_cast<SUMOVehicleParameter*>(myParameter)->stops[nextStopIndex] = stop;
2214 }
2215 if (teleport) {
2216 // let the vehicle jump rather than teleport
2217 // we add a jump-stop at the end of the edge (unless the vehicle is
2218 // already configure to jump before the replaced stop)
2219 if (!insertJump(nextStopIndex, itStart, errorMsg)) {
2220 return false;
2221 };
2222 }
2223 return replaceRouteEdges(newEdges, routeCost, savings, info, !hasDeparted(), false, false, &errorMsg);
2224}
2225
2226
2227bool
2228MSBaseVehicle::rerouteBetweenStops(int nextStopIndex, const std::string& info, bool teleport, std::string& errorMsg) {
2229 const int n = (int)myStops.size();
2230 if (nextStopIndex < 0 || nextStopIndex > n) {
2231 errorMsg = TLF("invalid nextStopIndex % for % remaining stops", nextStopIndex, n);
2232 return false;
2233 }
2234 if (nextStopIndex == 0 && isStopped()) {
2235 errorMsg = TL("cannot reroute towards reached stop");
2236 return false;
2237 }
2239
2240 const ConstMSEdgeVector& oldEdges = getRoute().getEdges();
2241 std::vector<MSStop> stops(myStops.begin(), myStops.end());
2242 const int junctionOffset = getLane() != nullptr && getLane()->isInternal() ? 1 : 0;
2243 MSRouteIterator itStart = nextStopIndex == 0 ? getCurrentRouteEdge() + junctionOffset : stops[nextStopIndex - 1].edge;
2244 double startPos = nextStopIndex == 0 ? getPositionOnLane() : stops[nextStopIndex - 1].pars.endPos;
2245 MSRouteIterator itEnd = nextStopIndex == n ? oldEdges.end() - 1 : stops[nextStopIndex].edge;
2246 auto endPos = nextStopIndex == n ? getArrivalPos() : stops[nextStopIndex].pars.endPos;
2248
2249 ConstMSEdgeVector newBetween;
2250 if (!teleport) {
2251 router.compute(*itStart, startPos, *itEnd, endPos, this, t, newBetween, true);
2252 if (newBetween.size() == 0) {
2253 errorMsg = TLF("no route found from edge '%' to stop edge '%'", (*itStart)->getID(), (*itEnd)->getID());
2254 return false;
2255 }
2256 }
2257
2258 ConstMSEdgeVector oldRemainingEdges(myCurrEdge, getRoute().end());
2259 ConstMSEdgeVector newEdges; // only remaining
2260 newEdges.insert(newEdges.end(), myCurrEdge, itStart);
2261 if (!teleport) {
2262 newEdges.insert(newEdges.end(), newBetween.begin(), newBetween.end() - 1);
2263 } else {
2264 newEdges.push_back(*itStart);
2265 }
2266 newEdges.insert(newEdges.end(), itEnd, oldEdges.end());
2267 //std::cout << SIMTIME << " rerouteBetweenStops veh=" << getID()
2268 // << " oldEdges=" << oldRemainingEdges.size()
2269 // << " newEdges=" << newEdges.size()
2270 // << " toNewStop=" << toNewStop.size()
2271 // << " fromNewStop=" << fromNewStop.size()
2272 // << "\n";
2273
2274 const double routeCost = router.recomputeCosts(newEdges, this, t);
2275 const double previousCost = router.recomputeCosts(oldRemainingEdges, this, t);
2276 const double savings = previousCost - routeCost;
2277
2278 if (teleport) {
2279 // let the vehicle jump rather than teleport
2280 // we add a jump-stop at the end of the edge (unless the vehicle is
2281 // already configure to jump before the replaced stop)
2282 if (!insertJump(nextStopIndex, itStart, errorMsg)) {
2283 return false;
2284 };
2285 }
2286 return replaceRouteEdges(newEdges, routeCost, savings, info, !hasDeparted(), false, false, &errorMsg);
2287}
2288
2289
2290bool
2291MSBaseVehicle::insertJump(int nextStopIndex, MSRouteIterator itStart, std::string& errorMsg) {
2292 bool needJump = true;
2293 if (nextStopIndex > 0) {
2294 auto itPriorStop = myStops.begin();
2295 std::advance(itPriorStop, nextStopIndex - 1);
2296 const MSStop& priorStop = *itPriorStop;
2297 if (priorStop.pars.jump >= 0) {
2298 needJump = false;
2299 }
2300 }
2301 if (needJump) {
2302 SUMOVehicleParameter::Stop jumpStopPars;
2303 jumpStopPars.endPos = (*itStart)->getLength();
2304 jumpStopPars.speed = 1000;
2305 jumpStopPars.jump = 0;
2306 jumpStopPars.edge = (*itStart)->getID();
2308 MSLane* jumpStopLane = nullptr;
2309 for (MSLane* cand : (*itStart)->getLanes()) {
2310 if (cand->allowsVehicleClass(getVClass())) {
2311 jumpStopLane = cand;
2312 break;
2313 }
2314 }
2315 if (jumpStopLane == nullptr) {
2316 errorMsg = TL("unable to replace stop with teleporting");
2317 return false;
2318 }
2319 auto itStop = myStops.begin();
2320 std::advance(itStop, nextStopIndex);
2321 MSStop jumpStop(jumpStopPars);
2322 jumpStop.initPars(jumpStopPars);
2323 jumpStop.lane = jumpStopLane;
2324 jumpStop.edge = myRoute->end(); // will be patched in replaceRoute
2325 myStops.insert(itStop, jumpStop);
2326 if (!hasDeparted() && (int)myParameter->stops.size() > nextStopIndex) {
2327 // stops will be rebuilt from scratch so we must patch the stops in myParameter
2328 auto it = myParameter->stops.begin() + nextStopIndex;
2329 const_cast<SUMOVehicleParameter*>(myParameter)->stops.insert(it, jumpStopPars);
2330 }
2331 }
2332 return true;
2333}
2334
2335
2336bool
2337MSBaseVehicle::insertStop(int nextStopIndex, SUMOVehicleParameter::Stop stop, const std::string& info, bool teleport, std::string& errorMsg) {
2338 const int n = (int)myStops.size();
2339 if (nextStopIndex < 0 || nextStopIndex > n) {
2340 errorMsg = TLF("invalid nextStopIndex % for % remaining stops", nextStopIndex, n);
2341 return false;
2342 }
2343 if (nextStopIndex == 0 && isStopped()) {
2344 errorMsg = TL("cannot insert stop before the currently reached stop");
2345 return false;
2346 }
2348 MSLane* stopLane = MSLane::dictionary(stop.lane);
2349 MSEdge* stopEdge = &stopLane->getEdge();
2350
2351 if (!stopLane->allowsVehicleClass(getVClass(), myRoutingMode)) {
2352 errorMsg = TLF("disallowed stop lane '%'", stopLane->getID());
2353 return false;
2354 }
2355
2356 // check parking access rights
2357 if (stop.parkingarea != "") {
2359 if (pa != nullptr && !pa->accepts(this)) {
2360 errorMsg = TLF("Vehicle '%' does not have the right badge to access parkingArea '%'.", getID(), stop.parkingarea);
2361 return false;
2362 }
2363 }
2364
2365 const ConstMSEdgeVector& oldEdges = getRoute().getEdges();
2366 std::vector<MSStop> stops(myStops.begin(), myStops.end());
2367 const int junctionOffset = getLane() != nullptr && getLane()->isInternal() ? 1 : 0;
2368 MSRouteIterator itStart = nextStopIndex == 0 ? getCurrentRouteEdge() + junctionOffset : stops[nextStopIndex - 1].edge;
2369 double startPos = nextStopIndex == 0 ? getPositionOnLane() : stops[nextStopIndex - 1].pars.endPos;
2370 MSRouteIterator itEnd = nextStopIndex == n ? oldEdges.end() - 1 : stops[nextStopIndex].edge;
2371 auto endPos = nextStopIndex == n ? getArrivalPos() : stops[nextStopIndex].pars.endPos;
2373
2374 bool newDestination = nextStopIndex == n && stopEdge == oldEdges.back();
2375
2376 ConstMSEdgeVector toNewStop;
2377 if (!teleport) {
2378 router.compute(*itStart, startPos, stopEdge, stop.endPos, this, t, toNewStop, true);
2379 if (toNewStop.size() == 0) {
2380 errorMsg = TLF("no route found from edge '%' to stop edge '%'", (*itStart)->getID(), stopEdge->getID());
2381 return false;
2382 }
2383 }
2384
2385 ConstMSEdgeVector fromNewStop;
2386 if (!newDestination) {
2387 router.compute(stopEdge, stop.endPos, *itEnd, endPos, this, t, fromNewStop, true);
2388 if (fromNewStop.size() == 0) {
2389 errorMsg = TLF("no route found from stop edge '%' to edge '%'", stopEdge->getID(), (*itEnd)->getID());
2390 return false;
2391 }
2392 }
2393
2394 auto itStop = myStops.begin();
2395 std::advance(itStop, nextStopIndex);
2396 MSStop newStop(stop);
2397 newStop.initPars(stop);
2398 newStop.edge = myRoute->end(); // will be patched in replaceRoute
2399 newStop.lane = stopLane;
2401 newStop.segment = MSGlobals::gMesoNet->getSegmentForEdge(newStop.lane->getEdge(), newStop.getEndPos(*this));
2402 if (newStop.lane->isInternal()) {
2403 errorMsg = TLF("Mesoscopic simulation does not allow stopping on internal edge '%' for vehicle '%'.", stop.edge, getID());
2404 return false;
2405 }
2406 }
2407 myStops.insert(itStop, newStop);
2408
2409 ConstMSEdgeVector oldRemainingEdges(myCurrEdge, getRoute().end());
2410 ConstMSEdgeVector newEdges; // only remaining
2411 newEdges.insert(newEdges.end(), myCurrEdge, itStart);
2412 if (!teleport) {
2413 newEdges.insert(newEdges.end(), toNewStop.begin(), toNewStop.end() - 1);
2414 } else {
2415 newEdges.push_back(*itStart);
2416 }
2417 if (!newDestination) {
2418 newEdges.insert(newEdges.end(), fromNewStop.begin(), fromNewStop.end() - 1);
2419 newEdges.insert(newEdges.end(), itEnd, oldEdges.end());
2420 } else {
2421 newEdges.push_back(stopEdge);
2422 }
2423 //std::cout << SIMTIME << " insertStop veh=" << getID()
2424 // << " teleport=" << teleport
2425 // << " busStop=" << stop.busstop
2426 // << " oldEdges=" << oldRemainingEdges.size()
2427 // << " newEdges=" << newEdges.size()
2428 // << " toNewStop=" << toNewStop.size()
2429 // << " fromNewStop=" << fromNewStop.size()
2430 // << "\n";
2431
2432 const double routeCost = router.recomputeCosts(newEdges, this, t);
2433 const double previousCost = router.recomputeCosts(oldRemainingEdges, this, t);
2434 const double savings = previousCost - routeCost;
2435
2436 if (!hasDeparted() && (int)myParameter->stops.size() >= nextStopIndex) {
2437 // stops will be rebuilt from scratch so we must patch the stops in myParameter
2438 auto it = myParameter->stops.begin() + nextStopIndex;
2439 const_cast<SUMOVehicleParameter*>(myParameter)->stops.insert(it, stop);
2440 }
2441 return replaceRouteEdges(newEdges, routeCost, savings, info, !hasDeparted(), false, false, &errorMsg);
2442}
2443
2444
2445double
2447 if (static_cast<MSDevice_Battery*>(getDevice(typeid(MSDevice_Battery))) != 0) {
2448 MSDevice_Battery* batteryOfVehicle = dynamic_cast<MSDevice_Battery*>(getDevice(typeid(MSDevice_Battery)));
2449 return batteryOfVehicle->getActualBatteryCapacity();
2450 } else {
2451 if (static_cast<MSDevice_ElecHybrid*>(getDevice(typeid(MSDevice_ElecHybrid))) != 0) {
2452 MSDevice_ElecHybrid* batteryOfVehicle = dynamic_cast<MSDevice_ElecHybrid*>(getDevice(typeid(MSDevice_ElecHybrid)));
2453 return batteryOfVehicle->getActualBatteryCapacity();
2454 }
2455 }
2456 return -1;
2457}
2458
2459
2460double
2462 if (static_cast<MSDevice_Battery*>(getDevice(typeid(MSDevice_Battery))) != 0) {
2463 MSDevice_Battery* batteryOfVehicle = dynamic_cast<MSDevice_Battery*>(getDevice(typeid(MSDevice_Battery)));
2464 return batteryOfVehicle->getActualBatteryCapacity() / batteryOfVehicle->getMaximumBatteryCapacity();
2465 } else {
2466 if (static_cast<MSDevice_ElecHybrid*>(getDevice(typeid(MSDevice_ElecHybrid))) != 0) {
2467 MSDevice_ElecHybrid* batteryOfVehicle = dynamic_cast<MSDevice_ElecHybrid*>(getDevice(typeid(MSDevice_ElecHybrid)));
2468 return batteryOfVehicle->getActualBatteryCapacity() / batteryOfVehicle->getMaximumBatteryCapacity();
2469 }
2470 }
2471 return -1;
2472}
2473
2474
2475double
2477 if (static_cast<MSDevice_Battery*>(getDevice(typeid(MSDevice_Battery))) != 0) {
2478 MSDevice_Battery* batteryOfVehicle = dynamic_cast<MSDevice_Battery*>(getDevice(typeid(MSDevice_Battery)));
2479 return batteryOfVehicle->getEnergyCharged();
2480 } else {
2481 if (static_cast<MSDevice_ElecHybrid*>(getDevice(typeid(MSDevice_ElecHybrid))) != 0) {
2482 MSDevice_ElecHybrid* batteryOfVehicle = dynamic_cast<MSDevice_ElecHybrid*>(getDevice(typeid(MSDevice_ElecHybrid)));
2483 return batteryOfVehicle->getEnergyCharged();
2484 }
2485 }
2486 return -1;
2487}
2488
2489
2490double
2492 if (static_cast<MSDevice_Battery*>(getDevice(typeid(MSDevice_Battery))) != 0) {
2493 MSDevice_Battery* batteryOfVehicle = dynamic_cast<MSDevice_Battery*>(getDevice(typeid(MSDevice_Battery)));
2494 return batteryOfVehicle->getMaximumChargeRate();
2495 }
2496 return -1;
2497}
2498
2499
2500double
2502 if (static_cast<MSDevice_ElecHybrid*>(getDevice(typeid(MSDevice_ElecHybrid))) != 0) {
2503 MSDevice_ElecHybrid* elecHybridDevice = dynamic_cast<MSDevice_ElecHybrid*>(getDevice(typeid(MSDevice_ElecHybrid)));
2504 return elecHybridDevice->getCurrentFromOverheadWire();
2505 }
2506
2507 return NAN;
2508}
2509
2510double
2512 if (isOnRoad() || isIdling()) {
2514 } else {
2515 return 0.;
2516 }
2517}
2518
2519
2524
2525
2530
2531
2534 if (myEdgeWeights == nullptr) {
2536 }
2537 return *myEdgeWeights;
2538}
2539
2540
2541
2542
2543int
2545 int boarded = myPersonDevice == nullptr ? 0 : myPersonDevice->size();
2546 return boarded + myParameter->personNumber;
2547}
2548
2549int
2551 int leavingPersonNumber = 0;
2552 const std::vector<MSTransportable*>& persons = getPersons();
2553 for (std::vector<MSTransportable*>::const_iterator it_p = persons.begin(); it_p != persons.end(); ++it_p) {
2554 MSStageDriving* const stage = dynamic_cast<MSStageDriving*>((*it_p)->getCurrentStage());
2555 const MSStop* stop = &myStops.front();
2556 const MSVehicle* joinVeh = dynamic_cast<MSVehicle*>(MSNet::getInstance()->getVehicleControl().getVehicle((*stop).pars.join));
2557 if (stop && stage->canLeaveVehicle(*it_p, *this, *stop) && !MSDevice_Transportable::willTransferAtJoin(*it_p, joinVeh)) {
2558 leavingPersonNumber++;
2559 }
2560 }
2561 return leavingPersonNumber;
2562}
2563
2564std::vector<std::string>
2566 std::vector<std::string> ret;
2567 const std::vector<MSTransportable*>& persons = getPersons();
2568 for (std::vector<MSTransportable*>::const_iterator it_p = persons.begin(); it_p != persons.end(); ++it_p) {
2569 ret.push_back((*it_p)->getID());
2570 }
2571 return ret;
2572}
2573
2574int
2576 int loaded = myContainerDevice == nullptr ? 0 : myContainerDevice->size();
2577 return loaded + myParameter->containerNumber;
2578}
2579
2580
2581void
2583 // this might be called from the MSTransportable destructor so we cannot do a dynamic cast to determine the type
2584 if (myPersonDevice != nullptr) {
2586 }
2587 if (myContainerDevice != nullptr) {
2589 }
2590 if (myEnergyParams != nullptr) {
2592 }
2593}
2594
2595
2596const std::vector<MSTransportable*>&
2598 if (myPersonDevice == nullptr) {
2600 } else {
2602 }
2603}
2604
2605
2606const std::vector<MSTransportable*>&
2608 if (myContainerDevice == nullptr) {
2610 } else {
2612 }
2613}
2614
2615
2616bool
2617MSBaseVehicle::isLineStop(double position) const {
2618 if (myParameter->line == "") {
2619 // not a public transport line
2620 return false;
2621 }
2622 for (const SUMOVehicleParameter::Stop& stop : myParameter->stops) {
2623 if (stop.startPos <= position && position <= stop.endPos) {
2624 return true;
2625 }
2626 }
2627 for (const SUMOVehicleParameter::Stop& stop : myRoute->getStops()) {
2628 if (stop.startPos <= position && position <= stop.endPos) {
2629 return true;
2630 }
2631 }
2632 return false;
2633}
2634
2635
2636bool
2637MSBaseVehicle::hasDevice(const std::string& deviceName) const {
2638 for (MSDevice* const dev : myDevices) {
2639 if (dev->deviceName() == deviceName) {
2640 return true;
2641 }
2642 }
2643 return false;
2644}
2645
2646
2647void
2648MSBaseVehicle::createDevice(const std::string& deviceName) {
2649 if (!hasDevice(deviceName)) {
2650 if (deviceName == "rerouting") {
2651 ((SUMOVehicleParameter*)myParameter)->setParameter("has." + deviceName + ".device", "true");
2653 if (hasDeparted()) {
2654 // vehicle already departed: disable pre-insertion rerouting and enable regular routing behavior
2655 MSDevice_Routing* routingDevice = static_cast<MSDevice_Routing*>(getDevice(typeid(MSDevice_Routing)));
2656 assert(routingDevice != 0);
2658 }
2659 } else {
2660 throw InvalidArgument(TLF("creating device of type '%' is not supported", deviceName));
2661 }
2662 }
2663}
2664
2665
2666std::string
2667MSBaseVehicle::getDeviceParameter(const std::string& deviceName, const std::string& key) const {
2668 for (MSVehicleDevice* const dev : myDevices) {
2669 if (dev->deviceName() == deviceName) {
2670 return dev->getParameter(key);
2671 }
2672 }
2673 throw InvalidArgument(TLF("no device of type '%' exists", deviceName));
2674}
2675
2676
2677void
2678MSBaseVehicle::setDeviceParameter(const std::string& deviceName, const std::string& key, const std::string& value) {
2679 for (MSVehicleDevice* const dev : myDevices) {
2680 if (dev->deviceName() == deviceName) {
2681 dev->setParameter(key, value);
2682 return;
2683 }
2684 }
2685 throw InvalidArgument(TLF("no device of type '%' exists", deviceName));
2686}
2687
2688
2689void
2690MSBaseVehicle::setJunctionModelParameter(const std::string& key, const std::string& value) {
2693 const_cast<SUMOVehicleParameter&>(getParameter()).setParameter(key, value);
2694 // checked in MSLink::ignoreFoe
2695 } else {
2696 throw InvalidArgument(TLF("Vehicle '%' does not support junctionModel parameter '%'.", getID(), key));
2697 }
2698}
2699
2700
2701void
2702MSBaseVehicle::setCarFollowModelParameter(const std::string& key, const std::string& value) {
2703 // handle some generic params first and then delegate to the carFollowModel itself
2706 const_cast<SUMOVehicleParameter&>(getParameter()).setParameter(key, value);
2707 // checked in MSVehicle::planMove
2708 } else {
2709 MSVehicle* microVeh = dynamic_cast<MSVehicle*>(this);
2710 if (microVeh) {
2711 // remove 'carFollowModel.' prefix
2712 const std::string attrName = key.substr(15);
2713 microVeh->getCarFollowModel().setParameter(microVeh, attrName, value);
2714 }
2715 }
2716}
2717
2718
2719void
2721 /* Design idea for additional junction model parameters:
2722 We can distinguish between 3 levels of parameters
2723 1. typically shared by multiple vehicles -> vType parameter
2724 2. specific to one vehicle but stays constant throughout the simulation -> vehicle parameter
2725 3. specific to one vehicle and expected to change during simulation -> prefixed generic vehicle parameter
2726 */
2727 for (auto item : getParameter().getParametersMap()) {
2728 if (StringUtils::startsWith(item.first, "junctionModel.")) {
2729 setJunctionModelParameter(item.first, item.second);
2730 } else if (StringUtils::startsWith(item.first, "carFollowModel.")) {
2731 setCarFollowModelParameter(item.first, item.second);
2732 }
2733 }
2734 const std::string routingModeStr = getStringParam("device.rerouting.mode");
2735 try {
2736 int routingMode = StringUtils::toInt(routingModeStr);
2737 if (routingMode != libsumo::ROUTING_MODE_DEFAULT) {
2738 setRoutingMode(routingMode);
2739 }
2740 } catch (NumberFormatException&) {
2741 // @todo interpret symbolic constants
2742 throw ProcessError(TLF("could not interpret routing.mode '%'", routingModeStr));
2743 }
2744}
2745
2746
2755
2756
2757void
2759 assert(type != nullptr);
2760 // save old parameters before possible type deletion
2761 const double oldMu = myType->getSpeedFactor().getParameter(0);
2762 const double oldDev = myType->getSpeedFactor().getParameter(1);
2763 if (myType->isVehicleSpecific() && type != myType) {
2765 }
2766 // adapt myChosenSpeedFactor to the new type
2767 if (oldDev == 0.) {
2768 // old type had speedDev 0, reroll
2770 } else {
2771 // map old speedFactor onto new distribution
2772 const double distPoint = (myChosenSpeedFactor - oldMu) / oldDev;
2773 const double newMu = type->getSpeedFactor().getParameter(0);
2774 const double newDev = type->getSpeedFactor().getParameter(1);
2775 myChosenSpeedFactor = newMu + distPoint * newDev;
2776 // respect distribution limits
2779 }
2780 myType = type;
2781 if (myEnergyParams != nullptr) {
2783 }
2784}
2785
2786
2789 if (myType->isVehicleSpecific()) {
2790 return *const_cast<MSVehicleType*>(myType);
2791 }
2792 MSVehicleType* type = myType->buildSingularType(myType->getID() + "@" + getID());
2793 replaceVehicleType(type);
2794 return *type;
2795}
2796
2797
2798int
2800 const MSLane* const lane = getLane();
2801 if (lane == nullptr) {
2802 return getEdge()->getLanes()[0]->getRNGIndex();
2803 } else {
2804 return lane->getRNGIndex();
2805 }
2806}
2807
2808
2809SumoRNG*
2811 const MSLane* lane = getLane();
2812 if (lane == nullptr) {
2813 return getEdge()->getLanes()[0]->getRNG();
2814 } else {
2815 return lane->getRNG();
2816 }
2817}
2818
2819std::string
2820MSBaseVehicle::getPrefixedParameter(const std::string& key, std::string& error) const {
2821 const MSVehicle* microVeh = dynamic_cast<const MSVehicle*>(this);
2822 if (StringUtils::startsWith(key, "device.")) {
2823 StringTokenizer tok(key, ".");
2824 if (tok.size() < 3) {
2825 error = TLF("Invalid device parameter '%' for vehicle '%'.", key, getID());
2826 return "";
2827 }
2828 try {
2829 return getDeviceParameter(tok.get(1), key.substr(tok.get(0).size() + tok.get(1).size() + 2));
2830 } catch (InvalidArgument& e) {
2831 error = TLF("Vehicle '%' does not support device parameter '%' (%).", getID(), key, e.what());
2832 return "";
2833 }
2834 } else if (StringUtils::startsWith(key, "laneChangeModel.")) {
2835 if (microVeh == nullptr) {
2836 error = TLF("Mesoscopic vehicle '%' does not support laneChangeModel parameters.", getID());
2837 return "";
2838 }
2839 const std::string attrName = key.substr(16);
2840 try {
2841 return microVeh->getLaneChangeModel().getParameter(attrName);
2842 } catch (InvalidArgument& e) {
2843 error = TLF("Vehicle '%' does not support laneChangeModel parameter '%' (%).", getID(), key, e.what());
2844 return "";
2845 }
2846 } else if (StringUtils::startsWith(key, "carFollowModel.")) {
2847 if (microVeh == nullptr) {
2848 error = TLF("Mesoscopic vehicle '%' does not support carFollowModel parameters.", getID());
2849 return "";
2850 }
2851 const std::string attrName = key.substr(15);
2852 try {
2853 return microVeh->getCarFollowModel().getParameter(microVeh, attrName);
2854 } catch (InvalidArgument& e) {
2855 error = TLF("Vehicle '%' does not support carFollowModel parameter '%' (%).", getID(), key, e.what());
2856 return "";
2857 }
2858 } else if (StringUtils::startsWith(key, "has.") && StringUtils::endsWith(key, ".device")) {
2859 StringTokenizer tok(key, ".");
2860 if (tok.size() != 3) {
2861 error = TL("Invalid check for device. Expected format is 'has.DEVICENAME.device'.");
2862 return "";
2863 }
2864 return hasDevice(tok.get(1)) ? "true" : "false";
2865 // parking related parameters start here
2866 } else if (key == "parking.rerouteCount") {
2868 } else if (StringUtils::startsWith(key, "parking.memory.")) {
2869 std::vector<std::string> values;
2870 if (getParkingMemory()) {
2871 if (key == "parking.memory.IDList") {
2872 for (const auto& item : *getParkingMemory()) {
2873 values.push_back(item.first->getID());
2874 }
2875 } else if (key == "parking.memory.score") {
2876 for (const auto& item : *getParkingMemory()) {
2877 values.push_back(item.second.score);
2878 }
2879 } else if (key == "parking.memory.blockedAtTime") {
2880 for (const auto& item : *getParkingMemory()) {
2881 values.push_back(toString(STEPS2TIME(item.second.blockedAtTime)));
2882 }
2883 } else if (key == "parking.memory.blockedAtTimeLocal") {
2884 for (const auto& item : *getParkingMemory()) {
2885 values.push_back(toString(STEPS2TIME(item.second.blockedAtTimeLocal)));
2886 }
2887 } else {
2888 error = TLF("Unsupported parking parameter '%' for vehicle '%'.", key, getID());
2889 }
2890 }
2891 return toString(values);
2892 } else {
2893 // default: custom user parameter
2894 return getParameter().getParameter(key, "");
2895 }
2896}
2897
2898
2899void
2906
2907
2908void
2914
2915
2916void
2918 if (myChargingMemory == nullptr) {
2920 }
2922}
2923
2924
2925void
2931
2932
2933void
2934MSBaseVehicle::rememberParkingAreaScore(const MSStoppingPlace* pa, const std::string& score) {
2935 if (myParkingMemory == nullptr) {
2937 }
2939}
2940
2941
2944 if (myParkingMemory == nullptr) {
2945 return -1;
2946 }
2947 return myParkingMemory->sawBlockedStoppingPlace(pa, local);
2948}
2949
2950
2957
2958
2961 if (myChargingMemory == nullptr) {
2962 return -1;
2963 }
2964 return myChargingMemory->sawBlockedStoppingPlace(cs, local);
2965}
2966
2967
2968#ifdef _DEBUG
2969void
2970MSBaseVehicle::initMoveReminderOutput(const OptionsCont& oc) {
2971 if (oc.isSet("movereminder-output.vehicles")) {
2972 const std::vector<std::string> vehicles = oc.getStringVector("movereminder-output.vehicles");
2973 myShallTraceMoveReminders.insert(vehicles.begin(), vehicles.end());
2974 }
2975}
2976
2977
2978void
2979MSBaseVehicle::traceMoveReminder(const std::string& type, MSMoveReminder* rem, double pos, bool keep) const {
2980 OutputDevice& od = OutputDevice::getDeviceByOption("movereminder-output");
2981 od.openTag("movereminder");
2982 od.writeAttr(SUMO_ATTR_TIME, STEPS2TIME(MSNet::getInstance()->getCurrentTimeStep()));
2983 od.writeAttr("veh", getID());
2985 od.writeAttr("type", type);
2986 od.writeAttr("pos", toString(pos));
2987 od.writeAttr("keep", toString(keep));
2988 od.closeTag();
2989}
2990#endif
2991
2992
2993/****************************************************************************/
long long int SUMOTime
Definition GUI.h:36
std::vector< const MSEdge * > ConstMSEdgeVector
Definition MSEdge.h:74
ConstMSEdgeVector::const_iterator MSRouteIterator
Definition MSRoute.h:57
#define WRITE_WARNINGF(...)
Definition MsgHandler.h:288
#define WRITE_ERRORF(...)
Definition MsgHandler.h:297
#define WRITE_WARNING(msg)
Definition MsgHandler.h:287
#define TL(string)
Definition MsgHandler.h:305
#define TLF(string,...)
Definition MsgHandler.h:307
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:91
#define STEPS2TIME(x)
Definition SUMOTime.h:55
#define SIMSTEP
Definition SUMOTime.h:61
#define SUMOTime_MAX
Definition SUMOTime.h:34
#define SIMTIME
Definition SUMOTime.h:62
#define TIME2STEPS(x)
Definition SUMOTime.h:57
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
int gPrecisionRandom
Definition StdDefs.cpp:28
const double INVALID_DOUBLE
invalid double
Definition StdDefs.h:64
T MIN2(T a, T b)
Definition StdDefs.h:76
const double SUMO_const_haltingSpeed
the speed threshold at which vehicles are considered as halting
Definition StdDefs.h:58
T MAX2(T a, T b)
Definition StdDefs.h:82
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition ToString.h:46
double getMax() const
Returns the maximum value of this distribution.
double getMin() const
Returns the minimum value of this distribution.
double getParameter(const int index) const
Returns the nth parameter of this distribution.
double getTransportableMass() const
Returns the mass of all transportables in the vehicle.
void setSecondary(const EnergyParams *secondaryParams)
Set secondary params.
void setTransportableMass(const double mass)
Sets the mass of all transportables in the vehicle.
static double computeNoise(SUMOEmissionClass c, double v, double a)
Returns the noise produced by the a vehicle of the given type at the given speed.
MESegment * getSegmentForEdge(const MSEdge &e, double pos=0)
Get the segment for a given edge at a given position.
Definition MELoop.cpp:340
virtual std::string getParameter(const std::string &key) const
try to retrieve the given parameter from this laneChangeModel. Throw exception for unsupported key
double getMaxSpeed() const
Returns the maximum speed (the minimum of desired and technical maximum speed)
bool haveValidStopEdges(bool silent=false) const
check whether all stop.edge MSRouteIterators are valid and in order
int myRoutingMode
routing mode (see TraCIConstants.h)
bool hasJump(const MSRouteIterator &it) const
check wether the vehicle has jump at the given part of its route
bool hasReminder(MSMoveReminder *rem) const
Checks whether the vehilce 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 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.
MSStop & getNextStopMutable()
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
double getOdometer() const
Returns the distance that was already driven by this vehicle.
bool isRail() const
virtual bool hasArrived() const
Returns whether this vehicle has already arived (by default this is true if the vehicle has reached i...
const NumericalID myNumericalID
bool isStoppedInRange(const double pos, const double tolerance, bool checkFuture=false) const
return whether the given position is within range of the current stop
bool isJumping() const
Returns whether the vehicle is perform a jump.
void checkRouteRemoval()
remove route at the end of the simulation
MSVehicleType & getSingularType()
Replaces the current vehicle type with a new one used by this vehicle only.
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.
double getLength() const
Returns the vehicle's length.
bool isParking() const
Returns whether the vehicle is parking.
MSParkingArea * getCurrentParkingArea()
get the current parking area stop or nullptr
const MSEdge * getEdge() const
Returns the edge the vehicle is currently at.
double getHarmonoise_NoiseEmissions() const
Returns noise emissions of the current state.
int getPersonNumber() const
Returns the number of persons.
double getRelativeStateOfCharge() const
Returns actual relative state of charge of battery (-)
void setJunctionModelParameter(const std::string &key, const std::string &value)
set individual junction model paramete (not type related)
void setDepartAndArrivalEdge()
apply departEdge and arrivalEdge attributes
void setID(const std::string &newID)
set the id (inherited from Named but forbidden for vehicles)
ConstMSEdgeVector routeAlongStops(SUMOTime t, SUMOAbstractRouter< MSEdge, SUMOVehicle > &router, std::vector< StopEdgeInfo > &stops, ConstMSEdgeVector edges, int originStop, SUMOTime maxDelay, double &skippedPrio2) const
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)
ConstMSEdgeVector optimizeSkipped(SUMOTime t, SUMOAbstractRouter< MSEdge, SUMOVehicle > &router, const MSEdge *source, double sourcePos, std::vector< StopEdgeInfo > &stops, ConstMSEdgeVector edges, SUMOTime maxDelay) const
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 equiped 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
void addStops(const bool ignoreStopErrors, MSRouteIterator *searchStart=nullptr, bool addRouteStops=true)
Adds stops to the built vehicle.
void removeTransportable(MSTransportable *t)
removes a person or container
SUMOTime sawBlockedParkingArea(const MSStoppingPlace *pa, bool local) const
SUMOVehicleClass getVClass() const
Returns the vehicle's access class.
MSParkingArea * getNextParkingArea()
get the upcoming parking area stop or nullptr
int myArrivalLane
The destination lane where the vehicle stops.
int getRouteValidity(bool update=true, bool silent=false, std::string *msgReturn=nullptr)
check for route validity at first insertion attempt
MSStop & getStop(int nextStopIndex)
virtual ~MSBaseVehicle()
Destructor.
bool insertStop(int nextStopIndex, SUMOVehicleParameter::Stop stop, const std::string &info, bool teleport, std::string &errorMsg)
SUMOTime myDeparture
The real departure time.
std::vector< std::string > getPersonIDList() const
Returns the list of persons.
const MSEdgeWeightsStorage & getWeightsStorage() const
Returns the vehicle's internal edge travel times/efforts container.
bool isStoppedTriggered() const
Returns whether the vehicle is on a triggered stop.
virtual bool resumeFromStopping()=0
virtual bool hasInfluencer() const =0
whether the vehicle is individually influenced (via TraCI or special parameters)
const std::set< SUMOTrafficObject::NumericalID > getUpcomingEdgeIDs() const
returns the numerical ids of edges to travel
bool stopsAtEdge(const MSEdge *edge) const
Returns whether the vehicle stops at the given edge.
bool addStop(const SUMOVehicleParameter::Stop &stopPar, std::string &errorMsg, SUMOTime untilOffset=0, MSRouteIterator *searchStart=nullptr)
Adds a stop.
double getChargedEnergy() const
Returns the energy charged to the battery in the current time step (Wh)
void onDepart()
Called when the vehicle is inserted into the network.
void removeReminder(MSMoveReminder *rem)
Removes a MoveReminder dynamically.
SUMOTime getStopDuration() const
get remaining stop duration or 0 if the vehicle isn't stopped
virtual double getAcceleration() const
Returns the vehicle's acceleration.
virtual bool addTraciStop(SUMOVehicleParameter::Stop stop, std::string &errorMsg)
const MSRoute & getRoute() const
Returns the current route.
int getRoutingMode() const
return routing mode (configures router choice but also handling of transient permission changes)
int getRoutePosition() const
return index of edge within route
bool replaceParkingArea(MSParkingArea *parkingArea, std::string &errorMsg)
replace the current parking area stop with a new stop with merge duration
static const SUMOTime NOT_YET_DEPARTED
SUMOTime getDepartDelay() const
Returns the depart delay.
double getElecHybridCurrent() const
Returns actual current (A) of ElecHybrid device RICE_CHECK: Is this the current consumed from the ove...
bool myAmRegisteredAsWaiting
Whether this vehicle is registered as waiting for a person or container (for deadlock-recognition)
SUMOAbstractRouter< MSEdge, SUMOVehicle > & getRouterTT() const
EnergyParams * myEnergyParams
The emission parameters this vehicle may have.
const SUMOVehicleParameter * myParameter
This vehicle's parameter.
virtual bool hasValidRouteStart(std::string &msg)
checks wether the vehicle can depart on the first edge
int myRouteValidity
status of the current vehicle route
std::vector< std::pair< int, double > > getStopIndices() const
return list of route indices for the remaining stops
SUMOTime myStopUntilOffset
The offset when adding route stops with 'until' on route replacement.
virtual bool isOnRoad() const
Returns the information whether the vehicle is on a road (is simulated)
const std::vector< MSTransportable * > & getContainers() const
retrieve riding containers
bool reroute(SUMOTime t, const std::string &info, SUMOAbstractRouter< MSEdge, SUMOVehicle > &router, const bool onInit=false, const bool withTaz=false, const bool silent=false, const MSEdge *sink=nullptr)
Performs a rerouting using the given router.
bool stopsAt(MSStoppingPlace *stop) const
Returns whether the vehicle stops at the given stopping place.
int getRNGIndex() const
MSEdgeWeightsStorage * myEdgeWeights
const MSVehicleType & getVehicleType() const
Returns the vehicle's type definition.
void createDevice(const std::string &deviceName)
create device of the given type
bool isStopped() const
Returns whether the vehicle is at a stop.
MSDevice * getDevice(const std::type_info &type) const
Returns a device of the given type if it exists, nullptr otherwise.
bool abortNextStop(int nextStopIndex=0)
deletes the next stop at the given index if it exists
int myNumberReroutes
The number of reroutings.
double myArrivalPos
The position on the destination lane where the vehicle stops.
bool insertJump(int nextStopIndex, MSRouteIterator itStart, std::string &errorMsg)
helper function
virtual void saveState(OutputDevice &out)
Saves the (common) state of a vehicle.
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:691
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:704
Battery device for electric vehicles.
double getActualBatteryCapacity() const
Get the actual vehicle's Battery Capacity in Wh.
double getMaximumChargeRate() const
Get current charge rate in W depending on the state of charge.
double getMaximumBatteryCapacity() const
Get the total vehicle's Battery Capacity in Wh.
double getEnergyCharged() const
Get charged energy.
A device which collects info on the vehicle trip (mainly on departure and arrival)
double getMaximumBatteryCapacity() const
Get the total vehicle's Battery Capacity in kWh.
double getCurrentFromOverheadWire() const
Get actual current in the overhead wire segment.
double getEnergyCharged() const
Get charged energy.
double getActualBatteryCapacity() const
Get the actual vehicle's Battery Capacity in kWh.
A device that performs vehicle rerouting based on current edge speeds.
bool notifyEnter(SUMOTrafficObject &veh, MSMoveReminder::Notification reason, const MSLane *enteredLane=0)
Computes a new route on vehicle insertion.
static void buildVehicleDevices(SUMOVehicle &v, std::vector< MSVehicleDevice * > &into)
Build devices for the given vehicle, if needed.
A device which collects info on the vehicle trip (mainly on departure and arrival)
bool allowsBoarding(const MSTransportable *t) const
whether the given person is allowed to board this taxi
const std::vector< MSTransportable * > & getTransportables() const
Returns the list of transportables using this vehicle.
static bool willTransferAtJoin(const MSTransportable *t, const MSBaseVehicle *joinVeh)
check if boardingDuration should be applied
static MSDevice_Transportable * buildVehicleDevices(SUMOVehicle &v, std::vector< MSVehicleDevice * > &into, const bool isContainer)
Build devices for the given vehicle, if needed.
int size() const
Return the number of passengers / containers.
void addTransportable(MSTransportable *transportable)
Add a passenger.
void removeTransportable(MSTransportable *transportable)
Remove a passenger (TraCI)
Abstract in-vehicle / in-person device.
Definition MSDevice.h:62
static void buildVehicleDevices(SUMOVehicle &v, std::vector< MSVehicleDevice * > &into)
Build devices for the given vehicle, if needed.
Definition MSDevice.cpp:112
A road/street connecting two junctions.
Definition MSEdge.h:77
bool hasTransientPermissions() const
Definition MSEdge.cpp:1670
const std::vector< MSLane * > & getLanes() const
Returns this edge's lanes.
Definition MSEdge.h:168
const MSEdge * getOppositeEdge() const
Returns the opposite direction edge if on exists else a nullptr.
Definition MSEdge.cpp:1339
const std::vector< MSLane * > * allowedLanes(const MSEdge &destination, SUMOVehicleClass vclass=SVC_IGNORING, bool ignoreTransientPermissions=false) const
Get the allowed lanes to reach the destination-edge.
Definition MSEdge.cpp:479
bool isNormal() const
return whether this edge is an internal edge
Definition MSEdge.h:263
double getLength() const
return the length of the edge
Definition MSEdge.h:685
bool isTazConnector() const
Definition MSEdge.h:291
int getNumLanes() const
Definition MSEdge.h:172
bool isInternal() const
return whether this edge is an internal edge
Definition MSEdge.h:268
static bool dictionary(const std::string &id, MSEdge *edge)
Inserts edge into the static dictionary Returns true if the key id isn't already in the dictionary....
Definition MSEdge.cpp:1046
const MSEdge * getNormalBefore() const
if this edge is an internal edge, return its first normal predecessor, otherwise the edge itself
Definition MSEdge.cpp:936
MSLane * getFirstAllowed(SUMOVehicleClass vClass, bool defaultFirst=false) const
Definition MSEdge.cpp:726
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:112
static int gInsertionChecks
The default value for insertion checks.
Definition MSGlobals.h:186
static SUMOTime gTimeToImpatience
Definition MSGlobals.h:78
static bool gHaveEmissions
Whether emission output of some type is needed (files or GUI)
Definition MSGlobals.h:183
static bool gUseStopEnded
whether the simulation should replay previous stop times
Definition MSGlobals.h:133
void descheduleDeparture(const SUMOVehicle *veh)
stops trying to emit the given vehicle (and delete it)
Representation of a lane in the micro simulation.
Definition MSLane.h:84
int getRNGIndex() const
returns the associated RNG index
Definition MSLane.h:241
const MSEdge * getNextNormal() const
Returns the lane's follower if it is an internal lane, the edge of the lane otherwise.
Definition MSLane.cpp:2439
double getLength() const
Returns the lane's length.
Definition MSLane.h:611
bool allowsVehicleClass(SUMOVehicleClass vclass) const
Definition MSLane.h:930
static bool dictionary(const std::string &id, MSLane *lane)
Static (sic!) container methods {.
Definition MSLane.cpp:2463
bool isInternal() const
Definition MSLane.cpp:2594
SumoRNG * getRNG() const
return the associated RNG
Definition MSLane.h:246
MSEdge & getEdge() const
Returns the lane's edge.
Definition MSLane.h:769
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.
bool warnOnce(const std::string &typeAndID)
return whether a warning regarding the given object shall be issued
Definition MSNet.cpp:1671
@ NEWROUTE
The vehicle got a new route.
static MSNet * getInstance()
Returns the pointer to the unique instance of MSNet (singleton).
Definition MSNet.cpp:186
MSEventControl * getBeginOfTimestepEvents()
Returns the event control for events executed at the begin of a time step.
Definition MSNet.h:477
MSVehicleRouter & getRouterTT(int rngIndex, const Prohibitions &prohibited={}) const
Definition MSNet.cpp:1531
SUMOTime getCurrentTimeStep() const
Returns the current simulation step.
Definition MSNet.h:326
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:1404
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:1286
MSInsertionControl & getInsertionControl()
Returns the insertion control.
Definition MSNet.h:437
MSVehicleControl & getVehicleControl()
Returns the vehicle control.
Definition MSNet.h:384
A lane area vehicles can halt at.
bool accepts(MSBaseVehicle *veh) const
Return the parking accepts the vehicle (due to its given badges)
static void storeTripId(const std::string &tripId, const std::string &vehID)
const ConstMSEdgeVector & getEdges() const
Definition MSRoute.h:125
void setCosts(double costs)
Sets the costs of the route.
Definition MSRoute.h:206
static bool hasRoute(const std::string &id)
returns whether a route with the given id exists
Definition MSRoute.cpp:152
static bool dictionary(const std::string &id, ConstMSRoutePtr route)
Adds a route to the dictionary.
Definition MSRoute.cpp:109
static void checkDist(const std::string &id)
Checks the distribution whether it is permanent and deletes it if not.
Definition MSRoute.cpp:187
void setSavings(double savings)
Sets the savings of the route.
Definition MSRoute.h:213
static MSVehicleRouter & getRouterTT(const int rngIndex, SUMOVehicleClass svc, const 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
bool isOpposite
whether this an opposite-direction stop
Definition MSStop.h:87
void initPars(const SUMOVehicleParameter::Stop &stopPar)
initialize attributes from the given stop parameters
Definition MSStop.cpp:112
const MESegment * segment
The segment to stop at (mesosim only)
Definition MSStop.h:52
bool reached
Information whether the stop has been reached.
Definition MSStop.h:75
MSRouteIterator edge
The edge in the route to stop at.
Definition MSStop.h:48
double getEndPos(const SUMOVehicle &veh) const
return halting position for upcoming stop;
Definition MSStop.cpp:35
MSParkingArea * parkingarea
(Optional) parkingArea if one is assigned to the stop
Definition MSStop.h:58
MSStoppingPlace * chargingStation
(Optional) charging station if one is assigned to the stop
Definition MSStop.h:60
std::string getDescription() const
get a short description for showing in the gui
Definition MSStop.cpp:69
SUMOTime getUntil() const
return until / ended time
Definition MSStop.cpp:151
SUMOTime getArrival() const
return arrival / started time
Definition MSStop.cpp:157
const SUMOVehicleParameter::Stop pars
The stop parameter.
Definition MSStop.h:65
MSStoppingPlace * busstop
(Optional) bus stop if one is assigned to the stop
Definition MSStop.h:54
MSStoppingPlace * overheadWireSegment
(Optional) overhead wire segment if one is assigned to the stop
Definition MSStop.h:63
A lane area vehicles can halt at.
double getBeginLanePosition() const
Returns the begin position of this stop.
double getParkingLength() const
double getEndLanePosition() const
Returns the end position of this stop.
const MSLane & getLane() const
Returns the lane this stop is located at.
bool isPerson() const
Whether it is a person.
const MSVehicleType & getVehicleType() const
Returns the object's "vehicle" type.
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:969
The car-following model and parameter.
const EnergyParams * getEmissionParameters() const
retrieve parameters for the energy consumption model
SUMOVehicleClass getVehicleClass() const
Get this vehicle type's vehicle class.
double getMaxSpeed() const
Get vehicle's (technical) maximum speed [m/s].
double getDesiredMaxSpeed() const
Returns the vehicles's desired maximum speed.
const std::string & getID() const
Returns the name of the vehicle type.
const Distribution_Parameterized & getSpeedFactor() const
Returns this type's speed factor.
bool isVehicleSpecific() const
Returns whether this type belongs to a single vehicle only (was modified)
SUMOEmissionClass getEmissionClass() const
Get this vehicle type's emission class.
double getLength() const
Get vehicle's length [m].
double getMass() const
Get this vehicle type's mass.
double computeChosenSpeedDeviation(SumoRNG *rng, const double minDev=-1.) const
Computes and returns the speed deviation.
MSVehicleType * buildSingularType(const std::string &id) const
Duplicates the microsim vehicle type giving the newly created type the given id, marking it as vehicl...
const std::vector< std::string > & getParkingBadges() const
Returns the parking access rights of this type.
static std::string getIDSecure(const T *obj, const std::string &fallBack="NULL")
get an identifier for Named-like object which may be Null
Definition Named.h:67
const std::string & getID() const
Returns the id.
Definition Named.h:74
A storage for options typed value containers)
Definition OptionsCont.h:89
bool isSet(const std::string &name, bool failOnNonExistant=true) const
Returns the information whether the named option is set.
const StringVector & getStringVector(const std::string &name) const
Returns the list of string-value of the named option (only for Option_StringVector)
static OptionsCont & getOptions()
Retrieves the options.
Static storage of an output device and its base (abstract) implementation.
OutputDevice & writeAttr(const SumoXMLAttr attr, const T &val)
writes a named attribute
OutputDevice & openTag(const std::string &xmlElement)
Opens an XML tag.
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:202
static double rand(SumoRNG *rng=nullptr)
Returns a random real number in [0, 1)
bool computeLooped(const E *from, const E *to, const V *const vehicle, SUMOTime msTime, std::vector< const E * > &into, bool silent=false)
Builds the route between the given edges using the minimum effort at the given time if from == to,...
virtual bool compute(const E *from, const E *to, const V *const vehicle, SUMOTime msTime, std::vector< const E * > &into, bool silent=false)=0
Builds the route between the given edges using the minimum effort at the given time The definition of...
virtual double recomputeCosts(const std::vector< const E * > &edges, const V *const v, SUMOTime msTime, double *lengthp=nullptr) const
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
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:62
virtual bool isIdling() const =0
Returns whether the vehicle is idling (waiting to re-enter the net.
virtual double getBrakeGap(bool delayed=false) const =0
get distance for coming to a stop (used for rerouting checks)
Definition of vehicle stop (position and duration)
std::string edge
The edge to stop at.
ParkingType parking
whether the vehicle is removed from the net while stopping
std::string lane
The lane to stop at.
double speed
the speed at which this stop counts as reached (waypoint mode)
std::string parkingarea
(Optional) parking area if one is assigned to the stop
double startPos
The stopping position start.
int parametersSet
Information for the output which parameter were set.
int index
at which position in the stops list
SUMOTime jump
transfer time if there shall be a jump from this stop to the next route edge
SUMOTime until
The time at which the vehicle may continue its journey.
bool triggered
whether an arriving person lets the vehicle continue
SUMOTime ended
the time at which this stop was ended
double endPos
The stopping position end.
std::string tripId
id of the trip within a cyclical public transport route
bool containerTriggered
whether an arriving container lets the vehicle continue
bool collision
Whether this stop was triggered by a collision.
SUMOTime arrival
The (expected) time at which the vehicle reaches the stop.
SUMOTime duration
The stopping duration.
Structure representing possible vehicle parameter.
ArrivalSpeedDefinition arrivalSpeedProcedure
Information how the vehicle's end speed shall be chosen.
double departSpeed
(optional) The initial speed of the vehicle
std::string vtypeid
The vehicle's type id.
SUMOTime repetitionOffset
The time offset between vehicle reinsertions.
std::vector< std::string > via
List of the via-edges the vehicle must visit.
int repetitionsDone
The number of times the vehicle was already inserted.
ArrivalLaneDefinition arrivalLaneProcedure
Information how the vehicle shall choose the lane to arrive on.
long long int parametersSet
Information for the router which parameter were set, TraCI may modify this (when changing color)
void write(OutputDevice &dev, const OptionsCont &oc, const SumoXMLTag altTag=SUMO_TAG_VEHICLE, const std::string &typeID="") const
Writes the parameters as a beginning element.
int personNumber
The static number of persons in the vehicle when it departs (not including boarding persons)
RouteIndexDefinition arrivalEdgeProcedure
Information how the vehicle's final edge shall be chosen.
bool wasSet(long long int what) const
Returns whether the given parameter was set.
double departPos
(optional) The position the vehicle shall depart from
DepartSpeedDefinition departSpeedProcedure
Information how the vehicle's initial speed shall be chosen.
double arrivalPos
(optional) The position the vehicle shall arrive on
std::string routeid
The vehicle's route id.
std::string id
The vehicle's id.
std::vector< std::string > parkingBadges
The parking access rights.
std::vector< Stop > stops
List of the stops the vehicle will make, TraCI may add entries here.
int departEdge
(optional) The initial edge within the route of the vehicle
ArrivalPosDefinition arrivalPosProcedure
Information how the vehicle shall choose the arrival position.
std::string toTaz
The vehicle's destination zone (district)
double arrivalSpeed
(optional) The final speed of the vehicle (not used yet)
DepartDefinition departProcedure
Information how the vehicle shall choose the depart time.
int 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_IGNORE_TRANSIENT_PERMISSIONS