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) {
883 myMoveReminders.insert(myMoveReminders.begin(), std::make_pair(myPersonDevice, 0.));
886 }
887 }
888 myPersonDevice->addTransportable(transportable);
889 } else {
890 if (myContainerDevice == nullptr) {
892 myMoveReminders.insert(myMoveReminders.begin(), std::make_pair(myContainerDevice, 0.));
895 }
896 }
897 myContainerDevice->addTransportable(transportable);
898 }
899 if (myEnergyParams != nullptr) {
901 }
902}
903
904
905bool
907 for (const MSStop& stop : myStops) {
908 if (stop.edge == it && stop.pars.jump >= 0) {
909 return true;
910 } else if (stop.edge > it) {
911 return false;
912 }
913 }
914 return false;
915}
916
917
918bool
919MSBaseVehicle::hasValidRoute(std::string& msg, ConstMSRoutePtr route) const {
921 if (route == nullptr) {
922 route = myRoute;
923 } else {
924 start = route->begin();
925 }
926 const bool checkJumps = route == myRoute; // the edge iterators in the stops are invalid otherwise
927 return hasValidRoute(msg, start, route->end(), checkJumps);
928}
929
930
931bool
932MSBaseVehicle::hasValidRoute(std::string& msg, MSRouteIterator start, MSRouteIterator last, bool checkJumps) const {
933 MSRouteIterator lastValid = last - 1;
934 // check connectivity, first
935 for (MSRouteIterator e = start; e != lastValid; ++e) {
936 const MSEdge& next = **(e + 1);
937 if ((*e)->allowedLanes(next, myType->getVehicleClass()) == nullptr) {
938 if (!checkJumps || !hasJump(e)) {
940 || (!next.hasTransientPermissions() && !(*e)->hasTransientPermissions())) {
941 msg = TLF("No connection between edge '%' and edge '%'.", (*e)->getID(), (*(e + 1))->getID());
942 return false;
943 }
944 }
945 }
946 }
947 // check usable lanes, then
948 for (MSRouteIterator e = start; e != last; ++e) {
949 if ((*e)->prohibits(this)) {
950 msg = TLF("Edge '%' prohibits.", (*e)->getID());
951 return false;
952 }
953 }
954 return true;
955}
956
957
958bool
960 if (!(*myCurrEdge)->isTazConnector()) {
962 msg = TLF("Departure speed for vehicle '%' is too high for the vehicle type '%'.", getID(), myType->getID());
964 return false;
965 }
966 }
967 if (myRoute->getEdges().size() > 0 && !(*myCurrEdge)->prohibits(this)) {
968 myRouteValidity &= ~ROUTE_START_INVALID_PERMISSIONS;
969 return true;
970 } else {
971 msg = TLF("Vehicle '%' is not allowed to depart on any lane of edge '%'.", getID(), (*myCurrEdge)->getID());
973 return false;
974 }
975}
976
977
978int
979MSBaseVehicle::getRouteValidity(bool update, bool silent, std::string* msgReturn) {
980 if (!update) {
981 return myRouteValidity;
982 }
983 // insertion check must be done in any case
984 std::string msg;
985 if (!hasValidRouteStart(msg)) {
987 throw ProcessError(msg);
988 } else if (!silent) {
989 // vehicle will be discarded
990 WRITE_WARNING(msg);
991 } else if (msgReturn != nullptr) {
992 *msgReturn = msg;
993 }
994 }
995 if ((MSGlobals::gCheckRoutes || myRoute->getFirstEdge()->isInternal())
997 // we could check after the first rerouting
999 if (!hasValidRoute(msg, myRoute)) {
1001 throw ProcessError(TLF("Vehicle '%' has no valid route. %", getID(), msg));
1002 }
1003 }
1004 myRouteValidity &= ~ROUTE_UNCHECKED;
1005 return myRouteValidity;
1006}
1007
1008
1009bool
1011 for (auto item : myMoveReminders) {
1012 if (item.first == rem) {
1013 return true;
1014 }
1015 }
1016 return false;
1017}
1018
1019
1020void
1022#ifdef _DEBUG
1023 if (myTraceMoveReminders) {
1024 traceMoveReminder("add", rem, pos, true);
1025 }
1026#endif
1027 myMoveReminders.push_back(std::make_pair(rem, pos));
1028}
1029
1030
1031void
1033 for (MoveReminderCont::iterator r = myMoveReminders.begin(); r != myMoveReminders.end(); ++r) {
1034 if (r->first == rem) {
1035#ifdef _DEBUG
1036 if (myTraceMoveReminders) {
1037 traceMoveReminder("remove", rem, 0, false);
1038 }
1039#endif
1040 myMoveReminders.erase(r);
1041 return;
1042 }
1043 }
1044}
1045
1046
1047void
1049 // notifyEnter may cause new reminders to be added so we cannot use an iterator
1050 for (int i = 0; i < (int)myMoveReminders.size();) {
1051 MSMoveReminder* rem = myMoveReminders[i].first;
1052 const double remPos = myMoveReminders[i].second;
1053 // skip the reminder if it is a lane reminder but not for my lane (indicated by rem->second > 0.)
1054 if (rem->getLane() != nullptr && remPos > 0.) {
1055#ifdef _DEBUG
1056 if (myTraceMoveReminders) {
1057 traceMoveReminder("notifyEnter_skipped", rem, remPos, true);
1058 }
1059#endif
1060 ++i;
1061 } else {
1062 if (rem->notifyEnter(*this, reason, enteredLane)) {
1063#ifdef _DEBUG
1064 if (myTraceMoveReminders) {
1065 traceMoveReminder("notifyEnter", rem, remPos, true);
1066 }
1067#endif
1068 ++i;
1069 } else {
1070#ifdef _DEBUG
1071 if (myTraceMoveReminders) {
1072 traceMoveReminder("notifyEnter", rem, remPos, false);
1073 }
1074#endif
1075 myMoveReminders.erase(myMoveReminders.begin() + i);
1076 }
1077 }
1078 }
1079}
1080
1081
1082bool
1084 return isRailway(getVClass()) || isRailway(getCurrentEdge()->getPermissions());
1085}
1086
1087void
1089 if (myRoute->getLastEdge()->isTazConnector()) {
1090 return;
1091 }
1092 const int arrivalEdgeIndex = MIN2(myParameter->arrivalEdge, (int)myRoute->getEdges().size() - 1);
1093 if (arrivalEdgeIndex != myParameter->arrivalEdge) {
1094 if (!(onInit && myParameter->wasSet(VEHPARS_FORCE_REROUTE))) {
1095 WRITE_WARNINGF(TL("Vehicle '%' ignores attribute arrivalEdge=% after rerouting at time=% (routeLength=%)"),
1096 getID(), myParameter->arrivalEdge, time2string(SIMSTEP), myRoute->getEdges().size() - 1);
1097 }
1098 }
1099 const MSEdge* arrivalEdge = myParameter->arrivalEdge >= 0 ? myRoute->getEdges()[arrivalEdgeIndex] : myRoute->getLastEdge();
1100 if (!onInit) {
1101 arrivalEdge = myRoute->getLastEdge();
1102 // ignore arrivalEdge parameter after rerouting
1103 const_cast<SUMOVehicleParameter*>(myParameter)->arrivalEdge = -1;
1104 }
1105 const std::vector<MSLane*>& lanes = arrivalEdge->getLanes();
1106 const double lastLaneLength = lanes[0]->getLength();
1109 if (fabs(myParameter->arrivalPos) > lastLaneLength) {
1110 WRITE_WARNINGF(TL("Vehicle '%' will not be able to arrive at the given position!"), getID());
1111 }
1112 // Maybe we should warn the user about invalid inputs!
1113 myArrivalPos = MIN2(myParameter->arrivalPos, lastLaneLength);
1114 if (myArrivalPos < 0) {
1115 myArrivalPos = MAX2(myArrivalPos + lastLaneLength, 0.);
1116 }
1117 break;
1119 myArrivalPos = RandHelper::rand(lastLaneLength);
1120 break;
1122 myArrivalPos = lastLaneLength / 2.;
1123 break;
1124 default:
1125 myArrivalPos = lastLaneLength;
1126 break;
1127 }
1129 if (myParameter->arrivalLane >= (int)lanes.size() || !lanes[myParameter->arrivalLane]->allowsVehicleClass(myType->getVehicleClass())) {
1130 WRITE_WARNINGF(TL("Vehicle '%' will not be able to arrive at the given lane '%_%'!"), getID(), arrivalEdge->getID(), toString(myParameter->arrivalLane));
1131 }
1132 myArrivalLane = MIN2(myParameter->arrivalLane, (int)(lanes.size() - 1));
1134 myArrivalLane = -1;
1135 for (MSLane* lane : lanes) {
1136 if (lane->allowsVehicleClass(myType->getVehicleClass())) {
1137 myArrivalLane = lane->getIndex();
1138 break;
1139 }
1140 }
1141 if (myArrivalLane == -1) {
1142 WRITE_WARNINGF(TL("Vehicle '%' has no usable arrivalLane on edge '%'."), getID(), arrivalEdge->getID());
1143 myArrivalLane = 0;
1144 }
1146 // pick random lane among all usable lanes
1147 std::vector<MSLane*> usable;
1148 for (MSLane* lane : lanes) {
1149 if (lane->allowsVehicleClass(myType->getVehicleClass())) {
1150 usable.push_back(lane);
1151 }
1152 }
1153 if (usable.empty()) {
1154 WRITE_WARNINGF(TL("Vehicle '%' has no usable arrivalLane on edge '%'."), getID(), arrivalEdge->getID());
1155 myArrivalLane = 0;
1156 } else {
1157 myArrivalLane = usable[RandHelper::rand(0, (int)usable.size())]->getIndex();
1158 }
1159 }
1161 for (std::vector<MSLane*>::const_iterator l = lanes.begin(); l != lanes.end(); ++l) {
1162 if (myParameter->arrivalSpeed <= (*l)->getVehicleMaxSpeed(this)) {
1163 return;
1164 }
1165 }
1166 WRITE_WARNINGF(TL("Vehicle '%' will not be able to arrive with the given speed!"), getID());
1167 }
1168}
1169
1170void
1174 const int routeEdges = (int)myRoute->getEdges().size();
1176 // write specific edge in vehroute output for reproducibility
1177 pars->departEdge = RandHelper::rand(0, routeEdges);
1179 }
1180 assert(pars->departEdge >= 0);
1181 if (pars->departEdge >= routeEdges) {
1182 WRITE_WARNINGF(TL("Ignoring departEdge % for vehicle '%' with % route edges"), toString(pars->departEdge), getID(), toString(routeEdges));
1183 } else {
1184 myCurrEdge = myRoute->begin() + pars->departEdge;
1185 }
1186 }
1188 const int routeEdges = (int)myRoute->getEdges().size();
1189 const int begin = (int)(myCurrEdge - myRoute->begin());
1190 // write specific edge in vehroute output for reproducibility
1191 pars->arrivalEdge = RandHelper::rand(begin, routeEdges);
1193 assert(pars->arrivalEdge >= begin);
1194 assert(pars->arrivalEdge < routeEdges);
1195 }
1196}
1197
1198int
1202
1203int
1207 } else {
1209 }
1210}
1211
1212double
1214 return MAX2(0., MIN2(1., getVehicleType().getImpatience()
1215 + (hasInfluencer() ? getBaseInfluencer()->getExtraImpatience() : 0)
1217}
1218
1219
1220MSDevice*
1221MSBaseVehicle::getDevice(const std::type_info& type) const {
1222 for (MSVehicleDevice* const dev : myDevices) {
1223 if (typeid(*dev) == type) {
1224 return dev;
1225 }
1226 }
1227 return nullptr;
1228}
1229
1230
1231void
1233 // the parameters may hold the name of a vTypeDistribution but we are interested in the actual type
1234 const std::string& typeID = myParameter->vtypeid != getVehicleType().getID() ? getVehicleType().getID() : "";
1236 // params and stops must be written in child classes since they may wish to add additional attributes first
1237 out.writeAttr(SUMO_ATTR_ROUTE, myRoute->getID());
1238 std::ostringstream os;
1239 os << myOdometer << " " << myNumberReroutes;
1240 out.writeAttr(SUMO_ATTR_DISTANCE, os.str());
1243 }
1245 const int precision = out.getPrecision();
1246 out.setPrecision(MAX2(gPrecisionRandom, precision));
1248 out.setPrecision(precision);
1249 }
1251 out.writeAttr(SUMO_ATTR_REROUTE, true);
1252 }
1254 // could be set from stop
1256 }
1257 // here starts the vehicle internal part (see loading)
1258 // @note: remember to close the vehicle tag when calling this in a subclass!
1259}
1260
1261
1262bool
1263MSBaseVehicle::handleCollisionStop(MSStop& stop, const double distToStop) {
1264 UNUSED_PARAMETER(stop);
1265 UNUSED_PARAMETER(distToStop);
1266 return true;
1267}
1268
1269
1270bool
1272 return !myStops.empty() && myStops.begin()->reached /*&& myState.mySpeed < SUMO_const_haltingSpeed @todo #1864#*/;
1273}
1274
1275
1276bool
1278 return (isStopped() && (myStops.begin()->pars.parking == ParkingType::OFFROAD)
1279 && (myStops.begin()->parkingarea == nullptr || !myStops.begin()->parkingarea->parkOnRoad())
1280 && (myStops.begin()->getSpeed() == 0 || getSpeed() < SUMO_const_haltingSpeed));
1281}
1282
1283
1284bool
1286 return myPastStops.size() > 0 && myPastStops.back().jump >= 0 && getEdge()->getID() == myPastStops.back().edge && myPastStops.back().ended == SIMSTEP;
1287}
1288
1289
1290bool
1292 return isStopped() && (myStops.begin()->triggered || myStops.begin()->containerTriggered || myStops.begin()->joinTriggered);
1293}
1294
1295
1296bool
1298 return isStopped() && (myStops.begin()->pars.parking == ParkingType::OFFROAD);
1299}
1300
1301
1302bool
1303MSBaseVehicle::isStoppedInRange(const double pos, const double tolerance, bool checkFuture) const {
1304 if (isStopped() || (checkFuture && hasStops())) {
1305 const MSStop& stop = myStops.front();
1306 return stop.pars.startPos - tolerance <= pos && stop.pars.endPos + tolerance >= pos;
1307 }
1308 return false;
1309}
1310
1311bool
1312MSBaseVehicle::replaceParkingArea(MSParkingArea* parkingArea, std::string& errorMsg) {
1313 // Check if there is a parking area to be replaced
1314 if (parkingArea == 0) {
1315 errorMsg = "new parkingArea is NULL";
1316 return false;
1317 }
1318 if (myStops.size() == 0) {
1319 errorMsg = "vehicle has no stops";
1320 return false;
1321 }
1322 if (myStops.front().parkingarea == 0) {
1323 errorMsg = "first stop is not at parkingArea";
1324 return false;
1325 }
1326 MSStop& first = myStops.front();
1327 SUMOVehicleParameter::Stop& stopPar = const_cast<SUMOVehicleParameter::Stop&>(first.pars);
1328 std::string oldStopEdgeID = first.lane->getEdge().getID();
1329 // merge subsequent duplicate stops equals to parking area
1330 for (std::list<MSStop>::iterator iter = ++myStops.begin(); iter != myStops.end();) {
1331 if (iter->parkingarea == parkingArea) {
1332 stopPar.duration += iter->duration;
1333 myStops.erase(iter++);
1334 } else {
1335 break;
1336 }
1337 }
1338 stopPar.lane = parkingArea->getLane().getID();
1339 stopPar.parkingarea = parkingArea->getID();
1340 stopPar.startPos = parkingArea->getBeginLanePosition();
1341 stopPar.endPos = parkingArea->getEndLanePosition();
1342 stopPar.index = STOP_INDEX_FIT;
1343 first.edge = myRoute->end(); // will be patched in replaceRoute
1344 first.lane = &parkingArea->getLane();
1345 first.parkingarea = parkingArea;
1346
1347 // patch via edges
1348 std::string newStopEdgeID = parkingArea->getLane().getEdge().getID();
1349 if (myParameter->via.size() > 0 && myParameter->via.front() != newStopEdgeID) {
1350 myParameter->via.erase(myParameter->via.begin());
1351 myParameter->via.insert(myParameter->via.begin(), newStopEdgeID);
1352 }
1353 return true;
1354}
1355
1356
1359 MSParkingArea* nextParkingArea = nullptr;
1360 if (!myStops.empty()) {
1362 MSStop stop = myStops.front();
1363 if (!stop.reached && stop.parkingarea != nullptr) {
1364 nextParkingArea = stop.parkingarea;
1365 }
1366 }
1367 return nextParkingArea;
1368}
1369
1370
1373 MSParkingArea* currentParkingArea = nullptr;
1374 if (isParking()) {
1375 currentParkingArea = myStops.begin()->parkingarea;
1376 }
1377 return currentParkingArea;
1378}
1379
1380
1381const std::vector<std::string>&
1384 return myParameter->parkingBadges;
1385 } else {
1387 }
1388}
1389
1390
1391double
1392MSBaseVehicle::basePos(const MSEdge* edge) const {
1393 double result = MIN2(getVehicleType().getLength() + POSITION_EPS, edge->getLength());
1394 if (hasStops()
1395 && myStops.front().edge == myRoute->begin()
1396 && (&myStops.front().lane->getEdge()) == *myStops.front().edge) {
1397 result = MIN2(result, MAX2(0.0, myStops.front().getEndPos(*this)));
1398 }
1399 return result;
1400}
1401
1402
1403MSLane*
1405 const std::string edgeID = SUMOXMLDefinitions::getEdgeIDFromLane(stop.lane);
1406 const MSEdge* edge = MSEdge::dictionary(edgeID);
1407 if (edge == nullptr || edge->getOppositeEdge() == nullptr || stop.lane.find("_") == std::string::npos) {
1408 return nullptr;
1409 }
1410 const int laneIndex = SUMOXMLDefinitions::getIndexFromLane(stop.lane);
1411 if (laneIndex < (edge->getNumLanes() + edge->getOppositeEdge()->getNumLanes())) {
1412 const int oppositeIndex = edge->getOppositeEdge()->getNumLanes() + edge->getNumLanes() - 1 - laneIndex;
1413 stop.edge = edgeID;
1414 return edge->getOppositeEdge()->getLanes()[oppositeIndex];
1415 }
1416 return nullptr;
1417}
1418
1419
1420bool
1421MSBaseVehicle::addStop(const SUMOVehicleParameter::Stop& stopPar, std::string& errorMsg, SUMOTime untilOffset,
1422 MSRouteIterator* searchStart) {
1423 MSStop stop(stopPar);
1424 if (stopPar.lane == "") {
1425 MSEdge* e = MSEdge::dictionary(stopPar.edge);
1427 if (stop.lane == nullptr) {
1428 errorMsg = "Vehicle '" + myParameter->id + "' is not allowed to stop on any lane of edge '" + stopPar.edge + "'.";
1429 return false;
1430 }
1431 } else {
1432 stop.lane = MSLane::dictionary(stopPar.lane);
1433 if (stop.lane == nullptr) {
1434 // must be an opposite stop
1435 SUMOVehicleParameter::Stop tmp = stopPar;
1436 stop.lane = interpretOppositeStop(tmp);
1437 assert(stop.lane != nullptr);
1438 }
1440 errorMsg = "Vehicle '" + myParameter->id + "' is not allowed to stop on lane '" + stopPar.lane + "'.";
1441 return false;
1442 }
1443 }
1445 stop.segment = MSGlobals::gMesoNet->getSegmentForEdge(stop.lane->getEdge(), stop.getEndPos(*this));
1446 if (stop.lane->isInternal()) {
1447 errorMsg = "Mesoscopic simulation does not allow stopping on internal edge '" + stopPar.edge + "' for vehicle '" + myParameter->id + "'.";
1448 return false;
1449 }
1450 }
1451 stop.initPars(stopPar);
1452 if (stopPar.until != -1) {
1453 // !!! it would be much cleaner to invent a constructor for stops which takes "until" as an argument
1454 const_cast<SUMOVehicleParameter::Stop&>(stop.pars).until += untilOffset;
1455 }
1456 if (stopPar.arrival != -1) {
1457 const_cast<SUMOVehicleParameter::Stop&>(stop.pars).arrival += untilOffset;
1458 }
1459 std::string stopType = "stop";
1460 std::string stopID = "";
1461 double parkingLength = stop.pars.endPos - stop.pars.startPos;
1462 if (stop.busstop != nullptr) {
1463 stopType = "busStop";
1464 stopID = stop.busstop->getID();
1465 parkingLength = stop.busstop->getParkingLength();
1466 } else if (stop.containerstop != nullptr) {
1467 stopType = "containerStop";
1468 stopID = stop.containerstop->getID();
1469 parkingLength = stop.containerstop->getParkingLength();
1470 } else if (stop.chargingStation != nullptr) {
1471 stopType = "chargingStation";
1472 stopID = stop.chargingStation->getID();
1473 parkingLength = stop.chargingStation->getParkingLength();
1474 } else if (stop.overheadWireSegment != nullptr) {
1475 stopType = "overheadWireSegment";
1476 stopID = stop.overheadWireSegment->getID();
1477 parkingLength = stop.overheadWireSegment->getParkingLength();
1478 } else if (stop.parkingarea != nullptr) {
1479 stopType = "parkingArea";
1480 stopID = stop.parkingarea->getID();
1481 }
1482 const std::string errorMsgStart = stopID == "" ? stopType : stopType + " '" + stopID + "'";
1483
1484 if (stop.pars.startPos < 0 || stop.pars.endPos > stop.lane->getLength()) {
1485 errorMsg = errorMsgStart + " for vehicle '" + myParameter->id + "' on lane '" + stop.lane->getID() + "' has an invalid position.";
1486 return false;
1487 }
1488 if (stopType != "stop" && stopType != "parkingArea" && myType->getLength() / 2. > parkingLength
1489 // do not warn for stops that fill the whole lane
1490 && parkingLength < stop.lane->getLength()
1491 // do not warn twice for the same stop
1492 && MSNet::getInstance()->warnOnce(stopType + ":" + stopID)) {
1493 errorMsg = errorMsgStart + " on lane '" + stop.lane->getID() + "' is too short for vehicle '" + myParameter->id + "'.";
1494 }
1495 if (stopType == "parkingArea" && !stop.parkingarea->accepts(this)) {
1496 // forbid access in case the parking requests other badges
1497 errorMsg = errorMsgStart + "on lane '" + stop.lane->getID() + "' forbids access because vehicle '" + myParameter->id + "' does not provide any valid badge.";
1498 return false;
1499 }
1500 const MSEdge* stopLaneEdge = &stop.lane->getEdge();
1501 const MSEdge* stopEdge;
1502 if (stopLaneEdge->getOppositeEdge() != nullptr && stopLaneEdge->getOppositeEdge()->getID() == stopPar.edge) {
1503 // stop lane is on the opposite side
1504 stopEdge = stopLaneEdge->getOppositeEdge();
1505 stop.isOpposite = true;
1506 } else {
1507 // if stop is on an internal edge the normal edge before the intersection is used
1508 stopEdge = stopLaneEdge->getNormalBefore();
1509 }
1510 MSRouteIterator succ = myCurrEdge + 1; // we're using the address but only within the scope of this function (and recursive calls)
1511 if (searchStart == nullptr) {
1512 searchStart = &myCurrEdge;
1513 if (stopLaneEdge->isNormal() && getLane() != nullptr && getLane()->isInternal()) {
1514 // already on the intersection but myCurrEdge is before it
1515 searchStart = &succ;
1516 }
1517 }
1518#ifdef DEBUG_ADD_STOP
1519 if (DEBUG_COND) {
1520 std::cout << "addStop desc=" << stop.getDescription() << " stopEdge=" << stopEdge->getID()
1521 << " searchStart=" << ((*searchStart) == myRoute->end() ? "END" : (**searchStart)->getID())
1522 << " index=" << (int)((*searchStart) - myRoute->begin()) << " route=" << toString(myRoute->getEdges())
1523 << " stopParIndex=" << stopPar.index
1524 << "\n";
1525 }
1526#endif
1527 stop.edge = std::find(*searchStart, myRoute->end(), stopEdge);
1528 MSRouteIterator prevStopEdge = myCurrEdge;
1529 const MSEdge* prevEdge = (getLane() == nullptr ? getEdge() : &getLane()->getEdge());
1530 double prevStopPos = getPositionOnLane();
1531 // where to insert the stop
1532 std::list<MSStop>::iterator iter = myStops.begin();
1533 if (stopPar.index == STOP_INDEX_END || stopPar.index >= static_cast<int>(myStops.size()) || stopPar.index == STOP_INDEX_REPEAT) {
1534 iter = myStops.end();
1535 if (myStops.size() > 0 && myStops.back().edge >= *searchStart) {
1536 prevStopEdge = myStops.back().edge;
1537 prevEdge = &myStops.back().lane->getEdge();
1538 prevStopPos = myStops.back().pars.endPos;
1539 stop.edge = std::find(prevStopEdge, myRoute->end(), stopEdge);
1540 if (prevStopEdge == stop.edge // laneEdge check is insufficient for looped routes
1541 && prevEdge == &stop.lane->getEdge() // route iterator check insufficient for internal lane stops
1542 && (prevStopPos > stop.pars.endPos ||
1543 (prevStopPos == stop.pars.endPos && stopPar.index == STOP_INDEX_REPEAT))) {
1544 stop.edge = std::find(prevStopEdge + 1, myRoute->end(), stopEdge);
1545 }
1546#ifdef DEBUG_ADD_STOP
1547 if (DEBUG_COND) {
1548 std::cout << " (@end) prevStopEdge=" << (*prevStopEdge)->getID() << " prevStopPos=" << prevStopPos << " index=" << (int)(prevStopEdge - myRoute->begin())
1549 << " foundIndex=" << (stop.edge == myRoute->end() ? -1 : (int)(stop.edge - myRoute->begin())) << "\n";
1550 }
1551#endif
1552 }
1553 // skip a number of occurences of stopEdge in looped route
1554 int skipLooped = stopPar.index - static_cast<int>(myStops.size());
1555 for (int j = 0; j < skipLooped; j++) {
1556 auto nextIt = std::find(stop.edge + 1, myRoute->end(), stopEdge);
1557 if (nextIt == myRoute->end()) {
1558 if (std::find(myRoute->begin(), stop.edge, stopEdge) != stop.edge) {
1559 // only warn if the route loops over the stop edge at least once
1560 errorMsg = errorMsgStart + " for vehicle '" + myParameter->id + "' could not skip " + toString(skipLooped) + " occurences of stop edge '" + stopEdge->getID() + "' in looped route.";
1561 }
1562 break;
1563 } else {
1564 stop.edge = nextIt;
1565 }
1566 }
1567 } else {
1568 if (stopPar.index == STOP_INDEX_FIT) {
1569 while (iter != myStops.end() && (iter->edge < stop.edge ||
1570 (iter->pars.endPos < stop.pars.endPos && iter->edge == stop.edge) ||
1571 (stop.lane->getEdge().isInternal() && iter->edge == stop.edge))) {
1572 prevStopEdge = iter->edge;
1573 prevStopPos = iter->pars.endPos;
1574 ++iter;
1575 }
1576 } else {
1577 int index = stopPar.index;
1578 while (index > 0) {
1579 prevStopEdge = iter->edge;
1580 prevStopPos = iter->pars.endPos;
1581 ++iter;
1582 --index;
1583 }
1584#ifdef DEBUG_ADD_STOP
1585 if (DEBUG_COND) {
1586 std::cout << " (@fit) prevStopEdge=" << (*prevStopEdge)->getID() << " index=" << (int)(prevStopEdge - myRoute->begin()) << "\n";
1587 }
1588#endif
1589 stop.edge = std::find(prevStopEdge, myRoute->end(), stopEdge);
1590 }
1591 }
1592 const bool wasTooClose = errorMsg != "" && errorMsg.find("too close") != std::string::npos;
1593 if (stop.edge == myRoute->end()) {
1594 if (!wasTooClose) {
1595 errorMsg = errorMsgStart + " for vehicle '" + myParameter->id + "' on lane '" + stop.lane->getID() + "' is not downstream the current route.";
1596 }
1597 return false;
1598 }
1599
1600 const bool tooClose = (prevStopEdge == stop.edge && prevEdge == &stop.lane->getEdge() &&
1601 prevStopPos + (iter == myStops.begin() && !instantStopping() ? getBrakeGap() : 0) > stop.pars.endPos + POSITION_EPS);
1602
1603 if (prevStopEdge > stop.edge ||
1604 // a collision-stop happens after vehicle movement and may move the
1605 // vehicle backwards on its lane (prevStopPos is the vehicle position)
1606 (tooClose && !stop.pars.collision)
1607 || (stop.lane->getEdge().isInternal() && stop.lane->getNextNormal() != *(stop.edge + 1))) {
1608 // check if the edge occurs again later in the route
1609 //std::cout << " could not add stop " << errorMsgStart << " prevStops=" << myStops.size() << " searchStart=" << (*searchStart - myRoute->begin()) << " route=" << toString(myRoute->getEdges()) << "\n";
1610 if (tooClose && prevStopPos <= stop.pars.endPos + POSITION_EPS) {
1611 errorMsg = errorMsgStart + " for vehicle '" + myParameter->id + "' on lane '" + stop.pars.lane + "' is too close to brake.";
1612 }
1613 MSRouteIterator next = stop.edge + 1;
1614 return addStop(stopPar, errorMsg, untilOffset, &next);
1615 }
1616 if (wasTooClose) {
1617 errorMsg = "";
1618 }
1619 // David.C:
1620 //if (!stop.parking && (myCurrEdge == stop.edge && myState.myPos > stop.endPos - getCarFollowModel().brakeGap(myState.mySpeed))) {
1621 const double endPosOffset = stop.lane->getEdge().isInternal() ? (*stop.edge)->getLength() : 0;
1622 const double distToStop = stop.pars.endPos + endPosOffset - getPositionOnLane();
1623 if (stop.pars.collision && !handleCollisionStop(stop, distToStop)) {
1624 return false;
1625 }
1626 if (!hasDeparted() && myCurrEdge == stop.edge) {
1627 double pos = -1;
1629 pos = myParameter->departPos;
1630 if (pos < 0.) {
1631 pos += (*myCurrEdge)->getLength();
1632 }
1633 }
1635 pos = MIN2(stop.pars.endPos + endPosOffset, basePos(*myCurrEdge));
1636 }
1637 if (pos > stop.pars.endPos + endPosOffset) {
1638 if (stop.edge != myRoute->end()) {
1639 // check if the edge occurs again later in the route
1640 MSRouteIterator next = stop.edge + 1;
1641 return addStop(stopPar, errorMsg, untilOffset, &next);
1642 }
1643 errorMsg = errorMsgStart + " for vehicle '" + myParameter->id + "' on lane '" + stop.lane->getID() + "' is before departPos.";
1644 return false;
1645 }
1646 }
1647 if (iter != myStops.begin()) {
1648 std::list<MSStop>::iterator iter2 = iter;
1649 iter2--;
1650 if (stop.getUntil() >= 0 && iter2->getUntil() > stop.getUntil()
1651 && (!MSGlobals::gUseStopEnded || iter2->pars.ended < 0 || stop.pars.ended >= 0)) {
1652 errorMsg = errorMsgStart + " for vehicle '" + myParameter->id + "' on lane '" + stop.lane->getID()
1653 + "' set to end at " + time2string(stop.getUntil())
1654 + " earlier than previous stop at " + time2string(iter2->getUntil()) + ".";
1655 }
1656 if (stop.pars.arrival >= 0 && iter2->pars.arrival > stop.pars.arrival) {
1657 errorMsg = errorMsgStart + " for vehicle '" + myParameter->id + "' on lane '" + stop.lane->getID()
1658 + "' set to start at " + time2string(stop.pars.arrival)
1659 + " earlier than previous stop end at " + time2string(iter2->getUntil()) + ".";
1660 }
1661 if (stop.pars.arrival >= 0 && iter2->pars.arrival > stop.pars.arrival) {
1662 errorMsg = errorMsgStart + " for vehicle '" + myParameter->id + "' on lane '" + stop.lane->getID()
1663 + "' set to start at " + time2string(stop.pars.arrival)
1664 + " earlier than previous stop arrival at " + time2string(iter2->pars.arrival) + ".";
1665 }
1666 } else {
1667 if (stop.getUntil() >= 0 && getParameter().depart > stop.getUntil()
1668 && (!MSGlobals::gUseStopEnded || stop.pars.ended < 0)) {
1669 errorMsg = errorMsgStart + " for vehicle '" + myParameter->id + "' on lane '" + stop.lane->getID()
1670 + "' set to end at " + time2string(stop.getUntil())
1671 + " earlier than departure at " + time2string(getParameter().depart) + ".";
1672 }
1673 }
1674 if (stop.getUntil() >= 0 && stop.getArrival() > stop.getUntil() && errorMsg == "") {
1675 errorMsg = errorMsgStart + " for vehicle '" + myParameter->id + "' on lane '" + stop.lane->getID()
1676 + "' set to end at " + time2string(stop.getUntil())
1677 + " earlier than arrival at " + time2string(stop.getArrival()) + ".";
1678 }
1679 setSkips(stop, (int)myStops.size());
1680 myStops.insert(iter, stop);
1681 if (stopPar.tripId != "") {
1683 }
1684 //std::cout << " added stop " << errorMsgStart << " totalStops=" << myStops.size() << " searchStart=" << (*searchStart - myRoute->begin())
1685 // << " routeIndex=" << (stop.edge - myRoute->begin())
1686 // << " stopIndex=" << std::distance(myStops.begin(), iter)
1687 // << " route=" << toString(myRoute->getEdges()) << "\n";
1688 return true;
1689}
1690
1691
1692void
1693MSBaseVehicle::setSkips(MSStop& stop, int prevActiveStops) {
1694 if (hasDeparted() && stop.edge > myRoute->begin()) {
1695 // if the route is looped we must patch the index to ensure that state
1696 // loading (and vehroute-output) encode the correct number of skips
1697 int foundSkips = 0;
1698 MSRouteIterator itPrev;
1699 double prevEndPos;
1700 if (prevActiveStops > 0) {
1701 assert((int)myStops.size() >= prevActiveStops);
1702 auto prevStopIt = myStops.begin();
1703 std::advance(prevStopIt, prevActiveStops - 1);
1704 const MSStop& prev = *prevStopIt;
1705 itPrev = prev.edge;
1706 prevEndPos = prev.pars.endPos;
1707 } else if (myPastStops.size() > 0) {
1708 itPrev = myRoute->begin() + myPastStops.back().routeIndex;
1709 prevEndPos = myPastStops.back().endPos;
1710 } else {
1711 itPrev = myRoute->begin() + myParameter->departEdge;
1712 prevEndPos = myDepartPos;
1713 }
1714 //auto itPrevOrig = itPrev;
1715 if (*itPrev == *stop.edge && prevEndPos > stop.pars.endPos) {
1716 itPrev++;
1717 }
1718 //std::cout << SIMTIME << " veh=" << getID() << " prevActive=" << prevActiveStops << " edge=" << (*stop.edge)->getID() << " routeIndex=" << (stop.edge - myRoute->begin()) << " prevIndex=" << (itPrev - myRoute->begin()) << "\n";
1719 while (itPrev < stop.edge) {
1720 if (*itPrev == *stop.edge) {
1721 foundSkips++;
1722 }
1723 itPrev++;
1724 }
1725 int newIndex = STOP_INDEX_END;
1726 if (foundSkips > 0) {
1727 //if (getID() == "77_0_0") {
1728 // std::cout << SIMTIME << " veh=" << getID() << " past=" << myPastStops.size() << " prevActive=" << prevActiveStops
1729 // << " edge=" << (*stop.edge)->getID() << " routeIndex=" << (stop.edge - myRoute->begin())
1730 // << " prevEdge=" << (*itPrevOrig)->getID()
1731 // << " prevIndex=" << (itPrevOrig - myRoute->begin())
1732 // << " skips=" << foundSkips << "\n";
1733 //}
1734 newIndex = (int)myPastStops.size() + prevActiveStops + foundSkips;
1735 }
1736 const_cast<SUMOVehicleParameter::Stop&>(stop.pars).index = newIndex;
1737 }
1738}
1739
1740
1743 for (int i = 0; i < (int)myMoveReminders.size();) {
1744 auto rem = &myMoveReminders[i];
1745 if (rem->first->notifyReroute(*this)) {
1746#ifdef _DEBUG
1747 if (myTraceMoveReminders) {
1748 traceMoveReminder("notifyReroute", rem->first, rem->second, true);
1749 }
1750#endif
1751 ++i;
1752 } else {
1753#ifdef _DEBUG
1754 if (myTraceMoveReminders) {
1755 traceMoveReminder("notifyReroute", rem->first, rem->second, false);
1756 }
1757#endif
1758 myMoveReminders.erase(myMoveReminders.begin() + i);
1759 }
1760 }
1762 // event only called once
1763 return 0;
1764}
1765
1766
1767void
1768MSBaseVehicle::addStops(const bool ignoreStopErrors, MSRouteIterator* searchStart, bool addRouteStops) {
1769 if (addRouteStops) {
1770 for (const SUMOVehicleParameter::Stop& stop : myRoute->getStops()) {
1771 std::string errorMsg;
1772 if (!addStop(stop, errorMsg, myParameter->depart, searchStart) && !ignoreStopErrors) {
1773 throw ProcessError(errorMsg);
1774 }
1775 if (errorMsg != "") {
1776 WRITE_WARNING(errorMsg);
1777 }
1778 }
1779 }
1781 for (const SUMOVehicleParameter::Stop& stop : myParameter->stops) {
1782 std::string errorMsg;
1783 if (!addStop(stop, errorMsg, untilOffset, searchStart) && !ignoreStopErrors) {
1784 throw ProcessError(errorMsg);
1785 }
1786 if (errorMsg != "") {
1787 WRITE_WARNING(errorMsg);
1788 }
1789 }
1790}
1791
1792
1793bool
1796 int i = 0;
1797 bool ok = true;
1798 for (const MSStop& stop : myStops) {
1799 MSRouteIterator it;
1800 if (stop.lane->isInternal()) {
1801 // find the normal predecessor and ensure that the next route edge
1802 // matches the successor of the internal edge successor
1803 it = std::find(start, myRoute->end(), stop.lane->getEdge().getNormalBefore());
1804 if (it != myRoute->end() && (
1805 it + 1 == myRoute->end() || *(it + 1) != stop.lane->getEdge().getNormalSuccessor())) {
1806 it = myRoute->end(); // signal failure
1807 }
1808 } else {
1809 it = std::find(start, myRoute->end(), &stop.lane->getEdge());
1810 }
1811 if (it == myRoute->end()) {
1812 if (!silent) {
1813 WRITE_ERRORF("Stop % on edge '%' is not found after edge '%' (% after current) for vehicle '%' at time=%.",
1814 i, stop.lane->getEdge().getID(), (*start)->getID(), toString(start - myCurrEdge), getID(), time2string(SIMSTEP));
1815 }
1816 ok = false;
1817 } else {
1818 MSRouteIterator it2;
1819 for (it2 = myRoute->begin(); it2 != myRoute->end(); it2++) {
1820 if (it2 == stop.edge) {
1821 break;
1822 }
1823 }
1824 if (it2 == myRoute->end()) {
1825 if (!silent) {
1826 WRITE_ERRORF("Stop % on edge '%' used invalid route index for vehicle '%' at time=%.",
1827 i, stop.lane->getEdge().getID(), getID(), time2string(SIMSTEP));
1828 }
1829 ok = false;
1830 } else if (it2 < start) {
1831 if (!silent) {
1832 WRITE_ERRORF("Stop % on edge '%' used invalid (relative) route index % expected after % for vehicle '%' at time=%.",
1833 i, stop.lane->getEdge().getID(), toString(it2 - myCurrEdge), toString(start - myCurrEdge), getID(), time2string(SIMSTEP));
1834 }
1835 ok = false;
1836 } else {
1837 start = stop.edge;
1838 }
1839 }
1840 i++;
1841 }
1842 return ok;
1843}
1844
1845
1846std::vector<MSBaseVehicle::StopEdgeInfo>
1847MSBaseVehicle::getStopEdges(double& firstPos, double& lastPos, std::set<int>& jumps) const {
1848 assert(haveValidStopEdges());
1849 std::vector<StopEdgeInfo> result;
1850 const MSStop* prev = nullptr;
1851 const MSEdge* internalSuccessor = nullptr;
1852 for (const MSStop& stop : myStops) {
1853 if (stop.reached) {
1854 if (stop.pars.jump >= 0) {
1855 jumps.insert((int)result.size());
1856 }
1857 continue;
1858 }
1859 double stopPos = stop.getEndPos(*this);
1860 if ((prev == nullptr
1861 || prev->edge != stop.edge
1862 || (prev->lane == stop.lane && prev->getEndPos(*this) > stopPos))
1863 && *stop.edge != internalSuccessor) {
1864 if (stop.lane->isInternal()) {
1865 stopPos = (*stop.edge)->getLength();
1866 }
1867 result.push_back(StopEdgeInfo(*stop.edge, stop.pars.priority, stop.getArrivalFallback(), stopPos));
1868 result.back().nameTag = stop.getStoppingPlaceName();
1869 result.back().stopPar = &stop.pars;
1870 if (stop.lane->isInternal()) {
1871 internalSuccessor = stop.lane->getNextNormal();
1872 result.push_back(StopEdgeInfo(internalSuccessor, stop.pars.priority, stop.getArrivalFallback(), 0));
1873 } else {
1874 internalSuccessor = nullptr;
1875 }
1876 } else if (prev != nullptr && prev->edge == stop.edge) {
1877 result.back().priority = addStopPriority(result.back().priority, stop.pars.priority);
1878 }
1879 prev = &stop;
1880 if (firstPos == INVALID_DOUBLE) {
1881 if (stop.parkingarea != nullptr) {
1882 firstPos = MAX2(0., stopPos);
1883 } else {
1884 firstPos = stopPos;
1885 }
1886 }
1887 lastPos = stopPos;
1888 if (stop.pars.jump >= 0) {
1889 jumps.insert((int)result.size() - 1);
1890 }
1891 }
1892 //std::cout << SIMTIME << " getStopEdges veh=" << getID() << "\n";
1893 //for (auto item : result) {
1894 // std::cout << " e=" << item.edge->getID() << " pos=" << item.pos << "\n";
1895 //}
1896 return result;
1897}
1898
1899
1900double
1901MSBaseVehicle::addStopPriority(double p1, double p2) {
1902 if (p1 < 0 || p2 < 0) {
1903 return p1;
1904 }
1905 return p1 + p2;
1906}
1907
1908std::vector<std::pair<int, double> >
1910 std::vector<std::pair<int, double> > result;
1911 for (std::list<MSStop>::const_iterator iter = myStops.begin(); iter != myStops.end(); ++iter) {
1912 result.push_back(std::make_pair(
1913 (int)(iter->edge - myRoute->begin()),
1914 iter->getEndPos(*this)));
1915 }
1916 return result;
1917}
1918
1919
1920const MSStop&
1922 assert(myStops.size() > 0);
1923 return myStops.front();
1924}
1925
1926MSStop&
1928 assert(myStops.size() > 0);
1929 return myStops.front();
1930}
1931
1934 if (isStopped()) {
1935 return myStops.front().duration;
1936 } else {
1937 return 0;
1938 }
1939}
1940
1941
1942MSStop&
1943MSBaseVehicle::getStop(int nextStopIndex) {
1944 if (nextStopIndex < 0 || (int)myStops.size() <= nextStopIndex) {
1945 throw InvalidArgument(TLF("Invalid stop index % (has % stops).", nextStopIndex, myStops.size()));
1946 }
1947 auto stopIt = myStops.begin();
1948 std::advance(stopIt, nextStopIndex);
1949 return *stopIt;
1950}
1951
1952
1955 if (hasStops()) {
1956 return &myStops.front().pars;
1957 }
1958 return nullptr;
1959}
1960
1961
1962bool
1964 //if the stop exists update the duration
1965 for (std::list<MSStop>::iterator iter = myStops.begin(); iter != myStops.end(); iter++) {
1966 if (iter->lane->getID() == stop.lane && fabs(iter->pars.endPos - stop.endPos) < POSITION_EPS) {
1967 // update existing stop
1968 if (stop.duration == 0 && stop.until < 0 && !iter->reached) {
1969 myStops.erase(iter);
1970 } else {
1971 iter->duration = stop.duration;
1972 iter->triggered = stop.triggered;
1973 iter->containerTriggered = stop.containerTriggered;
1974 const_cast<SUMOVehicleParameter::Stop&>(iter->pars).until = stop.until;
1975 const_cast<SUMOVehicleParameter::Stop&>(iter->pars).parking = stop.parking;
1976 }
1977 return true;
1978 }
1979 }
1980 const bool result = addStop(stop, errorMsg);
1981 if (result) {
1983 myParameter->stops.push_back(stop);
1984 }
1985 return result;
1986}
1987
1988
1989void
1996
1997
1998bool
2000 if (hasStops() && nextStopIndex < (int)myStops.size()) {
2001 if (nextStopIndex == 0 && isStopped()) {
2003 } else {
2004 auto stopIt = myStops.begin();
2005 std::advance(stopIt, nextStopIndex);
2006 if (stopIt->parkingarea != nullptr && stopIt->parkingarea->isReservable()) {
2007 stopIt->parkingarea->removeSpaceReservation(this);
2008 }
2009 myStops.erase(stopIt);
2010 }
2011 if (!hasDeparted() && (int)myParameter->stops.size() > nextStopIndex) {
2012 // stops will be rebuilt from scratch on rerouting so we must patch the stops in myParameter
2013 auto stopIt2 = myParameter->stops.begin();
2014 std::advance(stopIt2, nextStopIndex);
2015 const_cast<SUMOVehicleParameter*>(myParameter)->stops.erase(stopIt2);
2016 }
2017 return true;
2018 } else {
2019 return false;
2020 }
2021}
2022
2023
2024bool
2025MSBaseVehicle::replaceStop(int nextStopIndex, SUMOVehicleParameter::Stop stop, const std::string& info, bool teleport, std::string& errorMsg) {
2026 const int n = (int)myStops.size();
2027 if (nextStopIndex < 0 || nextStopIndex >= n) {
2028 errorMsg = TLF("invalid nextStopIndex % for % remaining stops", nextStopIndex, n);
2029 return false;
2030 }
2031 if (nextStopIndex == 0 && isStopped()) {
2032 errorMsg = TL("cannot replace reached stop");
2033 return false;
2034 }
2036 MSLane* stopLane = MSLane::dictionary(stop.lane);
2037 MSEdge* stopEdge = &stopLane->getEdge();
2038
2039 auto itStop = myStops.begin();
2040 std::advance(itStop, nextStopIndex);
2041 MSStop& replacedStop = *itStop;
2042
2043 // check parking access rights
2044 if (stop.parkingarea != "") {
2046 if (pa != nullptr && !pa->accepts(this)) {
2047 errorMsg = TLF("vehicle '%' does not have the right badge to access parkingArea '%'", getID(), stop.parkingarea);
2048 return false;
2049 }
2050 }
2051
2052 if (replacedStop.lane == stopLane && replacedStop.pars.endPos == stop.endPos && !teleport) {
2053 // only replace stop attributes
2054 const_cast<SUMOVehicleParameter::Stop&>(replacedStop.pars) = stop;
2055 replacedStop.initPars(stop);
2056 return true;
2057 }
2058
2059 if (!stopLane->allowsVehicleClass(getVClass(), myRoutingMode)) {
2060 errorMsg = TLF("disallowed stop lane '%'", stopLane->getID());
2061 return false;
2062 }
2063
2064 const ConstMSEdgeVector& oldEdges = getRoute().getEdges();
2065 std::vector<MSStop> stops(myStops.begin(), myStops.end());
2066 const int junctionOffset = getLane() != nullptr && getLane()->isInternal() ? 1 : 0;
2067 MSRouteIterator itStart = nextStopIndex == 0 ? getCurrentRouteEdge() + junctionOffset : stops[nextStopIndex - 1].edge;
2068 double startPos = nextStopIndex == 0 ? getPositionOnLane() : stops[nextStopIndex - 1].pars.endPos;
2069 MSRouteIterator itEnd = nextStopIndex == n - 1 ? oldEdges.end() - 1 : stops[nextStopIndex + 1].edge;
2070 auto endPos = nextStopIndex == n - 1 ? getArrivalPos() : stops[nextStopIndex + 1].pars.endPos;
2072
2073 bool newDestination = nextStopIndex == n - 1 && stops[nextStopIndex].edge == oldEdges.end() - 1;
2074
2075 ConstMSEdgeVector toNewStop;
2076 if (!teleport) {
2077 router.compute(*itStart, startPos, stopEdge, stop.endPos, this, t, toNewStop, true);
2078 if (toNewStop.size() == 0) {
2079 errorMsg = TLF("no route found from edge '%' to stop edge '%'", (*itStart)->getID(), stopEdge->getID());
2080 return false;
2081 }
2082 }
2083
2084 ConstMSEdgeVector fromNewStop;
2085 if (!newDestination) {
2086 router.compute(stopEdge, stop.endPos, *itEnd, endPos, this, t, fromNewStop, true);
2087 if (fromNewStop.size() == 0) {
2088 errorMsg = TLF("no route found from stop edge '%' to edge '%'", stopEdge->getID(), (*itEnd)->getID());
2089 return false;
2090 }
2091 }
2092
2094 const_cast<SUMOVehicleParameter::Stop&>(replacedStop.pars) = stop;
2095 replacedStop.initPars(stop);
2096 replacedStop.edge = myRoute->end(); // will be patched in replaceRoute
2097 replacedStop.lane = stopLane;
2099 replacedStop.segment = MSGlobals::gMesoNet->getSegmentForEdge(replacedStop.lane->getEdge(), replacedStop.getEndPos(*this));
2100 if (replacedStop.lane->isInternal()) {
2101 errorMsg = TLF("Mesoscopic simulation does not allow stopping on internal edge '%' for vehicle '%'.", stop.edge, getID());
2102 return false;
2103 }
2104 }
2105
2106 ConstMSEdgeVector oldRemainingEdges(myCurrEdge, getRoute().end());
2107 ConstMSEdgeVector newEdges; // only remaining
2108 newEdges.insert(newEdges.end(), myCurrEdge, itStart);
2109 if (!teleport) {
2110 newEdges.insert(newEdges.end(), toNewStop.begin(), toNewStop.end() - 1);
2111 } else {
2112 newEdges.push_back(*itStart);
2113 }
2114 if (!newDestination) {
2115 newEdges.insert(newEdges.end(), fromNewStop.begin(), fromNewStop.end() - 1);
2116 newEdges.insert(newEdges.end(), itEnd, oldEdges.end());
2117 } else {
2118 newEdges.push_back(stopEdge);
2119 }
2120 //std::cout << SIMTIME << " replaceStop veh=" << getID()
2121 // << " teleport=" << teleport
2122 // << " busStop=" << stop.busstop
2123 // << " oldEdges=" << oldRemainingEdges.size()
2124 // << " newEdges=" << newEdges.size()
2125 // << " toNewStop=" << toNewStop.size()
2126 // << " fromNewStop=" << fromNewStop.size()
2127 // << "\n";
2128
2129 const double routeCost = router.recomputeCosts(newEdges, this, t);
2130 const double previousCost = router.recomputeCosts(oldRemainingEdges, this, t);
2131 const double savings = previousCost - routeCost;
2132 if (!hasDeparted() && (int)myParameter->stops.size() > nextStopIndex) {
2133 // stops will be rebuilt from scratch so we must patch the stops in myParameter
2134 const_cast<SUMOVehicleParameter*>(myParameter)->stops[nextStopIndex] = stop;
2135 }
2136 if (teleport) {
2137 // let the vehicle jump rather than teleport
2138 // we add a jump-stop at the end of the edge (unless the vehicle is
2139 // already configure to jump before the replaced stop)
2140 if (!insertJump(nextStopIndex, itStart, errorMsg)) {
2141 return false;
2142 };
2143 }
2144 return replaceRouteEdges(newEdges, routeCost, savings, info, !hasDeparted(), false, false, &errorMsg);
2145}
2146
2147
2148bool
2149MSBaseVehicle::rerouteBetweenStops(int nextStopIndex, const std::string& info, bool teleport, std::string& errorMsg) {
2150 const int n = (int)myStops.size();
2151 if (nextStopIndex < 0 || nextStopIndex > n) {
2152 errorMsg = TLF("invalid nextStopIndex % for % remaining stops", nextStopIndex, n);
2153 return false;
2154 }
2155 if (nextStopIndex == 0 && isStopped()) {
2156 errorMsg = TL("cannot reroute towards reached stop");
2157 return false;
2158 }
2160
2161 const ConstMSEdgeVector& oldEdges = getRoute().getEdges();
2162 std::vector<MSStop> stops(myStops.begin(), myStops.end());
2163 const int junctionOffset = getLane() != nullptr && getLane()->isInternal() ? 1 : 0;
2164 MSRouteIterator itStart = nextStopIndex == 0 ? getCurrentRouteEdge() + junctionOffset : stops[nextStopIndex - 1].edge;
2165 double startPos = nextStopIndex == 0 ? getPositionOnLane() : stops[nextStopIndex - 1].pars.endPos;
2166 MSRouteIterator itEnd = nextStopIndex == n ? oldEdges.end() - 1 : stops[nextStopIndex].edge;
2167 auto endPos = nextStopIndex == n ? getArrivalPos() : stops[nextStopIndex].pars.endPos;
2169
2170 ConstMSEdgeVector newBetween;
2171 if (!teleport) {
2172 router.compute(*itStart, startPos, *itEnd, endPos, this, t, newBetween, true);
2173 if (newBetween.size() == 0) {
2174 errorMsg = TLF("no route found from edge '%' to stop edge '%'", (*itStart)->getID(), (*itEnd)->getID());
2175 return false;
2176 }
2177 }
2178
2179 ConstMSEdgeVector oldRemainingEdges(myCurrEdge, getRoute().end());
2180 ConstMSEdgeVector newEdges; // only remaining
2181 newEdges.insert(newEdges.end(), myCurrEdge, itStart);
2182 if (!teleport) {
2183 newEdges.insert(newEdges.end(), newBetween.begin(), newBetween.end() - 1);
2184 } else {
2185 newEdges.push_back(*itStart);
2186 }
2187 newEdges.insert(newEdges.end(), itEnd, oldEdges.end());
2188 //std::cout << SIMTIME << " rerouteBetweenStops veh=" << getID()
2189 // << " oldEdges=" << oldRemainingEdges.size()
2190 // << " newEdges=" << newEdges.size()
2191 // << " toNewStop=" << toNewStop.size()
2192 // << " fromNewStop=" << fromNewStop.size()
2193 // << "\n";
2194
2195 const double routeCost = router.recomputeCosts(newEdges, this, t);
2196 const double previousCost = router.recomputeCosts(oldRemainingEdges, this, t);
2197 const double savings = previousCost - routeCost;
2198
2199 if (teleport) {
2200 // let the vehicle jump rather than teleport
2201 // we add a jump-stop at the end of the edge (unless the vehicle is
2202 // already configure to jump before the replaced stop)
2203 if (!insertJump(nextStopIndex, itStart, errorMsg)) {
2204 return false;
2205 };
2206 }
2207 return replaceRouteEdges(newEdges, routeCost, savings, info, !hasDeparted(), false, false, &errorMsg);
2208}
2209
2210
2211bool
2212MSBaseVehicle::insertJump(int nextStopIndex, MSRouteIterator itStart, std::string& errorMsg) {
2213 bool needJump = true;
2214 if (nextStopIndex > 0) {
2215 auto itPriorStop = myStops.begin();
2216 std::advance(itPriorStop, nextStopIndex - 1);
2217 const MSStop& priorStop = *itPriorStop;
2218 if (priorStop.pars.jump >= 0) {
2219 needJump = false;
2220 }
2221 }
2222 if (needJump) {
2223 SUMOVehicleParameter::Stop jumpStopPars;
2224 jumpStopPars.endPos = (*itStart)->getLength();
2225 jumpStopPars.speed = 1000;
2226 jumpStopPars.jump = 0;
2227 jumpStopPars.edge = (*itStart)->getID();
2229 MSLane* jumpStopLane = nullptr;
2230 for (MSLane* cand : (*itStart)->getLanes()) {
2231 if (cand->allowsVehicleClass(getVClass())) {
2232 jumpStopLane = cand;
2233 break;
2234 }
2235 }
2236 if (jumpStopLane == nullptr) {
2237 errorMsg = TL("unable to replace stop with teleporting");
2238 return false;
2239 }
2240 auto itStop = myStops.begin();
2241 std::advance(itStop, nextStopIndex);
2242 MSStop jumpStop(jumpStopPars);
2243 jumpStop.initPars(jumpStopPars);
2244 jumpStop.lane = jumpStopLane;
2245 jumpStop.edge = myRoute->end(); // will be patched in replaceRoute
2246 myStops.insert(itStop, jumpStop);
2247 if (!hasDeparted() && (int)myParameter->stops.size() > nextStopIndex) {
2248 // stops will be rebuilt from scratch so we must patch the stops in myParameter
2249 auto it = myParameter->stops.begin() + nextStopIndex;
2250 const_cast<SUMOVehicleParameter*>(myParameter)->stops.insert(it, jumpStopPars);
2251 }
2252 }
2253 return true;
2254}
2255
2256
2257bool
2258MSBaseVehicle::insertStop(int nextStopIndex, SUMOVehicleParameter::Stop stop, const std::string& info, bool teleport, std::string& errorMsg) {
2259 const int n = (int)myStops.size();
2260 if (nextStopIndex < 0 || nextStopIndex > n) {
2261 errorMsg = TLF("invalid nextStopIndex % for % remaining stops", nextStopIndex, n);
2262 return false;
2263 }
2264 if (nextStopIndex == 0 && isStopped()) {
2265 errorMsg = TL("cannot insert stop before the currently reached stop");
2266 return false;
2267 }
2269 MSLane* stopLane = MSLane::dictionary(stop.lane);
2270 MSEdge* stopEdge = &stopLane->getEdge();
2271
2272 if (!stopLane->allowsVehicleClass(getVClass(), myRoutingMode)) {
2273 errorMsg = TLF("disallowed stop lane '%'", stopLane->getID());
2274 return false;
2275 }
2276
2277 // check parking access rights
2278 if (stop.parkingarea != "") {
2280 if (pa != nullptr && !pa->accepts(this)) {
2281 errorMsg = TLF("Vehicle '%' does not have the right badge to access parkingArea '%'.", getID(), stop.parkingarea);
2282 return false;
2283 }
2284 }
2285
2286 const ConstMSEdgeVector& oldEdges = getRoute().getEdges();
2287 std::vector<MSStop> stops(myStops.begin(), myStops.end());
2288 const int junctionOffset = ((getLane() != nullptr && getLane()->isInternal())
2289 || getRerouteOrigin() != getCurrentRouteEdge()) ? 1 : 0;
2290 MSRouteIterator itStart = nextStopIndex == 0 ? getCurrentRouteEdge() + junctionOffset : stops[nextStopIndex - 1].edge;
2291 double startPos = nextStopIndex == 0 ? getPositionOnLane() : stops[nextStopIndex - 1].pars.endPos;
2292 MSRouteIterator itEnd = nextStopIndex == n ? oldEdges.end() - 1 : stops[nextStopIndex].edge;
2293 auto endPos = nextStopIndex == n ? getArrivalPos() : stops[nextStopIndex].pars.endPos;
2295
2296 const bool newDestination = nextStopIndex == n && stopEdge == oldEdges.back();
2297 const bool needLoop = nextStopIndex > 0 && *itStart == stopEdge && startPos >= stop.endPos;
2298 if (needLoop && startPos == stop.endPos) {
2299 // assume that two stops at the same position indicate a looped route
2300 startPos += POSITION_EPS;
2301 stop.index = STOP_INDEX_REPEAT;
2302 } else if (!hasDeparted()) {
2303 stop.index = STOP_INDEX_END;
2304 }
2305
2306 MSRouteIterator itSentintel = itEnd + 1;
2307 MSRouteIterator onRouteStart = itStart + (needLoop ? 1 : 0);
2308 const bool onRoute = std::find(onRouteStart, itSentintel, stopEdge) != itSentintel;
2309 if (onRoute) {
2310 if (!hasDeparted() && (int)myParameter->stops.size() >= nextStopIndex) {
2311 // stops will be rebuilt from scratch so we must patch the stops in myParameter
2312 auto it = myParameter->stops.begin() + nextStopIndex;
2313 const_cast<SUMOVehicleParameter*>(myParameter)->stops.insert(it, stop);
2314 }
2315 const bool ok = addStop(stop, errorMsg, 0, &onRouteStart);
2316 if (ok) {
2317 updateBestLanes(true, !hasDeparted() ? (*myCurrEdge)->getLanes().front() : 0);
2318 }
2319 return ok;
2320 }
2321
2322 ConstMSEdgeVector toNewStop;
2323 if (!teleport) {
2324 router.compute(*itStart, startPos, stopEdge, stop.endPos, this, t, toNewStop, true);
2325 if (toNewStop.size() == 0) {
2326 errorMsg = TLF("no route found from edge '%' to stop edge '%'", (*itStart)->getID(), stopEdge->getID());
2327 return false;
2328 }
2329 }
2330
2331 ConstMSEdgeVector fromNewStop;
2332 if (!newDestination) {
2333 router.compute(stopEdge, stop.endPos, *itEnd, endPos, this, t, fromNewStop, true);
2334 if (fromNewStop.size() == 0) {
2335 errorMsg = TLF("no route found from stop edge '%' to edge '%'", stopEdge->getID(), (*itEnd)->getID());
2336 return false;
2337 }
2338 }
2339
2340 auto itStop = myStops.begin();
2341 std::advance(itStop, nextStopIndex);
2342 MSStop newStop(stop);
2343 newStop.initPars(stop);
2344 newStop.edge = myRoute->end(); // will be patched in replaceRoute
2345 newStop.lane = stopLane;
2347 newStop.segment = MSGlobals::gMesoNet->getSegmentForEdge(newStop.lane->getEdge(), newStop.getEndPos(*this));
2348 if (newStop.lane->isInternal()) {
2349 errorMsg = TLF("Mesoscopic simulation does not allow stopping on internal edge '%' for vehicle '%'.", stop.edge, getID());
2350 return false;
2351 }
2352 }
2353 myStops.insert(itStop, newStop);
2354
2355 ConstMSEdgeVector oldRemainingEdges(myCurrEdge, getRoute().end());
2356 ConstMSEdgeVector newEdges; // only remaining
2357 newEdges.insert(newEdges.end(), myCurrEdge, itStart);
2358 if (!teleport) {
2359 newEdges.insert(newEdges.end(), toNewStop.begin(), toNewStop.end() - 1);
2360 } else {
2361 newEdges.push_back(*itStart);
2362 }
2363 if (!newDestination) {
2364 newEdges.insert(newEdges.end(), fromNewStop.begin(), fromNewStop.end() - 1);
2365 newEdges.insert(newEdges.end(), itEnd, oldEdges.end());
2366 } else {
2367 newEdges.push_back(stopEdge);
2368 }
2369 //std::cout << SIMTIME << " insertStop veh=" << getID()
2370 // << " teleport=" << teleport
2371 // << " busStop=" << stop.busstop
2372 // << " oldEdges=" << oldRemainingEdges.size()
2373 // << " newEdges=" << newEdges.size()
2374 // << " toNewStop=" << toNewStop.size()
2375 // << " fromNewStop=" << fromNewStop.size()
2376 // << "\n";
2377
2378 const double routeCost = router.recomputeCosts(newEdges, this, t);
2379 const double previousCost = router.recomputeCosts(oldRemainingEdges, this, t);
2380 const double savings = previousCost - routeCost;
2381
2382 if (!hasDeparted() && (int)myParameter->stops.size() >= nextStopIndex) {
2383 // stops will be rebuilt from scratch so we must patch the stops in myParameter
2384 auto it = myParameter->stops.begin() + nextStopIndex;
2385 const_cast<SUMOVehicleParameter*>(myParameter)->stops.insert(it, stop);
2386 }
2387 return replaceRouteEdges(newEdges, routeCost, savings, info, !hasDeparted(), false, false, &errorMsg);
2388}
2389
2390
2393 if (myEnergyParams == nullptr) {
2395 double tMass = 0;
2396 if (myPersonDevice != nullptr) {
2398 tMass += t->getVehicleType().getMass();
2399 }
2400 }
2401 if (myContainerDevice != nullptr) {
2403 tMass += t->getVehicleType().getMass();
2404 }
2405 }
2407 }
2408 return myEnergyParams;
2409}
2410
2411
2412double
2414 if (static_cast<MSDevice_Battery*>(getDevice(typeid(MSDevice_Battery))) != 0) {
2415 MSDevice_Battery* batteryOfVehicle = dynamic_cast<MSDevice_Battery*>(getDevice(typeid(MSDevice_Battery)));
2416 return batteryOfVehicle->getActualBatteryCapacity();
2417 } else {
2418 if (static_cast<MSDevice_ElecHybrid*>(getDevice(typeid(MSDevice_ElecHybrid))) != 0) {
2419 MSDevice_ElecHybrid* batteryOfVehicle = dynamic_cast<MSDevice_ElecHybrid*>(getDevice(typeid(MSDevice_ElecHybrid)));
2420 return batteryOfVehicle->getActualBatteryCapacity();
2421 }
2422 }
2423 return -1;
2424}
2425
2426
2427double
2429 if (static_cast<MSDevice_Battery*>(getDevice(typeid(MSDevice_Battery))) != 0) {
2430 MSDevice_Battery* batteryOfVehicle = dynamic_cast<MSDevice_Battery*>(getDevice(typeid(MSDevice_Battery)));
2431 return batteryOfVehicle->getActualBatteryCapacity() / batteryOfVehicle->getMaximumBatteryCapacity();
2432 } else {
2433 if (static_cast<MSDevice_ElecHybrid*>(getDevice(typeid(MSDevice_ElecHybrid))) != 0) {
2434 MSDevice_ElecHybrid* batteryOfVehicle = dynamic_cast<MSDevice_ElecHybrid*>(getDevice(typeid(MSDevice_ElecHybrid)));
2435 return batteryOfVehicle->getActualBatteryCapacity() / batteryOfVehicle->getMaximumBatteryCapacity();
2436 }
2437 }
2438 return -1;
2439}
2440
2441
2442double
2444 if (static_cast<MSDevice_Battery*>(getDevice(typeid(MSDevice_Battery))) != 0) {
2445 MSDevice_Battery* batteryOfVehicle = dynamic_cast<MSDevice_Battery*>(getDevice(typeid(MSDevice_Battery)));
2446 return batteryOfVehicle->getEnergyCharged();
2447 } else {
2448 if (static_cast<MSDevice_ElecHybrid*>(getDevice(typeid(MSDevice_ElecHybrid))) != 0) {
2449 MSDevice_ElecHybrid* batteryOfVehicle = dynamic_cast<MSDevice_ElecHybrid*>(getDevice(typeid(MSDevice_ElecHybrid)));
2450 return batteryOfVehicle->getEnergyCharged();
2451 }
2452 }
2453 return -1;
2454}
2455
2456
2457double
2459 if (static_cast<MSDevice_Battery*>(getDevice(typeid(MSDevice_Battery))) != 0) {
2460 MSDevice_Battery* batteryOfVehicle = dynamic_cast<MSDevice_Battery*>(getDevice(typeid(MSDevice_Battery)));
2461 return batteryOfVehicle->getMaximumChargeRate();
2462 }
2463 return -1;
2464}
2465
2466
2467double
2469 if (static_cast<MSDevice_ElecHybrid*>(getDevice(typeid(MSDevice_ElecHybrid))) != 0) {
2470 MSDevice_ElecHybrid* elecHybridDevice = dynamic_cast<MSDevice_ElecHybrid*>(getDevice(typeid(MSDevice_ElecHybrid)));
2471 return elecHybridDevice->getCurrentFromOverheadWire();
2472 }
2473
2474 return NAN;
2475}
2476
2477double
2479 if (isOnRoad() || isIdling()) {
2481 } else {
2482 return 0.;
2483 }
2484}
2485
2486
2491
2492
2497
2498
2501 if (myEdgeWeights == nullptr) {
2503 }
2504 return *myEdgeWeights;
2505}
2506
2507
2508
2509
2510int
2512 int boarded = myPersonDevice == nullptr ? 0 : myPersonDevice->size();
2513 return boarded + myParameter->personNumber;
2514}
2515
2516int
2518 int leavingPersonNumber = 0;
2519 const std::vector<MSTransportable*>& persons = getPersons();
2520 for (std::vector<MSTransportable*>::const_iterator it_p = persons.begin(); it_p != persons.end(); ++it_p) {
2521 MSStageDriving* const stage = dynamic_cast<MSStageDriving*>((*it_p)->getCurrentStage());
2522 const MSStop* stop = &myStops.front();
2523 const MSVehicle* joinVeh = dynamic_cast<MSVehicle*>(MSNet::getInstance()->getVehicleControl().getVehicle((*stop).pars.join));
2524 if (stop && stage->canLeaveVehicle(*it_p, *this, *stop) && !MSDevice_Transportable::willTransferAtJoin(*it_p, joinVeh)) {
2525 leavingPersonNumber++;
2526 }
2527 }
2528 return leavingPersonNumber;
2529}
2530
2531std::vector<std::string>
2533 std::vector<std::string> ret;
2534 const std::vector<MSTransportable*>& persons = getPersons();
2535 for (std::vector<MSTransportable*>::const_iterator it_p = persons.begin(); it_p != persons.end(); ++it_p) {
2536 ret.push_back((*it_p)->getID());
2537 }
2538 return ret;
2539}
2540
2541int
2543 int loaded = myContainerDevice == nullptr ? 0 : myContainerDevice->size();
2544 return loaded + myParameter->containerNumber;
2545}
2546
2547
2548void
2550 // this might be called from the MSTransportable destructor so we cannot do a dynamic cast to determine the type
2551 if (myPersonDevice != nullptr) {
2553 }
2554 if (myContainerDevice != nullptr) {
2556 }
2557 if (myEnergyParams != nullptr) {
2559 }
2560}
2561
2562
2563void
2569
2570
2571const std::vector<MSTransportable*>&
2573 if (myPersonDevice == nullptr) {
2575 } else {
2577 }
2578}
2579
2580
2581const std::vector<MSTransportable*>&
2583 if (myContainerDevice == nullptr) {
2585 } else {
2587 }
2588}
2589
2590
2591bool
2592MSBaseVehicle::isLineStop(double position) const {
2593 if (myParameter->line == "") {
2594 // not a public transport line
2595 return false;
2596 }
2597 for (const SUMOVehicleParameter::Stop& stop : myParameter->stops) {
2598 if (stop.startPos <= position && position <= stop.endPos) {
2599 return true;
2600 }
2601 }
2602 for (const SUMOVehicleParameter::Stop& stop : myRoute->getStops()) {
2603 if (stop.startPos <= position && position <= stop.endPos) {
2604 return true;
2605 }
2606 }
2607 return false;
2608}
2609
2610
2611bool
2612MSBaseVehicle::hasDevice(const std::string& deviceName) const {
2613 for (MSDevice* const dev : myDevices) {
2614 if (dev->deviceName() == deviceName) {
2615 return true;
2616 }
2617 }
2618 return false;
2619}
2620
2621
2622void
2623MSBaseVehicle::createDevice(const std::string& deviceName) {
2624 if (!hasDevice(deviceName)) {
2625 if (deviceName == "rerouting") {
2626 ((SUMOVehicleParameter*)myParameter)->setParameter("has." + deviceName + ".device", "true");
2628 if (hasDeparted()) {
2629 // vehicle already departed: disable pre-insertion rerouting and enable regular routing behavior
2630 MSDevice_Routing* routingDevice = static_cast<MSDevice_Routing*>(getDevice(typeid(MSDevice_Routing)));
2631 assert(routingDevice != 0);
2633 }
2634 } else {
2635 throw InvalidArgument(TLF("creating device of type '%' is not supported", deviceName));
2636 }
2637 }
2638}
2639
2640
2641std::string
2642MSBaseVehicle::getDeviceParameter(const std::string& deviceName, const std::string& key) const {
2643 for (MSVehicleDevice* const dev : myDevices) {
2644 if (dev->deviceName() == deviceName) {
2645 return dev->getParameter(key);
2646 }
2647 }
2648 throw InvalidArgument(TLF("no device of type '%' exists", deviceName));
2649}
2650
2651
2652void
2653MSBaseVehicle::setDeviceParameter(const std::string& deviceName, const std::string& key, const std::string& value) {
2654 for (MSVehicleDevice* const dev : myDevices) {
2655 if (dev->deviceName() == deviceName) {
2656 dev->setParameter(key, value);
2657 return;
2658 }
2659 }
2660 throw InvalidArgument(TLF("no device of type '%' exists", deviceName));
2661}
2662
2663
2664void
2665MSBaseVehicle::setJunctionModelParameter(const std::string& key, const std::string& value) {
2668 const_cast<SUMOVehicleParameter&>(getParameter()).setParameter(key, value);
2669 // checked in MSLink::ignoreFoe
2670 } else {
2671 throw InvalidArgument(TLF("Vehicle '%' does not support junctionModel parameter '%'.", getID(), key));
2672 }
2673}
2674
2675
2676void
2677MSBaseVehicle::setCarFollowModelParameter(const std::string& key, const std::string& value) {
2678 // handle some generic params first and then delegate to the carFollowModel itself
2681 const_cast<SUMOVehicleParameter&>(getParameter()).setParameter(key, value);
2682 // checked in MSVehicle::planMove
2683 } else {
2684 MSVehicle* microVeh = dynamic_cast<MSVehicle*>(this);
2685 if (microVeh) {
2686 // remove 'carFollowModel.' prefix
2687 const std::string attrName = key.substr(15);
2688 microVeh->getCarFollowModel().setParameter(microVeh, attrName, value);
2689 }
2690 }
2691}
2692
2693
2694void
2696 /* Design idea for additional junction model parameters:
2697 We can distinguish between 3 levels of parameters
2698 1. typically shared by multiple vehicles -> vType parameter
2699 2. specific to one vehicle but stays constant throughout the simulation -> vehicle parameter
2700 3. specific to one vehicle and expected to change during simulation -> prefixed generic vehicle parameter
2701 */
2702 for (auto item : getParameter().getParametersMap()) {
2703 if (StringUtils::startsWith(item.first, "junctionModel.")) {
2704 setJunctionModelParameter(item.first, item.second);
2705 } else if (StringUtils::startsWith(item.first, "carFollowModel.")) {
2706 setCarFollowModelParameter(item.first, item.second);
2707 }
2708 }
2709 const std::string routingModeStr = getStringParam("device.rerouting.mode");
2710 try {
2711 int routingMode = StringUtils::toInt(routingModeStr);
2712 if (routingMode != libsumo::ROUTING_MODE_DEFAULT) {
2713 setRoutingMode(routingMode);
2714 }
2715 } catch (NumberFormatException&) {
2716 // @todo interpret symbolic constants
2717 throw ProcessError(TLF("could not interpret routing.mode '%'", routingModeStr));
2718 }
2719}
2720
2721
2730
2731
2732void
2734 assert(type != nullptr);
2735 // save old parameters before possible type deletion
2736 const double oldMu = myType->getSpeedFactor().getParameter(0);
2737 const double oldDev = myType->getSpeedFactor().getParameter(1);
2738 if (myType->isVehicleSpecific() && type != myType) {
2740 }
2741 // adapt myChosenSpeedFactor to the new type
2742 if (oldDev == 0.) {
2743 // old type had speedDev 0, reroll
2745 } else {
2746 // map old speedFactor onto new distribution
2747 const double distPoint = (myChosenSpeedFactor - oldMu) / oldDev;
2748 const double newMu = type->getSpeedFactor().getParameter(0);
2749 const double newDev = type->getSpeedFactor().getParameter(1);
2750 myChosenSpeedFactor = newMu + distPoint * newDev;
2751 // respect distribution limits
2754 }
2755 myType = type;
2756 if (myEnergyParams != nullptr) {
2758 }
2759}
2760
2761
2764 if (myType->isVehicleSpecific()) {
2765 return *const_cast<MSVehicleType*>(myType);
2766 }
2767 MSVehicleType* type = myType->buildSingularType(myType->getID() + "@" + getID());
2768 replaceVehicleType(type);
2769 return *type;
2770}
2771
2772
2773int
2775 const MSLane* const lane = getLane();
2776 if (lane == nullptr) {
2777 return getEdge()->getLanes()[0]->getRNGIndex();
2778 } else {
2779 return lane->getRNGIndex();
2780 }
2781}
2782
2783
2784SumoRNG*
2786 const MSLane* lane = getLane();
2787 if (lane == nullptr) {
2788 return getEdge()->getLanes()[0]->getRNG();
2789 } else {
2790 return lane->getRNG();
2791 }
2792}
2793
2794std::string
2795MSBaseVehicle::getPrefixedParameter(const std::string& key, std::string& error) const {
2796 const MSVehicle* microVeh = dynamic_cast<const MSVehicle*>(this);
2797 if (StringUtils::startsWith(key, "device.")) {
2798 StringTokenizer tok(key, ".");
2799 if (tok.size() < 3) {
2800 error = TLF("Invalid device parameter '%' for vehicle '%'.", key, getID());
2801 return "";
2802 }
2803 try {
2804 return getDeviceParameter(tok.get(1), key.substr(tok.get(0).size() + tok.get(1).size() + 2));
2805 } catch (InvalidArgument& e) {
2806 error = TLF("Vehicle '%' does not support device parameter '%' (%).", getID(), key, e.what());
2807 return "";
2808 }
2809 } else if (StringUtils::startsWith(key, "laneChangeModel.")) {
2810 if (microVeh == nullptr) {
2811 error = TLF("Mesoscopic vehicle '%' does not support laneChangeModel parameters.", getID());
2812 return "";
2813 }
2814 const std::string attrName = key.substr(16);
2815 try {
2816 return microVeh->getLaneChangeModel().getParameter(attrName);
2817 } catch (InvalidArgument& e) {
2818 error = TLF("Vehicle '%' does not support laneChangeModel parameter '%' (%).", getID(), key, e.what());
2819 return "";
2820 }
2821 } else if (StringUtils::startsWith(key, "carFollowModel.")) {
2822 if (microVeh == nullptr) {
2823 error = TLF("Mesoscopic vehicle '%' does not support carFollowModel parameters.", getID());
2824 return "";
2825 }
2826 const std::string attrName = key.substr(15);
2827 try {
2828 return microVeh->getCarFollowModel().getParameter(microVeh, attrName);
2829 } catch (InvalidArgument& e) {
2830 error = TLF("Vehicle '%' does not support carFollowModel parameter '%' (%).", getID(), key, e.what());
2831 return "";
2832 }
2833 } else if (StringUtils::startsWith(key, "has.") && StringUtils::endsWith(key, ".device")) {
2834 StringTokenizer tok(key, ".");
2835 if (tok.size() != 3) {
2836 error = TL("Invalid check for device. Expected format is 'has.DEVICENAME.device'.");
2837 return "";
2838 }
2839 return hasDevice(tok.get(1)) ? "true" : "false";
2840 // parking related parameters start here
2841 } else if (key == "parking.rerouteCount") {
2843 } else if (StringUtils::startsWith(key, "parking.memory.")) {
2844 std::vector<std::string> values;
2845 if (getParkingMemory()) {
2846 if (key == "parking.memory.IDList") {
2847 for (const auto& item : *getParkingMemory()) {
2848 values.push_back(item.first->getID());
2849 }
2850 } else if (key == "parking.memory.score") {
2851 for (const auto& item : *getParkingMemory()) {
2852 values.push_back(item.second.score);
2853 }
2854 } else if (key == "parking.memory.blockedAtTime") {
2855 for (const auto& item : *getParkingMemory()) {
2856 values.push_back(toString(STEPS2TIME(item.second.blockedAtTime)));
2857 }
2858 } else if (key == "parking.memory.blockedAtTimeLocal") {
2859 for (const auto& item : *getParkingMemory()) {
2860 values.push_back(toString(STEPS2TIME(item.second.blockedAtTimeLocal)));
2861 }
2862 } else {
2863 error = TLF("Unsupported parking parameter '%' for vehicle '%'.", key, getID());
2864 }
2865 }
2866 return toString(values);
2867 } else {
2868 // default: custom user parameter
2869 return getParameter().getParameter(key, "");
2870 }
2871}
2872
2873
2874void
2881
2882
2883void
2889
2890
2891void
2893 if (myChargingMemory == nullptr) {
2895 }
2897}
2898
2899
2900void
2906
2907
2908void
2909MSBaseVehicle::rememberParkingAreaScore(const MSStoppingPlace* pa, const std::string& score) {
2910 if (myParkingMemory == nullptr) {
2912 }
2914}
2915
2916
2919 if (myParkingMemory == nullptr) {
2920 return -1;
2921 }
2922 return myParkingMemory->sawBlockedStoppingPlace(pa, local);
2923}
2924
2925
2932
2933
2936 if (myChargingMemory == nullptr) {
2937 return -1;
2938 }
2939 return myChargingMemory->sawBlockedStoppingPlace(cs, local);
2940}
2941
2942
2943void
2945 if (hasStops() && myStops.front().parkingarea != nullptr && myStops.front().parkingarea->isReservable()) {
2946 myStops.front().parkingarea->removeSpaceReservation(this);
2947 }
2948}
2949
2950
2951#ifdef _DEBUG
2952void
2953MSBaseVehicle::initMoveReminderOutput(const OptionsCont& oc) {
2954 if (oc.isSet("movereminder-output.vehicles")) {
2955 const std::vector<std::string> vehicles = oc.getStringVector("movereminder-output.vehicles");
2956 myShallTraceMoveReminders.insert(vehicles.begin(), vehicles.end());
2957 }
2958}
2959
2960
2961void
2962MSBaseVehicle::traceMoveReminder(const std::string& type, MSMoveReminder* rem, double pos, bool keep) const {
2963 OutputDevice& od = OutputDevice::getDeviceByOption("movereminder-output");
2964 od.openTag("movereminder");
2965 od.writeAttr(SUMO_ATTR_TIME, STEPS2TIME(MSNet::getInstance()->getCurrentTimeStep()));
2966 od.writeAttr("veh", getID());
2968 od.writeAttr("type", type);
2969 od.writeAttr("pos", toString(pos));
2970 od.writeAttr("keep", toString(keep));
2971 od.closeTag();
2972}
2973#endif
2974
2975
2976/****************************************************************************/
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:330
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
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:1120
bool hasTransientPermissions() const
Definition MSEdge.cpp:1699
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:1368
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:1075
const MSEdge * getNormalBefore() const
if this edge is an internal edge, return its first normal predecessor, otherwise the edge itself
Definition MSEdge.cpp:965
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:2471
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:2495
bool isInternal() const
Definition MSLane.cpp:2626
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:1747
@ NEWROUTE
The vehicle got a new route.
static MSNet * getInstance()
Returns the pointer to the unique instance of MSNet (singleton).
Definition MSNet.cpp:187
MSEventControl * getBeginOfTimestepEvents()
Returns the event control for events executed at the begin of a time step.
Definition MSNet.h:485
const std::vector< MSStoppingPlace * > & getStoppingPlaceAlternatives(const std::string &name, SumoXMLTag category) const
Definition MSNet.cpp:1510
MSVehicleRouter & getRouterTT(int rngIndex, const Prohibitions &prohibited={}) const
Definition MSNet.cpp:1607
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:1475
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:1350
MSInsertionControl & getInsertionControl()
Returns the insertion control.
Definition MSNet.h:445
MSVehicleControl & getVehicleControl()
Returns the vehicle control.
Definition MSNet.h:392
A lane area vehicles can halt at.
bool accepts(SUMOVehicle *veh) const
Return the parking accepts the vehicle (due to its given badges)
static void storeTripId(const std::string &tripId, const std::string &vehID)
const ConstMSEdgeVector & getEdges() const
Definition MSRoute.h:128
void setCosts(double costs)
Sets the costs of the route.
Definition MSRoute.h:209
static bool hasRoute(const std::string &id)
returns whether a route with the given id exists
Definition MSRoute.cpp:159
static bool dictionary(const std::string &id, ConstMSRoutePtr route)
Adds a route to the dictionary.
Definition MSRoute.cpp:116
static void checkDist(const std::string &id)
Checks the distribution whether it is permanent and deletes it if not.
Definition MSRoute.cpp:194
void setSavings(double savings)
Sets the savings of the route.
Definition MSRoute.h:216
static MSVehicleRouter & getRouterTT(const int rngIndex, SUMOVehicleClass svc, const Prohibitions &prohibited={})
return the vehicle router instance
bool canLeaveVehicle(const MSTransportable *t, const SUMOVehicle &veh, const MSStop &stop)
checks whether the person may exit at the current vehicle position
const MSLane * lane
The lane to stop at (microsim only)
Definition MSStop.h:50
MSStoppingPlace * containerstop
(Optional) container stop if one is assigned to the stop
Definition MSStop.h:56
std::string getDescription(bool nameOnly=false) const
get a short description for showing in the gui
Definition MSStop.cpp:70
bool isOpposite
whether this an opposite-direction stop
Definition MSStop.h:87
void initPars(const SUMOVehicleParameter::Stop &stopPar)
initialize attributes from the given stop parameters
Definition MSStop.cpp:148
const MESegment * segment
The segment to stop at (mesosim only)
Definition MSStop.h:52
bool reached
Information whether the stop has been reached.
Definition MSStop.h:75
MSRouteIterator edge
The edge in the route to stop at.
Definition MSStop.h:48
double getEndPos(const SUMOVehicle &veh) const
return halting position for upcoming stop;
Definition MSStop.cpp:36
MSParkingArea * parkingarea
(Optional) parkingArea if one is assigned to the stop
Definition MSStop.h:58
MSStoppingPlace * chargingStation
(Optional) charging station if one is assigned to the stop
Definition MSStop.h:60
SUMOTime getUntil() const
return until / ended time
Definition MSStop.cpp:187
SUMOTime getArrival() const
return arrival / started time
Definition MSStop.cpp:193
const SUMOVehicleParameter::Stop pars
The stop parameter.
Definition MSStop.h:65
MSStoppingPlace * busstop
(Optional) bus stop if one is assigned to the stop
Definition MSStop.h:54
MSStoppingPlace * overheadWireSegment
(Optional) overhead wire segment if one is assigned to the stop
Definition MSStop.h:63
Finds a sequence of skips and stop alternatives to maximize priority of reached stops.
ConstMSEdgeVector optimizeSkipped(const MSEdge *source, double sourcePos, std::vector< StopEdgeInfo > &stops, ConstMSEdgeVector edges) const
A lane area vehicles can halt at.
double getBeginLanePosition() const
Returns the begin position of this stop.
double getParkingLength() const
double getEndLanePosition() const
Returns the end position of this stop.
const MSLane & getLane() const
Returns the lane this stop is located at.
bool isPerson() const override
Whether it is a person.
const MSVehicleType & getVehicleType() const override
Returns the object's "vehicle" type.
static const double DEFAULT_MAXDELAY
void vehicleDeparted(const SUMOVehicle &v)
Informs this control about a vehicle's departure.
SUMOVehicle * getVehicle(const std::string &id) const
Returns the vehicle with the given id.
void removeVType(const MSVehicleType *vehType)
void unregisterOneWaiting()
decreases the count of vehicles waiting for a transport to allow recognition of person / container re...
Abstract in-vehicle device.
Representation of a vehicle in the micro simulation.
Definition MSVehicle.h:77
MSAbstractLaneChangeModel & getLaneChangeModel()
const MSCFModel & getCarFollowModel() const
Returns the vehicle's car following model definition.
Definition MSVehicle.h:969
The car-following model and parameter.
const EnergyParams * getEmissionParameters() const
retrieve parameters for the energy consumption model
SUMOVehicleClass getVehicleClass() const
Get this vehicle type's vehicle class.
double getMaxSpeed() const
Get vehicle's (technical) maximum speed [m/s].
double getDesiredMaxSpeed() const
Returns the vehicles's desired maximum speed.
const std::string & getID() const
Returns the name of the vehicle type.
const Distribution_Parameterized & getSpeedFactor() const
Returns this type's speed factor.
bool isVehicleSpecific() const
Returns whether this type belongs to a single vehicle only (was modified)
SUMOEmissionClass getEmissionClass() const
Get this vehicle type's emission class.
double getLength() const
Get vehicle's length [m].
double getMass() const
Get this vehicle type's mass.
double computeChosenSpeedDeviation(SumoRNG *rng, const double minDev=-1.) const
Computes and returns the speed deviation.
MSVehicleType * buildSingularType(const std::string &id) const
Duplicates the microsim vehicle type giving the newly created type the given id, marking it as vehicl...
const std::vector< std::string > & getParkingBadges() const
Returns the parking access rights of this type.
static std::string getIDSecure(const T *obj, const std::string &fallBack="NULL")
get an identifier for Named-like object which may be Null
Definition Named.h:67
const std::string & getID() const
Returns the id.
Definition Named.h:74
A storage for options typed value containers)
Definition OptionsCont.h:89
bool isSet(const std::string &name, bool failOnNonExistant=true) const
Returns the information whether the named option is set.
const StringVector & getStringVector(const std::string &name) const
Returns the list of string-value of the named option (only for Option_StringVector)
static OptionsCont & getOptions()
Retrieves the options.
Static storage of an output device and its base (abstract) implementation.
OutputDevice & 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
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_IGNORE_TRANSIENT_PERMISSIONS