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