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.org/sumo
3 // Copyright (C) 2017-2018 German Aerospace Center (DLR) and others.
4 // This program and the accompanying materials
5 // are made available under the terms of the Eclipse Public License v2.0
6 // which accompanies this distribution, and is available at
7 // http://www.eclipse.org/legal/epl-v20.html
8 // SPDX-License-Identifier: EPL-2.0
9 /****************************************************************************/
17 // C++ TraCI client API implementation
18 /****************************************************************************/
19 
20 // ===========================================================================
21 // included modules
22 // ===========================================================================
23 #include <config.h>
24 
25 #include <utils/geom/GeomHelper.h>
26 #include <microsim/MSNet.h>
29 #include <microsim/MSEdgeControl.h>
31 #include <microsim/MSEdge.h>
32 #include <microsim/MSLane.h>
33 #include <microsim/MSVehicle.h>
36 #include <libsumo/TraCIDefs.h>
37 #include <libsumo/Edge.h>
38 #include <libsumo/InductionLoop.h>
39 #include <libsumo/Junction.h>
40 #include <libsumo/Lane.h>
41 #include <libsumo/LaneArea.h>
42 #include <libsumo/MultiEntryExit.h>
43 #include <libsumo/Person.h>
44 #include <libsumo/POI.h>
45 #include <libsumo/Polygon.h>
46 #include <libsumo/Route.h>
47 #include <libsumo/Simulation.h>
48 #include <libsumo/TrafficLight.h>
49 #include <libsumo/Vehicle.h>
50 #include <libsumo/VehicleType.h>
52 #include "Helper.h"
53 
54 #define FAR_AWAY 1000.0
55 
56 //#define DEBUG_MOVEXY
57 //#define DEBUG_MOVEXY_ANGLE
58 //#define DEBUG_SURROUNDING
59 
60 void
61 LaneStoringVisitor::add(const MSLane* const l) const {
62  switch (myDomain) {
64  const MSLane::VehCont& vehs = l->getVehiclesSecure();
65  for (MSLane::VehCont::const_iterator j = vehs.begin(); j != vehs.end(); ++j) {
66  if (myShape.distance2D((*j)->getPosition()) <= myRange) {
67  myIDs.insert((*j)->getID());
68  }
69  }
70  l->releaseVehicles();
71  }
72  break;
74  l->getVehiclesSecure();
75  std::vector<MSTransportable*> persons = l->getEdge().getSortedPersons(MSNet::getInstance()->getCurrentTimeStep(), true);
76  for (auto p : persons) {
77  if (myShape.distance2D(p->getPosition()) <= myRange) {
78  myIDs.insert(p->getID());
79  }
80  }
81  l->releaseVehicles();
82  }
83  break;
84  case CMD_GET_EDGE_VARIABLE: {
85  if (myShape.size() != 1 || l->getShape().distance2D(myShape[0]) <= myRange) {
86  myIDs.insert(l->getEdge().getID());
87  }
88  }
89  break;
90  case CMD_GET_LANE_VARIABLE: {
91  if (myShape.size() != 1 || l->getShape().distance2D(myShape[0]) <= myRange) {
92  myIDs.insert(l->getID());
93  }
94  }
95  break;
96  default:
97  break;
98 
99  }
100 }
101 
102 namespace libsumo {
103 // ===========================================================================
104 // static member initializations
105 // ===========================================================================
106 std::vector<Subscription> Helper::mySubscriptions;
107 std::map<int, std::shared_ptr<VariableWrapper> > Helper::myWrapper;
108 Helper::VehicleStateListener Helper::myVehicleStateListener;
109 std::map<int, NamedRTree*> Helper::myObjects;
110 LANE_RTREE_QUAL* Helper::myLaneTree;
111 std::map<std::string, MSVehicle*> Helper::myRemoteControlledVehicles;
112 std::map<std::string, MSPerson*> Helper::myRemoteControlledPersons;
113 
114 
115 // ===========================================================================
116 // static member definitions
117 // ===========================================================================
118 void
119 Helper::subscribe(const int commandId, const std::string& id, const std::vector<int>& variables,
120  const double beginTime, const double endTime, const int contextDomain, const double range) {
121  std::vector<std::vector<unsigned char> > parameters;
122  const SUMOTime begin = beginTime == INVALID_DOUBLE_VALUE ? 0 : TIME2STEPS(beginTime);
123  const SUMOTime end = endTime == INVALID_DOUBLE_VALUE || endTime > STEPS2TIME(SUMOTime_MAX) ? SUMOTime_MAX : TIME2STEPS(endTime);
124  libsumo::Subscription s(commandId, id, variables, parameters, begin, end, contextDomain, range);
125  mySubscriptions.push_back(s);
126  handleSingleSubscription(s);
127 }
128 
129 
130 void
131 Helper::handleSubscriptions(const SUMOTime t) {
132  for (const libsumo::Subscription& s : mySubscriptions) {
133  if (s.beginTime > t) {
134  continue;
135  }
136  handleSingleSubscription(s);
137  }
138 }
139 
140 
141 void
142 Helper::handleSingleSubscription(const Subscription& s) {
143  const int getCommandId = s.contextDomain > 0 ? s.contextDomain : s.commandId - 0x30;
144  std::set<std::string> objIDs;
145  if (s.contextDomain > 0) {
146  if ((s.activeFilters & SUBS_FILTER_NO_RTREE) == 0) {
147  PositionVector shape;
148  findObjectShape(s.commandId, s.id, shape);
149  collectObjectsInRange(s.contextDomain, shape, s.range, objIDs);
150  }
151  applySubscriptionFilters(s, objIDs);
152  } else {
153  objIDs.insert(s.id);
154  }
155  const int numVars = s.contextDomain > 0 && s.variables.size() == 1 && s.variables[0] == TRACI_ID_LIST ? 0 : (int)s.variables.size();
156  if (myWrapper.empty()) {
157  myWrapper[CMD_GET_EDGE_VARIABLE] = Edge::makeWrapper();
158  myWrapper[CMD_GET_INDUCTIONLOOP_VARIABLE] = InductionLoop::makeWrapper();
159  myWrapper[CMD_GET_JUNCTION_VARIABLE] = Junction::makeWrapper();
160  myWrapper[CMD_GET_LANE_VARIABLE] = Lane::makeWrapper();
161  myWrapper[CMD_GET_LANEAREA_VARIABLE] = LaneArea::makeWrapper();
162  myWrapper[CMD_GET_MULTIENTRYEXIT_VARIABLE] = MultiEntryExit::makeWrapper();
163  myWrapper[CMD_GET_PERSON_VARIABLE] = Person::makeWrapper();
164  myWrapper[CMD_GET_POI_VARIABLE] = POI::makeWrapper();
165  myWrapper[CMD_GET_POLYGON_VARIABLE] = Polygon::makeWrapper();
166  myWrapper[CMD_GET_ROUTE_VARIABLE] = Route::makeWrapper();
167  myWrapper[CMD_GET_SIM_VARIABLE] = Simulation::makeWrapper();
168  myWrapper[CMD_GET_TL_VARIABLE] = TrafficLight::makeWrapper();
169  myWrapper[CMD_GET_VEHICLE_VARIABLE] = Vehicle::makeWrapper();
170  myWrapper[CMD_GET_VEHICLETYPE_VARIABLE] = VehicleType::makeWrapper();
171  }
172  auto wrapper = myWrapper.find(getCommandId);
173  if (wrapper == myWrapper.end()) {
174  throw TraCIException("Unsupported command specified");
175  }
176  std::shared_ptr<VariableWrapper> handler = wrapper->second;
177  for (const std::string& objID : objIDs) {
178  if (numVars > 0) {
179  for (const int variable : s.variables) {
180  handler->handle(objID, variable, handler.get());
181  }
182  } else {
183  if (!handler->handle(objID, LAST_STEP_VEHICLE_NUMBER, handler.get())) {
184  handler->handle(objID, TRACI_ID_LIST, handler.get());
185  }
186  }
187  }
188 }
189 
190 
191 void
192 Helper::fuseLaneCoverage(std::shared_ptr<LaneCoverageInfo> aggregatedLaneCoverage, const std::shared_ptr<LaneCoverageInfo> newLaneCoverage) {
193  for (auto& p : *newLaneCoverage) {
194  const MSLane* lane = p.first;
195  if (aggregatedLaneCoverage->find(lane) == aggregatedLaneCoverage->end()) {
196  // Lane has no coverage in aggregatedLaneCoverage, yet
197  (*aggregatedLaneCoverage)[lane] = (*newLaneCoverage)[lane];
198  } else {
199  // Lane is covered in aggregatedLaneCoverage as well
200  std::pair<double, double>& range1 = (*aggregatedLaneCoverage)[lane];
201  std::pair<double, double>& range2 = (*newLaneCoverage)[lane];
202  std::pair<double, double> hull = std::make_pair(MIN2(range1.first, range2.first), MAX2(range1.second, range2.second));
203  (*aggregatedLaneCoverage)[lane] = hull;
204  }
205  }
206 }
207 
208 
210 Helper::makeTraCIPositionVector(const PositionVector& positionVector) {
212  for (int i = 0; i < (int)positionVector.size(); ++i) {
213  tp.push_back(makeTraCIPosition(positionVector[i]));
214  }
215  return tp;
216 }
217 
218 
220 Helper::makePositionVector(const TraCIPositionVector& vector) {
221  PositionVector pv;
222  for (int i = 0; i < (int)vector.size(); i++) {
223  pv.push_back(Position(vector[i].x, vector[i].y));
224  }
225  return pv;
226 }
227 
228 
230 Helper::makeTraCIColor(const RGBColor& color) {
231  TraCIColor tc;
232  tc.a = color.alpha();
233  tc.b = color.blue();
234  tc.g = color.green();
235  tc.r = color.red();
236  return tc;
237 }
238 
239 
240 RGBColor
241 Helper::makeRGBColor(const TraCIColor& c) {
242  return RGBColor((unsigned char)c.r, (unsigned char)c.g, (unsigned char)c.b, (unsigned char)c.a);
243 }
244 
245 
247 Helper::makeTraCIPosition(const Position& position, const bool includeZ) {
248  TraCIPosition p;
249  p.x = position.x();
250  p.y = position.y();
251  p.z = includeZ ? position.z() : Position::INVALID.z();
252  return p;
253 }
254 
255 
256 Position
257 Helper::makePosition(const TraCIPosition& tpos) {
258  return Position(tpos.x, tpos.y, tpos.z);
259 }
260 
261 
262 MSEdge*
263 Helper::getEdge(const std::string& edgeID) {
264  MSEdge* edge = MSEdge::dictionary(edgeID);
265  if (edge == nullptr) {
266  throw TraCIException("Referenced edge '" + edgeID + "' is not known.");
267  }
268  return edge;
269 }
270 
271 
272 const MSLane*
273 Helper::getLaneChecking(const std::string& edgeID, int laneIndex, double pos) {
274  const MSEdge* edge = MSEdge::dictionary(edgeID);
275  if (edge == nullptr) {
276  throw TraCIException("Unknown edge " + edgeID);
277  }
278  if (laneIndex < 0 || laneIndex >= (int)edge->getLanes().size()) {
279  throw TraCIException("Invalid lane index for " + edgeID);
280  }
281  const MSLane* lane = edge->getLanes()[laneIndex];
282  if (pos < 0 || pos > lane->getLength()) {
283  throw TraCIException("Position on lane invalid");
284  }
285  return lane;
286 }
287 
288 
289 std::pair<MSLane*, double>
290 Helper::convertCartesianToRoadMap(Position pos) {
292  std::pair<MSLane*, double> result;
293  std::vector<std::string> allEdgeIds;
294  double minDistance = std::numeric_limits<double>::max();
295 
296  allEdgeIds = MSNet::getInstance()->getEdgeControl().getEdgeNames();
297  for (std::vector<std::string>::iterator itId = allEdgeIds.begin(); itId != allEdgeIds.end(); itId++) {
298  const std::vector<MSLane*>& allLanes = MSEdge::dictionary((*itId))->getLanes();
299  for (std::vector<MSLane*>::const_iterator itLane = allLanes.begin(); itLane != allLanes.end(); itLane++) {
300  const double newDistance = (*itLane)->getShape().distance2D(pos);
301  if (newDistance < minDistance) {
302  minDistance = newDistance;
303  result.first = (*itLane);
304  }
305  }
306  }
307  // @todo this may be a place where 3D is required but 2D is delivered
308  result.second = result.first->getShape().nearest_offset_to_point2D(pos, false);
309  return result;
310 }
311 
312 
313 void
314 Helper::cleanup() {
315  for (const auto i : myObjects) {
316  delete i.second;
317  }
318  myObjects.clear();
319  delete myLaneTree;
320  myLaneTree = nullptr;
321 }
322 
323 
324 void
325 Helper::registerVehicleStateListener() {
326  MSNet::getInstance()->addVehicleStateListener(&myVehicleStateListener);
327 }
328 
329 
330 const std::vector<std::string>&
331 Helper::getVehicleStateChanges(const MSNet::VehicleState state) {
332  return myVehicleStateListener.myVehicleStateChanges[state];
333 }
334 
335 
336 void
337 Helper::clearVehicleStates() {
338  for (auto& i : myVehicleStateListener.myVehicleStateChanges) {
339  i.second.clear();
340  }
341 }
342 
343 
344 void
345 Helper::findObjectShape(int domain, const std::string& id, PositionVector& shape) {
346  switch (domain) {
348  InductionLoop::storeShape(id, shape);
349  break;
351  Lane::storeShape(id, shape);
352  break;
354  Vehicle::storeShape(id, shape);
355  break;
357  Person::storeShape(id, shape);
358  break;
360  POI::storeShape(id, shape);
361  break;
363  Polygon::storeShape(id, shape);
364  break;
366  Junction::storeShape(id, shape);
367  break;
369  Edge::storeShape(id, shape);
370  break;
371  default:
372  break;
373  }
374 }
375 
376 
377 void
378 Helper::collectObjectsInRange(int domain, const PositionVector& shape, double range, std::set<std::string>& into) {
379  // build the look-up tree if not yet existing
380  if (myObjects.find(domain) == myObjects.end()) {
381  switch (domain) {
383  myObjects[CMD_GET_INDUCTIONLOOP_VARIABLE] = InductionLoop::getTree();
384  break;
389  myObjects[CMD_GET_EDGE_VARIABLE] = nullptr;
390  myObjects[CMD_GET_LANE_VARIABLE] = nullptr;
391  myObjects[CMD_GET_PERSON_VARIABLE] = nullptr;
392  myObjects[CMD_GET_VEHICLE_VARIABLE] = nullptr;
393  myLaneTree = new LANE_RTREE_QUAL(&MSLane::visit);
394  MSLane::fill(*myLaneTree);
395  break;
397  myObjects[CMD_GET_POI_VARIABLE] = POI::getTree();
398  break;
400  myObjects[CMD_GET_POLYGON_VARIABLE] = Polygon::getTree();
401  break;
403  myObjects[CMD_GET_JUNCTION_VARIABLE] = Junction::getTree();
404  break;
405  default:
406  break;
407  }
408  }
409  const Boundary b = shape.getBoxBoundary().grow(range);
410  const float cmin[2] = {(float) b.xmin(), (float) b.ymin()};
411  const float cmax[2] = {(float) b.xmax(), (float) b.ymax()};
412  switch (domain) {
417  Named::StoringVisitor sv(into);
418  myObjects[domain]->Search(cmin, cmax, sv);
419  }
420  break;
425  LaneStoringVisitor sv(into, shape, range, domain);
426  myLaneTree->Search(cmin, cmax, sv);
427  }
428  break;
429  default:
430  break;
431  }
432 }
433 
434 
435 
436 void
437 Helper::applySubscriptionFilters(const Subscription& s, std::set<std::string>& objIDs) {
438 #ifdef DEBUG_SURROUNDING
440  std::cout << SIMTIME << " applySubscriptionFilters for vehicle '" << _veh->getID() << "' on lane '" << _veh->getLane()->getID() <<"'"
441  << "\n on edge '" << _veh->getLane()->getEdge().getID() << "' (" << toString(_veh->getLane()->getEdge().getLanes()) << ")\n"
442  << "objIDs = " << toString(objIDs) << std::endl;
443 #endif
444 
445  if (s.activeFilters == 0) {
446  // No filters set
447  return;
448  }
449 
450  // Whether vehicles on opposite lanes shall be taken into account
451  const bool disregardOppositeDirection = (s.activeFilters & SUBS_FILTER_NOOPPOSITE) != 0;
452 
453  // Check filter specification consistency
454  // TODO: Warn only once
455  if (disregardOppositeDirection && (s.activeFilters & SUBS_FILTER_NO_RTREE) == 0) {
456  WRITE_WARNING("Ignoring no-opposite subscription filter for geographic range object collection. Consider using the 'lanes' filter.")
457  }
458 
459  // TODO: Treat case, where ego vehicle is currently on opposite lane
460 
461  std::set<const MSVehicle*> vehs;
463  // Set defaults for upstream and downstream distances
464  double downstreamDist = s.range, upstreamDist = s.range;
466  // Specifies maximal downstream distance for vehicles in context subscription result
467  downstreamDist = s.filterDownstreamDist;
468  }
470  // Specifies maximal downstream distance for vehicles in context subscription result
471  upstreamDist = s.filterUpstreamDist;
472  }
474  if (!v->isOnRoad()) {
475  return;
476  }
477  MSLane* vehLane = v->getLane();
478  if (vehLane == nullptr) {
479  return;
480  }
481  MSEdge* vehEdge = &vehLane->getEdge();
482  std::vector<int> filterLanes;
483  if ((s.activeFilters & SUBS_FILTER_LANES) == 0) {
484  // No lane indices are specified (but downstream and/or upstream distance)
485  // -> use only vehicle's current lane as origin for the searches
486  filterLanes = {0};
487  // Lane indices must be specified when leader/follower information is requested.
488  assert((s.activeFilters & SUBS_FILTER_LEAD_FOLLOW) == 0);
489  } else {
490  filterLanes = s.filterLanes;
491  }
492 
493 #ifdef DEBUG_SURROUNDING
494  std::cout << "Filter lanes: " << toString(filterLanes) << std::endl;
495  std::cout << "Downstream distance: " << downstreamDist << std::endl;
496  std::cout << "Upstream distance: " << upstreamDist << std::endl;
497 #endif
498 
500  // Maneuver filters disables road net search for all surrounding vehicles
502  // Return leader and follower on the specified lanes in context subscription result.
503  for (int offset : filterLanes) {
504  MSLane* lane = v->getLane()->getParallelLane(offset);
505  if (lane != nullptr) {
506  // this is a non-opposite lane
507  MSVehicle* leader = lane->getLeader(v, v->getPositionOnLane(), v->getBestLanesContinuation(lane), downstreamDist).first;
508  MSVehicle* follower = lane->getFollower(v, v->getPositionOnLane(), upstreamDist, false).first;
509  vehs.insert(vehs.end(), leader);
510  vehs.insert(vehs.end(), follower);
511 
512 #ifdef DEBUG_SURROUNDING
513  std::cout << "Lane at index " << offset << ": '" << lane->getID() << std::endl;
514  std::cout << "Leader: '" << (leader != nullptr ? leader->getID() : "NULL") << "'" << std::endl;
515  std::cout << "Follower: '" << (follower != nullptr ? follower->getID() : "NULL") << "'" << std::endl;
516 #endif
517 
518  } else if (!disregardOppositeDirection && offset > 0) { // TODO: offset<0 may indicate opposite query when vehicle is on opposite itself
519  // check whether ix points to an opposite lane
520  const MSEdge* opposite = vehEdge->getOppositeEdge();
521  if (opposite == nullptr) {
522 #ifdef DEBUG_SURROUNDING
523  std::cout << "No lane at index " << offset << std::endl;
524 #endif
525  // no opposite edge
526  continue;
527  }
528  // Index of opposite lane at relative offset
529  const int ix_opposite = (int)opposite->getLanes().size() - 1 - (vehLane->getIndex() + offset - (int)vehEdge->getLanes().size());
530  if (ix_opposite < 0) {
531 #ifdef DEBUG_SURROUNDING
532  std::cout << "No lane on opposite at index " << ix_opposite << std::endl;
533 #endif
534  // no opposite edge
535  continue;
536  }
537  lane = opposite->getLanes()[ix_opposite];
538  // Search vehs along opposite lanes (swap upstream and downstream distance)
539  // XXX transformations for curved geometries
540  double posOnOpposite = MAX2(0., opposite->getLength() - v->getPositionOnLane());
541  // Get leader on opposite
542  vehs.insert(vehs.end(), lane->getFollower(v, posOnOpposite, downstreamDist, true).first);
543  // Get follower (no search on consecutive lanes
544  vehs.insert(vehs.end(), lane->getLeader(v, posOnOpposite-v->getLength(), std::vector<MSLane*>()).first);
545  }
546  }
547  }
548 
550  // Get upcoming junctions and vialanes within downstream distance, where foe links exist or at least the link direction is not straight
551  MSLane* lane = v->getLane();
552  std::vector<const MSLink*> links = lane->getUpcomingLinks(v->getPositionOnLane(), downstreamDist, v->getBestLanesContinuation());
553 #ifdef DEBUG_SURROUNDING
554  std::cout << "Applying turn filter for vehicle '" << v->getID() << "'\n Gathering foes ..." << std::endl;
555 #endif
556  // Iterate through junctions and find approaching foes within upstreamDist.
557  for (auto& l : links) {
558 #ifdef DEBUG_SURROUNDING
559  std::cout << " On junction '" << l->getJunction()->getID() << "' (no. foe links = " << l->getFoeLinks().size() << "):" << std::endl;
560 #endif
561  for(auto& foeLane : l->getFoeLanes()) {
562  // Check vehicles approaching the entry link corresponding to this lane
563  const MSLink* foeLink = foeLane->getEntryLink();
564  for (auto& vi : foeLink->getApproaching()) {
565  if (vi.second.dist <= upstreamDist) {
566 #ifdef DEBUG_SURROUNDING
567  std::cout << " Approaching from foe-lane '" << vi.first->getID() << "'" << std::endl;
568 #endif
569  vehs.insert(vehs.end(), dynamic_cast<const MSVehicle*>(vi.first));
570  }
571  }
572  // add vehicles currently on the junction
573  for (const MSVehicle* foe : foeLane->getVehiclesSecure()) {
574  vehs.insert(vehs.end(), foe);
575  }
576  foeLane->releaseVehicles();
577  }
578  }
579  }
580 #ifdef DEBUG_SURROUNDING
581  std::cout << SIMTIME << " applySubscriptionFilters() for veh '" << v->getID() << "'. Found the following vehicles:\n";
582  for (auto veh : vehs) {
583  if (veh != nullptr) {
584  std::cout << " '" << veh->getID() << "' on lane '" << veh->getLane()->getID() << "'\n";
585  }
586  }
587 #endif
588  } else {
589  // No maneuver filters requested, but only lanes filter (directly, or indirectly by specifying downstream or upstream distance)
590  assert(filterLanes.size() > 0);
591  // This is to remember the lanes checked in the driving direction of the vehicle (their opposites can be added in a second pass)
592  auto checkedLanesInDrivingDir = std::make_shared<LaneCoverageInfo>();
593  for (int offset : filterLanes){
594  MSLane* lane = vehLane->getParallelLane(offset);
595  if (lane != nullptr) {
596 #ifdef DEBUG_SURROUNDING
597  std::cout << "Checking for surrounding vehicles starting on lane '" << lane->getID() << "' at index " << offset << std::endl;
598 #endif
599  // Search vehs along this lane
600  // (Coverage info is collected per origin lane since lanes reached from neighboring lanes may have different distances
601  // and aborting at previously scanned when coming from a closer origin may prevent scanning of parts that should be included.)
602  std::shared_ptr<LaneCoverageInfo> checkedLanes = std::make_shared<LaneCoverageInfo>();
603  const std::set<MSVehicle*> new_vehs = lane->getSurroundingVehicles(v->getPositionOnLane(), downstreamDist, upstreamDist+v->getLength(), checkedLanes);
604  vehs.insert(new_vehs.begin(), new_vehs.end());
605  fuseLaneCoverage(checkedLanesInDrivingDir, checkedLanes);
606  } else if (!disregardOppositeDirection && offset > 0) {
607  // Check opposite edge, too
608  assert(vehLane->getIndex() + (unsigned int) offset >= vehEdge->getLanes().size()); // index points beyond this edge
609  const MSEdge* opposite = vehEdge->getOppositeEdge();
610  if (opposite == nullptr) {
611 #ifdef DEBUG_SURROUNDING
612  std::cout << "No opposite edge, thus no lane at index " << offset << std::endl;
613 #endif
614  // no opposite edge
615  continue;
616  }
617  // Index of opposite lane at relative offset
618  const int ix_opposite = (int)opposite->getLanes().size() - 1 - (vehLane->getIndex() + offset - (int)vehEdge->getLanes().size());
619  if (ix_opposite < 0) {
620 #ifdef DEBUG_SURROUNDING
621  std::cout << "No lane on opposite at index " << ix_opposite << std::endl;
622 #endif
623  // no opposite edge
624  continue;
625  }
626  lane = opposite->getLanes()[ix_opposite];
627  // Search vehs along opposite lanes (swap upstream and downstream distance)
628  const std::set<MSVehicle*> new_vehs = lane->getSurroundingVehicles(lane->getLength() - v->getPositionOnLane(), upstreamDist+v->getLength(), downstreamDist, std::make_shared<LaneCoverageInfo>());
629  vehs.insert(new_vehs.begin(), new_vehs.end());
630  }
631 #ifdef DEBUG_SURROUNDING
632  else {
633  std::cout << "No lane at index " << offset << std::endl;
634  }
635 #endif
636 
637  if (!disregardOppositeDirection) {
638  // If opposite should be checked, do this for each lane of the search tree in checkedLanesInDrivingDir
639  // (For instance, some opposite lanes of these would not be obtained if the ego lane does not have an opposite.)
640 
641  // Number of opposite lanes to be checked (assumes filterLanes.size()>0, see assertion above) determined as hypothetical offset
642  // overlap into opposing edge from the vehicle's current lane.
643  // TODO: offset<0 may indicate opposite query when vehicle is on opposite itself (-> use min_element(filterLanes...) instead, etc)
644  const int nOpp = MAX2(0, (*std::max_element(filterLanes.begin(), filterLanes.end())) - ((int)vehEdge->getLanes().size() - 1 - vehLane->getIndex()));
645  // Collect vehicles from opposite lanes
646  if (nOpp > 0) {
647  for (auto& laneCov : *checkedLanesInDrivingDir) {
648  const MSLane* lane = laneCov.first;
649  if (lane == nullptr || lane->getEdge().getOppositeEdge() == nullptr) {
650  continue;
651  }
652  const MSEdge* edge = &(lane->getEdge());
653  const MSEdge* opposite = edge->getOppositeEdge();
654  const std::pair<double, double>& range = laneCov.second;
655  auto leftMostOppositeLaneIt = opposite->getLanes().rbegin();
656  for (auto oppositeLaneIt = leftMostOppositeLaneIt;
657  oppositeLaneIt != opposite->getLanes().rend(); ++oppositeLaneIt) {
658  if ((int)(oppositeLaneIt - leftMostOppositeLaneIt) == nOpp) {
659  break;
660  }
661  // Add vehicles from corresponding range on opposite direction
662  const MSLane* oppositeLane = *oppositeLaneIt;
663  auto new_vehs = oppositeLane->getVehiclesInRange(lane->getLength()-range.second, lane->getLength()-range.first);
664  vehs.insert(new_vehs.begin(), new_vehs.end());
665  }
666  }
667  }
668  }
669 #ifdef DEBUG_SURROUNDING
670  std::cout << SIMTIME << " applySubscriptionFilters() for veh '" << v->getID() << "'. Found the following vehicles:\n";
671  for (auto veh : vehs) {
672  if (veh != nullptr) {
673  std::cout << " '" << veh->getID() << "' on lane '" << veh->getLane()->getID() << "'\n";
674  }
675  }
676 #endif
677  }
678 
679  // filter vehicles in vehs by class and/or type if requested
681  // Only return vehicles of the given vClass in context subscription result
682  auto i = vehs.begin();
683  while (i != vehs.end()) {
684  if (((*i)->getVehicleType().getVehicleClass() & s.filterVClasses) == 0) {
685  i = vehs.erase(i);
686  } else {
687  ++i;
688  }
689  }
690  }
692  // Only return vehicles of the given vType in context subscription result
693  auto i = vehs.begin();
694  while (i != vehs.end()) {
695  if (s.filterVTypes.find((*i)->getVehicleType().getID()) == s.filterVTypes.end()) {
696  i = vehs.erase(i);
697  } else {
698  ++i;
699  }
700  }
701  }
702  }
703  // Write vehs IDs in objIDs
704  for (const MSVehicle* veh : vehs) {
705  if (veh != nullptr) {
706  objIDs.insert(objIDs.end(), veh->getID());
707  }
708  }
709  } else {
710  // filter vehicles in vehs by class and/or type if requested
712  // Only return vehicles of the given vClass in context subscription result
713  auto i = objIDs.begin();
714  while (i != objIDs.end()) {
716  if ((veh->getVehicleType().getVehicleClass() & s.filterVClasses) == 0) {
717  i = objIDs.erase(i);
718  } else {
719  ++i;
720  }
721  }
722  }
724  // Only return vehicles of the given vType in context subscription result
725  auto i = objIDs.begin();
726  while (i != objIDs.end()) {
728  if (s.filterVTypes.find(veh->getVehicleType().getID()) == s.filterVTypes.end()) {
729  i = objIDs.erase(i);
730  } else {
731  ++i;
732  }
733  }
734  }
735  }
736 }
737 
738 void
739 Helper::setRemoteControlled(MSVehicle* v, Position xyPos, MSLane* l, double pos, double posLat, double angle,
740  int edgeOffset, ConstMSEdgeVector route, SUMOTime t) {
741  myRemoteControlledVehicles[v->getID()] = v;
742  v->getInfluencer().setRemoteControlled(xyPos, l, pos, posLat, angle, edgeOffset, route, t);
743 }
744 
745 void
746 Helper::setRemoteControlled(MSPerson* p, Position xyPos, MSLane* l, double pos, double posLat, double angle,
747  int edgeOffset, ConstMSEdgeVector route, SUMOTime t) {
748  myRemoteControlledPersons[p->getID()] = p;
749  p->getInfluencer().setRemoteControlled(xyPos, l, pos, posLat, angle, edgeOffset, route, t);
750 }
751 
752 
753 void
754 Helper::postProcessRemoteControl() {
755  for (auto& controlled : myRemoteControlledVehicles) {
756  if (MSNet::getInstance()->getVehicleControl().getVehicle(controlled.first) != nullptr) {
757  controlled.second->getInfluencer().postProcessRemoteControl(controlled.second);
758  } else {
759  WRITE_WARNING("Vehicle '" + controlled.first + "' was removed though being controlled by TraCI");
760  }
761  }
762  myRemoteControlledVehicles.clear();
763  for (auto& controlled : myRemoteControlledPersons) {
764  if (MSNet::getInstance()->getPersonControl().get(controlled.first) != nullptr) {
765  controlled.second->getInfluencer().postProcessRemoteControl(controlled.second);
766  } else {
767  WRITE_WARNING("Person '" + controlled.first + "' was removed though being controlled by TraCI");
768  }
769  }
770  myRemoteControlledPersons.clear();
771 }
772 
773 
774 bool
775 Helper::moveToXYMap(const Position& pos, double maxRouteDistance, bool mayLeaveNetwork, const std::string& origID, const double angle,
776  double speed, const ConstMSEdgeVector& currentRoute, const int routePosition, MSLane* currentLane, double currentLanePos, bool onRoad,
777  double& bestDistance, MSLane** lane, double& lanePos, int& routeOffset, ConstMSEdgeVector& edges) {
778  // collect edges around the vehicle/person
779  const MSEdge* const currentRouteEdge = currentRoute[routePosition];
780  std::set<std::string> into;
781  PositionVector shape;
782  shape.push_back(pos);
783  collectObjectsInRange(CMD_GET_EDGE_VARIABLE, shape, maxRouteDistance, into);
784  double maxDist = 0;
785  std::map<MSLane*, LaneUtility> lane2utility;
786  // compute utility for all candidate edges
787  for (std::set<std::string>::const_iterator j = into.begin(); j != into.end(); ++j) {
788  const MSEdge* const e = MSEdge::dictionary(*j);
789  const MSEdge* prevEdge = nullptr;
790  const MSEdge* nextEdge = nullptr;
791  bool onRoute = false;
792  // the next if/the clause sets "onRoute", "prevEdge", and "nextEdge", depending on
793  // whether the currently seen edge is an internal one or a normal one
794  if (!e->isInternal()) {
795 #ifdef DEBUG_MOVEXY_ANGLE
796  std::cout << "Ego on normal" << std::endl;
797 #endif
798  // a normal edge
799  //
800  // check whether the currently seen edge is in the vehicle's route
801  // - either the one it's on or one of the next edges
802  ConstMSEdgeVector::const_iterator searchStart = currentRoute.begin() + routePosition;
803  if (onRoad && currentLane->getEdge().isInternal()) {
804  ++searchStart;
805  }
806  ConstMSEdgeVector::const_iterator edgePos = std::find(searchStart, currentRoute.end(), e);
807  onRoute = edgePos != currentRoute.end(); // no? -> onRoute is false
808  if (edgePos == currentRoute.end() - 1 && currentRouteEdge == e) {
809  // onRoute is false as well if the vehicle is beyond the edge
810  onRoute &= currentRouteEdge->getLength() > currentLanePos + SPEED2DIST(speed);
811  }
812  // save prior and next edges
813  prevEdge = e;
814  nextEdge = !onRoute || edgePos == currentRoute.end() - 1 ? nullptr : *(edgePos + 1);
815 #ifdef DEBUG_MOVEXY_ANGLE
816  std::cout << "normal:" << e->getID() << " prev:" << prevEdge->getID() << " next:";
817  if (nextEdge != 0) {
818  std::cout << nextEdge->getID();
819  }
820  std::cout << std::endl;
821 #endif
822  } else {
823 #ifdef DEBUG_MOVEXY_ANGLE
824  std::cout << "Ego on internal" << std::endl;
825 #endif
826  // an internal edge
827  // get the previous edge
828  prevEdge = e;
829  while (prevEdge != nullptr && prevEdge->isInternal()) {
830  MSLane* l = prevEdge->getLanes()[0];
831  l = l->getLogicalPredecessorLane();
832  prevEdge = l == nullptr ? nullptr : &l->getEdge();
833  }
834  // check whether the previous edge is on the route (was on the route)
835  ConstMSEdgeVector::const_iterator prevEdgePos = std::find(currentRoute.begin() + routePosition, currentRoute.end(), prevEdge);
836  nextEdge = e;
837  while (nextEdge != nullptr && nextEdge->isInternal()) {
838  nextEdge = nextEdge->getSuccessors()[0]; // should be only one for an internal edge
839  }
840  if (prevEdgePos != currentRoute.end() && (prevEdgePos + 1) != currentRoute.end()) {
841  onRoute = *(prevEdgePos + 1) == nextEdge;
842  }
843 #ifdef DEBUG_MOVEXY_ANGLE
844  std::cout << "internal:" << e->getID() << " prev:" << prevEdge->getID() << " next:" << nextEdge->getID() << std::endl;
845 #endif
846  }
847 
848 
849  // weight the lanes...
850  const std::vector<MSLane*>& lanes = e->getLanes();
851  const bool perpendicular = false;
852  for (std::vector<MSLane*>::const_iterator k = lanes.begin(); k != lanes.end(); ++k) {
853  MSLane* lane = *k;
854  double langle = 180.;
855  double dist = FAR_AWAY;
856  double perpendicularDist = FAR_AWAY;
857  double off = lane->getShape().nearest_offset_to_point2D(pos, true);
858  if (off != GeomHelper::INVALID_OFFSET) {
859  perpendicularDist = lane->getShape().distance2D(pos, true);
860  }
861  off = lane->getShape().nearest_offset_to_point2D(pos, perpendicular);
862  if (off != GeomHelper::INVALID_OFFSET) {
863  dist = lane->getShape().distance2D(pos, perpendicular);
864  langle = GeomHelper::naviDegree(lane->getShape().rotationAtOffset(off));
865  }
866  bool sameEdge = onRoad && &lane->getEdge() == &currentLane->getEdge() && currentRouteEdge->getLength() > currentLanePos + SPEED2DIST(speed);
867  /*
868  const MSEdge* rNextEdge = nextEdge;
869  while(rNextEdge==0&&lane->getEdge().getPurpose()==MSEdge::EDGEFUNCTION_INTERNAL) {
870  MSLane* next = lane->getLinkCont()[0]->getLane();
871  rNextEdge = next == 0 ? 0 : &next->getEdge();
872  }
873  */
874  double dist2 = dist;
875  if (mayLeaveNetwork && dist != perpendicularDist) {
876  // ambiguous mapping. Don't trust this
877  dist2 = FAR_AWAY;
878  }
879  const double angleDiff = (angle == INVALID_DOUBLE_VALUE ? 0 : GeomHelper::getMinAngleDiff(angle, langle));
880 #ifdef DEBUG_MOVEXY_ANGLE
881  std::cout << lane->getID() << " lAngle:" << langle << " lLength=" << lane->getLength()
882  << " angleDiff:" << angleDiff
883  << " off:" << off
884  << " pDist=" << perpendicularDist
885  << " dist=" << dist
886  << " dist2=" << dist2
887  << "\n";
888  std::cout << lane->getID() << " param=" << lane->getParameter(SUMO_PARAM_ORIGID, lane->getID()) << " origID='" << origID << "\n";
889 #endif
890  lane2utility[lane] = LaneUtility(
891  dist2, perpendicularDist, off, angleDiff,
892  lane->getParameter(SUMO_PARAM_ORIGID, lane->getID()) == origID,
893  onRoute, sameEdge, prevEdge, nextEdge);
894  // update scaling value
895  maxDist = MAX2(maxDist, MIN2(dist, SUMO_const_laneWidth));
896 
897  }
898  }
899 
900  // get the best lane given the previously computed values
901  double bestValue = 0;
902  MSLane* bestLane = nullptr;
903  for (std::map<MSLane*, LaneUtility>::iterator i = lane2utility.begin(); i != lane2utility.end(); ++i) {
904  MSLane* l = (*i).first;
905  const LaneUtility& u = (*i).second;
906  double distN = u.dist > 999 ? -10 : 1. - (u.dist / maxDist);
907  double angleDiffN = 1. - (u.angleDiff / 180.);
908  double idN = u.ID ? 1 : 0;
909  double onRouteN = u.onRoute ? 1 : 0;
910  double sameEdgeN = u.sameEdge ? MIN2(currentRouteEdge->getLength() / speed, (double)1.) : 0;
911  double value = (distN * .5 // distance is more important than angle because the vehicle might be driving in the opposite direction
912  + angleDiffN * 0.35 /*.5 */
913  + idN * 1
914  + onRouteN * 0.1
915  + sameEdgeN * 0.1);
916 #ifdef DEBUG_MOVEXY
917  std::cout << " x; l:" << l->getID() << " d:" << u.dist << " dN:" << distN << " aD:" << angleDiffN <<
918  " ID:" << idN << " oRN:" << onRouteN << " sEN:" << sameEdgeN << " value:" << value << std::endl;
919 #endif
920  if (value > bestValue || bestLane == nullptr) {
921  bestValue = value;
922  if (u.dist == FAR_AWAY) {
923  bestLane = nullptr;
924  } else {
925  bestLane = l;
926  }
927  }
928  }
929  // no best lane found, return
930  if (bestLane == nullptr) {
931  return false;
932  }
933  const LaneUtility& u = lane2utility.find(bestLane)->second;
934  bestDistance = u.dist;
935  *lane = bestLane;
936  lanePos = bestLane->getShape().nearest_offset_to_point2D(pos, false);
937  const MSEdge* prevEdge = u.prevEdge;
938  if (u.onRoute) {
939  ConstMSEdgeVector::const_iterator prevEdgePos = std::find(currentRoute.begin(), currentRoute.end(), prevEdge);
940  routeOffset = (int)std::distance(currentRoute.begin(), prevEdgePos);
941  //std::cout << SIMTIME << "moveToXYMap vehicle=" << veh.getID() << " currLane=" << veh.getLane()->getID() << " routeOffset=" << routeOffset << " edges=" << toString(ev) << " bestLane=" << bestLane->getID() << " prevEdge=" << prevEdge->getID() << "\n";
942  } else {
943  edges.push_back(u.prevEdge);
944  /*
945  if(bestLane->getEdge().getPurpose()!=MSEdge::EDGEFUNCTION_INTERNAL) {
946  edges.push_back(&bestLane->getEdge());
947  }
948  */
949  if (u.nextEdge != nullptr) {
950  edges.push_back(u.nextEdge);
951  }
952  routeOffset = 0;
953 #ifdef DEBUG_MOVEXY_ANGLE
954  std::cout << "internal2: lane=" << bestLane->getID() << " prev=" << Named::getIDSecure(u.prevEdge) << " next=" << Named::getIDSecure(u.nextEdge) << "\n";;
955 #endif
956  }
957  return true;
958 }
959 
960 
961 bool
962 Helper::findCloserLane(const MSEdge* edge, const Position& pos, double& bestDistance, MSLane** lane) {
963  if (edge == nullptr) {
964  return false;
965  }
966  const std::vector<MSLane*>& lanes = edge->getLanes();
967  bool newBest = false;
968  for (std::vector<MSLane*>::const_iterator k = lanes.begin(); k != lanes.end() && bestDistance > POSITION_EPS; ++k) {
969  MSLane* candidateLane = *k;
970  const double dist = candidateLane->getShape().distance2D(pos); // get distance
971 #ifdef DEBUG_MOVEXY
972  std::cout << " b at lane " << candidateLane->getID() << " dist:" << dist << " best:" << bestDistance << std::endl;
973 #endif
974  if (dist < bestDistance) {
975  // is the new distance the best one? keep then...
976  bestDistance = dist;
977  *lane = candidateLane;
978  newBest = true;
979  }
980  }
981  return newBest;
982 }
983 
984 
985 bool
986 Helper::moveToXYMap_matchingRoutePosition(const Position& pos, const std::string& origID,
987  const ConstMSEdgeVector& currentRoute, int routeIndex,
988  double& bestDistance, MSLane** lane, double& lanePos, int& routeOffset) {
989  //std::cout << "moveToXYMap_matchingRoutePosition pos=" << pos << "\n";
990  routeOffset = 0;
991  // routes may be looped which makes routeOffset ambiguous. We first try to
992  // find the closest upcoming edge on the route and then look for closer passed edges
993 
994  // look forward along the route
995  const MSEdge* prev = nullptr;
996  for (int i = routeIndex; i < (int)currentRoute.size(); ++i) {
997  const MSEdge* cand = currentRoute[i];
998  while (prev != nullptr) {
999  // check internal edge(s)
1000  const MSEdge* internalCand = prev->getInternalFollowingEdge(cand);
1001  findCloserLane(internalCand, pos, bestDistance, lane);
1002  prev = internalCand;
1003  }
1004  if (findCloserLane(cand, pos, bestDistance, lane)) {
1005  routeOffset = i;
1006  }
1007  prev = cand;
1008  }
1009  // look backward along the route
1010  const MSEdge* next = currentRoute[routeIndex];
1011  for (int i = routeIndex; i >= 0; --i) {
1012  const MSEdge* cand = currentRoute[i];
1013  //std::cout << " next=" << next->getID() << " cand=" << cand->getID() << " i=" << i << " routeIndex=" << routeIndex << "\n";
1014  prev = cand;
1015  while (prev != nullptr) {
1016  // check internal edge(s)
1017  const MSEdge* internalCand = prev->getInternalFollowingEdge(next);
1018  if (findCloserLane(internalCand, pos, bestDistance, lane)) {
1019  routeOffset = i;
1020  }
1021  prev = internalCand;
1022  }
1023  if (findCloserLane(cand, pos, bestDistance, lane)) {
1024  routeOffset = i;
1025  }
1026  next = cand;
1027  }
1028 
1029  assert(lane != 0);
1030  // quit if no solution was found, reporting a failure
1031  if (lane == nullptr) {
1032 #ifdef DEBUG_MOVEXY
1033  std::cout << " b failed - no best route lane" << std::endl;
1034 #endif
1035  return false;
1036  }
1037 
1038 
1039  // position may be inaccurate; let's checkt the given index, too
1040  // @note: this is enabled for non-internal lanes only, as otherwise the position information may ambiguous
1041  if (!(*lane)->getEdge().isInternal()) {
1042  const std::vector<MSLane*>& lanes = (*lane)->getEdge().getLanes();
1043  for (std::vector<MSLane*>::const_iterator i = lanes.begin(); i != lanes.end(); ++i) {
1044  if ((*i)->getParameter(SUMO_PARAM_ORIGID, (*i)->getID()) == origID) {
1045  *lane = *i;
1046  break;
1047  }
1048  }
1049  }
1050  // check position, stuff, we should have the best lane along the route
1051  lanePos = MAX2(0., MIN2(double((*lane)->getLength() - POSITION_EPS),
1052  (*lane)->interpolateGeometryPosToLanePos(
1053  (*lane)->getShape().nearest_offset_to_point2D(pos, false))));
1054  //std::cout << SIMTIME << " moveToXYMap_matchingRoutePosition vehicle=" << veh.getID() << " currLane=" << veh.getLane()->getID() << " routeOffset=" << routeOffset << " edges=" << toString(edges) << " lane=" << (*lane)->getID() << "\n";
1055 #ifdef DEBUG_MOVEXY
1056  std::cout << " b ok lane " << (*lane)->getID() << " lanePos:" << lanePos << std::endl;
1057 #endif
1058  return true;
1059 }
1060 
1061 
1062 Helper::SubscriptionWrapper::SubscriptionWrapper(VariableWrapper::SubscriptionHandler handler, SubscriptionResults& into, ContextSubscriptionResults& context)
1063  : VariableWrapper(handler), myResults(into), myContextResults(context), myActiveResults(into) {
1064 
1065 }
1066 
1067 
1068 void
1069 Helper::SubscriptionWrapper::setContext(const std::string& refID) {
1070  myActiveResults = refID == "" ? myResults : myContextResults[refID];
1071 }
1072 
1073 
1074 bool
1075 Helper::SubscriptionWrapper::wrapDouble(const std::string& objID, const int variable, const double value) {
1076  myActiveResults[objID][variable] = std::make_shared<TraCIDouble>(value);
1077  return true;
1078 }
1079 
1080 
1081 bool
1082 Helper::SubscriptionWrapper::wrapInt(const std::string& objID, const int variable, const int value) {
1083  myActiveResults[objID][variable] = std::make_shared<TraCIInt>(value);
1084  return true;
1085 }
1086 
1087 
1088 bool
1089 Helper::SubscriptionWrapper::wrapString(const std::string& objID, const int variable, const std::string& value) {
1090  myActiveResults[objID][variable] = std::make_shared<TraCIString>(value);
1091  return true;
1092 }
1093 
1094 
1095 bool
1096 Helper::SubscriptionWrapper::wrapStringList(const std::string& objID, const int variable, const std::vector<std::string>& value) {
1097  auto sl = std::make_shared<TraCIStringList>();
1098  sl->value = value;
1099  myActiveResults[objID][variable] = sl;
1100  return true;
1101 }
1102 
1103 
1104 bool
1105 Helper::SubscriptionWrapper::wrapPosition(const std::string& objID, const int variable, const TraCIPosition& value) {
1106  myActiveResults[objID][variable] = std::make_shared<TraCIPosition>(value);
1107  return true;
1108 }
1109 
1110 
1111 bool
1112 Helper::SubscriptionWrapper::wrapColor(const std::string& objID, const int variable, const TraCIColor& value) {
1113  myActiveResults[objID][variable] = std::make_shared<TraCIColor>(value);
1114  return true;
1115 }
1116 
1117 
1118 void
1119 Helper::VehicleStateListener::vehicleStateChanged(const SUMOVehicle* const vehicle, MSNet::VehicleState to, const std::string& /*info*/) {
1120  myVehicleStateChanges[to].push_back(vehicle->getID());
1121 }
1122 
1123 
1124 }
1125 
1126 
1127 /****************************************************************************/
static double getMinAngleDiff(double angle1, double angle2)
Returns the minimum distance (clockwise/counter-clockwise) between both angles.
Definition: GeomHelper.cpp:161
std::pair< MSVehicle *const, double > getFollower(const MSVehicle *ego, double egoPos, double dist, bool ignoreMinorLinks) const
Find follower vehicle for the given ego vehicle (which may be on the opposite direction lane) ...
Definition: MSLane.cpp:3380
unsigned char g
Definition: TraCIDefs.h:139
std::map< std::string, TraCIResults > SubscriptionResults
{object->{variable->value}}
Definition: TraCIDefs.h:199
const MSEdge * prevEdge
Definition: Helper.h:179
#define FAR_AWAY
Definition: Helper.cpp:54
MSLane * getLogicalPredecessorLane() const
get the most likely precedecessor lane (sorted using by_connections_to_sorter). The result is cached ...
Definition: MSLane.cpp:2407
double ymin() const
Returns minimum y-coordinate.
Definition: Boundary.cpp:131
const MSEdge * nextEdge
Definition: Helper.h:180
#define CMD_SUBSCRIBE_VEHICLE_CONTEXT
double xmax() const
Returns maximum x-coordinate.
Definition: Boundary.cpp:125
double getLength() const
Returns the vehicle&#39;s length.
MSEdge & getEdge() const
Returns the lane&#39;s edge.
Definition: MSLane.h:640
Representation of a vehicle in the micro simulation.
Definition: MSVehicle.h:79
Representation of a subscription.
Definition: Subscription.h:65
long long int SUMOTime
Definition: SUMOTime.h:36
double range
The range of the context.
Definition: Subscription.h:98
#define CMD_GET_TL_VARIABLE
#define CMD_SUBSCRIBE_JUNCTION_CONTEXT
#define SPEED2DIST(x)
Definition: SUMOTime.h:48
const int myDomain
Definition: Helper.h:67
std::set< MSVehicle * > getSurroundingVehicles(double startPos, double downstreamDist, double upstreamDist, std::shared_ptr< LaneCoverageInfo > checkedLanes) const
Returns all vehicles closer than downstreamDist along the along the road network starting on the give...
Definition: MSLane.cpp:3212
double z() const
Returns the z-position.
Definition: Position.h:67
#define CMD_GET_VEHICLE_VARIABLE
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) ...
#define LANE_RTREE_QUAL
Definition: Helper.h:77
MSLane * getLane() const
Returns the lane the vehicle is on.
Definition: MSVehicle.h:565
#define CMD_GET_INDUCTIONLOOP_VARIABLE
bool wrapDouble(const std::string &objID, const int variable, const double value)
Definition: Helper.cpp:1075
bool wrapString(const std::string &objID, const int variable, const std::string &value)
Definition: Helper.cpp:1089
static void fill(RTREE &into)
Fills the given RTree with lane instances.
Definition: MSLane.cpp:1770
unsigned char alpha() const
Returns the alpha-amount of the color.
Definition: RGBColor.h:84
const double SUMO_const_laneWidth
Definition: StdDefs.h:51
double y() const
Returns the y-position.
Definition: Position.h:62
double getPositionOnLane() const
Get the vehicle&#39;s position along the lane.
Definition: MSVehicle.h:403
#define CMD_GET_LANEAREA_VARIABLE
#define CMD_GET_PERSON_VARIABLE
double x() const
Returns the x-position.
Definition: Position.h:57
void setRemoteControlled(Position xyPos, MSLane *l, double pos, double posLat, double angle, int edgeOffset, const ConstMSEdgeVector &route, SUMOTime t)
Definition: MSPerson.cpp:715
const std::vector< MSLane * > & getLanes() const
Returns this edge&#39;s lanes.
Definition: MSEdge.h:162
static MSNet * getInstance()
Returns the pointer to the unique instance of MSNet (singleton).
Definition: MSNet.cpp:165
T MAX2(T a, T b)
Definition: StdDefs.h:76
void visit(const LaneStoringVisitor &cont) const
Callback for visiting the lane when traversing an RTree.
Definition: MSLane.h:1126
std::set< MSVehicle * > getVehiclesInRange(double a, double b) const
Returns all vehicles on the lane overlapping with the interval [a,b].
Definition: MSLane.cpp:3264
double getLength() const
Returns the lane&#39;s length.
Definition: MSLane.h:514
virtual const VehCont & getVehiclesSecure() const
Returns the vehicles container; locks it for microsimulation.
Definition: MSLane.h:406
const PositionVector & getShape() const
Returns this lane&#39;s shape.
Definition: MSLane.h:456
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:71
#define CMD_SUBSCRIBE_POLYGON_CONTEXT
static bool dictionary(const std::string &id, MSEdge *edge)
Inserts edge into the static dictionary Returns true if the key id isn&#39;t already in the dictionary...
Definition: MSEdge.cpp:788
double rotationAtOffset(double pos) const
Returns the rotation at the given length.
unsigned char blue() const
Returns the blue-amount of the color.
Definition: RGBColor.h:77
std::map< std::string, SubscriptionResults > ContextSubscriptionResults
Definition: TraCIDefs.h:200
#define CMD_GET_POLYGON_VARIABLE
ContextSubscriptionResults myContextResults
Definition: Helper.h:196
std::vector< const MSEdge * > ConstMSEdgeVector
Definition: MSEdge.h:72
SubscriptionResults & myActiveResults
Definition: Helper.h:197
const std::string & getID() const
Returns the id.
Definition: Named.h:78
#define TIME2STEPS(x)
Definition: SUMOTime.h:60
bool wrapPosition(const std::string &objID, const int variable, const TraCIPosition &value)
Definition: Helper.cpp:1105
double getLength() const
return the length of the edge
Definition: MSEdge.h:568
std::vector< MSTransportable * > getSortedPersons(SUMOTime timestep, bool includeRiding=false) const
Returns this edge&#39;s persons sorted by pos.
Definition: MSEdge.cpp:929
void addVehicleStateListener(VehicleStateListener *listener)
Adds a vehicle states listener.
Definition: MSNet.cpp:838
#define CMD_GET_ROUTE_VARIABLE
A class that stores a 2D geometrical boundary.
Definition: Boundary.h:42
#define CMD_SUBSCRIBE_INDUCTIONLOOP_CONTEXT
#define WRITE_WARNING(msg)
Definition: MsgHandler.h:241
#define SIMTIME
Definition: SUMOTime.h:65
std::vector< std::string > getEdgeNames() const
Returns the list of names of all known edges.
std::string id
The id of the object that is subscribed.
Definition: Subscription.h:86
bool wrapColor(const std::string &objID, const int variable, const TraCIColor &value)
Definition: Helper.cpp:1112
int commandId
commandIdArg The command id of the subscription
Definition: Subscription.h:84
#define CMD_SUBSCRIBE_LANE_CONTEXT
unsigned char b
Definition: TraCIDefs.h:139
#define CMD_GET_VEHICLETYPE_VARIABLE
A road/street connecting two junctions.
Definition: MSEdge.h:75
bool isOnRoad() const
Returns the information whether the vehicle is on a road (is simulated)
Definition: MSVehicle.h:587
#define INVALID_DOUBLE_VALUE
Definition: TraCIDefs.h:42
int activeFilters
Active filters for the subscription (bitset,.
Definition: Subscription.h:101
static double naviDegree(const double angle)
Definition: GeomHelper.cpp:180
int getIndex() const
Returns the lane&#39;s index.
Definition: MSLane.h:537
#define TRACI_ID_LIST
Influencer & getInfluencer()
Returns the velocity/lane influencer.
Definition: MSPerson.cpp:690
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition: ToString.h:49
Representation of a vehicle.
Definition: SUMOVehicle.h:60
int contextDomain
The domain ID of the context.
Definition: Subscription.h:96
double filterDownstreamDist
Downstream distance specified by the downstream distance filter.
Definition: Subscription.h:105
A point in 2D or 3D with translation and scaling methods.
Definition: Position.h:39
#define CMD_GET_POI_VARIABLE
int filterVClasses
vClasses specified by the vClasses filter,
Definition: Subscription.h:111
const MSEdge * getOppositeEdge() const
Returns the opposite direction edge if on exists else a nullptr.
Definition: MSEdge.cpp:1079
A list of positions.
const std::vector< MSLane * > & getBestLanesContinuation() const
Returns the best sequence of lanes to continue the route starting at myLane.
Definition: MSVehicle.cpp:4668
bool wrapStringList(const std::string &objID, const int variable, const std::vector< std::string > &value)
Definition: Helper.cpp:1096
unsigned char a
Definition: TraCIDefs.h:139
const double myRange
Definition: Helper.h:66
#define STEPS2TIME(x)
Definition: SUMOTime.h:58
#define CMD_GET_LANE_VARIABLE
void add(const MSLane *const l) const
Adds the given object to the container.
Definition: Helper.cpp:61
T MIN2(T a, T b)
Definition: StdDefs.h:70
double xmin() const
Returns minimum x-coordinate.
Definition: Boundary.cpp:119
#define POSITION_EPS
Definition: config.h:172
const std::string & getID() const
returns the id of the transportable
#define CMD_GET_SIM_VARIABLE
#define CMD_GET_EDGE_VARIABLE
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:2143
SubscriptionResults myResults
Definition: Helper.h:195
Boundary & grow(double by)
extends the boundary by the given amount
Definition: Boundary.cpp:301
unsigned char r
Definition: TraCIDefs.h:139
#define CMD_SUBSCRIBE_EDGE_CONTEXT
#define CMD_GET_JUNCTION_VARIABLE
static const double INVALID_OFFSET
a value to signify offsets outside the range of [0, Line.length()]
Definition: GeomHelper.h:52
void setRemoteControlled(Position xyPos, MSLane *l, double pos, double posLat, double angle, int edgeOffset, const ConstMSEdgeVector &route, SUMOTime t)
Definition: MSVehicle.cpp:664
bool isInternal() const
return whether this edge is an internal edge
Definition: MSEdge.h:225
std::set< std::string > filterVTypes
vTypes specified by the vTypes filter
Definition: Subscription.h:109
std::vector< MSVehicle * > VehCont
Container for vehicles.
Definition: MSLane.h:90
double filterUpstreamDist
Upstream distance specified by the upstream distance filter.
Definition: Subscription.h:107
Definition: Edge.cpp:30
const MSEdge * getInternalFollowingEdge(const MSEdge *followerAfterInternal) const
Definition: MSEdge.cpp:701
VehicleState
Definition of a vehicle state.
Definition: MSNet.h:494
#define LAST_STEP_VEHICLE_NUMBER
const MSEdgeVector & getSuccessors(SUMOVehicleClass vClass=SVC_IGNORING) const
Returns the following edges, restricted by vClass.
Definition: MSEdge.cpp:981
Allows to store the object; used as context while traveling the rtree in TraCI.
Definition: Named.h:94
std::set< std::string > & myIDs
The container.
Definition: Helper.h:64
Influencer & getInfluencer()
Returns the velocity/lane influencer.
Definition: MSVehicle.cpp:5488
#define SUMOTime_MAX
Definition: SUMOTime.h:37
void vehicleStateChanged(const SUMOVehicle *const vehicle, MSNet::VehicleState to, const std::string &info="")
Called if a vehicle changes its state.
Definition: Helper.cpp:1119
const MSVehicleType & getVehicleType() const
Returns the vehicle&#39;s type definition.
const PositionVector & myShape
Definition: Helper.h:65
#define CMD_SUBSCRIBE_PERSON_CONTEXT
unsigned char green() const
Returns the green-amount of the color.
Definition: RGBColor.h:70
std::vector< int > variables
The subscribed variables.
Definition: Subscription.h:88
#define CMD_GET_MULTIENTRYEXIT_VARIABLE
bool wrapInt(const std::string &objID, const int variable, const int value)
Definition: Helper.cpp:1082
const std::string & getID() const
Returns the name of the vehicle type.
Definition: MSVehicleType.h:94
const std::string getParameter(const std::string &key, const std::string &defaultValue="") const
Returns the value for a given key.
const std::string SUMO_PARAM_ORIGID
unsigned char red() const
Returns the red-amount of the color.
Definition: RGBColor.h:63
MSEdgeControl & getEdgeControl()
Returns the edge control.
Definition: MSNet.h:359
static MSVehicle * getVehicle(const std::string &id)
Definition: Vehicle.cpp:60
Boundary getBoxBoundary() const
Returns a boundary enclosing this list of lines.
double ymax() const
Returns maximum y-coordinate.
Definition: Boundary.cpp:137
A 3D-position.
Definition: TraCIDefs.h:107
virtual void releaseVehicles() const
Allows to use the container for microsimulation again.
Definition: MSLane.h:436
double nearest_offset_to_point2D(const Position &p, bool perpendicular=true) const
return the nearest offest to point 2D
const std::string & getID() const
Returns the name of the vehicle.
#define CMD_SUBSCRIBE_POI_CONTEXT
Representation of a lane in the micro simulation.
Definition: MSLane.h:78
std::vector< const MSLink * > getUpcomingLinks(double pos, double range, const std::vector< MSLane *> &contLanes) const
Returns all upcoming junctions within given range along the given (non-internal) continuation lanes m...
Definition: MSLane.cpp:3311
A list of positions.
virtual const std::string & getID() const =0
Get the vehicle&#39;s ID.
SUMOVehicleClass getVehicleClass() const
Get this vehicle type&#39;s vehicle class.
static const Position INVALID
used to indicate that a position is valid
Definition: Position.h:285
MSLane * getParallelLane(int offset) const
Returns the lane with the given offset parallel to this one or 0 if it does not exist.
Definition: MSLane.cpp:2063
std::vector< int > filterLanes
lanes specified by the lanes filter
Definition: Subscription.h:103
void setContext(const std::string &refID)
Definition: Helper.cpp:1069