Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/dsm/dsm.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

static constexpr uint8_t DSM_VERSION_MAJOR = 2;
static constexpr uint8_t DSM_VERSION_MINOR = 6;
static constexpr uint8_t DSM_VERSION_PATCH = 2;
static constexpr uint8_t DSM_VERSION_PATCH = 3;

static auto const DSM_VERSION =
std::format("{}.{}.{}", DSM_VERSION_MAJOR, DSM_VERSION_MINOR, DSM_VERSION_PATCH);
Expand Down
2 changes: 1 addition & 1 deletion src/dsm/headers/RoadDynamics.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -1556,7 +1556,7 @@ namespace dsm {
continue;
}
auto& spire = dynamic_cast<SpireStreet&>(*pStreet);
file << separator << spire.code();
file << separator << streetId;
}
file << std::endl;
}
Expand Down
3 changes: 3 additions & 0 deletions src/dsm/headers/RoadNetwork.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,9 @@ namespace dsm {
/// 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();
/// @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();

/// @brief Import the graph's adjacency matrix from a file.
/// If the file is not of a supported format, it will read the file as a matrix with the first two elements being
Expand Down
71 changes: 71 additions & 0 deletions src/dsm/sources/RoadNetwork.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,77 @@
});
}
}
void RoadNetwork::autoMapStreetLanes() {
std::for_each(m_nodes.cbegin(), m_nodes.cend(), [this](auto const& pair) {
auto const& inNeighbours{m_adjacencyMatrix.getCol(pair.first)};
auto const& outNeighbours{m_adjacencyMatrix.getRow(pair.first)};
std::for_each(
inNeighbours.cbegin(),
inNeighbours.cend(),
[this, &pair, &outNeighbours](auto const& inNodeId) {

Check notice

Code scanning / Cppcheck (reported by Codacy)

MISRA 12.3 rule Note

MISRA 12.3 rule
auto const& pInStreet{m_edges.at(inNodeId * m_nodes.size() + pair.first)};
// auto const& laneMapping{pInStreet->laneMapping()};
std::multiset<Direction> allowedTurns;
std::for_each(
outNeighbours.cbegin(),
outNeighbours.cend(),
[this, &pair, &pInStreet, &allowedTurns](auto const& outNodeId) {

Check notice

Code scanning / Cppcheck (reported by Codacy)

MISRA 12.3 rule Note

MISRA 12.3 rule
auto const& pOutStreet{

Check warning on line 257 in src/dsm/sources/RoadNetwork.cpp

View check run for this annotation

Codecov / codecov/patch

src/dsm/sources/RoadNetwork.cpp#L257

Added line #L257 was not covered by tests
m_edges.at(pair.first * m_nodes.size() + outNodeId)};
auto const deltaAngle{pOutStreet->deltaAngle(pInStreet->angle())};
// Logger::debug(std::format("Angle in {} - angle out {}", pInStreet->angle(), pOutStreet->angle()));
// Logger::debug(std::format("Delta: {}", deltaAngle));
if (std::abs(deltaAngle) < 5 * std::numbers::pi / 6) {
if (deltaAngle < -std::numbers::pi / 6.) {
Logger::debug(
std::format("Street {} can turn RIGHT", pInStreet->id()));
allowedTurns.emplace(Direction::RIGHT);

Check notice

Code scanning / Cppcheck (reported by Codacy)

MISRA 17.7 rule Note

MISRA 17.7 rule
} else if (deltaAngle > std::numbers::pi / 6.) {
Logger::debug(
std::format("Street {} can turn LEFT", pInStreet->id()));
allowedTurns.emplace(Direction::LEFT);

Check notice

Code scanning / Cppcheck (reported by Codacy)

MISRA 17.7 rule Note

MISRA 17.7 rule
} else {
Logger::debug(
std::format("Street {} can go STRAIGHT", pInStreet->id()));
allowedTurns.emplace(Direction::STRAIGHT);

Check warning on line 274 in src/dsm/sources/RoadNetwork.cpp

View check run for this annotation

Codecov / codecov/patch

src/dsm/sources/RoadNetwork.cpp#L272-L274

Added lines #L272 - L274 were not covered by tests

Check notice

Code scanning / Cppcheck (reported by Codacy)

MISRA 17.7 rule Note

MISRA 17.7 rule
}
}
});
auto const nLanes{pInStreet->nLanes()};
while (allowedTurns.size() < static_cast<size_t>(nLanes)) {
if (allowedTurns.contains(Direction::STRAIGHT)) {

Check notice

Code scanning / Cppcheck (reported by Codacy)

MISRA 14.4 rule Note

MISRA 14.4 rule
allowedTurns.emplace(Direction::STRAIGHT);

Check warning on line 281 in src/dsm/sources/RoadNetwork.cpp

View check run for this annotation

Codecov / codecov/patch

src/dsm/sources/RoadNetwork.cpp#L281

Added line #L281 was not covered by tests

Check notice

Code scanning / Cppcheck (reported by Codacy)

MISRA 17.7 rule Note

MISRA 17.7 rule
} else if (allowedTurns.contains(Direction::RIGHT)) {

Check notice

Code scanning / Cppcheck (reported by Codacy)

MISRA 14.4 rule Note

MISRA 14.4 rule
allowedTurns.emplace(Direction::RIGHT);

Check notice

Code scanning / Cppcheck (reported by Codacy)

MISRA 17.7 rule Note

MISRA 17.7 rule
} else if (allowedTurns.contains(Direction::LEFT)) {

Check notice

Code scanning / Cppcheck (reported by Codacy)

MISRA 14.4 rule Note

MISRA 14.4 rule
allowedTurns.emplace(Direction::LEFT);

Check warning on line 285 in src/dsm/sources/RoadNetwork.cpp

View check run for this annotation

Codecov / codecov/patch

src/dsm/sources/RoadNetwork.cpp#L285

Added line #L285 was not covered by tests

Check notice

Code scanning / Cppcheck (reported by Codacy)

MISRA 17.7 rule Note

MISRA 17.7 rule
} else {
allowedTurns.emplace(Direction::ANY);

Check notice

Code scanning / Cppcheck (reported by Codacy)

MISRA 17.7 rule Note

MISRA 17.7 rule
}
}
switch (nLanes) {
case 1:
// Leaving Direction::ANY for one lane streets is the less painful option
break;
case 2:
if (allowedTurns.contains(Direction::STRAIGHT) &&
allowedTurns.contains(Direction::RIGHT) &&
allowedTurns.contains(Direction::LEFT)) {
break;

Check warning on line 298 in src/dsm/sources/RoadNetwork.cpp

View check run for this annotation

Codecov / codecov/patch

src/dsm/sources/RoadNetwork.cpp#L298

Added line #L298 was not covered by tests
}
[[fallthrough]];
default:
assert(allowedTurns.size() == static_cast<size_t>(nLanes));
std::vector<Direction> newMapping(nLanes);
auto it{allowedTurns.cbegin()};
for (size_t i{0}; i < allowedTurns.size(); ++i, ++it) {

Check notice

Code scanning / Cppcheck (reported by Codacy)

MISRA 12.3 rule Note

MISRA 12.3 rule
newMapping[i] = *it;
}
pInStreet->setLaneMapping(newMapping);
}

Check notice

Code scanning / Cppcheck (reported by Codacy)

MISRA 16.3 rule Note

MISRA 16.3 rule
});
});
}

