@@ -88,10 +88,162 @@ namespace dsm {
8888 }
8989 }
9090
91+ void RoadNetwork::initTrafficLights () {
92+ for (auto const & [id, pNode] : m_nodes) {
93+ if (!pNode->isTrafficLight ()) {
94+ continue ;
95+ }
96+ auto & tl = dynamic_cast <TrafficLight&>(*pNode);
97+ if (!tl.streetPriorities ().empty () || !tl.cycles ().empty ()) {
98+ continue ;
99+ }
100+ auto const & inNeighbours = m_adjacencyMatrix.getCol (id);
101+ std::map<Id, int , std::greater<int >> capacities;
102+ std::unordered_map<Id, double > streetAngles;
103+ std::unordered_map<Id, double > maxSpeeds;
104+ std::unordered_map<Id, int > nLanes;
105+ double higherSpeed{0 .}, lowerSpeed{std::numeric_limits<double >::max ()};
106+ int higherNLanes{0 }, lowerNLanes{std::numeric_limits<int >::max ()};
107+ if (inNeighbours.size () < 3 ) {
108+ Logger::warning (std::format (
109+ " Not enough in neighbours {} for Traffic Light {}" , inNeighbours.size (), id));
110+ // Replace with a normal intersection
111+ auto const & coordinates{pNode->coords ()};
112+ if (coordinates.has_value ()) {
113+ m_nodes[id] = std::make_unique<Intersection>(id, *coordinates);
114+ } else {
115+ m_nodes[id] = std::make_unique<Intersection>(id);
116+ }
117+ continue ;
118+ }
119+ for (auto const & inId : inNeighbours) {
120+ auto const streetId{inId * nNodes () + id};
121+ auto const & pStreet{m_edges.at (streetId)};
122+
123+ double const speed{pStreet->maxSpeed ()};
124+ int const nLan{pStreet->nLanes ()};
125+ auto const cap{pStreet->capacity ()};
126+ Logger::debug (std::format (" Street {} with capacity {}" , streetId, cap));
127+ capacities.emplace (streetId, cap);
128+ streetAngles.emplace (streetId, pStreet->angle ());
129+
130+ maxSpeeds.emplace (streetId, speed);
131+ nLanes.emplace (streetId, nLan);
132+
133+ higherSpeed = std::max (higherSpeed, speed);
134+ lowerSpeed = std::min (lowerSpeed, speed);
135+
136+ higherNLanes = std::max (higherNLanes, nLan);
137+ lowerNLanes = std::min (lowerNLanes, nLan);
138+ }
139+ if (higherSpeed != lowerSpeed) {
140+ // Assign streets with higher speed to priority
141+ for (auto const & [sid, speed] : maxSpeeds) {
142+ if (speed == higherSpeed) {
143+ tl.addStreetPriority (sid);
144+ }
145+ }
146+ // continue;
147+ } else if (higherNLanes != lowerNLanes) {
148+ for (auto const & [sid, nLan] : nLanes) {
149+ if (nLan == higherNLanes) {
150+ tl.addStreetPriority (sid);
151+ }
152+ }
153+ // continue;
154+ }
155+ // Set first two elements of capacities to street priorities
156+ // auto it{capacities.begin()};
157+ // tl.addStreetPriority(it->first);
158+ // ++it;
159+ // if (it != capacities.end()) {
160+ // tl.addStreetPriority(it->first);
161+ // continue;
162+ // }
163+ // Id firstStreetId{streetAngles.begin()->first};
164+ // tl.addStreetPriority(firstStreetId);
165+ // for (auto const& [streetId, angle] : streetAngles) {
166+ // if (streetId == firstStreetId) {
167+ // continue;
168+ // }
169+ // if (angle == streetAngles.begin()->second) {
170+ // tl.addStreetPriority(streetId);
171+ // }
172+ // }
173+ // if (tl.streetPriorities().size() > 1) {
174+ // continue;
175+ // }
176+ if (tl.streetPriorities ().empty ()) {
177+ Logger::warning (std::format (" Failed to auto-init Traffic Light {}" , id));
178+ continue ;
179+ }
180+
181+ // Assign cycles
182+ std::pair<Delay, Delay> greenTimes;
183+ {
184+ auto capPriority{0 .}, capNoPriority{0 .};
185+ std::unordered_map<Id, double > normCapacities;
186+ auto sum{0 .};
187+ for (auto const & [streetId, cap] : capacities) {
188+ sum += cap;
189+ }
190+ for (auto const & [streetId, cap] : capacities) {
191+ normCapacities.emplace (streetId, cap / sum);
192+ }
193+ for (auto const & [streetId, normCap] : normCapacities) {
194+ if (tl.streetPriorities ().contains (streetId)) {
195+ capPriority += normCap;
196+ } else {
197+ capNoPriority += normCap;
198+ }
199+ }
200+ Logger::debug (
201+ std::format (" Capacities for Traffic Light {}: priority {} no priority {}" ,
202+ id,
203+ capPriority,
204+ capNoPriority));
205+ greenTimes = std::make_pair (static_cast <Delay>(capPriority * tl.cycleTime ()),
206+ static_cast <Delay>(capNoPriority * tl.cycleTime ()));
207+ }
208+ std::for_each (inNeighbours.begin (), inNeighbours.end (), [&](Id const inId) {
209+ auto const streetId{inId * nNodes () + id};
210+ auto const nLane{nLanes.at (streetId)};
211+ Delay greenTime{greenTimes.first };
212+ Delay phase{0 };
213+ if (!tl.streetPriorities ().contains (streetId)) {
214+ phase = greenTime;
215+ greenTime = greenTimes.second ;
216+ }
217+ Logger::debug (
218+ std::format (" Setting cycle for street {} with green time {} and phase {}" ,
219+ streetId,
220+ greenTime,
221+ phase));
222+ switch (nLane) {
223+ case 3 :
224+ tl.setCycle (streetId,
225+ dsm::Direction::RIGHTANDSTRAIGHT,
226+ TrafficLightCycle{static_cast <Delay>(greenTime * 2 . / 3 ), phase});
227+ tl.setCycle (
228+ streetId,
229+ dsm::Direction::LEFT,
230+ TrafficLightCycle{
231+ static_cast <Delay>(greenTime / 3 .),
232+ static_cast <Delay>(phase + static_cast <Delay>(greenTime * 2 . / 3 ))});
233+ break ;
234+ default :
235+ tl.setCycle (
236+ streetId, dsm::Direction::ANY, TrafficLightCycle{greenTime, phase});
237+ break ;
238+ }
239+ });
240+ }
241+ }
242+
91243 void RoadNetwork::buildAdj () {
92244 // find max values in streets node pairs
93245 m_maxAgentCapacity = 0 ;
94- for (const auto & [streetId, pStreet] : m_edges) {
246+ for (auto const & [streetId, pStreet] : m_edges) {
95247 m_maxAgentCapacity += pStreet->capacity ();
96248 if (pStreet->geometry ().empty ()) {
97249 std::vector<std::pair<double , double >> coords;
@@ -319,7 +471,7 @@ namespace dsm {
319471 std::getline (iss, highway, ' ;' );
320472 if (highway.find (" traffic_signals" ) != std::string::npos) {
321473 addNode<TrafficLight>(
322- nodeIndex, 60 , std::make_pair (std::stod (lat), std::stod (lon)));
474+ nodeIndex, 120 , std::make_pair (std::stod (lat), std::stod (lon)));
323475 } else if (highway.find (" roundabout" ) != std::string::npos) {
324476 addNode<Roundabout>(nodeIndex, std::make_pair (std::stod (lat), std::stod (lon)));
325477 } else {
0 commit comments