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 // stopIt->edge may be invalid when trying to reroute for novel stops
413 while (stopIt != myStops.end() && stopIt->lane->getNextNormal()->getID() != stopEdge->getID()) {
414 stopIt++;
415 }
416
417 startTime += TIME2STEPS(router.recomputeCostsPos(into, this, sourcePos, stopEdgeInfo.pos, startTime));
418 if (stopIt != myStops.end()) {
419 if (stopIt->pars.priority >= 0 && info != "device.rerouting") {
420 // consider skipping this stop if it cannot be reached in a timely manner
421 if (stopIt != myStops.end()) {
422 SUMOTime arrival = stopEdgeInfo.arrival;
423 if (arrival > 0) {
424 SUMOTime delay = startTime - arrival;
425 //std::cout << " t=" << time2string(t) << " veh=" << getID() << " info=" << info << " stopIndex=" << stopIndex
426 // << " into=" << toString(into) << " sourcePos=" << sourcePos << " stopPos=" << stopPos
427 // << " startTime=" << time2string(startTime) << " arrival=" << time2string(arrival) << " delay=" << time2string(delay) << "\n";
428 if (delay > 0) {
429 if (delay > maxDelay) {
430 stopEdgeInfo.skipped = true;
431 stopEdgeInfo.delay = delay;
432 hasSkipped = true;
433 continue;
434 }
435 }
436 }
437 }
438 }
439 sourcePos = stopEdgeInfo.pos;
440 startTime += stopIt->getMinDuration(startTime);
441 }
442 edges.pop_back();
443 edges.insert(edges.end(), into.begin(), into.end());
444 if (edges.back()->isTazConnector()) {
445 edges.pop_back();
446 }
447 source = edges.back();
448 stopEdgeInfo.routeIndex = (int)edges.size() - 1;
449 } else {
450 if (priority >= 0) {
451 stopEdgeInfo.skipped = true;
452 hasSkipped = true;
453 continue;
454 } else if (stopEdgeInfo.isSink) {
455 //error = TLF("Vehicle '%' has no valid route from edge '%' to destination edge '%'.", getID(), source->getID(), stopEdge->getID());
456 edges.clear();
457 if (onInit && source == stopEdge && stops.size() == 1 && sourcePos > myArrivalPos) {
458 edges.push_back(stopEdge);
459 WRITE_WARNING(TLF("Vehicle '%' ignores arrivalPos % when driving from edge '%' to edge '%'.", getID(), myArrivalPos, source->getID(), stopEdge->getID()));
460 }
461 } else if (source == stopEdge && stopEdgeInfo.stopPar != nullptr && stopEdgeInfo.stopPar->endPos >= sourcePos) {
462 // special case: no failure on dynamically computed stop position
463 edges.clear();
464 } else {
465 std::string error = TLF("Vehicle '%' has no valid route from edge '%' to stop edge '%'.", getID(), source->getID(), stopEdge->getID());
466 if (MSGlobals::gCheckRoutes || silent) {
467 throw ProcessError(error);
468 } else {
469 WRITE_WARNING(error);
470 edges.push_back(source);
471 source = stopEdge;
472 }
473 }
474 }
475 }
476 if (hasSkipped) {
477 MSStopOptimizer opti(this, router, t, maxDelay);
478 edges = opti.optimizeSkipped(origSource, origSourcePos, stops, edges);
479 for (auto stop : stops) {
480 if (stop.skipped || stop.origEdge != nullptr) {
481 const MSEdge* origEdge = stop.origEdge == nullptr ? stop.edge : stop.origEdge;
482 if (stop.delay > 0) {
483 WRITE_WARNING(TLF("Vehicle '%' skips stop on edge '%' with delay % at time %.", getID(), origEdge->getID(), time2string(stop.delay), time2string(SIMSTEP)));
484 } else if (stop.backtracked) {
485 WRITE_WARNING(TLF("Vehicle '%' skips stop on edge '%' with priority % at time %.", getID(), origEdge->getID(), stop.priority, time2string(SIMSTEP)));
486 } else {
487 WRITE_WARNING(TLF("Vehicle '%' skips unreachable stop on edge '%' with priority % at time %.", getID(), origEdge->getID(), stop.priority, time2string(SIMSTEP)));
488 }
489 }
490 }
491 }
492
493 // router.setHint(myCurrEdge, myRoute->end(), this, t);
494 if (edges.empty() && silent) {
495 return false;
496 }
497 if (!edges.empty() && edges.front()->isTazConnector()) {
498 edges.erase(edges.begin());
499 }
500 if (!edges.empty() && edges.back()->isTazConnector()) {
501 edges.pop_back();
502 }
503 const double routeCost = router.recomputeCosts(edges, this, t);
504 const double previousCost = onInit ? routeCost : router.recomputeCosts(oldEdgesRemaining, this, t);
505 const double savings = previousCost - routeCost;
506 bool savingsOk = onInit || info != "device.rerouting" || gWeightsRandomFactor != 1;
507 if (!savingsOk) {
508 MSDevice_Routing* routingDevice = static_cast<MSDevice_Routing*>(getDevice(typeid(MSDevice_Routing)));
509 assert(routingDevice != 0);
510 savingsOk = routingDevice->sufficientSaving(previousCost, routeCost);
511 if (!savingsOk) {
512 std::string dummyMsg;
513 if (!hasValidRoute(dummyMsg, oldEdgesRemaining.begin(), oldEdgesRemaining.end(), true)) {
514 // the old route is prohibted (i.e. due to temporary permission changes)
515 savingsOk = true;
516 }
517 }
518 }
519 //if (getID() == "43") std::cout << SIMTIME << " pCost=" << previousCost << " cost=" << routeCost
520 // << " onInit=" << onInit
521 // << " prevEdges=" << toString(oldEdgesRemaining)
522 // << " newEdges=" << toString(edges)
523 // << "\n";
524 if (savingsOk) {
525 replaceRouteEdges(edges, routeCost, savings, info, onInit, false, hasSkipped);
526 }
527 // this must be called even if the route could not be replaced
528 if (onInit) {
529 if (edges.empty()) {
531 throw ProcessError(TLF("Vehicle '%' has no valid route.", getID()));
532 } else if (source->isTazConnector()) {
533 WRITE_WARNINGF(TL("Removing vehicle '%' which has no valid route."), getID());
535 return false;
536 }
537 }
540 }
541 return !edges.empty();
542}
543
544
545bool
546MSBaseVehicle::replaceRouteEdges(ConstMSEdgeVector& edges, double cost, double savings, const std::string& info, bool onInit, bool check, bool removeStops, std::string* msgReturn) {
547 if (edges.empty()) {
548 WRITE_WARNINGF(TL("No route for vehicle '%' found."), getID());
549 if (msgReturn != nullptr) {
550 *msgReturn = "No route found";
551 }
552 return false;
553 }
554 // build a new id, first
555 std::string id = getID();
556 if (id[0] != '!') {
557 id = "!" + id;
558 }
559 const std::string idSuffix = id + "!var#";
560 int varIndex = 1;
561 id = idSuffix + toString(varIndex);
562 while (MSRoute::hasRoute(id)) {
563 id = idSuffix + toString(++varIndex);
564 }
565 int oldSize = (int)edges.size();
566 if (!onInit) {
567 const MSEdge* const origin = *getRerouteOrigin();
568 if (origin != *myCurrEdge && edges.front() == origin) {
569 edges.insert(edges.begin(), *myCurrEdge);
570 oldSize = (int)edges.size();
571 }
572 edges.insert(edges.begin(), myRoute->begin(), myCurrEdge);
573 }
574 if (edges == myRoute->getEdges() && haveValidStopEdges(true)) {
575 // re-assign stop iterators when rerouting to a new parkingArea / insertStop
576 return true;
577 }
578 const RGBColor& c = myRoute->getColor();
579 MSRoute* newRoute = new MSRoute(id, edges, false, &c == &RGBColor::DEFAULT_COLOR ? nullptr : new RGBColor(c), StopParVector());
580 newRoute->setCosts(cost);
581 newRoute->setSavings(savings);
582 ConstMSRoutePtr constRoute = std::shared_ptr<MSRoute>(newRoute);
583 if (!MSRoute::dictionary(id, constRoute)) {
584 delete newRoute;
585 if (msgReturn != nullptr) {
586 *msgReturn = "duplicate routeID '" + id + "'";
587 }
588 return false;
589 }
590
591 std::string msg;
592 if (check && !hasValidRoute(msg, constRoute)) {
593 WRITE_WARNINGF(TL("Invalid route replacement for vehicle '%'. %"), getID(), msg);
595 if (msgReturn != nullptr) {
596 *msgReturn = msg;
597 }
598 return false;
599 }
600 }
601 if (!replaceRoute(constRoute, info, onInit, (int)edges.size() - oldSize, false, removeStops, msgReturn)) {
602 return false;
603 }
604 return true;
605}
606
607
608bool
609MSBaseVehicle::replaceRoute(ConstMSRoutePtr newRoute, const std::string& info, bool onInit, int offset, bool addRouteStops, bool removeStops, std::string* msgReturn) {
610 const ConstMSEdgeVector& edges = newRoute->getEdges();
611 // rebuild in-vehicle route information
612 if (onInit) {
613 myCurrEdge = newRoute->begin();
614 } else {
615 MSRouteIterator newCurrEdge = std::find(edges.begin() + offset, edges.end(), *myCurrEdge);
616 if (newCurrEdge == edges.end()) {
617 if (msgReturn != nullptr) {
618 *msgReturn = TLF("current edge '%' not found in new route", (*myCurrEdge)->getID());
619 }
620#ifdef DEBUG_REPLACE_ROUTE
621 if (DEBUG_COND) {
622 std::cout << " newCurrEdge not found\n";
623 }
624#endif
625 return false;
626 }
627 if (getLane() != nullptr) {
628 if (getLane()->getEdge().isInternal() && (
629 (newCurrEdge + 1) == edges.end() || (*(newCurrEdge + 1)) != &(getLane()->getOutgoingViaLanes().front().first->getEdge()))) {
630 if (msgReturn != nullptr) {
631 *msgReturn = TL("Vehicle is on junction-internal edge leading elsewhere");
632 }
633#ifdef DEBUG_REPLACE_ROUTE
634 if (DEBUG_COND) {
635 std::cout << " Vehicle is on junction-internal edge leading elsewhere\n";
636 }
637#endif
638 return false;
639 } else if (getPositionOnLane() > getLane()->getLength()
640 && (myCurrEdge + 1) != myRoute->end()
641 && (newCurrEdge + 1) != edges.end()
642 && *(myCurrEdge + 1) != *(newCurrEdge + 1)) {
643 if (msgReturn != nullptr) {
644 *msgReturn = TL("Vehicle is moving past junction and committed to move to another successor edge");
645 }
646#ifdef DEBUG_REPLACE_ROUTE
647 if (DEBUG_COND) {
648 std::cout << " Vehicle is moving past junction and committed to move to another successor edge\n";
649 }
650#endif
651 return false;
652 }
653 }
654 myCurrEdge = newCurrEdge;
655 }
656 const bool stopsFromScratch = onInit && myRoute->getStops().empty();
657 // assign new route
659 myRoute = newRoute;
660 // update arrival definition
662 // save information that the vehicle was rerouted
664 myStopUntilOffset += myRoute->getPeriod();
666 if (!onInit && isRail() && MSRailSignalControl::hasInstance()) {
667 // we need to update driveways (add/remove reminders) before the next call to MSRailSignalControl::updateSignals
668 //
669 // rerouting may be triggered through
670 // - MoveReminders (executeMove->activateReminders)
671 // - rerouters
672 // - devices (MSDevice_Stationfinder)
673 // - TraCI (changeTarget, replaceStop, ...
674 // - events (MSDevice_Routing::myRerouteCommand, MSDevice_Taxi::triggerDispatch)
675 //
676 // Since activateReminders actively modifies reminders, adding/deleting reminders would create a mess
677 // hence, we use an event to be safe for all case
678
681 }
682#ifdef DEBUG_REPLACE_ROUTE
683 if (DEBUG_COND) {
684 std::cout << SIMTIME << " veh=" << getID() << " replaceRoute info=" << info << " on " << (*myCurrEdge)->getID()
685 << " lane=" << Named::getIDSecure(getLane())
686 << " stopsFromScratch=" << stopsFromScratch
687 << " newSize=" << newRoute->getEdges().size()
688 << " newIndex=" << (myCurrEdge - newRoute->begin())
689 << " edges=" << toString(newRoute->getEdges())
690 << "\n";
691 }
692#endif
693 // remove past stops which are not on the route anymore
694 for (StopParVector::iterator it = myPastStops.begin(); it != myPastStops.end();) {
695 const MSEdge* stopEdge = (it->edge.empty()) ? &MSLane::dictionary(it->lane)->getEdge() : MSEdge::dictionary(it->edge);
696 if (std::find(myRoute->begin(), myRoute->end(), stopEdge) == myRoute->end()) {
697 it = myPastStops.erase(it);
698 } else {
699 ++it;
700 }
701 }
702 // if we did not drive yet it may be best to simply reassign the stops from scratch
703 if (stopsFromScratch) {
704 myStops.clear();
706 } else {
707 // recheck old stops
708 MSRouteIterator searchStart = myCurrEdge;
709 double lastPos = getPositionOnLane() + getBrakeGap();
710 if (getLane() != nullptr && getLane()->isInternal()
711 && myStops.size() > 0 && !myStops.front().lane->isInternal()) {
712 // searchStart is still incoming to the intersection so lastPos
713 // relative to that edge must be adapted
714 lastPos += (*myCurrEdge)->getLength();
715 }
716 int stopIndex = 0;
717 for (std::list<MSStop>::iterator iter = myStops.begin(); iter != myStops.end();) {
718 int lastToSkip = 0;
719 double endPos = iter->getEndPos(*this);
720#ifdef DEBUG_REPLACE_ROUTE
721 if (DEBUG_COND) {
722 std::cout << " stopEdge=" << iter->lane->getEdge().getID() << " start=" << (searchStart - myCurrEdge) << " endPos=" << endPos << " lastPos=" << lastPos << "\n";
723 }
724#endif
725 if (*searchStart != &iter->lane->getEdge()
726 // loop required to reach upstream position
727 || endPos + NUMERICAL_EPS < lastPos
728 // loop requested at duplicate pos
729 || (endPos == lastPos && iter->pars.index == STOP_INDEX_REPEAT)
730 // index encodes a skip
731 || (iter->pars.index > (int)myPastStops.size() + stopIndex
732 // and we are not already past the skipped edge
733 && lastToSkip < (int)iter->skips.size()
734 && searchStart - myRoute->begin() <= iter->skips[lastToSkip])) {
735 if (searchStart != edges.end() && !iter->reached) {
736#ifdef DEBUG_REPLACE_ROUTE
737 if (DEBUG_COND) {
738 std::cout << " skip " << (*searchStart)->getID() << "\n";
739 }
740#endif
741 lastToSkip++;
742 searchStart++;
743 }
744 }
745 lastPos = endPos;
746
747 iter->edge = std::find(searchStart, edges.end(), &iter->lane->getEdge());
748#ifdef DEBUG_REPLACE_ROUTE
749 if (DEBUG_COND) {
750 std::cout << " foundIndex=" << (iter->edge - myCurrEdge) << " end=" << (edges.end() - myCurrEdge) << "\n";
751 }
752#endif
753 if (iter->edge == edges.end() && iter->pars.priority >= 0) {
754 const std::string oldEdge = iter->pars.edge;
755 const std::string oldName = iter->getStoppingPlaceName().first;
756 if (replaceWithAlternative(iter, searchStart, edges.end())) {
757 WRITE_WARNINGF(TL("Vehicle '%' replaced stop on edge '%' (named '%') and now stops at '%' instead; after rerouting (%) at time=%."),
758 getID(), oldEdge, oldName, iter->getDescription(true), info, time2string(SIMSTEP));
759 }
760 }
761 if (iter->edge == edges.end()) {
762 if (!removeStops) {
763 WRITE_ERRORF(TL("Vehicle '%' could not assign stop '%' after rerouting (%) at time=%."), getID(), iter->getDescription(), info, time2string(SIMSTEP));
764 }
765 iter = myStops.erase(iter);
766 continue;
767 } else {
768 setSkips(*iter, stopIndex);
769 searchStart = iter->edge;
770 }
771 ++iter;
772 stopIndex++;
773 }
774 // add new stops
775 if (addRouteStops) {
776 for (StopParVector::const_iterator i = newRoute->getStops().begin(); i != newRoute->getStops().end(); ++i) {
777 std::string error;
779 if (error != "") {
780 WRITE_WARNING(error);
781 }
782 }
783 }
784 }
785 return true;
786}
787
788
789bool
790MSBaseVehicle::replaceWithAlternative(std::list<MSStop>::iterator iter, const MSRouteIterator searchStart, const MSRouteIterator end) {
791 std::pair<std::string, SumoXMLTag> nameTag = iter->getStoppingPlaceName();
792 if (!nameTag.first.empty()) {
793 const std::vector<MSStoppingPlace*>& alternatives = MSNet::getInstance()->getStoppingPlaceAlternatives(nameTag.first, nameTag.second);
794 for (MSStoppingPlace* alt : alternatives) {
795 //std::cout << SIMTIME << " veh=" << getID() << " name=" << nameTag.first << " alt=" << alt->getID() << "\n";
796 if (&alt->getLane().getEdge() == &iter->lane->getEdge()
797 || !alt->getLane().allowsVehicleClass(getVClass())) {
798 continue;
799 }
800 iter->edge = std::find(searchStart, end, &alt->getLane().getEdge());
801 if (iter->edge != end) {
802 iter->replaceStoppingPlace(alt);
803 return true;
804 }
805 }
806 }
807 return false;
808}
809
810
811double
813 return 0;
814}
815
816
817void
823
824
827 const SUMOTime dep = getParameter().depart;
828 if (dep < 0) {
829 return 0;
830 }
831 return hasDeparted() ? getDeparture() - dep : SIMSTEP - dep;
832}
833
834
835bool
837 return succEdge(1) == nullptr;
838}
839
840
841int
843 return (int) std::distance(myRoute->begin(), myCurrEdge);
844}
845
846
847int
849 if (myParameter->arrivalEdge >= 0) {
851 } else {
852 return myRoute->size() - getRoutePosition();
853 }
854}
855
856
857void
859 myCurrEdge = myRoute->begin() + index;
860 const_cast<SUMOVehicleParameter*>(myParameter)->departLaneProcedure = departLaneProcedure;
861 // !!! hack
862 myArrivalPos = (*(myRoute->end() - 1))->getLanes()[0]->getLength();
863}
864
865double
869
870bool
872 if (t->isPerson() && getPersonNumber() >= getVehicleType().getPersonCapacity()) {
873 return false;
874 } else if (!t->isPerson() && getContainerNumber() >= getVehicleType().getContainerCapacity()) {
875 return false;
876 }
877 if (isStopped() && myStops.begin()->pars.permitted.size() > 0
878 && myStops.begin()->pars.permitted.count(t->getID()) == 0) {
879 return false;
880 }
881 MSDevice_Taxi* taxiDevice = static_cast<MSDevice_Taxi*>(getDevice(typeid(MSDevice_Taxi)));
882 if (taxiDevice != nullptr) {
883 return taxiDevice->allowsBoarding(t);
884 }
885 return true;
886}
887
888
889void
891 if (transportable->isPerson()) {
892 if (myPersonDevice == nullptr) {
896 }
897 }
898 myPersonDevice->addTransportable(transportable);
899 } else {
900 if (myContainerDevice == nullptr) {
904 }
905 }
906 myContainerDevice->addTransportable(transportable);
907 }
908 if (myEnergyParams != nullptr) {
910 }
911}
912
913
914void
916 if (isPerson) {
918 myMoveReminders.insert(myMoveReminders.begin(), std::make_pair(myPersonDevice, 0.));
919 } else {
921 myMoveReminders.insert(myMoveReminders.begin(), std::make_pair(myContainerDevice, 0.));
922 }
923}
924
925
926bool
928 for (const MSStop& stop : myStops) {
929 if (stop.edge == it && stop.pars.jump >= 0) {
930 return true;
931 } else if (stop.edge > it) {
932 return false;
933 }
934 }
935 return false;
936}
937
938
939bool
940MSBaseVehicle::hasValidRoute(std::string& msg, ConstMSRoutePtr route) const {
942 if (route == nullptr) {
943 route = myRoute;
944 } else {
945 start = route->begin();
946 }
947 const bool checkJumps = route == myRoute; // the edge iterators in the stops are invalid otherwise
948 return hasValidRoute(msg, start, route->end(), checkJumps);
949}
950
951
952bool
953MSBaseVehicle::hasValidRoute(std::string& msg, MSRouteIterator start, MSRouteIterator last, bool checkJumps) const {
954 MSRouteIterator lastValid = last - 1;
955 // check connectivity, first
956 for (MSRouteIterator e = start; e != lastValid; ++e) {
957 const MSEdge& next = **(e + 1);
958 if ((*e)->allowedLanes(next, myType->getVehicleClass()) == nullptr) {
959 if (!checkJumps || !hasJump(e)) {
961 || (!next.hasTransientPermissions() && !(*e)->hasTransientPermissions())) {
962 msg = TLF("No connection between edge '%' and edge '%'.", (*e)->getID(), (*(e + 1))->getID());
963 return false;
964 }
965 }
966 }
967 }
968 // check usable lanes, then
969 for (MSRouteIterator e = start; e != last; ++e) {
970 if ((*e)->prohibits(this)) {
971 msg = TLF("Edge '%' prohibits.", (*e)->getID());
972 return false;
973 }
974 }
975 return true;
976}
977
978
979bool
981 if (!(*myCurrEdge)->isTazConnector()) {
983 msg = TLF("Departure speed for vehicle '%' is too high for the vehicle type '%'.", getID(), myType->getID());
985 return false;
986 }
987 }
988 if (myRoute->getEdges().size() > 0 && !(*myCurrEdge)->prohibits(this)) {
989 myRouteValidity &= ~ROUTE_START_INVALID_PERMISSIONS;
990 return true;
991 } else {
992 msg = TLF("Vehicle '%' is not allowed to depart on any lane of edge '%'.", getID(), (*myCurrEdge)->getID());
994 return false;
995 }
996}
997
998
999int
1000MSBaseVehicle::getRouteValidity(bool update, bool silent, std::string* msgReturn) {
1001 if (!update) {
1002 return myRouteValidity;
1003 }
1004 // insertion check must be done in any case
1005 std::string msg;
1006 if (!hasValidRouteStart(msg)) {
1008 throw ProcessError(msg);
1009 } else if (!silent) {
1010 // vehicle will be discarded
1011 WRITE_WARNING(msg);
1012 } else if (msgReturn != nullptr) {
1013 *msgReturn = msg;
1014 }
1015 }
1016 if ((MSGlobals::gCheckRoutes || myRoute->getFirstEdge()->isInternal())
1018 // we could check after the first rerouting
1020 if (!hasValidRoute(msg, myRoute)) {
1022 throw ProcessError(TLF("Vehicle '%' has no valid route. %", getID(), msg));
1023 }
1024 }
1025 myRouteValidity &= ~ROUTE_UNCHECKED;
1026 return myRouteValidity;
1027}
1028
1029
1030bool
1032 for (auto item : myMoveReminders) {
1033 if (item.first == rem) {
1034 return true;
1035 }
1036 }
1037 return false;
1038}
1039
1040
1041void
1043#ifdef _DEBUG
1044 if (myTraceMoveReminders) {
1045 traceMoveReminder("add", rem, pos, true);
1046 }
1047#endif
1048 myMoveReminders.push_back(std::make_pair(rem, pos));
1049}
1050
1051
1052void
1054 for (MoveReminderCont::iterator r = myMoveReminders.begin(); r != myMoveReminders.end(); ++r) {
1055 if (r->first == rem) {
1056#ifdef _DEBUG
1057 if (myTraceMoveReminders) {
1058 traceMoveReminder("remove", rem, 0, false);
1059 }
1060#endif
1061 myMoveReminders.erase(r);
1062 return;
1063 }
1064 }
1065}
1066
1067
1068void
1070 // notifyEnter may cause new reminders to be added so we cannot use an iterator
1071 for (int i = 0; i < (int)myMoveReminders.size();) {
1072 MSMoveReminder* rem = myMoveReminders[i].first;
1073 const double remPos = myMoveReminders[i].second;
1074 // skip the reminder if it is a lane reminder but not for my lane (indicated by rem->second > 0.)
1075 if (rem->getLane() != nullptr && remPos > 0.) {
1076#ifdef _DEBUG
1077 if (myTraceMoveReminders) {
1078 traceMoveReminder("notifyEnter_skipped", rem, remPos, true);
1079 }
1080#endif
1081 ++i;
1082 } else {
1083 if (rem->notifyEnter(*this, reason, enteredLane)) {
1084#ifdef _DEBUG
1085 if (myTraceMoveReminders) {
1086 traceMoveReminder("notifyEnter", rem, remPos, true);
1087 }
1088#endif
1089 ++i;
1090 } else {
1091#ifdef _DEBUG
1092 if (myTraceMoveReminders) {
1093 traceMoveReminder("notifyEnter", rem, remPos, false);
1094 }
1095#endif
1096 myMoveReminders.erase(myMoveReminders.begin() + i);
1097 }
1098 }
1099 }
1100}
1101
1102
1103bool
1105 return isRailway(getVClass()) || isRailway(getCurrentEdge()->getPermissions());
1106}
1107
1108void
1110 if (myRoute->getLastEdge()->isTazConnector()) {
1111 return;
1112 }
1113 const int arrivalEdgeIndex = MIN2(myParameter->arrivalEdge, (int)myRoute->getEdges().size() - 1);
1114 if (arrivalEdgeIndex != myParameter->arrivalEdge) {
1115 if (!(onInit && myParameter->wasSet(VEHPARS_FORCE_REROUTE))) {
1116 WRITE_WARNINGF(TL("Vehicle '%' ignores attribute arrivalEdge=% after rerouting at time=% (routeLength=%)"),
1117 getID(), myParameter->arrivalEdge, time2string(SIMSTEP), myRoute->getEdges().size() - 1);
1118 }
1119 }
1120 const MSEdge* arrivalEdge = myParameter->arrivalEdge >= 0 ? myRoute->getEdges()[arrivalEdgeIndex] : myRoute->getLastEdge();
1121 if (!onInit) {
1122 arrivalEdge = myRoute->getLastEdge();
1123 // ignore arrivalEdge parameter after rerouting
1124 const_cast<SUMOVehicleParameter*>(myParameter)->arrivalEdge = -1;
1125 }
1126 const std::vector<MSLane*>& lanes = arrivalEdge->getLanes();
1127 const double lastLaneLength = lanes[0]->getLength();
1130 if (fabs(myParameter->arrivalPos) > lastLaneLength) {
1131 WRITE_WARNINGF(TL("Vehicle '%' will not be able to arrive at the given position!"), getID());
1132 }
1133 // Maybe we should warn the user about invalid inputs!
1134 myArrivalPos = MIN2(myParameter->arrivalPos, lastLaneLength);
1135 if (myArrivalPos < 0) {
1136 myArrivalPos = MAX2(myArrivalPos + lastLaneLength, 0.);
1137 }
1138 break;
1140 myArrivalPos = RandHelper::rand(lastLaneLength);
1141 break;
1143 myArrivalPos = lastLaneLength / 2.;
1144 break;
1145 default:
1146 myArrivalPos = lastLaneLength;
1147 break;
1148 }
1150 if (myParameter->arrivalLane >= (int)lanes.size() || !lanes[myParameter->arrivalLane]->allowsVehicleClass(myType->getVehicleClass())) {
1151 WRITE_WARNINGF(TL("Vehicle '%' will not be able to arrive at the given lane '%_%'!"), getID(), arrivalEdge->getID(), toString(myParameter->arrivalLane));
1152 }
1153 myArrivalLane = MIN2(myParameter->arrivalLane, (int)(lanes.size() - 1));
1155 myArrivalLane = -1;
1156 for (MSLane* lane : lanes) {
1157 if (lane->allowsVehicleClass(myType->getVehicleClass())) {
1158 myArrivalLane = lane->getIndex();
1159 break;
1160 }
1161 }
1162 if (myArrivalLane == -1) {
1163 WRITE_WARNINGF(TL("Vehicle '%' has no usable arrivalLane on edge '%'."), getID(), arrivalEdge->getID());
1164 myArrivalLane = 0;
1165 }
1167 // pick random lane among all usable lanes
1168 std::vector<MSLane*> usable;
1169 for (MSLane* lane : lanes) {
1170 if (lane->allowsVehicleClass(myType->getVehicleClass())) {
1171 usable.push_back(lane);
1172 }
1173 }
1174 if (usable.empty()) {
1175 WRITE_WARNINGF(TL("Vehicle '%' has no usable arrivalLane on edge '%'."), getID(), arrivalEdge->getID());
1176 myArrivalLane = 0;
1177 } else {
1178 myArrivalLane = usable[RandHelper::rand(0, (int)usable.size())]->getIndex();
1179 }
1180 }
1182 for (std::vector<MSLane*>::const_iterator l = lanes.begin(); l != lanes.end(); ++l) {
1183 if (myParameter->arrivalSpeed <= (*l)->getVehicleMaxSpeed(this)) {
1184 return;
1185 }
1186 }
1187 WRITE_WARNINGF(TL("Vehicle '%' will not be able to arrive with the given speed!"), getID());
1188 }
1189}
1190
1191void
1195 const int routeEdges = (int)myRoute->getEdges().size();
1197 // write specific edge in vehroute output for reproducibility
1198 pars->departEdge = RandHelper::rand(0, routeEdges);
1200 }
1201 assert(pars->departEdge >= 0);
1202 if (pars->departEdge >= routeEdges) {
1203 WRITE_WARNINGF(TL("Ignoring departEdge % for vehicle '%' with % route edges"), toString(pars->departEdge), getID(), toString(routeEdges));
1204 } else {
1205 myCurrEdge = myRoute->begin() + pars->departEdge;
1206 }
1207 }
1209 const int routeEdges = (int)myRoute->getEdges().size();
1210 const int begin = (int)(myCurrEdge - myRoute->begin());
1211 // write specific edge in vehroute output for reproducibility
1212 pars->arrivalEdge = RandHelper::rand(begin, routeEdges);
1214 assert(pars->arrivalEdge >= begin);
1215 assert(pars->arrivalEdge < routeEdges);
1216 }
1217}
1218
1219int
1223
1224int
1228 } else {
1230 }
1231}
1232
1233double
1235 return MAX2(0., MIN2(1., getVehicleType().getImpatience()
1236 + (hasInfluencer() ? getBaseInfluencer()->getExtraImpatience() : 0)
1238}
1239
1240
1241MSDevice*
1242MSBaseVehicle::getDevice(const std::type_info& type) const {
1243 for (MSVehicleDevice* const dev : myDevices) {
1244 if (typeid(*dev) == type) {
1245 return dev;
1246 }
1247 }
1248 return nullptr;
1249}
1250
1251
1252void
1254 // the parameters may hold the name of a vTypeDistribution but we are interested in the actual type
1255 const std::string& typeID = myParameter->vtypeid != getVehicleType().getID() ? getVehicleType().getID() : "";
1257 // params and stops must be written in child classes since they may wish to add additional attributes first
1258 out.writeAttr(SUMO_ATTR_ROUTE, myRoute->getID());
1259 std::ostringstream os;
1260 os << myOdometer << " " << myNumberReroutes;
1261 out.writeAttr(SUMO_ATTR_DISTANCE, os.str());
1264 }
1266 const int precision = out.getPrecision();
1267 out.setPrecision(MAX2(gPrecisionRandom, precision));
1269 out.setPrecision(precision);
1270 }
1272 out.writeAttr(SUMO_ATTR_REROUTE, true);
1273 }
1275 // could be set from stop
1277 }
1278 // here starts the vehicle internal part (see loading)
1279 // @note: remember to close the vehicle tag when calling this in a subclass!
1280}
1281
1282
1283bool
1284MSBaseVehicle::handleCollisionStop(MSStop& stop, const double distToStop) {
1285 UNUSED_PARAMETER(stop);
1286 UNUSED_PARAMETER(distToStop);
1287 return true;
1288}
1289
1290
1291bool
1293 return !myStops.empty() && myStops.begin()->reached /*&& myState.mySpeed < SUMO_const_haltingSpeed @todo #1864#*/;
1294}
1295
1296
1297bool
1299 return (isStopped() && (myStops.begin()->pars.parking == ParkingType::OFFROAD)
1300 && (myStops.begin()->parkingarea == nullptr || !myStops.begin()->parkingarea->parkOnRoad())
1301 && (myStops.begin()->getSpeed() == 0 || getSpeed() < SUMO_const_haltingSpeed));
1302}
1303
1304
1305bool
1307 return myPastStops.size() > 0 && myPastStops.back().jump >= 0 && getEdge()->getID() == myPastStops.back().edge && myPastStops.back().ended == SIMSTEP;
1308}
1309
1310
1311bool
1313 return isStopped() && (myStops.begin()->triggered || myStops.begin()->containerTriggered || myStops.begin()->joinTriggered);
1314}
1315
1316
1317bool
1319 return isStopped() && (myStops.begin()->pars.parking == ParkingType::OFFROAD);
1320}
1321
1322
1323bool
1324MSBaseVehicle::isStoppedInRange(const double pos, const double tolerance, bool checkFuture) const {
1325 if (isStopped() || (checkFuture && hasStops())) {
1326 const MSStop& stop = myStops.front();
1327 return stop.pars.startPos - tolerance <= pos && stop.pars.endPos + tolerance >= pos;
1328 }
1329 return false;
1330}
1331
1332bool
1333MSBaseVehicle::replaceParkingArea(MSParkingArea* parkingArea, std::string& errorMsg) {
1334 // Check if there is a parking area to be replaced
1335 if (parkingArea == 0) {
1336 errorMsg = "new parkingArea is NULL";
1337 return false;
1338 }
1339 if (myStops.size() == 0) {
1340 errorMsg = "vehicle has no stops";
1341 return false;
1342 }
1343 if (myStops.front().parkingarea == 0) {
1344 errorMsg = "first stop is not at parkingArea";
1345 return false;
1346 }
1347 MSStop& first = myStops.front();
1348 SUMOVehicleParameter::Stop& stopPar = const_cast<SUMOVehicleParameter::Stop&>(first.pars);
1349 std::string oldStopEdgeID = first.lane->getEdge().getID();
1350 // merge subsequent duplicate stops equals to parking area
1351 for (std::list<MSStop>::iterator iter = ++myStops.begin(); iter != myStops.end();) {
1352 if (iter->parkingarea == parkingArea) {
1353 stopPar.duration += iter->duration;
1354 myStops.erase(iter++);
1355 } else {
1356 break;
1357 }
1358 }
1359 stopPar.lane = parkingArea->getLane().getID();
1360 stopPar.parkingarea = parkingArea->getID();
1361 stopPar.startPos = parkingArea->getBeginLanePosition();
1362 stopPar.endPos = parkingArea->getEndLanePosition();
1363 stopPar.index = STOP_INDEX_FIT;
1364 first.edge = myRoute->end(); // will be patched in replaceRoute
1365 first.lane = &parkingArea->getLane();
1366 first.parkingarea = parkingArea;
1367
1368 // patch via edges
1369 std::string newStopEdgeID = parkingArea->getLane().getEdge().getID();
1370 if (myParameter->via.size() > 0 && myParameter->via.front() != newStopEdgeID) {
1371 if (myParameter->via.front() == oldStopEdgeID) {
1372 myParameter->via.erase(myParameter->via.begin());
1373 }
1374 myParameter->via.insert(myParameter->via.begin(), newStopEdgeID);
1375 }
1376 return true;
1377}
1378
1379
1382 MSParkingArea* nextParkingArea = nullptr;
1383 if (!myStops.empty()) {
1385 MSStop stop = myStops.front();
1386 if (!stop.reached && stop.parkingarea != nullptr) {
1387 nextParkingArea = stop.parkingarea;
1388 }
1389 }
1390 return nextParkingArea;
1391}
1392
1393
1396 MSParkingArea* currentParkingArea = nullptr;
1397 if (isParking()) {
1398 currentParkingArea = myStops.begin()->parkingarea;
1399 }
1400 return currentParkingArea;
1401}
1402
1403
1404const std::vector<std::string>&
1407 return myParameter->parkingBadges;
1408 } else {
1410 }
1411}
1412
1413
1414double
1415MSBaseVehicle::basePos(const MSEdge* edge) const {
1416 double result = MIN2(getVehicleType().getLength() + POSITION_EPS, edge->getLength());
1417 if (hasStops()
1418 && myStops.front().edge == myRoute->begin()
1419 && (&myStops.front().lane->getEdge()) == *myStops.front().edge) {
1420 result = MIN2(result, MAX2(0.0, myStops.front().getEndPos(*this)));
1421 }
1422 return result;
1423}
1424
1425
1426MSLane*
1428 const std::string edgeID = SUMOXMLDefinitions::getEdgeIDFromLane(stop.lane);
1429 const MSEdge* edge = MSEdge::dictionary(edgeID);
1430 if (edge == nullptr || edge->getOppositeEdge() == nullptr || stop.lane.find("_") == std::string::npos) {
1431 return nullptr;
1432 }
1433 const int laneIndex = SUMOXMLDefinitions::getIndexFromLane(stop.lane);
1434 if (laneIndex < (edge->getNumLanes() + edge->getOppositeEdge()->getNumLanes())) {
1435 const int oppositeIndex = edge->getOppositeEdge()->getNumLanes() + edge->getNumLanes() - 1 - laneIndex;
1436 stop.edge = edgeID;
1437 return edge->getOppositeEdge()->getLanes()[oppositeIndex];
1438 }
1439 return nullptr;
1440}
1441
1442
1443bool
1444MSBaseVehicle::addStop(const SUMOVehicleParameter::Stop& stopPar, std::string& errorMsg, SUMOTime untilOffset,
1445 MSRouteIterator* searchStart) {
1446 MSStop stop(stopPar);
1447 if (stopPar.lane == "") {
1448 MSEdge* e = MSEdge::dictionary(stopPar.edge);
1450 if (stop.lane == nullptr) {
1451 errorMsg = "Vehicle '" + myParameter->id + "' is not allowed to stop on any lane of edge '" + stopPar.edge + "'.";
1452 return false;
1453 }
1454 } else {
1455 stop.lane = MSLane::dictionary(stopPar.lane);
1456 if (stop.lane == nullptr) {
1457 // must be an opposite stop
1458 SUMOVehicleParameter::Stop tmp = stopPar;
1459 stop.lane = interpretOppositeStop(tmp);
1460 assert(stop.lane != nullptr);
1461 }
1463 errorMsg = "Vehicle '" + myParameter->id + "' is not allowed to stop on lane '" + stopPar.lane + "'.";
1464 return false;
1465 }
1466 }
1468 stop.segment = MSGlobals::gMesoNet->getSegmentForEdge(stop.lane->getEdge(), stop.getEndPos(*this));
1469 if (stop.lane->isInternal()) {
1470 errorMsg = "Mesoscopic simulation does not allow stopping on internal edge '" + stopPar.edge + "' for vehicle '" + myParameter->id + "'.";
1471 return false;
1472 }
1473 }
1474 stop.initPars(stopPar);
1475 if (stopPar.until != -1) {
1476 // !!! it would be much cleaner to invent a constructor for stops which takes "until" as an argument
1477 const_cast<SUMOVehicleParameter::Stop&>(stop.pars).until += untilOffset;
1478 }
1479 if (stopPar.arrival != -1) {
1480 const_cast<SUMOVehicleParameter::Stop&>(stop.pars).arrival += untilOffset;
1481 }
1482 std::string stopType = "stop";
1483 std::string stopID = "";
1484 double parkingLength = stop.pars.endPos - stop.pars.startPos;
1485 if (stop.busstop != nullptr) {
1486 stopType = "busStop";
1487 stopID = stop.busstop->getID();
1488 parkingLength = stop.busstop->getParkingLength();
1489 } else if (stop.containerstop != nullptr) {
1490 stopType = "containerStop";
1491 stopID = stop.containerstop->getID();
1492 parkingLength = stop.containerstop->getParkingLength();
1493 } else if (stop.chargingStation != nullptr) {
1494 stopType = "chargingStation";
1495 stopID = stop.chargingStation->getID();
1496 parkingLength = stop.chargingStation->getParkingLength();
1497 } else if (stop.overheadWireSegment != nullptr) {
1498 stopType = "overheadWireSegment";
1499 stopID = stop.overheadWireSegment->getID();
1500 parkingLength = stop.overheadWireSegment->getParkingLength();
1501 } else if (stop.parkingarea != nullptr) {
1502 stopType = "parkingArea";
1503 stopID = stop.parkingarea->getID();
1504 }
1505 const std::string errorMsgStart = stopID == "" ? stopType : stopType + " '" + stopID + "'";
1506
1507 if (stop.pars.startPos < 0 || stop.pars.endPos > stop.lane->getLength()) {
1508 errorMsg = errorMsgStart + " for vehicle '" + myParameter->id + "' on lane '" + stop.lane->getID() + "' has an invalid position.";
1509 return false;
1510 }
1511 if (stopType != "stop" && stopType != "parkingArea" && myType->getLength() / 2. > parkingLength
1512 // do not warn for stops that fill the whole lane
1513 && parkingLength < stop.lane->getLength()
1514 // do not warn twice for the same stop
1515 && MSNet::getInstance()->warnOnce(stopType + ":" + stopID)) {
1516 errorMsg = errorMsgStart + " on lane '" + stop.lane->getID() + "' is too short for vehicle '" + myParameter->id + "'.";
1517 }
1518 if (stopType == "parkingArea" && !stop.parkingarea->accepts(this)) {
1519 // forbid access in case the parking requests other badges
1520 errorMsg = errorMsgStart + "on lane '" + stop.lane->getID() + "' forbids access because vehicle '" + myParameter->id + "' does not provide any valid badge.";
1521 return false;
1522 }
1523 const MSEdge* stopLaneEdge = &stop.lane->getEdge();
1524 const MSEdge* stopEdge;
1525 if (stopLaneEdge->getOppositeEdge() != nullptr && stopLaneEdge->getOppositeEdge()->getID() == stopPar.edge) {
1526 // stop lane is on the opposite side
1527 stopEdge = stopLaneEdge->getOppositeEdge();
1528 stop.isOpposite = true;
1529 } else {
1530 // if stop is on an internal edge the normal edge before the intersection is used
1531 stopEdge = stopLaneEdge->getNormalBefore();
1532 }
1533 MSRouteIterator succ = myCurrEdge + 1; // we're using the address but only within the scope of this function (and recursive calls)
1534 if (searchStart == nullptr) {
1535 searchStart = &myCurrEdge;
1536 if (stopLaneEdge->isNormal() && getLane() != nullptr && getLane()->isInternal()) {
1537 // already on the intersection but myCurrEdge is before it
1538 searchStart = &succ;
1539 }
1540 }
1541#ifdef DEBUG_ADD_STOP
1542 if (DEBUG_COND) {
1543 std::cout << "addStop desc=" << stop.getDescription() << " stopEdge=" << stopEdge->getID()
1544 << " searchStart=" << ((*searchStart) == myRoute->end() ? "END" : (**searchStart)->getID())
1545 << " index=" << (int)((*searchStart) - myRoute->begin()) << " route=" << toString(myRoute->getEdges())
1546 << " stopParIndex=" << stopPar.index
1547 << "\n";
1548 }
1549#endif
1550 stop.edge = std::find(*searchStart, myRoute->end(), stopEdge);
1551 MSRouteIterator prevStopEdge = myCurrEdge;
1552 const MSEdge* prevEdge = (getLane() == nullptr ? getEdge() : &getLane()->getEdge());
1553 double prevStopPos = getPositionOnLane();
1554 // where to insert the stop
1555 std::list<MSStop>::iterator iter = myStops.begin();
1556 if (stopPar.index == STOP_INDEX_END || stopPar.index >= static_cast<int>(myStops.size()) || stopPar.index == STOP_INDEX_REPEAT) {
1557 iter = myStops.end();
1558 if (myStops.size() > 0 && myStops.back().edge >= *searchStart) {
1559 prevStopEdge = myStops.back().edge;
1560 prevEdge = &myStops.back().lane->getEdge();
1561 prevStopPos = myStops.back().pars.endPos;
1562 stop.edge = std::find(prevStopEdge, myRoute->end(), stopEdge);
1563 if (prevStopEdge == stop.edge // laneEdge check is insufficient for looped routes
1564 && prevEdge == &stop.lane->getEdge() // route iterator check insufficient for internal lane stops
1565 && (prevStopPos > stop.pars.endPos ||
1566 (prevStopPos == stop.pars.endPos && stopPar.index == STOP_INDEX_REPEAT))) {
1567 stop.edge = std::find(prevStopEdge + 1, myRoute->end(), stopEdge);
1568 }
1569#ifdef DEBUG_ADD_STOP
1570 if (DEBUG_COND) {
1571 std::cout << " (@end) prevStopEdge=" << (*prevStopEdge)->getID() << " prevStopPos=" << prevStopPos << " index=" << (int)(prevStopEdge - myRoute->begin())
1572 << " foundIndex=" << (stop.edge == myRoute->end() ? -1 : (int)(stop.edge - myRoute->begin())) << "\n";
1573 }
1574#endif
1575 }
1576 // skip a number of occurences of stopEdge in looped route
1577 int skipLooped = stopPar.index - static_cast<int>(myStops.size());
1578 for (int j = 0; j < skipLooped; j++) {
1579 auto nextIt = std::find(stop.edge + 1, myRoute->end(), stopEdge);
1580 if (nextIt == myRoute->end()) {
1581 if (std::find(myRoute->begin(), stop.edge, stopEdge) != stop.edge) {
1582 // only warn if the route loops over the stop edge at least once
1583 errorMsg = errorMsgStart + " for vehicle '" + myParameter->id + "' could not skip " + toString(skipLooped) + " occurences of stop edge '" + stopEdge->getID() + "' in looped route.";
1584 }
1585 break;
1586 } else {
1587 stop.edge = nextIt;
1588 }
1589 }
1590 } else {
1591 if (stopPar.index == STOP_INDEX_FIT) {
1592 while (iter != myStops.end() && (iter->edge < stop.edge ||
1593 (iter->pars.endPos < stop.pars.endPos && iter->edge == stop.edge) ||
1594 (stop.lane->getEdge().isInternal() && iter->edge == stop.edge))) {
1595 prevStopEdge = iter->edge;
1596 prevStopPos = iter->pars.endPos;
1597 ++iter;
1598 }
1599 } else {
1600 int index = stopPar.index;
1601 while (index > 0) {
1602 prevStopEdge = iter->edge;
1603 prevStopPos = iter->pars.endPos;
1604 ++iter;
1605 --index;
1606 }
1607#ifdef DEBUG_ADD_STOP
1608 if (DEBUG_COND) {
1609 std::cout << " (@fit) prevStopEdge=" << (*prevStopEdge)->getID() << " index=" << (int)(prevStopEdge - myRoute->begin()) << "\n";
1610 }
1611#endif
1612 stop.edge = std::find(prevStopEdge, myRoute->end(), stopEdge);
1613 }
1614 }
1615 const bool wasTooClose = errorMsg != "" && errorMsg.find("too close") != std::string::npos;
1616 if (stop.edge == myRoute->end()) {
1617 if (!wasTooClose) {
1618 errorMsg = errorMsgStart + " for vehicle '" + myParameter->id + "' on lane '" + stop.lane->getID() + "' is not downstream the current route.";
1619 }
1620 return false;
1621 }
1622
1623 const bool tooClose = (prevStopEdge == stop.edge && prevEdge == &stop.lane->getEdge() &&
1624 prevStopPos + (iter == myStops.begin() && !instantStopping() ? getBrakeGap() : 0) > stop.pars.endPos + POSITION_EPS);
1625
1626 if (prevStopEdge > stop.edge ||
1627 // a collision-stop happens after vehicle movement and may move the
1628 // vehicle backwards on its lane (prevStopPos is the vehicle position)
1629 (tooClose && !stop.pars.collision)
1630 || (stop.lane->getEdge().isInternal() && stop.lane->getNextNormal() != *(stop.edge + 1))) {
1631 // check if the edge occurs again later in the route
1632 //std::cout << " could not add stop " << errorMsgStart << " prevStops=" << myStops.size() << " searchStart=" << (*searchStart - myRoute->begin()) << " route=" << toString(myRoute->getEdges()) << "\n";
1633 if (tooClose && prevStopPos <= stop.pars.endPos + POSITION_EPS) {
1634 errorMsg = errorMsgStart + " for vehicle '" + myParameter->id + "' on lane '" + stop.pars.lane + "' is too close to brake.";
1635 }
1636 MSRouteIterator next = stop.edge + 1;
1637 return addStop(stopPar, errorMsg, untilOffset, &next);
1638 }
1639 // David.C:
1640 //if (!stop.parking && (myCurrEdge == stop.edge && myState.myPos > stop.endPos - getCarFollowModel().brakeGap(myState.mySpeed))) {
1641 const double endPosOffset = stop.lane->getEdge().isInternal() ? (*stop.edge)->getLength() : 0;
1642 const double distToStop = stop.pars.endPos + endPosOffset - getPositionOnLane();
1643 if (stop.pars.collision && !handleCollisionStop(stop, distToStop)) {
1644 return false;
1645 }
1646 if (!hasDeparted() && myCurrEdge == stop.edge) {
1647 double pos = -1;
1649 pos = myParameter->departPos;
1650 if (pos < 0.) {
1651 pos += (*myCurrEdge)->getLength();
1652 }
1653 }
1655 pos = MIN2(stop.pars.endPos + endPosOffset, basePos(*myCurrEdge));
1656 }
1657 if (pos > stop.pars.endPos + endPosOffset) {
1658 if (stop.edge != myRoute->end()) {
1659 // check if the edge occurs again later in the route
1660 MSRouteIterator next = stop.edge + 1;
1661 return addStop(stopPar, errorMsg, untilOffset, &next);
1662 }
1663 errorMsg = errorMsgStart + " for vehicle '" + myParameter->id + "' on lane '" + stop.lane->getID() + "' is before departPos.";
1664 return false;
1665 }
1666 }
1667 if (iter != myStops.begin()) {
1668 std::list<MSStop>::iterator iter2 = iter;
1669 iter2--;
1670 if (stop.getUntil() >= 0 && iter2->getUntil() > stop.getUntil()
1671 && (!MSGlobals::gUseStopEnded || iter2->pars.ended < 0 || stop.pars.ended >= 0)) {
1672 errorMsg = errorMsgStart + " for vehicle '" + myParameter->id + "' on lane '" + stop.lane->getID()
1673 + "' set to end at " + time2string(stop.getUntil())
1674 + " earlier than previous stop at " + time2string(iter2->getUntil()) + ".";
1675 }
1676 if (stop.pars.arrival >= 0 && iter2->pars.arrival > stop.pars.arrival) {
1677 errorMsg = errorMsgStart + " for vehicle '" + myParameter->id + "' on lane '" + stop.lane->getID()
1678 + "' set to start at " + time2string(stop.pars.arrival)
1679 + " earlier than previous stop end at " + time2string(iter2->getUntil()) + ".";
1680 }
1681 if (stop.pars.arrival >= 0 && iter2->pars.arrival > stop.pars.arrival) {
1682 errorMsg = errorMsgStart + " for vehicle '" + myParameter->id + "' on lane '" + stop.lane->getID()
1683 + "' set to start at " + time2string(stop.pars.arrival)
1684 + " earlier than previous stop arrival at " + time2string(iter2->pars.arrival) + ".";
1685 }
1686 } else {
1687 if (stop.getUntil() >= 0 && getParameter().depart > stop.getUntil()
1688 && (!MSGlobals::gUseStopEnded || stop.pars.ended < 0)) {
1689 errorMsg = errorMsgStart + " for vehicle '" + myParameter->id + "' on lane '" + stop.lane->getID()
1690 + "' set to end at " + time2string(stop.getUntil())
1691 + " earlier than departure at " + time2string(getParameter().depart) + ".";
1692 }
1693 }
1694 if (stop.getUntil() >= 0 && stop.getArrival() > stop.getUntil() && errorMsg == "") {
1695 errorMsg = errorMsgStart + " for vehicle '" + myParameter->id + "' on lane '" + stop.lane->getID()
1696 + "' set to end at " + time2string(stop.getUntil())
1697 + " earlier than arrival at " + time2string(stop.getArrival()) + ".";
1698 }
1699 setSkips(stop, (int)myStops.size());
1700 myStops.insert(iter, stop);
1701 if (stopPar.tripId != "") {
1703 }
1704#ifdef DEBUG_ADD_STOP
1705 if (DEBUG_COND) {
1706 std::cout << " added stop " << errorMsgStart << " totalStops=" << myStops.size()
1707 << " routeIndex=" << (stop.edge - myRoute->begin())
1708 << " stopIndex=" << std::distance(myStops.begin(), iter)
1709 //<< " searchStart=" << (*searchStart - myRoute->begin())
1710 //<< " route=" << toString(myRoute->getEdges())
1711 << "\n";
1712 }
1713#endif
1714 return true;
1715}
1716
1717
1718void
1719MSBaseVehicle::setSkips(MSStop& stop, int prevActiveStops) {
1720 if (hasDeparted() && stop.edge > myRoute->begin()) {
1721 // if the route is looped we must patch the index to ensure that state
1722 // loading (and vehroute-output) encode the correct number of skips
1723 stop.skips.clear();
1724 MSRouteIterator itPrev;
1725 double prevEndPos;
1726 if (prevActiveStops > 0) {
1727 assert((int)myStops.size() >= prevActiveStops);
1728 auto prevStopIt = myStops.begin();
1729 std::advance(prevStopIt, prevActiveStops - 1);
1730 const MSStop& prev = *prevStopIt;
1731 itPrev = prev.edge;
1732 prevEndPos = prev.pars.endPos;
1733 } else if (myPastStops.size() > 0) {
1734 itPrev = myRoute->begin() + myPastStops.back().routeIndex;
1735 prevEndPos = myPastStops.back().endPos;
1736 } else {
1737 itPrev = myRoute->begin() + myParameter->departEdge;
1738 prevEndPos = myDepartPos;
1739 }
1740 //auto itPrevOrig = itPrev;
1741 if (*itPrev == *stop.edge && prevEndPos > stop.pars.endPos) {
1742 itPrev++;
1743 }
1744 //std::cout << SIMTIME << " veh=" << getID() << " prevActive=" << prevActiveStops << " edge=" << (*stop.edge)->getID() << " routeIndex=" << (stop.edge - myRoute->begin()) << " prevIndex=" << (itPrev - myRoute->begin()) << "\n";
1745 while (itPrev < stop.edge) {
1746 if (*itPrev == *stop.edge) {
1747 stop.skips.push_back((int)(itPrev - myRoute->begin()));
1748 }
1749 itPrev++;
1750 }
1751 int newIndex = STOP_INDEX_END;
1752 if (!stop.skips.empty()) {
1753 //if (getID() == "77_0_0") {
1754 // std::cout << SIMTIME << " veh=" << getID() << " past=" << myPastStops.size() << " prevActive=" << prevActiveStops
1755 // << " edge=" << (*stop.edge)->getID() << " routeIndex=" << (stop.edge - myRoute->begin())
1756 // << " prevEdge=" << (*itPrevOrig)->getID()
1757 // << " prevIndex=" << (itPrevOrig - myRoute->begin())
1758 // << " skips=" << foundSkips << "\n";
1759 //}
1760 newIndex = (int)myPastStops.size() + prevActiveStops + (int)stop.skips.size();
1761 }
1762 const_cast<SUMOVehicleParameter::Stop&>(stop.pars).index = newIndex;
1763 }
1764}
1765
1766
1769 for (int i = 0; i < (int)myMoveReminders.size();) {
1770 auto rem = &myMoveReminders[i];
1771 if (rem->first->notifyReroute(*this)) {
1772#ifdef _DEBUG
1773 if (myTraceMoveReminders) {
1774 traceMoveReminder("notifyReroute", rem->first, rem->second, true);
1775 }
1776#endif
1777 ++i;
1778 } else {
1779#ifdef _DEBUG
1780 if (myTraceMoveReminders) {
1781 traceMoveReminder("notifyReroute", rem->first, rem->second, false);
1782 }
1783#endif
1784 myMoveReminders.erase(myMoveReminders.begin() + i);
1785 }
1786 }
1788 // event only called once
1789 return 0;
1790}
1791
1792
1793void
1794MSBaseVehicle::addStops(const bool ignoreStopErrors, MSRouteIterator* searchStart, bool addRouteStops) {
1795 if (addRouteStops) {
1796 for (const SUMOVehicleParameter::Stop& stop : myRoute->getStops()) {
1797 std::string errorMsg;
1798 if (!addStop(stop, errorMsg, myParameter->depart, searchStart) && !ignoreStopErrors) {
1799 throw ProcessError(errorMsg);
1800 }
1801 if (errorMsg != "") {
1802 WRITE_WARNING(errorMsg);
1803 }
1804 }
1805 }
1807 for (const SUMOVehicleParameter::Stop& stop : myParameter->stops) {
1808 std::string errorMsg;
1809 if (!addStop(stop, errorMsg, untilOffset, searchStart) && !ignoreStopErrors) {
1810 throw ProcessError(errorMsg);
1811 }
1812 if (errorMsg != "") {
1813 WRITE_WARNING(errorMsg);
1814 }
1815 }
1816}
1817
1818
1819bool
1822 int i = 0;
1823 bool ok = true;
1824 for (const MSStop& stop : myStops) {
1825 MSRouteIterator it;
1826 if (stop.lane->isInternal()) {
1827 // find the normal predecessor and ensure that the next route edge
1828 // matches the successor of the internal edge successor
1829 it = std::find(start, myRoute->end(), stop.lane->getEdge().getNormalBefore());
1830 if (it != myRoute->end() && (
1831 it + 1 == myRoute->end() || *(it + 1) != stop.lane->getEdge().getNormalSuccessor())) {
1832 it = myRoute->end(); // signal failure
1833 }
1834 } else {
1835 it = std::find(start, myRoute->end(), &stop.lane->getEdge());
1836 }
1837 if (it == myRoute->end()) {
1838 if (!silent) {
1839 WRITE_ERRORF("Stop % on edge '%' is not found after edge '%' (% after current) for vehicle '%' at time=%.",
1840 i, stop.lane->getEdge().getID(), (*start)->getID(), toString(start - myCurrEdge), getID(), time2string(SIMSTEP));
1841 }
1842 ok = false;
1843 } else {
1844 MSRouteIterator it2;
1845 for (it2 = myRoute->begin(); it2 != myRoute->end(); it2++) {
1846 if (it2 == stop.edge) {
1847 break;
1848 }
1849 }
1850 if (it2 == myRoute->end()) {
1851 if (!silent) {
1852 WRITE_ERRORF("Stop % on edge '%' used invalid route index for vehicle '%' at time=%.",
1853 i, stop.lane->getEdge().getID(), getID(), time2string(SIMSTEP));
1854 }
1855 ok = false;
1856 } else if (it2 < start) {
1857 if (!silent) {
1858 WRITE_ERRORF("Stop % on edge '%' used invalid (relative) route index % expected after % for vehicle '%' at time=%.",
1859 i, stop.lane->getEdge().getID(), toString(it2 - myCurrEdge), toString(start - myCurrEdge), getID(), time2string(SIMSTEP));
1860 }
1861 ok = false;
1862 } else {
1863 start = stop.edge;
1864 }
1865 }
1866 i++;
1867 }
1868 return ok;
1869}
1870
1871
1872std::vector<MSBaseVehicle::StopEdgeInfo>
1873MSBaseVehicle::getStopEdges(double& firstPos, double& lastPos, std::set<int>& jumps) const {
1874 assert(haveValidStopEdges());
1875 std::vector<StopEdgeInfo> result;
1876 const MSStop* prev = nullptr;
1877 const MSEdge* internalSuccessor = nullptr;
1878 for (const MSStop& stop : myStops) {
1879 if (stop.reached) {
1880 if (stop.pars.jump >= 0) {
1881 jumps.insert((int)result.size());
1882 }
1883 continue;
1884 }
1885 double stopPos = stop.getEndPos(*this);
1886 if ((prev == nullptr
1887 || prev->edge != stop.edge
1888 || (prev->lane == stop.lane && prev->getEndPos(*this) > stopPos))
1889 && *stop.edge != internalSuccessor) {
1890 if (stop.lane->isInternal()) {
1891 stopPos = (*stop.edge)->getLength();
1892 }
1893 result.push_back(StopEdgeInfo(*stop.edge, stop.pars.priority, stop.getArrivalFallback(), stopPos));
1894 result.back().nameTag = stop.getStoppingPlaceName();
1895 result.back().stopPar = &stop.pars;
1896 if (stop.lane->isInternal()) {
1897 internalSuccessor = stop.lane->getNextNormal();
1898 result.push_back(StopEdgeInfo(internalSuccessor, stop.pars.priority, stop.getArrivalFallback(), 0));
1899 } else {
1900 internalSuccessor = nullptr;
1901 }
1902 } else if (prev != nullptr && prev->edge == stop.edge) {
1903 result.back().priority = addStopPriority(result.back().priority, stop.pars.priority);
1904 }
1905 prev = &stop;
1906 if (firstPos == INVALID_DOUBLE) {
1907 if (stop.parkingarea != nullptr) {
1908 firstPos = MAX2(0., stopPos);
1909 } else {
1910 firstPos = stopPos;
1911 }
1912 }
1913 lastPos = stopPos;
1914 if (stop.pars.jump >= 0) {
1915 jumps.insert((int)result.size() - 1);
1916 }
1917 }
1918 //std::cout << SIMTIME << " getStopEdges veh=" << getID() << "\n";
1919 //for (auto item : result) {
1920 // std::cout << " e=" << item.edge->getID() << " pos=" << item.pos << "\n";
1921 //}
1922 return result;
1923}
1924
1925
1926double
1927MSBaseVehicle::addStopPriority(double p1, double p2) {
1928 if (p1 < 0 || p2 < 0) {
1929 return p1;
1930 }
1931 return p1 + p2;
1932}
1933
1934std::vector<std::pair<int, double> >
1936 std::vector<std::pair<int, double> > result;
1937 for (std::list<MSStop>::const_iterator iter = myStops.begin(); iter != myStops.end(); ++iter) {
1938 result.push_back(std::make_pair(
1939 (int)(iter->edge - myRoute->begin()),
1940 iter->getEndPos(*this)));
1941 }
1942 return result;
1943}
1944
1945
1946const MSStop&
1948 assert(myStops.size() > 0);
1949 return myStops.front();
1950}
1951
1952MSStop&
1954 assert(myStops.size() > 0);
1955 return myStops.front();
1956}
1957
1960 if (isStopped()) {
1961 return myStops.front().duration;
1962 } else {
1963 return 0;
1964 }
1965}
1966
1967
1968MSStop&
1969MSBaseVehicle::getStop(int nextStopIndex) {
1970 if (nextStopIndex < 0 || (int)myStops.size() <= nextStopIndex) {
1971 throw InvalidArgument(TLF("Invalid stop index % (has % stops).", nextStopIndex, myStops.size()));
1972 }
1973 auto stopIt = myStops.begin();
1974 std::advance(stopIt, nextStopIndex);
1975 return *stopIt;
1976}
1977
1978
1981 if (hasStops()) {
1982 return &myStops.front().pars;
1983 }
1984 return nullptr;
1985}
1986
1987
1988bool
1990 //if the stop exists update the duration
1991 for (std::list<MSStop>::iterator iter = myStops.begin(); iter != myStops.end(); iter++) {
1992 if (iter->lane->getID() == stop.lane && fabs(iter->pars.endPos - stop.endPos) < POSITION_EPS) {
1993 // update existing stop
1994 if (stop.duration == 0 && stop.until < 0 && !iter->reached) {
1995 myStops.erase(iter);
1996 } else {
1997 iter->duration = stop.duration;
1998 iter->triggered = stop.triggered;
1999 iter->containerTriggered = stop.containerTriggered;
2000 const_cast<SUMOVehicleParameter::Stop&>(iter->pars).until = stop.until;
2001 const_cast<SUMOVehicleParameter::Stop&>(iter->pars).parking = stop.parking;
2002 }
2003 return true;
2004 }
2005 }
2006 const bool result = addStop(stop, errorMsg);
2007 if (result) {
2009 myParameter->stops.push_back(stop);
2010 }
2011 return result;
2012}
2013
2014
2015void
2022
2023
2024bool
2026 if (hasStops() && nextStopIndex < (int)myStops.size()) {
2027 if (nextStopIndex == 0 && isStopped()) {
2029 } else {
2030 auto stopIt = myStops.begin();
2031 std::advance(stopIt, nextStopIndex);
2032 if (stopIt->parkingarea != nullptr && stopIt->parkingarea->isReservable()) {
2033 stopIt->parkingarea->removeSpaceReservation(this);
2034 }
2035 myStops.erase(stopIt);
2036 }
2037 if (!hasDeparted() && (int)myParameter->stops.size() > nextStopIndex) {
2038 // stops will be rebuilt from scratch on rerouting so we must patch the stops in myParameter
2039 auto stopIt2 = myParameter->stops.begin();
2040 std::advance(stopIt2, nextStopIndex);
2041 const_cast<SUMOVehicleParameter*>(myParameter)->stops.erase(stopIt2);
2042 }
2043 return true;
2044 } else {
2045 return false;
2046 }
2047}
2048
2049
2050bool
2051MSBaseVehicle::replaceStop(int nextStopIndex, SUMOVehicleParameter::Stop stop, const std::string& info, bool teleport, std::string& errorMsg) {
2052 const int n = (int)myStops.size();
2053 if (nextStopIndex < 0 || nextStopIndex >= n) {
2054 errorMsg = TLF("invalid nextStopIndex % for % remaining stops", nextStopIndex, n);
2055 return false;
2056 }
2057 if (nextStopIndex == 0 && isStopped()) {
2058 errorMsg = TL("cannot replace reached stop");
2059 return false;
2060 }
2062 MSLane* stopLane = MSLane::dictionary(stop.lane);
2063 MSEdge* stopEdge = &stopLane->getEdge();
2064
2065 auto itStop = myStops.begin();
2066 std::advance(itStop, nextStopIndex);
2067 MSStop& replacedStop = *itStop;
2068
2069 // check parking access rights
2070 if (stop.parkingarea != "") {
2072 if (pa != nullptr && !pa->accepts(this)) {
2073 errorMsg = TLF("vehicle '%' does not have the right badge to access parkingArea '%'", getID(), stop.parkingarea);
2074 return false;
2075 }
2076 }
2077
2078 if (replacedStop.lane == stopLane && replacedStop.pars.endPos == stop.endPos && !teleport) {
2079 // only replace stop attributes
2080 const_cast<SUMOVehicleParameter::Stop&>(replacedStop.pars) = stop;
2081 replacedStop.initPars(stop);
2082 return true;
2083 }
2084
2085 if (!stopLane->allowsVehicleClass(getVClass(), myRoutingMode)) {
2086 errorMsg = TLF("disallowed stop lane '%'", stopLane->getID());
2087 return false;
2088 }
2089
2090 const ConstMSEdgeVector& oldEdges = getRoute().getEdges();
2091 std::vector<MSStop> stops(myStops.begin(), myStops.end());
2092 const int junctionOffset = getLane() != nullptr && getLane()->isInternal() ? 1 : 0;
2093 MSRouteIterator itStart = nextStopIndex == 0 ? getCurrentRouteEdge() + junctionOffset : stops[nextStopIndex - 1].edge;
2094 double startPos = nextStopIndex == 0 ? getPositionOnLane() : stops[nextStopIndex - 1].pars.endPos;
2095 MSRouteIterator itEnd = nextStopIndex == n - 1 ? oldEdges.end() - 1 : stops[nextStopIndex + 1].edge;
2096 auto endPos = nextStopIndex == n - 1 ? getArrivalPos() : stops[nextStopIndex + 1].pars.endPos;
2098
2099 bool newDestination = nextStopIndex == n - 1 && stops[nextStopIndex].edge == oldEdges.end() - 1;
2100
2101 ConstMSEdgeVector toNewStop;
2102 if (!teleport) {
2103 router.compute(*itStart, startPos, stopEdge, stop.endPos, this, t, toNewStop, true);
2104 if (toNewStop.size() == 0) {
2105 errorMsg = TLF("no route found from edge '%' to stop edge '%'", (*itStart)->getID(), stopEdge->getID());
2106 return false;
2107 }
2108 }
2109
2110 ConstMSEdgeVector fromNewStop;
2111 if (!newDestination) {
2112 router.compute(stopEdge, stop.endPos, *itEnd, endPos, this, t, fromNewStop, true);
2113 if (fromNewStop.size() == 0) {
2114 errorMsg = TLF("no route found from stop edge '%' to edge '%'", stopEdge->getID(), (*itEnd)->getID());
2115 return false;
2116 }
2117 }
2118
2120 const_cast<SUMOVehicleParameter::Stop&>(replacedStop.pars) = stop;
2121 replacedStop.initPars(stop);
2122 replacedStop.edge = myRoute->end(); // will be patched in replaceRoute
2123 replacedStop.lane = stopLane;
2125 replacedStop.segment = MSGlobals::gMesoNet->getSegmentForEdge(replacedStop.lane->getEdge(), replacedStop.getEndPos(*this));
2126 if (replacedStop.lane->isInternal()) {
2127 errorMsg = TLF("Mesoscopic simulation does not allow stopping on internal edge '%' for vehicle '%'.", stop.edge, getID());
2128 return false;
2129 }
2130 }
2131
2132 ConstMSEdgeVector oldRemainingEdges(myCurrEdge, getRoute().end());
2133 ConstMSEdgeVector newEdges; // only remaining
2134 newEdges.insert(newEdges.end(), myCurrEdge, itStart);
2135 if (!teleport) {
2136 newEdges.insert(newEdges.end(), toNewStop.begin(), toNewStop.end() - 1);
2137 } else {
2138 newEdges.push_back(*itStart);
2139 }
2140 if (!newDestination) {
2141 newEdges.insert(newEdges.end(), fromNewStop.begin(), fromNewStop.end() - 1);
2142 newEdges.insert(newEdges.end(), itEnd, oldEdges.end());
2143 } else {
2144 newEdges.push_back(stopEdge);
2145 }
2146 //std::cout << SIMTIME << " replaceStop veh=" << getID()
2147 // << " teleport=" << teleport
2148 // << " busStop=" << stop.busstop
2149 // << " oldEdges=" << oldRemainingEdges.size()
2150 // << " newEdges=" << newEdges.size()
2151 // << " toNewStop=" << toNewStop.size()
2152 // << " fromNewStop=" << fromNewStop.size()
2153 // << "\n";
2154
2155 const double routeCost = router.recomputeCosts(newEdges, this, t);
2156 const double previousCost = router.recomputeCosts(oldRemainingEdges, this, t);
2157 const double savings = previousCost - routeCost;
2158 if (!hasDeparted() && (int)myParameter->stops.size() > nextStopIndex) {
2159 // stops will be rebuilt from scratch so we must patch the stops in myParameter
2160 const_cast<SUMOVehicleParameter*>(myParameter)->stops[nextStopIndex] = stop;
2161 }
2162 if (teleport) {
2163 // let the vehicle jump rather than teleport
2164 // we add a jump-stop at the end of the edge (unless the vehicle is
2165 // already configure to jump before the replaced stop)
2166 if (!insertJump(nextStopIndex, itStart, errorMsg)) {
2167 return false;
2168 };
2169 }
2170 return replaceRouteEdges(newEdges, routeCost, savings, info, !hasDeparted(), false, false, &errorMsg);
2171}
2172
2173
2174bool
2175MSBaseVehicle::rerouteBetweenStops(int nextStopIndex, const std::string& info, bool teleport, std::string& errorMsg) {
2176 const int n = (int)myStops.size();
2177 if (nextStopIndex < 0 || nextStopIndex > n) {
2178 errorMsg = TLF("invalid nextStopIndex % for % remaining stops", nextStopIndex, n);
2179 return false;
2180 }
2181 if (nextStopIndex == 0 && isStopped()) {
2182 errorMsg = TL("cannot reroute towards reached stop");
2183 return false;
2184 }
2186
2187 const ConstMSEdgeVector& oldEdges = getRoute().getEdges();
2188 std::vector<MSStop> stops(myStops.begin(), myStops.end());
2189 const int junctionOffset = getLane() != nullptr && getLane()->isInternal() ? 1 : 0;
2190 MSRouteIterator itStart = nextStopIndex == 0 ? getCurrentRouteEdge() + junctionOffset : stops[nextStopIndex - 1].edge;
2191 double startPos = nextStopIndex == 0 ? getPositionOnLane() : stops[nextStopIndex - 1].pars.endPos;
2192 MSRouteIterator itEnd = nextStopIndex == n ? oldEdges.end() - 1 : stops[nextStopIndex].edge;
2193 auto endPos = nextStopIndex == n ? getArrivalPos() : stops[nextStopIndex].pars.endPos;
2195
2196 ConstMSEdgeVector newBetween;
2197 if (!teleport) {
2198 router.compute(*itStart, startPos, *itEnd, endPos, this, t, newBetween, true);
2199 if (newBetween.size() == 0) {
2200 errorMsg = TLF("no route found from edge '%' to stop edge '%'", (*itStart)->getID(), (*itEnd)->getID());
2201 return false;
2202 }
2203 }
2204
2205 ConstMSEdgeVector oldRemainingEdges(myCurrEdge, getRoute().end());
2206 ConstMSEdgeVector newEdges; // only remaining
2207 newEdges.insert(newEdges.end(), myCurrEdge, itStart);
2208 if (!teleport) {
2209 newEdges.insert(newEdges.end(), newBetween.begin(), newBetween.end() - 1);
2210 } else {
2211 newEdges.push_back(*itStart);
2212 }
2213 newEdges.insert(newEdges.end(), itEnd, oldEdges.end());
2214 //std::cout << SIMTIME << " rerouteBetweenStops veh=" << getID()
2215 // << " oldEdges=" << oldRemainingEdges.size()
2216 // << " newEdges=" << newEdges.size()
2217 // << " toNewStop=" << toNewStop.size()
2218 // << " fromNewStop=" << fromNewStop.size()
2219 // << "\n";
2220
2221 const double routeCost = router.recomputeCosts(newEdges, this, t);
2222 const double previousCost = router.recomputeCosts(oldRemainingEdges, this, t);
2223 const double savings = previousCost - routeCost;
2224
2225 if (teleport) {
2226 // let the vehicle jump rather than teleport
2227 // we add a jump-stop at the end of the edge (unless the vehicle is
2228 // already configure to jump before the replaced stop)
2229 if (!insertJump(nextStopIndex, itStart, errorMsg)) {
2230 return false;
2231 };
2232 }
2233 return replaceRouteEdges(newEdges, routeCost, savings, info, !hasDeparted(), false, false, &errorMsg);
2234}
2235
2236
2237bool
2238MSBaseVehicle::insertJump(int nextStopIndex, MSRouteIterator itStart, std::string& errorMsg) {
2239 bool needJump = true;
2240 if (nextStopIndex > 0) {
2241 auto itPriorStop = myStops.begin();
2242 std::advance(itPriorStop, nextStopIndex - 1);
2243 const MSStop& priorStop = *itPriorStop;
2244 if (priorStop.pars.jump >= 0) {
2245 needJump = false;
2246 }
2247 }
2248 if (needJump) {
2249 SUMOVehicleParameter::Stop jumpStopPars;
2250 jumpStopPars.endPos = (*itStart)->getLength();
2251 jumpStopPars.speed = 1000;
2252 jumpStopPars.jump = 0;
2253 jumpStopPars.edge = (*itStart)->getID();
2255 MSLane* jumpStopLane = nullptr;
2256 for (MSLane* cand : (*itStart)->getLanes()) {
2257 if (cand->allowsVehicleClass(getVClass())) {
2258 jumpStopLane = cand;
2259 break;
2260 }
2261 }
2262 if (jumpStopLane == nullptr) {
2263 errorMsg = TL("unable to replace stop with teleporting");
2264 return false;
2265 }
2266 auto itStop = myStops.begin();
2267 std::advance(itStop, nextStopIndex);
2268 MSStop jumpStop(jumpStopPars);
2269 jumpStop.initPars(jumpStopPars);
2270 jumpStop.lane = jumpStopLane;
2271 jumpStop.edge = myRoute->end(); // will be patched in replaceRoute
2272 myStops.insert(itStop, jumpStop);
2273 if (!hasDeparted() && (int)myParameter->stops.size() > nextStopIndex) {
2274 // stops will be rebuilt from scratch so we must patch the stops in myParameter
2275 auto it = myParameter->stops.begin() + nextStopIndex;
2276 const_cast<SUMOVehicleParameter*>(myParameter)->stops.insert(it, jumpStopPars);
2277 }
2278 }
2279 return true;
2280}
2281
2282
2283bool
2284MSBaseVehicle::insertStop(int nextStopIndex, SUMOVehicleParameter::Stop stop, const std::string& info, bool teleport, std::string& errorMsg) {
2285 const int n = (int)myStops.size();
2286 if (nextStopIndex < 0 || nextStopIndex > n) {
2287 errorMsg = TLF("invalid nextStopIndex % for % remaining stops", nextStopIndex, n);
2288 return false;
2289 }
2290 if (nextStopIndex == 0 && isStopped()) {
2291 errorMsg = TL("cannot insert stop before the currently reached stop");
2292 return false;
2293 }
2295 MSLane* stopLane = MSLane::dictionary(stop.lane);
2296 MSEdge* stopEdge = &stopLane->getEdge();
2297
2298 if (!stopLane->allowsVehicleClass(getVClass(), myRoutingMode)) {
2299 errorMsg = TLF("disallowed stop lane '%'", stopLane->getID());
2300 return false;
2301 }
2302
2303 // check parking access rights
2304 if (stop.parkingarea != "") {
2306 if (pa != nullptr && !pa->accepts(this)) {
2307 errorMsg = TLF("Vehicle '%' does not have the right badge to access parkingArea '%'.", getID(), stop.parkingarea);
2308 return false;
2309 }
2310 }
2311
2312 const ConstMSEdgeVector& oldEdges = getRoute().getEdges();
2313 std::vector<MSStop> stops(myStops.begin(), myStops.end());
2314 const int junctionOffset = ((getLane() != nullptr && getLane()->isInternal())
2315 || getRerouteOrigin() != getCurrentRouteEdge()) ? 1 : 0;
2316 MSRouteIterator itStart = nextStopIndex == 0 ? getCurrentRouteEdge() + junctionOffset : stops[nextStopIndex - 1].edge;
2317 double startPos = nextStopIndex == 0 ? getPositionOnLane() : stops[nextStopIndex - 1].pars.endPos;
2318 MSRouteIterator itEnd = nextStopIndex == n ? oldEdges.end() - 1 : stops[nextStopIndex].edge;
2319 auto endPos = nextStopIndex == n ? getArrivalPos() : stops[nextStopIndex].pars.endPos;
2321
2322 const bool newDestination = nextStopIndex == n && stopEdge == oldEdges.back();
2323 const bool needLoop = nextStopIndex > 0 && *itStart == stopEdge && startPos >= stop.endPos;
2324 if (needLoop && startPos == stop.endPos) {
2325 // assume that two stops at the same position indicate a looped route
2326 startPos += POSITION_EPS;
2327 stop.index = STOP_INDEX_REPEAT;
2328 } else if (!hasDeparted()) {
2329 stop.index = STOP_INDEX_END;
2330 }
2331
2332 MSRouteIterator itSentintel = itEnd + 1;
2333 MSRouteIterator onRouteStart = itStart + (needLoop ? 1 : 0);
2334 const bool onRoute = std::find(onRouteStart, itSentintel, stopEdge) != itSentintel;
2335 if (onRoute) {
2336 if (!hasDeparted() && (int)myParameter->stops.size() >= nextStopIndex) {
2337 // stops will be rebuilt from scratch so we must patch the stops in myParameter
2338 auto it = myParameter->stops.begin() + nextStopIndex;
2339 const_cast<SUMOVehicleParameter*>(myParameter)->stops.insert(it, stop);
2340 }
2341 const bool ok = addStop(stop, errorMsg, 0, &onRouteStart);
2342 if (ok) {
2343 updateBestLanes(true, !hasDeparted() ? (*myCurrEdge)->getLanes().front() : 0);
2344 }
2345 return ok;
2346 }
2347
2348 ConstMSEdgeVector toNewStop;
2349 if (!teleport) {
2350 router.compute(*itStart, startPos, stopEdge, stop.endPos, this, t, toNewStop, true);
2351 if (toNewStop.size() == 0) {
2352 errorMsg = TLF("no route found from edge '%' to stop edge '%'", (*itStart)->getID(), stopEdge->getID());
2353 return false;
2354 }
2355 }
2356
2357 ConstMSEdgeVector fromNewStop;
2358 if (!newDestination) {
2359 router.compute(stopEdge, stop.endPos, *itEnd, endPos, this, t, fromNewStop, true);
2360 if (fromNewStop.size() == 0) {
2361 errorMsg = TLF("no route found from stop edge '%' to edge '%'", stopEdge->getID(), (*itEnd)->getID());
2362 return false;
2363 }
2364 }
2365
2366 auto itStop = myStops.begin();
2367 std::advance(itStop, nextStopIndex);
2368 MSStop newStop(stop);
2369 newStop.initPars(stop);
2370 newStop.edge = myRoute->end(); // will be patched in replaceRoute
2371 newStop.lane = stopLane;
2373 newStop.segment = MSGlobals::gMesoNet->getSegmentForEdge(newStop.lane->getEdge(), newStop.getEndPos(*this));
2374 if (newStop.lane->isInternal()) {
2375 errorMsg = TLF("Mesoscopic simulation does not allow stopping on internal edge '%' for vehicle '%'.", stop.edge, getID());
2376 return false;
2377 }
2378 }
2379 myStops.insert(itStop, newStop);
2380
2381 ConstMSEdgeVector oldRemainingEdges(myCurrEdge, getRoute().end());
2382 ConstMSEdgeVector newEdges; // only remaining
2383 newEdges.insert(newEdges.end(), myCurrEdge, itStart);
2384 if (!teleport) {
2385 newEdges.insert(newEdges.end(), toNewStop.begin(), toNewStop.end() - 1);
2386 } else {
2387 newEdges.push_back(*itStart);
2388 }
2389 if (!newDestination) {
2390 newEdges.insert(newEdges.end(), fromNewStop.begin(), fromNewStop.end() - 1);
2391 newEdges.insert(newEdges.end(), itEnd, oldEdges.end());
2392 } else {
2393 newEdges.push_back(stopEdge);
2394 }
2395 //std::cout << SIMTIME << " insertStop veh=" << getID()
2396 // << " teleport=" << teleport
2397 // << " busStop=" << stop.busstop
2398 // << " oldEdges=" << oldRemainingEdges.size()
2399 // << " newEdges=" << newEdges.size()
2400 // << " toNewStop=" << toNewStop.size()
2401 // << " fromNewStop=" << fromNewStop.size()
2402 // << "\n";
2403
2404 const double routeCost = router.recomputeCosts(newEdges, this, t);
2405 const double previousCost = router.recomputeCosts(oldRemainingEdges, this, t);
2406 const double savings = previousCost - routeCost;
2407
2408 if (!hasDeparted() && (int)myParameter->stops.size() >= nextStopIndex) {
2409 // stops will be rebuilt from scratch so we must patch the stops in myParameter
2410 auto it = myParameter->stops.begin() + nextStopIndex;
2411 const_cast<SUMOVehicleParameter*>(myParameter)->stops.insert(it, stop);
2412 }
2413 return replaceRouteEdges(newEdges, routeCost, savings, info, !hasDeparted(), false, false, &errorMsg);
2414}
2415
2416
2419 if (myEnergyParams == nullptr) {
2421 double tMass = 0;
2422 if (myPersonDevice != nullptr) {
2424 tMass += t->getVehicleType().getMass();
2425 }
2426 }
2427 if (myContainerDevice != nullptr) {
2429 tMass += t->getVehicleType().getMass();
2430 }
2431 }
2433 }
2434 return myEnergyParams;
2435}
2436
2437
2438double
2440 if (static_cast<MSDevice_Battery*>(getDevice(typeid(MSDevice_Battery))) != 0) {
2441 MSDevice_Battery* batteryOfVehicle = dynamic_cast<MSDevice_Battery*>(getDevice(typeid(MSDevice_Battery)));
2442 return batteryOfVehicle->getActualBatteryCapacity();
2443 } else {
2444 if (static_cast<MSDevice_ElecHybrid*>(getDevice(typeid(MSDevice_ElecHybrid))) != 0) {
2445 MSDevice_ElecHybrid* batteryOfVehicle = dynamic_cast<MSDevice_ElecHybrid*>(getDevice(typeid(MSDevice_ElecHybrid)));
2446 return batteryOfVehicle->getActualBatteryCapacity();
2447 }
2448 }
2449 return -1;
2450}
2451
2452
2453double
2455 if (static_cast<MSDevice_Battery*>(getDevice(typeid(MSDevice_Battery))) != 0) {
2456 MSDevice_Battery* batteryOfVehicle = dynamic_cast<MSDevice_Battery*>(getDevice(typeid(MSDevice_Battery)));
2457 return batteryOfVehicle->getActualBatteryCapacity() / batteryOfVehicle->getMaximumBatteryCapacity();
2458 } else {
2459 if (static_cast<MSDevice_ElecHybrid*>(getDevice(typeid(MSDevice_ElecHybrid))) != 0) {
2460 MSDevice_ElecHybrid* batteryOfVehicle = dynamic_cast<MSDevice_ElecHybrid*>(getDevice(typeid(MSDevice_ElecHybrid)));
2461 return batteryOfVehicle->getActualBatteryCapacity() / batteryOfVehicle->getMaximumBatteryCapacity();
2462 }
2463 }
2464 return -1;
2465}
2466
2467
2468double
2470 if (static_cast<MSDevice_Battery*>(getDevice(typeid(MSDevice_Battery))) != 0) {
2471 MSDevice_Battery* batteryOfVehicle = dynamic_cast<MSDevice_Battery*>(getDevice(typeid(MSDevice_Battery)));
2472 return batteryOfVehicle->getEnergyCharged();
2473 } else {
2474 if (static_cast<MSDevice_ElecHybrid*>(getDevice(typeid(MSDevice_ElecHybrid))) != 0) {
2475 MSDevice_ElecHybrid* batteryOfVehicle = dynamic_cast<MSDevice_ElecHybrid*>(getDevice(typeid(MSDevice_ElecHybrid)));
2476 return batteryOfVehicle->getEnergyCharged();
2477 }
2478 }
2479 return -1;
2480}
2481
2482
2483double
2485 if (static_cast<MSDevice_Battery*>(getDevice(typeid(MSDevice_Battery))) != 0) {
2486 MSDevice_Battery* batteryOfVehicle = dynamic_cast<MSDevice_Battery*>(getDevice(typeid(MSDevice_Battery)));
2487 return batteryOfVehicle->getMaximumChargeRate();
2488 }
2489 return -1;
2490}
2491
2492
2493double
2495 if (static_cast<MSDevice_ElecHybrid*>(getDevice(typeid(MSDevice_ElecHybrid))) != 0) {
2496 MSDevice_ElecHybrid* elecHybridDevice = dynamic_cast<MSDevice_ElecHybrid*>(getDevice(typeid(MSDevice_ElecHybrid)));
2497 return elecHybridDevice->getCurrentFromOverheadWire();
2498 }
2499
2500 return NAN;
2501}
2502
2503double
2505 if (isOnRoad() || isIdling()) {
2507 } else {
2508 return 0.;
2509 }
2510}
2511
2512
2517
2518
2523
2524
2527 if (myEdgeWeights == nullptr) {
2529 }
2530 return *myEdgeWeights;
2531}
2532
2533
2534
2535
2536int
2538 int boarded = myPersonDevice == nullptr ? 0 : myPersonDevice->size();
2539 return boarded + myParameter->personNumber;
2540}
2541
2542int
2544 int leavingPersonNumber = 0;
2545 const std::vector<MSTransportable*>& persons = getPersons();
2546 for (std::vector<MSTransportable*>::const_iterator it_p = persons.begin(); it_p != persons.end(); ++it_p) {
2547 MSStageDriving* const stage = dynamic_cast<MSStageDriving*>((*it_p)->getCurrentStage());
2548 const MSStop* stop = &myStops.front();
2549 const MSVehicle* joinVeh = dynamic_cast<MSVehicle*>(MSNet::getInstance()->getVehicleControl().getVehicle((*stop).pars.join));
2550 if (stop && stage->canLeaveVehicle(*it_p, *this, *stop) && !MSDevice_Transportable::willTransferAtJoin(*it_p, joinVeh)) {
2551 leavingPersonNumber++;
2552 }
2553 }
2554 return leavingPersonNumber;
2555}
2556
2557std::vector<std::string>
2559 std::vector<std::string> ret;
2560 const std::vector<MSTransportable*>& persons = getPersons();
2561 for (std::vector<MSTransportable*>::const_iterator it_p = persons.begin(); it_p != persons.end(); ++it_p) {
2562 ret.push_back((*it_p)->getID());
2563 }
2564 return ret;
2565}
2566
2567int
2569 int loaded = myContainerDevice == nullptr ? 0 : myContainerDevice->size();
2570 return loaded + myParameter->containerNumber;
2571}
2572
2573
2574void
2576 // this might be called from the MSTransportable destructor so we cannot do a dynamic cast to determine the type
2577 if (myPersonDevice != nullptr) {
2579 }
2580 if (myContainerDevice != nullptr) {
2582 }
2583 if (myEnergyParams != nullptr) {
2585 }
2586}
2587
2588
2589void
2595
2596
2597const std::vector<MSTransportable*>&
2599 if (myPersonDevice == nullptr) {
2601 } else {
2603 }
2604}
2605
2606
2607const std::vector<MSTransportable*>&
2609 if (myContainerDevice == nullptr) {
2611 } else {
2613 }
2614}
2615
2616
2617bool
2618MSBaseVehicle::isLineStop(double position) const {
2619 if (myParameter->line == "") {
2620 // not a public transport line
2621 return false;
2622 }
2623 for (const SUMOVehicleParameter::Stop& stop : myParameter->stops) {
2624 if (stop.startPos <= position && position <= stop.endPos) {
2625 return true;
2626 }
2627 }
2628 for (const SUMOVehicleParameter::Stop& stop : myRoute->getStops()) {
2629 if (stop.startPos <= position && position <= stop.endPos) {
2630 return true;
2631 }
2632 }
2633 return false;
2634}
2635
2636
2637bool
2638MSBaseVehicle::hasDevice(const std::string& deviceName) const {
2639 for (MSDevice* const dev : myDevices) {
2640 if (dev->deviceName() == deviceName) {
2641 return true;
2642 }
2643 }
2644 return false;
2645}
2646
2647
2648void
2649MSBaseVehicle::createDevice(const std::string& deviceName) {
2650 if (!hasDevice(deviceName)) {
2651 if (deviceName == "rerouting") {
2652 ((SUMOVehicleParameter*)myParameter)->setParameter("has." + deviceName + ".device", "true");
2654 if (hasDeparted()) {
2655 // vehicle already departed: disable pre-insertion rerouting and enable regular routing behavior
2656 MSDevice_Routing* routingDevice = static_cast<MSDevice_Routing*>(getDevice(typeid(MSDevice_Routing)));
2657 assert(routingDevice != 0);
2659 }
2660 } else {
2661 throw InvalidArgument(TLF("creating device of type '%' is not supported", deviceName));
2662 }
2663 }
2664}
2665
2666
2667std::string
2668MSBaseVehicle::getDeviceParameter(const std::string& deviceName, const std::string& key) const {
2669 for (MSVehicleDevice* const dev : myDevices) {
2670 if (dev->deviceName() == deviceName) {
2671 return dev->getParameter(key);
2672 }
2673 }
2674 throw InvalidArgument(TLF("no device of type '%' exists", deviceName));
2675}
2676
2677
2678void
2679MSBaseVehicle::setDeviceParameter(const std::string& deviceName, const std::string& key, const std::string& value) {
2680 for (MSVehicleDevice* const dev : myDevices) {
2681 if (dev->deviceName() == deviceName) {
2682 dev->setParameter(key, value);
2683 return;
2684 }
2685 }
2686 throw InvalidArgument(TLF("no device of type '%' exists", deviceName));
2687}
2688
2689
2690void
2691MSBaseVehicle::setJunctionModelParameter(const std::string& key, const std::string& value) {
2694 const_cast<SUMOVehicleParameter&>(getParameter()).setParameter(key, value);
2695 // checked in MSLink::ignoreFoe
2696 } else {
2697 throw InvalidArgument(TLF("Vehicle '%' does not support junctionModel parameter '%'.", getID(), key));
2698 }
2699}
2700
2701
2702void
2703MSBaseVehicle::setCarFollowModelParameter(const std::string& key, const std::string& value) {
2704 // handle some generic params first and then delegate to the carFollowModel itself
2707 const_cast<SUMOVehicleParameter&>(getParameter()).setParameter(key, value);
2708 // checked in MSVehicle::planMove
2709 } else {
2710 MSVehicle* microVeh = dynamic_cast<MSVehicle*>(this);
2711 if (microVeh) {
2712 // remove 'carFollowModel.' prefix
2713 const std::string attrName = key.substr(15);
2714 microVeh->getCarFollowModel().setParameter(microVeh, attrName, value);
2715 }
2716 }
2717}
2718
2719
2720void
2722 /* Design idea for additional junction model parameters:
2723 We can distinguish between 3 levels of parameters
2724 1. typically shared by multiple vehicles -> vType parameter
2725 2. specific to one vehicle but stays constant throughout the simulation -> vehicle parameter
2726 3. specific to one vehicle and expected to change during simulation -> prefixed generic vehicle parameter
2727 */
2728 for (auto item : getParameter().getParametersMap()) {
2729 if (StringUtils::startsWith(item.first, "junctionModel.")) {
2730 setJunctionModelParameter(item.first, item.second);
2731 } else if (StringUtils::startsWith(item.first, "carFollowModel.")) {
2732 setCarFollowModelParameter(item.first, item.second);
2733 }
2734 }
2735 const std::string routingModeStr = getStringParam("device.rerouting.mode");
2736 try {
2737 int routingMode = StringUtils::toInt(routingModeStr);
2738 if (routingMode != libsumo::ROUTING_MODE_DEFAULT) {
2739 setRoutingMode(routingMode);
2741 // vehicles wishes to use traffic-dependent routing weights on triggere rerouting
2742 // (initWeightUpdate would be triggered anyway when equipped with device.rerouting)
2745 }
2746 }
2747 } catch (NumberFormatException&) {
2748 // @todo interpret symbolic constants
2749 throw ProcessError(TLF("could not interpret routing.mode '%'", routingModeStr));
2750 }
2751}
2752
2753
2762
2763
2764void
2766 assert(type != nullptr);
2767 // save old parameters before possible type deletion
2768 const double oldMu = myType->getSpeedFactor().getParameter(0);
2769 const double oldDev = myType->getSpeedFactor().getParameter(1);
2770 if (myType->isVehicleSpecific() && type != myType) {
2772 }
2773 // adapt myChosenSpeedFactor to the new type
2774 if (oldDev == 0.) {
2775 // old type had speedDev 0, reroll
2777 } else {
2778 // map old speedFactor onto new distribution
2779 const double distPoint = (myChosenSpeedFactor - oldMu) / oldDev;
2780 const double newMu = type->getSpeedFactor().getParameter(0);
2781 const double newDev = type->getSpeedFactor().getParameter(1);
2782 myChosenSpeedFactor = newMu + distPoint * newDev;
2783 // respect distribution limits
2786 }
2787 myType = type;
2788 if (myEnergyParams != nullptr) {
2790 }
2791}
2792
2793
2796 if (myType->isVehicleSpecific()) {
2797 return *const_cast<MSVehicleType*>(myType);
2798 }
2799 MSVehicleType* type = myType->buildSingularType(myType->getID() + "@" + getID());
2800 replaceVehicleType(type);
2801 return *type;
2802}
2803
2804
2805int
2807 const MSLane* const lane = getLane();
2808 if (lane == nullptr) {
2809 return getEdge()->getLanes()[0]->getRNGIndex();
2810 } else {
2811 return lane->getRNGIndex();
2812 }
2813}
2814
2815
2816SumoRNG*
2818 const MSLane* lane = getLane();
2819 if (lane == nullptr) {
2820 return getEdge()->getLanes()[0]->getRNG();
2821 } else {
2822 return lane->getRNG();
2823 }
2824}
2825
2826std::string
2827MSBaseVehicle::getPrefixedParameter(const std::string& key, std::string& error) const {
2828 const MSVehicle* microVeh = dynamic_cast<const MSVehicle*>(this);
2829 if (StringUtils::startsWith(key, "device.")) {
2830 StringTokenizer tok(key, ".");
2831 if (tok.size() < 3) {
2832 error = TLF("Invalid device parameter '%' for vehicle '%'.", key, getID());
2833 return "";
2834 }
2835 try {
2836 return getDeviceParameter(tok.get(1), key.substr(tok.get(0).size() + tok.get(1).size() + 2));
2837 } catch (InvalidArgument& e) {
2838 error = TLF("Vehicle '%' does not support device parameter '%' (%).", getID(), key, e.what());
2839 return "";
2840 }
2841 } else if (StringUtils::startsWith(key, "laneChangeModel.")) {
2842 if (microVeh == nullptr) {
2843 error = TLF("Mesoscopic vehicle '%' does not support laneChangeModel parameters.", getID());
2844 return "";
2845 }
2846 const std::string attrName = key.substr(16);
2847 try {
2848 return microVeh->getLaneChangeModel().getParameter(attrName);
2849 } catch (InvalidArgument& e) {
2850 error = TLF("Vehicle '%' does not support laneChangeModel parameter '%' (%).", getID(), key, e.what());
2851 return "";
2852 }
2853 } else if (StringUtils::startsWith(key, "carFollowModel.")) {
2854 if (microVeh == nullptr) {
2855 error = TLF("Mesoscopic vehicle '%' does not support carFollowModel parameters.", getID());
2856 return "";
2857 }
2858 const std::string attrName = key.substr(15);
2859 try {
2860 return microVeh->getCarFollowModel().getParameter(microVeh, attrName);
2861 } catch (InvalidArgument& e) {
2862 error = TLF("Vehicle '%' does not support carFollowModel parameter '%' (%).", getID(), key, e.what());
2863 return "";
2864 }
2865 } else if (StringUtils::startsWith(key, "has.") && StringUtils::endsWith(key, ".device")) {
2866 StringTokenizer tok(key, ".");
2867 if (tok.size() != 3) {
2868 error = TL("Invalid check for device. Expected format is 'has.DEVICENAME.device'.");
2869 return "";
2870 }
2871 return hasDevice(tok.get(1)) ? "true" : "false";
2872 // parking related parameters start here
2873 } else if (key == "parking.rerouteCount") {
2875 } else if (StringUtils::startsWith(key, "parking.memory.")) {
2876 std::vector<std::string> values;
2877 if (getParkingMemory()) {
2878 if (key == "parking.memory.IDList") {
2879 for (const auto& item : *getParkingMemory()) {
2880 values.push_back(item.first->getID());
2881 }
2882 } else if (key == "parking.memory.score") {
2883 for (const auto& item : *getParkingMemory()) {
2884 values.push_back(item.second.score);
2885 }
2886 } else if (key == "parking.memory.blockedAtTime") {
2887 for (const auto& item : *getParkingMemory()) {
2888 values.push_back(toString(STEPS2TIME(item.second.blockedAtTime)));
2889 }
2890 } else if (key == "parking.memory.blockedAtTimeLocal") {
2891 for (const auto& item : *getParkingMemory()) {
2892 values.push_back(toString(STEPS2TIME(item.second.blockedAtTimeLocal)));
2893 }
2894 } else {
2895 error = TLF("Unsupported parking parameter '%' for vehicle '%'.", key, getID());
2896 }
2897 }
2898 return toString(values);
2899 } else {
2900 // default: custom user parameter
2901 return getParameter().getParameter(key, "");
2902 }
2903}
2904
2905
2906void
2913
2914
2915void
2921
2922
2923void
2925 if (myChargingMemory == nullptr) {
2927 }
2929}
2930
2931
2932void
2938
2939
2940void
2941MSBaseVehicle::rememberParkingAreaScore(const MSStoppingPlace* pa, const std::string& score) {
2942 if (myParkingMemory == nullptr) {
2944 }
2946}
2947
2948
2951 if (myParkingMemory == nullptr) {
2952 return -1;
2953 }
2954 return myParkingMemory->sawBlockedStoppingPlace(pa, local);
2955}
2956
2957
2964
2965
2968 if (myChargingMemory == nullptr) {
2969 return -1;
2970 }
2971 return myChargingMemory->sawBlockedStoppingPlace(cs, local);
2972}
2973
2974
2975void
2977 if (hasStops() && myStops.front().parkingarea != nullptr && myStops.front().parkingarea->isReservable()) {
2978 myStops.front().parkingarea->removeSpaceReservation(this);
2979 }
2980}
2981
2982
2983#ifdef _DEBUG
2984void
2985MSBaseVehicle::initMoveReminderOutput(const OptionsCont& oc) {
2986 if (oc.isSet("movereminder-output.vehicles")) {
2987 const std::vector<std::string> vehicles = oc.getStringVector("movereminder-output.vehicles");
2988 myShallTraceMoveReminders.insert(vehicles.begin(), vehicles.end());
2989 }
2990}
2991
2992
2993void
2994MSBaseVehicle::traceMoveReminder(const std::string& type, MSMoveReminder* rem, double pos, bool keep) const {
2995 OutputDevice& od = OutputDevice::getDeviceByOption("movereminder-output");
2996 od.openTag("movereminder");
2997 od.writeAttr(SUMO_ATTR_TIME, STEPS2TIME(MSNet::getInstance()->getCurrentTimeStep()));
2998 od.writeAttr("veh", getID());
3000 od.writeAttr("type", type);
3001 od.writeAttr("pos", toString(pos));
3002 od.writeAttr("keep", toString(keep));
3003 od.closeTag();
3004}
3005#endif
3006
3007
3008/****************************************************************************/
long long int SUMOTime
Definition GUI.h:36
std::vector< const MSEdge * > ConstMSEdgeVector
Definition MSEdge.h:74
ConstMSEdgeVector::const_iterator MSRouteIterator
Definition MSRoute.h:57
#define WRITE_WARNINGF(...)
Definition MsgHandler.h:287
#define WRITE_ERRORF(...)
Definition MsgHandler.h:296
#define WRITE_WARNING(msg)
Definition MsgHandler.h:286
#define TL(string)
Definition MsgHandler.h:304
#define TLF(string,...)
Definition MsgHandler.h:306
std::shared_ptr< const MSRoute > ConstMSRoutePtr
Definition Route.h:32
std::string time2string(SUMOTime t, bool humanReadable)
convert SUMOTime to string (independently of global format setting)
Definition SUMOTime.cpp:91
#define STEPS2TIME(x)
Definition SUMOTime.h:58
#define SIMSTEP
Definition SUMOTime.h:64
#define SUMOTime_MAX
Definition SUMOTime.h:34
#define SIMTIME
Definition SUMOTime.h:65
#define TIME2STEPS(x)
Definition SUMOTime.h:60
bool isRailway(SVCPermissions permissions)
Returns whether an edge with the given permissions is a (exclusive) railway edge.
@ RANDOM
The edge is chosen randomly.
@ GIVEN
The edge index is given.
@ DEFAULT
No information given; use default.
const int STOP_INDEX_END
const long long int VEHPARS_FORCE_REROUTE
DepartLaneDefinition
Possible ways to choose a lane on depart.
@ GIVEN
The speed is given.
@ GIVEN
The position is given.
@ DEFAULT
No information given; use default.
@ BASE
Back-at-zero position.
const int STOP_SPEED_SET
const long long int VEHPARS_CFMODEL_PARAMS_SET
@ RANDOM
The lane is chosen randomly.
@ GIVEN
The arrival lane is given.
@ FIRST_ALLOWED
The rightmost lane the vehicle may use.
std::vector< SUMOVehicleParameter::Stop > StopParVector
@ GIVEN
The speed is given.
const int STOP_INDEX_REPEAT
const long long int VEHPARS_PARKING_BADGES_SET
const int STOP_INDEX_FIT
const long long int VEHPARS_JUNCTIONMODEL_PARAMS_SET
const long long int VEHPARS_SPEEDFACTOR_SET
@ RANDOM
The arrival position is chosen randomly.
@ GIVEN
The arrival position is given.
@ CENTER
Half the road length.
const int STOP_JUMP_SET
const long long int VEHPARS_LINE_SET
const long long int VEHPARS_INSERTION_CHECKS_SET
@ CONTAINER_TRIGGERED
The departure is container triggered.
@ TRIGGERED
The departure is person triggered.
@ SUMO_TAG_CLOSING_REROUTE
reroute of type closing
@ SUMO_TAG_VEHICLE
description of a vehicle
@ SUMO_TAG_PARKING_AREA
A parking area.
@ SUMO_ATTR_CF_IGNORE_IDS
@ SUMO_ATTR_JM_IGNORE_IDS
@ SUMO_ATTR_JM_IGNORE_TYPES
@ SUMO_ATTR_LINE
@ SUMO_ATTR_REROUTE
@ SUMO_ATTR_DISTANCE
@ SUMO_ATTR_SPEEDFACTOR
@ SUMO_ATTR_ROUTE
@ SUMO_ATTR_ID
@ SUMO_ATTR_CF_IGNORE_TYPES
@ SUMO_ATTR_ARRIVALPOS_RANDOMIZED
@ SUMO_ATTR_TIME
trigger: the time of the step
double gWeightsRandomFactor
Definition StdDefs.cpp:35
int gPrecisionRandom
Definition StdDefs.cpp:30
const double INVALID_DOUBLE
invalid double
Definition StdDefs.h:68
T MIN2(T a, T b)
Definition StdDefs.h:80
const double SUMO_const_haltingSpeed
the speed threshold at which vehicles are considered as halting
Definition StdDefs.h:62
T MAX2(T a, T b)
Definition StdDefs.h:86
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition ToString.h:49
double getMax() const
Returns the maximum value of this distribution.
double getMin() const
Returns the minimum value of this distribution.
double getParameter(const int index) const
Returns the nth parameter of this distribution.
An upper class for objects with additional parameters.
double getTransportableMass() const
Returns the mass of all transportables in the vehicle.
void setSecondary(const EnergyParams *secondaryParams)
Set secondary params.
void setTransportableMass(const double mass)
Sets the mass of all transportables in the vehicle.
static double computeNoise(SUMOEmissionClass c, double v, double a)
Returns the noise produced by the a vehicle of the given type at the given speed.
MESegment * getSegmentForEdge(const MSEdge &e, double pos=0)
Get the segment for a given edge at a given position.
Definition MELoop.cpp:339
virtual std::string getParameter(const std::string &key) const
try to retrieve the given parameter from this laneChangeModel. Throw exception for unsupported key
double getMaxSpeed() const
Returns the maximum speed (the minimum of desired and technical maximum speed)
bool haveValidStopEdges(bool silent=false) const
check whether all stop.edge MSRouteIterators are valid and in order
int myRoutingMode
routing mode (see TraCIConstants.h)
bool hasJump(const MSRouteIterator &it) const
check wether the vehicle has jump at the given part of its route
bool hasReminder(MSMoveReminder *rem) const
Checks whether the vehilce has the given MoveReminder.
static double addStopPriority(double p1, double p2)
std::list< MSStop > myStops
The vehicle's list of stops.
StoppingPlaceMemory * myParkingMemory
memory for parking search
double getImpatience() const
Returns this vehicles impatience.
void setSkips(MSStop &stop, int prevActiveStops)
patch stop.pars.index to record the number of skipped candidate edges before stop....
virtual ConstMSEdgeVector::const_iterator getRerouteOrigin() const
Returns the starting point for reroutes (usually the current edge)
const StoppingPlaceMemory * getParkingMemory() const
const std::vector< MSTransportable * > & getPersons() const
retrieve riding persons
virtual void initDevices()
void rememberParkingAreaScore(const MSStoppingPlace *pa, const std::string &score)
score only needed when running with gui
const long long int myRandomSeed
const MSEdge * succEdge(int nSuccs) const
Returns the nSuccs'th successor of edge the vehicle is currently at.
int getDepartEdge() const
Returns the edge on which this vehicle shall depart.
void resetRoutePosition(int index, DepartLaneDefinition departLaneProcedure)
reset index of edge within route
std::string getDeviceParameter(const std::string &deviceName, const std::string &key) const
try to retrieve the given parameter from any of the vehicles devices, raise InvalidArgument if no dev...
StoppingPlaceMemory * myChargingMemory
bool replaceStop(int nextStopIndex, SUMOVehicleParameter::Stop stop, const std::string &info, bool teleport, std::string &errorMsg)
int getLeavingPersonNumber() const
Returns the number of leaving persons.
MSBaseVehicle(SUMOVehicleParameter *pars, ConstMSRoutePtr route, MSVehicleType *type, const double speedFactor)
Constructor.
void calculateArrivalParams(bool onInit)
(Re-)Calculates the arrival position and lane from the vehicle parameters
virtual double getArrivalPos() const
Returns this vehicle's desired arrivalPos for its current route (may change on reroute)
void setCarFollowModelParameter(const std::string &key, const std::string &value)
set individual carFollow model parameters (not type related)
void setRoutingMode(int value)
Sets routing behavior.
void resetParkingAreaScores()
static NumericalID myCurrentNumericalIndex
bool rerouteBetweenStops(int nextStopIndex, const std::string &info, bool teleport, std::string &errorMsg)
MoveReminderCont myMoveReminders
Currently relevant move reminders.
void rememberChargingStationScore(const MSStoppingPlace *cs, const std::string &score)
int getInsertionChecks() const
double myDepartPos
The real depart position.
const SUMOVehicleParameter & getParameter() const
Returns the vehicle's parameter (including departure definition)
double getMaxChargeRate() const
Returns the maximum charge rate allowed by the battery in the current time step (W)
void replaceParameter(const SUMOVehicleParameter *newParameter)
replace the vehicle parameter (deleting the old one)
void rememberBlockedParkingArea(const MSStoppingPlace *pa, bool local)
int getNumberParkingReroutes() const
std::vector< MSVehicleDevice * > myDevices
The devices this vehicle has.
virtual const MSEdge * getCurrentEdge() const
Returns the edge the vehicle is currently at (possibly an internal edge)
double getPreviousSpeed() const
Returns the vehicle's previous speed.
void removeTransportableMass(MSTransportable *t)
removes a person or containers mass
MSStop & getNextStopMutable()
virtual void updateBestLanes(bool forceRebuild=false, const MSLane *startLane=0)
virtual void addTransportable(MSTransportable *transportable)
Adds a person or container to this vehicle.
virtual BaseInfluencer & getBaseInfluencer()=0
Returns the velocity/lane influencer.
const SUMOVehicleParameter::Stop * getNextStopParameter() const
return parameters for the next stop (SUMOVehicle Interface)
void rememberBlockedChargingStation(const MSStoppingPlace *cs, bool local)
virtual bool replaceRoute(ConstMSRoutePtr route, const std::string &info, bool onInit=false, int offset=0, bool addRouteStops=true, bool removeStops=true, std::string *msgReturn=nullptr)
Replaces the current route by the given one.
SUMOTime activateRemindersOnReroute(SUMOTime currentTime)
remove outdated driveways on reroute
int getNumRemainingEdges() const
return the number of edges remaining in the route (include the current)
double getOdometer() const
Returns the distance that was already driven by this vehicle.
bool isRail() const
virtual bool hasArrived() const
Returns whether this vehicle has already arived (by default this is true if the vehicle has reached i...
const NumericalID myNumericalID
bool isStoppedInRange(const double pos, const double tolerance, bool checkFuture=false) const
return whether the given position is within range of the current stop
bool isJumping() const
Returns whether the vehicle is perform a jump.
void checkRouteRemoval()
remove route at the end of the simulation
MSVehicleType & getSingularType()
Replaces the current vehicle type with a new one used by this vehicle only.
const MSVehicleType * myType
This vehicle's type.
const MSRouteIterator & getCurrentRouteEdge() const
Returns an iterator pointing to the current edge in this vehicles route.
bool isStoppedParking() const
Returns whether the vehicle is on a parking stop.
void unregisterWaiting()
mark vehicle as active
bool hasValidRoute(std::string &msg, ConstMSRoutePtr route=0) const
Validates the current or given route.
void cleanupParkingReservation()
unregisters from a parking reservation when changing or skipping stops
double getLength() const
Returns the vehicle's length.
bool isParking() const
Returns whether the vehicle is parking.
MSParkingArea * getCurrentParkingArea()
get the current parking area stop or nullptr
const MSEdge * getEdge() const
Returns the edge the vehicle is currently at.
double getHarmonoise_NoiseEmissions() const
Returns noise emissions of the current state.
int getPersonNumber() const
Returns the number of persons.
double getRelativeStateOfCharge() const
Returns actual relative state of charge of battery (-)
void setJunctionModelParameter(const std::string &key, const std::string &value)
set individual junction model paramete (not type related)
void setDepartAndArrivalEdge()
apply departEdge and arrivalEdge attributes
void setID(const std::string &newID)
set the id (inherited from Named but forbidden for vehicles)
MSRouteIterator myCurrEdge
Iterator to current route-edge.
static MSLane * interpretOppositeStop(SUMOVehicleParameter::Stop &stop)
interpret stop lane on opposite side of the road
StopParVector myPastStops
The list of stops that the vehicle has already reached.
static std::vector< MSTransportable * > myEmptyTransportableVector
const std::vector< std::string > & getParkingBadges() const
get the valid parking access rights (vehicle settings override vehicle type settings)
bool hasDeparted() const
Returns whether this vehicle has already departed.
bool ignoreTransientPermissions() const
Returns whether this object is ignoring transient permission changes (during routing)
virtual void resetApproachOnReroute()
reset rail signal approach information
ConstMSRoutePtr myRoute
This vehicle's route.
MSDevice_Transportable * myContainerDevice
The containers this vehicle may have.
void resetChargingStationScores()
bool allowsBoarding(const MSTransportable *t) const
whether the given transportable is allowed to board this vehicle
double getStateOfCharge() const
Returns actual state of charge of battery (Wh) RICE_CHECK: This may be a misnomer,...
MSEdgeWeightsStorage & _getWeightsStorage() const
virtual bool handleCollisionStop(MSStop &stop, const double distToStop)
bool hasDevice(const std::string &deviceName) const
check whether the vehicle is equiped with a device of the given name
void addReminder(MSMoveReminder *rem, double pos=0)
Adds a MoveReminder dynamically.
SumoRNG * getRNG() const
SUMOTime getDeparture() const
Returns this vehicle's real departure time.
SUMOTime sawBlockedChargingStation(const MSStoppingPlace *cs, bool local) const
EnergyParams * getEmissionParameters() const
retrieve parameters for the energy consumption model
double basePos(const MSEdge *edge) const
departure position where the vehicle fits fully onto the edge (if possible)
void setDeviceParameter(const std::string &deviceName, const std::string &key, const std::string &value)
try to set the given parameter from any of the vehicles devices, raise InvalidArgument if no device p...
MSDevice_Transportable * myPersonDevice
The passengers this vehicle may have.
bool hasStops() const
Returns whether the vehicle has to stop somewhere.
std::string getFlowID() const
reconstruct flow id from vehicle id
virtual void activateReminders(const MSMoveReminder::Notification reason, const MSLane *enteredLane=0)
"Activates" all current move reminder
bool isLineStop(double position) const
returns whether the vehicle serves a public transport line that serves the given stop
double myChosenSpeedFactor
A precomputed factor by which the driver wants to be faster than the speed limit.
const MSStop & getNextStop() const
@ ROUTE_INVALID
route was checked and is valid
@ ROUTE_START_INVALID_PERMISSIONS
std::string getPrefixedParameter(const std::string &key, std::string &error) const
retrieve parameters of devices, models and the vehicle itself
bool replaceWithAlternative(std::list< MSStop >::iterator iter, const MSRouteIterator searchStart, const MSRouteIterator end)
replace stop with a same-name alternative that is on the route and return success
void addStops(const bool ignoreStopErrors, MSRouteIterator *searchStart=nullptr, bool addRouteStops=true)
Adds stops to the built vehicle.
void removeTransportable(MSTransportable *t)
removes a person or container
SUMOTime sawBlockedParkingArea(const MSStoppingPlace *pa, bool local) const
SUMOVehicleClass getVClass() const
Returns the vehicle's access class.
MSParkingArea * getNextParkingArea()
get the upcoming parking area stop or nullptr
int myArrivalLane
The destination lane where the vehicle stops.
int getRouteValidity(bool update=true, bool silent=false, std::string *msgReturn=nullptr)
check for route validity at first insertion attempt
MSStop & getStop(int nextStopIndex)
virtual ~MSBaseVehicle()
Destructor.
bool insertStop(int nextStopIndex, SUMOVehicleParameter::Stop stop, const std::string &info, bool teleport, std::string &errorMsg)
virtual bool instantStopping() const
whether instant stopping is permitted
SUMOTime myDeparture
The real departure time.
std::vector< std::string > getPersonIDList() const
Returns the list of persons.
const MSEdgeWeightsStorage & getWeightsStorage() const
Returns the vehicle's internal edge travel times/efforts container.
bool isStoppedTriggered() const
Returns whether the vehicle is on a triggered stop.
virtual bool resumeFromStopping()=0
virtual bool hasInfluencer() const =0
whether the vehicle is individually influenced (via TraCI or special parameters)
const std::set< SUMOTrafficObject::NumericalID > getUpcomingEdgeIDs() const
returns the numerical ids of edges to travel
void initTransportableDevice(bool isPerson)
init device during state loading
bool stopsAtEdge(const MSEdge *edge) const
Returns whether the vehicle stops at the given edge.
bool addStop(const SUMOVehicleParameter::Stop &stopPar, std::string &errorMsg, SUMOTime untilOffset=0, MSRouteIterator *searchStart=nullptr)
Adds a stop.
double getChargedEnergy() const
Returns the energy charged to the battery in the current time step (Wh)
void onDepart()
Called when the vehicle is inserted into the network.
void removeReminder(MSMoveReminder *rem)
Removes a MoveReminder dynamically.
SUMOTime getStopDuration() const
get remaining stop duration or 0 if the vehicle isn't stopped
virtual double getAcceleration() const
Returns the vehicle's acceleration.
virtual bool addTraciStop(SUMOVehicleParameter::Stop stop, std::string &errorMsg)
const MSRoute & getRoute() const
Returns the current route.
int getRoutingMode() const
return routing mode (configures router choice but also handling of transient permission changes)
int getRoutePosition() const
return index of edge within route
bool replaceParkingArea(MSParkingArea *parkingArea, std::string &errorMsg)
replace the current parking area stop with a new stop with merge duration
static const SUMOTime NOT_YET_DEPARTED
SUMOTime getDepartDelay() const
Returns the depart delay.
double getElecHybridCurrent() const
Returns actual current (A) of ElecHybrid device RICE_CHECK: Is this the current consumed from the ove...
bool myAmRegisteredAsWaiting
Whether this vehicle is registered as waiting for a person or container (for deadlock-recognition)
SUMOAbstractRouter< MSEdge, SUMOVehicle > & getRouterTT() const
EnergyParams * myEnergyParams
The emission parameters this vehicle may have.
const SUMOVehicleParameter * myParameter
This vehicle's parameter.
virtual bool hasValidRouteStart(std::string &msg)
checks wether the vehicle can depart on the first edge
int myRouteValidity
status of the current vehicle route
std::vector< std::pair< int, double > > getStopIndices() const
return list of route indices for the remaining stops
SUMOTime myStopUntilOffset
The offset when adding route stops with 'until' on route replacement.
virtual bool isOnRoad() const
Returns the information whether the vehicle is on a road (is simulated)
const std::vector< MSTransportable * > & getContainers() const
retrieve riding containers
bool reroute(SUMOTime t, const std::string &info, SUMOAbstractRouter< MSEdge, SUMOVehicle > &router, const bool onInit=false, const bool withTaz=false, const bool silent=false, const MSEdge *sink=nullptr)
Performs a rerouting using the given router.
bool stopsAt(MSStoppingPlace *stop) const
Returns whether the vehicle stops at the given stopping place.
int getRNGIndex() const
MSEdgeWeightsStorage * myEdgeWeights
const MSVehicleType & getVehicleType() const
Returns the vehicle's type definition.
void createDevice(const std::string &deviceName)
create device of the given type
bool isStopped() const
Returns whether the vehicle is at a stop.
MSDevice * getDevice(const std::type_info &type) const
Returns a device of the given type if it exists, nullptr otherwise.
bool abortNextStop(int nextStopIndex=0)
deletes the next stop at the given index if it exists
int myNumberReroutes
The number of reroutings.
double myArrivalPos
The position on the destination lane where the vehicle stops.
bool insertJump(int nextStopIndex, MSRouteIterator itStart, std::string &errorMsg)
helper function
virtual void saveState(OutputDevice &out)
Saves the (common) state of a vehicle.
virtual void replaceVehicleType(const MSVehicleType *type)
Replaces the current vehicle type by the one given.
std::vector< StopEdgeInfo > getStopEdges(double &firstPos, double &lastPos, std::set< int > &jumps) const
Returns the list of still pending stop edges also returns the first and last stop position.
double myOdometer
A simple odometer to keep track of the length of the route already driven.
void initTransientModelParams()
init model parameters from generic params
int getContainerNumber() const
Returns the number of containers.
bool replaceRouteEdges(ConstMSEdgeVector &edges, double cost, double savings, const std::string &info, bool onInit=false, bool check=false, bool removeStops=true, std::string *msgReturn=nullptr)
Replaces the current route by the given edges.
virtual std::string getParameter(const MSVehicle *veh, const std::string &key) const
try to get the given parameter for this carFollowingModel
Definition MSCFModel.h:691
virtual void setParameter(MSVehicle *veh, const std::string &key, const std::string &value) const
try to set the given parameter for this carFollowingModel
Definition MSCFModel.h:704
Battery device for electric vehicles.
double getActualBatteryCapacity() const
Get the actual vehicle's Battery Capacity in Wh.
double getMaximumChargeRate() const
Get current charge rate in W depending on the state of charge.
double getMaximumBatteryCapacity() const
Get the total vehicle's Battery Capacity in Wh.
double getEnergyCharged() const
Get charged energy.
A device which collects info on the vehicle trip (mainly on departure and arrival)
double getMaximumBatteryCapacity() const
Get the total vehicle's Battery Capacity in kWh.
double getCurrentFromOverheadWire() const
Get actual current in the overhead wire segment.
double getEnergyCharged() const
Get charged energy.
double getActualBatteryCapacity() const
Get the actual vehicle's Battery Capacity in kWh.
A device that performs vehicle rerouting based on current edge speeds.
bool sufficientSaving(double oldCost, double newCost)
whether the change in saving is enough to trigger rerouting
bool notifyEnter(SUMOTrafficObject &veh, MSMoveReminder::Notification reason, const MSLane *enteredLane=0)
Computes a new route on vehicle insertion.
static void buildVehicleDevices(SUMOVehicle &v, std::vector< MSVehicleDevice * > &into)
Build devices for the given vehicle, if needed.
A device which collects info on the vehicle trip (mainly on departure and arrival)
bool allowsBoarding(const MSTransportable *t) const
whether the given person is allowed to board this taxi
const std::vector< MSTransportable * > & getTransportables() const
Returns the list of transportables using this vehicle.
static bool willTransferAtJoin(const MSTransportable *t, const MSBaseVehicle *joinVeh)
check if boardingDuration should be applied
static MSDevice_Transportable * buildVehicleDevices(SUMOVehicle &v, std::vector< MSVehicleDevice * > &into, const bool isContainer)
Build devices for the given vehicle, if needed.
int size() const
Return the number of passengers / containers.
void addTransportable(MSTransportable *transportable)
Add a passenger.
void removeTransportable(MSTransportable *transportable)
Remove a passenger (TraCI)
Abstract in-vehicle / in-person device.
Definition MSDevice.h:62
static void buildVehicleDevices(SUMOVehicle &v, std::vector< MSVehicleDevice * > &into)
Build devices for the given vehicle, if needed.
Definition MSDevice.cpp:114
A road/street connecting two junctions.
Definition MSEdge.h:77
static void clear()
Clears the dictionary.
Definition MSEdge.cpp:1126
bool hasTransientPermissions() const
Definition MSEdge.cpp:1705
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:1374
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:1081
const MSEdge * getNormalBefore() const
if this edge is an internal edge, return its first normal predecessor, otherwise the edge itself
Definition MSEdge.cpp:971
MSLane * getFirstAllowed(SUMOVehicleClass vClass, bool defaultFirst=false, int routingMode=0) const
Definition MSEdge.cpp:755
A storage for edge travel times and efforts.
virtual void addEvent(Command *operation, SUMOTime execTimeStep=-1)
Adds an Event.
static bool gUseMesoSim
Definition MSGlobals.h:106
static bool gCheckRoutes
Definition MSGlobals.h:91
static MELoop * gMesoNet
mesoscopic simulation infrastructure
Definition MSGlobals.h:115
static int gInsertionChecks
The default value for insertion checks.
Definition MSGlobals.h:189
static SUMOTime gTimeToImpatience
Definition MSGlobals.h:78
static bool gHaveEmissions
Whether emission output of some type is needed (files or GUI)
Definition MSGlobals.h:186
static bool gUseStopEnded
whether the simulation should replay previous stop times
Definition MSGlobals.h:136
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:2496
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:2520
bool isInternal() const
Definition MSLane.cpp:2651
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:1777
@ NEWROUTE
The vehicle got a new route.
static MSNet * getInstance()
Returns the pointer to the unique instance of MSNet (singleton).
Definition MSNet.cpp:199
MSEventControl * getBeginOfTimestepEvents()
Returns the event control for events executed at the begin of a time step.
Definition MSNet.h:495
const std::vector< MSStoppingPlace * > & getStoppingPlaceAlternatives(const std::string &name, SumoXMLTag category) const
Definition MSNet.cpp:1531
MSVehicleRouter & getRouterTT(int rngIndex, const Prohibitions &prohibited={}) const
Definition MSNet.cpp:1628
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:1496
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:1371
MSInsertionControl & getInsertionControl()
Returns the insertion control.
Definition MSNet.h:455
MSVehicleControl & getVehicleControl()
Returns the vehicle control.
Definition MSNet.h:402
A lane area vehicles can halt at.
bool accepts(SUMOVehicle *veh) const override
Return the parking accepts the vehicle (due to its given badges)
static void storeTripId(const std::string &tripId, const std::string &vehID)
const ConstMSEdgeVector & getEdges() const
Definition MSRoute.h:128
void setCosts(double costs)
Sets the costs of the route.
Definition MSRoute.h:209
static bool hasRoute(const std::string &id)
returns whether a route with the given id exists
Definition MSRoute.cpp:159
static bool dictionary(const std::string &id, ConstMSRoutePtr route)
Adds a route to the dictionary.
Definition MSRoute.cpp:116
static void checkDist(const std::string &id)
Checks the distribution whether it is permanent and deletes it if not.
Definition MSRoute.cpp:194
void setSavings(double savings)
Sets the savings of the route.
Definition MSRoute.h:216
static void initEdgeWeights(SUMOVehicleClass svc, SUMOTime lastAdaption=-1, int index=-1)
initialize the edge weights if not done before
static void initWeightUpdate(SUMOTime lastAdaption=- 1)
intialize period edge weight update
static MSVehicleRouter & getRouterTT(const int rngIndex, SUMOVehicleClass svc, const Prohibitions &prohibited={})
return the vehicle router instance
bool canLeaveVehicle(const MSTransportable *t, const SUMOVehicle &veh, const MSStop &stop)
checks whether the person may exit at the current vehicle position
const MSLane * lane
The lane to stop at (microsim only)
Definition MSStop.h:50
MSStoppingPlace * containerstop
(Optional) container stop if one is assigned to the stop
Definition MSStop.h:56
std::string getDescription(bool nameOnly=false) const
get a short description for showing in the gui
Definition MSStop.cpp: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:149
const MESegment * segment
The segment to stop at (mesosim only)
Definition MSStop.h:52
bool reached
Information whether the stop has been reached.
Definition MSStop.h:75
MSRouteIterator edge
The edge in the route to stop at.
Definition MSStop.h:48
std::vector< int > skips
route indices on looped route that were skipped before this stop (after pior stop or depart edge)
Definition MSStop.h:95
double getEndPos(const SUMOVehicle &veh) const
return halting position for upcoming stop;
Definition MSStop.cpp: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:188
SUMOTime getArrival() const
return arrival / started time
Definition MSStop.cpp:194
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(double speedFactorOverride, SumoRNG *rng, const double minDev=-1.) const
Computes and returns the speed deviation.
MSVehicleType * buildSingularType(const std::string &id) const
Duplicates the microsim vehicle type giving the newly created type the given id, marking it as vehicl...
const std::vector< std::string > & getParkingBadges() const
Returns the parking access rights of this type.
static std::string getIDSecure(const T *obj, const std::string &fallBack="NULL")
get an identifier for Named-like object which may be Null
Definition Named.h:67
const std::string & getID() const
Returns the id.
Definition Named.h:74
A storage for options typed value containers)
Definition OptionsCont.h:89
bool isSet(const std::string &name, bool failOnNonExistant=true) const
Returns the information whether the named option is set.
const StringVector & getStringVector(const std::string &name) const
Returns the list of string-value of the named option (only for Option_StringVector)
static OptionsCont & getOptions()
Retrieves the options.
Static storage of an output device and its base (abstract) implementation.
OutputDevice & openTag(const std::string &xmlElement)
Opens an XML tag.
OutputDevice & writeAttr(const ATTR_TYPE &attr, const T &val, const bool isNull=false)
writes a named attribute
static OutputDevice & getDeviceByOption(const std::string &name)
Returns the device described by the option.
int getPrecision()
Returns the precision of the underlying stream.
bool closeTag(const std::string &comment="")
Closes the most recently opened tag and optionally adds a comment.
void setPrecision(int precision=gPrecision)
Sets the precision or resets it to default.
virtual const std::string getParameter(const std::string &key, const std::string defaultValue="") const
Returns the value for a given key.
const Parameterised::Map & getParametersMap() const
Returns the inner key/value map.
static const RGBColor DEFAULT_COLOR
The default color (for vehicle types and vehicles)
Definition RGBColor.h:202
Utility functions for using a global, resetable random number generator.
Definition RandHelper.h:133
static double rand(SumoRNG *rng=nullptr)
Returns a random real number in [0, 1)
virtual bool compute(const E *from, const E *to, const V *const vehicle, SUMOTime msTime, std::vector< const E * > &into, bool silent=false)=0
Builds the route between the given edges using the minimum effort at the given time The definition of...
virtual double recomputeCosts(const std::vector< const E * > &edges, const V *const v, SUMOTime msTime, double *lengthp=nullptr) const
double recomputeCostsPos(const std::vector< const E * > &edges, const V *const v, double fromPos, double toPos, SUMOTime msTime, double *lengthp=nullptr) const
std::string getStringParam(const std::string &paramName, const bool required=false, const std::string &deflt="") const
Retrieve a string parameter for the traffic object.
virtual const MSLane * getLane() const =0
Returns the lane the object is currently at.
long long int NumericalID
virtual double getSpeed() const =0
Returns the object's current speed.
virtual SUMOTime getWaitingTime(const bool accumulated=false) const =0
virtual bool isPerson() const
Whether it is a person.
double getFloatParam(const std::string &paramName, const bool required=false, const double deflt=INVALID_DOUBLE, bool checkDist=true) const
Retrieve a floating point parameter for the traffic object.
virtual double getPositionOnLane() const =0
Get the object's position along the lane.
Representation of a vehicle.
Definition SUMOVehicle.h:63
virtual bool isIdling() const =0
Returns whether the vehicle is idling (waiting to re-enter the net.
virtual double getBrakeGap(bool delayed=false) const =0
get distance for coming to a stop (used for rerouting checks)
Definition of vehicle stop (position and duration)
std::string edge
The edge to stop at.
ParkingType parking
whether the vehicle is removed from the net while stopping
std::string lane
The lane to stop at.
double speed
the speed at which this stop counts as reached (waypoint mode)
std::string parkingarea
(Optional) parking area if one is assigned to the stop
double startPos
The stopping position start.
int parametersSet
Information for the output which parameter were set.
int index
at which position in the stops list
SUMOTime jump
transfer time if there shall be a jump from this stop to the next route edge
SUMOTime until
The time at which the vehicle may continue its journey.
bool triggered
whether an arriving person lets the vehicle continue
SUMOTime ended
the time at which this stop was ended
double endPos
The stopping position end.
std::string tripId
id of the trip within a cyclical public transport route
bool containerTriggered
whether an arriving container lets the vehicle continue
bool collision
Whether this stop was triggered by a collision.
SUMOTime arrival
The (expected) time at which the vehicle reaches the stop.
SUMOTime duration
The stopping duration.
Structure representing possible vehicle parameter.
ArrivalSpeedDefinition arrivalSpeedProcedure
Information how the vehicle's end speed shall be chosen.
double departSpeed
(optional) The initial speed of the vehicle
std::string vtypeid
The vehicle's type id.
SUMOTime repetitionOffset
The time offset between vehicle reinsertions.
long long int repetitionsDone
The number of times the vehicle was already inserted.
std::vector< std::string > via
List of the via-edges the vehicle must visit.
ArrivalLaneDefinition arrivalLaneProcedure
Information how the vehicle shall choose the lane to arrive on.
long long int parametersSet
Information for the router which parameter were set, TraCI may modify this (when changing color)
void write(OutputDevice &dev, const OptionsCont &oc, const SumoXMLTag altTag=SUMO_TAG_VEHICLE, const std::string &typeID="") const
Writes the parameters as a beginning element.
int personNumber
The static number of persons in the vehicle when it departs (not including boarding persons)
RouteIndexDefinition arrivalEdgeProcedure
Information how the vehicle's final edge shall be chosen.
bool wasSet(long long int what) const
Returns whether the given parameter was set.
double departPos
(optional) The position the vehicle shall depart from
DepartSpeedDefinition departSpeedProcedure
Information how the vehicle's initial speed shall be chosen.
double arrivalPos
(optional) The position the vehicle shall arrive on
std::string routeid
The vehicle's route id.
std::string id
The vehicle's id.
std::vector< std::string > parkingBadges
The parking access rights.
std::vector< Stop > stops
List of the stops the vehicle will make, TraCI may add entries here.
int departEdge
(optional) The initial edge within the route of the vehicle
ArrivalPosDefinition arrivalPosProcedure
Information how the vehicle shall choose the arrival position.
std::string toTaz
The vehicle's destination zone (district)
double arrivalSpeed
(optional) The final speed of the vehicle (not used yet)
DepartDefinition departProcedure
Information how the vehicle shall choose the depart time.
int insertionChecks
bitset of InsertionCheck
int arrivalEdge
(optional) The final edge within the route of the vehicle
std::string fromTaz
The vehicle's origin zone (district)
DepartPosDefinition departPosProcedure
Information how the vehicle shall choose the departure position.
std::string line
The vehicle's line (mainly for public transport)
int containerNumber
The static number of containers in the vehicle when it departs.
RouteIndexDefinition departEdgeProcedure
Information how the vehicle's initial edge shall be chosen.
static std::string getEdgeIDFromLane(const std::string laneID)
return edge id when given the lane ID
static int getIndexFromLane(const std::string laneID)
return lane index when given the lane ID
SUMOTime sawBlockedStoppingPlace(const MSStoppingPlace *stoppingPlace, bool local) const
Get the time the StoppingPlace was confirmed to be blocked.
void rememberStoppingPlaceScore(const MSStoppingPlace *stoppingPlace, const std::string &score)
score only needed when running with gui
void rememberBlockedStoppingPlace(const MSStoppingPlace *stoppingPlace, bool local)
Store the time the StoppingPlace was confirmed to be blocked.
int size() const
returns the number of existing substrings
std::string get(int pos) const
returns the item at the given position
static bool startsWith(const std::string &str, const std::string prefix)
Checks whether a given string starts with the prefix.
static bool endsWith(const std::string &str, const std::string suffix)
Checks whether a given string ends with the suffix.
static int toInt(const std::string &sData)
converts a string into the integer value described by it by calling the char-type converter,...
A wrapper for a Command function.
#define UNUSED_PARAMETER(x)
#define DEBUG_COND
TRACI_CONST int ROUTING_MODE_AGGREGATED
TRACI_CONST int ROUTING_MODE_DEFAULT
TRACI_CONST int ROUTING_MODE_AGGREGATED_CUSTOM
TRACI_CONST int ROUTING_MODE_IGNORE_TRANSIENT_PERMISSIONS