@@ -13,43 +13,93 @@ class Grid():
1313 time_limit = 100
1414 num_obstacles = 2
1515
16+ # Logging control
17+ verbose = False
18+
1619 def __init__ (self , grid_size : np .ndarray [int , int ]):
1720 self .grid_size = grid_size
1821 self .grid = np .zeros ((grid_size [0 ], grid_size [1 ], self .time_limit ))
1922
20- for i in range (1 , self .num_obstacles + 1 ):
21- self .obstacle_paths .append (self .generate_dynamic_obstacle (i ))
23+ if self .num_obstacles > self .grid_size [0 ] * self .grid_size [1 ]:
24+ raise Exception ("Number of obstacles is greater than grid size!" )
25+
26+ for i in range (self .num_obstacles ):
27+ self .obstacle_paths .append (self .generate_dynamic_obstacle (i + 1 ))
2228
29+ """
30+ Generate a dynamic obstacle following a random trajectory, and reserve its path in `self.grid`
31+
32+ input:
33+ obs_idx (int): index of the obstacle. Used to reserve its path in `self.grid`
34+
35+ output:
36+ list[np.ndarray[int, int]]: list of positions of the obstacle at each time step
37+ """
2338 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 ]))
39+
40+ # Sample until a free starting space is found
41+ initial_position = self .sample_random_position ()
42+ while not self .valid_position (initial_position , 0 ):
43+ initial_position = self .sample_random_position ()
44+
2645 positions = [initial_position ]
27- print ("Initial position: " , initial_position )
46+ if self .verbose :
47+ print ("Obstacle initial position: " , initial_position )
2848
2949 diffs = [np .array ([0 , 1 ]), np .array ([0 , - 1 ]), np .array ([1 , 0 ]), np .array ([- 1 , 0 ]), np .array ([0 , 0 ])]
3050
3151 for t in range (1 , self .time_limit - 1 ):
3252 random .shuffle (diffs )
53+ valid_position = None
3354 for diff in diffs :
3455 new_position = positions [- 1 ] + diff
3556
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 ]:
57+ if not self .valid_position (new_position , t ):
3858 continue
3959
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
60+ valid_position = new_position
61+ break
4562
46- # Impossible situation for obstacle - stay in place
47- print ("Impossible situation for obstacle!" )
48- positions .append (positions [- 1 ])
63+ # Impossible situation for obstacle - stay in place
64+ # -> this can happen if another obstacle's path traps this one
65+ if valid_position is None :
66+ valid_position = positions [- 1 ]
4967
50- print ('obs path len: ' , len (positions ))
68+ # Reserve old & new position at this time step
69+ positions .append (new_position )
70+ self .grid [positions [- 2 ][0 ], positions [- 2 ][1 ], t ] = obs_idx
71+ self .grid [new_position [0 ], new_position [1 ], t ] = obs_idx
72+
5173 return positions
5274
75+ """
76+ Check if the given position is valid at time t
77+
78+ input:
79+ position (np.ndarray[int, int]): (x, y) position
80+ t (int): time step
81+
82+ output:
83+ bool: True if position/time combination is valid, False otherwise
84+ """
85+ def valid_position (self , position , t ) -> bool :
86+
87+ # Check if new position is in grid
88+ if position [0 ] < 0 or position [0 ] >= self .grid_size [0 ] or position [1 ] < 0 or position [1 ] >= self .grid_size [1 ]:
89+ return False
90+
91+ # Check if new position is not occupied at time t
92+ return self .grid [position [0 ], position [1 ], t ] == 0
93+
94+ """
95+ Sample a random position that is within the grid's boundaries
96+
97+ output:
98+ np.ndarray[int, int]: (x, y) position
99+ """
100+ def sample_random_position (self ) -> np .ndarray [int , int ]:
101+ return np .array ([np .random .randint (0 , self .grid_size [0 ]), np .random .randint (0 , self .grid_size [1 ])])
102+
53103show_animation = True
54104
55105def main ():
0 commit comments