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-2023 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
26#include <microsim/MSLane.h>
27#include <microsim/MSEdge.h>
28#include <microsim/MSNet.h>
30#include <microsim/MSStop.h>
43#include "Helper.h"
44#include "TrafficLight.h"
45
46//#define DEBUG_CONSTRAINT_DEADLOCK
47
48namespace libsumo {
49// ===========================================================================
50// static member initializations
51// ===========================================================================
52SubscriptionResults TrafficLight::mySubscriptionResults;
53ContextSubscriptionResults TrafficLight::myContextSubscriptionResults;
54
55// ===========================================================================
56// static member definitions
57// ===========================================================================
58std::vector<std::string>
59TrafficLight::getIDList() {
61}
62
63
64int
65TrafficLight::getIDCount() {
66 return (int)getIDList().size();
67}
68
69
70std::string
71TrafficLight::getRedYellowGreenState(const std::string& tlsID) {
73}
74
75
76std::vector<TraCILogic>
77TrafficLight::getAllProgramLogics(const std::string& tlsID) {
78 std::vector<TraCILogic> result;
79 const std::vector<MSTrafficLightLogic*> logics = Helper::getTLS(tlsID).getAllLogics();
80 for (MSTrafficLightLogic* logic : logics) {
81 TraCILogic l(logic->getProgramID(), (int)logic->getLogicType(), logic->getCurrentPhaseIndex());
82 l.subParameter = logic->getParametersMap();
83 for (const MSPhaseDefinition* const phase : logic->getPhases()) {
84 l.phases.emplace_back(new TraCIPhase(STEPS2TIME(phase->duration), phase->getState(),
85 STEPS2TIME(phase->minDuration), STEPS2TIME(phase->maxDuration),
86 phase->getNextPhases(), phase->getName()));
87 }
88 result.emplace_back(l);
89 }
90 return result;
91}
92
93
94std::vector<std::string>
95TrafficLight::getControlledJunctions(const std::string& tlsID) {
96 std::set<std::string> junctionIDs;
98 for (const MSTrafficLightLogic::LinkVector& llinks : links) {
99 for (const MSLink* l : llinks) {
100 junctionIDs.insert(l->getJunction()->getID());
101 }
102 }
103 return std::vector<std::string>(junctionIDs.begin(), junctionIDs.end());
104}
105
106
107std::vector<std::string>
108TrafficLight::getControlledLanes(const std::string& tlsID) {
109 std::vector<std::string> laneIDs;
111 for (const MSTrafficLightLogic::LaneVector& llanes : lanes) {
112 for (const MSLane* l : llanes) {
113 laneIDs.push_back(l->getID());
114 }
115 }
116 return laneIDs;
117}
118
119
120std::vector<std::vector<TraCILink> >
121TrafficLight::getControlledLinks(const std::string& tlsID) {
122 std::vector<std::vector<TraCILink> > result;
125 for (int i = 0; i < (int)lanes.size(); ++i) {
126 std::vector<TraCILink> subList;
127 const MSTrafficLightLogic::LaneVector& llanes = lanes[i];
128 const MSTrafficLightLogic::LinkVector& llinks = links[i];
129 // number of links controlled by this signal (signal i)
130 for (int j = 0; j < (int)llanes.size(); ++j) {
131 MSLink* link = llinks[j];
132 // approached non-internal lane (if any)
133 const std::string to = link->getLane() != nullptr ? link->getLane()->getID() : "";
134 // approached "via", internal lane (if any)
135 const std::string via = link->getViaLane() != nullptr ? link->getViaLane()->getID() : "";
136 subList.emplace_back(TraCILink(llanes[j]->getID(), via, to));
137 }
138 result.emplace_back(subList);
139 }
140 return result;
141}
142
143
144std::string
145TrafficLight::getProgram(const std::string& tlsID) {
146 return Helper::getTLS(tlsID).getActive()->getProgramID();
147}
148
149
150int
151TrafficLight::getPhase(const std::string& tlsID) {
153}
154
155
156std::string
157TrafficLight::getPhaseName(const std::string& tlsID) {
159}
160
161
162double
163TrafficLight::getPhaseDuration(const std::string& tlsID) {
164 return STEPS2TIME(Helper::getTLS(tlsID).getActive()->getCurrentPhaseDef().duration);
165}
166
167
168double
169TrafficLight::getNextSwitch(const std::string& tlsID) {
170 return STEPS2TIME(Helper::getTLS(tlsID).getActive()->getNextSwitchTime());
171}
172
173int
174TrafficLight::getServedPersonCount(const std::string& tlsID, int index) {
175 MSTrafficLightLogic* const active = Helper::getTLS(tlsID).getActive();
176 if (index < 0 || active->getPhaseNumber() <= index) {
177 throw TraCIException("The phase index " + toString(index) + " is not in the allowed range [0,"
178 + toString(active->getPhaseNumber() - 1) + "].");
179 }
180 // find all crossings which have a green light in that phas
181 int result = 0;
182
183 const std::string& state = active->getPhases()[index]->getState();
184 for (int i = 0; i < (int)state.size(); i++) {
185 for (MSLink* link : active->getLinksAt(i)) {
186 if (link->getLane()->getEdge().isCrossing()) {
187 // walking forwards across
188 for (MSTransportable* person : link->getLaneBefore()->getEdge().getPersons()) {
189 if (static_cast<MSPerson*>(person)->getNextEdge() == link->getLane()->getEdge().getID()) {
190 result += 1;
191 }
192 }
193 // walking backwards across
194 MSLane* walkingAreaAcross = link->getLane()->getLinkCont().front()->getLane();
195 for (MSTransportable* person : walkingAreaAcross->getEdge().getPersons()) {
196 if (static_cast<MSPerson*>(person)->getNextEdge() == link->getLane()->getEdge().getID()) {
197 result += 1;
198 }
199 }
200 } else if (link->getLaneBefore()->getEdge().isCrossing()) {
201 // walking backwards across (in case both sides are separately controlled)
202 for (MSTransportable* person : link->getLane()->getEdge().getPersons()) {
203 if (static_cast<MSPerson*>(person)->getNextEdge() == link->getLaneBefore()->getEdge().getID()) {
204 result += 1;
205 }
206 }
207 }
208 }
209 }
210 return result;
211}
212
213std::vector<std::string>
214TrafficLight::getBlockingVehicles(const std::string& tlsID, int linkIndex) {
215 std::vector<std::string> result;
216 // for railsignals we cannot use the "online" program
217 MSTrafficLightLogic* const active = Helper::getTLS(tlsID).getDefault();
218 if (linkIndex < 0 || linkIndex >= active->getNumLinks()) {
219 throw TraCIException("The link index " + toString(linkIndex) + " is not in the allowed range [0,"
220 + toString(active->getNumLinks() - 1) + "].");
221 }
222 for (const SUMOVehicle* veh : active->getBlockingVehicles(linkIndex)) {
223 result.push_back(veh->getID());
224 }
225 return result;
226}
227
228std::vector<std::string>
229TrafficLight::getRivalVehicles(const std::string& tlsID, int linkIndex) {
230 std::vector<std::string> result;
231 MSTrafficLightLogic* const active = Helper::getTLS(tlsID).getDefault();
232 if (linkIndex < 0 || linkIndex >= active->getNumLinks()) {
233 throw TraCIException("The link index " + toString(linkIndex) + " is not in the allowed range [0,"
234 + toString(active->getNumLinks() - 1) + "].");
235 }
236 for (const SUMOVehicle* veh : active->getRivalVehicles(linkIndex)) {
237 result.push_back(veh->getID());
238 }
239 return result;
240}
241
242std::vector<std::string>
243TrafficLight::getPriorityVehicles(const std::string& tlsID, int linkIndex) {
244 std::vector<std::string> result;
245 MSTrafficLightLogic* const active = Helper::getTLS(tlsID).getDefault();
246 if (linkIndex < 0 || linkIndex >= active->getNumLinks()) {
247 throw TraCIException("The link index " + toString(linkIndex) + " is not in the allowed range [0,"
248 + toString(active->getNumLinks() - 1) + "].");
249 }
250 for (const SUMOVehicle* veh : active->getPriorityVehicles(linkIndex)) {
251 result.push_back(veh->getID());
252 }
253 return result;
254}
255
256std::vector<TraCISignalConstraint>
257TrafficLight::getConstraints(const std::string& tlsID, const std::string& tripId) {
258 std::vector<TraCISignalConstraint> result;
259 MSTrafficLightLogic* const active = Helper::getTLS(tlsID).getDefault();
260 MSRailSignal* s = dynamic_cast<MSRailSignal*>(active);
261 if (s == nullptr) {
262 throw TraCIException("'" + tlsID + "' is not a rail signal");
263 }
264 for (auto item : s->getConstraints()) {
265 if (tripId != "" && tripId != item.first) {
266 continue;
267 }
268 for (MSRailSignalConstraint* c : item.second) {
269 result.push_back(buildConstraint(tlsID, item.first, c));
270 }
271 }
272 return result;
273}
274
275std::vector<TraCISignalConstraint>
276TrafficLight::getConstraintsByFoe(const std::string& foeSignal, const std::string& foeId) {
277 // retrieve all constraints that have the given foeSignal (optionally filtered by foeId)
278 // @note could improve efficiency by storing a map of rail signals in MSRailSignalControl
279 std::vector<TraCISignalConstraint> result;
280 for (const std::string& tlsID : getIDList()) {
281 MSTrafficLightLogic* const active = Helper::getTLS(tlsID).getDefault();
282 MSRailSignal* s = dynamic_cast<MSRailSignal*>(active);
283 if (s != nullptr) {
284 for (auto item : s->getConstraints()) {
285 for (MSRailSignalConstraint* cand : item.second) {
287 if (pc != nullptr && pc->myFoeSignal->getID() == foeSignal
288 && (foeId == "" || pc->myTripId == foeId)) {
289 result.push_back(buildConstraint(s->getID(), item.first, pc));
290 }
291 }
292 }
293 }
294 }
295 return result;
296}
297
298std::vector<TraCISignalConstraint>
299TrafficLight::swapConstraints(const std::string& tlsID, const std::string& tripId, const std::string& foeSignal, const std::string& foeId) {
300#ifdef DEBUG_CONSTRAINT_DEADLOCK
301 std::cout << "swapConstraints tlsId=" << tlsID << " tripId=" << tripId << " foeSignal=" << foeSignal << " foeId=" << foeId << "\n";
302#endif
303 MSTrafficLightLogic* const active = Helper::getTLS(tlsID).getDefault();
304 MSTrafficLightLogic* const active2 = Helper::getTLS(foeSignal).getDefault();
305 MSRailSignal* s = dynamic_cast<MSRailSignal*>(active);
306 MSRailSignal* s2 = dynamic_cast<MSRailSignal*>(active2);
307 if (s == nullptr) {
308 throw TraCIException("'" + tlsID + "' is not a rail signal");
309 }
310 if (s2 == nullptr) {
311 throw TraCIException("'" + foeSignal + "' is not a rail signal");
312 }
314 for (auto item : s->getConstraints()) {
315 if (tripId == item.first) {
316 for (MSRailSignalConstraint* cand : item.second) {
318 if (pc != nullptr && pc->myFoeSignal->getID() == foeSignal && pc->myTripId == foeId) {
319 c = pc;
320 break;
321 }
322 }
323 break;
324 }
325 }
326 if (c != nullptr) {
327 const int limit = c->myLimit;
328 // the two constraints are complementary so we actually remove rather than deactivate to avoid redundant conflict information
330 MSRailSignalConstraint* swapped = new MSRailSignalConstraint_Predecessor(type, s, tripId, limit, true);
331 swapped->updateParameters(c->getParametersMap());
332 swapParameters(swapped);
333 s->removeConstraint(tripId, c);
334 s2->addConstraint(foeId, swapped);
335 return findConstraintsDeadLocks(foeId, tripId, foeSignal, tlsID);
336 } else {
337 throw TraCIException("Rail signal '" + tlsID + "' does not have a constraint for tripId '" + tripId + "' with foeSignal '" + foeSignal + "' and foeId '" + foeId + "'");
338 }
339}
340
341
342std::vector<std::pair<std::string, std::string> >
343TrafficLight::getSwapParams(int constraintType) {
344 std::vector<std::pair<std::string, std::string> > result({
345 {"vehID", "foeID"},
346 {"line", "foeLine"},
347 {"arrival", "foeArrival"}});
348
349 if (constraintType == MSRailSignalConstraint::ConstraintType::BIDI_PREDECESSOR) {
350 std::vector<std::pair<std::string, std::string> > special({
351 {"busStop", "busStop2"},
352 {"priorStop", "priorStop2"},
353 {"stopArrival", "foeStopArrival"}});
354 result.insert(result.end(), special.begin(), special.end());
355 }
356 return result;
357}
358
359
360void
361TrafficLight::swapParameters(MSRailSignalConstraint* c) {
362 // swap parameters that were assigned by generateRailSignalConstraints.py
363 for (auto keys : getSwapParams(c->getType())) {
364 swapParameters(c, keys.first, keys.second);
365 }
366}
367
368void
369TrafficLight::swapParameters(MSRailSignalConstraint* c, const std::string& key1, const std::string& key2) {
370 const std::string value1 = c->getParameter(key1);
371 const std::string value2 = c->getParameter(key2);
372 if (value1 != "") {
373 c->setParameter(key2, value1);
374 } else {
375 c->unsetParameter(key2);
376 }
377 if (value2 != "") {
378 c->setParameter(key1, value2);
379 } else {
380 c->unsetParameter(key1);
381 }
382}
383
384void
385TrafficLight::swapParameters(TraCISignalConstraint& c) {
386 // swap parameters that were assigned by generateRailSignalConstraints.py
387 for (auto keys : getSwapParams(c.type)) {
388 swapParameters(c, keys.first, keys.second);
389 }
390}
391
392void
393TrafficLight::swapParameters(TraCISignalConstraint& c, const std::string& key1, const std::string& key2) {
394 auto it1 = c.param.find(key1);
395 auto it2 = c.param.find(key2);
396 const std::string value1 = it1 != c.param.end() ? it1->second : "";
397 const std::string value2 = it2 != c.param.end() ? it2->second : "";
398 if (value1 != "") {
399 c.param[key2] = value1;
400 } else {
401 c.param.erase(key2);
402 }
403 if (value2 != "") {
404 c.param[key1] = value2;
405 } else {
406 c.param.erase(key1);
407 }
408}
409
410
411void
412TrafficLight::removeConstraints(const std::string& tlsID, const std::string& tripId, const std::string& foeSignal, const std::string& foeId) {
413 // remove all constraints that have the given foeId
414 // @note could improve efficiency by storing a map of rail signals in MSRailSignalControl
415 for (const std::string& tlsCand : getIDList()) {
416 if (tlsID == "" || tlsCand == tlsID) {
417 MSTrafficLightLogic* const active = Helper::getTLS(tlsCand).getDefault();
418 MSRailSignal* s = dynamic_cast<MSRailSignal*>(active);
419 if (s != nullptr) {
420 for (auto item : s->getConstraints()) {
421 if (tripId == "" || item.first == tripId) {
422 for (MSRailSignalConstraint* cand : item.second) {
424 if (pc != nullptr
425 && (foeId == "" || pc->myTripId == foeId)
426 && (foeSignal == "" || pc->myFoeSignal->getID() == foeSignal)) {
427 cand->setActive(false);
428 }
429 }
430 }
431 }
432 }
433 }
434 }
435}
436
437
438void
439TrafficLight::updateConstraints(const std::string& vehID, std::string tripId) {
440 // Removes all constraints that can no longer be met because the route of
441 // vehID does not pass the signal involved in the constraint with the given tripId.
442 // This includes constraints on tripId as well as constraints where tripId is the foeId.
443
444 MSBaseVehicle* veh = Helper::getVehicle(vehID);
445 std::string curTripId = veh->getParameter().getParameter("tripId", veh->getID());
446 tripId = tripId == "" ? curTripId : tripId;
447
448 // find signals and tripId along the route of veh
449 std::map<const MSRailSignal*, std::set<std::string> > onRoute;
450 const ConstMSEdgeVector& route = veh->getRoute().getEdges();
451 auto routeIt = veh->getCurrentRouteEdge();
452 for (const MSStop& stop : veh->getStops()) {
453 for (auto it = routeIt; it < stop.edge; it++) {
454 const MSEdge* edge = *it;
456 if (it + 1 != route.end()) {
457 const MSEdge* next = *(it + 1);
458 const MSLink* link = edge->getLanes()[0]->getLinkTo(next->getLanes()[0]);
459 if (link != nullptr && link->getTLLogic() != nullptr) {
460 const MSRailSignal* s = dynamic_cast<const MSRailSignal*>(link->getTLLogic());
461 onRoute[s].insert(curTripId);
462 }
463 }
464 }
465 }
466 if (stop.pars.tripId != "") {
467 curTripId = stop.pars.tripId;
468 }
469 routeIt = stop.edge;
470 }
471 for (auto it = routeIt; it < route.end(); it++) {
472 const MSEdge* edge = *it;
474 if (it + 1 != route.end()) {
475 const MSEdge* next = *(it + 1);
476 const MSLink* link = edge->getLanes()[0]->getLinkTo(next->getLanes()[0]);
477 if (link != nullptr && link->getTLLogic() != nullptr) {
478 const MSRailSignal* s = dynamic_cast<const MSRailSignal*>(link->getTLLogic());
479 onRoute[s].insert(curTripId);
480 }
481 }
482 }
483 }
484 //for (auto item : onRoute) {
485 // std::cout << " s=" << item.first->getID() << " @" << item.first << " ids=" << toString(item.second) << "\n";
486 //}
487
488 // check relevance for all active contraints
490
491 // record outdated constraints on and by the vehicle
492 std::vector<MSRailSignalConstraint*> onVeh;
493 std::vector<std::pair<std::string, MSRailSignalConstraint*> > byVeh;
494
495 for (auto item : s->getConstraints()) {
496 for (MSRailSignalConstraint* cand : item.second) {
498 if (pc != nullptr && !pc->cleared() && pc->isActive()) {
499 if (item.first == tripId) {
500 if (onRoute[s].count(tripId) == 0) {
501 // constraint on our veh no longer relevant
502 onVeh.push_back(cand);
503 }
504 } else if (pc->myTripId == tripId) {
505 if (onRoute[pc->myFoeSignal].count(tripId) == 0) {
506 // constraint by our veh no longer relevant
507 byVeh.push_back(std::make_pair(item.first, cand));
508 }
509 }
510 }
511 }
512 }
513 for (MSRailSignalConstraint* c : onVeh) {
514 s->removeConstraint(tripId, c);
515 }
516 for (auto item : byVeh) {
517 s->removeConstraint(item.first, item.second);
518 }
519 }
520}
521
522
523std::vector<TraCISignalConstraint>
524TrafficLight::findConstraintsDeadLocks(const std::string& foeId, const std::string& tripId, const std::string& foeSignal, const std::string& tlsID) {
525 std::vector<TraCISignalConstraint> result;
526 // find circular constraints (deadlock)
527 // foeId is now constrainted by tripId and assumed to follow tripId on the
528 // same track without possibility of overtaking
529 // we look for a third vehicle foeId2 where
530 // tripId waits for foeId2 and foeId2 waits on foeId
531 std::map<std::string, TraCISignalConstraint> constraintsOnTripId;
532 std::map<std::string, TraCISignalConstraint> constrainedByFoeId;
533 std::set<std::string> foeId2Cands1;
534 std::set<std::string> foeId2Cands2;
535 for (MSRailSignal* s : MSRailSignalControl::getInstance().getSignals()) {
536 for (auto item : s->getConstraints()) {
537 for (MSRailSignalConstraint* cand : item.second) {
539 if (pc != nullptr && !pc->cleared() && pc->isActive()) {
540 if (item.first == tripId) {
541 // tripId waits for foe2
542 // @could there by more than one constraint on tripId by this foe2?
543 libsumo::TraCISignalConstraint tsc = buildConstraint(s->getID(), item.first, pc);
544 constraintsOnTripId[pc->myTripId] = tsc;
545 foeId2Cands1.insert(pc->myTripId);
546 for (std::string& futureFoe2Id : getFutureTripIds(pc->myTripId)) {
547 foeId2Cands1.insert(futureFoe2Id);
548 //tsc.foeId = futureFoe2Id; // if we do this, the constraint to swap will not be found
549 constraintsOnTripId[futureFoe2Id] = tsc;
550 }
551 } else if (pc->myTripId == foeId) {
552 // foeId2 waits for foe
553 libsumo::TraCISignalConstraint tsc = buildConstraint(s->getID(), item.first, pc);
554 constrainedByFoeId[item.first] = tsc;
555 foeId2Cands2.insert(item.first);
556 for (std::string& futureTripId : getFutureTripIds(item.first)) {
557 foeId2Cands2.insert(futureTripId);
558 //tsc.tripId = futureTripId; // if we do this, the constraint to swap will not be found
559 constrainedByFoeId[futureTripId] = tsc;
560 }
561 }
562 }
563 }
564 }
565 }
566#ifdef DEBUG_CONSTRAINT_DEADLOCK
567 std::cout << "findConstraintsDeadLocks foeId=" << foeId << " tripId=" << tripId << " foeSignal=" << foeSignal << " tlsID=" << tlsID << "\n";
568 std::cout << " foeId2Cands1=" << toString(foeId2Cands1) << "\n";
569 std::cout << " foeId2Cands2=" << toString(foeId2Cands2) << "\n";
570#endif
571 if (foeId2Cands1.size() > 0) {
572 // foe2 might be constrained implicitly by foe due to following on the same track
573 // in this case foe must be on the route of foe2 between its current position and foeSignal
574
575 // we have to check this first because it also affects foeInsertion
576 // constraints if the foe is already inserted but hasn't yet passed the
577 // signal (cleared == false).
578 SUMOVehicle* foe = getVehicleByTripId(foeId);
579 if (foe != nullptr) {
580 const MSEdge* foeEdge = foe->getEdge();
581 const double foePos = foe->getPositionOnLane();
582 for (const std::string& foeId2 : foeId2Cands1) {
583 // tripId waits for foeId2
584 SUMOVehicle* foe2 = getVehicleByTripId(foeId2);
585 if (foe2 != nullptr) {
586 const ConstMSEdgeVector& foe2Route = foe2->getRoute().getEdges();
587 const TraCISignalConstraint& c = constraintsOnTripId[foeId2];
588 bool foeAhead = false;
589 for (int i = foe2->getRoutePosition(); i < (int)foe2Route.size(); i++) {
590 const MSEdge* e = foe2Route[i];
591 if (e == foeEdge &&
592 ((e != foe2->getEdge() || foe2->getPositionOnLane() < foePos)
593 || (foe->hasDeparted() && !foe2->hasDeparted())
594 || (!foe->hasDeparted() && !foe2->hasDeparted() &&
595 (foe->getParameter().depart < foe2->getParameter().depart
596 || (foe->getParameter().depart == foe2->getParameter().depart && foe->getNumericalID() < foe2->getNumericalID())))
597 )) {
598 foeAhead = true;
599#ifdef DEBUG_CONSTRAINT_DEADLOCK
600 std::cout << "findConstraintsDeadLocks foeId=" << foeId << " tripId=" << tripId << " foeSignal=" << foeSignal << "\n";
601 std::cout << " foeLeaderDeadlock foeEdge=" << foeEdge->getID() << " foe2=" << foe2->getParameter().getParameter("tripId", foe2->getID())
602 << " routePos=" << foe2->getRoutePosition() << " futureRPos=" << i << " e=" << e->getID()
603 //<< " foePos=" << foePos << " foe2Pos=" << foe2->getPositionOnLane()
604 << " " << constraintsOnTripId[foeId2].getString() << "\n";
605#endif
606 break;
607 }
608 if (e->getToJunction()->getID() == foeSignal
609 || e->getToJunction()->getID() == c.foeSignal) {
610 break;
611 }
612 }
613 if (foeAhead) {
614 // foe cannot wait for foe2 (since it's behind). Instead foe2 must wait for tripId
615 TraCISignalConstraint nc; // constraint after swap
616 nc.tripId = c.foeId;
617 nc.foeId = c.tripId;
618 nc.signalId = c.foeSignal;
619 nc.foeSignal = c.signalId;
620 nc.limit = c.limit;
621 nc.type = c.type;
622 nc.mustWait = true; // ???
623 nc.active = true;
624 nc.param = c.param;
625 swapParameters(nc);
626 result.push_back(nc);
627 // let foe wait for foe2
628 std::vector<TraCISignalConstraint> result2 = swapConstraints(c.signalId, c.tripId, c.foeSignal, c.foeId);
629 result.insert(result.end(), result2.begin(), result2.end());
630
631 // Other deadlocks might not be valid anymore so we need a fresh recheck for remaining implicit or explicit deadlocks
632 const std::vector<TraCISignalConstraint>& result4 = findConstraintsDeadLocks(foeId, tripId, foeSignal, tlsID);
633 result.insert(result.end(), result4.begin(), result4.end());
634 return result;
635 }
636 }
637 }
638 }
639 }
640
641 if (foeId2Cands2.size() > 0) {
642 // tripId might be constrained implicitly by foe2 due to following on the same track
643 // in this case foe2 must be on the route of tripId between its current position and tlsID
644 // if foe2 then waits for foe, deadlock occurs
645
646 SUMOVehicle* ego = getVehicleByTripId(tripId);
647 if (ego != nullptr && (ego->hasDeparted() || !ego->getParameter().wasSet(VEHPARS_FORCE_REROUTE))) {
648 std::set<const MSEdge*> egoToSignal;
649 const double egoPos = ego->getPositionOnLane();
650 const ConstMSEdgeVector& egoRoute = ego->getRoute().getEdges();
651 for (int i = ego->getRoutePosition(); i < (int)egoRoute.size(); i++) {
652 const MSEdge* e = egoRoute[i];
653 egoToSignal.insert(e);
654 if (e->getToJunction()->getID() == tlsID) {
655 break;
656 }
657 }
658
659 for (const std::string& foeId2 : foeId2Cands2) {
660 // foeId2 waits for foe
661 SUMOVehicle* foe2 = getVehicleByTripId(foeId2);
662 //std::cout << " foe2=" << foe2->getID() << " edge=" << foe2->getEdge()->getID() << " egoToSignal=" << toString(egoToSignal) << "\n";
663 if (foe2 != nullptr) {
664 if (egoToSignal.count(foe2->getEdge()) != 0
665 && (foe2->getEdge() != ego->getEdge() || foe2->getPositionOnLane() > egoPos)) {
666 const TraCISignalConstraint& c = constrainedByFoeId[foeId2];
667#ifdef DEBUG_CONSTRAINT_DEADLOCK
668 std::cout << "findConstraintsDeadLocks foeId=" << foeId << " tripId=" << tripId << " foeSignal=" << foeSignal << "\n";
669 std::cout << " egoLeaderDeadlock foe2Edge=" << foe2->getEdge()->getID() << " foe2=" << foe2->getParameter().getParameter("tripId", foe2->getID())
670 << " " << c.getString() << "\n";
671#endif
672 // foe is already waiting for tripId (ego) and should also wait for foeId2
673 TraCISignalConstraint nc; // constraint after swap
674 nc.tripId = c.foeId;
675 nc.foeId = c.tripId;
676 nc.signalId = c.foeSignal;
677 nc.foeSignal = c.signalId;
678 nc.limit = c.limit;
679 nc.type = c.type;
680 nc.mustWait = true; // ???
681 nc.active = true;
682 nc.param = c.param;
683 swapParameters(nc);
684 result.push_back(nc);
685 // let foe wait for foe2
686 std::vector<TraCISignalConstraint> result2 = swapConstraints(c.signalId, c.tripId, c.foeSignal, c.foeId);
687 result.insert(result.end(), result2.begin(), result2.end());
688
689 // Other deadlocks might not be valid anymore so we need a fresh recheck for remaining implicit or explicit deadlocks
690 const std::vector<TraCISignalConstraint>& result4 = findConstraintsDeadLocks(foeId, tripId, foeSignal, tlsID);
691 result.insert(result.end(), result4.begin(), result4.end());
692 return result;
693 }
694 }
695 }
696 } else if (ego != nullptr) {
697 WRITE_WARNINGF(TL("Cannot check for all deadlocks on swapConstraints because the route for vehicle '%' is not computed yet"), ego->getID());
698 }
699 }
700
701 // find deadlock in explicit constraints
702 std::vector<std::string> foeIds2;
703 std::set_intersection(
704 foeId2Cands1.begin(), foeId2Cands1.end(),
705 foeId2Cands2.begin(), foeId2Cands2.end(),
706 std::back_inserter(foeIds2));
707#ifdef DEBUG_CONSTRAINT_DEADLOCK
708 std::cout << "findConstraintsDeadLocks foeId=" << foeId << " tripId=" << tripId << " foeSignal=" << foeSignal << "\n";
709 for (const std::string& foeId2 : foeIds2) {
710 std::cout << " deadlockId=" << foeId2 << " " << constraintsOnTripId[foeId2].getString() << " " << constrainedByFoeId[foeId2].getString() << "\n";
711 }
712#endif
713 if (foeIds2.size() > 0) {
714 TraCISignalConstraint c = constrainedByFoeId[foeIds2.front()];
715 if (c.type == MSRailSignalConstraint::ConstraintType::INSERTION_PREDECESSOR) {
716 // avoid swapping insertion constraint
717 c = constraintsOnTripId[foeIds2.front()];
718 }
719 TraCISignalConstraint nc; // constraint after swap
720 nc.tripId = c.foeId;
721 nc.foeId = c.tripId;
722 nc.signalId = c.foeSignal;
723 nc.foeSignal = c.signalId;
724 nc.limit = c.limit;
725 nc.type = c.type;
726 nc.mustWait = true; // ???
727 nc.active = true;
728 nc.param = c.param;
729 swapParameters(nc);
730 result.push_back(nc);
731 // let foe wait for foe2
732 const std::vector<TraCISignalConstraint>& result2 = swapConstraints(c.signalId, c.tripId, c.foeSignal, c.foeId);
733 result.insert(result.end(), result2.begin(), result2.end());
734 if (foeIds2.size() > 1) {
735 // calling swapConstraints once may result in further swaps so we have to recheck for remaining deadlocks anew
736 const std::vector<TraCISignalConstraint>& result3 = findConstraintsDeadLocks(foeId, tripId, foeSignal, tlsID);
737 result.insert(result.end(), result3.begin(), result3.end());
738 }
739 }
740 return result;
741}
742
743
745TrafficLight::getVehicleByTripId(const std::string tripOrVehID) {
747 for (MSVehicleControl::constVehIt i = c.loadedVehBegin(); i != c.loadedVehEnd(); ++i) {
748 SUMOVehicle* veh = i->second;
749 if (veh->getParameter().getParameter("tripId", veh->getID()) == tripOrVehID) {
750 return veh;
751 }
752 }
753 return nullptr;
754}
755
756
757std::vector<std::string>
758TrafficLight::getFutureTripIds(const std::string vehID) {
759 std::vector<std::string> result;
761 if (veh) {
762 std::string tripId = veh->getParameter().getParameter("tripId");
763 if (tripId != "") {
764 result.push_back(tripId);
765 }
766 for (const MSStop& stop : veh->getStops()) {
767 if (stop.pars.tripId != "") {
768 result.push_back(stop.pars.tripId);
769 }
770 }
771 }
772 return result;
773}
774
775
776std::string
777TrafficLight::getParameter(const std::string& tlsID, const std::string& paramName) {
779 if (StringUtils::startsWith(paramName, "NEMA.") && tll->getLogicType() != TrafficLightType::NEMA) {
780 throw TraCIException("'" + tlsID + "' is not a NEMA controller");
781 }
782 return tll->getParameter(paramName, "");
783}
784
785
787
788
789void
790TrafficLight::setRedYellowGreenState(const std::string& tlsID, const std::string& state) {
791 Helper::getTLS(tlsID).setStateInstantiatingOnline(MSNet::getInstance()->getTLSControl(), state);
792}
793
794
795void
796TrafficLight::setPhase(const std::string& tlsID, const int index) {
797 MSTrafficLightLogic* const active = Helper::getTLS(tlsID).getActive();
798 if (index < 0 || active->getPhaseNumber() <= index) {
799 throw TraCIException("The phase index " + toString(index) + " is not in the allowed range [0,"
800 + toString(active->getPhaseNumber() - 1) + "].");
801 }
803 const SUMOTime duration = active->getPhase(index).duration;
804 active->changeStepAndDuration(MSNet::getInstance()->getTLSControl(), cTime, index, duration);
805}
806
807void
808TrafficLight::setPhaseName(const std::string& tlsID, const std::string& name) {
809 MSTrafficLightLogic* const active = Helper::getTLS(tlsID).getActive();
810 const_cast<MSPhaseDefinition&>(active->getCurrentPhaseDef()).setName(name);
811}
812
813
814void
815TrafficLight::setProgram(const std::string& tlsID, const std::string& programID) {
816 try {
817 Helper::getTLS(tlsID).switchTo(MSNet::getInstance()->getTLSControl(), programID);
818 } catch (ProcessError& e) {
819 throw TraCIException(e.what());
820 }
821}
822
823
824void
825TrafficLight::setPhaseDuration(const std::string& tlsID, const double phaseDuration) {
826 MSTrafficLightLogic* const active = Helper::getTLS(tlsID).getActive();
828 active->changeStepAndDuration(MSNet::getInstance()->getTLSControl(), cTime, -1, TIME2STEPS(phaseDuration));
829}
830
831
832void
833TrafficLight::setProgramLogic(const std::string& tlsID, const TraCILogic& logic) {
835 // make sure index and phaseNo are consistent
836 if (logic.currentPhaseIndex >= (int)logic.phases.size()) {
837 throw TraCIException("set program: parameter index must be less than parameter phase number.");
838 }
839 std::vector<MSPhaseDefinition*> phases;
840 for (const std::shared_ptr<libsumo::TraCIPhase>& phase : logic.phases) {
841 MSPhaseDefinition* sumoPhase = new MSPhaseDefinition(TIME2STEPS(phase->duration), phase->state, phase->name);
842 sumoPhase->minDuration = TIME2STEPS(phase->minDur);
843 sumoPhase->maxDuration = TIME2STEPS(phase->maxDur);
844 sumoPhase->nextPhases = phase->next;
845 phases.push_back(sumoPhase);
846 }
847 if (vars.getLogic(logic.programID) == nullptr) {
849 int step = logic.currentPhaseIndex;
850 const std::string basePath = "";
851 MSTrafficLightLogic* tlLogic = nullptr;
852 SUMOTime nextSwitch = MSNet::getInstance()->getCurrentTimeStep() + phases[0]->duration;
853 switch ((TrafficLightType)logic.type) {
855 tlLogic = new MSActuatedTrafficLightLogic(tlc,
856 tlsID, logic.programID, 0,
857 phases, step, nextSwitch,
858 logic.subParameter, basePath);
859 break;
861 tlLogic = new NEMALogic(tlc,
862 tlsID, logic.programID, 0,
863 phases, step, nextSwitch,
864 logic.subParameter, basePath);
865 break;
867 tlLogic = new MSDelayBasedTrafficLightLogic(tlc,
868 tlsID, logic.programID, 0,
869 phases, step, nextSwitch,
870 logic.subParameter, basePath);
871 break;
873 tlLogic = new MSSimpleTrafficLightLogic(tlc,
874 tlsID, logic.programID, 0, TrafficLightType::STATIC,
875 phases, step, nextSwitch,
876 logic.subParameter);
877 break;
878 default:
879 throw TraCIException("Unsupported traffic light type '" + toString(logic.type) + "'");
880 }
881 try {
882 if (!vars.addLogic(logic.programID, tlLogic, true, true)) {
883 throw TraCIException("Could not add traffic light logic '" + logic.programID + "'");
884 }
885 } catch (const ProcessError& e) {
886 throw TraCIException(e.what());
887 }
888 // XXX pass GUIDetectorBuilder when running with gui
890 tlLogic->init(db);
892 } else {
893 MSSimpleTrafficLightLogic* tlLogic = static_cast<MSSimpleTrafficLightLogic*>(vars.getLogic(logic.programID));
894 tlLogic->setPhases(phases, logic.currentPhaseIndex);
897 }
898}
899
900
901void
902TrafficLight::setParameter(const std::string& tlsID, const std::string& paramName, const std::string& value) {
904 if (StringUtils::startsWith(paramName, "NEMA.") && tll->getLogicType() != TrafficLightType::NEMA) {
905 throw TraCIException("'" + tlsID + "' is not a NEMA controller");
906 }
907 tll->setParameter(paramName, value);
908}
909
911
912void
913TrafficLight::setNemaSplits(const std::string& tlsID, const std::vector<double>& splits) {
914 setParameter(tlsID, "NEMA.splits", toString(splits));
915}
916
917void
918TrafficLight::setNemaMaxGreens(const std::string& tlsID, const std::vector<double>& maxGreens) {
919 setParameter(tlsID, "NEMA.maxGreens", toString(maxGreens));
920}
921
922void
923TrafficLight::setNemaCycleLength(const std::string& tlsID, double cycleLength) {
924 setParameter(tlsID, "NEMA.cycleLength", toString(cycleLength));
925}
926
927void
928TrafficLight::setNemaOffset(const std::string& tlsID, double offset) {
929 setParameter(tlsID, "NEMA.offset", toString(offset));
930}
931
932
934TrafficLight::buildConstraint(const std::string& tlsID, const std::string& tripId, MSRailSignalConstraint* constraint) {
935 TraCISignalConstraint c;
936 c.tripId = tripId;
938 if (pc == nullptr) {
939 // unsupported constraint
940 c.type = -1;
941 } else {
942 c.signalId = tlsID;
943 c.foeId = pc->myTripId;
944 c.foeSignal = pc->myFoeSignal->getID();
945 c.limit = pc->myLimit;
946 c.type = pc->getType();
947 c.mustWait = !pc->cleared() && pc->isActive();
948 c.active = pc->isActive();
949 c.param = constraint->getParametersMap();
950 }
951 return c;
952}
953
954
955std::shared_ptr<VariableWrapper>
956TrafficLight::makeWrapper() {
957 return std::make_shared<Helper::SubscriptionWrapper>(handleVariable, mySubscriptionResults, myContextSubscriptionResults);
958}
959
960
961bool
962TrafficLight::handleVariable(const std::string& objID, const int variable, VariableWrapper* wrapper, tcpip::Storage* paramData) {
963 switch (variable) {
964 case TRACI_ID_LIST:
965 return wrapper->wrapStringList(objID, variable, getIDList());
966 case ID_COUNT:
967 return wrapper->wrapInt(objID, variable, getIDCount());
969 return wrapper->wrapString(objID, variable, getRedYellowGreenState(objID));
971 return wrapper->wrapStringList(objID, variable, getControlledLanes(objID));
972 case TL_CURRENT_PHASE:
973 return wrapper->wrapInt(objID, variable, getPhase(objID));
974 case VAR_NAME:
975 return wrapper->wrapString(objID, variable, getPhaseName(objID));
977 return wrapper->wrapString(objID, variable, getProgram(objID));
979 return wrapper->wrapDouble(objID, variable, getPhaseDuration(objID));
980 case TL_NEXT_SWITCH:
981 return wrapper->wrapDouble(objID, variable, getNextSwitch(objID));
983 return wrapper->wrapStringList(objID, variable, getControlledJunctions(objID));
985 paramData->readUnsignedByte();
986 return wrapper->wrapString(objID, variable, getParameter(objID, paramData->readString()));
988 paramData->readUnsignedByte();
989 return wrapper->wrapStringPair(objID, variable, getParameterWithKey(objID, paramData->readString()));
990 default:
991 return false;
992 }
993}
994}
995
996
997/****************************************************************************/
long long int SUMOTime
Definition: GUI.h:36
std::vector< const MSEdge * > ConstMSEdgeVector
Definition: MSEdge.h:74
#define WRITE_WARNINGF(...)
Definition: MsgHandler.h:268
#define TL(string)
Definition: MsgHandler.h:284
#define STEPS2TIME(x)
Definition: SUMOTime.h:54
#define TIME2STEPS(x)
Definition: SUMOTime.h:56
const int VEHPARS_FORCE_REROUTE
TrafficLightType
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition: ToString.h:46
#define LIBSUMO_SUBSCRIPTION_IMPLEMENTATION(CLASS, DOM)
Definition: TraCIDefs.h:76
#define LIBSUMO_GET_PARAMETER_WITH_KEY_IMPLEMENTATION(CLASS)
Definition: TraCIDefs.h:123
An actuated (adaptive) traffic light logic.
The base class for microscopic and mesoscopic vehicles.
Definition: MSBaseVehicle.h:55
const SUMOVehicleParameter & getParameter() const
Returns the vehicle's parameter (including departure definition)
const MSRouteIterator & getCurrentRouteEdge() const
Returns an iterator pointing to the current edge in this vehicles route.
const std::list< MSStop > & getStops() const
const MSRoute & getRoute() const
Returns the current route.
An actuated traffic light logic based on time delay of approaching vehicles.
A road/street connecting two junctions.
Definition: MSEdge.h:77
const std::set< MSTransportable *, ComparatorNumericalIdLess > & getPersons() const
Returns this edge's persons set.
Definition: MSEdge.h:201
const std::vector< MSLane * > & getLanes() const
Returns this edge's lanes.
Definition: MSEdge.h:168
const MSJunction * getToJunction() const
Definition: MSEdge.h:415
SumoXMLNodeType getType() const
return the type of this Junction
Definition: MSJunction.h:135
Representation of a lane in the micro simulation.
Definition: MSLane.h:84
MSEdge & getEdge() const
Returns the lane's edge.
Definition: MSLane.h:745
const std::vector< MSLink * > & getLinkCont() const
returns the container with all links !!!
Definition: MSLane.h:707
static MSNet * getInstance()
Returns the pointer to the unique instance of MSNet (singleton).
Definition: MSNet.cpp:183
MSTLLogicControl & getTLSControl()
Returns the tls logics control.
Definition: MSNet.h:451
SUMOTime getCurrentTimeStep() const
Returns the current simulation step.
Definition: MSNet.h:320
virtual void createTLWrapper(MSTrafficLightLogic *)
creates a wrapper for the given logic (see GUINet)
Definition: MSNet.h:577
MSVehicleControl & getVehicleControl()
Returns the vehicle control.
Definition: MSNet.h:378
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:561
The definition of a single phase of a tls logic.
SUMOTime maxDuration
The maximum duration of the phase.
SUMOTime minDuration
The minimum duration of the phase.
const std::string & getName() const
const std::string & getState() const
Returns the state within this phase.
SUMOTime duration
The duration of the phase.
std::vector< int > nextPhases
The index of the phase that suceeds this one (or -1)
const MSRailSignal * myFoeSignal
store the foe signal (for TraCI access)
bool cleared() const
whether the constraint has been met
const std::string myTripId
id of the predecessor that must already have passed
const int myLimit
the number of passed vehicles within which tripId must have occured
A base class for constraints.
virtual void setActive(bool active)=0
ConstraintType getType() const
ConstraintType getSwappedType() const
static MSRailSignalControl & getInstance()
const std::vector< MSRailSignal * > & getSignals() const
A signal for rails.
Definition: MSRailSignal.h:46
void addConstraint(const std::string &tripId, MSRailSignalConstraint *constraint)
register contraint for signal switching
const std::map< std::string, std::vector< MSRailSignalConstraint * > > & getConstraints() const
Definition: MSRailSignal.h:230
bool removeConstraint(const std::string &tripId, MSRailSignalConstraint *constraint)
remove contraint for signal switching
const ConstMSEdgeVector & getEdges() const
Definition: MSRoute.h:124
A fixed traffic light logic.
void setPhases(const Phases &phases, int index)
Replaces the phases and set the phase index.
Definition: MSStop.h:44
Storage for all programs of a single tls.
void switchTo(MSTLLogicControl &tlc, const std::string &programID)
void setStateInstantiatingOnline(MSTLLogicControl &tlc, const std::string &state)
std::vector< MSTrafficLightLogic * > getAllLogics() const
MSTrafficLightLogic * getLogic(const std::string &programID) const
bool addLogic(const std::string &programID, MSTrafficLightLogic *logic, bool netWasLoaded, bool isNewDefault=true)
Adds a logic (program). In case of an error the logic gets deleted.
MSTrafficLightLogic * getActive() const
MSTrafficLightLogic * getDefault() const
return the default program (that last used program except TRACI_PROGRAM)
A class that stores and controls tls and switching of their programs.
std::vector< std::string > getAllTLIds() const
The parent class for traffic light logics.
const LinkVectorVector & getLinks() const
Returns the list of lists of all affected links.
std::vector< LaneVector > LaneVectorVector
Definition of a list that holds lists of lanes that do have the same attribute.
virtual const MSPhaseDefinition & getCurrentPhaseDef() const =0
Returns the definition of the current phase.
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 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 const MSPhaseDefinition & getPhase(int givenstep) const =0
Returns the definition of the phase from the given position within the plan.
virtual VehicleVector getRivalVehicles(int linkIndex)
return vehicles that approach the intersection/rail signal and are in conflict with vehicles that wis...
const std::string & getProgramID() const
Returns this tl-logic's id.
TrafficLightType getLogicType() const
Returns the type of the logic.
int getNumLinks() const
return the number of controlled link indices
virtual const Phases & getPhases() const =0
Returns the phases of this tls program.
const LaneVectorVector & getLaneVectors() const
Returns the list of lists of all lanes controlled by this tls.
bool setTrafficLightSignals(SUMOTime t) const
Applies the current signal states to controlled links.
const LinkVector & getLinksAt(int i) const
Returns the list of links that are controlled by the signals at the given position.
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 void init(NLDetectorBuilder &nb)
Initialises the tls with information about incoming lanes.
const MSLane * getLane() const
Returns the current lane (may be nullptr)
const MSEdge * getEdge() const
Returns the current edge.
The class responsible for building and deletion of vehicles.
SUMOVehicle * getVehicle(const std::string &id) const
Returns the vehicle with the given id.
std::map< std::string, SUMOVehicle * >::const_iterator constVehIt
Definition of the internal vehicles map iterator.
constVehIt loadedVehBegin() const
Returns the begin of the internal vehicle map.
constVehIt loadedVehEnd() const
Returns the end of the internal vehicle map.
A NEMA (adaptive) traffic light logic based on E2Detector.
Builds detectors for microsim.
const std::string & getID() const
Returns the id.
Definition: Named.h:74
void unsetParameter(const std::string &key)
Removes a parameter.
virtual const std::string getParameter(const std::string &key, const std::string defaultValue="") const
Returns the value for a given key.
const Parameterised::Map & getParametersMap() const
Returns the inner key/value map.
virtual void setParameter(const std::string &key, const std::string &value)
Sets a parameter.
void updateParameters(const Parameterised::Map &mapArg)
Adds or updates all given parameters from the map.
virtual NumericalID getNumericalID() const =0
return the numerical ID which is only for internal usage
virtual const SUMOVehicleParameter & getParameter() const =0
Returns the vehicle's parameter (including departure definition)
virtual int getRoutePosition() const =0
return index of edge within route
virtual const MSEdge * getEdge() const =0
Returns the edge the object is currently at.
virtual double getPositionOnLane() const =0
Get the object's position along the lane.
Representation of a vehicle.
Definition: SUMOVehicle.h:62
virtual bool hasDeparted() const =0
Returns whether this vehicle has departed.
virtual const MSRoute & getRoute() const =0
Returns the current route.
bool wasSet(int what) const
Returns whether the given parameter was set.
static bool startsWith(const std::string &str, const std::string prefix)
Checks whether a given string starts with the prefix.
C++ TraCI client API implementation.
static MSBaseVehicle * getVehicle(const std::string &id)
Definition: Helper.cpp:477
static MSTLLogicControl::TLSLogicVariants & getTLS(const std::string &id)
Definition: Helper.cpp:518
virtual std::string readString()
Definition: storage.cpp:180
virtual int readUnsignedByte()
Definition: storage.cpp:155
TRACI_CONST int VAR_NAME
TRACI_CONST int TRACI_ID_LIST
std::map< std::string, libsumo::SubscriptionResults > ContextSubscriptionResults
Definition: TraCIDefs.h:338
TRACI_CONST int TL_CONTROLLED_LANES
TRACI_CONST int TL_CONTROLLED_JUNCTIONS
std::map< std::string, libsumo::TraCIResults > SubscriptionResults
{object->{variable->value}}
Definition: TraCIDefs.h:337
TRACI_CONST int ID_COUNT
TRACI_CONST int VAR_PARAMETER
TRACI_CONST int TL_NEXT_SWITCH
TRACI_CONST int VAR_PARAMETER_WITH_KEY
TRACI_CONST int TL_PHASE_DURATION
TRACI_CONST int TL_CURRENT_PHASE
TRACI_CONST int TL_RED_YELLOW_GREEN_STATE
TRACI_CONST int TL_CURRENT_PROGRAM
std::string tripId
the tripId or vehicle id of the train that is constrained
Definition: TraCIDefs.h:653