Eclipse SUMO - Simulation of Urban MObility
libsumo/TrafficLight.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-2020 German Aerospace Center (DLR) and others.
4 // This program and the accompanying materials are made available under the
5 // terms of the Eclipse Public License 2.0 which is available at
6 // https://www.eclipse.org/legal/epl-2.0/
7 // This Source Code may also be made available under the following Secondary
8 // Licenses when the conditions for such availability set forth in the Eclipse
9 // Public License 2.0 are satisfied: GNU General Public License, version 2
10 // or later which is available at
11 // https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
12 // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
13 /****************************************************************************/
21 // C++ TraCI client API implementation
22 /****************************************************************************/
23 #include <config.h>
24 
25 #include <microsim/MSLane.h>
26 #include <microsim/MSEdge.h>
27 #include <microsim/MSNet.h>
35 #include <libsumo/TraCIConstants.h>
36 #include "TrafficLight.h"
37 
38 
39 namespace libsumo {
40 // ===========================================================================
41 // static member initializations
42 // ===========================================================================
43 SubscriptionResults TrafficLight::mySubscriptionResults;
44 ContextSubscriptionResults TrafficLight::myContextSubscriptionResults;
45 
46 
47 // ===========================================================================
48 // static member definitions
49 // ===========================================================================
50 std::vector<std::string>
51 TrafficLight::getIDList() {
53 }
54 
55 
56 int
57 TrafficLight::getIDCount() {
58  return (int)getIDList().size();
59 }
60 
61 
62 std::string
63 TrafficLight::getRedYellowGreenState(const std::string& tlsID) {
64  return getTLS(tlsID).getActive()->getCurrentPhaseDef().getState();
65 }
66 
67 
68 std::vector<TraCILogic>
69 TrafficLight::getAllProgramLogics(const std::string& tlsID) {
70  std::vector<TraCILogic> result;
71  const std::vector<MSTrafficLightLogic*> logics = getTLS(tlsID).getAllLogics();
72  for (MSTrafficLightLogic* logic : logics) {
73  TraCILogic l(logic->getProgramID(), (int)logic->getLogicType(), logic->getCurrentPhaseIndex());
74  l.subParameter = logic->getParametersMap();
75  for (const MSPhaseDefinition* const phase : logic->getPhases()) {
76  l.phases.emplace_back(new TraCIPhase(STEPS2TIME(phase->duration), phase->getState(),
77  STEPS2TIME(phase->minDuration), STEPS2TIME(phase->maxDuration),
78  phase->getNextPhases(), phase->getName()));
79  }
80  result.emplace_back(l);
81  }
82  return result;
83 }
84 
85 
86 std::vector<std::string>
87 TrafficLight::getControlledJunctions(const std::string& tlsID) {
88  std::set<std::string> junctionIDs;
89  const MSTrafficLightLogic::LinkVectorVector& links = getTLS(tlsID).getActive()->getLinks();
90  for (const MSTrafficLightLogic::LinkVector& llinks : links) {
91  for (const MSLink* l : llinks) {
92  junctionIDs.insert(l->getJunction()->getID());
93  }
94  }
95  return std::vector<std::string>(junctionIDs.begin(), junctionIDs.end());
96 }
97 
98 
99 std::vector<std::string>
100 TrafficLight::getControlledLanes(const std::string& tlsID) {
101  std::vector<std::string> laneIDs;
102  const MSTrafficLightLogic::LaneVectorVector& lanes = getTLS(tlsID).getActive()->getLaneVectors();
103  for (const MSTrafficLightLogic::LaneVector& llanes : lanes) {
104  for (const MSLane* l : llanes) {
105  laneIDs.push_back(l->getID());
106  }
107  }
108  return laneIDs;
109 }
110 
111 
112 std::vector<std::vector<TraCILink> >
113 TrafficLight::getControlledLinks(const std::string& tlsID) {
114  std::vector<std::vector<TraCILink> > result;
115  const MSTrafficLightLogic::LaneVectorVector& lanes = getTLS(tlsID).getActive()->getLaneVectors();
116  const MSTrafficLightLogic::LinkVectorVector& links = getTLS(tlsID).getActive()->getLinks();
117  for (int i = 0; i < (int)lanes.size(); ++i) {
118  std::vector<TraCILink> subList;
119  const MSTrafficLightLogic::LaneVector& llanes = lanes[i];
120  const MSTrafficLightLogic::LinkVector& llinks = links[i];
121  // number of links controlled by this signal (signal i)
122  for (int j = 0; j < (int)llanes.size(); ++j) {
123  MSLink* link = llinks[j];
124  // approached non-internal lane (if any)
125  const std::string to = link->getLane() != nullptr ? link->getLane()->getID() : "";
126  // approached "via", internal lane (if any)
127  const std::string via = link->getViaLane() != nullptr ? link->getViaLane()->getID() : "";
128  subList.emplace_back(TraCILink(llanes[j]->getID(), via, to));
129  }
130  result.emplace_back(subList);
131  }
132  return result;
133 }
134 
135 
136 std::string
137 TrafficLight::getProgram(const std::string& tlsID) {
138  return getTLS(tlsID).getActive()->getProgramID();
139 }
140 
141 
142 int
143 TrafficLight::getPhase(const std::string& tlsID) {
144  return getTLS(tlsID).getActive()->getCurrentPhaseIndex();
145 }
146 
147 
148 std::string
149 TrafficLight::getPhaseName(const std::string& tlsID) {
150  return getTLS(tlsID).getActive()->getCurrentPhaseDef().getName();
151 }
152 
153 
154 double
155 TrafficLight::getPhaseDuration(const std::string& tlsID) {
156  return STEPS2TIME(getTLS(tlsID).getActive()->getCurrentPhaseDef().duration);
157 }
158 
159 
160 double
161 TrafficLight::getNextSwitch(const std::string& tlsID) {
162  return STEPS2TIME(getTLS(tlsID).getActive()->getNextSwitchTime());
163 }
164 
165 int
166 TrafficLight::getServedPersonCount(const std::string& tlsID, int index) {
167  MSTrafficLightLogic* const active = getTLS(tlsID).getActive();
168  if (index < 0 || active->getPhaseNumber() <= index) {
169  throw TraCIException("The phase index " + toString(index) + " is not in the allowed range [0,"
170  + toString(active->getPhaseNumber() - 1) + "].");
171  }
172  // find all crossings which have a green light in that phas
173  int result = 0;
174 
175  const std::string& state = active->getPhases()[index]->getState();
176  for (int i = 0; i < (int)state.size(); i++) {
177  for (MSLink* link : active->getLinksAt(i)) {
178  if (link->getLane()->getEdge().isCrossing()) {
179  // walking forwards across
180  for (MSTransportable* person : link->getLaneBefore()->getEdge().getPersons()) {
181  if (static_cast<MSPerson*>(person)->getNextEdge() == link->getLane()->getEdge().getID()) {
182  result += 1;
183  }
184  }
185  // walking backwards across
186  MSLane* walkingAreaAcross = link->getLane()->getLinkCont().front()->getLane();
187  for (MSTransportable* person : walkingAreaAcross->getEdge().getPersons()) {
188  if (static_cast<MSPerson*>(person)->getNextEdge() == link->getLane()->getEdge().getID()) {
189  result += 1;
190  }
191  }
192  } else if (link->getLaneBefore()->getEdge().isCrossing()) {
193  // walking backwards across (in case both sides are separately controlled)
194  for (MSTransportable* person : link->getLane()->getEdge().getPersons()) {
195  if (static_cast<MSPerson*>(person)->getNextEdge() == link->getLaneBefore()->getEdge().getID()) {
196  result += 1;
197  }
198  }
199  }
200  }
201  }
202  return result;
203 }
204 
205 std::vector<std::string>
206 TrafficLight::getBlockingVehicles(const std::string& tlsID, int linkIndex) {
207  std::vector<std::string> result;
208  // for railsignals we cannot use the "online" program
209  MSTrafficLightLogic* const active = getTLS(tlsID).getDefault();
210  if (linkIndex < 0 || linkIndex >= active->getNumLinks()) {
211  throw TraCIException("The link index " + toString(linkIndex) + " is not in the allowed range [0,"
212  + toString(active->getNumLinks() - 1) + "].");
213  }
214  for (const SUMOVehicle* veh : active->getBlockingVehicles(linkIndex)) {
215  result.push_back(veh->getID());
216  }
217  return result;
218 }
219 
220 std::vector<std::string>
221 TrafficLight::getRivalVehicles(const std::string& tlsID, int linkIndex) {
222  std::vector<std::string> result;
223  MSTrafficLightLogic* const active = getTLS(tlsID).getDefault();
224  if (linkIndex < 0 || linkIndex >= active->getNumLinks()) {
225  throw TraCIException("The link index " + toString(linkIndex) + " is not in the allowed range [0,"
226  + toString(active->getNumLinks() - 1) + "].");
227  }
228  for (const SUMOVehicle* veh : active->getRivalVehicles(linkIndex)) {
229  result.push_back(veh->getID());
230  }
231  return result;
232 }
233 
234 std::vector<std::string>
235 TrafficLight::getPriorityVehicles(const std::string& tlsID, int linkIndex) {
236  std::vector<std::string> result;
237  MSTrafficLightLogic* const active = getTLS(tlsID).getDefault();
238  if (linkIndex < 0 || linkIndex >= active->getNumLinks()) {
239  throw TraCIException("The link index " + toString(linkIndex) + " is not in the allowed range [0,"
240  + toString(active->getNumLinks() - 1) + "].");
241  }
242  for (const SUMOVehicle* veh : active->getPriorityVehicles(linkIndex)) {
243  result.push_back(veh->getID());
244  }
245  return result;
246 }
247 
248 std::string
249 TrafficLight::getParameter(const std::string& tlsID, const std::string& paramName) {
250  return getTLS(tlsID).getActive()->getParameter(paramName, "");
251 }
252 
253 
255 
256 
257 void
258 TrafficLight::setRedYellowGreenState(const std::string& tlsID, const std::string& state) {
259  getTLS(tlsID).setStateInstantiatingOnline(MSNet::getInstance()->getTLSControl(), state);
260 }
261 
262 
263 void
264 TrafficLight::setPhase(const std::string& tlsID, const int index) {
265  MSTrafficLightLogic* const active = getTLS(tlsID).getActive();
266  if (index < 0 || active->getPhaseNumber() <= index) {
267  throw TraCIException("The phase index " + toString(index) + " is not in the allowed range [0,"
268  + toString(active->getPhaseNumber() - 1) + "].");
269  }
271  const SUMOTime duration = active->getPhase(index).duration;
272  active->changeStepAndDuration(MSNet::getInstance()->getTLSControl(), cTime, index, duration);
273 }
274 
275 void
276 TrafficLight::setPhaseName(const std::string& tlsID, const std::string& name) {
277  MSTrafficLightLogic* const active = getTLS(tlsID).getActive();
278  const_cast<MSPhaseDefinition&>(active->getCurrentPhaseDef()).setName(name);
279 }
280 
281 
282 void
283 TrafficLight::setProgram(const std::string& tlsID, const std::string& programID) {
284  try {
285  getTLS(tlsID).switchTo(MSNet::getInstance()->getTLSControl(), programID);
286  } catch (ProcessError& e) {
287  throw TraCIException(e.what());
288  }
289 }
290 
291 
292 void
293 TrafficLight::setPhaseDuration(const std::string& tlsID, const double phaseDuration) {
294  MSTrafficLightLogic* const active = getTLS(tlsID).getActive();
296  const int index = active->getCurrentPhaseIndex();
297  active->changeStepAndDuration(MSNet::getInstance()->getTLSControl(), cTime, index, TIME2STEPS(phaseDuration));
298 }
299 
300 
301 void
302 TrafficLight::setProgramLogic(const std::string& tlsID, const TraCILogic& logic) {
303  MSTLLogicControl::TLSLogicVariants& vars = getTLS(tlsID);
304  // make sure index and phaseNo are consistent
305  if (logic.currentPhaseIndex >= (int)logic.phases.size()) {
306  throw TraCIException("set program: parameter index must be less than parameter phase number.");
307  }
308  std::vector<MSPhaseDefinition*> phases;
309  for (TraCIPhase* phase : logic.phases) {
310  phases.push_back(new MSPhaseDefinition(TIME2STEPS(phase->duration), phase->state, TIME2STEPS(phase->minDur), TIME2STEPS(phase->maxDur), phase->next, phase->name));
311  }
312  if (vars.getLogic(logic.programID) == nullptr) {
314  int step = logic.currentPhaseIndex;
315  const std::string basePath = "";
316  MSTrafficLightLogic* tlLogic = nullptr;
317  SUMOTime nextSwitch = 0; //MSNet::getInstance()->getCurrentTimeStep();
318  switch ((TrafficLightType)logic.type) {
320  tlLogic = new MSActuatedTrafficLightLogic(tlc,
321  tlsID, logic.programID,
322  phases, step, nextSwitch,
323  logic.subParameter, basePath);
324  break;
326  tlLogic = new MSDelayBasedTrafficLightLogic(tlc,
327  tlsID, logic.programID,
328  phases, step, nextSwitch,
329  logic.subParameter, basePath);
330  break;
332  tlLogic = new MSSimpleTrafficLightLogic(tlc,
333  tlsID, logic.programID, TrafficLightType::STATIC,
334  phases, step, nextSwitch,
335  logic.subParameter);
336  break;
337  default:
338  throw TraCIException("Unsupported traffic light type '" + toString(logic.type) + "'");
339  }
340  vars.addLogic(logic.programID, tlLogic, true, true);
341  // XXX pass GUIDetectorBuilder when running with gui
343  tlLogic->init(db);
344  } else {
345  static_cast<MSSimpleTrafficLightLogic*>(vars.getLogic(logic.programID))->setPhases(phases, logic.currentPhaseIndex);
346  }
347 }
348 
349 
350 void
351 TrafficLight::setParameter(const std::string& tlsID, const std::string& paramName, const std::string& value) {
352  return getTLS(tlsID).getActive()->setParameter(paramName, value);
353 }
354 
355 
357 
358 
360 TrafficLight::getTLS(const std::string& id) {
361  if (!MSNet::getInstance()->getTLSControl().knows(id)) {
362  throw TraCIException("Traffic light '" + id + "' is not known");
363  }
364  return MSNet::getInstance()->getTLSControl().get(id);
365 }
366 
367 
368 std::shared_ptr<VariableWrapper>
369 TrafficLight::makeWrapper() {
370  return std::make_shared<Helper::SubscriptionWrapper>(handleVariable, mySubscriptionResults, myContextSubscriptionResults);
371 }
372 
373 
374 bool
375 TrafficLight::handleVariable(const std::string& objID, const int variable, VariableWrapper* wrapper) {
376  switch (variable) {
377  case TRACI_ID_LIST:
378  return wrapper->wrapStringList(objID, variable, getIDList());
379  case ID_COUNT:
380  return wrapper->wrapInt(objID, variable, getIDCount());
382  return wrapper->wrapString(objID, variable, getRedYellowGreenState(objID));
383  case TL_CONTROLLED_LANES:
384  return wrapper->wrapStringList(objID, variable, getControlledLanes(objID));
385  case TL_CURRENT_PHASE:
386  return wrapper->wrapInt(objID, variable, getPhase(objID));
387  case VAR_NAME:
388  return wrapper->wrapString(objID, variable, getPhaseName(objID));
389  case TL_CURRENT_PROGRAM:
390  return wrapper->wrapString(objID, variable, getProgram(objID));
391  case TL_PHASE_DURATION:
392  return wrapper->wrapDouble(objID, variable, getPhaseDuration(objID));
393  case TL_NEXT_SWITCH:
394  return wrapper->wrapDouble(objID, variable, getNextSwitch(objID));
396  return wrapper->wrapStringList(objID, variable, getControlledJunctions(objID));
397  default:
398  return false;
399  }
400 }
401 }
402 
403 
404 /****************************************************************************/
#define STEPS2TIME(x)
Definition: SUMOTime.h:53
#define TIME2STEPS(x)
Definition: SUMOTime.h:55
long long int SUMOTime
Definition: SUMOTime.h:31
TrafficLightType
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition: ToString.h:44
#define LIBSUMO_SUBSCRIPTION_IMPLEMENTATION(CLASS, DOMAIN)
Definition: TraCIDefs.h:57
#define LIBSUMO_GET_PARAMETER_WITH_KEY_IMPLEMENTATION(CLASS)
Definition: TraCIDefs.h:104
An actuated (adaptive) traffic light logic.
An actuated traffic light logic based on time delay of approaching vehicles.
const std::set< MSTransportable * > & getPersons() const
Returns this edge's persons set.
Definition: MSEdge.h:192
Representation of a lane in the micro simulation.
Definition: MSLane.h:82
const std::vector< MSLink * > & getLinkCont() const
returns the container with all links !!!
Definition: MSLane.h:640
MSEdge & getEdge() const
Returns the lane's edge.
Definition: MSLane.h:673
static MSNet * getInstance()
Returns the pointer to the unique instance of MSNet (singleton).
Definition: MSNet.cpp:171
MSTLLogicControl & getTLSControl()
Returns the tls logics control.
Definition: MSNet.h:444
SUMOTime getCurrentTimeStep() const
Returns the current simulation step.
Definition: MSNet.h:313
const std::string & getNextEdge() const
return the list of internal edges if this person is walking and the pedestrian model allows it
Definition: MSPerson.cpp:449
The definition of a single phase of a tls logic.
SUMOTime duration
The duration of the phase.
A fixed traffic light logic.
Storage for all programs of a single tls.
MSTrafficLightLogic * getLogic(const std::string &programID) const
bool addLogic(const std::string &programID, MSTrafficLightLogic *logic, bool netWasLoaded, bool isNewDefault=true)
Adds a logic (program)
A class that stores and controls tls and switching of their programs.
std::vector< std::string > getAllTLIds() const
TLSLogicVariants & get(const std::string &id) const
Returns the variants of a named tls.
The parent class for traffic light logics.
int getNumLinks()
return the number of controlled link indices
const LinkVector & getLinksAt(int i) const
Returns the list of links that are controlled by the signals at the given position.
virtual const MSPhaseDefinition & getCurrentPhaseDef() const =0
Returns the definition of the current phase.
std::vector< LaneVector > LaneVectorVector
Definition of a list that holds lists of lanes that do have the same attribute.
virtual int getPhaseNumber() const =0
Returns the number of phases.
virtual int getCurrentPhaseIndex() const =0
Returns the current index within the program.
std::vector< MSLane * > LaneVector
Definition of the list of arrival lanes subjected to this tls.
virtual const MSPhaseDefinition & getPhase(int givenstep) const =0
Returns the definition of the phase from the given position within the plan.
virtual VehicleVector getPriorityVehicles(int linkIndex)
return vehicles that approach the intersection/rail signal and have priority over vehicles that wish ...
virtual void changeStepAndDuration(MSTLLogicControl &tlcontrol, SUMOTime simStep, int step, SUMOTime stepDuration)=0
Changes the current phase and her duration.
virtual VehicleVector getBlockingVehicles(int linkIndex)
return vehicles that block the intersection/rail signal for vehicles that wish to pass the given link...
virtual VehicleVector getRivalVehicles(int linkIndex)
return vehicles that approach the intersection/rail signal and are in conflict with vehicles that wis...
std::vector< LinkVector > LinkVectorVector
Definition of a list that holds lists of links that do have the same attribute.
std::vector< MSLink * > LinkVector
Definition of the list of links that are subjected to this tls.
virtual const Phases & getPhases() const =0
Returns the phases of this tls program.
virtual void init(NLDetectorBuilder &nb)
Initialises the tls with information about incoming lanes.
const MSEdge * getEdge() const
Returns the current edge.
const MSLane * getLane() const
Returns the current lane (may be nullptr)
Builds detectors for microsim.
const std::string & getID() const
Returns the id.
Definition: Named.h:73
virtual void setParameter(const std::string &key, const std::string &value)
Sets a parameter.
Representation of a vehicle.
Definition: SUMOVehicle.h:58
C++ TraCI client API implementation.
TRACI_CONST int VAR_NAME
TRACI_CONST int TRACI_ID_LIST
TRACI_CONST int TL_CONTROLLED_LANES
TRACI_CONST int TL_CONTROLLED_JUNCTIONS
std::map< std::string, TraCIResults > SubscriptionResults
{object->{variable->value}}
Definition: TraCIDefs.h:250
TRACI_CONST int ID_COUNT
TRACI_CONST int TL_NEXT_SWITCH
TRACI_CONST int TL_PHASE_DURATION
TRACI_CONST int TL_CURRENT_PHASE
TRACI_CONST int TL_RED_YELLOW_GREEN_STATE
std::map< std::string, SubscriptionResults > ContextSubscriptionResults
Definition: TraCIDefs.h:251
TRACI_CONST int TL_CURRENT_PROGRAM