Eclipse SUMO - Simulation of Urban MObility
Loading...
Searching...
No Matches
MSBaseVehicle.cpp
Go to the documentation of this file.
1/****************************************************************************/
2// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3// Copyright (C) 2001-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 "MSStopOptimizer.h"
66#include "MSBaseVehicle.h"
67
68//#define DEBUG_REROUTE
69//#define DEBUG_ADD_STOP
70//#define DEBUG_COND (getID() == "")
71//#define DEBUG_COND (true)
72//#define DEBUG_REPLACE_ROUTE
73#define DEBUG_COND (isSelected())
74
75// ===========================================================================
76// static members
77// ===========================================================================
79std::vector<MSTransportable*> MSBaseVehicle::myEmptyTransportableVector;
80#ifdef _DEBUG
81std::set<std::string> MSBaseVehicle::myShallTraceMoveReminders;
82#endif
84
85// ===========================================================================
86// Influencer method definitions
87// ===========================================================================
88
91
92// ===========================================================================
93// method definitions
94// ===========================================================================
95
96double
98 throw ProcessError("getPreviousSpeed() is not available for non-MSVehicles.");
99}
100
101
103 MSVehicleType* type, const double speedFactor) :
104 SUMOVehicle(pars->id),
105 myParameter(pars),
106 myRoute(route),
107 myType(type),
108 myCurrEdge(route->begin()),
109 myChosenSpeedFactor(pars->speedFactor < 0 ? speedFactor : pars->speedFactor),
111 myPersonDevice(nullptr),
112 myContainerDevice(nullptr),
113 myEnergyParams(nullptr),
115 myDepartPos(-1),
116 myArrivalPos(-1),
117 myArrivalLane(-1),
120 myOdometer(0.),
122 myRoutingMode(libsumo::ROUTING_MODE_DEFAULT),
124 myRandomSeed(RandHelper::murmur3_32(pars->id, RandHelper::getSeed())),
125 myEdgeWeights(nullptr)
126#ifdef _DEBUG
127 , myTraceMoveReminders(myShallTraceMoveReminders.count(pars->id) > 0)
128#endif
129{
130 if ((*myRoute->begin())->isTazConnector() || myRoute->getLastEdge()->isTazConnector()) {
132 }
133 if ((pars->parametersSet & VEHPARS_FORCE_REROUTE) == 0) {
135 }
138}
139
140
142 delete myEdgeWeights;
143 if (myParameter->repetitionNumber == -1) {
144 // this is not a flow (flows call checkDist in MSInsertionControl::determineCandidates)
146 }
147 for (MSVehicleDevice* dev : myDevices) {
148 delete dev;
149 }
150 delete myEnergyParams;
151 delete myParkingMemory;
152 delete myChargingMemory;
154 delete myParameter;
155}
156
157
158void
160 // the check for an instance is needed for the unit tests which do not construct a network
161 // TODO Optimize for speed and there should be a better way to check whether a vehicle is part of a flow
162 if (MSNet::hasInstance() && !MSNet::getInstance()->hasFlow(getFlowID())) {
163 myRoute->checkRemoval();
164 }
165}
166
167
168std::string
170 return getID().substr(0, getID().rfind('.'));
171}
172
173
174void
177 for (MSVehicleDevice* dev : myDevices) {
178 myMoveReminders.push_back(std::make_pair(dev, 0.));
179 }
181 // ensure we have the emission parameters even if we don't have the device
183 }
184}
185
186
187void
188MSBaseVehicle::setID(const std::string& /*newID*/) {
189 throw ProcessError(TL("Changing a vehicle ID is not permitted"));
190}
191
194 return *myParameter;
195}
196
197
198void
200 delete myParameter;
201 myParameter = newParameter;
202}
203
204
205bool
209
210double
214
215
216const MSEdge*
217MSBaseVehicle::succEdge(int nSuccs) const {
218 if (myCurrEdge + nSuccs < myRoute->end() && std::distance(myCurrEdge, myRoute->begin()) <= nSuccs) {
219 return *(myCurrEdge + nSuccs);
220 } else {
221 return nullptr;
222 }
223}
224
225
226const MSEdge*
228 return *myCurrEdge;
229}
230
231
232const std::set<SUMOTrafficObject::NumericalID>
234 std::set<SUMOTrafficObject::NumericalID> result;
235 for (auto e = myCurrEdge; e != myRoute->end(); ++e) {
236 result.insert((*e)->getNumericalID());
237 }
238 return result;
239}
240
241
242bool
244 if (stop == nullptr) {
245 return false;
246 }
247 for (const MSStop& s : myStops) {
248 if (s.busstop == stop
249 || s.containerstop == stop
250 || s.parkingarea == stop
251 || s.chargingStation == stop) {
252 return true;
253 }
254 }
255 return false;
256}
257
258bool
260 for (const MSStop& s : myStops) {
261 if (&s.lane->getEdge() == edge) {
262 return true;
263 }
264 }
265 return myRoute->getLastEdge() == edge;
266}
267
268
269bool
270MSBaseVehicle::reroute(SUMOTime t, const std::string& info, SUMOAbstractRouter<MSEdge, SUMOVehicle>& router, const bool onInit, const bool withTaz, const bool silent, const MSEdge* sink) {
271 // check whether to reroute
272 const MSEdge* source = withTaz && onInit ? MSEdge::dictionary(myParameter->fromTaz + "-source") : *getRerouteOrigin();
273 if (source == nullptr) {
274 source = *getRerouteOrigin();
275 }
276 if (sink == nullptr) {
277 sink = withTaz ? MSEdge::dictionary(myParameter->toTaz + "-sink") : myRoute->getLastEdge();
278 if (sink == nullptr) {
279 sink = myRoute->getLastEdge();
280 }
281 }
282 ConstMSEdgeVector oldEdgesRemaining(source == *myCurrEdge ? myCurrEdge : myCurrEdge + 1, myRoute->end());
283 ConstMSEdgeVector edges;
284 if (source != sink || !sink->prohibits(this)) {
285 edges.push_back(source);
286 }
287 std::vector<StopEdgeInfo> stops;
288 std::set<int> jumps;
289
290
291 double sourcePos = getPositionOnLane();
292#ifdef DEBUG_REROUTE
293 if (DEBUG_COND) {
294 std::cout << " sourcePos=" << sourcePos << " lane=" << Named::getIDSecure(getLane()) << " departPos=" << myParameter->departPos << "\n";
295 }
296#endif
298 sourcePos = myParameter->departPos;
299 } else if (getLane() != nullptr && source != &getLane()->getEdge()) {
300 // routing starts on the next edge
301 sourcePos = 0;
302 }
303 if (myParameter->via.size() == 0) {
304 double firstPos = INVALID_DOUBLE;
305 double lastPos = INVALID_DOUBLE;
306 stops = getStopEdges(firstPos, lastPos, jumps);
307 if (stops.size() > 0) {
309 sourcePos = getNextStop().pars.endPos;
310 }
311 if ( !isStopped() && myStops.front().pars.speed == 0) {
312 sourcePos += getBrakeGap();
313 }
314 // avoid superfluous waypoints for first and last edge
315 const bool skipFirst = stops.front().edge == source && (source != getEdge() || sourcePos <= firstPos + NUMERICAL_EPS);
316#ifdef DEBUG_REROUTE
317 if (DEBUG_COND) {
318 std::cout << SIMTIME << " reroute " << info << " veh=" << getID() << " lane=" << Named::getIDSecure(getLane())
319 << " source=" << source->getID() << " sourcePos=" << sourcePos << " firstPos=" << firstPos << " arrivalPos=" << myArrivalPos << " lastPos=" << lastPos
320 << " route=" << toString(myRoute->getEdges()) << " skipFirst=" << skipFirst << "\n";
321 }
322#endif
323 if (stops.size() == 1 && skipFirst) {
324 stops.clear();
325 } else if (skipFirst) {
326 sourcePos = stops.front().pos;
327 stops.erase(stops.begin());
328 }
329 }
330 } else {
331 std::set<const MSEdge*> jumpEdges;
332 std::map<const MSEdge*, StopEdgeInfo> stopsOnVia;
333 for (const MSStop& stop : myStops) {
334 if (stop.pars.jump >= 0) {
335 jumpEdges.insert(*stop.edge);
336 }
337 auto itsov = stopsOnVia.find(*stop.edge);
338 if (itsov == stopsOnVia.end()) {
339 stopsOnVia.insert({*stop.edge, StopEdgeInfo(*stop.edge, stop.pars.priority, stop.getArrivalFallback(), stop.getEndPos(*this))});
340 } else {
341 itsov->second.priority = addStopPriority(itsov->second.priority, stop.pars.priority);
342 }
343 }
344 // via takes precedence over stop edges
345 // there is a consistency check in MSRouteHandler::addStop that warns when a stop edge is not part of the via edges
346 for (std::vector<std::string>::const_iterator it = myParameter->via.begin(); it != myParameter->via.end(); ++it) {
347 MSEdge* viaEdge = MSEdge::dictionary(*it);
348 if ((viaEdge == source && it == myParameter->via.begin()) || (viaEdge == sink && myParameter->via.end() - it == 1)) {
349 continue;
350 }
351 assert(viaEdge != 0);
352 if (!viaEdge->isTazConnector() && viaEdge->allowedLanes(getVClass()) == nullptr) {
353 throw ProcessError(TLF("Vehicle '%' is not allowed on any lane of via edge '%'.", getID(), viaEdge->getID()));
354 }
355 auto itsov = stopsOnVia.find(viaEdge);
356 const double priority = (itsov == stopsOnVia.end() ? -1 : itsov->second.priority);
357 const SUMOTime arrival = (itsov == stopsOnVia.end() ? -1 : itsov->second.arrival);
358 const double pos = (itsov == stopsOnVia.end() ? 0 : itsov->second.pos);
359 stops.push_back(StopEdgeInfo(viaEdge, priority, arrival, pos));
360 // @todo determine wether the viaEdge is also used by a stop and then use the stop priority here
361 if (jumpEdges.count(viaEdge) != 0) {
362 jumps.insert((int)stops.size());
363 }
364 }
365 }
366 if ((stops.size() == 0 && (source != sink || sourcePos > myArrivalPos))
367 || ((stops.size() != 0) && (stops.back().edge != sink || myArrivalPos < stops.back().pos))) {
368 stops.push_back(StopEdgeInfo(sink, -1, -1, myArrivalPos, true));
369 }
370#ifdef DEBUG_REROUTE
371 if (DEBUG_COND) {
372 std::cout << SIMTIME << " stops: veh=" << getID() << " source=" << source->getID() << " sink=" << sink->getID() << " sourcePos=" << sourcePos << " arrivalPos=" << myArrivalPos << "\n";
373 for (auto item : stops) {
374 std::cout << " e=" << item.edge->getID() << " pos=" << item.pos << "\n";
375 }
376 }
377#endif
378 int stopIndex = -1;
379 auto stopIt = myStops.begin();
380 SUMOTime startTime = t;
381 bool hasSkipped = false;
382 const double origSourcePos = sourcePos;
383 const MSEdge* origSource = source;
385 for (auto& stopEdgeInfo : stops) {
386 const MSEdge* const stopEdge = stopEdgeInfo.edge;
387 const double priority = stopEdgeInfo.priority;
388 stopIndex++;
390 if (jumps.count(stopIndex) != 0) {
391 edges.push_back(stopEdge);
392 source = stopEdge;
393 continue;
394 }
395 // !!! need to adapt t here
396 router.compute(source, sourcePos, stopEdge, stopEdgeInfo.pos, this, t, into, silent || priority >= 0);
397#ifdef DEBUG_REROUTE
398 if (DEBUG_COND) {
399 std::cout << SIMTIME << " reroute veh=" << getID() << " source=" << source->getID() << " sourcePos=" << sourcePos << " target=" << stopEdgeInfo.edge->getID() << " targetPos=" << stopEdgeInfo.pos << " edges=" << toString(into) << "\n";
400 }
401#endif
402 if (into.size() > 0) {
403 while (stopIt != myStops.end() && stopIt->pars.edge != stopEdge->getID()) {
404 stopIt++;
405 }
406
407 startTime += TIME2STEPS(router.recomputeCostsPos(into, this, sourcePos, stopEdgeInfo.pos, startTime));
408 if (stopIt != myStops.end()) {
409 if (stopIt->pars.priority >= 0 && info != "device.rerouting") {
410 // consider skipping this stop if it cannot be reached in a timely manner
411 if (stopIt != myStops.end()) {
412 SUMOTime arrival = stopEdgeInfo.arrival;
413 if (arrival > 0) {
414 SUMOTime delay = startTime - arrival;
415 //std::cout << " t=" << time2string(t) << " veh=" << getID() << " info=" << info << " stopIndex=" << stopIndex
416 // << " into=" << toString(into) << " sourcePos=" << sourcePos << " stopPos=" << stopPos
417 // << " startTime=" << time2string(startTime) << " arrival=" << time2string(arrival) << " delay=" << time2string(delay) << "\n";
418 if (delay > 0) {
419 if (delay > maxDelay) {
420 stopEdgeInfo.skipped = true;
421 stopEdgeInfo.delay = delay;
422 hasSkipped = true;
423 continue;
424 }
425 }
426 }
427 }
428 }
429 sourcePos = stopEdgeInfo.pos;
430 startTime += stopIt->getMinDuration(startTime);
431 }
432 edges.pop_back();
433 edges.insert(edges.end(), into.begin(), into.end());
434 if (edges.back()->isTazConnector()) {
435 edges.pop_back();
436 }
437 source = edges.back();
438 stopEdgeInfo.routeIndex = (int)edges.size() - 1;
439 } else {
440 if (priority >= 0) {
441 stopEdgeInfo.skipped = true;
442 hasSkipped = true;
443 continue;
444 } else if (stopEdgeInfo.isSink) {
445 //error = TLF("Vehicle '%' has no valid route from edge '%' to destination edge '%'.", getID(), source->getID(), stopEdge->getID());
446 edges.clear();
447 } else if (source == stopEdge && stopEdgeInfo.stopPar != nullptr && stopEdgeInfo.stopPar->endPos >= sourcePos) {
448 // special case: no failure on dynamically computed stop position
449 edges.clear();
450 } else {
451 std::string error = TLF("Vehicle '%' has no valid route from edge '%' to stop edge '%'.", getID(), source->getID(), stopEdge->getID());
452 if (MSGlobals::gCheckRoutes || silent) {
453 throw ProcessError(error);
454 } else {
455 WRITE_WARNING(error);
456 edges.push_back(source);
457 source = stopEdge;
458 }
459 }
460 }
461 }
462 if (hasSkipped) {
463 MSStopOptimizer opti(this, router, t, maxDelay);
464 edges = opti.optimizeSkipped(origSource, origSourcePos, stops, edges);
465 for (auto stop : stops) {
466 if (stop.skipped || stop.origEdge != nullptr) {
467 const MSEdge* origEdge = stop.origEdge == nullptr ? stop.edge : stop.origEdge;
468 if (stop.delay > 0) {
469 WRITE_WARNING(TLF("Vehicle '%' skips stop on edge '%' with delay % at time %.", getID(), origEdge->getID(), time2string(stop.delay), time2string(SIMSTEP)));
470 } else if (stop.backtracked) {
471 WRITE_WARNING(TLF("Vehicle '%' skips stop on edge '%' with priority % at time %.", getID(), origEdge->getID(), stop.priority, time2string(SIMSTEP)));
472 } else {
473 WRITE_WARNING(TLF("Vehicle '%' skips unreachable stop on edge '%' with priority % at time %.", getID(), origEdge->getID(), stop.priority, time2string(SIMSTEP)));
474 }
475 }
476 }
477 }
478
479 // router.setHint(myCurrEdge, myRoute->end(), this, t);
480 if (edges.empty() && silent) {
481 return false;
482 }
483 if (!edges.empty() && edges.front()->isTazConnector()) {
484 edges.erase(edges.begin());
485 }
486 if (!edges.empty() && edges.back()->isTazConnector()) {
487 edges.pop_back();
488 }
489 const double routeCost = router.recomputeCosts(edges, this, t);
490 const double previousCost = onInit ? routeCost : router.recomputeCosts(oldEdgesRemaining, this, t);
491 const double savings = previousCost - routeCost;
492 bool savingsOk = onInit || info != "device.rerouting" || gWeightsRandomFactor != 1;
493 if (!savingsOk) {
494 MSDevice_Routing* routingDevice = static_cast<MSDevice_Routing*>(getDevice(typeid(MSDevice_Routing)));
495 assert(routingDevice != 0);
496 savingsOk = routingDevice->sufficientSaving(previousCost, routeCost);
497 if (!savingsOk) {
498 std::string dummyMsg;
499 if (!hasValidRoute(dummyMsg, oldEdgesRemaining.begin(), oldEdgesRemaining.end(), true)) {
500 // the old route is prohibted (i.e. due to temporary permission changes)
501 savingsOk = true;
502 }
503 }
504 }
505 //if (getID() == "43") std::cout << SIMTIME << " pCost=" << previousCost << " cost=" << routeCost
506 // << " onInit=" << onInit
507 // << " prevEdges=" << toString(oldEdgesRemaining)
508 // << " newEdges=" << toString(edges)
509 // << "\n";
510 if (savingsOk) {
511 replaceRouteEdges(edges, routeCost, savings, info, onInit);
512 }
513 // this must be called even if the route could not be replaced
514 if (onInit) {
515 if (edges.empty()) {
517 throw ProcessError(TLF("Vehicle '%' has no valid route.", getID()));
518 } else if (source->isTazConnector()) {
519 WRITE_WARNINGF(TL("Removing vehicle '%' which has no valid route."), getID());
521 return false;
522 }
523 }
526 }
527 return !edges.empty();
528}
529
530
531bool
532MSBaseVehicle::replaceRouteEdges(ConstMSEdgeVector& edges, double cost, double savings, const std::string& info, bool onInit, bool check, bool removeStops, std::string* msgReturn) {
533 if (edges.empty()) {
534 WRITE_WARNINGF(TL("No route for vehicle '%' found."), getID());
535 if (msgReturn != nullptr) {
536 *msgReturn = "No route found";
537 }
538 return false;
539 }
540 // build a new id, first
541 std::string id = getID();
542 if (id[0] != '!') {
543 id = "!" + id;
544 }
545 const std::string idSuffix = id + "!var#";
546 int varIndex = 1;
547 id = idSuffix + toString(varIndex);
548 while (MSRoute::hasRoute(id)) {
549 id = idSuffix + toString(++varIndex);
550 }
551 int oldSize = (int)edges.size();
552 if (!onInit) {
553 const MSEdge* const origin = *getRerouteOrigin();
554 if (origin != *myCurrEdge && edges.front() == origin) {
555 edges.insert(edges.begin(), *myCurrEdge);
556 oldSize = (int)edges.size();
557 }
558 edges.insert(edges.begin(), myRoute->begin(), myCurrEdge);
559 }
560 if (edges == myRoute->getEdges() && haveValidStopEdges(true)) {
561 // re-assign stop iterators when rerouting to a new parkingArea / insertStop
562 return true;
563 }
564 const RGBColor& c = myRoute->getColor();
565 MSRoute* newRoute = new MSRoute(id, edges, false, &c == &RGBColor::DEFAULT_COLOR ? nullptr : new RGBColor(c), StopParVector());
566 newRoute->setCosts(cost);
567 newRoute->setSavings(savings);
568 ConstMSRoutePtr constRoute = std::shared_ptr<MSRoute>(newRoute);
569 if (!MSRoute::dictionary(id, constRoute)) {
570 delete newRoute;
571 if (msgReturn != nullptr) {
572 *msgReturn = "duplicate routeID '" + id + "'";
573 }
574 return false;
575 }
576
577 std::string msg;
578 if (check && !hasValidRoute(msg, constRoute)) {
579 WRITE_WARNINGF(TL("Invalid route replacement for vehicle '%'. %"), getID(), msg);
581 if (msgReturn != nullptr) {
582 *msgReturn = msg;
583 }
584 return false;
585 }
586 }
587 if (!replaceRoute(constRoute, info, onInit, (int)edges.size() - oldSize, false, removeStops, msgReturn)) {
588 return false;
589 }
590 return true;
591}
592
593
594bool
595MSBaseVehicle::replaceRoute(ConstMSRoutePtr newRoute, const std::string& info, bool onInit, int offset, bool addRouteStops, bool removeStops, std::string* msgReturn) {
596 const ConstMSEdgeVector& edges = newRoute->getEdges();
597 // rebuild in-vehicle route information
598 if (onInit) {
599 myCurrEdge = newRoute->begin();
600 } else {
601 MSRouteIterator newCurrEdge = std::find(edges.begin() + offset, edges.end(), *myCurrEdge);
602 if (newCurrEdge == edges.end()) {
603 if (msgReturn != nullptr) {
604 *msgReturn = TLF("current edge '%' not found in new route", (*myCurrEdge)->getID());
605 }
606#ifdef DEBUG_REPLACE_ROUTE
607 if (DEBUG_COND) {
608 std::cout << " newCurrEdge not found\n";
609 }
610#endif
611 return false;
612 }
613 if (getLane() != nullptr) {
614 if (getLane()->getEdge().isInternal() && (
615 (newCurrEdge + 1) == edges.end() || (*(newCurrEdge + 1)) != &(getLane()->getOutgoingViaLanes().front().first->getEdge()))) {
616 if (msgReturn != nullptr) {
617 *msgReturn = TL("Vehicle is on junction-internal edge leading elsewhere");
618 }
619#ifdef DEBUG_REPLACE_ROUTE
620 if (DEBUG_COND) {
621 std::cout << " Vehicle is on junction-internal edge leading elsewhere\n";
622 }
623#endif
624 return false;
625 } else if (getPositionOnLane() > getLane()->getLength()
626 && (myCurrEdge + 1) != myRoute->end()
627 && (newCurrEdge + 1) != edges.end()
628 && *(myCurrEdge + 1) != *(newCurrEdge + 1)) {
629 if (msgReturn != nullptr) {
630 *msgReturn = TL("Vehicle is moving past junction and committed to move to another successor edge");
631 }
632#ifdef DEBUG_REPLACE_ROUTE
633 if (DEBUG_COND) {
634 std::cout << " Vehicle is moving past junction and committed to move to another successor edge\n";
635 }
636#endif
637 return false;
638 }
639 }
640 myCurrEdge = newCurrEdge;
641 }
642 const bool stopsFromScratch = onInit && myRoute->getStops().empty();
643 // assign new route
645 myRoute = newRoute;
646 // update arrival definition
648 // save information that the vehicle was rerouted
650 myStopUntilOffset += myRoute->getPeriod();
652 if (!onInit && isRail() && MSRailSignalControl::hasInstance()) {
653 // we need to update driveways (add/remove reminders) before the next call to MSRailSignalControl::updateSignals
654 //
655 // rerouting may be triggered through
656 // - MoveReminders (executeMove->activateReminders)
657 // - rerouters
658 // - devices (MSDevice_Stationfinder)
659 // - TraCI (changeTarget, replaceStop, ...
660 // - events (MSDevice_Routing::myRerouteCommand, MSDevice_Taxi::triggerDispatch)
661 //
662 // Since activateReminders actively modifies reminders, adding/deleting reminders would create a mess
663 // hence, we use an event to be safe for all case
664
667 }
668#ifdef DEBUG_REPLACE_ROUTE
669 if (DEBUG_COND) {
670 std::cout << SIMTIME << " veh=" << getID() << " replaceRoute info=" << info << " on " << (*myCurrEdge)->getID()
671 << " lane=" << Named::getIDSecure(getLane())
672 << " stopsFromScratch=" << stopsFromScratch
673 << " newSize=" << newRoute->getEdges().size()
674 << " newIndex=" << (myCurrEdge - newRoute->begin())
675 << " edges=" << toString(newRoute->getEdges())
676 << "\n";
677 }
678#endif
679 // remove past stops which are not on the route anymore
680 for (StopParVector::iterator it = myPastStops.begin(); it != myPastStops.end();) {
681 const MSEdge* stopEdge = (it->edge.empty()) ? &MSLane::dictionary(it->lane)->getEdge() : MSEdge::dictionary(it->edge);
682 if (std::find(myRoute->begin(), myRoute->end(), stopEdge) == myRoute->end()) {
683 it = myPastStops.erase(it);
684 } else {
685 ++it;
686 }
687 }
688 // if we did not drive yet it may be best to simply reassign the stops from scratch
689 if (stopsFromScratch) {
690 myStops.clear();
692 } else {
693 // recheck old stops
694 MSRouteIterator searchStart = myCurrEdge;
695 double lastPos = getPositionOnLane() + getBrakeGap();
696 if (getLane() != nullptr && getLane()->isInternal()
697 && myStops.size() > 0 && !myStops.front().lane->isInternal()) {
698 // searchStart is still incoming to the intersection so lastPos
699 // relative to that edge must be adapted
700 lastPos += (*myCurrEdge)->getLength();
701 }
702 int stopIndex = 0;
703 for (std::list<MSStop>::iterator iter = myStops.begin(); iter != myStops.end();) {
704 double endPos = iter->getEndPos(*this);
705#ifdef DEBUG_REPLACE_ROUTE
706 if (DEBUG_COND) {
707 std::cout << " stopEdge=" << iter->lane->getEdge().getID() << " start=" << (searchStart - myCurrEdge) << " endPos=" << endPos << " lastPos=" << lastPos << "\n";
708 }
709#endif
710 if (*searchStart != &iter->lane->getEdge()
711 || endPos + NUMERICAL_EPS < lastPos) {
712 if (searchStart != edges.end() && !iter->reached) {
713 searchStart++;
714 }
715 }
716 lastPos = endPos;
717
718 iter->edge = std::find(searchStart, edges.end(), &iter->lane->getEdge());
719#ifdef DEBUG_REPLACE_ROUTE
720 if (DEBUG_COND) {
721 std::cout << " foundIndex=" << (iter->edge - myCurrEdge) << " end=" << (edges.end() - myCurrEdge) << "\n";
722 }
723#endif
724 if (iter->edge == edges.end() && iter->pars.priority >= 0) {
725 const std::string oldEdge = iter->pars.edge;
726 const std::string oldName = iter->getStoppingPlaceName().first;
727 if (replaceWithAlternative(iter, searchStart, edges.end())) {
728 WRITE_WARNINGF(TL("Vehicle '%' replaced stop on edge '%' (named '%') and now stops at '%' instead; after rerouting (%) at time=%."),
729 getID(), oldEdge, oldName, iter->getDescription(true), info, time2string(SIMSTEP));
730 }
731 }
732 if (iter->edge == edges.end()) {
733 if (!removeStops) {
734 WRITE_ERRORF(TL("Vehicle '%' could not assign stop '%' after rerouting (%) at time=%."), getID(), iter->getDescription(), info, time2string(SIMSTEP));
735 }
736 iter = myStops.erase(iter);
737 continue;
738 } else {
739 setSkips(*iter, stopIndex);
740 searchStart = iter->edge;
741 }
742 ++iter;
743 stopIndex++;
744 }
745 // add new stops
746 if (addRouteStops) {
747 for (StopParVector::const_iterator i = newRoute->getStops().begin(); i != newRoute->getStops().end(); ++i) {
748 std::string error;
750 if (error != "") {
751 WRITE_WARNING(error);
752 }
753 }
754 }
755 }
756 return true;
757}
758
759
760bool
761MSBaseVehicle::replaceWithAlternative(std::list<MSStop>::iterator iter, const MSRouteIterator searchStart, const MSRouteIterator end) {
762 std::pair<std::string, SumoXMLTag> nameTag = iter->getStoppingPlaceName();
763 if (!nameTag.first.empty()) {
764 const std::vector<MSStoppingPlace*>& alternatives = MSNet::getInstance()->getStoppingPlaceAlternatives(nameTag.first, nameTag.second);
765 for (MSStoppingPlace* alt : alternatives) {
766 //std::cout << SIMTIME << " veh=" << getID() << " name=" << nameTag.first << " alt=" << alt->getID() << "\n";
767 if (&alt->getLane().getEdge() == &iter->lane->getEdge()
768 || !alt->getLane().allowsVehicleClass(getVClass())) {
769 continue;
770 }
771 iter->edge = std::find(searchStart, end, &alt->getLane().getEdge());
772 if (iter->edge != end) {
773 iter->replaceStoppingPlace(alt);
774 return true;
775 }
776 }
777 }
778 return false;
779}
780
781
782double
784 return 0;
785}
786
787
788void
794
795
798 const SUMOTime dep = getParameter().depart;
799 if (dep < 0) {
800 return 0;
801 }
802 return hasDeparted() ? getDeparture() - dep : SIMSTEP - dep;
803}
804
805
806bool
808 return succEdge(1) == nullptr;
809}
810
811
812int
814 return (int) std::distance(myRoute->begin(), myCurrEdge);
815}
816
817
818int
820 if (myParameter->arrivalEdge >= 0) {
822 } else {
823 return myRoute->size() - getRoutePosition();
824 }
825}
826
827
828void
830 myCurrEdge = myRoute->begin() + index;
831 const_cast<SUMOVehicleParameter*>(myParameter)->departLaneProcedure = departLaneProcedure;
832 // !!! hack
833 myArrivalPos = (*(myRoute->end() - 1))->getLanes()[0]->getLength();
834}
835
836double
840
841bool
843 if (t->isPerson() && getPersonNumber() >= getVehicleType().getPersonCapacity()) {
844 return false;
845 } else if (!t->isPerson() && getContainerNumber() >= getVehicleType().getContainerCapacity()) {
846 return false;
847 }
848 if (isStopped() && myStops.begin()->pars.permitted.size() > 0
849 && myStops.begin()->pars.permitted.count(t->getID()) == 0) {
850 return false;
851 }
852 MSDevice_Taxi* taxiDevice = static_cast<MSDevice_Taxi*>(getDevice(typeid(MSDevice_Taxi)));
853 if (taxiDevice != nullptr) {
854 return taxiDevice->allowsBoarding(t);
855 }
856 return true;
857}
858
859
860void
862 if (transportable->isPerson()) {
863 if (myPersonDevice == nullptr) {
865 myMoveReminders.insert(myMoveReminders.begin(), std::make_pair(myPersonDevice, 0.));
868 }
869 }
870 myPersonDevice->addTransportable(transportable);
871 } else {
872 if (myContainerDevice == nullptr) {
874 myMoveReminders.insert(myMoveReminders.begin(), std::make_pair(myContainerDevice, 0.));
877 }
878 }
879 myContainerDevice->addTransportable(transportable);
880 }
881 if (myEnergyParams != nullptr) {
883 }
884}
885
886
887bool
889 for (const MSStop& stop : myStops) {
890 if (stop.edge == it && stop.pars.jump >= 0) {
891 return true;
892 } else if (stop.edge > it) {
893 return false;
894 }
895 }
896 return false;
897}
898
899
900bool
901MSBaseVehicle::hasValidRoute(std::string& msg, ConstMSRoutePtr route) const {
903 if (route == nullptr) {
904 route = myRoute;
905 } else {
906 start = route->begin();
907 }
908 const bool checkJumps = route == myRoute; // the edge iterators in the stops are invalid otherwise
909 return hasValidRoute(msg, start, route->end(), checkJumps);
910}
911
912
913bool
914MSBaseVehicle::hasValidRoute(std::string& msg, MSRouteIterator start, MSRouteIterator last, bool checkJumps) const {
915 MSRouteIterator lastValid = last - 1;
916 // check connectivity, first
917 for (MSRouteIterator e = start; e != lastValid; ++e) {
918 const MSEdge& next = **(e + 1);
919 if ((*e)->allowedLanes(next, myType->getVehicleClass()) == nullptr) {
920 if (!checkJumps || !hasJump(e)) {
922 || (!next.hasTransientPermissions() && !(*e)->hasTransientPermissions())) {
923 msg = TLF("No connection between edge '%' and edge '%'.", (*e)->getID(), (*(e + 1))->getID());
924 return false;
925 }
926 }
927 }
928 }
929 // check usable lanes, then
930 for (MSRouteIterator e = start; e != last; ++e) {
931 if ((*e)->prohibits(this)) {
932 msg = TLF("Edge '%' prohibits.", (*e)->getID());
933 return false;
934 }
935 }
936 return true;
937}
938
939
940bool
942 if (!(*myCurrEdge)->isTazConnector()) {
944 msg = TLF("Departure speed for vehicle '%' is too high for the vehicle type '%'.", getID(), myType->getID());
946 return false;
947 }
948 }
949 if (myRoute->getEdges().size() > 0 && !(*myCurrEdge)->prohibits(this)) {
950 myRouteValidity &= ~ROUTE_START_INVALID_PERMISSIONS;
951 return true;
952 } else {
953 msg = TLF("Vehicle '%' is not allowed to depart on any lane of edge '%'.", getID(), (*myCurrEdge)->getID());
955 return false;
956 }
957}
958
959
960int
961MSBaseVehicle::getRouteValidity(bool update, bool silent, std::string* msgReturn) {
962 if (!update) {
963 return myRouteValidity;
964 }
965 // insertion check must be done in any case
966 std::string msg;
967 if (!hasValidRouteStart(msg)) {
969 throw ProcessError(msg);
970 } else if (!silent) {
971 // vehicle will be discarded
972 WRITE_WARNING(msg);
973 } else if (msgReturn != nullptr) {
974 *msgReturn = msg;
975 }
976 }
977 if ((MSGlobals::gCheckRoutes || myRoute->getFirstEdge()->isInternal())
979 // we could check after the first rerouting
981 if (!hasValidRoute(msg, myRoute)) {
983 throw ProcessError(TLF("Vehicle '%' has no valid route. %", getID(), msg));
984 }
985 }
986 myRouteValidity &= ~ROUTE_UNCHECKED;
987 return myRouteValidity;
988}
989
990
991bool
993 for (auto item : myMoveReminders) {
994 if (item.first == rem) {
995 return true;
996 }
997 }
998 return false;
999}
1000
1001
1002void
1004#ifdef _DEBUG
1005 if (myTraceMoveReminders) {
1006 traceMoveReminder("add", rem, pos, true);
1007 }
1008#endif
1009 myMoveReminders.push_back(std::make_pair(rem, pos));
1010}
1011
1012
1013void
1015 for (MoveReminderCont::iterator r = myMoveReminders.begin(); r != myMoveReminders.end(); ++r) {
1016 if (r->first == rem) {
1017#ifdef _DEBUG
1018 if (myTraceMoveReminders) {
1019 traceMoveReminder("remove", rem, 0, false);
1020 }
1021#endif
1022 myMoveReminders.erase(r);
1023 return;
1024 }
1025 }
1026}
1027
1028
1029void
1031 // notifyEnter may cause new reminders to be added so we cannot use an iterator
1032 for (int i = 0; i < (int)myMoveReminders.size();) {
1033 MSMoveReminder* rem = myMoveReminders[i].first;
1034 const double remPos = myMoveReminders[i].second;
1035 // skip the reminder if it is a lane reminder but not for my lane (indicated by rem->second > 0.)
1036 if (rem->getLane() != nullptr && remPos > 0.) {
1037#ifdef _DEBUG
1038 if (myTraceMoveReminders) {
1039 traceMoveReminder("notifyEnter_skipped", rem, remPos, true);
1040 }
1041#endif
1042 ++i;
1043 } else {
1044 if (rem->notifyEnter(*this, reason, enteredLane)) {
1045#ifdef _DEBUG
1046 if (myTraceMoveReminders) {
1047 traceMoveReminder("notifyEnter", rem, remPos, true);
1048 }
1049#endif
1050 ++i;
1051 } else {
1052#ifdef _DEBUG
1053 if (myTraceMoveReminders) {
1054 traceMoveReminder("notifyEnter", rem, remPos, false);
1055 }
1056#endif
1057 myMoveReminders.erase(myMoveReminders.begin() + i);
1058 }
1059 }
1060 }
1061}
1062
1063
1064bool
1066 return isRailway(getVClass()) || isRailway(getCurrentEdge()->getPermissions());
1067}
1068
1069void
1071 if (myRoute->getLastEdge()->isTazConnector()) {
1072 return;
1073 }
1074 const int arrivalEdgeIndex = MIN2(myParameter->arrivalEdge, (int)myRoute->getEdges().size() - 1);
1075 if (arrivalEdgeIndex != myParameter->arrivalEdge) {
1076 if (!(onInit && myParameter->wasSet(VEHPARS_FORCE_REROUTE))) {
1077 WRITE_WARNINGF(TL("Vehicle '%' ignores attribute arrivalEdge=% after rerouting at time=% (routeLength=%)"),
1078 getID(), myParameter->arrivalEdge, time2string(SIMSTEP), myRoute->getEdges().size() - 1);
1079 }
1080 }
1081 const MSEdge* arrivalEdge = myParameter->arrivalEdge >= 0 ? myRoute->getEdges()[arrivalEdgeIndex] : myRoute->getLastEdge();
1082 if (!onInit) {
1083 arrivalEdge = myRoute->getLastEdge();
1084 // ignore arrivalEdge parameter after rerouting
1085 const_cast<SUMOVehicleParameter*>(myParameter)->arrivalEdge = -1;
1086 }
1087 const std::vector<MSLane*>& lanes = arrivalEdge->getLanes();
1088 const double lastLaneLength = lanes[0]->getLength();
1091 if (fabs(myParameter->arrivalPos) > lastLaneLength) {
1092 WRITE_WARNINGF(TL("Vehicle '%' will not be able to arrive at the given position!"), getID());
1093 }
1094 // Maybe we should warn the user about invalid inputs!
1095 myArrivalPos = MIN2(myParameter->arrivalPos, lastLaneLength);
1096 if (myArrivalPos < 0) {
1097 myArrivalPos = MAX2(myArrivalPos + lastLaneLength, 0.);
1098 }
1099 break;
1101 myArrivalPos = RandHelper::rand(lastLaneLength);
1102 break;
1104 myArrivalPos = lastLaneLength / 2.;
1105 break;
1106 default:
1107 myArrivalPos = lastLaneLength;
1108 break;
1109 }
1111 if (myParameter->arrivalLane >= (int)lanes.size() || !lanes[myParameter->arrivalLane]->allowsVehicleClass(myType->getVehicleClass())) {
1112 WRITE_WARNINGF(TL("Vehicle '%' will not be able to arrive at the given lane '%_%'!"), getID(), arrivalEdge->getID(), toString(myParameter->arrivalLane));
1113 }
1114 myArrivalLane = MIN2(myParameter->arrivalLane, (int)(lanes.size() - 1));
1116 myArrivalLane = -1;
1117 for (MSLane* lane : lanes) {
1118 if (lane->allowsVehicleClass(myType->getVehicleClass())) {
1119 myArrivalLane = lane->getIndex();
1120 break;
1121 }
1122 }
1123 if (myArrivalLane == -1) {
1124 WRITE_WARNINGF(TL("Vehicle '%' has no usable arrivalLane on edge '%'."), getID(), arrivalEdge->getID());
1125 myArrivalLane = 0;
1126 }
1128 // pick random lane among all usable lanes
1129 std::vector<MSLane*> usable;
1130 for (MSLane* lane : lanes) {
1131 if (lane->allowsVehicleClass(myType->getVehicleClass())) {
1132 usable.push_back(lane);
1133 }
1134 }
1135 if (usable.empty()) {
1136 WRITE_WARNINGF(TL("Vehicle '%' has no usable arrivalLane on edge '%'."), getID(), arrivalEdge->getID());
1137 myArrivalLane = 0;
1138 } else {
1139 myArrivalLane = usable[RandHelper::rand(0, (int)usable.size())]->getIndex();
1140 }
1141 }
1143 for (std::vector<MSLane*>::const_iterator l = lanes.begin(); l != lanes.end(); ++l) {
1144 if (myParameter->arrivalSpeed <= (*l)->getVehicleMaxSpeed(this)) {
1145 return;
1146 }
1147 }
1148 WRITE_WARNINGF(TL("Vehicle '%' will not be able to arrive with the given speed!"), getID());
1149 }
1150}
1151
1152void
1156 const int routeEdges = (int)myRoute->getEdges().size();
1158 // write specific edge in vehroute output for reproducibility
1159 pars->departEdge = RandHelper::rand(0, routeEdges);
1161 }
1162 assert(pars->departEdge >= 0);
1163 if (pars->departEdge >= routeEdges) {
1164 WRITE_WARNINGF(TL("Ignoring departEdge % for vehicle '%' with % route edges"), toString(pars->departEdge), getID(), toString(routeEdges));
1165 } else {
1166 myCurrEdge += pars->departEdge;
1167 }
1168 }
1170 const int routeEdges = (int)myRoute->getEdges().size();
1171 const int begin = (int)(myCurrEdge - myRoute->begin());
1172 // write specific edge in vehroute output for reproducibility
1173 pars->arrivalEdge = RandHelper::rand(begin, routeEdges);
1175 assert(pars->arrivalEdge >= begin);
1176 assert(pars->arrivalEdge < routeEdges);
1177 }
1178}
1179
1180int
1184
1185int
1189 } else {
1191 }
1192}
1193
1194double
1196 return MAX2(0., MIN2(1., getVehicleType().getImpatience()
1197 + (hasInfluencer() ? getBaseInfluencer()->getExtraImpatience() : 0)
1199}
1200
1201
1202MSDevice*
1203MSBaseVehicle::getDevice(const std::type_info& type) const {
1204 for (MSVehicleDevice* const dev : myDevices) {
1205 if (typeid(*dev) == type) {
1206 return dev;
1207 }
1208 }
1209 return nullptr;
1210}
1211
1212
1213void
1215 // the parameters may hold the name of a vTypeDistribution but we are interested in the actual type
1216 const std::string& typeID = myParameter->vtypeid != getVehicleType().getID() ? getVehicleType().getID() : "";
1218 // params and stops must be written in child classes since they may wish to add additional attributes first
1219 out.writeAttr(SUMO_ATTR_ROUTE, myRoute->getID());
1220 std::ostringstream os;
1221 os << myOdometer << " " << myNumberReroutes;
1222 out.writeAttr(SUMO_ATTR_DISTANCE, os.str());
1225 }
1227 const int precision = out.getPrecision();
1228 out.setPrecision(MAX2(gPrecisionRandom, precision));
1230 out.setPrecision(precision);
1231 }
1233 out.writeAttr(SUMO_ATTR_REROUTE, true);
1234 }
1236 // could be set from stop
1238 }
1239 // here starts the vehicle internal part (see loading)
1240 // @note: remember to close the vehicle tag when calling this in a subclass!
1241}
1242
1243
1244bool
1245MSBaseVehicle::handleCollisionStop(MSStop& stop, const double distToStop) {
1246 UNUSED_PARAMETER(stop);
1247 UNUSED_PARAMETER(distToStop);
1248 return true;
1249}
1250
1251
1252bool
1254 return !myStops.empty() && myStops.begin()->reached /*&& myState.mySpeed < SUMO_const_haltingSpeed @todo #1864#*/;
1255}
1256
1257
1258bool
1260 return (isStopped() && (myStops.begin()->pars.parking == ParkingType::OFFROAD)
1261 && (myStops.begin()->parkingarea == nullptr || !myStops.begin()->parkingarea->parkOnRoad())
1262 && (myStops.begin()->getSpeed() == 0 || getSpeed() < SUMO_const_haltingSpeed));
1263}
1264
1265
1266bool
1268 return myPastStops.size() > 0 && myPastStops.back().jump >= 0 && getEdge()->getID() == myPastStops.back().edge && myPastStops.back().ended == SIMSTEP;
1269}
1270
1271
1272bool
1274 return isStopped() && (myStops.begin()->triggered || myStops.begin()->containerTriggered || myStops.begin()->joinTriggered);
1275}
1276
1277
1278bool
1280 return isStopped() && (myStops.begin()->pars.parking == ParkingType::OFFROAD);
1281}
1282
1283
1284bool
1285MSBaseVehicle::isStoppedInRange(const double pos, const double tolerance, bool checkFuture) const {
1286 if (isStopped() || (checkFuture && hasStops())) {
1287 const MSStop& stop = myStops.front();
1288 return stop.pars.startPos - tolerance <= pos && stop.pars.endPos + tolerance >= pos;
1289 }
1290 return false;
1291}
1292
1293bool
1294MSBaseVehicle::replaceParkingArea(MSParkingArea* parkingArea, std::string& errorMsg) {
1295 // Check if there is a parking area to be replaced
1296 if (parkingArea == 0) {
1297 errorMsg = "new parkingArea is NULL";
1298 return false;
1299 }
1300 if (myStops.size() == 0) {
1301 errorMsg = "vehicle has no stops";
1302 return false;
1303 }
1304 if (myStops.front().parkingarea == 0) {
1305 errorMsg = "first stop is not at parkingArea";
1306 return false;
1307 }
1308 MSStop& first = myStops.front();
1309 SUMOVehicleParameter::Stop& stopPar = const_cast<SUMOVehicleParameter::Stop&>(first.pars);
1310 std::string oldStopEdgeID = first.lane->getEdge().getID();
1311 // merge subsequent duplicate stops equals to parking area
1312 for (std::list<MSStop>::iterator iter = ++myStops.begin(); iter != myStops.end();) {
1313 if (iter->parkingarea == parkingArea) {
1314 stopPar.duration += iter->duration;
1315 myStops.erase(iter++);
1316 } else {
1317 break;
1318 }
1319 }
1320 stopPar.lane = parkingArea->getLane().getID();
1321 stopPar.parkingarea = parkingArea->getID();
1322 stopPar.startPos = parkingArea->getBeginLanePosition();
1323 stopPar.endPos = parkingArea->getEndLanePosition();
1324 first.edge = myRoute->end(); // will be patched in replaceRoute
1325 first.lane = &parkingArea->getLane();
1326 first.parkingarea = parkingArea;
1327
1328 // patch via edges
1329 std::string newStopEdgeID = parkingArea->getLane().getEdge().getID();
1330 if (myParameter->via.size() > 0 && myParameter->via.front() != newStopEdgeID) {
1331 myParameter->via.erase(myParameter->via.begin());
1332 myParameter->via.insert(myParameter->via.begin(), newStopEdgeID);
1333 }
1334 return true;
1335}
1336
1337
1340 MSParkingArea* nextParkingArea = nullptr;
1341 if (!myStops.empty()) {
1343 MSStop stop = myStops.front();
1344 if (!stop.reached && stop.parkingarea != nullptr) {
1345 nextParkingArea = stop.parkingarea;
1346 }
1347 }
1348 return nextParkingArea;
1349}
1350
1351
1354 MSParkingArea* currentParkingArea = nullptr;
1355 if (isParking()) {
1356 currentParkingArea = myStops.begin()->parkingarea;
1357 }
1358 return currentParkingArea;
1359}
1360
1361
1362const std::vector<std::string>&
1365 return myParameter->parkingBadges;
1366 } else {
1368 }
1369}
1370
1371
1372double
1373MSBaseVehicle::basePos(const MSEdge* edge) const {
1374 double result = MIN2(getVehicleType().getLength() + POSITION_EPS, edge->getLength());
1375 if (hasStops()
1376 && myStops.front().edge == myRoute->begin()
1377 && (&myStops.front().lane->getEdge()) == *myStops.front().edge) {
1378 result = MIN2(result, MAX2(0.0, myStops.front().getEndPos(*this)));
1379 }
1380 return result;
1381}
1382
1383
1384MSLane*
1386 const std::string edgeID = SUMOXMLDefinitions::getEdgeIDFromLane(stop.lane);
1387 const MSEdge* edge = MSEdge::dictionary(edgeID);
1388 if (edge == nullptr || edge->getOppositeEdge() == nullptr || stop.lane.find("_") == std::string::npos) {
1389 return nullptr;
1390 }
1391 const int laneIndex = SUMOXMLDefinitions::getIndexFromLane(stop.lane);
1392 if (laneIndex < (edge->getNumLanes() + edge->getOppositeEdge()->getNumLanes())) {
1393 const int oppositeIndex = edge->getOppositeEdge()->getNumLanes() + edge->getNumLanes() - 1 - laneIndex;
1394 stop.edge = edgeID;
1395 return edge->getOppositeEdge()->getLanes()[oppositeIndex];
1396 }
1397 return nullptr;
1398}
1399
1400
1401bool
1402MSBaseVehicle::addStop(const SUMOVehicleParameter::Stop& stopPar, std::string& errorMsg, SUMOTime untilOffset,
1403 MSRouteIterator* searchStart) {
1404 MSStop stop(stopPar);
1405 if (stopPar.lane == "") {
1406 MSEdge* e = MSEdge::dictionary(stopPar.edge);
1407 stop.lane = e->getFirstAllowed(getVClass());
1408 if (stop.lane == nullptr) {
1409 errorMsg = "Vehicle '" + myParameter->id + "' is not allowed to stop on any lane of edge '" + stopPar.edge + "'.";
1410 return false;
1411 }
1412 } else {
1413 stop.lane = MSLane::dictionary(stopPar.lane);
1414 if (stop.lane == nullptr) {
1415 // must be an opposite stop
1416 SUMOVehicleParameter::Stop tmp = stopPar;
1417 stop.lane = interpretOppositeStop(tmp);
1418 assert(stop.lane != nullptr);
1419 }
1421 errorMsg = "Vehicle '" + myParameter->id + "' is not allowed to stop on lane '" + stopPar.lane + "'.";
1422 return false;
1423 }
1424 }
1426 stop.segment = MSGlobals::gMesoNet->getSegmentForEdge(stop.lane->getEdge(), stop.getEndPos(*this));
1427 if (stop.lane->isInternal()) {
1428 errorMsg = "Mesoscopic simulation does not allow stopping on internal edge '" + stopPar.edge + "' for vehicle '" + myParameter->id + "'.";
1429 return false;
1430 }
1431 }
1432 stop.initPars(stopPar);
1433 if (stopPar.until != -1) {
1434 // !!! it would be much cleaner to invent a constructor for stops which takes "until" as an argument
1435 const_cast<SUMOVehicleParameter::Stop&>(stop.pars).until += untilOffset;
1436 }
1437 if (stopPar.arrival != -1) {
1438 const_cast<SUMOVehicleParameter::Stop&>(stop.pars).arrival += untilOffset;
1439 }
1440 std::string stopType = "stop";
1441 std::string stopID = "";
1442 double parkingLength = stop.pars.endPos - stop.pars.startPos;
1443 if (stop.busstop != nullptr) {
1444 stopType = "busStop";
1445 stopID = stop.busstop->getID();
1446 parkingLength = stop.busstop->getParkingLength();
1447 } else if (stop.containerstop != nullptr) {
1448 stopType = "containerStop";
1449 stopID = stop.containerstop->getID();
1450 parkingLength = stop.containerstop->getParkingLength();
1451 } else if (stop.chargingStation != nullptr) {
1452 stopType = "chargingStation";
1453 stopID = stop.chargingStation->getID();
1454 parkingLength = stop.chargingStation->getParkingLength();
1455 } else if (stop.overheadWireSegment != nullptr) {
1456 stopType = "overheadWireSegment";
1457 stopID = stop.overheadWireSegment->getID();
1458 parkingLength = stop.overheadWireSegment->getParkingLength();
1459 } else if (stop.parkingarea != nullptr) {
1460 stopType = "parkingArea";
1461 stopID = stop.parkingarea->getID();
1462 }
1463 const std::string errorMsgStart = stopID == "" ? stopType : stopType + " '" + stopID + "'";
1464
1465 if (stop.pars.startPos < 0 || stop.pars.endPos > stop.lane->getLength()) {
1466 errorMsg = errorMsgStart + " for vehicle '" + myParameter->id + "' on lane '" + stop.lane->getID() + "' has an invalid position.";
1467 return false;
1468 }
1469 if (stopType != "stop" && stopType != "parkingArea" && myType->getLength() / 2. > parkingLength
1470 // do not warn for stops that fill the whole lane
1471 && parkingLength < stop.lane->getLength()
1472 // do not warn twice for the same stop
1473 && MSNet::getInstance()->warnOnce(stopType + ":" + stopID)) {
1474 errorMsg = errorMsgStart + " on lane '" + stop.lane->getID() + "' is too short for vehicle '" + myParameter->id + "'.";
1475 }
1476 if (stopType == "parkingArea" && !stop.parkingarea->accepts(this)) {
1477 // forbid access in case the parking requests other badges
1478 errorMsg = errorMsgStart + "on lane '" + stop.lane->getID() + "' forbids access because vehicle '" + myParameter->id + "' does not provide any valid badge.";
1479 return false;
1480 }
1481 const MSEdge* stopLaneEdge = &stop.lane->getEdge();
1482 const MSEdge* stopEdge;
1483 if (stopLaneEdge->getOppositeEdge() != nullptr && stopLaneEdge->getOppositeEdge()->getID() == stopPar.edge) {
1484 // stop lane is on the opposite side
1485 stopEdge = stopLaneEdge->getOppositeEdge();
1486 stop.isOpposite = true;
1487 } else {
1488 // if stop is on an internal edge the normal edge before the intersection is used
1489 stopEdge = stopLaneEdge->getNormalBefore();
1490 }
1491 MSRouteIterator succ = myCurrEdge + 1; // we're using the address but only within the scope of this function (and recursive calls)
1492 if (searchStart == nullptr) {
1493 searchStart = &myCurrEdge;
1494 if (stopLaneEdge->isNormal() && getLane() != nullptr && getLane()->isInternal()) {
1495 // already on the intersection but myCurrEdge is before it
1496 searchStart = &succ;
1497 }
1498 }
1499#ifdef DEBUG_ADD_STOP
1500 if (DEBUG_COND) {
1501 std::cout << "addStop desc=" << stop.getDescription() << " stopEdge=" << stopEdge->getID()
1502 << " searchStart=" << ((*searchStart) == myRoute->end() ? "END" : (**searchStart)->getID())
1503 << " index=" << (int)((*searchStart) - myRoute->begin()) << " route=" << toString(myRoute->getEdges())
1504 << "\n";
1505 }
1506#endif
1507 stop.edge = std::find(*searchStart, myRoute->end(), stopEdge);
1508 MSRouteIterator prevStopEdge = myCurrEdge;
1509 const MSEdge* prevEdge = (getLane() == nullptr ? getEdge() : &getLane()->getEdge());
1510 double prevStopPos = getPositionOnLane();
1511 // where to insert the stop
1512 std::list<MSStop>::iterator iter = myStops.begin();
1513 if (stopPar.index == STOP_INDEX_END || stopPar.index >= static_cast<int>(myStops.size()) || stopPar.index == STOP_INDEX_REPEAT) {
1514 iter = myStops.end();
1515 if (myStops.size() > 0 && myStops.back().edge >= *searchStart) {
1516 prevStopEdge = myStops.back().edge;
1517 prevEdge = &myStops.back().lane->getEdge();
1518 prevStopPos = myStops.back().pars.endPos;
1519 stop.edge = std::find(prevStopEdge, myRoute->end(), stopEdge);
1520 if (prevStopEdge == stop.edge // laneEdge check is insufficient for looped routes
1521 && prevEdge == &stop.lane->getEdge() // route iterator check insufficient for internal lane stops
1522 && (prevStopPos > stop.pars.endPos ||
1523 (prevStopPos == stop.pars.endPos && stopPar.index == STOP_INDEX_REPEAT))) {
1524 stop.edge = std::find(prevStopEdge + 1, myRoute->end(), stopEdge);
1525 }
1526#ifdef DEBUG_ADD_STOP
1527 if (DEBUG_COND) {
1528 std::cout << " (@end) prevStopEdge=" << (*prevStopEdge)->getID() << " prevStopPos=" << prevStopPos << " index=" << (int)(prevStopEdge - myRoute->begin())
1529 << " foundIndex=" << (stop.edge == myRoute->end() ? -1 : (int)(stop.edge - myRoute->begin())) << "\n";
1530 }
1531#endif
1532 }
1533 // skip a number of occurences of stopEdge in looped route
1534 int skipLooped = stopPar.index - static_cast<int>(myStops.size());
1535 for (int j = 0; j < skipLooped; j++) {
1536 auto nextIt = std::find(stop.edge + 1, myRoute->end(), stopEdge);
1537 if (nextIt == myRoute->end()) {
1538 if (std::find(myRoute->begin(), stop.edge, stopEdge) != stop.edge) {
1539 // only warn if the route loops over the stop edge at least once
1540 errorMsg = errorMsgStart + " for vehicle '" + myParameter->id + "' could not skip " + toString(skipLooped) + " occurences of stop edge '" + stopEdge->getID() + "' in looped route.";
1541 }
1542 break;
1543 } else {
1544 stop.edge = nextIt;
1545 }
1546 }
1547 } else {
1548 if (stopPar.index == STOP_INDEX_FIT) {
1549 while (iter != myStops.end() && (iter->edge < stop.edge ||
1550 (iter->pars.endPos < stop.pars.endPos && iter->edge == stop.edge) ||
1551 (stop.lane->getEdge().isInternal() && iter->edge == stop.edge))) {
1552 prevStopEdge = iter->edge;
1553 prevStopPos = iter->pars.endPos;
1554 ++iter;
1555 }
1556 } else {
1557 int index = stopPar.index;
1558 while (index > 0) {
1559 prevStopEdge = iter->edge;
1560 prevStopPos = iter->pars.endPos;
1561 ++iter;
1562 --index;
1563 }
1564#ifdef DEBUG_ADD_STOP
1565 if (DEBUG_COND) {
1566 std::cout << " (@fit) prevStopEdge=" << (*prevStopEdge)->getID() << " index=" << (int)(prevStopEdge - myRoute->begin()) << "\n";
1567 }
1568#endif
1569 stop.edge = std::find(prevStopEdge, myRoute->end(), stopEdge);
1570 }
1571 }
1572 const bool wasTooClose = errorMsg != "" && errorMsg.find("too close") != std::string::npos;
1573 if (stop.edge == myRoute->end()) {
1574 if (!wasTooClose) {
1575 errorMsg = errorMsgStart + " for vehicle '" + myParameter->id + "' on lane '" + stop.lane->getID() + "' is not downstream the current route.";
1576 }
1577 return false;
1578 }
1579
1580 const bool tooClose = (prevStopEdge == stop.edge && prevEdge == &stop.lane->getEdge() &&
1581 prevStopPos + (iter == myStops.begin() ? getBrakeGap() : 0) > stop.pars.endPos + POSITION_EPS);
1582
1583 if (prevStopEdge > stop.edge ||
1584 // a collision-stop happens after vehicle movement and may move the
1585 // vehicle backwards on its lane (prevStopPos is the vehicle position)
1586 (tooClose && !stop.pars.collision)
1587 || (stop.lane->getEdge().isInternal() && stop.lane->getNextNormal() != *(stop.edge + 1))) {
1588 // check if the edge occurs again later in the route
1589 //std::cout << " could not add stop " << errorMsgStart << " prevStops=" << myStops.size() << " searchStart=" << (*searchStart - myRoute->begin()) << " route=" << toString(myRoute->getEdges()) << "\n";
1590 if (tooClose && prevStopPos <= stop.pars.endPos + POSITION_EPS) {
1591 errorMsg = errorMsgStart + " for vehicle '" + myParameter->id + "' on lane '" + stop.pars.lane + "' is too close to brake.";
1592 }
1593 MSRouteIterator next = stop.edge + 1;
1594 return addStop(stopPar, errorMsg, untilOffset, &next);
1595 }
1596 if (wasTooClose) {
1597 errorMsg = "";
1598 }
1599 // David.C:
1600 //if (!stop.parking && (myCurrEdge == stop.edge && myState.myPos > stop.endPos - getCarFollowModel().brakeGap(myState.mySpeed))) {
1601 const double endPosOffset = stop.lane->getEdge().isInternal() ? (*stop.edge)->getLength() : 0;
1602 const double distToStop = stop.pars.endPos + endPosOffset - getPositionOnLane();
1603 if (stop.pars.collision && !handleCollisionStop(stop, distToStop)) {
1604 return false;
1605 }
1606 if (!hasDeparted() && myCurrEdge == stop.edge) {
1607 double pos = -1;
1609 pos = myParameter->departPos;
1610 if (pos < 0.) {
1611 pos += (*myCurrEdge)->getLength();
1612 }
1613 }
1615 pos = MIN2(stop.pars.endPos + endPosOffset, basePos(*myCurrEdge));
1616 }
1617 if (pos > stop.pars.endPos + endPosOffset) {
1618 if (stop.edge != myRoute->end()) {
1619 // check if the edge occurs again later in the route
1620 MSRouteIterator next = stop.edge + 1;
1621 return addStop(stopPar, errorMsg, untilOffset, &next);
1622 }
1623 errorMsg = errorMsgStart + " for vehicle '" + myParameter->id + "' on lane '" + stop.lane->getID() + "' is before departPos.";
1624 return false;
1625 }
1626 }
1627 if (iter != myStops.begin()) {
1628 std::list<MSStop>::iterator iter2 = iter;
1629 iter2--;
1630 if (stop.getUntil() >= 0 && iter2->getUntil() > stop.getUntil()
1631 && (!MSGlobals::gUseStopEnded || iter2->pars.ended < 0 || stop.pars.ended >= 0)) {
1632 errorMsg = errorMsgStart + " for vehicle '" + myParameter->id + "' on lane '" + stop.lane->getID()
1633 + "' set to end at " + time2string(stop.getUntil())
1634 + " earlier than previous stop at " + time2string(iter2->getUntil()) + ".";
1635 }
1636 if (stop.pars.arrival >= 0 && iter2->pars.arrival > stop.pars.arrival) {
1637 errorMsg = errorMsgStart + " for vehicle '" + myParameter->id + "' on lane '" + stop.lane->getID()
1638 + "' set to start at " + time2string(stop.pars.arrival)
1639 + " earlier than previous stop end at " + time2string(iter2->getUntil()) + ".";
1640 }
1641 if (stop.pars.arrival >= 0 && iter2->pars.arrival > stop.pars.arrival) {
1642 errorMsg = errorMsgStart + " for vehicle '" + myParameter->id + "' on lane '" + stop.lane->getID()
1643 + "' set to start at " + time2string(stop.pars.arrival)
1644 + " earlier than previous stop arrival at " + time2string(iter2->pars.arrival) + ".";
1645 }
1646 } else {
1647 if (stop.getUntil() >= 0 && getParameter().depart > stop.getUntil()
1648 && (!MSGlobals::gUseStopEnded || stop.pars.ended < 0)) {
1649 errorMsg = errorMsgStart + " for vehicle '" + myParameter->id + "' on lane '" + stop.lane->getID()
1650 + "' set to end at " + time2string(stop.getUntil())
1651 + " earlier than departure at " + time2string(getParameter().depart) + ".";
1652 }
1653 }
1654 if (stop.getUntil() >= 0 && stop.getArrival() > stop.getUntil() && errorMsg == "") {
1655 errorMsg = errorMsgStart + " for vehicle '" + myParameter->id + "' on lane '" + stop.lane->getID()
1656 + "' set to end at " + time2string(stop.getUntil())
1657 + " earlier than arrival at " + time2string(stop.getArrival()) + ".";
1658 }
1659 setSkips(stop, (int)myStops.size());
1660 myStops.insert(iter, stop);
1661 if (stopPar.tripId != "") {
1663 }
1664 //std::cout << " added stop " << errorMsgStart << " totalStops=" << myStops.size() << " searchStart=" << (*searchStart - myRoute->begin())
1665 // << " routeIndex=" << (stop.edge - myRoute->begin())
1666 // << " stopIndex=" << std::distance(myStops.begin(), iter)
1667 // << " route=" << toString(myRoute->getEdges()) << "\n";
1668 return true;
1669}
1670
1671
1672void
1673MSBaseVehicle::setSkips(MSStop& stop, int prevActiveStops) {
1674 if (hasDeparted() && stop.edge > myRoute->begin()) {
1675 // if the route is looped we must patch the index to ensure that state
1676 // loading (and vehroute-output) encode the correct number of skips
1677 int foundSkips = 0;
1678 MSRouteIterator itPrev;
1679 double prevEndPos;
1680 if (prevActiveStops > 0) {
1681 assert((int)myStops.size() >= prevActiveStops);
1682 auto prevStopIt = myStops.begin();
1683 std::advance(prevStopIt, prevActiveStops - 1);
1684 const MSStop& prev = *prevStopIt;
1685 itPrev = prev.edge;
1686 prevEndPos = prev.pars.endPos;
1687 } else if (myPastStops.size() > 0) {
1688 itPrev = myRoute->begin() + myPastStops.back().routeIndex;
1689 prevEndPos = myPastStops.back().endPos;
1690 } else {
1691 itPrev = myRoute->begin() + myParameter->departEdge;
1692 prevEndPos = myDepartPos;
1693 }
1694 //auto itPrevOrig = itPrev;
1695 if (*itPrev == *stop.edge && prevEndPos > stop.pars.endPos) {
1696 itPrev++;
1697 }
1698 //std::cout << SIMTIME << " veh=" << getID() << " prevActive=" << prevActiveStops << " edge=" << (*stop.edge)->getID() << " routeIndex=" << (stop.edge - myRoute->begin()) << " prevIndex=" << (itPrev - myRoute->begin()) << "\n";
1699 while (itPrev < stop.edge) {
1700 if (*itPrev == *stop.edge) {
1701 foundSkips++;
1702 }
1703 itPrev++;
1704 }
1705 int newIndex = STOP_INDEX_END;
1706 if (foundSkips > 0) {
1707 //if (getID() == "77_0_0") {
1708 // std::cout << SIMTIME << " veh=" << getID() << " past=" << myPastStops.size() << " prevActive=" << prevActiveStops
1709 // << " edge=" << (*stop.edge)->getID() << " routeIndex=" << (stop.edge - myRoute->begin())
1710 // << " prevEdge=" << (*itPrevOrig)->getID()
1711 // << " prevIndex=" << (itPrevOrig - myRoute->begin())
1712 // << " skips=" << foundSkips << "\n";
1713 //}
1714 newIndex = (int)myPastStops.size() + prevActiveStops + foundSkips;
1715 }
1716 const_cast<SUMOVehicleParameter::Stop&>(stop.pars).index = newIndex;
1717 }
1718}
1719
1720
1723 for (int i = 0; i < (int)myMoveReminders.size();) {
1724 auto rem = &myMoveReminders[i];
1725 if (rem->first->notifyReroute(*this)) {
1726#ifdef _DEBUG
1727 if (myTraceMoveReminders) {
1728 traceMoveReminder("notifyReroute", rem->first, rem->second, true);
1729 }
1730#endif
1731 ++i;
1732 } else {
1733#ifdef _DEBUG
1734 if (myTraceMoveReminders) {
1735 traceMoveReminder("notifyReroute", rem->first, rem->second, false);
1736 }
1737#endif
1738 myMoveReminders.erase(myMoveReminders.begin() + i);
1739 }
1740 }
1742 // event only called once
1743 return 0;
1744}
1745
1746
1747void
1748MSBaseVehicle::addStops(const bool ignoreStopErrors, MSRouteIterator* searchStart, bool addRouteStops) {
1749 if (addRouteStops) {
1750 for (const SUMOVehicleParameter::Stop& stop : myRoute->getStops()) {
1751 std::string errorMsg;
1752 if (!addStop(stop, errorMsg, myParameter->depart, searchStart) && !ignoreStopErrors) {
1753 throw ProcessError(errorMsg);
1754 }
1755 if (errorMsg != "") {
1756 WRITE_WARNING(errorMsg);
1757 }
1758 }
1759 }
1761 for (const SUMOVehicleParameter::Stop& stop : myParameter->stops) {
1762 std::string errorMsg;
1763 if (!addStop(stop, errorMsg, untilOffset, searchStart) && !ignoreStopErrors) {
1764 throw ProcessError(errorMsg);
1765 }
1766 if (errorMsg != "") {
1767 WRITE_WARNING(errorMsg);
1768 }
1769 }
1770}
1771
1772
1773bool
1776 int i = 0;
1777 bool ok = true;
1778 for (const MSStop& stop : myStops) {
1779 MSRouteIterator it;
1780 if (stop.lane->isInternal()) {
1781 // find the normal predecessor and ensure that the next route edge
1782 // matches the successor of the internal edge successor
1783 it = std::find(start, myRoute->end(), stop.lane->getEdge().getNormalBefore());
1784 if (it != myRoute->end() && (
1785 it + 1 == myRoute->end() || *(it + 1) != stop.lane->getEdge().getNormalSuccessor())) {
1786 it = myRoute->end(); // signal failure
1787 }
1788 } else {
1789 it = std::find(start, myRoute->end(), &stop.lane->getEdge());
1790 }
1791 if (it == myRoute->end()) {
1792 if (!silent) {
1793 WRITE_ERRORF("Stop % on edge '%' is not found after edge '%' (% after current) for vehicle '%' at time=%.",
1794 i, stop.lane->getEdge().getID(), (*start)->getID(), toString(start - myCurrEdge), getID(), time2string(SIMSTEP));
1795 }
1796 ok = false;
1797 } else {
1798 MSRouteIterator it2;
1799 for (it2 = myRoute->begin(); it2 != myRoute->end(); it2++) {
1800 if (it2 == stop.edge) {
1801 break;
1802 }
1803 }
1804 if (it2 == myRoute->end()) {
1805 if (!silent) {
1806 WRITE_ERRORF("Stop % on edge '%' used invalid route index for vehicle '%' at time=%.",
1807 i, stop.lane->getEdge().getID(), getID(), time2string(SIMSTEP));
1808 }
1809 ok = false;
1810 } else if (it2 < start) {
1811 if (!silent) {
1812 WRITE_ERRORF("Stop % on edge '%' used invalid (relative) route index % expected after % for vehicle '%' at time=%.",
1813 i, stop.lane->getEdge().getID(), toString(it2 - myCurrEdge), toString(start - myCurrEdge), getID(), time2string(SIMSTEP));
1814 }
1815 ok = false;
1816 } else {
1817 start = stop.edge;
1818 }
1819 }
1820 i++;
1821 }
1822 return ok;
1823}
1824
1825
1826std::vector<MSBaseVehicle::StopEdgeInfo>
1827MSBaseVehicle::getStopEdges(double& firstPos, double& lastPos, std::set<int>& jumps) const {
1828 assert(haveValidStopEdges());
1829 std::vector<StopEdgeInfo> result;
1830 const MSStop* prev = nullptr;
1831 const MSEdge* internalSuccessor = nullptr;
1832 for (const MSStop& stop : myStops) {
1833 if (stop.reached) {
1834 if (stop.pars.jump >= 0) {
1835 jumps.insert((int)result.size());
1836 }
1837 continue;
1838 }
1839 double stopPos = stop.getEndPos(*this);
1840 if ((prev == nullptr
1841 || prev->edge != stop.edge
1842 || (prev->lane == stop.lane && prev->getEndPos(*this) > stopPos))
1843 && *stop.edge != internalSuccessor) {
1844 if (stop.lane->isInternal()) {
1845 stopPos = (*stop.edge)->getLength();
1846 }
1847 result.push_back(StopEdgeInfo(*stop.edge, stop.pars.priority, stop.getArrivalFallback(), stopPos));
1848 result.back().nameTag = stop.getStoppingPlaceName();
1849 result.back().stopPar = &stop.pars;
1850 if (stop.lane->isInternal()) {
1851 internalSuccessor = stop.lane->getNextNormal();
1852 result.push_back(StopEdgeInfo(internalSuccessor, stop.pars.priority, stop.getArrivalFallback(), 0));
1853 } else {
1854 internalSuccessor = nullptr;
1855 }
1856 } else if (prev != nullptr && prev->edge == stop.edge) {
1857 result.back().priority = addStopPriority(result.back().priority, stop.pars.priority);
1858 }
1859 prev = &stop;
1860 if (firstPos == INVALID_DOUBLE) {
1861 if (stop.parkingarea != nullptr) {
1862 firstPos = MAX2(0., stopPos);
1863 } else {
1864 firstPos = stopPos;
1865 }
1866 }
1867 lastPos = stopPos;
1868 if (stop.pars.jump >= 0) {
1869 jumps.insert((int)result.size() - 1);
1870 }
1871 }
1872 //std::cout << SIMTIME << " getStopEdges veh=" << getID() << "\n";
1873 //for (auto item : result) {
1874 // std::cout << " e=" << item.edge->getID() << " pos=" << item.pos << "\n";
1875 //}
1876 return result;
1877}
1878
1879
1880double
1881MSBaseVehicle::addStopPriority(double p1, double p2) {
1882 if (p1 < 0 || p2 < 0) {
1883 return p1;
1884 }
1885 return p1 + p2;
1886}
1887
1888std::vector<std::pair<int, double> >
1890 std::vector<std::pair<int, double> > result;
1891 for (std::list<MSStop>::const_iterator iter = myStops.begin(); iter != myStops.end(); ++iter) {
1892 result.push_back(std::make_pair(
1893 (int)(iter->edge - myRoute->begin()),
1894 iter->getEndPos(*this)));
1895 }
1896 return result;
1897}
1898
1899
1900const MSStop&
1902 assert(myStops.size() > 0);
1903 return myStops.front();
1904}
1905
1906MSStop&
1908 assert(myStops.size() > 0);
1909 return myStops.front();
1910}
1911
1914 if (isStopped()) {
1915 return myStops.front().duration;
1916 } else {
1917 return 0;
1918 }
1919}
1920
1921
1922MSStop&
1923MSBaseVehicle::getStop(int nextStopIndex) {
1924 if (nextStopIndex < 0 || (int)myStops.size() <= nextStopIndex) {
1925 throw InvalidArgument(TLF("Invalid stop index % (has % stops).", nextStopIndex, myStops.size()));
1926 }
1927 auto stopIt = myStops.begin();
1928 std::advance(stopIt, nextStopIndex);
1929 return *stopIt;
1930}
1931
1932
1935 if (hasStops()) {
1936 return &myStops.front().pars;
1937 }
1938 return nullptr;
1939}
1940
1941
1942bool
1944 //if the stop exists update the duration
1945 for (std::list<MSStop>::iterator iter = myStops.begin(); iter != myStops.end(); iter++) {
1946 if (iter->lane->getID() == stop.lane && fabs(iter->pars.endPos - stop.endPos) < POSITION_EPS) {
1947 // update existing stop
1948 if (stop.duration == 0 && stop.until < 0 && !iter->reached) {
1949 myStops.erase(iter);
1950 } else {
1951 iter->duration = stop.duration;
1952 iter->triggered = stop.triggered;
1953 iter->containerTriggered = stop.containerTriggered;
1954 const_cast<SUMOVehicleParameter::Stop&>(iter->pars).until = stop.until;
1955 const_cast<SUMOVehicleParameter::Stop&>(iter->pars).parking = stop.parking;
1956 }
1957 return true;
1958 }
1959 }
1960 const bool result = addStop(stop, errorMsg);
1961 if (result) {
1963 myParameter->stops.push_back(stop);
1964 }
1965 return result;
1966}
1967
1968
1969void
1976
1977
1978bool
1980 if (hasStops() && nextStopIndex < (int)myStops.size()) {
1981 if (nextStopIndex == 0 && isStopped()) {
1983 } else {
1984 auto stopIt = myStops.begin();
1985 std::advance(stopIt, nextStopIndex);
1986 myStops.erase(stopIt);
1987 }
1988 if (!hasDeparted() && (int)myParameter->stops.size() > nextStopIndex) {
1989 // stops will be rebuilt from scratch on rerouting so we must patch the stops in myParameter
1990 auto stopIt2 = myParameter->stops.begin();
1991 std::advance(stopIt2, nextStopIndex);
1992 const_cast<SUMOVehicleParameter*>(myParameter)->stops.erase(stopIt2);
1993 }
1994 return true;
1995 } else {
1996 return false;
1997 }
1998}
1999
2000
2001bool
2002MSBaseVehicle::replaceStop(int nextStopIndex, SUMOVehicleParameter::Stop stop, const std::string& info, bool teleport, std::string& errorMsg) {
2003 const int n = (int)myStops.size();
2004 if (nextStopIndex < 0 || nextStopIndex >= n) {
2005 errorMsg = TLF("invalid nextStopIndex % for % remaining stops", nextStopIndex, n);
2006 return false;
2007 }
2008 if (nextStopIndex == 0 && isStopped()) {
2009 errorMsg = TL("cannot replace reached stop");
2010 return false;
2011 }
2013 MSLane* stopLane = MSLane::dictionary(stop.lane);
2014 MSEdge* stopEdge = &stopLane->getEdge();
2015
2016 auto itStop = myStops.begin();
2017 std::advance(itStop, nextStopIndex);
2018 MSStop& replacedStop = *itStop;
2019
2020 // check parking access rights
2021 if (stop.parkingarea != "") {
2023 if (pa != nullptr && !pa->accepts(this)) {
2024 errorMsg = TLF("vehicle '%' does not have the right badge to access parkingArea '%'", getID(), stop.parkingarea);
2025 return false;
2026 }
2027 }
2028
2029 if (replacedStop.lane == stopLane && replacedStop.pars.endPos == stop.endPos && !teleport) {
2030 // only replace stop attributes
2031 const_cast<SUMOVehicleParameter::Stop&>(replacedStop.pars) = stop;
2032 replacedStop.initPars(stop);
2033 return true;
2034 }
2035
2036 if (!stopLane->allowsVehicleClass(getVClass(), myRoutingMode)) {
2037 errorMsg = TLF("disallowed stop lane '%'", stopLane->getID());
2038 return false;
2039 }
2040
2041 const ConstMSEdgeVector& oldEdges = getRoute().getEdges();
2042 std::vector<MSStop> stops(myStops.begin(), myStops.end());
2043 const int junctionOffset = getLane() != nullptr && getLane()->isInternal() ? 1 : 0;
2044 MSRouteIterator itStart = nextStopIndex == 0 ? getCurrentRouteEdge() + junctionOffset : stops[nextStopIndex - 1].edge;
2045 double startPos = nextStopIndex == 0 ? getPositionOnLane() : stops[nextStopIndex - 1].pars.endPos;
2046 MSRouteIterator itEnd = nextStopIndex == n - 1 ? oldEdges.end() - 1 : stops[nextStopIndex + 1].edge;
2047 auto endPos = nextStopIndex == n - 1 ? getArrivalPos() : stops[nextStopIndex + 1].pars.endPos;
2049
2050 bool newDestination = nextStopIndex == n - 1 && stops[nextStopIndex].edge == oldEdges.end() - 1;
2051
2052 ConstMSEdgeVector toNewStop;
2053 if (!teleport) {
2054 router.compute(*itStart, startPos, stopEdge, stop.endPos, this, t, toNewStop, true);
2055 if (toNewStop.size() == 0) {
2056 errorMsg = TLF("no route found from edge '%' to stop edge '%'", (*itStart)->getID(), stopEdge->getID());
2057 return false;
2058 }
2059 }
2060
2061 ConstMSEdgeVector fromNewStop;
2062 if (!newDestination) {
2063 router.compute(stopEdge, stop.endPos, *itEnd, endPos, this, t, fromNewStop, true);
2064 if (fromNewStop.size() == 0) {
2065 errorMsg = TLF("no route found from stop edge '%' to edge '%'", stopEdge->getID(), (*itEnd)->getID());
2066 return false;
2067 }
2068 }
2069
2070 const_cast<SUMOVehicleParameter::Stop&>(replacedStop.pars) = stop;
2071 replacedStop.initPars(stop);
2072 replacedStop.edge = myRoute->end(); // will be patched in replaceRoute
2073 replacedStop.lane = stopLane;
2075 replacedStop.segment = MSGlobals::gMesoNet->getSegmentForEdge(replacedStop.lane->getEdge(), replacedStop.getEndPos(*this));
2076 if (replacedStop.lane->isInternal()) {
2077 errorMsg = TLF("Mesoscopic simulation does not allow stopping on internal edge '%' for vehicle '%'.", stop.edge, getID());
2078 return false;
2079 }
2080 }
2081
2082 ConstMSEdgeVector oldRemainingEdges(myCurrEdge, getRoute().end());
2083 ConstMSEdgeVector newEdges; // only remaining
2084 newEdges.insert(newEdges.end(), myCurrEdge, itStart);
2085 if (!teleport) {
2086 newEdges.insert(newEdges.end(), toNewStop.begin(), toNewStop.end() - 1);
2087 } else {
2088 newEdges.push_back(*itStart);
2089 }
2090 if (!newDestination) {
2091 newEdges.insert(newEdges.end(), fromNewStop.begin(), fromNewStop.end() - 1);
2092 newEdges.insert(newEdges.end(), itEnd, oldEdges.end());
2093 } else {
2094 newEdges.push_back(stopEdge);
2095 }
2096 //std::cout << SIMTIME << " replaceStop veh=" << getID()
2097 // << " teleport=" << teleport
2098 // << " busStop=" << stop.busstop
2099 // << " oldEdges=" << oldRemainingEdges.size()
2100 // << " newEdges=" << newEdges.size()
2101 // << " toNewStop=" << toNewStop.size()
2102 // << " fromNewStop=" << fromNewStop.size()
2103 // << "\n";
2104
2105 const double routeCost = router.recomputeCosts(newEdges, this, t);
2106 const double previousCost = router.recomputeCosts(oldRemainingEdges, this, t);
2107 const double savings = previousCost - routeCost;
2108 if (!hasDeparted() && (int)myParameter->stops.size() > nextStopIndex) {
2109 // stops will be rebuilt from scratch so we must patch the stops in myParameter
2110 const_cast<SUMOVehicleParameter*>(myParameter)->stops[nextStopIndex] = stop;
2111 }
2112 if (teleport) {
2113 // let the vehicle jump rather than teleport
2114 // we add a jump-stop at the end of the edge (unless the vehicle is
2115 // already configure to jump before the replaced stop)
2116 if (!insertJump(nextStopIndex, itStart, errorMsg)) {
2117 return false;
2118 };
2119 }
2120 return replaceRouteEdges(newEdges, routeCost, savings, info, !hasDeparted(), false, false, &errorMsg);
2121}
2122
2123
2124bool
2125MSBaseVehicle::rerouteBetweenStops(int nextStopIndex, const std::string& info, bool teleport, std::string& errorMsg) {
2126 const int n = (int)myStops.size();
2127 if (nextStopIndex < 0 || nextStopIndex > n) {
2128 errorMsg = TLF("invalid nextStopIndex % for % remaining stops", nextStopIndex, n);
2129 return false;
2130 }
2131 if (nextStopIndex == 0 && isStopped()) {
2132 errorMsg = TL("cannot reroute towards reached stop");
2133 return false;
2134 }
2136
2137 const ConstMSEdgeVector& oldEdges = getRoute().getEdges();
2138 std::vector<MSStop> stops(myStops.begin(), myStops.end());
2139 const int junctionOffset = getLane() != nullptr && getLane()->isInternal() ? 1 : 0;
2140 MSRouteIterator itStart = nextStopIndex == 0 ? getCurrentRouteEdge() + junctionOffset : stops[nextStopIndex - 1].edge;
2141 double startPos = nextStopIndex == 0 ? getPositionOnLane() : stops[nextStopIndex - 1].pars.endPos;
2142 MSRouteIterator itEnd = nextStopIndex == n ? oldEdges.end() - 1 : stops[nextStopIndex].edge;
2143 auto endPos = nextStopIndex == n ? getArrivalPos() : stops[nextStopIndex].pars.endPos;
2145
2146 ConstMSEdgeVector newBetween;
2147 if (!teleport) {
2148 router.compute(*itStart, startPos, *itEnd, endPos, this, t, newBetween, true);
2149 if (newBetween.size() == 0) {
2150 errorMsg = TLF("no route found from edge '%' to stop edge '%'", (*itStart)->getID(), (*itEnd)->getID());
2151 return false;
2152 }
2153 }
2154
2155 ConstMSEdgeVector oldRemainingEdges(myCurrEdge, getRoute().end());
2156 ConstMSEdgeVector newEdges; // only remaining
2157 newEdges.insert(newEdges.end(), myCurrEdge, itStart);
2158 if (!teleport) {
2159 newEdges.insert(newEdges.end(), newBetween.begin(), newBetween.end() - 1);
2160 } else {
2161 newEdges.push_back(*itStart);
2162 }
2163 newEdges.insert(newEdges.end(), itEnd, oldEdges.end());
2164 //std::cout << SIMTIME << " rerouteBetweenStops veh=" << getID()
2165 // << " oldEdges=" << oldRemainingEdges.size()
2166 // << " newEdges=" << newEdges.size()
2167 // << " toNewStop=" << toNewStop.size()
2168 // << " fromNewStop=" << fromNewStop.size()
2169 // << "\n";
2170
2171 const double routeCost = router.recomputeCosts(newEdges, this, t);
2172 const double previousCost = router.recomputeCosts(oldRemainingEdges, this, t);
2173 const double savings = previousCost - routeCost;
2174
2175 if (teleport) {
2176 // let the vehicle jump rather than teleport
2177 // we add a jump-stop at the end of the edge (unless the vehicle is
2178 // already configure to jump before the replaced stop)
2179 if (!insertJump(nextStopIndex, itStart, errorMsg)) {
2180 return false;
2181 };
2182 }
2183 return replaceRouteEdges(newEdges, routeCost, savings, info, !hasDeparted(), false, false, &errorMsg);
2184}
2185
2186
2187bool
2188MSBaseVehicle::insertJump(int nextStopIndex, MSRouteIterator itStart, std::string& errorMsg) {
2189 bool needJump = true;
2190 if (nextStopIndex > 0) {
2191 auto itPriorStop = myStops.begin();
2192 std::advance(itPriorStop, nextStopIndex - 1);
2193 const MSStop& priorStop = *itPriorStop;
2194 if (priorStop.pars.jump >= 0) {
2195 needJump = false;
2196 }
2197 }
2198 if (needJump) {
2199 SUMOVehicleParameter::Stop jumpStopPars;
2200 jumpStopPars.endPos = (*itStart)->getLength();
2201 jumpStopPars.speed = 1000;
2202 jumpStopPars.jump = 0;
2203 jumpStopPars.edge = (*itStart)->getID();
2205 MSLane* jumpStopLane = nullptr;
2206 for (MSLane* cand : (*itStart)->getLanes()) {
2207 if (cand->allowsVehicleClass(getVClass())) {
2208 jumpStopLane = cand;
2209 break;
2210 }
2211 }
2212 if (jumpStopLane == nullptr) {
2213 errorMsg = TL("unable to replace stop with teleporting");
2214 return false;
2215 }
2216 auto itStop = myStops.begin();
2217 std::advance(itStop, nextStopIndex);
2218 MSStop jumpStop(jumpStopPars);
2219 jumpStop.initPars(jumpStopPars);
2220 jumpStop.lane = jumpStopLane;
2221 jumpStop.edge = myRoute->end(); // will be patched in replaceRoute
2222 myStops.insert(itStop, jumpStop);
2223 if (!hasDeparted() && (int)myParameter->stops.size() > nextStopIndex) {
2224 // stops will be rebuilt from scratch so we must patch the stops in myParameter
2225 auto it = myParameter->stops.begin() + nextStopIndex;
2226 const_cast<SUMOVehicleParameter*>(myParameter)->stops.insert(it, jumpStopPars);
2227 }
2228 }
2229 return true;
2230}
2231
2232
2233bool
2234MSBaseVehicle::insertStop(int nextStopIndex, SUMOVehicleParameter::Stop stop, const std::string& info, bool teleport, std::string& errorMsg) {
2235 const int n = (int)myStops.size();
2236 if (nextStopIndex < 0 || nextStopIndex > n) {
2237 errorMsg = TLF("invalid nextStopIndex % for % remaining stops", nextStopIndex, n);
2238 return false;
2239 }
2240 if (nextStopIndex == 0 && isStopped()) {
2241 errorMsg = TL("cannot insert stop before the currently reached stop");
2242 return false;
2243 }
2245 MSLane* stopLane = MSLane::dictionary(stop.lane);
2246 MSEdge* stopEdge = &stopLane->getEdge();
2247
2248 if (!stopLane->allowsVehicleClass(getVClass(), myRoutingMode)) {
2249 errorMsg = TLF("disallowed stop lane '%'", stopLane->getID());
2250 return false;
2251 }
2252
2253 // check parking access rights
2254 if (stop.parkingarea != "") {
2256 if (pa != nullptr && !pa->accepts(this)) {
2257 errorMsg = TLF("Vehicle '%' does not have the right badge to access parkingArea '%'.", getID(), stop.parkingarea);
2258 return false;
2259 }
2260 }
2261
2262 const ConstMSEdgeVector& oldEdges = getRoute().getEdges();
2263 std::vector<MSStop> stops(myStops.begin(), myStops.end());
2264 const int junctionOffset = getLane() != nullptr && getLane()->isInternal() ? 1 : 0;
2265 MSRouteIterator itStart = nextStopIndex == 0 ? getCurrentRouteEdge() + junctionOffset : stops[nextStopIndex - 1].edge;
2266 double startPos = nextStopIndex == 0 ? getPositionOnLane() : stops[nextStopIndex - 1].pars.endPos;
2267 MSRouteIterator itEnd = nextStopIndex == n ? oldEdges.end() - 1 : stops[nextStopIndex].edge;
2268 auto endPos = nextStopIndex == n ? getArrivalPos() : stops[nextStopIndex].pars.endPos;
2270
2271 bool newDestination = nextStopIndex == n && stopEdge == oldEdges.back();
2272
2273 ConstMSEdgeVector toNewStop;
2274 if (!teleport) {
2275 router.compute(*itStart, startPos, stopEdge, stop.endPos, this, t, toNewStop, true);
2276 if (toNewStop.size() == 0) {
2277 errorMsg = TLF("no route found from edge '%' to stop edge '%'", (*itStart)->getID(), stopEdge->getID());
2278 return false;
2279 }
2280 }
2281
2282 ConstMSEdgeVector fromNewStop;
2283 if (!newDestination) {
2284 router.compute(stopEdge, stop.endPos, *itEnd, endPos, this, t, fromNewStop, true);
2285 if (fromNewStop.size() == 0) {
2286 errorMsg = TLF("no route found from stop edge '%' to edge '%'", stopEdge->getID(), (*itEnd)->getID());
2287 return false;
2288 }
2289 }
2290
2291 auto itStop = myStops.begin();
2292 std::advance(itStop, nextStopIndex);
2293 MSStop newStop(stop);
2294 newStop.initPars(stop);
2295 newStop.edge = myRoute->end(); // will be patched in replaceRoute
2296 newStop.lane = stopLane;
2298 newStop.segment = MSGlobals::gMesoNet->getSegmentForEdge(newStop.lane->getEdge(), newStop.getEndPos(*this));
2299 if (newStop.lane->isInternal()) {
2300 errorMsg = TLF("Mesoscopic simulation does not allow stopping on internal edge '%' for vehicle '%'.", stop.edge, getID());
2301 return false;
2302 }
2303 }
2304 myStops.insert(itStop, newStop);
2305
2306 ConstMSEdgeVector oldRemainingEdges(myCurrEdge, getRoute().end());
2307 ConstMSEdgeVector newEdges; // only remaining
2308 newEdges.insert(newEdges.end(), myCurrEdge, itStart);
2309 if (!teleport) {
2310 newEdges.insert(newEdges.end(), toNewStop.begin(), toNewStop.end() - 1);
2311 } else {
2312 newEdges.push_back(*itStart);
2313 }
2314 if (!newDestination) {
2315 newEdges.insert(newEdges.end(), fromNewStop.begin(), fromNewStop.end() - 1);
2316 newEdges.insert(newEdges.end(), itEnd, oldEdges.end());
2317 } else {
2318 newEdges.push_back(stopEdge);
2319 }
2320 //std::cout << SIMTIME << " insertStop veh=" << getID()
2321 // << " teleport=" << teleport
2322 // << " busStop=" << stop.busstop
2323 // << " oldEdges=" << oldRemainingEdges.size()
2324 // << " newEdges=" << newEdges.size()
2325 // << " toNewStop=" << toNewStop.size()
2326 // << " fromNewStop=" << fromNewStop.size()
2327 // << "\n";
2328
2329 const double routeCost = router.recomputeCosts(newEdges, this, t);
2330 const double previousCost = router.recomputeCosts(oldRemainingEdges, this, t);
2331 const double savings = previousCost - routeCost;
2332
2333 if (!hasDeparted() && (int)myParameter->stops.size() >= nextStopIndex) {
2334 // stops will be rebuilt from scratch so we must patch the stops in myParameter
2335 auto it = myParameter->stops.begin() + nextStopIndex;
2336 const_cast<SUMOVehicleParameter*>(myParameter)->stops.insert(it, stop);
2337 }
2338 return replaceRouteEdges(newEdges, routeCost, savings, info, !hasDeparted(), false, false, &errorMsg);
2339}
2340
2341
2342double
2344 if (static_cast<MSDevice_Battery*>(getDevice(typeid(MSDevice_Battery))) != 0) {
2345 MSDevice_Battery* batteryOfVehicle = dynamic_cast<MSDevice_Battery*>(getDevice(typeid(MSDevice_Battery)));
2346 return batteryOfVehicle->getActualBatteryCapacity();
2347 } else {
2348 if (static_cast<MSDevice_ElecHybrid*>(getDevice(typeid(MSDevice_ElecHybrid))) != 0) {
2349 MSDevice_ElecHybrid* batteryOfVehicle = dynamic_cast<MSDevice_ElecHybrid*>(getDevice(typeid(MSDevice_ElecHybrid)));
2350 return batteryOfVehicle->getActualBatteryCapacity();
2351 }
2352 }
2353 return -1;
2354}
2355
2356
2357double
2359 if (static_cast<MSDevice_Battery*>(getDevice(typeid(MSDevice_Battery))) != 0) {
2360 MSDevice_Battery* batteryOfVehicle = dynamic_cast<MSDevice_Battery*>(getDevice(typeid(MSDevice_Battery)));
2361 return batteryOfVehicle->getActualBatteryCapacity() / batteryOfVehicle->getMaximumBatteryCapacity();
2362 } else {
2363 if (static_cast<MSDevice_ElecHybrid*>(getDevice(typeid(MSDevice_ElecHybrid))) != 0) {
2364 MSDevice_ElecHybrid* batteryOfVehicle = dynamic_cast<MSDevice_ElecHybrid*>(getDevice(typeid(MSDevice_ElecHybrid)));
2365 return batteryOfVehicle->getActualBatteryCapacity() / batteryOfVehicle->getMaximumBatteryCapacity();
2366 }
2367 }
2368 return -1;
2369}
2370
2371
2372double
2374 if (static_cast<MSDevice_Battery*>(getDevice(typeid(MSDevice_Battery))) != 0) {
2375 MSDevice_Battery* batteryOfVehicle = dynamic_cast<MSDevice_Battery*>(getDevice(typeid(MSDevice_Battery)));
2376 return batteryOfVehicle->getEnergyCharged();
2377 } else {
2378 if (static_cast<MSDevice_ElecHybrid*>(getDevice(typeid(MSDevice_ElecHybrid))) != 0) {
2379 MSDevice_ElecHybrid* batteryOfVehicle = dynamic_cast<MSDevice_ElecHybrid*>(getDevice(typeid(MSDevice_ElecHybrid)));
2380 return batteryOfVehicle->getEnergyCharged();
2381 }
2382 }
2383 return -1;
2384}
2385
2386
2387double
2389 if (static_cast<MSDevice_Battery*>(getDevice(typeid(MSDevice_Battery))) != 0) {
2390 MSDevice_Battery* batteryOfVehicle = dynamic_cast<MSDevice_Battery*>(getDevice(typeid(MSDevice_Battery)));
2391 return batteryOfVehicle->getMaximumChargeRate();
2392 }
2393 return -1;
2394}
2395
2396
2397double
2399 if (static_cast<MSDevice_ElecHybrid*>(getDevice(typeid(MSDevice_ElecHybrid))) != 0) {
2400 MSDevice_ElecHybrid* elecHybridDevice = dynamic_cast<MSDevice_ElecHybrid*>(getDevice(typeid(MSDevice_ElecHybrid)));
2401 return elecHybridDevice->getCurrentFromOverheadWire();
2402 }
2403
2404 return NAN;
2405}
2406
2407double
2409 if (isOnRoad() || isIdling()) {
2411 } else {
2412 return 0.;
2413 }
2414}
2415
2416
2421
2422
2427
2428
2431 if (myEdgeWeights == nullptr) {
2433 }
2434 return *myEdgeWeights;
2435}
2436
2437
2438
2439
2440int
2442 int boarded = myPersonDevice == nullptr ? 0 : myPersonDevice->size();
2443 return boarded + myParameter->personNumber;
2444}
2445
2446int
2448 int leavingPersonNumber = 0;
2449 const std::vector<MSTransportable*>& persons = getPersons();
2450 for (std::vector<MSTransportable*>::const_iterator it_p = persons.begin(); it_p != persons.end(); ++it_p) {
2451 MSStageDriving* const stage = dynamic_cast<MSStageDriving*>((*it_p)->getCurrentStage());
2452 const MSStop* stop = &myStops.front();
2453 const MSVehicle* joinVeh = dynamic_cast<MSVehicle*>(MSNet::getInstance()->getVehicleControl().getVehicle((*stop).pars.join));
2454 if (stop && stage->canLeaveVehicle(*it_p, *this, *stop) && !MSDevice_Transportable::willTransferAtJoin(*it_p, joinVeh)) {
2455 leavingPersonNumber++;
2456 }
2457 }
2458 return leavingPersonNumber;
2459}
2460
2461std::vector<std::string>
2463 std::vector<std::string> ret;
2464 const std::vector<MSTransportable*>& persons = getPersons();
2465 for (std::vector<MSTransportable*>::const_iterator it_p = persons.begin(); it_p != persons.end(); ++it_p) {
2466 ret.push_back((*it_p)->getID());
2467 }
2468 return ret;
2469}
2470
2471int
2473 int loaded = myContainerDevice == nullptr ? 0 : myContainerDevice->size();
2474 return loaded + myParameter->containerNumber;
2475}
2476
2477
2478void
2480 // this might be called from the MSTransportable destructor so we cannot do a dynamic cast to determine the type
2481 if (myPersonDevice != nullptr) {
2483 }
2484 if (myContainerDevice != nullptr) {
2486 }
2487 if (myEnergyParams != nullptr) {
2489 }
2490}
2491
2492
2493void
2499
2500
2501const std::vector<MSTransportable*>&
2503 if (myPersonDevice == nullptr) {
2505 } else {
2507 }
2508}
2509
2510
2511const std::vector<MSTransportable*>&
2513 if (myContainerDevice == nullptr) {
2515 } else {
2517 }
2518}
2519
2520
2521bool
2522MSBaseVehicle::isLineStop(double position) const {
2523 if (myParameter->line == "") {
2524 // not a public transport line
2525 return false;
2526 }
2527 for (const SUMOVehicleParameter::Stop& stop : myParameter->stops) {
2528 if (stop.startPos <= position && position <= stop.endPos) {
2529 return true;
2530 }
2531 }
2532 for (const SUMOVehicleParameter::Stop& stop : myRoute->getStops()) {
2533 if (stop.startPos <= position && position <= stop.endPos) {
2534 return true;
2535 }
2536 }
2537 return false;
2538}
2539
2540
2541bool
2542MSBaseVehicle::hasDevice(const std::string& deviceName) const {
2543 for (MSDevice* const dev : myDevices) {
2544 if (dev->deviceName() == deviceName) {
2545 return true;
2546 }
2547 }
2548 return false;
2549}
2550
2551
2552void
2553MSBaseVehicle::createDevice(const std::string& deviceName) {
2554 if (!hasDevice(deviceName)) {
2555 if (deviceName == "rerouting") {
2556 ((SUMOVehicleParameter*)myParameter)->setParameter("has." + deviceName + ".device", "true");
2558 if (hasDeparted()) {
2559 // vehicle already departed: disable pre-insertion rerouting and enable regular routing behavior
2560 MSDevice_Routing* routingDevice = static_cast<MSDevice_Routing*>(getDevice(typeid(MSDevice_Routing)));
2561 assert(routingDevice != 0);
2563 }
2564 } else {
2565 throw InvalidArgument(TLF("creating device of type '%' is not supported", deviceName));
2566 }
2567 }
2568}
2569
2570
2571std::string
2572MSBaseVehicle::getDeviceParameter(const std::string& deviceName, const std::string& key) const {
2573 for (MSVehicleDevice* const dev : myDevices) {
2574 if (dev->deviceName() == deviceName) {
2575 return dev->getParameter(key);
2576 }
2577 }
2578 throw InvalidArgument(TLF("no device of type '%' exists", deviceName));
2579}
2580
2581
2582void
2583MSBaseVehicle::setDeviceParameter(const std::string& deviceName, const std::string& key, const std::string& value) {
2584 for (MSVehicleDevice* const dev : myDevices) {
2585 if (dev->deviceName() == deviceName) {
2586 dev->setParameter(key, value);
2587 return;
2588 }
2589 }
2590 throw InvalidArgument(TLF("no device of type '%' exists", deviceName));
2591}
2592
2593
2594void
2595MSBaseVehicle::setJunctionModelParameter(const std::string& key, const std::string& value) {
2598 const_cast<SUMOVehicleParameter&>(getParameter()).setParameter(key, value);
2599 // checked in MSLink::ignoreFoe
2600 } else {
2601 throw InvalidArgument(TLF("Vehicle '%' does not support junctionModel parameter '%'.", getID(), key));
2602 }
2603}
2604
2605
2606void
2607MSBaseVehicle::setCarFollowModelParameter(const std::string& key, const std::string& value) {
2608 // handle some generic params first and then delegate to the carFollowModel itself
2611 const_cast<SUMOVehicleParameter&>(getParameter()).setParameter(key, value);
2612 // checked in MSVehicle::planMove
2613 } else {
2614 MSVehicle* microVeh = dynamic_cast<MSVehicle*>(this);
2615 if (microVeh) {
2616 // remove 'carFollowModel.' prefix
2617 const std::string attrName = key.substr(15);
2618 microVeh->getCarFollowModel().setParameter(microVeh, attrName, value);
2619 }
2620 }
2621}
2622
2623
2624void
2626 /* Design idea for additional junction model parameters:
2627 We can distinguish between 3 levels of parameters
2628 1. typically shared by multiple vehicles -> vType parameter
2629 2. specific to one vehicle but stays constant throughout the simulation -> vehicle parameter
2630 3. specific to one vehicle and expected to change during simulation -> prefixed generic vehicle parameter
2631 */
2632 for (auto item : getParameter().getParametersMap()) {
2633 if (StringUtils::startsWith(item.first, "junctionModel.")) {
2634 setJunctionModelParameter(item.first, item.second);
2635 } else if (StringUtils::startsWith(item.first, "carFollowModel.")) {
2636 setCarFollowModelParameter(item.first, item.second);
2637 }
2638 }
2639 const std::string routingModeStr = getStringParam("device.rerouting.mode");
2640 try {
2641 int routingMode = StringUtils::toInt(routingModeStr);
2642 if (routingMode != libsumo::ROUTING_MODE_DEFAULT) {
2643 setRoutingMode(routingMode);
2644 }
2645 } catch (NumberFormatException&) {
2646 // @todo interpret symbolic constants
2647 throw ProcessError(TLF("could not interpret routing.mode '%'", routingModeStr));
2648 }
2649}
2650
2651
2660
2661
2662void
2664 assert(type != nullptr);
2665 // save old parameters before possible type deletion
2666 const double oldMu = myType->getSpeedFactor().getParameter(0);
2667 const double oldDev = myType->getSpeedFactor().getParameter(1);
2668 if (myType->isVehicleSpecific() && type != myType) {
2670 }
2671 // adapt myChosenSpeedFactor to the new type
2672 if (oldDev == 0.) {
2673 // old type had speedDev 0, reroll
2675 } else {
2676 // map old speedFactor onto new distribution
2677 const double distPoint = (myChosenSpeedFactor - oldMu) / oldDev;
2678 const double newMu = type->getSpeedFactor().getParameter(0);
2679 const double newDev = type->getSpeedFactor().getParameter(1);
2680 myChosenSpeedFactor = newMu + distPoint * newDev;
2681 // respect distribution limits
2684 }
2685 myType = type;
2686 if (myEnergyParams != nullptr) {
2688 }
2689}
2690
2691
2694 if (myType->isVehicleSpecific()) {
2695 return *const_cast<MSVehicleType*>(myType);
2696 }
2697 MSVehicleType* type = myType->buildSingularType(myType->getID() + "@" + getID());
2698 replaceVehicleType(type);
2699 return *type;
2700}
2701
2702
2703int
2705 const MSLane* const lane = getLane();
2706 if (lane == nullptr) {
2707 return getEdge()->getLanes()[0]->getRNGIndex();
2708 } else {
2709 return lane->getRNGIndex();
2710 }
2711}
2712
2713
2714SumoRNG*
2716 const MSLane* lane = getLane();
2717 if (lane == nullptr) {
2718 return getEdge()->getLanes()[0]->getRNG();
2719 } else {
2720 return lane->getRNG();
2721 }
2722}
2723
2724std::string
2725MSBaseVehicle::getPrefixedParameter(const std::string& key, std::string& error) const {
2726 const MSVehicle* microVeh = dynamic_cast<const MSVehicle*>(this);
2727 if (StringUtils::startsWith(key, "device.")) {
2728 StringTokenizer tok(key, ".");
2729 if (tok.size() < 3) {
2730 error = TLF("Invalid device parameter '%' for vehicle '%'.", key, getID());
2731 return "";
2732 }
2733 try {
2734 return getDeviceParameter(tok.get(1), key.substr(tok.get(0).size() + tok.get(1).size() + 2));
2735 } catch (InvalidArgument& e) {
2736 error = TLF("Vehicle '%' does not support device parameter '%' (%).", getID(), key, e.what());
2737 return "";
2738 }
2739 } else if (StringUtils::startsWith(key, "laneChangeModel.")) {
2740 if (microVeh == nullptr) {
2741 error = TLF("Mesoscopic vehicle '%' does not support laneChangeModel parameters.", getID());
2742 return "";
2743 }
2744 const std::string attrName = key.substr(16);
2745 try {
2746 return microVeh->getLaneChangeModel().getParameter(attrName);
2747 } catch (InvalidArgument& e) {
2748 error = TLF("Vehicle '%' does not support laneChangeModel parameter '%' (%).", getID(), key, e.what());
2749 return "";
2750 }
2751 } else if (StringUtils::startsWith(key, "carFollowModel.")) {
2752 if (microVeh == nullptr) {
2753 error = TLF("Mesoscopic vehicle '%' does not support carFollowModel parameters.", getID());
2754 return "";
2755 }
2756 const std::string attrName = key.substr(15);
2757 try {
2758 return microVeh->getCarFollowModel().getParameter(microVeh, attrName);
2759 } catch (InvalidArgument& e) {
2760 error = TLF("Vehicle '%' does not support carFollowModel parameter '%' (%).", getID(), key, e.what());
2761 return "";
2762 }
2763 } else if (StringUtils::startsWith(key, "has.") && StringUtils::endsWith(key, ".device")) {
2764 StringTokenizer tok(key, ".");
2765 if (tok.size() != 3) {
2766 error = TL("Invalid check for device. Expected format is 'has.DEVICENAME.device'.");
2767 return "";
2768 }
2769 return hasDevice(tok.get(1)) ? "true" : "false";
2770 // parking related parameters start here
2771 } else if (key == "parking.rerouteCount") {
2773 } else if (StringUtils::startsWith(key, "parking.memory.")) {
2774 std::vector<std::string> values;
2775 if (getParkingMemory()) {
2776 if (key == "parking.memory.IDList") {
2777 for (const auto& item : *getParkingMemory()) {
2778 values.push_back(item.first->getID());
2779 }
2780 } else if (key == "parking.memory.score") {
2781 for (const auto& item : *getParkingMemory()) {
2782 values.push_back(item.second.score);
2783 }
2784 } else if (key == "parking.memory.blockedAtTime") {
2785 for (const auto& item : *getParkingMemory()) {
2786 values.push_back(toString(STEPS2TIME(item.second.blockedAtTime)));
2787 }
2788 } else if (key == "parking.memory.blockedAtTimeLocal") {
2789 for (const auto& item : *getParkingMemory()) {
2790 values.push_back(toString(STEPS2TIME(item.second.blockedAtTimeLocal)));
2791 }
2792 } else {
2793 error = TLF("Unsupported parking parameter '%' for vehicle '%'.", key, getID());
2794 }
2795 }
2796 return toString(values);
2797 } else {
2798 // default: custom user parameter
2799 return getParameter().getParameter(key, "");
2800 }
2801}
2802
2803
2804void
2811
2812
2813void
2819
2820
2821void
2823 if (myChargingMemory == nullptr) {
2825 }
2827}
2828
2829
2830void
2836
2837
2838void
2839MSBaseVehicle::rememberParkingAreaScore(const MSStoppingPlace* pa, const std::string& score) {
2840 if (myParkingMemory == nullptr) {
2842 }
2844}
2845
2846
2849 if (myParkingMemory == nullptr) {
2850 return -1;
2851 }
2852 return myParkingMemory->sawBlockedStoppingPlace(pa, local);
2853}
2854
2855
2862
2863
2866 if (myChargingMemory == nullptr) {
2867 return -1;
2868 }
2869 return myChargingMemory->sawBlockedStoppingPlace(cs, local);
2870}
2871
2872
2873#ifdef _DEBUG
2874void
2875MSBaseVehicle::initMoveReminderOutput(const OptionsCont& oc) {
2876 if (oc.isSet("movereminder-output.vehicles")) {
2877 const std::vector<std::string> vehicles = oc.getStringVector("movereminder-output.vehicles");
2878 myShallTraceMoveReminders.insert(vehicles.begin(), vehicles.end());
2879 }
2880}
2881
2882
2883void
2884MSBaseVehicle::traceMoveReminder(const std::string& type, MSMoveReminder* rem, double pos, bool keep) const {
2885 OutputDevice& od = OutputDevice::getDeviceByOption("movereminder-output");
2886 od.openTag("movereminder");
2887 od.writeAttr(SUMO_ATTR_TIME, STEPS2TIME(MSNet::getInstance()->getCurrentTimeStep()));
2888 od.writeAttr("veh", getID());
2890 od.writeAttr("type", type);
2891 od.writeAttr("pos", toString(pos));
2892 od.writeAttr("keep", toString(keep));
2893 od.closeTag();
2894}
2895#endif
2896
2897
2898/****************************************************************************/
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:287
#define WRITE_ERRORF(...)
Definition MsgHandler.h:296
#define WRITE_WARNING(msg)
Definition MsgHandler.h:286
#define TL(string)
Definition MsgHandler.h:304
#define TLF(string,...)
Definition MsgHandler.h:306
std::shared_ptr< const MSRoute > ConstMSRoutePtr
Definition Route.h:32
std::string time2string(SUMOTime t, bool humanReadable)
convert SUMOTime to string (independently of global format setting)
Definition SUMOTime.cpp: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
double gWeightsRandomFactor
Definition StdDefs.cpp:35
int gPrecisionRandom
Definition StdDefs.cpp:30
const double INVALID_DOUBLE
invalid double
Definition StdDefs.h:68
T MIN2(T a, T b)
Definition StdDefs.h:80
const double SUMO_const_haltingSpeed
the speed threshold at which vehicles are considered as halting
Definition StdDefs.h:62
T MAX2(T a, T b)
Definition StdDefs.h:86
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition ToString.h: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 long long int myRandomSeed
const MSEdge * succEdge(int nSuccs) const
Returns the nSuccs'th successor of edge the vehicle is currently at.
int getDepartEdge() const
Returns the edge on which this vehicle shall depart.
void resetRoutePosition(int index, DepartLaneDefinition departLaneProcedure)
reset index of edge within route
std::string getDeviceParameter(const std::string &deviceName, const std::string &key) const
try to retrieve the given parameter from any of the vehicles devices, raise InvalidArgument if no dev...
StoppingPlaceMemory * myChargingMemory
bool replaceStop(int nextStopIndex, SUMOVehicleParameter::Stop stop, const std::string &info, bool teleport, std::string &errorMsg)
int getLeavingPersonNumber() const
Returns the number of leaving persons.
MSBaseVehicle(SUMOVehicleParameter *pars, ConstMSRoutePtr route, MSVehicleType *type, const double speedFactor)
Constructor.
void calculateArrivalParams(bool onInit)
(Re-)Calculates the arrival position and lane from the vehicle parameters
virtual double getArrivalPos() const
Returns this vehicle's desired arrivalPos for its current route (may change on reroute)
void setCarFollowModelParameter(const std::string &key, const std::string &value)
set individual carFollow model parameters (not type related)
void setRoutingMode(int value)
Sets routing behavior.
void resetParkingAreaScores()
static NumericalID myCurrentNumericalIndex
bool rerouteBetweenStops(int nextStopIndex, const std::string &info, bool teleport, std::string &errorMsg)
MoveReminderCont myMoveReminders
Currently relevant move reminders.
void rememberChargingStationScore(const MSStoppingPlace *cs, const std::string &score)
int getInsertionChecks() const
double myDepartPos
The real depart position.
const SUMOVehicleParameter & getParameter() const
Returns the vehicle's parameter (including departure definition)
double getMaxChargeRate() const
Returns the maximum charge rate allowed by the battery in the current time step (W)
void replaceParameter(const SUMOVehicleParameter *newParameter)
replace the vehicle parameter (deleting the old one)
void rememberBlockedParkingArea(const MSStoppingPlace *pa, bool local)
int getNumberParkingReroutes() const
std::vector< MSVehicleDevice * > myDevices
The devices this vehicle has.
virtual const MSEdge * getCurrentEdge() const
Returns the edge the vehicle is currently at (possibly an internal edge)
double getPreviousSpeed() const
Returns the vehicle's previous speed.
void removeTransportableMass(MSTransportable *t)
removes a person or containers mass
MSStop & getNextStopMutable()
virtual void addTransportable(MSTransportable *transportable)
Adds a person or container to this vehicle.
virtual BaseInfluencer & getBaseInfluencer()=0
Returns the velocity/lane influencer.
const SUMOVehicleParameter::Stop * getNextStopParameter() const
return parameters for the next stop (SUMOVehicle Interface)
void rememberBlockedChargingStation(const MSStoppingPlace *cs, bool local)
virtual bool replaceRoute(ConstMSRoutePtr route, const std::string &info, bool onInit=false, int offset=0, bool addRouteStops=true, bool removeStops=true, std::string *msgReturn=nullptr)
Replaces the current route by the given one.
SUMOTime activateRemindersOnReroute(SUMOTime currentTime)
remove outdated driveways on reroute
int getNumRemainingEdges() const
return the number of edges remaining in the route (include the current)
double getOdometer() const
Returns the distance that was already driven by this vehicle.
bool isRail() const
virtual bool hasArrived() const
Returns whether this vehicle has already 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)
MSRouteIterator myCurrEdge
Iterator to current route-edge.
static MSLane * interpretOppositeStop(SUMOVehicleParameter::Stop &stop)
interpret stop lane on opposite side of the road
StopParVector myPastStops
The list of stops that the vehicle has already reached.
static std::vector< MSTransportable * > myEmptyTransportableVector
const std::vector< std::string > & getParkingBadges() const
get the valid parking access rights (vehicle settings override vehicle type settings)
bool hasDeparted() const
Returns whether this vehicle has already departed.
bool ignoreTransientPermissions() const
Returns whether this object is ignoring transient permission changes (during routing)
virtual void resetApproachOnReroute()
reset rail signal approach information
ConstMSRoutePtr myRoute
This vehicle's route.
MSDevice_Transportable * myContainerDevice
The containers this vehicle may have.
void resetChargingStationScores()
bool allowsBoarding(const MSTransportable *t) const
whether the given transportable is allowed to board this vehicle
double getStateOfCharge() const
Returns actual state of charge of battery (Wh) RICE_CHECK: This may be a misnomer,...
MSEdgeWeightsStorage & _getWeightsStorage() const
virtual bool handleCollisionStop(MSStop &stop, const double distToStop)
bool hasDevice(const std::string &deviceName) const
check whether the vehicle is 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
bool replaceWithAlternative(std::list< MSStop >::iterator iter, const MSRouteIterator searchStart, const MSRouteIterator end)
replace stop with a same-name alternative that is on the route and return success
void addStops(const bool ignoreStopErrors, MSRouteIterator *searchStart=nullptr, bool addRouteStops=true)
Adds stops to the built vehicle.
void removeTransportable(MSTransportable *t)
removes a person or container
SUMOTime sawBlockedParkingArea(const MSStoppingPlace *pa, bool local) const
SUMOVehicleClass getVClass() const
Returns the vehicle's access class.
MSParkingArea * getNextParkingArea()
get the upcoming parking area stop or nullptr
int myArrivalLane
The destination lane where the vehicle stops.
int getRouteValidity(bool update=true, bool silent=false, std::string *msgReturn=nullptr)
check for route validity at first insertion attempt
MSStop & getStop(int nextStopIndex)
virtual ~MSBaseVehicle()
Destructor.
bool insertStop(int nextStopIndex, SUMOVehicleParameter::Stop stop, const std::string &info, bool teleport, std::string &errorMsg)
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 sufficientSaving(double oldCost, double newCost)
whether the change in saving is enough to trigger rerouting
bool notifyEnter(SUMOTrafficObject &veh, MSMoveReminder::Notification reason, const MSLane *enteredLane=0)
Computes a new route on vehicle insertion.
static void buildVehicleDevices(SUMOVehicle &v, std::vector< MSVehicleDevice * > &into)
Build devices for the given vehicle, if needed.
A device which collects info on the vehicle trip (mainly on departure and arrival)
bool allowsBoarding(const MSTransportable *t) const
whether the given person is allowed to board this taxi
const std::vector< MSTransportable * > & getTransportables() const
Returns the list of transportables using this vehicle.
static bool willTransferAtJoin(const MSTransportable *t, const MSBaseVehicle *joinVeh)
check if boardingDuration should be applied
static MSDevice_Transportable * buildVehicleDevices(SUMOVehicle &v, std::vector< MSVehicleDevice * > &into, const bool isContainer)
Build devices for the given vehicle, if needed.
int size() const
Return the number of passengers / containers.
void addTransportable(MSTransportable *transportable)
Add a passenger.
void removeTransportable(MSTransportable *transportable)
Remove a passenger (TraCI)
Abstract in-vehicle / in-person device.
Definition MSDevice.h:62
static void buildVehicleDevices(SUMOVehicle &v, std::vector< MSVehicleDevice * > &into)
Build devices for the given vehicle, if needed.
Definition MSDevice.cpp:114
A road/street connecting two junctions.
Definition MSEdge.h:77
static void clear()
Clears the dictionary.
Definition MSEdge.cpp:1102
bool hasTransientPermissions() const
Definition MSEdge.cpp:1681
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:1350
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:482
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:693
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
bool prohibits(const SUMOVehicle *const vehicle) const
Returns whether the vehicle (class) is not allowed on the edge.
Definition MSEdge.h:635
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:1057
const MSEdge * getNormalBefore() const
if this edge is an internal edge, return its first normal predecessor, otherwise the edge itself
Definition MSEdge.cpp:947
MSLane * getFirstAllowed(SUMOVehicleClass vClass, bool defaultFirst=false) const
Definition MSEdge.cpp:735
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:2465
double getLength() const
Returns the lane's length.
Definition MSLane.h:611
bool allowsVehicleClass(SUMOVehicleClass vclass) const
Definition MSLane.h:932
static bool dictionary(const std::string &id, MSLane *lane)
Static (sic!) container methods {.
Definition MSLane.cpp:2489
bool isInternal() const
Definition MSLane.cpp:2620
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:1750
@ NEWROUTE
The vehicle got a new route.
static MSNet * getInstance()
Returns the pointer to the unique instance of MSNet (singleton).
Definition MSNet.cpp:187
MSEventControl * getBeginOfTimestepEvents()
Returns the event control for events executed at the begin of a time step.
Definition MSNet.h:485
const std::vector< MSStoppingPlace * > & getStoppingPlaceAlternatives(const std::string &name, SumoXMLTag category) const
Definition MSNet.cpp:1502
MSVehicleRouter & getRouterTT(int rngIndex, const Prohibitions &prohibited={}) const
Definition MSNet.cpp:1610
SUMOTime getCurrentTimeStep() const
Returns the current simulation step.
Definition MSNet.h:334
static bool hasInstance()
Returns whether the network was already constructed.
Definition MSNet.h:158
MSStoppingPlace * getStoppingPlace(const std::string &id, const SumoXMLTag category) const
Returns the named stopping place of the given category.
Definition MSNet.cpp:1467
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:1342
MSInsertionControl & getInsertionControl()
Returns the insertion control.
Definition MSNet.h:445
MSVehicleControl & getVehicleControl()
Returns the vehicle control.
Definition MSNet.h:392
A lane area vehicles can halt at.
bool accepts(SUMOVehicle *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:128
void setCosts(double costs)
Sets the costs of the route.
Definition MSRoute.h:209
static bool hasRoute(const std::string &id)
returns whether a route with the given id exists
Definition MSRoute.cpp:159
static bool dictionary(const std::string &id, ConstMSRoutePtr route)
Adds a route to the dictionary.
Definition MSRoute.cpp:116
static void checkDist(const std::string &id)
Checks the distribution whether it is permanent and deletes it if not.
Definition MSRoute.cpp:194
void setSavings(double savings)
Sets the savings of the route.
Definition MSRoute.h:216
static MSVehicleRouter & getRouterTT(const int rngIndex, SUMOVehicleClass svc, const Prohibitions &prohibited={})
return the vehicle router instance
bool canLeaveVehicle(const MSTransportable *t, const SUMOVehicle &veh, const MSStop &stop)
checks whether the person may exit at the current vehicle position
const MSLane * lane
The lane to stop at (microsim only)
Definition MSStop.h:50
MSStoppingPlace * containerstop
(Optional) container stop if one is assigned to the stop
Definition MSStop.h:56
std::string getDescription(bool nameOnly=false) const
get a short description for showing in the gui
Definition MSStop.cpp:70
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:148
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:36
MSParkingArea * parkingarea
(Optional) parkingArea if one is assigned to the stop
Definition MSStop.h:58
MSStoppingPlace * chargingStation
(Optional) charging station if one is assigned to the stop
Definition MSStop.h:60
SUMOTime getUntil() const
return until / ended time
Definition MSStop.cpp:187
SUMOTime getArrival() const
return arrival / started time
Definition MSStop.cpp:193
const SUMOVehicleParameter::Stop pars
The stop parameter.
Definition MSStop.h:65
MSStoppingPlace * busstop
(Optional) bus stop if one is assigned to the stop
Definition MSStop.h:54
MSStoppingPlace * overheadWireSegment
(Optional) overhead wire segment if one is assigned to the stop
Definition MSStop.h:63
Finds a sequence of skips and stop alternatives to maximize priority of reached stops.
ConstMSEdgeVector optimizeSkipped(const MSEdge *source, double sourcePos, std::vector< StopEdgeInfo > &stops, ConstMSEdgeVector edges) const
A lane area vehicles can halt at.
double getBeginLanePosition() const
Returns the begin position of this stop.
double getParkingLength() const
double getEndLanePosition() const
Returns the end position of this stop.
const MSLane & getLane() const
Returns the lane this stop is located at.
bool isPerson() const override
Whether it is a person.
const MSVehicleType & getVehicleType() const override
Returns the object's "vehicle" type.
static const double DEFAULT_MAXDELAY
void vehicleDeparted(const SUMOVehicle &v)
Informs this control about a vehicle's departure.
SUMOVehicle * getVehicle(const std::string &id) const
Returns the vehicle with the given id.
void removeVType(const MSVehicleType *vehType)
void unregisterOneWaiting()
decreases the count of vehicles waiting for a transport to allow recognition of person / container re...
Abstract in-vehicle device.
Representation of a vehicle in the micro simulation.
Definition MSVehicle.h:77
MSAbstractLaneChangeModel & getLaneChangeModel()
const MSCFModel & getCarFollowModel() const
Returns the vehicle's car following model definition.
Definition MSVehicle.h: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
Utility functions for using a global, resetable random number generator.
Definition RandHelper.h:133
static double rand(SumoRNG *rng=nullptr)
Returns a random real number in [0, 1)
virtual bool compute(const E *from, const E *to, const V *const vehicle, SUMOTime msTime, std::vector< const E * > &into, bool silent=false)=0
Builds the route between the given edges using the minimum effort at the given time The definition of...
virtual double recomputeCosts(const std::vector< const E * > &edges, const V *const v, SUMOTime msTime, double *lengthp=nullptr) const
double recomputeCostsPos(const std::vector< const E * > &edges, const V *const v, double fromPos, double toPos, SUMOTime msTime, double *lengthp=nullptr) const
std::string getStringParam(const std::string &paramName, const bool required=false, const std::string &deflt="") const
Retrieve a string parameter for the traffic object.
virtual const MSLane * getLane() const =0
Returns the lane the object is currently at.
long long int NumericalID
virtual double getSpeed() const =0
Returns the object's current speed.
virtual SUMOTime getWaitingTime(const bool accumulated=false) const =0
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