void RoadNetwork::buildAdj() {
// find max values in streets node pairs
Expand Down
7 changes: 7 additions & 0 deletions src/dsm/sources/Street.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,13 @@
void Street::setLaneMapping(std::vector<Direction> const& laneMapping) {
assert(laneMapping.size() == static_cast<size_t>(m_nLanes));
m_laneMapping = laneMapping;
std::string strLaneMapping;
std::for_each(
laneMapping.cbegin(), laneMapping.cend(), [&strLaneMapping](auto const item) {

Check notice

Code scanning / Cppcheck (reported by Codacy)

MISRA 13.1 rule Note

MISRA 13.1 rule
strLaneMapping += std::format("{} - ", static_cast<int>(item));
});
Logger::debug(
std::format("New lane mapping for street {} is: {}", m_id, strLaneMapping));
}
void Street::setQueue(dsm::queue<std::unique_ptr<Agent>> queue, size_t index) {
assert(index < m_exitQueues.size());
Expand Down
44 changes: 43 additions & 1 deletion test/Test_graph.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,49 @@
CHECK(graph.adjacencyMatrix().contains(0, 2));
CHECK_FALSE(graph.adjacencyMatrix().contains(1, 3));
}

SUBCASE("autoMapStreetLanes") {
GIVEN("A Graph object") {
RoadNetwork graph{};
graph.addNode(0, std::make_pair(0., 0.));
graph.addNode(1, std::make_pair(0., -1.));
graph.addNode(2, std::make_pair(-1., 0.));
graph.addNode(3, std::make_pair(1., 1.));
graph.addEdge<Street>(1, std::make_pair(0, 1), 1., 1., 3);

Check notice

Code scanning / Cppcheck (reported by Codacy)

MISRA 12.3 rule Note test

MISRA 12.3 rule
graph.addEdge<Street>(4, std::make_pair(1, 0), 1., 1., 3);

Check notice

Code scanning / Cppcheck (reported by Codacy)

MISRA 12.3 rule Note test

MISRA 12.3 rule
graph.addEdge<Street>(2, std::make_pair(0, 2), 1.);

Check notice

Code scanning / Cppcheck (reported by Codacy)

MISRA 12.3 rule Note test

MISRA 12.3 rule
graph.addEdge<Street>(8, std::make_pair(2, 0), 1.);

Check notice

Code scanning / Cppcheck (reported by Codacy)

MISRA 12.3 rule Note test

MISRA 12.3 rule
graph.addEdge<Street>(3, std::make_pair(0, 3), 1., 1., 2);

Check notice

Code scanning / Cppcheck (reported by Codacy)

MISRA 12.3 rule Note test

MISRA 12.3 rule
graph.addEdge<Street>(12, std::make_pair(3, 0), 1., 1., 2);

Check notice

Code scanning / Cppcheck (reported by Codacy)

MISRA 12.3 rule Note test

MISRA 12.3 rule
graph.buildAdj();
CHECK_EQ(graph.nEdges(), 6);
CHECK_EQ(graph.nNodes(), 4);
WHEN("We automatically map street lanes") {
// dsm::Logger::setLogLevel(dsm::log_level_t::DEBUG);
graph.autoMapStreetLanes();
// dsm::Logger::setLogLevel(dsm::log_level_t::INFO);
THEN("The lanes are correctly mapped") {
CHECK_EQ(graph.edge(1)->laneMapping().size(), 3);
CHECK_EQ(graph.edge(1)->laneMapping()[0], dsm::Direction::ANY);
CHECK_EQ(graph.edge(1)->laneMapping()[1], dsm::Direction::ANY);
CHECK_EQ(graph.edge(1)->laneMapping()[2], dsm::Direction::ANY);
CHECK_EQ(graph.edge(4)->laneMapping().size(), 3);
CHECK_EQ(graph.edge(4)->laneMapping()[0], dsm::Direction::RIGHT);
CHECK_EQ(graph.edge(4)->laneMapping()[1], dsm::Direction::RIGHT);
CHECK_EQ(graph.edge(4)->laneMapping()[2], dsm::Direction::LEFT);
CHECK_EQ(graph.edge(2)->laneMapping().size(), 1);
CHECK_EQ(graph.edge(2)->laneMapping()[0], dsm::Direction::ANY);
CHECK_EQ(graph.edge(8)->laneMapping().size(), 1);
CHECK_EQ(graph.edge(8)->laneMapping()[0], dsm::Direction::ANY);
CHECK_EQ(graph.edge(3)->laneMapping().size(), 2);
CHECK_EQ(graph.edge(3)->laneMapping()[0], dsm::Direction::ANY);
CHECK_EQ(graph.edge(3)->laneMapping()[1], dsm::Direction::ANY);
CHECK_EQ(graph.edge(12)->laneMapping().size(), 2);
CHECK_EQ(graph.edge(12)->laneMapping()[0], dsm::Direction::RIGHT);
CHECK_EQ(graph.edge(12)->laneMapping()[1], dsm::Direction::LEFT);
}
}
}
}
SUBCASE("importMatrix - dsm") {
// This tests the importMatrix function over .dsm files
// GIVEN: a graph
Expand Down
Loading