-
Notifications
You must be signed in to change notification settings - Fork 4
Make priority attribute boolean and bugfixing traffic lights #385
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #385 +/- ##
==========================================
+ Coverage 83.55% 84.76% +1.21%
==========================================
Files 53 53
Lines 5466 5699 +233
Branches 634 640 +6
==========================================
+ Hits 4567 4831 +264
+ Misses 888 857 -31
Partials 11 11
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
| RoadNetwork graph{}; | ||
| // Node 1 is the intersection | ||
| // Edge 1: 0 -> 1 (HIGHWAY) | ||
| Street s1(1, std::make_pair(0, 1), 100., 30., 1); |
Check notice
Code scanning / Cppcheck (reported by Codacy)
MISRA 12.3 rule Note test
| s1.setRoadType(RoadType::HIGHWAY); | ||
|
|
||
| // Edge 2: 2 -> 1 (HIGHWAY) | ||
| Street s2(2, std::make_pair(2, 1), 100., 30., 1); |
Check notice
Code scanning / Cppcheck (reported by Codacy)
MISRA 12.3 rule Note test
| s2.setRoadType(RoadType::HIGHWAY); | ||
|
|
||
| // Edge 3: 3 -> 1 (SECONDARY) | ||
| Street s3(3, std::make_pair(3, 1), 100., 30., 1); |
Check notice
Code scanning / Cppcheck (reported by Codacy)
MISRA 12.3 rule Note test
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This pull request refactors the road priority system from a numeric priority value (int m_priority) to a boolean flag (bool m_hasPriority) that indicates whether a road has priority or not. It also introduces a new method autoAssignRoadPriorities() that automatically assigns priorities based on road types at intersections.
Changes:
- Changed priority from a numeric value to a boolean flag indicating presence/absence of priority
- Updated
autoMapStreetLanes()to use estimated flow (maxSpeed × nLanes) instead of numeric priorities - Added
autoAssignRoadPriorities()method to automatically assign priorities based on road types
Reviewed changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| src/dsf/mobility/Road.hpp | Changed m_priority from int to bool m_hasPriority, updated setPriority() to take no parameters and priority() to hasPriority() |
| src/dsf/mobility/Road.cpp | Removed the constructor initialization of m_priority and the setPriority(int) method implementation |
| src/dsf/mobility/Street.cpp | Updated equality operator to compare m_hasPriority instead of m_priority |
| src/dsf/mobility/RoadNetwork.hpp | Added declaration for autoAssignRoadPriorities() method |
| src/dsf/mobility/RoadNetwork.cpp | Updated autoMapStreetLanes() to use estimated flow calculations; added autoAssignRoadPriorities() implementation |
| test/mobility/Test_street.cpp | Updated tests to use hasPriority() and parameter-less setPriority() |
| test/mobility/Test_graph.cpp | Added test case for autoAssignRoadPriorities() |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
src/dsf/mobility/RoadNetwork.hpp
Outdated
| /// @brief Automatically re-maps street lanes basing on network's topology | ||
| /// @details For example, if one street has the right turn forbidden, then the right lane becomes a straight one | ||
| void autoMapStreetLanes(); | ||
|
|
Copilot
AI
Jan 16, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The new autoAssignRoadPriorities() method lacks documentation. Add a @brief comment explaining what this method does, such as '@brief Automatically assigns road priorities based on road types at intersections'.
| /// @brief Automatically assigns road priorities based on road types at intersections. |
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Cppcheck (reported by Codacy) found more than 20 potential problems in the proposed changes. Check the Files changed tab for more details.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
Copilot reviewed 9 out of 9 changed files in this pull request and generated 11 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| /************************************************************* | ||
| * 2. Check for street names with same max speed | ||
| * ***********************************************************/ |
Copilot
AI
Jan 19, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The comment says "Check for street names with same max speed" but the logic is checking for streets with the highest speed, not streets with the same speed. The comment should be updated to reflect the actual behavior, e.g., "Check for streets with highest max speed".
src/dsf/mobility/RoadNetwork.cpp
Outdated
| // Replace with a normal intersection | ||
| auto const& geometry{pNode->geometry()}; | ||
| if (geometry.has_value()) { | ||
| pNode = std::make_unique<Intersection>(pNode->id(), *geometry); | ||
| } else { | ||
| pNode = std::make_unique<Intersection>(pNode->id()); |
Copilot
AI
Jan 19, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Modifying pNode inside a parallel_for_each can cause a data race. At line 387 and 389, pNode is reassigned to a new unique_ptr, which modifies the map entry. If multiple threads are iterating over m_nodes and one thread modifies the map structure or a specific entry, this can lead to undefined behavior. Consider using a standard for_each loop for this function, or collect nodes to convert and process them sequentially after the parallel phase.
| // Replace with a normal intersection | |
| auto const& geometry{pNode->geometry()}; | |
| if (geometry.has_value()) { | |
| pNode = std::make_unique<Intersection>(pNode->id(), *geometry); | |
| } else { | |
| pNode = std::make_unique<Intersection>(pNode->id()); | |
| // Not enough neighbours to configure a proper traffic light; skip further processing | |
| auto const& geometry{pNode->geometry()}; | |
| if (geometry.has_value()) { | |
| // In a parallel context, avoid modifying the underlying node container here. | |
| } else { | |
| // In a parallel context, avoid modifying the underlying node container here. |
| #include "RoadNetwork.hpp" | ||
| #include "../geometry/Point.hpp" | ||
| #include "../geometry/PolyLine.hpp" | ||
| #include "RoadNetwork.hpp" | ||
|
|
||
| #include <algorithm> | ||
| #include <ranges> | ||
|
|
||
| #include <rapidcsv.h> | ||
| #include <simdjson.h> | ||
| #include <tbb/parallel_for_each.h> |
Copilot
AI
Jan 19, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The include order has been changed: "RoadNetwork.hpp" is now first, followed by local includes, then standard library includes, then third-party includes. While this is a common pattern (own header first), make sure this aligns with the project's style guide. If the project previously grouped includes differently, this change could affect compilation order or cause issues with implicit dependencies.
| #include <simdjson.h> | ||
| #include <tbb/parallel_for_each.h> | ||
|
|
||
| // Default traffic light cycle duration in seconds |
Copilot
AI
Jan 19, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The default traffic light cycle duration has been changed from 120 to 90 seconds. This is a significant behavioral change that affects traffic light initialization from CSV imports. Ensure this change is intentional and documented, as it will affect all traffic lights created during import operations. Consider whether this should be configurable or if existing configurations need to be migrated.
| // Default traffic light cycle duration in seconds | |
| // Default traffic light cycle duration in seconds for traffic lights created during | |
| // CSV import operations. This value was intentionally changed from 120s to 90s to | |
| // better match typical urban signal timing and simulation requirements. If existing | |
| // scenarios relied on the previous 120s default, they should be updated explicitly | |
| // in their configuration rather than depending on this hard-coded default. |
| /************************************************************* | ||
| * 2. Check for street names with same number of lanes | ||
| * ***********************************************************/ |
Copilot
AI
Jan 19, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The comment numbering is incorrect. Both the speed check (line 451) and the lane count check (line 461) are labeled as "2". The lane count check should be labeled as "3" since it's the third check, and the angle check should be labeled as "4".
| // Assign first and third keys of capacity map | ||
| auto it = capacities.begin(); | ||
| auto const& firstKey = it->first; | ||
| ++it; | ||
| ++it; | ||
| auto const& thirdKey = it->first; | ||
| tl.addStreetPriority(firstKey); | ||
| tl.addStreetPriority(thirdKey); |
Copilot
AI
Jan 19, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This code assumes the capacities map has at least 3 elements (accessing first, incrementing twice, then accessing third). However, the check at line 380 only ensures there are at least 3 incoming neighbours, but if the angle-based or other priority selection methods succeeded but resulted in a count other than 2, this fallback code could fail with undefined behavior if capacities has fewer than 3 elements. Consider adding a check that capacities.size() >= 3 before this logic.
| // Assign first and third keys of capacity map | |
| auto it = capacities.begin(); | |
| auto const& firstKey = it->first; | |
| ++it; | |
| ++it; | |
| auto const& thirdKey = it->first; | |
| tl.addStreetPriority(firstKey); | |
| tl.addStreetPriority(thirdKey); | |
| // Assign priorities based on capacity map, guarding against small maps | |
| if (capacities.size() >= 3) { | |
| // Original behavior: use first and third keys | |
| auto it = capacities.begin(); | |
| auto const& firstKey = it->first; | |
| ++it; | |
| ++it; | |
| auto const& thirdKey = it->first; | |
| tl.addStreetPriority(firstKey); | |
| tl.addStreetPriority(thirdKey); | |
| } else if (capacities.size() >= 2) { | |
| // Fallback: use first two keys | |
| auto it = capacities.begin(); | |
| auto const& firstKey = it->first; | |
| ++it; | |
| auto const& secondKey = it->first; | |
| tl.addStreetPriority(firstKey); | |
| tl.addStreetPriority(secondKey); | |
| } else if (!capacities.empty()) { | |
| // Last resort: only one key available | |
| tl.addStreetPriority(capacities.begin()->first); | |
| } |
| /************************************************************* | ||
| if (tl.streetPriorities().empty() && higherNLanes != lowerNLanes) { | ||
| /************************************************************* | ||
| * 2. Check for street names with same number of lanes |
Copilot
AI
Jan 19, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The comment says "Check for street names with same number of lanes" but the logic is checking for streets with the highest number of lanes, not streets with the same count. The comment should be updated to reflect the actual behavior, e.g., "Check for streets with highest number of lanes".
| * 2. Check for street names with same number of lanes | |
| * 2. Check for streets with highest number of lanes |
| /// @brief Initialize the traffic lights with random parameters | ||
| /// @param minGreenTime The minimum green time for the traffic lights cycles (default is 30) | ||
| /// @param mainRoadPercentage The percentage of main roads for the traffic lights cycles (default is 0.6) | ||
| /// @details Traffic Lights with no parameters set are initialized with random parameters. | ||
| /// Street priorities are assigned considering the number of lanes and the speed limit. | ||
| /// Traffic Lights with an input degree lower than 3 are converted to standard intersections. | ||
| void initTrafficLights(Delay const minGreenTime = 30); | ||
| void autoInitTrafficLights(double const mainRoadPercentage = 0.6); |
Copilot
AI
Jan 19, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The docstring says "Initialize the traffic lights with random parameters" but the function now uses a deterministic algorithm based on street characteristics (names, speeds, lanes, angles) with a fallback to capacity-based selection. The word "random" is misleading. Consider updating the description to something like "Automatically initialize traffic lights based on street characteristics".
| for (auto const& streetId : priorityRoads) { | ||
| auto const& pStreet{this->edge(streetId)}; | ||
| pStreet->setPriority(); | ||
| spdlog::debug("Setting priority to street {}", pStreet->id()); | ||
| } |
Copilot
AI
Jan 19, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Calling setPriority() on edges from within a parallel_for_each can cause a data race if multiple threads attempt to modify the same edge. Although each node processes its own incoming edges, the same edge could theoretically be an incoming edge to multiple nodes being processed in parallel. Consider using a mutex to protect edge modifications or collect all edges to modify and process them sequentially after the parallel phase.
| if (tl.streetPriorities().empty() || tl.streetPriorities().size() != 2) { | ||
| spdlog::warn("Failed to auto-init Traffic Light {} - going random", | ||
| pNode->id()); | ||
| // Assign first and third keys of capacity map | ||
| auto it = capacities.begin(); | ||
| auto const& firstKey = it->first; | ||
| ++it; | ||
| ++it; | ||
| auto const& thirdKey = it->first; | ||
| tl.addStreetPriority(firstKey); | ||
| tl.addStreetPriority(thirdKey); | ||
| } |
Copilot
AI
Jan 19, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The condition now checks if the size is not exactly 2, which is a new requirement. However, if the number of street priorities is already greater than 2 (e.g., 3 or 4), this will trigger the "going random" logic and add two more priorities, leading to duplicate priorities or an incorrect total count. Consider only adding the fallback priorities if the set is empty, or first clearing existing priorities before adding new ones.
No description provided.