tess 1.0.0
Performance-first tile and path simulation substrate
Loading...
Searching...
No Matches
path_agent_replan_selection.h
1#pragma once
2
3#include <tess/core/shape.h>
4#include <tess/sim/path_agent.h>
5#include <tess/sim/path_agent_tick.h>
6
7#include <span>
8#include <utility>
9
10namespace tess::experimental {
11
46template <typename CostIncreasedFn>
47[[nodiscard]] auto request_replans_for_route_crossings(
48 std::span<const PathAgentState> agents, const PathAgentRoutes& routes,
49 CostIncreasedFn&& cost_increased, PathAgentReplanQueue& queue)
50 -> std::size_t {
51 std::size_t newly_queued = 0;
52 for (std::size_t i = 0; i < agents.size(); ++i) {
53 const auto& agent = agents[i];
54 if (!agent.has_goal || agent.phase == PathAgentPhase::Unreachable ||
55 i >= routes.routes.size()) {
56 continue;
57 }
58 // An agent already waiting in the queue cannot be queued again --
59 // `request` refuses it -- so scanning its route can only reach a
60 // conclusion that is then discarded. Under a bounded planning
61 // budget the backlog persists across repricings, so this is the
62 // difference between rescanning the whole backlog every time and
63 // scanning only what is new.
64 if (queue.contains(i)) {
65 continue;
66 }
67 const auto& route = routes.routes[i];
68 if (!detail::has_next_step(agent.path_index, route.size())) {
69 continue;
70 }
71 for (auto step = agent.path_index + 1; step < route.size(); ++step) {
72 if (cost_increased(route[step])) {
73 if (queue.request(i, agent)) {
74 ++newly_queued;
75 }
76 break;
77 }
78 }
79 }
80 return newly_queued;
81}
82
83} // namespace tess::experimental