when-to-switch
177 строк · 6.1 Кб
1// cppimport
2#include <pybind11/pybind11.h>
3#include <pybind11/stl.h>
4#include <pybind11/stl_bind.h>
5#include <vector>
6#include <queue>
7#include <cmath>
8#include <set>
9#include <map>
10#include <list>
11#define INF 1000000000
12namespace py = pybind11;
13
14struct Node {
15Node(int _i = INF, int _j = INF, int _g = 0, int _h = 0) : i(_i), j(_j), g(_g), h(_h), f(_g+_h){}
16int i;
17int j;
18int g;
19int h;
20int f;
21bool operator<(const Node& other) const
22{
23return this->f < other.f or
24(this->f == other.f and (this->g < other.g or
25(this->g == other.g and (this->i < other.i or
26(this->i == other.i and this->j < other.j)))));
27}
28bool operator>(const Node& other) const
29{
30return this->f > other.f or
31(this->f == other.f and (this->g > other.g or
32(this->g == other.g and (this->i > other.i or
33(this->i == other.i and this->j > other.j)))));
34}
35bool operator==(const Node& other) const
36{
37return this->i == other.i and this->j == other.j;
38}
39bool operator==(const std::pair<int, int> &other) const
40{
41return this->i == other.first and this->j == other.second;
42}
43};
44
45class planner {
46std::set<std::pair<int,int>> obstacles;
47std::set<std::pair<int,int>> other_agents;
48std::set<std::pair<int,int>> bad_actions;
49std::priority_queue<Node, std::vector<Node>, std::greater<Node>> OPEN;
50std::map<std::pair<int, int>, std::pair<int, int>> CLOSED;
51std::pair<int, int> start;
52std::pair<int, int> desired_position;
53std::pair<int, int> goal;
54Node best_node;
55int max_steps;
56inline int h(std::pair<int, int> n)
57{
58return std::abs(n.first - goal.first) + std::abs(n.second - goal.second);
59}
60std::vector<std::pair<int,int>> get_neighbors(std::pair<int, int> node)
61{
62std::vector<std::pair<int,int>> neighbors;
63std::vector<std::pair<int,int>> deltas = {{0,1},{1,0},{-1,0},{0,-1}};
64for(auto d:deltas)
65{
66std::pair<int,int> n(node.first + d.first, node.second + d.second);
67if(obstacles.count(n) == 0)
68neighbors.push_back(n);
69}
70return neighbors;
71}
72void compute_shortest_path()
73{
74Node current;
75int steps = 0;
76while(!OPEN.empty() and steps < max_steps and !(current == goal))
77{
78current = OPEN.top();
79OPEN.pop();
80if(current.h < best_node.h)
81best_node = current;
82steps++;
83for(auto n: get_neighbors({current.i, current.j})) {
84if (CLOSED.find(n) == CLOSED.end() and other_agents.find(n) == other_agents.end()) {
85OPEN.push(Node(n.first, n.second, current.g + 1, h(n)));
86CLOSED[n] = {current.i, current.j};
87}
88}
89}
90}
91void reset()
92{
93CLOSED.clear();
94OPEN = std::priority_queue<Node, std::vector<Node>, std::greater<Node>>();
95Node s = Node(start.first, start.second, 0, h(start));
96OPEN.push(s);
97best_node = s;
98}
99public:
100planner(int steps=10000) {max_steps = steps;}
101void update_obstacles(const std::list<std::pair<int, int>>& _obstacles,
102const std::list<std::pair<int, int>>& _other_agents,
103std::pair<int, int> cur_pos)
104{
105for(auto o:_obstacles)
106obstacles.insert({cur_pos.first + o.first, cur_pos.second + o.second});
107other_agents.clear();
108for(auto o:_other_agents)
109other_agents.insert({cur_pos.first + o.first, cur_pos.second + o.second});
110}
111void update_path(std::pair<int, int> s, std::pair<int, int> g)
112{
113if(desired_position.first < INF and (desired_position.first != s.first or desired_position.second != s.second)) {
114bad_actions.insert(desired_position);
115if (start.first == s.first and start.second == s.second)
116for (auto bad_a: bad_actions)
117other_agents.insert(bad_a);
118}
119else
120bad_actions.clear();
121start = s;
122goal = g;
123reset();
124compute_shortest_path();
125}
126std::list<std::pair<int, int>> get_path(bool use_best_node = true)
127{
128std::list<std::pair<int, int>> path;
129std::pair<int, int> next_node(INF,INF);
130if(CLOSED.find(goal) != CLOSED.end())
131next_node = goal;
132else if(use_best_node)
133next_node = {best_node.i, best_node.j};
134if(next_node.first < INF and (next_node.first != start.first or next_node.second != start.second))
135{
136while (CLOSED[next_node] != start) {
137path.push_back(next_node);
138next_node = CLOSED[next_node];
139}
140path.push_back(next_node);
141path.push_back(start);
142path.reverse();
143}
144desired_position = next_node;
145return path;
146}
147std::pair<std::pair<int, int>, std::pair<int, int>> get_next_node(bool use_best_node = true)
148{
149std::pair<int, int> next_node(INF, INF);
150if(CLOSED.find(goal) != CLOSED.end())
151next_node = goal;
152else if(use_best_node)
153next_node = {best_node.i, best_node.j};
154if(next_node.first < INF and (next_node.first != start.first or next_node.second != start.second))
155while (CLOSED[next_node] != start)
156next_node = CLOSED[next_node];
157if(next_node == start)
158next_node = {INF, INF};
159desired_position = next_node;
160return {start, next_node};
161}
162};
163
164PYBIND11_MODULE(planner, m) {
165py::class_<planner>(m, "planner")
166.def(py::init<int>())
167.def("update_obstacles", &planner::update_obstacles)
168.def("update_path", &planner::update_path)
169.def("get_path", &planner::get_path)
170.def("get_next_node", &planner::get_next_node);
171}
172
173/*
174<%
175setup_pybind11(cfg)
176%>
177*/
178