Skip to content

Commit 26c2f65

Browse files
authored
Rework m_nextStreetId function to better handle forbidden turns (#293)
* Rework `m_nextStreetId` function to better handle forbidden turns * Small optimization * Review fix * Try to fix apple * Missing override keyword * Try #2
1 parent f29fda3 commit 26c2f65

File tree

4 files changed

+50
-25
lines changed

4 files changed

+50
-25
lines changed

src/dsm/dsm.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
static constexpr uint8_t DSM_VERSION_MAJOR = 2;
88
static constexpr uint8_t DSM_VERSION_MINOR = 6;
9-
static constexpr uint8_t DSM_VERSION_PATCH = 13;
9+
static constexpr uint8_t DSM_VERSION_PATCH = 14;
1010

1111
static auto const DSM_VERSION =
1212
std::format("{}.{}.{}", DSM_VERSION_MAJOR, DSM_VERSION_MINOR, DSM_VERSION_PATCH);

src/dsm/headers/RoadDynamics.hpp

Lines changed: 45 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -489,43 +489,66 @@ namespace dsm {
489489
Id nodeId,
490490
std::optional<Id> streetId) {
491491
auto possibleMoves = this->graph().adjacencyMatrix().getRow(nodeId);
492+
493+
std::set<Id> forbiddenStreetIds;
494+
if (streetId.has_value()) {
495+
auto const& pStreet{this->graph().edge(*streetId)};
496+
forbiddenStreetIds = pStreet->forbiddenTurns();
497+
// Avoid U-TURNS, if possible
498+
if (!(this->graph().node(nodeId)->isRoundabout()) &&
499+
(possibleMoves.size() > forbiddenStreetIds.size() + 1)) {
500+
auto const& pOppositeStreet{this->graph().oppositeStreet(*streetId)};
501+
if (pOppositeStreet) {
502+
forbiddenStreetIds.insert(pOppositeStreet->get()->id());
503+
}
504+
}
505+
}
506+
// Exclude FORBIDDEN turns
507+
for (auto const& forbiddenStreetId : forbiddenStreetIds) {
508+
auto const& pForbiddenStreet{this->graph().edge(forbiddenStreetId)};
509+
// if possible moves contains the forbidden street, remove it
510+
auto it = std::find(
511+
possibleMoves.begin(), possibleMoves.end(), pForbiddenStreet->target());
512+
if (it != possibleMoves.end()) {
513+
possibleMoves.erase(it);
514+
}
515+
}
516+
492517
if (!pAgent->isRandom()) {
518+
std::vector<Id> newPossibleMoves;
493519
std::uniform_real_distribution<double> uniformDist{0., 1.};
494520
if (!(this->itineraries().empty())) {
495521
if (!(m_errorProbability.has_value() &&
496522
uniformDist(this->m_generator) < m_errorProbability)) {
497523
const auto& it = this->itineraries().at(pAgent->itineraryId());
498524
if (it->destination() != nodeId) {
499-
possibleMoves = it->path()->getRow(nodeId);
525+
newPossibleMoves = it->path()->getRow(nodeId);
500526
}
501527
}
528+
for (auto const& forbiddenStreetId : forbiddenStreetIds) {
529+
auto const& pForbiddenStreet{this->graph().edge(forbiddenStreetId)};
530+
// if possible moves contains the forbidden street, remove it
531+
auto it = std::find(newPossibleMoves.begin(),
532+
newPossibleMoves.end(),
533+
pForbiddenStreet->target());
534+
if (it != newPossibleMoves.end()) {
535+
newPossibleMoves.erase(it);
536+
}
537+
}
538+
if (!newPossibleMoves.empty()) {
539+
possibleMoves = newPossibleMoves;
540+
}
502541
}
503542
}
543+
504544
assert(!possibleMoves.empty());
505-
if (streetId.has_value()) {
506-
auto const& pStreet{this->graph().edge(*streetId)};
507-
for (auto const& foirbiddenStreetId : pStreet->forbiddenTurns()) {
508-
auto const& pForbiddenStreet{this->graph().edge(foirbiddenStreetId)};
509-
// if possible moves contains the forbidden street, remove it
510-
auto it = std::find(
511-
possibleMoves.begin(), possibleMoves.end(), pForbiddenStreet->target());
512-
if (it != possibleMoves.end()) {
513-
possibleMoves.erase(it);
514-
}
515-
}
545+
546+
if (possibleMoves.size() == 1) {
547+
return nodeId * this->graph().nNodes() + possibleMoves[0];
516548
}
517549
std::uniform_int_distribution<Size> moveDist{
518550
0, static_cast<Size>(possibleMoves.size() - 1)};
519-
// while loop to avoid U turns in non-roundabout junctions
520-
Id nextStreetId;
521-
do {
522-
nextStreetId =
523-
nodeId * this->graph().nNodes() + possibleMoves[moveDist(this->m_generator)];
524-
} while (!this->graph().node(nodeId)->isRoundabout() && streetId.has_value() &&
525-
(this->graph().edge(nextStreetId)->target() ==
526-
this->graph().edge(streetId.value())->source()) &&
527-
(possibleMoves.size() > 1));
528-
return nextStreetId;
551+
return nodeId * this->graph().nNodes() + possibleMoves[moveDist(this->m_generator)];
529552
}
530553

531554
template <typename delay_t>

src/dsm/headers/Street.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ namespace dsm {
118118
/// @param normalizeOnNLanes If true, the number of agents is normalized by the number of lanes
119119
/// @return double The number of agents on all queues for a given direction
120120
double nExitingAgents(Direction direction = Direction::ANY,
121-
bool normalizeOnNLanes = false) const;
121+
bool normalizeOnNLanes = false) const final;
122122

123123
inline std::vector<Direction> const& laneMapping() const { return m_laneMapping; }
124124

test/Test_dynamics.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -926,9 +926,11 @@ TEST_CASE("FirstOrderDynamics") {
926926
dynamics.evolve(false);
927927
dynamics.evolve(false);
928928
#ifndef __APPLE__
929+
dynamics.evolve(false);
930+
dynamics.evolve(false);
929931
THEN("The agent has travelled the correct distance") {
930932
auto const& pAgent{dynamics.graph().edge(5)->queue(0).front()};
931-
CHECK_EQ(dynamics.time() - pAgent->spawnTime(), 7);
933+
CHECK_EQ(dynamics.time() - pAgent->spawnTime(), 9);
932934
CHECK_EQ(pAgent->freeTime() + 1, dynamics.time());
933935
CHECK_EQ(pAgent->streetId().value(), 5);
934936
CHECK_EQ(pAgent->speed(), 0.);

0 commit comments

Comments
 (0)