1 /****************************************************************************/
2 // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
3 // Copyright (C) 2001-2019 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 /****************************************************************************/
10 /// @file NIVissimTL.cpp
11 /// @author Daniel Krajzewicz
12 /// @author Jakob Erdmann
13 /// @author Michael Behrisch
14 /// @date Sept 2002
15 /// @version $Id$
16 ///
17 // -------------------
18 /****************************************************************************/
19
20
21 // ===========================================================================
22 // included modules
23 // ===========================================================================
24 #include <config.h>
25
26
27 #include <map>
28 #include <string>
29 #include <cassert>
30 #include <utils/geom/GeomHelper.h>
31 #include <utils/geom/Boundary.h>
32 #include <utils/common/MsgHandler.h>
33 #include <utils/common/ToString.h>
34 #include "NIVissimConnection.h"
35 #include <netbuild/NBEdge.h>
36 #include <netbuild/NBEdgeCont.h>
37 #include <netbuild/NBTrafficLightLogicCont.h>
38 #include <netbuild/NBLoadedTLDef.h>
39 #include "NIVissimDisturbance.h"
40 #include "NIVissimNodeDef.h"
41 #include "NIVissimEdge.h"
42 #include "NIVissimTL.h"
43
44
45 // ===========================================================================
46 // static member variables
47 // ===========================================================================
48 NIVissimTL::SignalDictType NIVissimTL::NIVissimTLSignal::myDict;
49
50
51 // ===========================================================================
52 // method definitions
53 // ===========================================================================
NIVissimTLSignal(int id,const std::string & name,const std::vector<int> & groupids,int edgeid,int laneno,double position,const std::vector<int> & vehicleTypes)54 NIVissimTL::NIVissimTLSignal::NIVissimTLSignal(int id,
55 const std::string& name,
56 const std::vector<int>& groupids,
57 int edgeid,
58 int laneno,
59 double position,
60 const std::vector<int>& vehicleTypes)
61 : myID(id), myName(name), myGroupIDs(groupids),
62 myEdgeID(edgeid), myLane(laneno), myPosition(position),
63 myVehicleTypes(vehicleTypes) {}
64
65
~NIVissimTLSignal()66 NIVissimTL::NIVissimTLSignal::~NIVissimTLSignal() {}
67
68 bool
isWithin(const PositionVector & poly) const69 NIVissimTL::NIVissimTLSignal::isWithin(const PositionVector& poly) const {
70 return poly.around(getPosition());
71 }
72
73
74 Position
getPosition() const75 NIVissimTL::NIVissimTLSignal::getPosition() const {
76 return NIVissimAbstractEdge::dictionary(myEdgeID)->getGeomPosition(myPosition);
77 }
78
79
80 bool
dictionary(int lsaid,int id,NIVissimTL::NIVissimTLSignal * o)81 NIVissimTL::NIVissimTLSignal::dictionary(int lsaid, int id,
82 NIVissimTL::NIVissimTLSignal* o) {
83 SignalDictType::iterator i = myDict.find(lsaid);
84 if (i == myDict.end()) {
85 myDict[lsaid] = SSignalDictType();
86 i = myDict.find(lsaid);
87 }
88 SSignalDictType::iterator j = (*i).second.find(id);
89 if (j == (*i).second.end()) {
90 myDict[lsaid][id] = o;
91 return true;
92 }
93 return false;
94 }
95
96
97 NIVissimTL::NIVissimTLSignal*
dictionary(int lsaid,int id)98 NIVissimTL::NIVissimTLSignal::dictionary(int lsaid, int id) {
99 SignalDictType::iterator i = myDict.find(lsaid);
100 if (i == myDict.end()) {
101 return nullptr;
102 }
103 SSignalDictType::iterator j = (*i).second.find(id);
104 if (j == (*i).second.end()) {
105 return nullptr;
106 }
107 return (*j).second;
108 }
109
110
111 void
clearDict()112 NIVissimTL::NIVissimTLSignal::clearDict() {
113 for (SignalDictType::iterator i = myDict.begin(); i != myDict.end(); i++) {
114 for (SSignalDictType::iterator j = (*i).second.begin(); j != (*i).second.end(); j++) {
115 delete (*j).second;
116 }
117 }
118 myDict.clear();
119 }
120
121
122 NIVissimTL::SSignalDictType
getSignalsFor(int tlid)123 NIVissimTL::NIVissimTLSignal::getSignalsFor(int tlid) {
124 SignalDictType::iterator i = myDict.find(tlid);
125 if (i == myDict.end()) {
126 return SSignalDictType();
127 }
128 return (*i).second;
129 }
130
131
132 bool
addTo(NBEdgeCont & ec,NBLoadedTLDef * tl) const133 NIVissimTL::NIVissimTLSignal::addTo(NBEdgeCont& ec, NBLoadedTLDef* tl) const {
134 NIVissimConnection* c = NIVissimConnection::dictionary(myEdgeID);
135 NBConnectionVector assignedConnections;
136 if (c == nullptr) {
137 // What to do if on an edge? -> close all outgoing connections
138 NBEdge* edge = ec.retrievePossiblySplit(toString<int>(myEdgeID), myPosition);
139 if (edge == nullptr) {
140 WRITE_WARNING("Could not set tls signal at edge '" + toString(myEdgeID) + "' - the edge was not built.");
141 return false;
142 }
143 // Check whether it is already known, which edges are approached
144 // by which lanes
145 // check whether to use the original lanes only
146 if (edge->lanesWereAssigned()) {
147 std::vector<NBEdge::Connection> connections = edge->getConnectionsFromLane(myLane - 1);
148 for (std::vector<NBEdge::Connection>::iterator i = connections.begin(); i != connections.end(); i++) {
149 const NBEdge::Connection& conn = *i;
150 assert(myLane - 1 < (int)edge->getNumLanes());
151 assignedConnections.push_back(NBConnection(edge, myLane - 1, conn.toEdge, conn.toLane));
152 }
153 } else {
154 WRITE_WARNING("Edge : Lanes were not assigned(!)");
155 for (int j = 0; j < edge->getNumLanes(); j++) {
156 std::vector<NBEdge::Connection> connections = edge->getConnectionsFromLane(j);
157 for (std::vector<NBEdge::Connection>::iterator i = connections.begin(); i != connections.end(); i++) {
158 const NBEdge::Connection& conn = *i;
159 assignedConnections.push_back(NBConnection(edge, j, conn.toEdge, conn.toLane));
160 }
161 }
162 }
163 } else {
164 // get the edges
165 NBEdge* tmpFrom = ec.retrievePossiblySplit(toString<int>(c->getFromEdgeID()), toString<int>(c->getToEdgeID()), true);
166 NBEdge* tmpTo = ec.retrievePossiblySplit(toString<int>(c->getToEdgeID()), toString<int>(c->getFromEdgeID()), false);
167 // check whether the edges are known
168 if (tmpFrom != nullptr && tmpTo != nullptr) {
169 // add connections this signal is responsible for
170 assignedConnections.push_back(NBConnection(tmpFrom, -1, tmpTo, -1));
171 } else {
172 return false;
173 // !!! one of the edges could not be build
174 }
175 }
176 // add to the group
177 assert(myGroupIDs.size() != 0);
178 // @todo just another hack?!
179 /*
180 if (myGroupIDs.size() == 1) {
181 return tl->addToSignalGroup(toString<int>(*(myGroupIDs.begin())),
182 assignedConnections);
183 } else {
184 // !!!
185 return tl->addToSignalGroup(toString<int>(*(myGroupIDs.begin())),
186 assignedConnections);
187 }
188 */
189 return tl->addToSignalGroup(toString<int>(myGroupIDs.front()), assignedConnections);
190 }
191
192
193
194
195
196
197
198
199 NIVissimTL::GroupDictType NIVissimTL::NIVissimTLSignalGroup::myDict;
200
NIVissimTLSignalGroup(int id,const std::string & name,bool isGreenBegin,const std::vector<double> & times,SUMOTime tredyellow,SUMOTime tyellow)201 NIVissimTL::NIVissimTLSignalGroup::NIVissimTLSignalGroup(
202 int id,
203 const std::string& name,
204 bool isGreenBegin, const std::vector<double>& times,
205 SUMOTime tredyellow, SUMOTime tyellow)
206 : myID(id), myName(name), myTimes(times),
207 myFirstIsRed(!isGreenBegin), myTRedYellow(tredyellow),
208 myTYellow(tyellow) {}
209
210
~NIVissimTLSignalGroup()211 NIVissimTL::NIVissimTLSignalGroup::~NIVissimTLSignalGroup() {}
212
213
214 bool
dictionary(int lsaid,int id,NIVissimTL::NIVissimTLSignalGroup * o)215 NIVissimTL::NIVissimTLSignalGroup::dictionary(int lsaid, int id,
216 NIVissimTL::NIVissimTLSignalGroup* o) {
217 GroupDictType::iterator i = myDict.find(lsaid);
218 if (i == myDict.end()) {
219 myDict[lsaid] = SGroupDictType();
220 i = myDict.find(lsaid);
221 }
222 SGroupDictType::iterator j = (*i).second.find(id);
223 if (j == (*i).second.end()) {
224 myDict[lsaid][id] = o;
225 return true;
226 }
227 return false;
228 /*
229 GroupDictType::iterator i=myDict.find(id);
230 if(i==myDict.end()) {
231 myDict[id] = o;
232 return true;
233 }
234 return false;
235 */
236 }
237
238
239 NIVissimTL::NIVissimTLSignalGroup*
dictionary(int lsaid,int id)240 NIVissimTL::NIVissimTLSignalGroup::dictionary(int lsaid, int id) {
241 GroupDictType::iterator i = myDict.find(lsaid);
242 if (i == myDict.end()) {
243 return nullptr;
244 }
245 SGroupDictType::iterator j = (*i).second.find(id);
246 if (j == (*i).second.end()) {
247 return nullptr;
248 }
249 return (*j).second;
250 }
251
252 void
clearDict()253 NIVissimTL::NIVissimTLSignalGroup::clearDict() {
254 for (GroupDictType::iterator i = myDict.begin(); i != myDict.end(); i++) {
255 for (SGroupDictType::iterator j = (*i).second.begin(); j != (*i).second.end(); j++) {
256 delete (*j).second;
257 }
258 }
259 myDict.clear();
260 }
261
262
263 NIVissimTL::SGroupDictType
getGroupsFor(int tlid)264 NIVissimTL::NIVissimTLSignalGroup::getGroupsFor(int tlid) {
265 GroupDictType::iterator i = myDict.find(tlid);
266 if (i == myDict.end()) {
267 return SGroupDictType();
268 }
269 return (*i).second;
270 }
271
272
273 bool
addTo(NBLoadedTLDef * tl) const274 NIVissimTL::NIVissimTLSignalGroup::addTo(NBLoadedTLDef* tl) const {
275 // get the color at the begin
276 NBTrafficLightDefinition::TLColor color = myFirstIsRed
277 ? NBTrafficLightDefinition::TLCOLOR_RED : NBTrafficLightDefinition::TLCOLOR_GREEN;
278 std::string id = toString<int>(myID);
279 tl->addSignalGroup(id); // !!! myTimes als SUMOTime
280 for (std::vector<double>::const_iterator i = myTimes.begin(); i != myTimes.end(); i++) {
281 tl->addSignalGroupPhaseBegin(id, (SUMOTime) *i, color);
282 color = color == NBTrafficLightDefinition::TLCOLOR_RED
283 ? NBTrafficLightDefinition::TLCOLOR_GREEN : NBTrafficLightDefinition::TLCOLOR_RED;
284 }
285 if (myTimes.size() == 0) {
286 if (myFirstIsRed) {
287 tl->addSignalGroupPhaseBegin(id, 0, NBTrafficLightDefinition::TLCOLOR_RED);
288 } else {
289 tl->addSignalGroupPhaseBegin(id, 0, NBTrafficLightDefinition::TLCOLOR_GREEN);
290 }
291 }
292 tl->setSignalYellowTimes(id, myTRedYellow, myTYellow);
293 return true;
294 }
295
296
297
298
299
300
301
302
303 NIVissimTL::DictType NIVissimTL::myDict;
304
NIVissimTL(int id,const std::string & type,const std::string & name,SUMOTime absdur,SUMOTime offset)305 NIVissimTL::NIVissimTL(int id, const std::string& type,
306 const std::string& name, SUMOTime absdur,
307 SUMOTime offset)
308 : myID(id), myName(name), myAbsDuration(absdur), myOffset(offset),
309 myCurrentGroup(nullptr), myType(type)
310
311 {}
312
313
~NIVissimTL()314 NIVissimTL::~NIVissimTL() {}
315
316
317
318
319
320 bool
dictionary(int id,const std::string & type,const std::string & name,SUMOTime absdur,SUMOTime offset)321 NIVissimTL::dictionary(int id, const std::string& type,
322 const std::string& name, SUMOTime absdur,
323 SUMOTime offset) {
324 NIVissimTL* o = new NIVissimTL(id, type, name, absdur, offset);
325 if (!dictionary(id, o)) {
326 delete o;
327 return false;
328 }
329 return true;
330 }
331
332 bool
dictionary(int id,NIVissimTL * o)333 NIVissimTL::dictionary(int id, NIVissimTL* o) {
334 DictType::iterator i = myDict.find(id);
335 if (i == myDict.end()) {
336 myDict[id] = o;
337 return true;
338 }
339 return false;
340 }
341
342
343 NIVissimTL*
dictionary(int id)344 NIVissimTL::dictionary(int id) {
345 DictType::iterator i = myDict.find(id);
346 if (i == myDict.end()) {
347 return nullptr;
348 }
349 return (*i).second;
350 }
351
352
353 void
clearDict()354 NIVissimTL::clearDict() {
355 for (DictType::iterator i = myDict.begin(); i != myDict.end(); i++) {
356 delete (*i).second;
357 }
358 myDict.clear();
359 }
360
361
362
363
364
365 bool
dict_SetSignals(NBTrafficLightLogicCont & tlc,NBEdgeCont & ec)366 NIVissimTL::dict_SetSignals(NBTrafficLightLogicCont& tlc,
367 NBEdgeCont& ec) {
368 int ref = 0;
369 int ref_groups = 0;
370 int ref_signals = 0;
371 int no_signals = 0;
372 int no_groups = 0;
373 for (DictType::iterator i = myDict.begin(); i != myDict.end(); i++) {
374 NIVissimTL* tl = (*i).second;
375 /* if(tl->myType!="festzeit") {
376 cout << " Warning: The traffic light '" << tl->myID
377 << "' could not be assigned to a node." << endl;
378 ref++;
379 continue;
380 }*/
381 std::string id = toString<int>(tl->myID);
382 TrafficLightType type = ((tl->getType() == "festzeit" || tl->getType() == "festzeit_fake") ?
383 TLTYPE_STATIC : TLTYPE_ACTUATED);
384 NBLoadedTLDef* def = new NBLoadedTLDef(ec, id, 0, type);
385 if (!tlc.insert(def)) {
386 WRITE_ERROR("Error on adding a traffic light\n Must be a multiple id ('" + id + "')");
387 continue;
388 }
389 def->setCycleDuration((int) tl->myAbsDuration);
390 // add each group to the node's container
391 SGroupDictType sgs = NIVissimTLSignalGroup::getGroupsFor(tl->getID());
392 for (SGroupDictType::const_iterator j = sgs.begin(); j != sgs.end(); j++) {
393 if (!(*j).second->addTo(def)) {
394 WRITE_WARNING("The signal group '" + toString<int>((*j).first) + "' could not be assigned to tl '" + toString<int>(tl->myID) + "'.");
395 ref_groups++;
396 }
397 no_groups++;
398 }
399 // add the signal group signals to the node
400 SSignalDictType signals = NIVissimTLSignal::getSignalsFor(tl->getID());
401 for (SSignalDictType::const_iterator k = signals.begin(); k != signals.end(); k++) {
402 if (!(*k).second->addTo(ec, def)) {
403 WRITE_WARNING("The signal '" + toString<int>((*k).first) + "' could not be assigned to tl '" + toString<int>(tl->myID) + "'.");
404 ref_signals++;
405 }
406 no_signals++;
407 }
408 }
409 if (ref != 0) {
410 WRITE_WARNING("Could not set " + toString<int>(ref) + " of " + toString<int>((int)myDict.size()) + " traffic lights.");
411 }
412 if (ref_groups != 0) {
413 WRITE_WARNING("Could not set " + toString<int>(ref_groups) + " of " + toString<int>(no_groups) + " groups.");
414 }
415 if (ref_signals != 0) {
416 WRITE_WARNING("Could not set " + toString<int>(ref_signals) + " of " + toString<int>(no_signals) + " signals.");
417 }
418 return true;
419
420 }
421
422
423 std::string
getType() const424 NIVissimTL::getType() const {
425 return myType;
426 }
427
428
429 int
getID() const430 NIVissimTL::getID() const {
431 return myID;
432 }
433
434
435
436 /****************************************************************************/
437
438