Eclipse SUMO - Simulation of Urban MObility
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>
25 #include <utils/geom/GeomHelper.h>
27 #include <microsim/MSNet.h>
29 #include <microsim/MSEdgeControl.h>
31 #include <microsim/MSEdge.h>
32 #include <microsim/MSLane.h>
33 #include <microsim/MSLink.h>
35 #include <microsim/MSVehicle.h>
41 #include <libsumo/StorageHelper.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
50 #include <libsumo/InductionLoop.h>
51 #include <libsumo/Junction.h>
52 #include <libsumo/Lane.h>
53 #include <libsumo/LaneArea.h>
54 #include <libsumo/MeanData.h>
55 #include <libsumo/MultiEntryExit.h>
56 #include <libsumo/OverheadWire.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>
65 #include <libsumo/TrafficLight.h>
67 #include <libsumo/Vehicle.h>
68 #include <libsumo/VehicleType.h>
69 #include <libsumo/TraCIConstants.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 
78 namespace libsumo {
79 // ===========================================================================
80 // static member initializations
81 // ===========================================================================
82 std::vector<Subscription> Helper::mySubscriptions;
83 Subscription* Helper::myLastContextSubscription = nullptr;
84 std::map<int, std::shared_ptr<VariableWrapper> > Helper::myWrapper;
85 Helper::VehicleStateListener Helper::myVehicleStateListener;
86 Helper::TransportableStateListener Helper::myTransportableStateListener;
88 std::map<std::string, MSVehicle*> Helper::myRemoteControlledVehicles;
89 std::map<std::string, MSPerson*> Helper::myRemoteControlledPersons;
90 
91 
92 // ===========================================================================
93 // static member definitions
94 // ===========================================================================
95 
96 void
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 
108 void
109 Helper::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) {
112  myLastContextSubscription = nullptr;
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 
152 void
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 
177 bool
178 Helper::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 
202 void
204  mySubscriptions.clear();
205  myLastContextSubscription = nullptr;
206 }
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 
231 void
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 
318 void
319 Helper::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 
348  PositionVector pv;
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 
370 RGBColor
372  return RGBColor((unsigned char)c.r, (unsigned char)c.g, (unsigned char)c.b, (unsigned char)c.a);
373 }
374 
375 
377 Helper::makeTraCIPosition(const Position& position, const bool includeZ) {
378  TraCIPosition p;
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 
386 Position
388  return Position(tpos.x, tpos.y, tpos.z);
389 }
390 
391 
392 MSEdge*
393 Helper::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 
402 const MSLane*
403 Helper::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 
419 std::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 
454 double
455 Helper::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 
477 Helper::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 
490 MSPerson*
491 Helper::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 
501 Helper::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 
511 const MSVehicleType&
512 Helper::getVehicleType(const std::string& vehicleID) {
513  return getVehicle(vehicleID)->getVehicleType();
514 }
515 
516 
518 Helper::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 
527 Helper::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 
537 Helper::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) {
550  newStop.parametersSet |= STOP_DURATION_SET;
551  }
552  if (newStop.until >= 0) {
553  newStop.parametersSet |= STOP_UNTIL_SET;
554  }
555  if ((flags & 1) != 0) {
556  newStop.parking = ParkingType::OFFROAD;
557  newStop.parametersSet |= STOP_PARKING_SET;
558  }
559  if ((flags & 2) != 0) {
560  newStop.triggered = true;
561  newStop.parametersSet |= STOP_TRIGGER_SET;
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) {
595  case SUMO_TAG_BUS_STOP:
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 
682 void
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 
697 void
699  if (MSNet::hasInstance()) {
702  }
703 }
704 
705 
706 const std::vector<std::string>&
709 }
710 
711 
712 const std::vector<std::string>&
715 }
716 
717 
718 void
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 
739 void
740 Helper::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 
809 void
810 Helper::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 
819 void
820 Helper::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;
833  for (const auto& stop : MSNet::getInstance()->getStoppingPlaces(SUMO_TAG_CHARGING_STATION)) {
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 
889 void
890 Helper::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,
969  MSLane::MinorLinkMode::FOLLOW_ALWAYS).first;
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 
1010  if (s.activeFilters & SUBS_FILTER_TURN) {
1011  applySubscriptionFilterTurn(s, vehs);
1012  if (s.activeFilters & SUBS_FILTER_LANES) {
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  }
1051  if (s.activeFilters & SUBS_FILTER_VTYPE) {
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 
1069 void
1070 Helper::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 
1167 void
1168 Helper::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 
1232 void
1233 Helper::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 
1271 void
1272 Helper::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 
1305 void
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 
1382 void
1383 Helper::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 
1389 void
1390 Helper::setRemoteControlled(MSPerson* p, Position xyPos, MSLane* l, double pos, double posLat, double angle,
1391  int edgeOffset, ConstMSEdgeVector route, SUMOTime t) {
1392  myRemoteControlledPersons[p->getID()] = p;
1393  p->getInfluencer().setRemoteControlled(xyPos, l, pos, posLat, angle, edgeOffset, route, t);
1394 }
1395 
1396 
1397 int
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  }
1417  myRemoteControlledPersons.clear();
1418  return numControlled;
1419 }
1420 
1421 
1422 bool
1423 Helper::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];
1532  l = l->getLogicalPredecessorLane();
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 
1684 bool
1685 Helper::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 
1730 bool
1731 Helper::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 
1852 void
1853 Helper::SubscriptionWrapper::setContext(const std::string* const refID) {
1854  myActiveResults = refID == nullptr ? &myResults : &myContextResults[*refID];
1855 }
1856 
1857 
1858 void
1860  myActiveResults = &myResults;
1861  myResults.clear();
1862  myContextResults.clear();
1863 }
1864 
1865 
1866 bool
1867 Helper::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 
1873 bool
1874 Helper::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 
1880 bool
1881 Helper::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 
1887 bool
1888 Helper::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 
1896 bool
1897 Helper::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 
1905 bool
1906 Helper::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 
1912 bool
1913 Helper::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 
1919 bool
1920 Helper::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 
1926 bool
1927 Helper::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 
1933 bool
1934 Helper::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 
1943 void
1944 Helper::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 
1949 void
1950 Helper::VehicleStateListener::vehicleStateChanged(const SUMOVehicle* const vehicle, MSNet::VehicleState to, const std::string& /*info*/) {
1951  myVehicleStateChanges[to].push_back(vehicle->getID());
1952 }
1953 
1954 
1955 void
1957  myTransportableStateChanges[to].push_back(transportable->getID());
1958 }
1959 
1960 
1961 }
1962 
1963 
1964 /****************************************************************************/
long long int SUMOTime
Definition: GUI.h:35
#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:1783
#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:150
#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:319
double distanceTo2D(const Position &p) const
returns the euclidean distance in the x-y-plane
Definition: Boundary.cpp:241
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)
Definition: GeomHelper.cpp:191
static double angleDiff(const double angle1, const double angle2)
Returns the difference of the second angle to the first angle in radiants.
Definition: GeomHelper.cpp:178
static double getMinAngleDiff(double angle1, double angle2)
Returns the minimum distance (clockwise/counter-clockwise) between both angles.
Definition: GeomHelper.cpp:172
The base class for microscopic and mesoscopic vehicles.
Definition: MSBaseVehicle.h:57
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.
Definition: MSCalibrator.h:47
static const std::map< std::string, MSCalibrator * > & getInstances()
return all calibrator instances
Definition: MSCalibrator.h:94
const MSLane * getLane() const
Definition: MSCalibrator.h:113
AspiredState getCurrentStateInterval() const
A simple description of a position on a lane (crossing of a lane)
A detector of vehicles passing an area between entry/exit points.
Definition: MSE3Collector.h:59
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:634
const MSEdgeVector & getPredecessors() const
Definition: MSEdge.h:409
bool isWalkingArea() const
return whether this edge is walking area
Definition: MSEdge.h:287
const MSEdge * getOppositeEdge() const
Returns the opposite direction edge if on exists else a nullptr.
Definition: MSEdge.cpp:1288
bool isNormal() const
return whether this edge is an internal edge
Definition: MSEdge.h:263
const std::vector< MSLane * > & getLanes() const
Returns this edge's lanes.
Definition: MSEdge.h:168
const MSJunction * getFromJunction() const
Definition: MSEdge.h:414
double getLength() const
return the length of the edge
Definition: MSEdge.h:670
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:995
const MSJunction * getToJunction() const
Definition: MSEdge.h:418
const MSEdge * getInternalFollowingEdge(const MSEdge *followerAfterInternal, SUMOVehicleClass vClass) const
Definition: MSEdge.cpp:848
const MSEdgeVector & getSuccessors(SUMOVehicleClass vClass=SVC_IGNORING) const
Returns the following edges, restricted by vClass.
Definition: MSEdge.cpp:1206
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:4297
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:2754
virtual const VehCont & getVehiclesSecure() const
Returns the vehicles container; locks it for microsimulation.
Definition: MSLane.h:475
void visit(const MSLane::StoringVisitor &cont) const
Callback for visiting the lane when traversing an RTree.
Definition: MSLane.h:1326
static void fill(RTREE &into)
Fills the given RTree with lane instances.
Definition: MSLane.cpp:2435
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:4201
double getLength() const
Returns the lane's length.
Definition: MSLane.h:598
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:4232
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:4149
bool allowsVehicleClass(SUMOVehicleClass vclass) const
Definition: MSLane.h:917
int getIndex() const
Returns the lane's index.
Definition: MSLane.h:634
double getOppositePos(double pos) const
return the corresponding position on the opposite lane
Definition: MSLane.cpp:4292
MSLane * getLogicalPredecessorLane() const
get the most likely precedecessor lane (sorted using by_connections_to_sorter). The result is cached ...
Definition: MSLane.cpp:3116
bool isInternal() const
Definition: MSLane.cpp:2526
MSEdge & getEdge() const
Returns the lane's edge.
Definition: MSLane.h:756
double interpolateGeometryPosToLanePos(double geometryPos) const
Definition: MSLane.h:558
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:2823
virtual void releaseVehicles() const
Allows to use the container for microsimulation again.
Definition: MSLane.h:505
MSLane * getParallelOpposite() const
return the opposite direction lane of this lanes edge or nullptr
Definition: MSLane.cpp:4286
virtual const PositionVector & getShape(bool) const
Definition: MSLane.h:294
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:184
MSTLLogicControl & getTLSControl()
Returns the tls logics control.
Definition: MSNet.h:451
MSVehicleControl & getVehicleControl()
Returns the vehicle control.
Definition: MSNet.h:378
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:1373
void addVehicleStateListener(VehicleStateListener *listener)
Adds a vehicle states listener.
Definition: MSNet.cpp:1250
void addTransportableStateListener(TransportableStateListener *listener)
Adds a transportable states listener.
Definition: MSNet.cpp:1278
TransportableState
Definition of a transportable state.
Definition: MSNet.h:685
MSVehicleRouter & getRouterTT(const int rngIndex, const MSEdgeVector &prohibited=MSEdgeVector()) const
Definition: MSNet.cpp:1487
virtual MSTransportableControl & getPersonControl()
Returns the person control.
Definition: MSNet.cpp:1182
const NamedObjectCont< MSStoppingPlace * > & getStoppingPlaces(SumoXMLTag category) const
Definition: MSNet.cpp:1408
void setRemoteControlled(Position xyPos, MSLane *l, double pos, double posLat, double angle, int edgeOffset, const ConstMSEdgeVector &route, SUMOTime t)
Definition: MSPerson.cpp:297
Influencer & getInfluencer()
Returns the velocity/lane influencer.
Definition: MSPerson.cpp:272
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)
Definition: MSVehicle.cpp:802
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...
Definition: MSVehicle.cpp:6318
bool isOnRoad() const
Returns the information whether the vehicle is on a road (is simulated)
Definition: MSVehicle.h:608
MSAbstractLaneChangeModel & getLaneChangeModel()
Definition: MSVehicle.cpp:5774
const std::vector< MSLane * > & getBestLanesContinuation() const
Returns the best sequence of lanes to continue the route starting at myLane.
Definition: MSVehicle.cpp:6290
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...
Definition: MSVehicle.cpp:6387
Influencer & getInfluencer()
Definition: MSVehicle.cpp:7251
double getLateralPositionOnLane() const
Get the vehicle's lateral position on the lane.
Definition: MSVehicle.h:416
double getPositionOnLane() const
Get the vehicle's position along the lane.
Definition: MSVehicle.h:377
const MSLane * getLane() const
Returns the lane the vehicle is on.
Definition: MSVehicle.h:584
The car-following model and parameter.
Definition: MSVehicleType.h:63
SUMOVehicleClass getVehicleClass() const
Get this vehicle type's vehicle class.
const std::string & getID() const
Returns the name of the vehicle type.
Definition: MSVehicleType.h:91
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 Position getPosition(const double offset=0) const =0
Return current position (x/y, cartesian)
virtual const MSLane * getLane() const =0
Returns the lane the object is currently at.
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)
Definition: StorageHelper.h:33
Representation of a subscription.
Definition: Subscription.h:70
double filterUpstreamDist
Upstream distance specified by the upstream distance filter.
Definition: Subscription.h:137
int commandId
commandIdArg The command id of the subscription
Definition: Subscription.h:114
std::set< std::string > filterVTypes
vTypes specified by the vTypes filter
Definition: Subscription.h:141
double filterFieldOfVisionOpeningAngle
Opening angle (in deg) specified by the field of vision filter.
Definition: Subscription.h:145
std::vector< int > filterLanes
lanes specified by the lanes filter
Definition: Subscription.h:133
std::string id
The id of the object that is subscribed.
Definition: Subscription.h:116
SUMOTime endTime
The end time of the subscription.
Definition: Subscription.h:124
int contextDomain
The domain ID of the context.
Definition: Subscription.h:126
double filterFoeDistToJunction
Foe distance to junction specified by the turn filter.
Definition: Subscription.h:139
bool isVehicleToVehicleContextSubscription() const
Definition: Subscription.h:105
SUMOTime beginTime
The begin time of the subscription.
Definition: Subscription.h:122
std::vector< int > variables
The subscribed variables.
Definition: Subscription.h:118
SVCPermissions filterVClasses
vClasses specified by the vClasses filter,
Definition: Subscription.h:143
bool isVehicleToPersonContextSubscription() const
Definition: Subscription.h:109
double filterDownstreamDist
Downstream distance specified by the downstream distance filter.
Definition: Subscription.h:135
double filterLateralDist
Lateral distance specified by the lateral distance filter.
Definition: Subscription.h:147
int activeFilters
Active filters for the subscription (bitset,.
Definition: Subscription.h:131
double range
The range of the context.
Definition: Subscription.h:128
std::vector< std::shared_ptr< tcpip::Storage > > parameters
The parameters for the subscribed variables.
Definition: Subscription.h:120
An error which allows to continue.
Definition: TraCIDefs.h:144
virtual void empty(const std::string &)
Definition: Subscription.h:169
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.
Definition: Subscription.h:153
virtual void setContext(const std::string *const)
Definition: Subscription.h:157
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.
Definition: Subscription.h:37
@ SUBS_FILTER_LEAD_FOLLOW
Definition: Subscription.h:49
@ SUBS_FILTER_UPSTREAM_DIST
Definition: Subscription.h:47
@ SUBS_FILTER_VTYPE
Definition: Subscription.h:55
@ SUBS_FILTER_NO_RTREE
Definition: Subscription.h:62
@ SUBS_FILTER_LANES
Definition: Subscription.h:41
@ SUBS_FILTER_NOOPPOSITE
Definition: Subscription.h:43
@ SUBS_FILTER_DOWNSTREAM_DIST
Definition: Subscription.h:45
@ SUBS_FILTER_LATERAL_DIST
Definition: Subscription.h:60
@ SUBS_FILTER_TURN
Definition: Subscription.h:51
@ SUBS_FILTER_VCLASS
Definition: Subscription.h:53
@ SUBS_FILTER_MANEUVER
Definition: Subscription.h:64
@ SUBS_FILTER_FIELD_OF_VISION
Definition: Subscription.h:58
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
auto get(const nlohmann::detail::iteration_proxy_value< IteratorType > &i) -> decltype(i.key())
Definition: json.hpp:4451
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