Skip to content
Draft
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
4 changes: 4 additions & 0 deletions src/dsf/binding.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,10 @@ PYBIND11_MODULE(dsf_cpp, m) {
&dsf::FirstOrderDynamics::setWeightFunction,
pybind11::arg("weightFunction"),
pybind11::arg("weightThreshold") = std::nullopt)
.def("killStagnantAgents",
&dsf::FirstOrderDynamics::killStagnantAgents,
pybind11::arg("timeToleranceFactor") = 3.,
dsf::g_docstrings.at("dsf::RoadDynamics::killStagnantAgents").c_str())
.def(
"setDestinationNodes",
[](dsf::FirstOrderDynamics& self,
Expand Down
98 changes: 53 additions & 45 deletions src/dsf/headers/RoadDynamics.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@
double m_maxTravelDistance;
Time m_maxTravelTime;
double m_weightTreshold;
std::optional<double> m_timeToleranceFactor;
std::optional<delay_t> m_dataUpdatePeriod;
bool m_bCacheEnabled;
bool m_forcePriorities;
Expand Down Expand Up @@ -125,9 +126,16 @@
/// @details The passage probability is the probability of passing through a node
/// It is useful in the case of random agents
void setPassageProbability(double passageProbability);

/// @brief Set the time tolerance factor for killing stagnant agents.
/// An agent will be considered stagnant if it has not moved for timeToleranceFactor * std::ceil(street_length / street_maxSpeed) time units.
/// @param timeToleranceFactor The time tolerance factor
/// @throw std::invalid_argument If the time tolerance factor is not positive
void killStagnantAgents(double timeToleranceFactor = 3.);

Check notice

Code scanning / Cppcheck (reported by Codacy)

MISRA 17.8 rule Note

MISRA 17.8 rule

Check notice

Code scanning / Cppcheck (reported by Codacy)

MISRA 13.4 rule Note

MISRA 13.4 rule
/// @brief Set the weight function
/// @param pathWeight The dsf::PathWeight function to use for the pathfinding
/// @param weightThreshold The weight threshold for updating the paths (default is std::nullopt)
void setWeightFunction(PathWeight const pathWeight,
std::optional<double> weigthThreshold = std::nullopt);
std::optional<double> weightThreshold = std::nullopt);
/// @brief Set the force priorities flag
/// @param forcePriorities The flag
/// @details If true, if an agent cannot move to the next street, the whole node is skipped
Expand Down Expand Up @@ -393,6 +401,7 @@
m_errorProbability{std::nullopt},
m_passageProbability{std::nullopt},
m_maxTravelDistance{std::numeric_limits<double>::max()},
m_timeToleranceFactor{std::nullopt},
m_maxTravelTime{std::numeric_limits<Time>::max()},
m_bCacheEnabled{useCache},
m_forcePriorities{false} {
Expand Down Expand Up @@ -670,34 +679,31 @@
pAgentTemp->freeTime());
continue;
}
bool overtimed{false};
{

if (m_timeToleranceFactor.has_value()) {

Check notice

Code scanning / Cppcheck (reported by Codacy)

MISRA 14.4 rule Note

MISRA 14.4 rule
auto const timeDiff{this->time() - pAgentTemp->freeTime()};
auto const timeTolerance{3 *
auto const timeTolerance{m_timeToleranceFactor.value() *
std::ceil(pStreet->length() / pStreet->maxSpeed())};
if (timeDiff > timeTolerance) {
overtimed = true;
spdlog::warn(
"Time {} - {} currently on {} ({} turn - Traffic Light? {}), "
"has been still for more than {} seconds ({} seconds)",
"has been still for more than {} seconds ({} seconds). Killing it.",
this->time(),
*pAgentTemp,
*pStreet,
directionToString.at(pStreet->laneMapping().at(queueIndex)),
this->graph().node(pStreet->target())->isTrafficLight(),
timeTolerance,
timeDiff);
// Kill the agent
auto pAgent{pStreet->dequeue(queueIndex)};
continue;
}
}
pAgentTemp->setSpeed(0.);
const auto& destinationNode{this->graph().node(pStreet->target())};
if (destinationNode->isFull()) {
if (overtimed) {
spdlog::warn("Skipping due to full destination node {}", *destinationNode);
} else {
spdlog::debug("Skipping due to space at destination node {}",
*destinationNode);
}
spdlog::debug("Skipping due to full destination node {}", *destinationNode);
continue;
}
if (destinationNode->isTrafficLight()) {
Expand Down Expand Up @@ -807,17 +813,9 @@
}
if (!bCanPass) {
spdlog::debug(
"Skipping agent emission from street {} -> {} due to right of way.",
"Skipping agent emission from street {} -> {} due to right of way",
pStreet->source(),
pStreet->target());
if (overtimed) {
spdlog::warn(
"Skipping agent emission from street {} -> {} due to right of way "
"and overtimed agent {}",
pStreet->source(),
pStreet->target(),
pAgentTemp->id());
}
continue;
}
}
Expand All @@ -832,14 +830,6 @@
"probability",
pStreet->source(),
pStreet->target());
if (overtimed) {
spdlog::warn(
"Skipping agent emission from street {} -> {} due to passage "
"probability and overtimed agent {}",
pStreet->source(),
pStreet->target(),
pAgentTemp->id());
}
continue;
}
}
Expand Down Expand Up @@ -879,21 +869,12 @@
}
auto const& nextStreet{this->graph().edge(pAgentTemp->nextStreetId().value())};
if (nextStreet->isFull()) {
if (overtimed) {
spdlog::warn(
"Skipping agent emission from street {} -> {} due to full "
"next street: {}",
pStreet->source(),
pStreet->target(),
*nextStreet);
} else {
spdlog::debug(
"Skipping agent emission from street {} -> {} due to full "
"next street: {}",
pStreet->source(),
pStreet->target(),
*nextStreet);
}
spdlog::debug(
"Skipping agent emission from street {} -> {} due to full "
"next street: {}",
pStreet->source(),
pStreet->target(),
*nextStreet);
continue;
}
auto pAgent{pStreet->dequeue(queueIndex)};
Expand Down Expand Up @@ -1056,6 +1037,15 @@
}
m_passageProbability = passageProbability;
}
template <typename delay_t>
requires(is_numeric_v<delay_t>)
void RoadDynamics<delay_t>::killStagnantAgents(double timeToleranceFactor) {
if (timeToleranceFactor <= 0.) {
throw std::invalid_argument(std::format(
"The time tolerance factor ({}) must be positive", timeToleranceFactor));
}
m_timeToleranceFactor = timeToleranceFactor;
}
template <typename delay_t>
requires(is_numeric_v<delay_t>)
void RoadDynamics<delay_t>::setWeightFunction(PathWeight const pathWeight,
Expand Down Expand Up @@ -1214,6 +1204,15 @@
requires(is_numeric_v<delay_t>)
void RoadDynamics<delay_t>::addAgentsUniformly(Size nAgents,
std::optional<Id> optItineraryId) {
if (m_timeToleranceFactor.has_value() && !m_agents.empty()) {
auto const nStagnantAgents{m_agents.size()};
spdlog::warn(
"Removing {} stagnant agents that were not inserted since the previous call to "
"addAgentsUniformly().",
nStagnantAgents);
m_agents.clear();
m_nAgents -= nStagnantAgents;
}
if (optItineraryId.has_value() && !this->itineraries().contains(*optItineraryId)) {
throw std::invalid_argument(
std::format("No itineraries available. Cannot add agents with itinerary id {}",
Expand Down Expand Up @@ -1269,6 +1268,15 @@
void RoadDynamics<delay_t>::addAgentsRandomly(Size nAgents,
const TContainer& src_weights,
const TContainer& dst_weights) {
if (m_timeToleranceFactor.has_value() && !m_agents.empty()) {
auto const nStagnantAgents{m_agents.size()};
spdlog::warn(
"Removing {} stagnant agents that were not inserted since the previous call to "
"addAgentsRandomly().",
nStagnantAgents);
m_agents.clear();
m_nAgents -= nStagnantAgents;
}
auto const& nSources{src_weights.size()};
auto const& nDestinations{dst_weights.size()};
spdlog::debug("Init addAgentsRandomly for {} agents from {} nodes to {} nodes.",
Expand Down
Loading