From ffff202c6daeba17946d26bb8d8194a3ba933b0f Mon Sep 17 00:00:00 2001 From: Adam Sitabkhan <adam.sitabkhan@gmail.com> Date: Sun, 19 Jan 2025 16:45:54 -0600 Subject: [PATCH] Added obstacle plotting, starting to integrate into place_grid --- guided_mrmp/controllers/place_grid.py | 51 +++++++++++++++++++++------ 1 file changed, 41 insertions(+), 10 deletions(-) diff --git a/guided_mrmp/controllers/place_grid.py b/guided_mrmp/controllers/place_grid.py index b1766aa..e2541f9 100644 --- a/guided_mrmp/controllers/place_grid.py +++ b/guided_mrmp/controllers/place_grid.py @@ -20,7 +20,8 @@ def place_grid(robot_locations, cell_size, grid_size=5, subgoals=[], obstacles=[ robot_locations = np.array(robot_locations) subgoals = np.array(subgoals) obstacles = np.array(obstacles) - N = len(robot_locations) + num_robots = len(robot_locations) + num_obst = len(obstacles) # Decision variable: Bottom-left corner of the grid in continuous space bottom_left = cp.Variable(2, name='origin') @@ -28,12 +29,21 @@ def place_grid(robot_locations, cell_size, grid_size=5, subgoals=[], obstacles=[ top_right = bottom_left + grid_size * cell_size # Decision variable: Integer grid indices for each robot - grid_indices = cp.Variable((N, 2), integer=True, name='grid_indices') + grid_indices = cp.Variable((num_robots, 2), integer=True, name='grid_indices') # Calculate cell centers for each robot based on grid indices # Reshape origin to (1, 2) for broadcasting cell_centers = cp.reshape(bottom_left, (1, 2), order='C') + grid_indices * cell_size + cell_size / 2 + if num_obst: + obstacle_cells = cp.Variable((num_obst, grid_size, grid_size), boolean=True, name='obstacle_cells') + + for (cx, cy, r) in obstacles: + for x_idx in range(grid_size): + for y_idx in range(grid_size): + p1 = bottom_left + np.array([x_idx, y_idx]) * cell_size + p2 = p1 + np.ones(2) * cell_size + # Objective: Minimize the sum of squared distances cost = cp.sum_squares(robot_locations - cell_centers) @@ -50,8 +60,8 @@ def place_grid(robot_locations, cell_size, grid_size=5, subgoals=[], obstacles=[ # Use Big M method to ensure unique grid indices M_ind = 10 * grid_size # Big M relative to grid indices M_cts = 10 * max(max(robot_locations[:,0]) - min(robot_locations[:,0]), max(robot_locations[:,1]) - min(robot_locations[:,1])) # Big M relative to robot locations - for i in range(N): - for j in range(i+1, N): + for i in range(num_robots): + for j in range(i+1, num_robots): # At least one of the two constraints below must be true xsep = cp.Variable(boolean=True) ysep = cp.Variable(boolean=True) @@ -76,9 +86,13 @@ def place_grid(robot_locations, cell_size, grid_size=5, subgoals=[], obstacles=[ constraints.append(grid_indices[j, 1] - grid_indices[i, 1] + M_ind * (1 - b1) + M_ind * (1 - ysep) >= 1) # All robots and subgoals must be within grid bounds + for loc in robot_locations: + constraints.append(bottom_left <= loc) + constraints.append(loc <= top_right) for sg in subgoals: constraints.append(bottom_left <= sg) constraints.append(sg <= top_right) + # Solve the optimization problem prob_init_start_time = time.time() @@ -98,6 +112,7 @@ def place_grid(robot_locations, cell_size, grid_size=5, subgoals=[], obstacles=[ return bottom_left.value, cell_centers.value +# Working on making this convex def two_corner_place_grid(robot_locations, grid_size=5, subgoals=[], obstacles=[]): """ Place a grid to cover robot locations with alignment to centers. @@ -254,7 +269,7 @@ def plot_grid(bottom_left, top_right, grid_size): [(bottom_left + i * y_prime_hat)[1], (bottom_right + i * y_prime_hat)[1]], 'k-') -def get_roomba_locs(low, high, num_robots, radius=0.5): +def get_roomba_locs(low, high, num_robots, radius=0.5, obstacles=[]): """ Generates a list of roomba locations within the box bounded by points (low, low), (high, low), (high, high), (low, high). The roombas must be separated by at least 2 * radius @@ -262,10 +277,17 @@ def get_roomba_locs(low, high, num_robots, radius=0.5): locs = [] while len(locs) < num_robots: locs.append(np.random.uniform(low, high, 2)) + invalid = False + for (obst_x, obst_y, obst_r) in obstacles: + if np.linalg.norm(np.array(locs[-1]) - np.array([obst_x, obst_y])) <= radius + obst_r: + invalid = True + break for other_loc in locs[:-1]: if np.linalg.norm(np.array(locs[-1]) - np.array(other_loc)) <= 2 * radius: - locs = locs[:-1] + invalid = True break + if invalid: + locs = locs[:-1] return np.array(locs) @@ -275,12 +297,15 @@ def main(seed, num_robots, plot, two_corner): if not two_corner: roomba_radius = 0.5 - robot_locations = get_roomba_locs(low=0, high=6, num_robots=num_robots, radius=roomba_radius) - # robot_locations = np.random.uniform(low=0, high=5, size=(num_robots, 2)) cell_size = 2.5 * roomba_radius grid_size = 5 - # subgoals = np.random.uniform(low=0, high=6, size=(num_robots, 2)) - subgoals = np.array([[0, 0], [0, 6], [6, 6], [6, 0]]) + + + obstacles = np.array([[2, 2, 0.75], [4, 4, 0.5]]) + # robot_locations = np.random.uniform(low=0, high=5, size=(num_robots, 2)) + robot_locations = get_roomba_locs(low=0, high=6, num_robots=num_robots, radius=roomba_radius, obstacles=obstacles) + # subgoals = np.array([[0, 0], [0, 6], [6, 6], [6, 0]]) + subgoals = get_roomba_locs(low=0, high=6, num_robots=num_robots, radius=roomba_radius, obstacles=obstacles) bottom_left, cell_centers = place_grid(robot_locations=robot_locations, cell_size=cell_size, @@ -329,6 +354,12 @@ def main(seed, num_robots, plot, two_corner): for (x, y) in subgoals: circle = patches.Circle((x, y), radius=roomba_radius, edgecolor='orange', fill=False, linewidth=2) ax.add_patch(circle) + + obstacles = np.array(obstacles) + plt.scatter(obstacles[:, 0], obstacles[:, 1], c='black', marker='s', label='Obstacles') + for (x, y, r) in obstacles: + circle = patches.Circle((x, y), radius=r, edgecolor='black', fill=False, linewidth=2) + ax.add_patch(circle) plt.legend(loc='upper left') -- GitLab