EvolutionGym / evogym

A large-scale benchmark for co-optimizing the design and control of soft robots, as seen in NeurIPS 2021.
https://evolutiongym.github.io/
MIT License
193 stars 33 forks source link

Reshaping state information into grid #6

Closed mhorton19 closed 2 years ago

mhorton19 commented 2 years ago

I am interested in using horizontal/vertical stretches as evolvable operations, and therefore I would really like to process the state vector in a way that I can attribute to individual voxels rather than one big flat state vector. Is there a way to lay out the voxel portion of the state vector into a tensor that includes both dimensions of the robot shape? Specifically, from the paper:

"Then the state information of the robot in our tasks is a (2N + 3)-D vector including the relative position of each voxel corner with respect to the center of mass of the robot (2N-D), and the velocity and orientation of center of mass (3-D)"

I may be misunderstanding this, but (2N - D) + (3 - D) = (2N + 3) - 2D, rather than (2N - 3) - D as stated in the paper. I think this actually supposed to be (2N) and (3 - D), and I found a variable of size 2N stepping through the code with a debugger. However, it was not clear how to attribute each point to a particular voxel. Is there a way to transform this representation to vectors of corner, x_init_voxel_position, y_init_voxel_position, x_pos, y_pos

mhorton19 commented 2 years ago

I reverse engineered the representation with this code if anybody is interested. It populates a grid with the indexes in the "coordinate_data" array generated by the following code:

original_state_vec = env.reset() coordinate_data = original_state_vec[-2*num_coordinates:].reshape((2, num_coordinates))

def get_coordinates_of_corners(body): loc_idx = 0 coordinate_idxs = []

index in obs vector where each corner will be stored. -1 if no value

index_by_corner = np.zeros(tuple(body.shape) + (2, 2), dtype=int) - 1
for y in range(body.shape[0]):
    for x in range(body.shape[1]):
        if body[y,x] != 0:
            has_upper_neighbor = ((y-1) >= 0) and (body[y-1,x] != 0)
            has_left_neighbor = ((x-1) >= 0) and (body[y,x-1] != 0)

            has_right_neighbor = ((x+1) < body.shape[1]) and (body[y,x+1] != 0)
            has_upper_right_neighbor = ((x+1) < body.shape[1]) and ((y-1) >= 0) and (body[y-1,x+1] != 0)

            if has_upper_neighbor:
                index_by_corner[y, x, 0, :] = index_by_corner[y - 1, x, 1, :]
            if has_left_neighbor:
                index_by_corner[y, x, :, 0] = index_by_corner[y, x - 1, :, 1]

            if not (has_upper_neighbor or has_left_neighbor):
                index_by_corner[y, x, 0, 0] = loc_idx
                loc_idx += 1
            if not has_upper_neighbor:
                if has_right_neighbor and has_upper_right_neighbor:
                    index_by_corner[y, x, 0, 1] = index_by_corner[y-1, x+1, 1, 0]
                else:
                    index_by_corner[y, x, 0, 1] = loc_idx
                    loc_idx += 1
            if not has_left_neighbor:
                index_by_corner[y, x, 1, 0] = loc_idx
                loc_idx += 1

            index_by_corner[y, x, 1, 1] = loc_idx
            loc_idx += 1

return index_by_corner, loc_idx