Esempio n. 1
0
 def rotations(self):
     rots = [self.matrix]
     for i in range(3):
         base = rotate90(rots[-1])
         for p in permutations(range(1,4)):
             rots.append(replace(base,p))
     return rots
Esempio n. 2
0
    def forward(self, images):
        """images.shape = (batch, time, channels, obs_height, obs_width)
        output.shape = (batch, time, orientations, map_height, map_width)"""

        (batch_sz, seq_length, channels, obs_h, obs_w) = images.shape
        assert obs_w == obs_h and obs_w % 2 == 1
        map_sz = self.map_size
        state = None

        # merge time dimension into batch dimension, and run net
        images_ = rearrange(images, 'b t e h w -> (b t) e h w')
        obs = self.cnn(images_)
        obs = rearrange(obs, '(b t) e h w -> b t e h w', t=seq_length)
        assert obs.shape[-3] == self.embedding_size
        view_range = (obs.shape[-1] - 1) // 2

        # create stack of rotated observations. shape = (batch, time, orientations, embedding, height, width)
        rotated_obs = t.stack([rotate90(obs, times=i) for i in range(self.orientations)], dim=2)

        # initial pose heatmap, one-hot at center of map and first orientation
        pose = t.zeros((batch_sz, self.orientations, map_sz, map_sz), device=images.device)
        pose[:, 0, (map_sz - 1) // 2, (map_sz - 1) // 2] = 1

        (raw_poses, softmax_poses, maps) = ([], [], [])  # pose tensors and maps through time

        for step in range(seq_length - 1):
            # registration: deconvolve pose estimate with rotated observations to get map-sized embedding
            # output shape = (batch, embeding, height, width)
            registered_obs = self.register(pose, rotated_obs[:, step, :, :, :, :])

            # aggregate registered observations into a map, updating the map state
            (map, state) = self.aggregate_rnn(registered_obs, state)

            # localization: convolve map with rotated observations (from next frame) to obtain pose estimate
            pose = self.localize(map, rotated_obs[:, step + 1, :, :, :, :], pad=not self.improved_padding)

            if self.temperature != 1.0:
                pose = pose * self.temperature

            # return poses before the softmax
            raw_poses.append(pose)

            # softmax over spatial/orientation dimensions
            pose = self.softmax_pose(pose)

            # option to apply padding after softmax (so edges are ignored)
            if self.improved_padding: pose = F.pad(pose, [view_range] * 4)

            # return poses after the softmax, and the map
            softmax_poses.append(pose)
            maps.append(map)

        # aggregate poses (before softmax) over time and apply padding if needed
        raw_poses = t.stack(raw_poses, dim=1)
        if self.improved_padding:
            raw_poses = F.pad(raw_poses, [view_range] * 4)

        return {'raw_poses': raw_poses, 'softmax_poses': t.stack(softmax_poses, dim=1), 'maps': t.stack(maps, dim=1)}
Esempio n. 3
0
 def is_max(self):
     p = self.current
     n = to_int(p)
     for i in range(3):
         p = rotate90(p)
         for q in permutations(range(1, 4)):
             if len(p) == len(self.current) and to_int(replace(p, q)) > n:
                 return False
     return True
Esempio n. 4
0
 def is_max(self):
     p = self.current
     n = to_int(p)
     for i in range(3):
         p = rotate90(p)
         for q in permutations(range(1,4)):
             if len(p) == len(self.current) and to_int(replace(p,q)) > n:
                 return False
     return True
Esempio n. 5
0
def update_visiblility(square_patch, visible_patch, angle_ranges, u, v):
    new_angle_range = []

    for ang_sm, ang_lg, side in angle_ranges:
        # rotate so that ang_sm and ang_lg is in range (-pi/4, pi/4)
        square_patch = rotate90(square_patch, -side)
        visible_patch = rotate90(visible_patch, -side)
        rotate = (pi / 2) * side

        # update strip visibility
        square_patch[-1, :], visible_patch[:, -1, :], strip_ang_ranges\
            = eval_strip_visibility(square_patch[-1, :], visible_patch[:, -1, :], ang_sm - rotate, ang_lg - rotate, u, v)

        # rotate back to original angle
        new_angle_range += [(s + rotate, l + rotate, side) for s, l in strip_ang_ranges]
        square_patch = rotate90(square_patch, side)
        visible_patch = rotate90(visible_patch, side)
    return visible_patch, new_angle_range
Esempio n. 6
0
def embed_view(patch, env_shape, ang90, h0, w0):
    """Embed a local view in an environment at the given pose"""
    patch = rotate90(patch, ang90)

    assert len(env_shape) == 2
    image = torch.zeros((*patch.shape[:-2], *env_shape), dtype=patch.dtype)
    h_env, w_env = env_shape
    h_patch, w_patch = patch.shape[-2:]
    image[..., max(0, h0):h_patch + h0, max(0, w0):w_patch + w0]\
        = patch[..., max(0, -h0):h_env - h0, max(0, -w0):w_env - w0]

    return image
Esempio n. 7
0
def extract_view(env, x, y, ang, view_range):
  """Extract a local view from an environment at the given pose"""
  # get coordinates of window to extract
  xs = t.arange(x - view_range, x + view_range + 1, dtype=t.long)
  ys = t.arange(y - view_range, y + view_range + 1, dtype=t.long)

  # get coordinate 0 instead of going out of bounds
  (h, w) = (env.shape[-2], env.shape[-1])
  (invalid_xs, invalid_ys) = ((xs < 0) | (xs >= w), (ys < 0) | (ys >= h))  # coords outside the env
  xs[invalid_xs] = 0
  ys[invalid_ys] = 0

  # extract view, and set to 0 observations that were out of bounds
  #view = env[..., ys, xs]  # not equivalent to view = env[..., y1:y2, x1:x2]
  view = env.index_select(dim=-2, index=ys).index_select(dim=-1, index=xs)

  view[..., :, invalid_xs] = 0
  view[..., invalid_ys, :] = 0

  # rotate back. note only 90 degrees rotations are allowed
  return rotate90(view, (-ang) % 4)
Esempio n. 8
0
def extract_view(env, h, w, ang90, view_range):
    """Extract a local view from an environment at the given pose"""
    # get coordinates of window to extract
    hs = torch.arange(h - view_range, h + view_range + 1, dtype=torch.long)
    ws = torch.arange(w - view_range, w + view_range + 1, dtype=torch.long)

    # get coordinate 0 instead of going out of bounds
    h_env, w_env = env.shape[-2:]
    invalid_hs, invalid_ws = (
        (hs < 0) | (hs >= h_env), (ws < 0) | (ws >= w_env)
    )  # coords outside the env
    hs[invalid_hs] = 0
    ws[invalid_ws] = 0

    # extract view, and set to 0 observations that were out of bounds
    # view = env[..., xs, ys]  # not equivalent to view = env[..., y1:y2, x1:x2]
    view = env.index_select(dim=-2, index=hs).index_select(dim=-1, index=ws)

    view[..., invalid_hs, :] = 0
    view[..., :, invalid_ws] = 0

    # rotate. note only 90 degrees rotations are allowed
    return rotate90(view, ang90)