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