Eclipse SUMO - Simulation of Urban MObility
Loading...
Searching...
No Matches
Helper.cpp
Go to the documentation of this file.
1/****************************************************************************/
2// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3// Copyright (C) 2017-2024 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/****************************************************************************/
20// C++ TraCI client API implementation
21/****************************************************************************/
22#include <config.h>
23
24#include <cstring>
27#include <microsim/MSNet.h>
31#include <microsim/MSEdge.h>
32#include <microsim/MSLane.h>
33#include <microsim/MSLink.h>
35#include <microsim/MSVehicle.h>
42#include <libsumo/TraCIDefs.h>
43#include <libsumo/BusStop.h>
44#include <libsumo/Calibrator.h>
46#include <libsumo/Edge.h>
47#ifdef HAVE_LIBSUMOGUI
48#include <libsumo/GUI.h>
49#endif
51#include <libsumo/Junction.h>
52#include <libsumo/Lane.h>
53#include <libsumo/LaneArea.h>
54#include <libsumo/MeanData.h>
57#include <libsumo/ParkingArea.h>
58#include <libsumo/Person.h>
59#include <libsumo/POI.h>
60#include <libsumo/Polygon.h>
61#include <libsumo/Rerouter.h>
62#include <libsumo/Route.h>
63#include <libsumo/RouteProbe.h>
64#include <libsumo/Simulation.h>
67#include <libsumo/Vehicle.h>
68#include <libsumo/VehicleType.h>
70#include "Helper.h"
71
72#define FAR_AWAY 1000.0
73
74//#define DEBUG_MOVEXY
75//#define DEBUG_MOVEXY_ANGLE
76//#define DEBUG_SURROUNDING
77
78namespace libsumo {
79// ===========================================================================
80// static member initializations
81// ===========================================================================
82std::vector<Subscription> Helper::mySubscriptions;
83Subscription* Helper::myLastContextSubscription = nullptr;
84std::map<int, std::shared_ptr<VariableWrapper> > Helper::myWrapper;
85Helper::VehicleStateListener Helper::myVehicleStateListener;
86Helper::TransportableStateListener Helper::myTransportableStateListener;
88std::map<std::string, MSVehicle*> Helper::myRemoteControlledVehicles;
89std::map<std::string, MSPerson*> Helper::myRemoteControlledPersons;
90
91
92// ===========================================================================
93// static member definitions
94// ===========================================================================
95
96void
98 if (veh != nullptr) {
99 if (veh->isVehicle()) {
100 std::cout << " '" << veh->getID() << "' on lane '" << ((SUMOVehicle*)veh)->getLane()->getID() << "'\n";
101 } else {
102 std::cout << " '" << veh->getID() << "' on edge '" << veh->getEdge()->getID() << "'\n";
103 }
104 }
105}
106
107
108void
109Helper::subscribe(const int commandId, const std::string& id, const std::vector<int>& variables,
110 const double beginTime, const double endTime, const libsumo::TraCIResults& params,
111 const int contextDomain, const double range) {
113 if (variables.empty()) {
114 for (std::vector<libsumo::Subscription>::iterator j = mySubscriptions.begin(); j != mySubscriptions.end();) {
115 if (j->id == id && j->commandId == commandId && j->contextDomain == contextDomain) {
116 j = mySubscriptions.erase(j);
117 } else {
118 ++j;
119 }
120 }
121 return;
122 }
123 std::vector<std::shared_ptr<tcpip::Storage> > parameters;
124 for (const int var : variables) {
125 const auto& p = params.find(var);
126 if (p == params.end()) {
127 parameters.push_back(std::make_shared<tcpip::Storage>());
128 } else {
129 parameters.push_back(libsumo::StorageHelper::toStorage(*p->second));
130 }
131 }
132 const SUMOTime begin = beginTime == INVALID_DOUBLE_VALUE ? 0 : TIME2STEPS(beginTime);
133 const SUMOTime end = endTime == INVALID_DOUBLE_VALUE || endTime > STEPS2TIME(SUMOTime_MAX) ? SUMOTime_MAX : TIME2STEPS(endTime);
134 libsumo::Subscription s(commandId, id, variables, parameters, begin, end, contextDomain, range);
135 if (commandId == libsumo::CMD_SUBSCRIBE_SIM_CONTEXT) {
136 s.range = std::numeric_limits<double>::max();
137 }
138 if (s.variables.size() == 1 && s.variables.front() == -1) {
139 s.variables.clear();
140 }
142 libsumo::Subscription* modifiedSubscription = nullptr;
143 needNewSubscription(s, mySubscriptions, modifiedSubscription);
144 if (modifiedSubscription->isVehicleToVehicleContextSubscription()
145 || modifiedSubscription->isVehicleToPersonContextSubscription()) {
146 // Set last modified vehicle context subscription active for filter modifications
147 myLastContextSubscription = modifiedSubscription;
148 }
149}
150
151
152void
154 for (auto& wrapper : myWrapper) {
155 wrapper.second->clear();
156 }
157 for (std::vector<libsumo::Subscription>::iterator i = mySubscriptions.begin(); i != mySubscriptions.end();) {
158 const libsumo::Subscription& s = *i;
159 const bool isArrivedVehicle = (s.commandId == CMD_SUBSCRIBE_VEHICLE_VARIABLE || s.commandId == CMD_SUBSCRIBE_VEHICLE_CONTEXT)
162 && MSNet::getInstance()->getPersonControl().get(s.id) == nullptr;
163 if (s.endTime < t || isArrivedVehicle || isArrivedPerson) {
164 i = mySubscriptions.erase(i);
165 continue;
166 }
167 ++i;
168 }
169 for (const libsumo::Subscription& s : mySubscriptions) {
170 if (s.beginTime <= t) {
172 }
173 }
174}
175
176
177bool
178Helper::needNewSubscription(libsumo::Subscription& s, std::vector<Subscription>& subscriptions, libsumo::Subscription*& modifiedSubscription) {
179 for (libsumo::Subscription& o : subscriptions) {
180 if (s.commandId == o.commandId && s.id == o.id &&
181 s.beginTime == o.beginTime && s.endTime == o.endTime &&
182 s.contextDomain == o.contextDomain && s.range == o.range) {
183 std::vector<std::shared_ptr<tcpip::Storage> >::const_iterator k = s.parameters.begin();
184 for (const int v : s.variables) {
185 const int offset = (int)(std::find(o.variables.begin(), o.variables.end(), v) - o.variables.begin());
186 if (offset == (int)o.variables.size() || o.parameters[offset]->size() != (*k)->size() || !std::equal((*k)->begin(), (*k)->end(), o.parameters[offset]->begin())) {
187 o.variables.push_back(v);
188 o.parameters.push_back(*k);
189 }
190 ++k;
191 }
192 modifiedSubscription = &o;
193 return false;
194 }
195 }
196 subscriptions.push_back(s);
197 modifiedSubscription = &subscriptions.back();
198 return true;
199}
200
201
202void
207
208
211 if (myLastContextSubscription != nullptr) {
213 } else {
214 // The following code relies on the fact that the filter is 2^(filterType-1),
215 // see Subscription.h and the corresponding TraCIConstants.h.
216 // It is only for getting similar error messages with libsumo and traci.
217 int index = (int)filter;
218 int filterType = 0;
219 if (index != 0) {
220 ++filterType;
221 while (index >>= 1) {
222 ++filterType;
223 }
224 }
225 throw TraCIException("No previous vehicle context subscription exists to apply filter type " + toHex(filterType, 2));
226 }
228}
229
230
231void
233 const int getCommandId = s.contextDomain > 0 ? s.contextDomain : s.commandId - 0x30;
234 std::set<std::string> objIDs;
235 if (s.contextDomain > 0) {
236 if ((s.activeFilters & SUBS_FILTER_NO_RTREE) == 0) {
237 PositionVector shape;
238 findObjectShape(s.commandId, s.id, shape);
239 collectObjectIDsInRange(s.contextDomain, shape, s.range, objIDs);
240 }
241 applySubscriptionFilters(s, objIDs);
242 } else {
243 objIDs.insert(s.id);
244 }
245 if (myWrapper.empty()) {
246 myWrapper[libsumo::CMD_GET_BUSSTOP_VARIABLE] = BusStop::makeWrapper();
247 myWrapper[libsumo::CMD_GET_CALIBRATOR_VARIABLE] = Calibrator::makeWrapper();
248 myWrapper[libsumo::CMD_GET_CHARGINGSTATION_VARIABLE] = ChargingStation::makeWrapper();
249 myWrapper[libsumo::CMD_GET_EDGE_VARIABLE] = Edge::makeWrapper();
250#ifdef HAVE_LIBSUMOGUI
251 myWrapper[libsumo::CMD_GET_GUI_VARIABLE] = GUI::makeWrapper();
252#endif
253 myWrapper[libsumo::CMD_GET_INDUCTIONLOOP_VARIABLE] = InductionLoop::makeWrapper();
254 myWrapper[libsumo::CMD_GET_JUNCTION_VARIABLE] = Junction::makeWrapper();
255 myWrapper[libsumo::CMD_GET_LANE_VARIABLE] = Lane::makeWrapper();
256 myWrapper[libsumo::CMD_GET_LANEAREA_VARIABLE] = LaneArea::makeWrapper();
257 myWrapper[libsumo::CMD_GET_MEANDATA_VARIABLE] = MeanData::makeWrapper();
258 myWrapper[libsumo::CMD_GET_MULTIENTRYEXIT_VARIABLE] = MultiEntryExit::makeWrapper();
259 myWrapper[libsumo::CMD_GET_OVERHEADWIRE_VARIABLE] = OverheadWire::makeWrapper();
260 myWrapper[libsumo::CMD_GET_PARKINGAREA_VARIABLE] = ParkingArea::makeWrapper();
261 myWrapper[libsumo::CMD_GET_PERSON_VARIABLE] = Person::makeWrapper();
262 myWrapper[libsumo::CMD_GET_POI_VARIABLE] = POI::makeWrapper();
263 myWrapper[libsumo::CMD_GET_POLYGON_VARIABLE] = Polygon::makeWrapper();
264 myWrapper[libsumo::CMD_GET_REROUTER_VARIABLE] = Rerouter::makeWrapper();
265 myWrapper[libsumo::CMD_GET_ROUTE_VARIABLE] = Route::makeWrapper();
266 myWrapper[libsumo::CMD_GET_ROUTEPROBE_VARIABLE] = RouteProbe::makeWrapper();
267 myWrapper[libsumo::CMD_GET_SIM_VARIABLE] = Simulation::makeWrapper();
268 myWrapper[libsumo::CMD_GET_TL_VARIABLE] = TrafficLight::makeWrapper();
269 myWrapper[libsumo::CMD_GET_VARIABLESPEEDSIGN_VARIABLE] = VariableSpeedSign::makeWrapper();
270 myWrapper[libsumo::CMD_GET_VEHICLE_VARIABLE] = Vehicle::makeWrapper();
271 myWrapper[libsumo::CMD_GET_VEHICLETYPE_VARIABLE] = VehicleType::makeWrapper();
272 }
273 auto wrapper = myWrapper.find(getCommandId);
274 if (wrapper == myWrapper.end()) {
275 throw TraCIException("Unsupported command specified");
276 }
277 std::shared_ptr<VariableWrapper> handler = wrapper->second;
278 VariableWrapper* container = handler.get();
279 if (s.contextDomain > 0) {
280 auto containerWrapper = myWrapper.find(s.commandId + 0x20);
281 if (containerWrapper == myWrapper.end()) {
282 throw TraCIException("Unsupported domain specified");
283 }
284 container = containerWrapper->second.get();
285 container->setContext(&s.id);
286 } else {
287 container->setContext(nullptr);
288 }
289 for (const std::string& objID : objIDs) {
290 if (!s.variables.empty()) {
291 std::vector<std::shared_ptr<tcpip::Storage> >::const_iterator k = s.parameters.begin();
292 for (const int variable : s.variables) {
293 if (s.contextDomain > 0 && variable == libsumo::TRACI_ID_LIST) {
294 container->empty(objID);
295 } else {
296 (*k)->resetPos();
297 handler->handle(objID, variable, container, k->get());
298 ++k;
299 }
300 }
301 } else {
302 if (s.contextDomain == 0 && getCommandId == libsumo::CMD_GET_VEHICLE_VARIABLE) {
303 // default for vehicles is edge id and lane position
304 handler->handle(objID, VAR_ROAD_ID, container, nullptr);
305 handler->handle(objID, VAR_LANEPOSITION, container, nullptr);
306 } else if (s.contextDomain > 0) {
307 // default for contexts is an empty map (similar to id list)
308 container->empty(objID);
309 } else if (!handler->handle(objID, libsumo::LAST_STEP_VEHICLE_NUMBER, container, nullptr)) {
310 // default for detectors is vehicle number, for all others id list
311 handler->handle(objID, libsumo::TRACI_ID_LIST, container, nullptr);
312 }
313 }
314 }
315}
316
317
318void
319Helper::fuseLaneCoverage(std::shared_ptr<LaneCoverageInfo> aggregatedLaneCoverage, const std::shared_ptr<LaneCoverageInfo> newLaneCoverage) {
320 for (auto& p : *newLaneCoverage) {
321 const MSLane* lane = p.first;
322 if (aggregatedLaneCoverage->find(lane) == aggregatedLaneCoverage->end()) {
323 // Lane has no coverage in aggregatedLaneCoverage, yet
324 (*aggregatedLaneCoverage)[lane] = (*newLaneCoverage)[lane];
325 } else {
326 // Lane is covered in aggregatedLaneCoverage as well
327 std::pair<double, double>& range1 = (*aggregatedLaneCoverage)[lane];
328 std::pair<double, double>& range2 = (*newLaneCoverage)[lane];
329 std::pair<double, double> hull = std::make_pair(MIN2(range1.first, range2.first), MAX2(range1.second, range2.second));
330 (*aggregatedLaneCoverage)[lane] = hull;
331 }
332 }
333}
334
335
339 for (int i = 0; i < (int)positionVector.size(); ++i) {
340 tp.value.push_back(makeTraCIPosition(positionVector[i]));
341 }
342 return tp;
343}
344
345
349 for (const TraCIPosition& pos : vector.value) {
350 if (std::isnan(pos.x) || std::isnan(pos.y)) {
351 throw libsumo::TraCIException("NaN-Value in shape.");
352 }
353 pv.push_back(Position(pos.x, pos.y));
354 }
355 return pv;
356}
357
358
361 TraCIColor tc;
362 tc.a = color.alpha();
363 tc.b = color.blue();
364 tc.g = color.green();
365 tc.r = color.red();
366 return tc;
367}
368
369
372 return RGBColor((unsigned char)c.r, (unsigned char)c.g, (unsigned char)c.b, (unsigned char)c.a);
373}
374
375
377Helper::makeTraCIPosition(const Position& position, const bool includeZ) {
379 p.x = position.x();
380 p.y = position.y();
381 p.z = includeZ ? position.z() : INVALID_DOUBLE_VALUE;
382 return p;
383}
384
385
388 return Position(tpos.x, tpos.y, tpos.z);
389}
390
391
392MSEdge*
393Helper::getEdge(const std::string& edgeID) {
394 MSEdge* edge = MSEdge::dictionary(edgeID);
395 if (edge == nullptr) {
396 throw TraCIException("Referenced edge '" + edgeID + "' is not known.");
397 }
398 return edge;
399}
400
401
402const MSLane*
403Helper::getLaneChecking(const std::string& edgeID, int laneIndex, double pos) {
404 const MSEdge* edge = MSEdge::dictionary(edgeID);
405 if (edge == nullptr) {
406 throw TraCIException("Unknown edge " + edgeID);
407 }
408 if (laneIndex < 0 || laneIndex >= (int)edge->getLanes().size()) {
409 throw TraCIException("Invalid lane index for " + edgeID);
410 }
411 const MSLane* lane = edge->getLanes()[laneIndex];
412 if (pos < 0 || pos > lane->getLength()) {
413 throw TraCIException("Position on lane invalid");
414 }
415 return lane;
416}
417
418
419std::pair<MSLane*, double>
421 const PositionVector shape({ pos });
422 std::pair<MSLane*, double> result(nullptr, -1);
423 double range = 1000.;
424 const Boundary& netBounds = GeoConvHelper::getFinal().getConvBoundary();
425 const double maxRange = MAX2(1001., netBounds.getWidth() + netBounds.getHeight() + netBounds.distanceTo2D(pos));
426 while (range < maxRange) {
427 std::set<const Named*> lanes;
429 double minDistance = std::numeric_limits<double>::max();
430 for (const Named* named : lanes) {
431 MSLane* lane = const_cast<MSLane*>(dynamic_cast<const MSLane*>(named));
432 if (lane->allowsVehicleClass(vClass)) {
433 // @todo this may be a place where 3D is required but 2D is used
434 const double newDistance = lane->getShape().distance2D(pos);
435 if (newDistance < minDistance ||
436 (newDistance == minDistance
437 && result.first != nullptr
438 && lane->getID() < result.first->getID())) {
439 minDistance = newDistance;
440 result.first = lane;
441 }
442 }
443 }
444 if (minDistance < std::numeric_limits<double>::max()) {
445 result.second = result.first->interpolateGeometryPosToLanePos(result.first->getShape().nearest_offset_to_point2D(pos, false));
446 break;
447 }
448 range *= 2;
449 }
450 return result;
451}
452
453
454double
455Helper::getDrivingDistance(std::pair<const MSLane*, double>& roadPos1, std::pair<const MSLane*, double>& roadPos2) {
456 if (roadPos1.first == roadPos2.first && roadPos1.second <= roadPos2.second) {
457 // same edge
458 return roadPos2.second - roadPos1.second;
459 }
460 double distance = 0.0;
461 ConstMSEdgeVector newRoute;
462 while (roadPos2.first->isInternal() && roadPos2.first != roadPos1.first) {
463 distance += roadPos2.second;
464 roadPos2.first = roadPos2.first->getLogicalPredecessorLane();
465 roadPos2.second = roadPos2.first->getLength();
466 }
467 MSNet::getInstance()->getRouterTT(0).compute(&roadPos1.first->getEdge(), &roadPos2.first->getEdge(), nullptr, SIMSTEP, newRoute, true);
468 if (newRoute.empty()) {
470 }
471 MSRoute route("", newRoute, false, nullptr, std::vector<SUMOVehicleParameter::Stop>());
472 return distance + route.getDistanceBetween(roadPos1.second, roadPos2.second, roadPos1.first, roadPos2.first);
473}
474
475
477Helper::getVehicle(const std::string& id) {
479 if (sumoVehicle == nullptr) {
480 throw TraCIException("Vehicle '" + id + "' is not known.");
481 }
482 MSBaseVehicle* v = dynamic_cast<MSBaseVehicle*>(sumoVehicle);
483 if (v == nullptr) {
484 throw TraCIException("Vehicle '" + id + "' is not a proper vehicle.");
485 }
486 return v;
487}
488
489
491Helper::getPerson(const std::string& personID) {
493 MSPerson* p = dynamic_cast<MSPerson*>(c.get(personID));
494 if (p == nullptr) {
495 throw TraCIException("Person '" + personID + "' is not known");
496 }
497 return p;
498}
499
501Helper::getTrafficObject(int domain, const std::string& id) {
502 if (domain == CMD_GET_VEHICLE_VARIABLE) {
503 return getVehicle(id);
504 } else if (domain == CMD_GET_PERSON_VARIABLE) {
505 return getPerson(id);
506 } else {
507 throw TraCIException("Cannot retrieve traffic object for domain " + toString(domain));
508 }
509}
510
511const MSVehicleType&
512Helper::getVehicleType(const std::string& vehicleID) {
513 return getVehicle(vehicleID)->getVehicleType();
514}
515
516
518Helper::getTLS(const std::string& id) {
519 if (!MSNet::getInstance()->getTLSControl().knows(id)) {
520 throw TraCIException("Traffic light '" + id + "' is not known");
521 }
522 return MSNet::getInstance()->getTLSControl().get(id);
523}
524
525
527Helper::getStoppingPlace(const std::string& id, const SumoXMLTag type) {
529 if (s == nullptr) {
530 throw TraCIException(toString(type) + " '" + id + "' is not known");
531 }
532 return s;
533}
534
535
537Helper::buildStopParameters(const std::string& edgeOrStoppingPlaceID,
538 double pos, int laneIndex, double startPos, int flags, double duration, double until) {
540 try {
541 checkTimeBounds(duration);
542 checkTimeBounds(until);
543 } catch (ProcessError&) {
544 throw TraCIException("Duration or until parameter exceed the time value range.");
545 }
546 newStop.duration = duration == INVALID_DOUBLE_VALUE ? SUMOTime_MAX : TIME2STEPS(duration);
547 newStop.until = until == INVALID_DOUBLE_VALUE ? -1 : TIME2STEPS(until);
548 newStop.index = STOP_INDEX_FIT;
549 if (newStop.duration >= 0) {
551 }
552 if (newStop.until >= 0) {
553 newStop.parametersSet |= STOP_UNTIL_SET;
554 }
555 if ((flags & 1) != 0) {
558 }
559 if ((flags & 2) != 0) {
560 newStop.triggered = true;
562 }
563 if ((flags & 4) != 0) {
564 newStop.containerTriggered = true;
566 }
567
568 SumoXMLTag stoppingPlaceType = SUMO_TAG_NOTHING;
569 if ((flags & 8) != 0) {
570 stoppingPlaceType = SUMO_TAG_BUS_STOP;
571 }
572 if ((flags & 16) != 0) {
573 stoppingPlaceType = SUMO_TAG_CONTAINER_STOP;
574 }
575 if ((flags & 32) != 0) {
576 stoppingPlaceType = SUMO_TAG_CHARGING_STATION;
577 }
578 if ((flags & 64) != 0) {
579 stoppingPlaceType = SUMO_TAG_PARKING_AREA;
580 }
581 if ((flags & 128) != 0) {
582 stoppingPlaceType = SUMO_TAG_OVERHEAD_WIRE_SEGMENT;
583 }
584
585 if (stoppingPlaceType != SUMO_TAG_NOTHING) {
586 MSStoppingPlace* bs = MSNet::getInstance()->getStoppingPlace(edgeOrStoppingPlaceID, stoppingPlaceType);
587 if (bs == nullptr) {
588 throw TraCIException("The " + toString(stoppingPlaceType) + " '" + edgeOrStoppingPlaceID + "' is not known");
589 }
590 newStop.lane = bs->getLane().getID();
591 newStop.edge = bs->getLane().getEdge().getID();
592 newStop.endPos = bs->getEndLanePosition();
593 newStop.startPos = bs->getBeginLanePosition();
594 switch (stoppingPlaceType) {
596 newStop.busstop = edgeOrStoppingPlaceID;
597 break;
599 newStop.containerstop = edgeOrStoppingPlaceID;
600 break;
602 newStop.chargingStation = edgeOrStoppingPlaceID;
603 break;
605 newStop.parkingarea = edgeOrStoppingPlaceID;
606 break;
608 newStop.overheadWireSegment = edgeOrStoppingPlaceID;
609 break;
610 default:
611 throw TraCIException("Unknown stopping place type '" + toString(stoppingPlaceType) + "'.");
612 }
613 } else {
614 if (startPos == INVALID_DOUBLE_VALUE) {
615 startPos = MAX2(0.0, pos - POSITION_EPS);
616 }
617 if (startPos < 0.) {
618 throw TraCIException("Position on lane must not be negative.");
619 }
620 if (pos < startPos) {
621 throw TraCIException("End position on lane must be after start position.");
622 }
623 // get the actual lane that is referenced by laneIndex
624 MSEdge* road = MSEdge::dictionary(edgeOrStoppingPlaceID);
625 if (road == nullptr) {
626 throw TraCIException("Edge '" + edgeOrStoppingPlaceID + "' is not known.");
627 }
628 const std::vector<MSLane*>& allLanes = road->getLanes();
629 if ((laneIndex < 0) || laneIndex >= (int)(allLanes.size())) {
630 throw TraCIException("No lane with index '" + toString(laneIndex) + "' on edge '" + edgeOrStoppingPlaceID + "'.");
631 }
632 newStop.lane = allLanes[laneIndex]->getID();
633 newStop.edge = allLanes[laneIndex]->getEdge().getID();
634 newStop.endPos = pos;
635 newStop.startPos = startPos;
637 }
638 return newStop;
639}
640
641
644 std::string stoppingPlaceID = "";
645 if (stopPar.busstop != "") {
646 stoppingPlaceID = stopPar.busstop;
647 }
648 if (stopPar.containerstop != "") {
649 stoppingPlaceID = stopPar.containerstop;
650 }
651 if (stopPar.parkingarea != "") {
652 stoppingPlaceID = stopPar.parkingarea;
653 }
654 if (stopPar.chargingStation != "") {
655 stoppingPlaceID = stopPar.chargingStation;
656 }
657 if (stopPar.overheadWireSegment != "") {
658 stoppingPlaceID = stopPar.overheadWireSegment;
659 }
660
661 return TraCINextStopData(stopPar.lane,
662 stopPar.startPos,
663 stopPar.endPos,
664 stoppingPlaceID,
665 stopPar.getFlags(),
666 // negative duration is permitted to indicate that a vehicle cannot
667 // re-enter traffic after parking
668 stopPar.duration != -1 ? STEPS2TIME(stopPar.duration) : INVALID_DOUBLE_VALUE,
669 stopPar.until >= 0 ? STEPS2TIME(stopPar.until) : INVALID_DOUBLE_VALUE,
670 stopPar.arrival >= 0 ? STEPS2TIME(stopPar.arrival) : INVALID_DOUBLE_VALUE,
671 stopPar.started >= 0 ? STEPS2TIME(stopPar.started) : INVALID_DOUBLE_VALUE,
672 stopPar.ended >= 0 ? STEPS2TIME(stopPar.ended) : INVALID_DOUBLE_VALUE,
673 stopPar.split,
674 stopPar.join,
675 stopPar.actType,
676 stopPar.tripId,
677 stopPar.line,
678 stopPar.speed);
679}
680
681
682void
684 // clean up NamedRTrees
685 InductionLoop::cleanup();
686 Junction::cleanup();
687 LaneArea::cleanup();
688 POI::cleanup();
689 Polygon::cleanup();
692 delete myLaneTree;
693 myLaneTree = nullptr;
694}
695
696
697void
704
705
706const std::vector<std::string>&
710
711
712const std::vector<std::string>&
716
717
718void
721 i.second.clear();
722 }
724 i.second.clear();
725 }
726}
727
728
731 try {
732 return c->getCurrentStateInterval();
733 } catch (ProcessError& e) {
734 throw TraCIException(e.what());
735 }
736}
737
738
739void
740Helper::findObjectShape(int domain, const std::string& id, PositionVector& shape) {
741 switch (domain) {
744 shape.push_back(stop->getLane().getShape().positionAtOffset(stop->getBeginLanePosition()));
745 shape.push_back(stop->getLane().getShape().positionAtOffset(stop->getEndLanePosition()));
746 break;
747 }
749 MSCalibrator* const calib = Calibrator::getCalibrator(id);
750 shape.push_back(calib->getLane()->getShape()[0]);
751 break;
752 }
755 shape.push_back(stop->getLane().getShape().positionAtOffset(stop->getBeginLanePosition()));
756 shape.push_back(stop->getLane().getShape().positionAtOffset(stop->getEndLanePosition()));
757 break;
758 }
760 Edge::storeShape(id, shape);
761 break;
763 InductionLoop::storeShape(id, shape);
764 break;
766 Junction::storeShape(id, shape);
767 break;
769 Lane::storeShape(id, shape);
770 break;
772 LaneArea::storeShape(id, shape);
773 break;
775 MSE3Collector* const det = MultiEntryExit::getDetector(id);
776 for (const MSCrossSection& cs : det->getEntries()) {
777 shape.push_back(cs.myLane->getShape().positionAtOffset(cs.myPosition));
778 }
779 for (const MSCrossSection& cs : det->getExits()) {
780 shape.push_back(cs.myLane->getShape().positionAtOffset(cs.myPosition));
781 }
782 break;
783 }
786 shape.push_back(stop->getLane().getShape().positionAtOffset(stop->getBeginLanePosition()));
787 shape.push_back(stop->getLane().getShape().positionAtOffset(stop->getEndLanePosition()));
788 break;
789 }
791 Person::storeShape(id, shape);
792 break;
794 POI::storeShape(id, shape);
795 break;
797 Polygon::storeShape(id, shape);
798 break;
800 Vehicle::storeShape(id, shape);
801 break;
802 default:
803 Simulation::storeShape(shape);
804 break;
805 }
806}
807
808
809void
810Helper::collectObjectIDsInRange(int domain, const PositionVector& shape, double range, std::set<std::string>& into) {
811 std::set<const Named*> objects;
812 collectObjectsInRange(domain, shape, range, objects);
813 for (const Named* obj : objects) {
814 into.insert(obj->getID());
815 }
816}
817
818
819void
820Helper::collectObjectsInRange(int domain, const PositionVector& shape, double range, std::set<const Named*>& into) {
821 const Boundary b = shape.getBoxBoundary().grow(range);
822 const float cmin[2] = {(float) b.xmin(), (float) b.ymin()};
823 const float cmax[2] = {(float) b.xmax(), (float) b.ymax()};
824 switch (domain) {
826 for (const auto& stop : MSNet::getInstance()->getStoppingPlaces(SUMO_TAG_BUS_STOP)) {
827 if (shape.distance2D(stop.second->getCenterPos()) <= range) {
828 into.insert(stop.second);
829 }
830 }
831 break;
834 if (shape.distance2D(stop.second->getCenterPos()) <= range) {
835 into.insert(stop.second);
836 }
837 }
838 break;
840 for (const auto& calib : MSCalibrator::getInstances()) {
841 if (shape.distance2D(calib.second->getLane()->getShape()[0]) <= range) {
842 into.insert(calib.second);
843 }
844 }
845 break;
847 InductionLoop::getTree()->Search(cmin, cmax, Named::StoringVisitor(into));
848 break;
850 Junction::getTree()->Search(cmin, cmax, Named::StoringVisitor(into));
851 break;
853 LaneArea::getTree()->Search(cmin, cmax, Named::StoringVisitor(into));
854 break;
856 for (const auto& stop : MSNet::getInstance()->getStoppingPlaces(SUMO_TAG_PARKING_AREA)) {
857 if (shape.distance2D(stop.second->getCenterPos()) <= range) {
858 into.insert(stop.second);
859 }
860 }
861 break;
862 }
864 POI::getTree()->Search(cmin, cmax, Named::StoringVisitor(into));
865 break;
867 Polygon::getTree()->Search(cmin, cmax, Named::StoringVisitor(into));
868 break;
873 if (myLaneTree == nullptr) {
876 }
877 MSLane::StoringVisitor lsv(into, shape, range, domain);
878 myLaneTree->Search(cmin, cmax, lsv);
879 }
880 break;
881 default:
882 throw TraCIException("Infeasible context domain (" + toString(domain) + ")");
883 break;
884 }
885}
886
887
888
889void
890Helper::applySubscriptionFilters(const Subscription& s, std::set<std::string>& objIDs) {
891#ifdef DEBUG_SURROUNDING
892 MSBaseVehicle* _veh = getVehicle(s.id);
893 std::cout << SIMTIME << " applySubscriptionFilters for vehicle '" << _veh->getID() << "' on lane '" << _veh->getLane()->getID() << "'"
894 << "\n on edge '" << _veh->getLane()->getEdge().getID() << "' (" << toString(_veh->getLane()->getEdge().getLanes()) << ")\n"
895 << "objIDs = " << toString(objIDs) << std::endl;
896#endif
897
898 if (s.activeFilters == 0) {
899 // No filters set
900 return;
901 }
902
903 MSVehicle* v = dynamic_cast<MSVehicle*>(getVehicle(s.id));
904
905 // Whether vehicles on opposite lanes shall be taken into account
906 const bool disregardOppositeDirection = (s.activeFilters & SUBS_FILTER_NOOPPOSITE) != 0;
907
908 // Check filter specification consistency
909 if (disregardOppositeDirection && (s.activeFilters & SUBS_FILTER_NO_RTREE) == 0) {
910 WRITE_WARNINGF(TL("Ignoring veh '%' no-opposite subscription filter for geographic range object collection. Consider using the 'lanes' filter."), v->getID())
911 }
912 // TODO: Treat case, where ego vehicle is currently on opposite lane
913
914 std::set<const SUMOTrafficObject*> vehs;
916 // Set defaults for upstream/downstream/lateral distances
917 double downstreamDist = s.range, upstreamDist = s.range, lateralDist = s.range;
919 // Specifies maximal downstream distance for vehicles in context subscription result
920 downstreamDist = s.filterDownstreamDist;
921 }
923 // Specifies maximal downstream distance for vehicles in context subscription result
924 upstreamDist = s.filterUpstreamDist;
925 }
927 // Specifies maximal lateral distance for vehicles in context subscription result
928 lateralDist = s.filterLateralDist;
929 }
930 if (v == nullptr) {
931 throw TraCIException("Subscription filter not yet implemented for meso vehicle");
932 }
933 if (!v->isOnRoad()) {
934 return;
935 }
936 const MSLane* vehLane = v->getLane();
937 if (vehLane == nullptr) {
938 return;
939 }
940 MSEdge* vehEdge = &vehLane->getEdge();
941 std::vector<int> filterLanes;
942 if ((s.activeFilters & SUBS_FILTER_LANES) == 0) {
943 // No lane indices are specified (but downstream and/or upstream distance)
944 // -> use only vehicle's current lane as origin for the searches
945 filterLanes = {0};
946 // Lane indices must be specified when leader/follower information is requested.
947 assert((s.activeFilters & SUBS_FILTER_LEAD_FOLLOW) == 0);
948 } else {
949 filterLanes = s.filterLanes;
950 }
951
952#ifdef DEBUG_SURROUNDING
953 std::cout << "Filter lanes: " << toString(filterLanes) << std::endl;
954 std::cout << "Downstream distance: " << downstreamDist << std::endl;
955 std::cout << "Upstream distance: " << upstreamDist << std::endl;
956 std::cout << "Lateral distance: " << lateralDist << std::endl;
957#endif
958
959 if ((s.activeFilters & SUBS_FILTER_MANEUVER) != 0) {
960 // Maneuver filters disables road net search for all surrounding vehicles
961 if ((s.activeFilters & SUBS_FILTER_LEAD_FOLLOW) != 0) {
962 // Return leader and follower on the specified lanes in context subscription result.
963 for (int offset : filterLanes) {
964 MSLane* lane = v->getLane()->getParallelLane(offset, false);
965 if (lane != nullptr) {
966 // this is a non-opposite lane
967 MSVehicle* leader = lane->getLeader(v, v->getPositionOnLane(), v->getBestLanesContinuation(lane), downstreamDist).first;
968 MSVehicle* follower = lane->getFollower(v, v->getPositionOnLane(), upstreamDist,
970 vehs.insert(vehs.end(), leader);
971 vehs.insert(vehs.end(), follower);
972
973#ifdef DEBUG_SURROUNDING
974 std::cout << "Lane at index " << offset << ": '" << lane->getID() << std::endl;
975 std::cout << "Leader: '" << (leader != nullptr ? leader->getID() : "NULL") << "'" << std::endl;
976 std::cout << "Follower: '" << (follower != nullptr ? follower->getID() : "NULL") << "'" << std::endl;
977#endif
978
979 } else if (!disregardOppositeDirection && offset > 0) { // TODO: offset<0 may indicate opposite query when vehicle is on opposite itself
980 // check whether ix points to an opposite lane
981 const MSEdge* opposite = vehEdge->getOppositeEdge();
982 if (opposite == nullptr) {
983#ifdef DEBUG_SURROUNDING
984 std::cout << "No lane at index " << offset << std::endl;
985#endif
986 // no opposite edge
987 continue;
988 }
989 // Index of opposite lane at relative offset
990 const int ix_opposite = (int)opposite->getLanes().size() - 1 - (vehLane->getIndex() + offset - (int)vehEdge->getLanes().size());
991 if (ix_opposite < 0) {
992#ifdef DEBUG_SURROUNDING
993 std::cout << "No lane on opposite at index " << ix_opposite << std::endl;
994#endif
995 // no opposite edge
996 continue;
997 }
998 lane = opposite->getLanes()[ix_opposite];
999 // Search vehs along opposite lanes (swap upstream and downstream distance)
1000 // XXX transformations for curved geometries
1001 double posOnOpposite = MAX2(0., opposite->getLength() - v->getPositionOnLane());
1002 // Get leader on opposite
1003 vehs.insert(vehs.end(), lane->getFollower(v, posOnOpposite, downstreamDist, MSLane::MinorLinkMode::FOLLOW_NEVER).first);
1004 // Get follower (no search on consecutive lanes
1005 vehs.insert(vehs.end(), lane->getLeader(v, posOnOpposite - v->getLength(), std::vector<MSLane*>()).first);
1006 }
1007 }
1008 }
1009
1013 applySubscriptionFilterLanes(s, vehs, filterLanes, downstreamDist, upstreamDist, disregardOppositeDirection);
1014 }
1016 applySubscriptionFilterLateralDistance(s, vehs, downstreamDist, upstreamDist, lateralDist);
1017 }
1018 }
1019#ifdef DEBUG_SURROUNDING
1020 std::cout << SIMTIME << " applySubscriptionFilters() for veh '" << v->getID() << "'. Found the following vehicles:\n";
1021 for (auto veh : vehs) {
1022 debugPrint(veh);
1023 }
1024#endif
1025 } else if (s.activeFilters & SUBS_FILTER_LATERAL_DIST) {
1026 applySubscriptionFilterLateralDistance(s, vehs, downstreamDist, upstreamDist, lateralDist);
1027 } else {
1028 // No maneuver or lateral distance filters requested, but only lanes filter (directly, or indirectly by specifying downstream or upstream distance)
1029 applySubscriptionFilterLanes(s, vehs, filterLanes, downstreamDist, upstreamDist, disregardOppositeDirection);
1030 }
1031 // Write vehs IDs in objIDs
1032 for (const SUMOTrafficObject* veh : vehs) {
1033 if (veh != nullptr) {
1034 objIDs.insert(objIDs.end(), veh->getID());
1035 }
1036 }
1037 }
1038
1040 // Only return vehicles of the given vClass in context subscription result
1041 auto i = objIDs.begin();
1042 while (i != objIDs.end()) {
1043 MSBaseVehicle* veh = getVehicle(*i);
1044 if ((veh->getVehicleType().getVehicleClass() & s.filterVClasses) == 0) {
1045 i = objIDs.erase(i);
1046 } else {
1047 ++i;
1048 }
1049 }
1050 }
1052 // Only return vehicles of the given vType in context subscription result
1053 auto i = objIDs.begin();
1054 while (i != objIDs.end()) {
1055 MSBaseVehicle* veh = getVehicle(*i);
1056 if (s.filterVTypes.find(veh->getVehicleType().getID()) == s.filterVTypes.end()) {
1057 i = objIDs.erase(i);
1058 } else {
1059 ++i;
1060 }
1061 }
1062 }
1064 // Only return vehicles within field of vision in context subscription result
1066 }
1067}
1068
1069void
1070Helper::applySubscriptionFilterLanes(const Subscription& s, std::set<const SUMOTrafficObject*>& vehs, std::vector<int>& filterLanes, double downstreamDist,
1071 double upstreamDist, bool disregardOppositeDirection) {
1073 WRITE_WARNINGF(TL("Lanes filter is only feasible for context domain 'vehicle' (current is '%'), ignoring filter..."), toHex(s.contextDomain, 2));
1074 return;
1075 }
1076 assert(filterLanes.size() > 0);
1077 MSVehicle* v = dynamic_cast<MSVehicle*>(getVehicle(s.id));
1078 const MSLane* vehLane = v->getLane();
1079 MSEdge* vehEdge = &vehLane->getEdge();
1080 // This is to remember the lanes checked in the driving direction of the vehicle (their opposites can be added in a second pass)
1081 auto checkedLanesInDrivingDir = std::make_shared<LaneCoverageInfo>();
1082 for (int offset : filterLanes) {
1083 MSLane* lane = vehLane->getParallelLane(offset, false);
1084 if (lane != nullptr) {
1085#ifdef DEBUG_SURROUNDING
1086 std::cout << "Checking for surrounding vehicles starting on lane '" << lane->getID() << "' at index " << offset << std::endl;
1087#endif
1088 // Search vehs along this lane
1089 // (Coverage info is collected per origin lane since lanes reached from neighboring lanes may have different distances
1090 // and aborting at previously scanned when coming from a closer origin may prevent scanning of parts that should be included.)
1091 std::shared_ptr<LaneCoverageInfo> checkedLanes = std::make_shared<LaneCoverageInfo>();
1092 const std::set<MSVehicle*> new_vehs =
1093 lane->getSurroundingVehicles(v->getPositionOnLane(), downstreamDist, upstreamDist + v->getLength(), checkedLanes);
1094 vehs.insert(new_vehs.begin(), new_vehs.end());
1095 fuseLaneCoverage(checkedLanesInDrivingDir, checkedLanes);
1096 } else if (!disregardOppositeDirection && offset > 0) {
1097 // Check opposite edge, too
1098 assert(vehLane->getIndex() + offset >= (int)vehEdge->getLanes().size()); // index points beyond this edge
1099 const MSEdge* opposite = vehEdge->getOppositeEdge();
1100 if (opposite == nullptr) {
1101#ifdef DEBUG_SURROUNDING
1102 std::cout << "No opposite edge, thus no lane at index " << offset << std::endl;
1103#endif
1104 // no opposite edge
1105 continue;
1106 }
1107 // Index of opposite lane at relative offset
1108 const int ix_opposite = (int)opposite->getLanes().size() - 1 - (vehLane->getIndex() + offset - (int)vehEdge->getLanes().size());
1109 if (ix_opposite < 0) {
1110#ifdef DEBUG_SURROUNDING
1111 std::cout << "No lane on opposite at index " << ix_opposite << std::endl;
1112#endif
1113 // no opposite edge
1114 continue;
1115 }
1116 lane = opposite->getLanes()[ix_opposite];
1117 // Search vehs along opposite lanes (swap upstream and downstream distance)
1118 const std::set<MSVehicle*> new_vehs = lane->getSurroundingVehicles(lane->getLength() - v->getPositionOnLane(), upstreamDist + v->getLength(),
1119 downstreamDist, std::make_shared<LaneCoverageInfo>());
1120 vehs.insert(new_vehs.begin(), new_vehs.end());
1121 }
1122#ifdef DEBUG_SURROUNDING
1123 else {
1124 std::cout << "No lane at index " << offset << std::endl;
1125 }
1126#endif
1127
1128 if (!disregardOppositeDirection) {
1129 // If opposite should be checked, do this for each lane of the search tree in checkedLanesInDrivingDir
1130 // (For instance, some opposite lanes of these would not be obtained if the ego lane does not have an opposite.)
1131
1132 // Number of opposite lanes to be checked (assumes filterLanes.size()>0, see assertion above) determined as hypothetical offset
1133 // overlap into opposing edge from the vehicle's current lane.
1134 // TODO: offset<0 may indicate opposite query when vehicle is on opposite itself (-> use min_element(filterLanes...) instead, etc)
1135 const int nOpp = MAX2(0, (*std::max_element(filterLanes.begin(), filterLanes.end())) - ((int)vehEdge->getLanes().size() - 1 - vehLane->getIndex()));
1136 // Collect vehicles from opposite lanes
1137 if (nOpp > 0) {
1138 for (auto& laneCov : *checkedLanesInDrivingDir) {
1139 const MSLane* const l = laneCov.first;
1140 if (l == nullptr || l->getEdge().getOppositeEdge() == nullptr) {
1141 continue;
1142 }
1143 const MSEdge* opposite = l->getEdge().getOppositeEdge();
1144 const std::pair<double, double>& range = laneCov.second;
1145 auto leftMostOppositeLaneIt = opposite->getLanes().rbegin();
1146 for (auto oppositeLaneIt = leftMostOppositeLaneIt; oppositeLaneIt != opposite->getLanes().rend(); ++oppositeLaneIt) {
1147 if ((int)(oppositeLaneIt - leftMostOppositeLaneIt) == nOpp) {
1148 break;
1149 }
1150 // Add vehicles from corresponding range on opposite direction
1151 const MSLane* oppositeLane = *oppositeLaneIt;
1152 auto new_vehs = oppositeLane->getVehiclesInRange(l->getLength() - range.second, l->getLength() - range.first);
1153 vehs.insert(new_vehs.begin(), new_vehs.end());
1154 }
1155 }
1156 }
1157 }
1158#ifdef DEBUG_SURROUNDING
1159 std::cout << SIMTIME << " applySubscriptionFilterLanes() for veh '" << v->getID() << "', lane offset '" << offset << "'. Found the following vehicles so far:\n";
1160 for (auto veh : vehs) {
1161 debugPrint(veh);
1162 }
1163#endif
1164 }
1165}
1166
1167void
1168Helper::applySubscriptionFilterTurn(const Subscription& s, std::set<const SUMOTrafficObject*>& vehs) {
1170 WRITE_WARNINGF(TL("Turn filter is only feasible for context domain 'vehicle' (current is '%'), ignoring filter..."), toHex(s.contextDomain, 2));
1171 return;
1172 }
1173 // Get upcoming junctions and vialanes within downstream distance, where foe links exist or at least the link direction is not straight
1174 MSVehicle* v = dynamic_cast<MSVehicle*>(getVehicle(s.id));
1175 const MSLane* lane = v->getLane();
1176 std::vector<const MSLink*> links = lane->getUpcomingLinks(v->getPositionOnLane(), s.filterDownstreamDist, v->getBestLanesContinuation());
1177#ifdef DEBUG_SURROUNDING
1178 std::cout << "Applying turn filter for vehicle '" << v->getID() << "'\n Gathering foes ..." << std::endl;
1179#endif
1180 // Iterate through junctions and find approaching foes within foeDistToJunction.
1181 for (auto& l : links) {
1182#ifdef DEBUG_SURROUNDING
1183 std::cout << " On junction '" << l->getJunction()->getID() << "' (no. foe links = " << l->getFoeLinks().size() << "):" << std::endl;
1184#endif
1185 for (auto& foeLane : l->getFoeLanes()) {
1186 if (foeLane->getEdge().isCrossing()) {
1187#ifdef DEBUG_SURROUNDING
1188 std::cout << " skipping crossing foeLane '" << foeLane->getID() << "'" << std::endl;
1189#endif
1190 continue;
1191 }
1192#ifdef DEBUG_SURROUNDING
1193 std::cout << " foeLane '" << foeLane->getID() << "'" << std::endl;
1194#endif
1195 // Check vehicles approaching the entry link corresponding to this lane
1196 const MSLink* foeLink = foeLane->getEntryLink();
1197 for (auto& vi : foeLink->getApproaching()) {
1198 if (vi.second.dist <= s.filterFoeDistToJunction) {
1199#ifdef DEBUG_SURROUNDING
1200 std::cout << " Approaching foeLane entry link '" << vi.first->getID() << "'" << std::endl;
1201#endif
1202 vehs.insert(vehs.end(), dynamic_cast<const MSVehicle*>(vi.first));
1203 }
1204 }
1205 // add vehicles currently on the junction
1206 for (const MSVehicle* foe : foeLane->getVehiclesSecure()) {
1207#ifdef DEBUG_SURROUNDING
1208 std::cout << " On foeLane '" << foe->getID() << "'" << std::endl;
1209#endif
1210 vehs.insert(vehs.end(), foe);
1211 }
1212 foeLane->releaseVehicles();
1213 for (auto& laneInfo : foeLane->getIncomingLanes()) {
1214 const MSLane* foeLanePred = laneInfo.lane;
1215 if (foeLanePred->isInternal()) {
1216#ifdef DEBUG_SURROUNDING
1217 std::cout << " foeLanePred '" << foeLanePred->getID() << "'" << std::endl;
1218#endif
1219 for (const MSVehicle* foe : foeLanePred->getVehiclesSecure()) {
1220#ifdef DEBUG_SURROUNDING
1221 std::cout << " On foeLanePred '" << foe->getID() << "'" << std::endl;
1222#endif
1223 vehs.insert(vehs.end(), foe);
1224 }
1225 foeLanePred->releaseVehicles();
1226 }
1227 }
1228 }
1229 }
1230}
1231
1232void
1233Helper::applySubscriptionFilterFieldOfVision(const Subscription& s, std::set<std::string>& objIDs) {
1235 WRITE_WARNINGF(TL("Field of vision opening angle ('%') should be within interval (0, 360), ignoring filter..."), s.filterFieldOfVisionOpeningAngle);
1236 return;
1237 }
1238
1239 MSBaseVehicle* egoVehicle = getVehicle(s.id);
1240 Position egoPosition = egoVehicle->getPosition();
1241 double openingAngle = DEG2RAD(s.filterFieldOfVisionOpeningAngle);
1242
1243#ifdef DEBUG_SURROUNDING
1244 std::cout << "FOVFILTER: ego direction = " << toString(RAD2DEG(egoVehicle->getAngle())) << " (deg)" << std::endl;
1245#endif
1246
1247 auto i = objIDs.begin();
1248 while (i != objIDs.end()) {
1249 if (s.id.compare(*i) == 0) { // skip if this is the ego vehicle
1250 ++i;
1251 continue;
1252 }
1254 double angleEgoToVeh = egoPosition.angleTo2D(obj->getPosition());
1255 double alpha = GeomHelper::angleDiff(egoVehicle->getAngle(), angleEgoToVeh);
1256
1257#ifdef DEBUG_SURROUNDING
1258 const std::string objType = s.isVehicleToPersonContextSubscription() ? "person" : "veh";
1259 std::cout << "FOVFILTER: " << objType << " '" << *i << "' dist = " << toString(egoPosition.distanceTo2D(obj->getPosition())) << std::endl;
1260 std::cout << "FOVFILTER: " << objType << " '" << *i << "' alpha = " << toString(RAD2DEG(alpha)) << " (deg)" << std::endl;
1261#endif
1262
1263 if (abs(alpha) > openingAngle * 0.5) {
1264 i = objIDs.erase(i);
1265 } else {
1266 ++i;
1267 }
1268 }
1269}
1270
1271void
1272Helper::applySubscriptionFilterLateralDistance(const Subscription& s, std::set<const SUMOTrafficObject*>& vehs, double downstreamDist, double upstreamDist,
1273 double lateralDist) {
1274 // collect all vehicles within maximum range of interest to get an upper bound
1275 PositionVector vehShape;
1276 findObjectShape(s.commandId, s.id, vehShape);
1277 double range = MAX3(downstreamDist, upstreamDist, lateralDist);
1278 std::set<std::string> objIDs;
1279 collectObjectIDsInRange(s.contextDomain, vehShape, range, objIDs);
1280
1281#ifdef DEBUG_SURROUNDING
1282 std::cout << "FILTER_LATERAL_DIST: collected object IDs (range " << range << "):" << std::endl;
1283 for (std::string i : objIDs) {
1284 std::cout << i << std::endl;
1285 }
1286#endif
1287
1288 MSVehicle* v = dynamic_cast<MSVehicle*>(getVehicle(s.id));
1289#ifdef DEBUG_SURROUNDING
1290 std::cout << "FILTER_LATERAL_DIST: myLane is '" << v->getLane()->getID() << "', pos " << v->getPositionOnLane() << std::endl;
1291 std::cout << "FILTER_LATERAL_DIST: opposite lane is '" << v->getLane()->getParallelOpposite()->getID() << "'" << std::endl;
1292#endif
1293 double frontPosOnLane = v->getPositionOnLane();
1294 if (v->getLaneChangeModel().isOpposite()) {
1295 frontPosOnLane = v->getLane()->getOppositePos(frontPosOnLane);
1296 }
1297 // 1st pass: downstream (make sure that the whole length of the vehicle is included in the match)
1298 const double backPosOnLane = MAX2(0.0, frontPosOnLane - v->getVehicleType().getLength());
1299 applySubscriptionFilterLateralDistanceSinglePass(s, objIDs, vehs, v->getUpcomingLanesUntil(downstreamDist), backPosOnLane, v->getLateralPositionOnLane(),
1300 true);
1301 // 2nd pass: upstream
1302 applySubscriptionFilterLateralDistanceSinglePass(s, objIDs, vehs, v->getPastLanesUntil(upstreamDist), frontPosOnLane, v->getLateralPositionOnLane(), false);
1303}
1304
1305void
1307 std::set<const SUMOTrafficObject*>& vehs,
1308 const std::vector<const MSLane*>& lanes, double posOnLane, double posLat, bool isDownstream) {
1309 const double streamDist = isDownstream ? s.filterDownstreamDist : s.filterUpstreamDist;
1310 double distRemaining = streamDist;
1311 bool isFirstLane = true;
1312 PositionVector combinedShape;
1313 for (const MSLane* lane : lanes) {
1314#ifdef DEBUG_SURROUNDING
1315 std::cout << "FILTER_LATERAL_DIST: current lane " << (isDownstream ? "down" : "up") << " is '" << lane->getID() << "', length " << lane->getLength()
1316 << ", pos " << posOnLane << ", distRemaining " << distRemaining << std::endl;
1317#endif
1318 PositionVector laneShape = lane->getShape();
1319 if (isFirstLane) {
1320 isFirstLane = false;
1321 double geometryPos = lane->interpolateLanePosToGeometryPos(posOnLane);
1322 if (geometryPos <= POSITION_EPS) {
1323 if (!isDownstream) {
1324 continue;
1325 }
1326 } else {
1327 if (geometryPos >= laneShape.length() - POSITION_EPS) {
1328 laneShape = isDownstream ? PositionVector() : laneShape;
1329 } else {
1330 auto pair = laneShape.splitAt(geometryPos, false);
1331 laneShape = isDownstream ? pair.second : pair.first;
1332 }
1333 }
1334 }
1335 double laneLength = lane->interpolateGeometryPosToLanePos(laneShape.length());
1336 if (distRemaining - laneLength < 0.) {
1337 double geometryPos = lane->interpolateLanePosToGeometryPos(isDownstream ? distRemaining : laneLength - distRemaining);
1338 if (geometryPos > POSITION_EPS && geometryPos < laneShape.length() - POSITION_EPS) {
1339 auto pair = laneShape.splitAt(geometryPos, false);
1340 laneShape = isDownstream ? pair.first : pair.second;
1341 }
1342 }
1343 distRemaining -= laneLength;
1344 try {
1345 laneShape.move2side(-posLat);
1346 } catch (ProcessError&) {
1347 WRITE_WARNINGF(TL("addSubscriptionFilterLateralDistance could not determine shape of lane '%' with a lateral shift of %."),
1348 lane->getID(), toString(posLat));
1349 }
1350#ifdef DEBUG_SURROUNDING
1351 std::cout << " posLat=" << posLat << " laneShape=" << laneShape << "\n";
1352#endif
1353 if (isDownstream) {
1354 combinedShape.append(laneShape);
1355 } else {
1356 combinedShape.prepend(laneShape);
1357 }
1358 if (distRemaining <= POSITION_EPS) {
1359 break;
1360 }
1361 }
1362#ifdef DEBUG_SURROUNDING
1363 std::cout << " combinedShape=" << combinedShape << "\n";
1364#endif
1365 // check remaining objects' distances to the combined shape
1366 auto i = objIDs.begin();
1367 while (i != objIDs.end()) {
1369 double minPerpendicularDist = combinedShape.distance2D(obj->getPosition(), true);
1370#ifdef DEBUG_SURROUNDING
1371 std::cout << (isDownstream ? "DOWN" : "UP") << " obj " << obj->getID() << " perpendicular dist=" << minPerpendicularDist << " filterLateralDist=" << s.filterLateralDist << "\n";
1372#endif
1373 if ((minPerpendicularDist != GeomHelper::INVALID_OFFSET) && (minPerpendicularDist <= s.filterLateralDist)) {
1374 vehs.insert(obj);
1375 i = objIDs.erase(i);
1376 } else {
1377 ++i;
1378 }
1379 }
1380}
1381
1382void
1383Helper::setRemoteControlled(MSVehicle* v, Position xyPos, MSLane* l, double pos, double posLat, double angle,
1384 int edgeOffset, ConstMSEdgeVector route, SUMOTime t) {
1386 v->getInfluencer().setRemoteControlled(xyPos, l, pos, posLat, angle, edgeOffset, route, t);
1387}
1388
1389void
1390Helper::setRemoteControlled(MSPerson* p, Position xyPos, MSLane* l, double pos, double posLat, double angle,
1391 int edgeOffset, ConstMSEdgeVector route, SUMOTime t) {
1393 p->getInfluencer().setRemoteControlled(xyPos, l, pos, posLat, angle, edgeOffset, route, t);
1394}
1395
1396
1397int
1399 int numControlled = 0;
1400 for (auto& controlled : myRemoteControlledVehicles) {
1401 if (MSNet::getInstance()->getVehicleControl().getVehicle(controlled.first) != nullptr) {
1402 controlled.second->getInfluencer().postProcessRemoteControl(controlled.second);
1403 numControlled++;
1404 } else {
1405 WRITE_WARNINGF(TL("Vehicle '%' was removed though being controlled by TraCI"), controlled.first);
1406 }
1407 }
1409 for (auto& controlled : myRemoteControlledPersons) {
1410 if (MSNet::getInstance()->getPersonControl().get(controlled.first) != nullptr) {
1411 controlled.second->getInfluencer().postProcessRemoteControl(controlled.second);
1412 numControlled++;
1413 } else {
1414 WRITE_WARNINGF(TL("Person '%' was removed though being controlled by TraCI"), controlled.first);
1415 }
1416 }
1418 return numControlled;
1419}
1420
1421
1422bool
1423Helper::moveToXYMap(const Position& pos, double maxRouteDistance, bool mayLeaveNetwork, const std::string& origID, const double angle,
1424 double speed, const ConstMSEdgeVector& currentRoute, const int routePosition, const MSLane* currentLane, double currentLanePos, bool onRoad,
1425 SUMOVehicleClass vClass, bool setLateralPos,
1426 double& bestDistance, MSLane** lane, double& lanePos, int& routeOffset, ConstMSEdgeVector& edges) {
1427 // collect edges around the vehicle/person
1428#ifdef DEBUG_MOVEXY
1429 std::cout << SIMTIME << " moveToXYMap pos=" << pos << " angle=" << angle << " vClass=" << toString(vClass) << "\n";
1430#endif
1431 const MSEdge* const currentRouteEdge = currentRoute[routePosition];
1432 std::set<const Named*> into;
1433 PositionVector shape;
1434 shape.push_back(pos);
1435 collectObjectsInRange(libsumo::CMD_GET_EDGE_VARIABLE, shape, maxRouteDistance, into);
1436 double maxDist = 0;
1437 std::map<MSLane*, LaneUtility, ComparatorNumericalIdLess> lane2utility;
1438 // compute utility for all candidate edges
1439 for (const Named* namedEdge : into) {
1440 const MSEdge* e = dynamic_cast<const MSEdge*>(namedEdge);
1441 if ((e->getPermissions() & vClass) != vClass) {
1442 continue;
1443 }
1444 const MSEdge* prevEdge = nullptr;
1445 const MSEdge* nextEdge = nullptr;
1446 bool onRoute = false;
1447 // the next if/the clause sets "onRoute", "prevEdge", and "nextEdge", depending on
1448 // whether the currently seen edge is an internal one or a normal one
1449 if (e->isWalkingArea() || e->isCrossing()) {
1450 // find current intersection along the route
1451 const MSJunction* junction = e->getFromJunction();
1452 for (int i = routePosition; i < (int)currentRoute.size(); i++) {
1453 const MSEdge* cand = currentRoute[i];
1454 if (cand->getToJunction() == junction) {
1455 prevEdge = cand;
1456 if (i + 1 < (int)currentRoute.size()) {
1457 onRoute = true;
1458 nextEdge = currentRoute[i + 1];
1459 }
1460 break;
1461 }
1462 }
1463 if (!onRoute) {
1464 // search backward
1465 for (int i = routePosition - 1; i >= 0; i--) {
1466 const MSEdge* cand = currentRoute[i];
1467 if (cand->getToJunction() == junction) {
1468 onRoute = true;
1469 prevEdge = cand;
1470 nextEdge = currentRoute[i + 1];
1471 break;
1472 }
1473 }
1474 }
1475 if (prevEdge == nullptr) {
1476 // use arbitrary predecessor
1477 if (e->getPredecessors().size() > 0) {
1478 prevEdge = e->getPredecessors().front();
1479 } else if (e->getSuccessors().size() > 1) {
1480 for (MSEdge* e2 : e->getSuccessors()) {
1481 if (e2 != nextEdge) {
1482 prevEdge = e2;
1483 break;
1484 }
1485 }
1486 }
1487 }
1488 if (nextEdge == nullptr) {
1489 if (e->getSuccessors().size() > 0) {
1490 nextEdge = e->getSuccessors().front();
1491 } else if (e->getPredecessors().size() > 1) {
1492 for (MSEdge* e2 : e->getPredecessors()) {
1493 if (e2 != prevEdge) {
1494 nextEdge = e2;
1495 break;
1496 }
1497 }
1498 }
1499 }
1500#ifdef DEBUG_MOVEXY_ANGLE
1501 std::cout << "walkingarea/crossing:" << e->getID() << " prev:" << Named::getIDSecure(prevEdge) << " next:" << Named::getIDSecure(nextEdge)
1502 << " pred=" << toString(e->getPredecessors()) << " succ=" << toString(e->getSuccessors())
1503 << "\n";
1504#endif
1505 } else if (e->isNormal()) {
1506 // a normal edge
1507 //
1508 // check whether the currently seen edge is in the vehicle's route
1509 // - either the one it's on or one of the next edges
1510 ConstMSEdgeVector::const_iterator searchStart = currentRoute.begin() + routePosition;
1511 if (onRoad && currentLane->getEdge().isInternal()) {
1512 ++searchStart;
1513 }
1514 ConstMSEdgeVector::const_iterator edgePos = std::find(searchStart, currentRoute.end(), e);
1515 onRoute = edgePos != currentRoute.end(); // no? -> onRoute is false
1516 if (edgePos == currentRoute.end() - 1 && currentRouteEdge == e) {
1517 // onRoute is false as well if the vehicle is beyond the edge
1518 onRoute &= currentRouteEdge->getLength() > currentLanePos + SPEED2DIST(speed);
1519 }
1520 // save prior and next edges
1521 prevEdge = e;
1522 nextEdge = !onRoute || edgePos == currentRoute.end() - 1 ? nullptr : *(edgePos + 1);
1523#ifdef DEBUG_MOVEXY_ANGLE
1524 std::cout << "normal:" << e->getID() << " prev:" << Named::getIDSecure(prevEdge) << " next:" << Named::getIDSecure(nextEdge) << "\n";
1525#endif
1526 } else if (e->isInternal()) {
1527 // an internal edge
1528 // get the previous edge
1529 prevEdge = e;
1530 while (prevEdge != nullptr && prevEdge->isInternal()) {
1531 MSLane* l = prevEdge->getLanes()[0];
1533 prevEdge = l == nullptr ? nullptr : &l->getEdge();
1534 }
1535 // check whether the previous edge is on the route (was on the route)
1536 ConstMSEdgeVector::const_iterator prevEdgePos = std::find(currentRoute.begin() + routePosition, currentRoute.end(), prevEdge);
1537 nextEdge = e;
1538 while (nextEdge != nullptr && nextEdge->isInternal()) {
1539 nextEdge = nextEdge->getSuccessors()[0]; // should be only one for an internal edge
1540 }
1541 if (prevEdgePos != currentRoute.end() && (prevEdgePos + 1) != currentRoute.end()) {
1542 onRoute = *(prevEdgePos + 1) == nextEdge;
1543 }
1544#ifdef DEBUG_MOVEXY_ANGLE
1545 std::cout << "internal:" << e->getID() << " prev:" << Named::getIDSecure(prevEdge) << " next:" << Named::getIDSecure(nextEdge) << "\n";
1546#endif
1547 }
1548
1549
1550 // weight the lanes...
1551 const bool perpendicular = false;
1552 for (MSLane* const l : e->getLanes()) {
1553 if (!l->allowsVehicleClass(vClass)) {
1554 continue;
1555 }
1556 if (l->getShape().length() == 0) {
1557 // mapping to shapeless lanes is a bad idea
1558 continue;
1559 }
1560 double langle = 180.;
1561 double dist = FAR_AWAY;
1562 double perpendicularDist = FAR_AWAY;
1563 // add some slack to avoid issues from tiny gaps between consecutive lanes
1564 // except when simulating with high precision where the slack can throw of mapping
1565 const double slack = POSITION_EPS * TS;
1566 PositionVector laneShape = l->getShape();
1567 laneShape.extrapolate2D(slack);
1568 double off = laneShape.nearest_offset_to_point2D(pos, true);
1569 if (off != GeomHelper::INVALID_OFFSET) {
1570 perpendicularDist = laneShape.distance2D(pos, true);
1571 }
1572 off = l->getShape().nearest_offset_to_point2D(pos, perpendicular);
1573 if (off != GeomHelper::INVALID_OFFSET) {
1574 dist = l->getShape().distance2D(pos, perpendicular);
1575 langle = GeomHelper::naviDegree(l->getShape().rotationAtOffset(off));
1576 }
1577 // cannot trust lanePos on walkingArea
1578 bool sameEdge = onRoad && e == &currentLane->getEdge() && currentRouteEdge->getLength() > currentLanePos + SPEED2DIST(speed) && !e->isWalkingArea();
1579 /*
1580 const MSEdge* rNextEdge = nextEdge;
1581 while(rNextEdge==0&&lane->getEdge().getPurpose()==MSEdge::EDGEFUNCTION_INTERNAL) {
1582 MSLane* next = lane->getLinkCont()[0]->getLane();
1583 rNextEdge = next == 0 ? 0 : &next->getEdge();
1584 }
1585 */
1586 double dist2 = dist;
1587 if (mayLeaveNetwork && fabs(dist - perpendicularDist) > slack) {
1588 // ambiguous mapping. Don't trust this
1589 dist2 = FAR_AWAY;
1590 }
1591 const double angleDiff = (angle == INVALID_DOUBLE_VALUE || l->getEdge().isWalkingArea() ? 0 : GeomHelper::getMinAngleDiff(angle, langle));
1592#ifdef DEBUG_MOVEXY_ANGLE
1593 std::cout << std::setprecision(gPrecision)
1594 << " candLane=" << l->getID() << " lAngle=" << langle << " lLength=" << l->getLength()
1595 << " angleDiff=" << angleDiff
1596 << " off=" << off
1597 << " pDist=" << perpendicularDist
1598 << " dist=" << dist
1599 << " dist2=" << dist2
1600 << "\n";
1601 std::cout << l->getID() << " param=" << l->getParameter(SUMO_PARAM_ORIGID, "") << " origID='" << origID << "\n";
1602#endif
1603
1604 bool origIDMatch = l->getParameter(SUMO_PARAM_ORIGID, l->getID()) == origID;
1605 if (origIDMatch && setLateralPos
1606 && perpendicularDist > l->getWidth() / 2) {
1607 origIDMatch = false;
1608 }
1609 lane2utility.emplace(l, LaneUtility(
1610 dist2, perpendicularDist, off, angleDiff,
1611 origIDMatch,
1612 onRoute, sameEdge, prevEdge, nextEdge));
1613 // update scaling value
1614 maxDist = MAX2(maxDist, MIN2(dist, SUMO_const_laneWidth));
1615
1616 }
1617 }
1618
1619 // get the best lane given the previously computed values
1620 double bestValue = 0;
1621 MSLane* bestLane = nullptr;
1622 for (const auto& it : lane2utility) {
1623 MSLane* const l = it.first;
1624 const LaneUtility& u = it.second;
1625 double distN = u.dist > 999 ? -10 : 1. - (u.dist / maxDist);
1626 double angleDiffN = 1. - (u.angleDiff / 180.);
1627 double idN = u.ID ? 1 : 0;
1628 double onRouteN = u.onRoute ? 1 : 0;
1629 double sameEdgeN = u.sameEdge ? MIN2(currentRouteEdge->getLength() / MAX2(NUMERICAL_EPS, speed), (double)1.) : 0;
1630 // distance is more important than angle because the vehicle might be driving in the opposite direction
1631 // also, distance becomes increasingly more important with lower step lengths (because position errors from one step to the next can result in large acceleration/speed errors)
1632 double value = (distN * .5 / TS
1633 + angleDiffN * 0.35 /*.5 */
1634 + idN * 1
1635 + onRouteN * 0.1
1636 + sameEdgeN * 0.1);
1637#ifdef DEBUG_MOVEXY
1638 std::cout << " x; l:" << l->getID() << " d:" << u.dist << " dN:" << distN << " aD:" << angleDiffN <<
1639 " ID:" << idN << " oRN:" << onRouteN << " sEN:" << sameEdgeN << " value:" << value << std::endl;
1640#endif
1641 if (value > bestValue || bestLane == nullptr) {
1642 bestValue = value;
1643 if (u.dist == FAR_AWAY) {
1644 bestLane = nullptr;
1645 } else {
1646 bestLane = l;
1647 }
1648 }
1649 }
1650 // no best lane found, return
1651 if (bestLane == nullptr) {
1652 return false;
1653 }
1654 const LaneUtility& u = lane2utility.find(bestLane)->second;
1655 bestDistance = u.dist;
1656 *lane = bestLane;
1657 lanePos = MAX2(0., MIN2(double((*lane)->getLength() - NUMERICAL_EPS),
1659 bestLane->getShape().nearest_offset_to_point25D(pos, false))));
1660 const MSEdge* prevEdge = u.prevEdge;
1661 if (u.onRoute) {
1662 ConstMSEdgeVector::const_iterator prevEdgePos = std::find(currentRoute.begin(), currentRoute.end(), prevEdge);
1663 routeOffset = (int)std::distance(currentRoute.begin(), prevEdgePos);
1664 //std::cout << SIMTIME << "moveToXYMap currLane=" << currentLane->getID() << " routeOffset=" << routeOffset << " edges=" << toString(edges) << " bestLane=" << bestLane->getID() << " prevEdge=" << prevEdge->getID() << "\n";
1665 } else {
1666 edges.push_back(u.prevEdge);
1667 /*
1668 if(bestLane->getEdge().getPurpose()!=MSEdge::EDGEFUNCTION_INTERNAL) {
1669 edges.push_back(&bestLane->getEdge());
1670 }
1671 */
1672 if (u.nextEdge != nullptr) {
1673 edges.push_back(u.nextEdge);
1674 }
1675 routeOffset = 0;
1676#ifdef DEBUG_MOVEXY_ANGLE
1677 std::cout << SIMTIME << " internal2: lane=" << bestLane->getID() << " prev=" << Named::getIDSecure(u.prevEdge) << " next=" << Named::getIDSecure(u.nextEdge) << "\n";
1678#endif
1679 }
1680 return true;
1681}
1682
1683
1684bool
1685Helper::findCloserLane(const MSEdge* edge, const Position& pos, SUMOVehicleClass vClass, double& bestDistance, MSLane** lane) {
1686 // TODO maybe there is a way to abort this early if the lane already found is good enough but simply
1687 // checking for bestDistance < POSITON_EPS gives ugly order dependencies (#7933), so think twice and profile first
1688 if (edge == nullptr) {
1689 return false;
1690 }
1691 bool newBest = false;
1692 for (MSLane* const candidateLane : edge->getLanes()) {
1693 if (!candidateLane->allowsVehicleClass(vClass)) {
1694 continue;
1695 }
1696 if (candidateLane->getShape().length() == 0) {
1697 // mapping to shapeless lanes is a bad idea
1698 continue;
1699 }
1700 const double dist = candidateLane->getShape().distance2D(pos); // get distance
1701#ifdef DEBUG_MOVEXY
1702 std::cout << " b at lane " << candidateLane->getID() << " dist:" << dist << " best:" << bestDistance << std::endl;
1703#endif
1704 if (dist < bestDistance || (dist == bestDistance && candidateLane->getNumericalID() < (*lane)->getNumericalID())) {
1705 // is the new distance the best one? keep then...
1706 bestDistance = dist;
1707 *lane = candidateLane;
1708 newBest = true;
1709 }
1710 }
1711 if (edge->isInternal() && edge->getNumLanes() > 1) {
1712 // there is a parallel internal edge that isn't returned by getInternalFollowingEdge but is also usable for the same route
1713 for (const MSLane* const l : edge->getLanes()) {
1714 if (l->getIndex() == 0) {
1715 continue;
1716 }
1717 for (const MSLink* const link : l->getLinkCont()) {
1718 if (link->isInternalJunctionLink()) {
1719 if (findCloserLane(&link->getViaLane()->getEdge(), pos, vClass, bestDistance, lane)) {
1720 newBest = true;
1721 }
1722 }
1723 }
1724 }
1725 }
1726 return newBest;
1727}
1728
1729
1730bool
1731Helper::moveToXYMap_matchingRoutePosition(const Position& pos, const std::string& origID,
1732 const ConstMSEdgeVector& currentRoute, int routeIndex,
1733 SUMOVehicleClass vClass, bool setLateralPos,
1734 double& bestDistance, MSLane** lane, double& lanePos, int& routeOffset) {
1735#ifdef DEBUG_MOVEXY
1736 std::cout << SIMTIME << " moveToXYMap_matchingRoutePosition pos=" << pos << " vClass=" << toString(vClass) << "\n";
1737#endif
1738 //std::cout << "moveToXYMap_matchingRoutePosition pos=" << pos << "\n";
1739 routeOffset = 0;
1740 // routes may be looped which makes routeOffset ambiguous. We first try to
1741 // find the closest upcoming edge on the route and then look for closer passed edges
1742
1743 // look forward along the route
1744 const MSEdge* prev = nullptr;
1745 for (int i = routeIndex; i < (int)currentRoute.size(); ++i) {
1746 const MSEdge* cand = currentRoute[i];
1747 while (prev != nullptr) {
1748 // check internal edge(s)
1749 const MSEdge* internalCand = prev->getInternalFollowingEdge(cand, vClass);
1750#ifdef DEBUG_MOVEXY
1751 std::cout << SIMTIME << " prev=" << Named::getIDSecure(prev) << " cand=" << Named::getIDSecure(cand) << " internal=" << Named::getIDSecure(internalCand) << "\n";
1752#endif
1753 if (findCloserLane(internalCand, pos, vClass, bestDistance, lane)) {
1754 routeOffset = i - 1;
1755 }
1756 prev = internalCand;
1757 }
1758 if (findCloserLane(cand, pos, vClass, bestDistance, lane)) {
1759 routeOffset = i;
1760 }
1761 prev = cand;
1762 }
1763 // look backward along the route
1764 const MSEdge* next = currentRoute[routeIndex];
1765 for (int i = routeIndex; i >= 0; --i) {
1766 const MSEdge* cand = currentRoute[i];
1767 //std::cout << " next=" << next->getID() << " cand=" << cand->getID() << " i=" << i << " routeIndex=" << routeIndex << "\n";
1768 prev = cand;
1769 while (prev != nullptr) {
1770 // check internal edge(s)
1771 const MSEdge* internalCand = prev->getInternalFollowingEdge(next, vClass);
1772 if (findCloserLane(internalCand, pos, vClass, bestDistance, lane)) {
1773 routeOffset = i;
1774 }
1775 prev = internalCand;
1776 }
1777 if (findCloserLane(cand, pos, vClass, bestDistance, lane)) {
1778 routeOffset = i;
1779 }
1780 next = cand;
1781 }
1782 if (vClass == SVC_PEDESTRIAN) {
1783 // consider all crossings and walkingareas along the route
1784 std::map<const MSJunction*, int> routeJunctions;
1785 for (int i = 0; i < (int)currentRoute.size() - 1; ++i) {
1786 routeJunctions[currentRoute[i]->getToJunction()] = i;
1787 }
1788 std::set<const Named*> into;
1789 PositionVector shape;
1790 shape.push_back(pos);
1792 for (const Named* named : into) {
1793 const MSLane* cand = dynamic_cast<const MSLane*>(named);
1794 if ((cand->getEdge().isWalkingArea() || cand->getEdge().isCrossing())
1795 && routeJunctions.count(cand->getEdge().getToJunction()) != 0) {
1796 if (findCloserLane(&cand->getEdge(), pos, vClass, bestDistance, lane)) {
1797 routeOffset = routeJunctions[cand->getEdge().getToJunction()];
1798 }
1799 }
1800 }
1801 }
1802
1803 assert(lane != nullptr);
1804 // quit if no solution was found, reporting a failure
1805 if (lane == nullptr) {
1806#ifdef DEBUG_MOVEXY
1807 std::cout << " b failed - no best route lane" << std::endl;
1808#endif
1809 return false;
1810 }
1811
1812
1813 // position may be inaccurate; let's check the given index, too
1814 // @note: this is enabled for non-internal lanes only, as otherwise the position information may ambiguous
1815 if (!(*lane)->getEdge().isInternal()) {
1816 const std::vector<MSLane*>& lanes = (*lane)->getEdge().getLanes();
1817 for (std::vector<MSLane*>::const_iterator i = lanes.begin(); i != lanes.end(); ++i) {
1818 if ((*i)->getParameter(SUMO_PARAM_ORIGID, (*i)->getID()) == origID) {
1819 if (setLateralPos) {
1820 // vehicle might end up on top of another lane with a big
1821 // lateral offset to the lane with origID.
1822 const double dist = (*i)->getShape().distance2D(pos); // get distance
1823 if (dist < (*i)->getWidth() / 2) {
1824 *lane = *i;
1825 break;
1826 }
1827 } else {
1828 *lane = *i;
1829 break;
1830 }
1831 }
1832 }
1833 }
1834 // check position, stuff, we should have the best lane along the route
1835 lanePos = MAX2(0., MIN2(double((*lane)->getLength() - NUMERICAL_EPS),
1836 (*lane)->interpolateGeometryPosToLanePos(
1837 (*lane)->getShape().nearest_offset_to_point25D(pos, false))));
1838 //std::cout << SIMTIME << " moveToXYMap_matchingRoutePosition vehicle=" << veh.getID() << " currLane=" << veh.getLane()->getID() << " routeOffset=" << routeOffset << " edges=" << toString(edges) << " lane=" << (*lane)->getID() << "\n";
1839#ifdef DEBUG_MOVEXY
1840 std::cout << " b ok lane " << (*lane)->getID() << " lanePos:" << lanePos << std::endl;
1841#endif
1842 return true;
1843}
1844
1845
1847 : VariableWrapper(handler), myResults(into), myContextResults(context), myActiveResults(&into) {
1848
1849}
1850
1851
1852void
1853Helper::SubscriptionWrapper::setContext(const std::string* const refID) {
1854 myActiveResults = refID == nullptr ? &myResults : &myContextResults[*refID];
1855}
1856
1857
1858void
1860 myActiveResults = &myResults;
1861 myResults.clear();
1862 myContextResults.clear();
1863}
1864
1865
1866bool
1867Helper::SubscriptionWrapper::wrapDouble(const std::string& objID, const int variable, const double value) {
1868 (*myActiveResults)[objID][variable] = std::make_shared<TraCIDouble>(value);
1869 return true;
1870}
1871
1872
1873bool
1874Helper::SubscriptionWrapper::wrapInt(const std::string& objID, const int variable, const int value) {
1875 (*myActiveResults)[objID][variable] = std::make_shared<TraCIInt>(value);
1876 return true;
1877}
1878
1879
1880bool
1881Helper::SubscriptionWrapper::wrapString(const std::string& objID, const int variable, const std::string& value) {
1882 (*myActiveResults)[objID][variable] = std::make_shared<TraCIString>(value);
1883 return true;
1884}
1885
1886
1887bool
1888Helper::SubscriptionWrapper::wrapStringList(const std::string& objID, const int variable, const std::vector<std::string>& value) {
1889 auto sl = std::make_shared<TraCIStringList>();
1890 sl->value = value;
1891 (*myActiveResults)[objID][variable] = sl;
1892 return true;
1893}
1894
1895
1896bool
1897Helper::SubscriptionWrapper::wrapDoubleList(const std::string& objID, const int variable, const std::vector<double>& value) {
1898 auto sl = std::make_shared<TraCIDoubleList>();
1899 sl->value = value;
1900 (*myActiveResults)[objID][variable] = sl;
1901 return true;
1902}
1903
1904
1905bool
1906Helper::SubscriptionWrapper::wrapPosition(const std::string& objID, const int variable, const TraCIPosition& value) {
1907 (*myActiveResults)[objID][variable] = std::make_shared<TraCIPosition>(value);
1908 return true;
1909}
1910
1911
1912bool
1913Helper::SubscriptionWrapper::wrapPositionVector(const std::string& objID, const int variable, const TraCIPositionVector& value) {
1914 (*myActiveResults)[objID][variable] = std::make_shared<TraCIPositionVector>(value);
1915 return true;
1916}
1917
1918
1919bool
1920Helper::SubscriptionWrapper::wrapColor(const std::string& objID, const int variable, const TraCIColor& value) {
1921 (*myActiveResults)[objID][variable] = std::make_shared<TraCIColor>(value);
1922 return true;
1923}
1924
1925
1926bool
1927Helper::SubscriptionWrapper::wrapStringDoublePair(const std::string& objID, const int variable, const std::pair<std::string, double>& value) {
1928 (*myActiveResults)[objID][variable] = std::make_shared<TraCIRoadPosition>(value.first, value.second);
1929 return true;
1930}
1931
1932
1933bool
1934Helper::SubscriptionWrapper::wrapStringPair(const std::string& objID, const int variable, const std::pair<std::string, std::string>& value) {
1935 auto sl = std::make_shared<TraCIStringList>();
1936 sl->value.push_back(value.first);
1937 sl->value.push_back(value.second);
1938 (*myActiveResults)[objID][variable] = sl;
1939 return true;
1940}
1941
1942
1943void
1944Helper::SubscriptionWrapper::empty(const std::string& objID) {
1945 (*myActiveResults)[objID]; // initiate the empty map to track the objectID for TRACI_ID_LIST context subscriptions
1946}
1947
1948
1949void
1950Helper::VehicleStateListener::vehicleStateChanged(const SUMOVehicle* const vehicle, MSNet::VehicleState to, const std::string& /*info*/) {
1951 myVehicleStateChanges[to].push_back(vehicle->getID());
1952}
1953
1954
1955void
1957 myTransportableStateChanges[to].push_back(transportable->getID());
1958}
1959
1960
1961}
1962
1963
1964/****************************************************************************/
long long int SUMOTime
Definition GUI.h:36
#define DEG2RAD(x)
Definition GeomHelper.h:35
#define RAD2DEG(x)
Definition GeomHelper.h:36
#define FAR_AWAY
Definition Helper.cpp:72
std::vector< const MSEdge * > ConstMSEdgeVector
Definition MSEdge.h:74
#define LANE_RTREE_QUAL
Definition MSLane.h:1793
#define WRITE_WARNINGF(...)
Definition MsgHandler.h:296
#define TL(string)
Definition MsgHandler.h:315
void checkTimeBounds(const double time)
check the valid SUMOTime range of double input and throw an error if out of bounds
Definition SUMOTime.cpp:151
#define STEPS2TIME(x)
Definition SUMOTime.h:55
#define SPEED2DIST(x)
Definition SUMOTime.h:45
#define SIMSTEP
Definition SUMOTime.h:61
#define SUMOTime_MAX
Definition SUMOTime.h:34
#define TS
Definition SUMOTime.h:42
#define SIMTIME
Definition SUMOTime.h:62
#define TIME2STEPS(x)
Definition SUMOTime.h:57
SUMOVehicleClass
Definition of vehicle classes to differ between different lane usage and authority types.
@ SVC_PEDESTRIAN
pedestrian
const int STOP_DURATION_SET
const int STOP_UNTIL_SET
const int STOP_PARKING_SET
const int STOP_START_SET
const int STOP_CONTAINER_TRIGGER_SET
const int STOP_INDEX_FIT
const int STOP_TRIGGER_SET
const int STOP_END_SET
const std::string SUMO_PARAM_ORIGID
SumoXMLTag
Numbers representing SUMO-XML - element names.
@ SUMO_TAG_CHARGING_STATION
A Charging Station.
@ SUMO_TAG_NOTHING
invalid tag, must be the last one
@ SUMO_TAG_CONTAINER_STOP
A container stop.
@ SUMO_TAG_BUS_STOP
A bus stop.
@ SUMO_TAG_PARKING_AREA
A parking area.
@ SUMO_TAG_OVERHEAD_WIRE_SEGMENT
An overhead wire segment.
int gPrecision
the precision for floating point outputs
Definition StdDefs.cpp:26
const double SUMO_const_laneWidth
Definition StdDefs.h:48
T MIN2(T a, T b)
Definition StdDefs.h:76
T MAX2(T a, T b)
Definition StdDefs.h:82
T MAX3(T a, T b, T c)
Definition StdDefs.h:96
std::string toHex(const T i, std::streamsize numDigits=0)
Definition ToString.h:56
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition ToString.h:46
A class that stores a 2D geometrical boundary.
Definition Boundary.h:39
double ymin() const
Returns minimum y-coordinate.
Definition Boundary.cpp:130
double xmin() const
Returns minimum x-coordinate.
Definition Boundary.cpp:118
Boundary & grow(double by)
extends the boundary by the given amount
Definition Boundary.cpp:343
double distanceTo2D(const Position &p) const
returns the euclidean distance in the x-y-plane
Definition Boundary.cpp:265
double getHeight() const
Returns the height of the boundary (y-axis)
Definition Boundary.cpp:160
double getWidth() const
Returns the width of the boudary (x-axis)
Definition Boundary.cpp:154
double ymax() const
Returns maximum y-coordinate.
Definition Boundary.cpp:136
double xmax() const
Returns maximum x-coordinate.
Definition Boundary.cpp:124
static const GeoConvHelper & getFinal()
the coordinate transformation for writing the location element and for tracking the original coordina...
const Boundary & getConvBoundary() const
Returns the converted boundary.
static const double INVALID_OFFSET
a value to signify offsets outside the range of [0, Line.length()]
Definition GeomHelper.h:50
static double naviDegree(const double angle)
static double angleDiff(const double angle1, const double angle2)
Returns the difference of the second angle to the first angle in radiants.
static double getMinAngleDiff(double angle1, double angle2)
Returns the minimum distance (clockwise/counter-clockwise) between both angles.
The base class for microscopic and mesoscopic vehicles.
double getLength() const
Returns the vehicle's length.
const MSVehicleType & getVehicleType() const
Returns the vehicle's type definition.
Calibrates the flow on a segment to a specified one.
const MSLane * getLane() const
AspiredState getCurrentStateInterval() const
static const std::map< std::string, MSCalibrator * > & getInstances()
return all calibrator instances
A simple description of a position on a lane (crossing of a lane)
A detector of vehicles passing an area between entry/exit points.
const CrossSectionVector & getEntries() const
Returns the entry cross sections.
const CrossSectionVector & getExits() const
Returns the exit cross sections.
A road/street connecting two junctions.
Definition MSEdge.h:77
bool isCrossing() const
return whether this edge is a pedestrian crossing
Definition MSEdge.h:273
SVCPermissions getPermissions() const
Returns the combined permissions of all lanes of this edge.
Definition MSEdge.h:649
bool isWalkingArea() const
return whether this edge is walking area
Definition MSEdge.h:287
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:1340
bool isNormal() const
return whether this edge is an internal edge
Definition MSEdge.h:263
const MSJunction * getToJunction() const
Definition MSEdge.h:418
double getLength() const
return the length of the edge
Definition MSEdge.h:685
const MSJunction * getFromJunction() const
Definition MSEdge.h:414
int getNumLanes() const
Definition MSEdge.h:172
bool isInternal() const
return whether this edge is an internal edge
Definition MSEdge.h:268
static bool dictionary(const std::string &id, MSEdge *edge)
Inserts edge into the static dictionary Returns true if the key id isn't already in the dictionary....
Definition MSEdge.cpp:1047
const MSEdgeVector & getPredecessors() const
Definition MSEdge.h:409
const MSEdge * getInternalFollowingEdge(const MSEdge *followerAfterInternal, SUMOVehicleClass vClass) const
Definition MSEdge.cpp:900
const MSEdgeVector & getSuccessors(SUMOVehicleClass vClass=SVC_IGNORING) const
Returns the following edges, restricted by vClass.
Definition MSEdge.cpp:1258
The base class for an intersection.
Definition MSJunction.h:58
Representation of a lane in the micro simulation.
Definition MSLane.h:84
std::pair< MSVehicle *const, double > getFollower(const MSVehicle *ego, double egoPos, double dist, MinorLinkMode mLinkMode) const
Find follower vehicle for the given ego vehicle (which may be on the opposite direction lane)
Definition MSLane.cpp:4316
MSLane * getParallelLane(int offset, bool includeOpposite=true) const
Returns the lane with the given offset parallel to this one or 0 if it does not exist.
Definition MSLane.cpp:2773
void visit(const MSLane::StoringVisitor &cont) const
Callback for visiting the lane when traversing an RTree.
Definition MSLane.h:1334
static void fill(RTREE &into)
Fills the given RTree with lane instances.
Definition MSLane.cpp:2454
std::set< MSVehicle * > getVehiclesInRange(const double a, const double b) const
Returns all vehicles on the lane overlapping with the interval [a,b].
Definition MSLane.cpp:4220
double getLength() const
Returns the lane's length.
Definition MSLane.h:606
std::vector< const MSLink * > getUpcomingLinks(double pos, double range, const std::vector< MSLane * > &contLanes) const
Returns all upcoming links within given range along the given (non-internal) continuation lanes measu...
Definition MSLane.cpp:4251
std::set< MSVehicle * > getSurroundingVehicles(double startPos, double downstreamDist, double upstreamDist, std::shared_ptr< LaneCoverageInfo > checkedLanes) const
Returns all vehicles closer than downstreamDist along the road network starting on the given position...
Definition MSLane.cpp:4168
bool allowsVehicleClass(SUMOVehicleClass vclass) const
Definition MSLane.h:925
int getIndex() const
Returns the lane's index.
Definition MSLane.h:642
double getOppositePos(double pos) const
return the corresponding position on the opposite lane
Definition MSLane.cpp:4311
MSLane * getLogicalPredecessorLane() const
get the most likely precedecessor lane (sorted using by_connections_to_sorter). The result is cached ...
Definition MSLane.cpp:3135
bool isInternal() const
Definition MSLane.cpp:2545
@ FOLLOW_ALWAYS
Definition MSLane.h:975
@ FOLLOW_NEVER
Definition MSLane.h:974
double interpolateGeometryPosToLanePos(double geometryPos) const
Definition MSLane.h:566
std::pair< MSVehicle *const, double > getLeader(const MSVehicle *veh, const double vehPos, const std::vector< MSLane * > &bestLaneConts, double dist=-1, bool checkTmpVehicles=false) const
Returns the immediate leader of veh and the distance to veh starting on this lane.
Definition MSLane.cpp:2842
virtual const VehCont & getVehiclesSecure() const
Returns the vehicles container; locks it for microsimulation.
Definition MSLane.h:483
virtual void releaseVehicles() const
Allows to use the container for microsimulation again.
Definition MSLane.h:513
virtual const PositionVector & getShape(bool) const
Definition MSLane.h:294
MSLane * getParallelOpposite() const
return the opposite direction lane of this lanes edge or nullptr
Definition MSLane.cpp:4305
MSEdge & getEdge() const
Returns the lane's edge.
Definition MSLane.h:764
VehicleState
Definition of a vehicle state.
Definition MSNet.h:608
@ ARRIVED
The vehicle arrived at his destination (is deleted)
static MSNet * getInstance()
Returns the pointer to the unique instance of MSNet (singleton).
Definition MSNet.cpp:185
MSTLLogicControl & getTLSControl()
Returns the tls logics control.
Definition MSNet.h:451
static bool hasInstance()
Returns whether the network was already constructed.
Definition MSNet.h:152
MSStoppingPlace * getStoppingPlace(const std::string &id, const SumoXMLTag category) const
Returns the named stopping place of the given category.
Definition MSNet.cpp:1380
void addVehicleStateListener(VehicleStateListener *listener)
Adds a vehicle states listener.
Definition MSNet.cpp:1257
void addTransportableStateListener(TransportableStateListener *listener)
Adds a transportable states listener.
Definition MSNet.cpp:1285
TransportableState
Definition of a transportable state.
Definition MSNet.h:685
MSVehicleRouter & getRouterTT(const int rngIndex, const MSEdgeVector &prohibited=MSEdgeVector()) const
Definition MSNet.cpp:1507
MSVehicleControl & getVehicleControl()
Returns the vehicle control.
Definition MSNet.h:378
virtual MSTransportableControl & getPersonControl()
Returns the person control.
Definition MSNet.cpp:1189
const NamedObjectCont< MSStoppingPlace * > & getStoppingPlaces(SumoXMLTag category) const
Definition MSNet.cpp:1415
void setRemoteControlled(Position xyPos, MSLane *l, double pos, double posLat, double angle, int edgeOffset, const ConstMSEdgeVector &route, SUMOTime t)
Definition MSPerson.cpp:298
Influencer & getInfluencer()
Returns the velocity/lane influencer.
Definition MSPerson.cpp:273
double getDistanceBetween(double fromPos, double toPos, const MSLane *fromLane, const MSLane *toLane, int routePosition=0) const
Compute the distance between 2 given edges on this route, optionally including the length of internal...
Definition MSRoute.cpp:311
A lane area vehicles can halt at.
double getBeginLanePosition() const
Returns the begin position of this stop.
double getEndLanePosition() const
Returns the end position of this stop.
const MSLane & getLane() const
Returns the lane this stop is located at.
Storage for all programs of a single tls.
TLSLogicVariants & get(const std::string &id) const
Returns the variants of a named tls.
MSTransportable * get(const std::string &id) const
Returns the named transportable, if existing.
void setRemoteControlled(Position xyPos, MSLane *l, double pos, double posLat, double angle, int edgeOffset, const ConstMSEdgeVector &route, SUMOTime t)
SUMOVehicle * getVehicle(const std::string &id) const
Returns the vehicle with the given id.
Representation of a vehicle in the micro simulation.
Definition MSVehicle.h:77
const std::vector< const MSLane * > getUpcomingLanesUntil(double distance) const
Returns the upcoming (best followed by default 0) sequence of lanes to continue the route starting at...
bool isOnRoad() const
Returns the information whether the vehicle is on a road (is simulated)
Definition MSVehicle.h:605
MSAbstractLaneChangeModel & getLaneChangeModel()
const std::vector< MSLane * > & getBestLanesContinuation() const
Returns the best sequence of lanes to continue the route starting at myLane.
const std::vector< const MSLane * > getPastLanesUntil(double distance) const
Returns the sequence of past lanes (right-most on edge) based on the route starting at the current la...
const MSLane * getLane() const
Returns the lane the vehicle is on.
Definition MSVehicle.h:581
Influencer & getInfluencer()
double getLateralPositionOnLane() const
Get the vehicle's lateral position on the lane.
Definition MSVehicle.h:413
double getPositionOnLane() const
Get the vehicle's position along the lane.
Definition MSVehicle.h:374
The car-following model and parameter.
SUMOVehicleClass getVehicleClass() const
Get this vehicle type's vehicle class.
const std::string & getID() const
Returns the name of the vehicle type.
double getLength() const
Get vehicle's length [m].
Allows to store the object; used as context while traveling the rtree in TraCI.
Definition Named.h:90
Base class for objects which have an id.
Definition Named.h:54
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 point in 2D or 3D with translation and scaling methods.
Definition Position.h:37
double distanceTo2D(const Position &p2) const
returns the euclidean distance in the x-y-plane
Definition Position.h:276
double x() const
Returns the x-position.
Definition Position.h:55
double z() const
Returns the z-position.
Definition Position.h:65
double angleTo2D(const Position &other) const
returns the angle in the plane of the vector pointing from here to the other position (in radians bet...
Definition Position.h:286
double y() const
Returns the y-position.
Definition Position.h:60
A list of positions.
void append(const PositionVector &v, double sameThreshold=2.0)
double length() const
Returns the length.
Position positionAtOffset(double pos, double lateralOffset=0) const
Returns the position at the given length.
double distance2D(const Position &p, bool perpendicular=false) const
closest 2D-distance to point p (or -1 if perpendicular is true and the point is beyond this vector)
void prepend(const PositionVector &v, double sameThreshold=2.0)
double nearest_offset_to_point2D(const Position &p, bool perpendicular=true) const
return the nearest offest to point 2D
std::pair< PositionVector, PositionVector > splitAt(double where, bool use2D=false) const
Returns the two lists made when this list vector is splitted at the given point.
void move2side(double amount, double maxExtension=100)
move position vector to side using certain amount
Boundary getBoxBoundary() const
Returns a boundary enclosing this list of lines.
void extrapolate2D(const double val, const bool onlyFirst=false)
extrapolate position vector in two dimensions (Z is ignored)
double nearest_offset_to_point25D(const Position &p, bool perpendicular=true) const
return the nearest offest to point 2D projected onto the 3D geometry
unsigned char red() const
Returns the red-amount of the color.
Definition RGBColor.cpp:74
unsigned char alpha() const
Returns the alpha-amount of the color.
Definition RGBColor.cpp:92
unsigned char green() const
Returns the green-amount of the color.
Definition RGBColor.cpp:80
unsigned char blue() const
Returns the blue-amount of the color.
Definition RGBColor.cpp:86
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...
Representation of a vehicle, person, or container.
virtual bool isVehicle() const
Whether it is a vehicle.
virtual const MSLane * getLane() const =0
Returns the lane the object is currently at.
virtual Position getPosition(const double offset=0) const =0
Return current position (x/y, cartesian)
virtual const MSEdge * getEdge() const =0
Returns the edge the object is currently at.
Representation of a vehicle.
Definition SUMOVehicle.h:62
virtual double getAngle() const =0
Get the vehicle's angle.
Definition of vehicle stop (position and duration)
int getFlags() const
return flags as per Vehicle::getStops
SUMOTime started
the time at which this stop was reached
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
std::string split
the id of the vehicle (train portion) that splits of upon reaching this stop
double startPos
The stopping position start.
std::string line
the new line id of the trip within a cyclical public transport route
std::string chargingStation
(Optional) charging station if one is assigned to the stop
std::string overheadWireSegment
(Optional) overhead line segment if one is assigned to the stop
int parametersSet
Information for the output which parameter were set.
int index
at which position in the stops list
std::string join
the id of the vehicle (train portion) to which this vehicle shall be joined
SUMOTime until
The time at which the vehicle may continue its journey.
std::string actType
act Type (only used by Persons) (used by netedit)
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 busstop
(Optional) bus stop if one is assigned to the stop
std::string tripId
id of the trip within a cyclical public transport route
std::string containerstop
(Optional) container stop if one is assigned to the stop
bool containerTriggered
whether an arriving container lets the vehicle continue
SUMOTime arrival
The (expected) time at which the vehicle reaches the stop.
SUMOTime duration
The stopping duration.
const MSEdge * nextEdge
Definition Helper.h:205
const MSEdge * prevEdge
Definition Helper.h:204
bool wrapDouble(const std::string &objID, const int variable, const double value)
Definition Helper.cpp:1867
void empty(const std::string &objID)
Definition Helper.cpp:1944
bool wrapPositionVector(const std::string &objID, const int variable, const TraCIPositionVector &value)
Definition Helper.cpp:1913
bool wrapColor(const std::string &objID, const int variable, const TraCIColor &value)
Definition Helper.cpp:1920
bool wrapInt(const std::string &objID, const int variable, const int value)
Definition Helper.cpp:1874
bool wrapStringList(const std::string &objID, const int variable, const std::vector< std::string > &value)
Definition Helper.cpp:1888
bool wrapPosition(const std::string &objID, const int variable, const TraCIPosition &value)
Definition Helper.cpp:1906
bool wrapString(const std::string &objID, const int variable, const std::string &value)
Definition Helper.cpp:1881
bool wrapStringPair(const std::string &objID, const int variable, const std::pair< std::string, std::string > &value)
Definition Helper.cpp:1934
bool wrapStringDoublePair(const std::string &objID, const int variable, const std::pair< std::string, double > &value)
Definition Helper.cpp:1927
SubscriptionWrapper(VariableWrapper::SubscriptionHandler handler, SubscriptionResults &into, ContextSubscriptionResults &context)
Definition Helper.cpp:1846
void setContext(const std::string *const refID)
Definition Helper.cpp:1853
bool wrapDoubleList(const std::string &objID, const int variable, const std::vector< double > &value)
Definition Helper.cpp:1897
void transportableStateChanged(const MSTransportable *const transportable, MSNet::TransportableState to, const std::string &info="")
Called if a transportable changes its state.
Definition Helper.cpp:1956
std::map< MSNet::TransportableState, std::vector< std::string > > myTransportableStateChanges
Changes in the states of simulated transportables.
Definition Helper.h:258
std::map< MSNet::VehicleState, std::vector< std::string > > myVehicleStateChanges
Changes in the states of simulated vehicles.
Definition Helper.h:251
void vehicleStateChanged(const SUMOVehicle *const vehicle, MSNet::VehicleState to, const std::string &info="")
Called if a vehicle changes its state.
Definition Helper.cpp:1950
static Position makePosition(const TraCIPosition &position)
Definition Helper.cpp:387
static MSEdge * getEdge(const std::string &edgeID)
Definition Helper.cpp:393
static void cleanup()
Definition Helper.cpp:683
static double getDrivingDistance(std::pair< const MSLane *, double > &roadPos1, std::pair< const MSLane *, double > &roadPos2)
Definition Helper.cpp:455
static void collectObjectsInRange(int domain, const PositionVector &shape, double range, std::set< const Named * > &into)
Definition Helper.cpp:820
static MSCalibrator::AspiredState getCalibratorState(const MSCalibrator *c)
Definition Helper.cpp:730
static TraCIPosition makeTraCIPosition(const Position &position, const bool includeZ=false)
Definition Helper.cpp:377
static LANE_RTREE_QUAL * myLaneTree
A lookup tree of lanes.
Definition Helper.h:277
static void applySubscriptionFilterTurn(const Subscription &s, std::set< const SUMOTrafficObject * > &vehs)
Apply the subscription filter "turn": Gather upcoming junctions and vialanes within downstream distan...
Definition Helper.cpp:1168
static void findObjectShape(int domain, const std::string &id, PositionVector &shape)
Definition Helper.cpp:740
static void clearStateChanges()
Definition Helper.cpp:719
static PositionVector makePositionVector(const TraCIPositionVector &vector)
Definition Helper.cpp:347
static void fuseLaneCoverage(std::shared_ptr< LaneCoverageInfo > aggregatedLaneCoverage, const std::shared_ptr< LaneCoverageInfo > newLaneCoverage)
Adds lane coverage information from newLaneCoverage into aggregatedLaneCoverage.
Definition Helper.cpp:319
static bool moveToXYMap_matchingRoutePosition(const Position &pos, const std::string &origID, const ConstMSEdgeVector &currentRoute, int routeIndex, SUMOVehicleClass vClass, bool setLateralPos, double &bestDistance, MSLane **lane, double &lanePos, int &routeOffset)
Definition Helper.cpp:1731
static void debugPrint(const SUMOTrafficObject *veh)
Definition Helper.cpp:97
static MSPerson * getPerson(const std::string &id)
Definition Helper.cpp:491
static void subscribe(const int commandId, const std::string &id, const std::vector< int > &variables, const double beginTime, const double endTime, const libsumo::TraCIResults &params, const int contextDomain=0, const double range=0.)
Definition Helper.cpp:109
static TraCIPositionVector makeTraCIPositionVector(const PositionVector &positionVector)
helper functions
Definition Helper.cpp:337
static const std::vector< std::string > & getTransportableStateChanges(const MSNet::TransportableState state)
Definition Helper.cpp:713
static std::map< int, std::shared_ptr< VariableWrapper > > myWrapper
Map of commandIds -> their executors; applicable if the executor applies to the method footprint.
Definition Helper.h:268
static void clearSubscriptions()
Definition Helper.cpp:203
static MSBaseVehicle * getVehicle(const std::string &id)
Definition Helper.cpp:477
static void applySubscriptionFilterLateralDistanceSinglePass(const Subscription &s, std::set< std::string > &objIDs, std::set< const SUMOTrafficObject * > &vehs, const std::vector< const MSLane * > &lanes, double posOnLane, double posLat, bool isDownstream)
Definition Helper.cpp:1306
static MSStoppingPlace * getStoppingPlace(const std::string &id, const SumoXMLTag type)
Definition Helper.cpp:527
static TraCIColor makeTraCIColor(const RGBColor &color)
Definition Helper.cpp:360
static void applySubscriptionFilterFieldOfVision(const Subscription &s, std::set< std::string > &objIDs)
Definition Helper.cpp:1233
static Subscription * myLastContextSubscription
The last context subscription.
Definition Helper.h:265
static TraCINextStopData buildStopData(const SUMOVehicleParameter::Stop &stopPar)
Definition Helper.cpp:643
static void registerStateListener()
Definition Helper.cpp:698
static TransportableStateListener myTransportableStateListener
Changes in the states of simulated transportables.
Definition Helper.h:274
static void setRemoteControlled(MSVehicle *v, Position xyPos, MSLane *l, double pos, double posLat, double angle, int edgeOffset, ConstMSEdgeVector route, SUMOTime t)
Definition Helper.cpp:1383
static int postProcessRemoteControl()
return number of remote-controlled entities
Definition Helper.cpp:1398
static void applySubscriptionFilters(const Subscription &s, std::set< std::string > &objIDs)
Filter the given ID-Set (which was obtained from an R-Tree search) according to the filters set by th...
Definition Helper.cpp:890
static std::map< std::string, MSVehicle * > myRemoteControlledVehicles
Definition Helper.h:279
static const MSVehicleType & getVehicleType(const std::string &vehicleID)
Definition Helper.cpp:512
static bool moveToXYMap(const Position &pos, double maxRouteDistance, bool mayLeaveNetwork, const std::string &origID, const double angle, double speed, const ConstMSEdgeVector &currentRoute, const int routePosition, const MSLane *currentLane, double currentLanePos, bool onRoad, SUMOVehicleClass vClass, bool setLateralPos, double &bestDistance, MSLane **lane, double &lanePos, int &routeOffset, ConstMSEdgeVector &edges)
Definition Helper.cpp:1423
static std::pair< MSLane *, double > convertCartesianToRoadMap(const Position &pos, const SUMOVehicleClass vClass)
Definition Helper.cpp:420
static MSTLLogicControl::TLSLogicVariants & getTLS(const std::string &id)
Definition Helper.cpp:518
static SUMOTrafficObject * getTrafficObject(int domain, const std::string &id)
Definition Helper.cpp:501
static VehicleStateListener myVehicleStateListener
Changes in the states of simulated vehicles.
Definition Helper.h:271
static std::vector< Subscription > mySubscriptions
The list of known, still valid subscriptions.
Definition Helper.h:262
static SUMOVehicleParameter::Stop buildStopParameters(const std::string &edgeOrStoppingPlaceID, double pos, int laneIndex, double startPos, int flags, double duration, double until)
Definition Helper.cpp:537
static void handleSingleSubscription(const Subscription &s)
Definition Helper.cpp:232
static void applySubscriptionFilterLateralDistance(const Subscription &s, std::set< const SUMOTrafficObject * > &vehs, double downstreamDist, double upstreamDist, double lateralDist)
Apply the subscription filter "lateral distance": Only return vehicles within the given lateral dista...
Definition Helper.cpp:1272
static const std::vector< std::string > & getVehicleStateChanges(const MSNet::VehicleState state)
Definition Helper.cpp:707
static void collectObjectIDsInRange(int domain, const PositionVector &shape, double range, std::set< std::string > &into)
Definition Helper.cpp:810
static void handleSubscriptions(const SUMOTime t)
Definition Helper.cpp:153
static Subscription * addSubscriptionFilter(SubscriptionFilterType filter)
Definition Helper.cpp:210
static const MSLane * getLaneChecking(const std::string &edgeID, int laneIndex, double pos)
Definition Helper.cpp:403
static RGBColor makeRGBColor(const TraCIColor &color)
Definition Helper.cpp:371
static void applySubscriptionFilterLanes(const Subscription &s, std::set< const SUMOTrafficObject * > &vehs, std::vector< int > &filterLanes, double downstreamDist, double upstreamDist, bool disregardOppositeDirection)
Apply the subscription filter "lanes": Only return vehicles on list of lanes relative to ego vehicle....
Definition Helper.cpp:1070
static std::map< std::string, MSPerson * > myRemoteControlledPersons
Definition Helper.h:280
static bool needNewSubscription(libsumo::Subscription &s, std::vector< Subscription > &subscriptions, libsumo::Subscription *&modifiedSubscription)
Definition Helper.cpp:178
static bool findCloserLane(const MSEdge *edge, const Position &pos, SUMOVehicleClass vClass, double &bestDistance, MSLane **lane)
Definition Helper.cpp:1685
static std::shared_ptr< tcpip::Storage > toStorage(const TraCIResult &v)
Representation of a subscription.
double filterUpstreamDist
Upstream distance specified by the upstream distance filter.
int commandId
commandIdArg The command id of the subscription
std::set< std::string > filterVTypes
vTypes specified by the vTypes filter
double filterFieldOfVisionOpeningAngle
Opening angle (in deg) specified by the field of vision filter.
std::vector< int > filterLanes
lanes specified by the lanes filter
std::string id
The id of the object that is subscribed.
SUMOTime endTime
The end time of the subscription.
int contextDomain
The domain ID of the context.
double filterFoeDistToJunction
Foe distance to junction specified by the turn filter.
bool isVehicleToVehicleContextSubscription() const
SUMOTime beginTime
The begin time of the subscription.
std::vector< int > variables
The subscribed variables.
SVCPermissions filterVClasses
vClasses specified by the vClasses filter,
bool isVehicleToPersonContextSubscription() const
double filterDownstreamDist
Downstream distance specified by the downstream distance filter.
double filterLateralDist
Lateral distance specified by the lateral distance filter.
int activeFilters
Active filters for the subscription (bitset,.
double range
The range of the context.
std::vector< std::shared_ptr< tcpip::Storage > > parameters
The parameters for the subscribed variables.
An error which allows to continue.
Definition TraCIDefs.h:144
virtual void empty(const std::string &)
bool(* SubscriptionHandler)(const std::string &objID, const int variable, VariableWrapper *wrapper, tcpip::Storage *paramData)
Definition of a method to be called for serving an associated commandID.
virtual void setContext(const std::string *const)
TRACI_CONST double INVALID_DOUBLE_VALUE
TRACI_CONST int LAST_STEP_VEHICLE_NUMBER
TRACI_CONST int CMD_GET_CHARGINGSTATION_VARIABLE
TRACI_CONST int CMD_SUBSCRIBE_EDGE_CONTEXT
TRACI_CONST int CMD_SUBSCRIBE_LANE_CONTEXT
TRACI_CONST int TRACI_ID_LIST
TRACI_CONST int CMD_GET_PARKINGAREA_VARIABLE
TRACI_CONST int CMD_GET_POI_VARIABLE
TRACI_CONST int CMD_GET_TL_VARIABLE
TRACI_CONST int CMD_SUBSCRIBE_VEHICLE_CONTEXT
std::map< std::string, libsumo::SubscriptionResults > ContextSubscriptionResults
Definition TraCIDefs.h:338
TRACI_CONST int CMD_GET_REROUTER_VARIABLE
TRACI_CONST int VAR_ROAD_ID
TRACI_CONST int CMD_GET_VEHICLE_VARIABLE
TRACI_CONST int CMD_GET_EDGE_VARIABLE
TRACI_CONST int CMD_GET_CALIBRATOR_VARIABLE
TRACI_CONST int CMD_GET_PERSON_VARIABLE
TRACI_CONST int CMD_GET_ROUTEPROBE_VARIABLE
TRACI_CONST int CMD_GET_LANEAREA_VARIABLE
TRACI_CONST int CMD_SUBSCRIBE_BUSSTOP_CONTEXT
TRACI_CONST int CMD_GET_BUSSTOP_VARIABLE
TRACI_CONST int CMD_GET_ROUTE_VARIABLE
TRACI_CONST int CMD_GET_MEANDATA_VARIABLE
TRACI_CONST int CMD_GET_JUNCTION_VARIABLE
std::map< std::string, libsumo::TraCIResults > SubscriptionResults
{object->{variable->value}}
Definition TraCIDefs.h:337
TRACI_CONST int CMD_GET_VARIABLESPEEDSIGN_VARIABLE
TRACI_CONST int CMD_SUBSCRIBE_CALIBRATOR_CONTEXT
TRACI_CONST int VAR_LANEPOSITION
TRACI_CONST int CMD_GET_SIM_VARIABLE
TRACI_CONST int CMD_SUBSCRIBE_PERSON_CONTEXT
TRACI_CONST int CMD_GET_VEHICLETYPE_VARIABLE
TRACI_CONST int CMD_SUBSCRIBE_CHARGINGSTATION_CONTEXT
TRACI_CONST int CMD_SUBSCRIBE_POLYGON_CONTEXT
TRACI_CONST int CMD_GET_LANE_VARIABLE
TRACI_CONST int CMD_GET_GUI_VARIABLE
TRACI_CONST int CMD_SUBSCRIBE_PARKINGAREA_CONTEXT
TRACI_CONST int CMD_GET_POLYGON_VARIABLE
TRACI_CONST int CMD_SUBSCRIBE_MULTIENTRYEXIT_CONTEXT
TRACI_CONST int CMD_SUBSCRIBE_VEHICLE_VARIABLE
TRACI_CONST int CMD_GET_MULTIENTRYEXIT_VARIABLE
TRACI_CONST int CMD_SUBSCRIBE_INDUCTIONLOOP_CONTEXT
SubscriptionFilterType
Filter types for context subscriptions.
@ SUBS_FILTER_LEAD_FOLLOW
@ SUBS_FILTER_UPSTREAM_DIST
@ SUBS_FILTER_VTYPE
@ SUBS_FILTER_NO_RTREE
@ SUBS_FILTER_LANES
@ SUBS_FILTER_NOOPPOSITE
@ SUBS_FILTER_DOWNSTREAM_DIST
@ SUBS_FILTER_LATERAL_DIST
@ SUBS_FILTER_TURN
@ SUBS_FILTER_VCLASS
@ SUBS_FILTER_MANEUVER
@ SUBS_FILTER_FIELD_OF_VISION
TRACI_CONST int CMD_SUBSCRIBE_POI_CONTEXT
TRACI_CONST int CMD_SUBSCRIBE_SIM_CONTEXT
TRACI_CONST int CMD_SUBSCRIBE_PERSON_VARIABLE
TRACI_CONST int CMD_GET_INDUCTIONLOOP_VARIABLE
TRACI_CONST int CMD_GET_OVERHEADWIRE_VARIABLE
TRACI_CONST int CMD_SUBSCRIBE_LANEAREA_CONTEXT
TRACI_CONST int CMD_SUBSCRIBE_JUNCTION_CONTEXT
std::map< int, std::shared_ptr< libsumo::TraCIResult > > TraCIResults
{variable->value}
Definition TraCIDefs.h:335
A 2D or 3D-position, for 2D positions z == INVALID_DOUBLE_VALUE.
Definition TraCIDefs.h:178
A list of positions.
Definition TraCIDefs.h:234
std::vector< TraCIPosition > value
Definition TraCIDefs.h:244