1+ import numpy as np
2+ import random
3+ import matplotlib .pyplot as plt
4+
5+ class Grid ():
6+
7+ # Set in constructor
8+ grid_size = None
9+ grid = None
10+ obstacle_paths = []
11+
12+ # Problem definition
13+ time_limit = 100
14+ num_obstacles = 2
15+
16+ def __init__ (self , grid_size : np .ndarray [int , int ]):
17+ self .grid_size = grid_size
18+ self .grid = np .zeros ((grid_size [0 ], grid_size [1 ], self .time_limit ))
19+
20+ for i in range (1 , self .num_obstacles + 1 ):
21+ self .obstacle_paths .append (self .generate_dynamic_obstacle (i ))
22+
23+ def generate_dynamic_obstacle (self , obs_idx : int ) -> list [np .ndarray [int , int ]]:
24+ # TODO: dont spawn on another obstacle
25+ initial_position = (np .random .randint (0 , self .grid_size [0 ]), np .random .randint (0 , self .grid_size [1 ]))
26+ positions = [initial_position ]
27+ print ("Initial position: " , initial_position )
28+
29+ diffs = [np .array ([0 , 1 ]), np .array ([0 , - 1 ]), np .array ([1 , 0 ]), np .array ([- 1 , 0 ]), np .array ([0 , 0 ])]
30+
31+ for t in range (1 , self .time_limit - 1 ):
32+ random .shuffle (diffs )
33+ for diff in diffs :
34+ new_position = positions [- 1 ] + diff
35+
36+ # Check if new position is in grid
37+ if new_position [0 ] < 0 or new_position [0 ] >= self .grid_size [0 ] or new_position [1 ] < 0 or new_position [1 ] >= self .grid_size [1 ]:
38+ continue
39+
40+ # Check if new position occupied by another obstacle
41+ if self .grid [new_position [0 ], new_position [1 ], t ] == 0 :
42+ positions .append (new_position )
43+ self .grid [new_position [0 ], new_position [1 ], t ] = obs_idx
44+ break
45+
46+ # Impossible situation for obstacle - stay in place
47+ print ("Impossible situation for obstacle!" )
48+ positions .append (positions [- 1 ])
49+
50+ return positions
51+
52+ show_animation = True
53+
54+ def main ():
55+ grid = Grid (np .array ([10 , 10 ]))
56+
57+ plt .figure ()
58+
59+ for t in range (0 , grid .time_limit ):
60+ plt .clf ()
61+
62+ if show_animation : # pragma: no cover
63+ # TODO: iter is clunky. Should use np array
64+ ax = plt .axes ()
65+ ax .set_xlim (0 , grid .grid_size [0 ])
66+ ax .set_ylim (0 , grid .grid_size [1 ])
67+
68+ for (obs_idx , obs_path ) in enumerate (grid .obstacle_paths ):
69+ obs_pos = obs_path [t ]
70+ # plt.plot(obs_pos[0], obs_pos[1], "xr")
71+ circle = plt .Circle ((obs_pos [0 ], obs_pos [1 ]), 0.2 )
72+ ax .add_patch (circle )
73+ plt .grid (True )
74+ plt .pause (0.3 )
75+
76+ # TODO: better animation closing
77+ # fig, ax = plt.subplots()
78+ # line, = ax.plot([], [])
79+ # ax.set_xlim(0, 10)
80+ # ax.set_ylim(-1, 1)
81+
82+ # def init():
83+ # line.set_data([], [])
84+ # return line,
85+
86+ # def animate(i):
87+ # x = [0, 10]
88+ # y = [0, i % 2 * 2 - 1]
89+ # line.set_data(x, y)
90+ # return line,
91+
92+ # ani = animation.FuncAnimation(fig, animate, init_func=init, frames=100, interval=20, blit=True)
93+
94+ # def close_event(evt):
95+ # ani.event_source.stop()
96+ # plt.close(fig)
97+
98+ if __name__ == '__main__' :
99+ main ()
0 commit comments