Exemple #1
0
def test_draw_robot_full():
    costmap = CostMap2D.create_empty((5, 5), 0.05)
    array_to_draw = np.zeros((costmap.get_data().shape + (3, )),
                             dtype=np.uint8)
    draw_robot(array_to_draw,
               _tricycle_footprint(), (2, 2, np.pi / 4),
               costmap.get_resolution(),
               costmap.get_origin(),
               color=(0, 0, 150))

    draw_robot(array_to_draw,
               _tricycle_footprint(), (-0.5, -0.5, np.pi / 4),
               costmap.get_resolution(),
               costmap.get_origin(),
               color=(0, 0, 150))

    draw_robot(array_to_draw,
               _tricycle_footprint(), (4.6, 3, np.pi / 4),
               costmap.get_resolution(),
               costmap.get_origin(),
               color=(0, 0, 150))

    draw_robot(array_to_draw,
               _tricycle_footprint(), (-4234.6, 3456, np.pi / 4),
               costmap.get_resolution(),
               costmap.get_origin(),
               color=(0, 0, 150))

    static_map = CostMap2D.create_empty((5, 5), 0.05)

    img = prepare_canvas(static_map.get_data().shape)
    draw_robot(img, _tricycle_footprint(), [0., -3, np.pi / 2.],
               static_map.get_resolution(), static_map.get_origin())
def test_world_size_and_center():
    costmap = CostMap2D.create_empty((1, 1), 0.5, world_origin=(0, 0))
    assert costmap.get_data().shape == (2, 2)
    np.testing.assert_array_equal(costmap.world_bounds(), [0, 1, 0, 1])
    np.testing.assert_array_equal(costmap.world_size(), [1, 1])
    np.testing.assert_array_equal(costmap.world_center(), [0.5, 0.5])

    costmap = CostMap2D.create_empty((1, 1), 0.5, world_origin=(-0.13, 0.23))
    assert costmap.get_data().shape == (2, 2)
    np.testing.assert_array_equal(costmap.world_bounds(), [-0.13, 1-0.13, 0.23, 1+0.23])
    np.testing.assert_array_equal(costmap.world_size(), [1, 1])
    np.testing.assert_array_equal(costmap.world_center(), [0.5-0.13, 0.5+0.23])

    costmap = CostMap2D.create_empty((1, 1), 0.05, world_origin=(-0.13, 0.23))
    assert costmap.get_data().shape == (20, 20)
    np.testing.assert_array_equal(costmap.world_bounds(), [-0.13, 1-0.13, 0.23, 1+0.23])
    np.testing.assert_array_equal(costmap.world_size(), [1, 1])
    np.testing.assert_array_equal(costmap.world_center(), [0.5-0.13, 0.5+0.23])

    costmap = CostMap2D.create_empty((1, 1), 0.03, world_origin=(-0.13, 0.23))
    assert costmap.get_data().shape == (33, 33)
    # if there is not an exact match with resolution, we create smaller map than requested
    np.testing.assert_array_equal(costmap.world_bounds(), [-0.13, 1-0.13-0.01, 0.23, 1+0.23-0.01])
    np.testing.assert_array_equal(costmap.world_size(), [1-0.01, 1-0.01])
    np.testing.assert_array_equal(costmap.world_center(), [0.5-0.13-0.005, 0.5+0.23-0.005])
Exemple #3
0
def get_random_maps_squeeze_between_obstacle_in_corridor_on_path():
    """
    Download (or read from cache) randomly edited real world map with of a robot
    in a corridor with 3 square obstacles
    :return: a tuple of 3 elements
      - original realworld costmap of the corridor with 3 boxes
      - reference path that human took
      - tuple of 1000 randomized maps that were obstained by cutting and pasting 3 boxes randomly around
        their original localization
    """
    key = '413293a9-086b-46e0-83ef-bb09d23c70d5'
    test_maps_cache = 'test_random_maps_%s.pkl' % key

    session_tar_key = 'tdwa_paper_' + os.path.splitext(
        test_maps_cache)[0] + '.tar.xz'

    session_tar_file = get_cache_key_path(session_tar_key)
    tar_contents_folder = session_tar_file + '.contents/'
    if not os.path.exists(session_tar_file):
        r = requests.get(
            'https://s3-us-west-1.amazonaws.com/braincorp-research-public-datasets/'
            + session_tar_key)
        with open(session_tar_file, 'wb') as f:
            f.write(r.content)
        # remove unzipped cache if redownloaded
        if os.path.exists(tar_contents_folder):
            shutil.rmtree(tar_contents_folder)

    if not os.path.exists(tar_contents_folder):
        print('Unzipping Tar file "%s"' % session_tar_file)
        try:
            decompress_tar_archive(session_tar_file,
                                   tar_contents_folder,
                                   verbose=True)
        except Exception as ex:
            shutil.rmtree(tar_contents_folder)
            raise ex

    with open(os.path.join(tar_contents_folder, test_maps_cache), 'rb') as f:
        if sys.version_info > (3, 0):
            original_costmap = CostMap2D.from_state(
                pickle.load(f, encoding='latin1'))  # pylint: disable=unexpected-keyword-arg
            static_path = pickle.load(f, encoding='latin1')  # pylint: disable=unexpected-keyword-arg
            test_maps = tuple([
                CostMap2D.from_state(s)
                for s in pickle.load(f, encoding='latin1')
            ])  # pylint: disable=unexpected-keyword-arg
        else:
            original_costmap = CostMap2D.from_state(pickle.load(f))
            static_path = pickle.load(f)
            test_maps = tuple(
                [CostMap2D.from_state(s) for s in pickle.load(f)])

    return original_costmap, static_path, test_maps
Exemple #4
0
    def deserialize(cls, state):

        ver = state.pop('version')
        assert ver == cls.VERSION

        state['costmap'] = CostMap2D.from_state(state['costmap'])

        reward_provider_state_instance = create_reward_provider_state(
            state.pop('reward_provider_state_name'))
        state[
            'reward_provider_state'] = reward_provider_state_instance.deserialize(
                state['reward_provider_state'])

        # prepare for robot state deserialization
        robot_instance = create_standard_robot(state.pop('robot_type_name'))
        robot_state_type = robot_instance.get_state_type()

        # deserialize the robot state
        state['robot_state'] = robot_state_type.deserialize(
            state['robot_state'])

        # deserialize robot state queue
        acc = []
        for item in state['robot_state_queue']:
            acc.append(robot_state_type.deserialize(item))
        state['robot_state_queue'] = acc

        return cls(**state)
Exemple #5
0
def prepare_map_and_path(params):
    """
    Prepare costmap and static path based on the mini env params
    :param params MiniEnvParams: params of the mini env
    :return Tuple[CostMap2D, np.ndarray(3, 2)]: costmap with obstacles and path to follow
    """

    obstacles = [
        Wall(from_pt=params.obstacle_o.as_np(),
             to_pt=params.obstacle_a.as_np()),
        Wall(from_pt=params.obstacle_o.as_np(),
             to_pt=params.obstacle_b.as_np()),
    ]

    obstacle = Block(poly_pt=np.asarray([
        params.obstacle_o.as_np(),
        params.obstacle_a.as_np(),
        params.obstacle_b.as_np()
    ]))

    coarse_static_path = np.array(
        [params.start_pos.as_np(),
         params.end_pos.as_np()])

    static_map = CostMap2D.create_empty(
        world_size=(params.h, params.w),  # x width, y height
        resolution=params.env_params.resolution,
        world_origin=(-params.h / 2., -params.w / 2.))

    if not params.turn_off_obstacles:
        # for obs in obstacles:
        #     static_map = obs.render(static_map)
        obstacle.render(static_map)

    return static_map, coarse_static_path
def box_3d_planning(debug):
    costmap = CostMap2D.create_empty((4, 4), 0.05, np.zeros((2,)))

    gap = 1.4
    add_wall_to_static_map(costmap, (0, 2), (2, 2), width=0.5)
    add_wall_to_static_map(costmap, (2+gap, 2), (4, 2), width=0.5)

    footprint_width = 0.79
    footprint = np.array(
        [[0.5*footprint_width, 0.5*footprint_width],
         [-0.5 * footprint_width+1e-6, 0.5 * footprint_width],
         [-0.5 * footprint_width+1e-6, -0.5 * footprint_width+1e-6],
         [0.5 * footprint_width, -0.5 * footprint_width+1e-6]]
    )

    motion_primitives = exhaustive_geometric_primitives(
        costmap.get_resolution(), 10, 32
    )

    start_pose = np.array([2.3, 1.0, np.pi/4])
    goal_pose = np.array([2.6, 3.0, np.pi/4])
    plan_xytheta, plan_xytheta_cell, controls, plan_time, solution_eps, environment = perform_single_planning(
        planner_name='arastar',
        footprint=footprint,
        motion_primitives=motion_primitives,
        forward_search=True,
        costmap=costmap,
        start_pose=start_pose,
        goal_pose=goal_pose,
        target_v=0.65,
        target_w=1.0,
        allocated_time=np.inf,
        cost_scaling_factor=40.,
        debug=False)

    if debug:

        print(environment.xytheta_real_to_cell(start_pose))
        print(environment.xytheta_real_to_cell(goal_pose))

        print(plan_xytheta_cell)
        print("done with the solution of size=%d and sol. eps=%f" % (len(plan_xytheta_cell), solution_eps))
        print("actual path (with intermediate poses) size=%d" % len(plan_xytheta))

        params = environment.get_params()
        costmap = environment.get_costmap()
        img = prepare_canvas(costmap.shape)
        draw_world_map_with_inflation(img, costmap)
        for pose in plan_xytheta:
            draw_robot(img, footprint, pose, params.cellsize_m, np.zeros((2,)),
                       color=70, color_axis=(1, 2))
        draw_trajectory(img, params.cellsize_m, np.zeros((2,)), plan_xytheta)
        draw_robot(img, footprint, start_pose, params.cellsize_m, np.zeros((2,)))
        draw_robot(img, footprint, goal_pose, params.cellsize_m, np.zeros((2,)))
        magnify = 4
        img = cv2.resize(img, dsize=(0, 0), fx=magnify, fy=magnify, interpolation=cv2.INTER_NEAREST)
        cv2.imshow("planning result", img)
        cv2.waitKey(-1)
def clone_costmap(costmap):
    '''
    Clone other costmap copying the data and other fields
    :param costmap CostMap2D: costmap to clone
    :return CostMap2D: costmap with copied data
    '''
    return CostMap2D(costmap.get_data().copy(),
                     costmap.get_resolution(),
                     costmap.get_origin().copy())
Exemple #8
0
def load_costmap_from_img(img_fname):
    """
    Make a costmap from an image.
    :param img_fname str: fname of image to load.
    :return (path_to_follow, CostMap2D) pair: path following task specification
    """
    resolution = 0.03
    world_size = 10

    static_map = CostMap2D.create_empty(world_size=(world_size, world_size),
                                        resolution=resolution,
                                        world_origin=(0, 0))

    img = cv2.imread(img_fname)
    # opencv loads bgr
    b, g, _ = img[..., 0], img[..., 1], img[..., 2]

    start_img = g
    # walls_img = r
    path_img = b

    start_y, start_x = np.where(start_img == 255)
    start_x = start_x[0]
    start_y = start_y[0]

    current_node = start_x, start_y
    path = []

    found_neighbour = True

    while found_neighbour:
        path.append(np.array(current_node))
        cur_x, cur_y = current_node

        found_neighbour = False
        for v_x, v_y in _neighbours():
            n_x = cur_x + v_x
            n_y = cur_y + v_y
            val = path_img[n_y, n_x]

            if val == 255:
                current_node = n_x, n_y
                found_neighbour = True
                path_img[n_y, n_x] = 0
                break

    prepath = np.array(path)
    path = prepath * resolution

    # Should actually do this, but not allowed for now
    # static_map._data = np.clip(walls_img, 0, 254)

    path = orient_path(path)
    return path, static_map
Exemple #9
0
    def deserialize(cls, state):
        ver = state.pop('version')
        assert ver == cls.VERSION

        state['costmap'] = CostMap2D.from_state(state['costmap'])
        robot_instance = create_standard_robot(state.pop('robot_type_name'))
        robot_state_type = robot_instance.get_state_type()

        # deserialize the robot state
        state['robot_state'] = robot_state_type.deserialize(
            state['robot_state'])
        return cls(**state)
Exemple #10
0
def test_rotate_costmap():
    # test inflated map
    costmap = CostMap2D.create_empty((5, 4), 0.05)
    costmap.get_data()[30, 30] = CostMap2D.LETHAL_OBSTACLE

    assert_mark_at(costmap, 30, 30)
    rotated_costmap = CostMap2D(rotate_costmap(costmap.get_data(), -np.pi / 4),
                                costmap.get_resolution(), costmap.get_origin())
    assert_mark_at(rotated_costmap, 29, 47, check_inflation=False)

    # test binary map
    costmap = CostMap2D.create_empty((5, 4), 0.05)
    costmap.get_data()[30, 30] = CostMap2D.LETHAL_OBSTACLE

    rotated_data = rotate_costmap(costmap.get_data(), -np.pi / 4)

    non_free_indices = np.where(rotated_data != 0)
    assert len(non_free_indices[0]) == 1
    non_free_indices = (non_free_indices[0][0], non_free_indices[1][0])
    assert non_free_indices == (47, 29)
    assert (rotated_data[non_free_indices[0],
                         non_free_indices[1]] == CostMap2D.LETHAL_OBSTACLE)
def test_costmap_inflation():
    """Sanity checks on inflation"""
    costmap = CostMap2D.create_empty((1, 1), 0.1, (0, 0))
    add_wall_to_static_map(costmap, (0, 0), (1, 1))

    cost_scaling_factor = 1.
    inflated_costmap = inflate_costmap(costmap, cost_scaling_factor,
                                       _rectangular_footprint())

    inflated_pixels = len(
        np.where(
            inflated_costmap.get_data() == INSCRIBED_INFLATED_OBSTACLE)[0])
    assert inflated_pixels == 70
Exemple #12
0
    def deserialize(cls, state):

        ver = state.pop('version')
        assert ver == cls.VERSION

        init_costmap = CostMap2D.from_state(state['costmap'])
        init_path = state['path']
        params = EnvParams.deserialize(state['params'])
        state = State.deserialize(state['state'])
        instance = cls(init_costmap, init_path, params)
        instance.set_state(state)

        return instance
def extract_egocentric_costmap(costmap_2d, ego_position_in_world,
                               resulting_origin=None,
                               resulting_size=None, border_value=0):
    """
    Returns a costmap as seen by robot at ego_position_in_world.
    In this costmap robot is at (0, 0) with 0 angle.

    :param costmap_2d: global costmap
    :param ego_position_in_world: robot's position in the world costmap
    :param resulting_origin: Perform additional shifts and cuts so that
        resulting costmap origin and world size are equal to those parameters
    :param resulting_size: Perform additional shifts and cuts so that
        resulting costmap origin and world size are equal to those parameters
    :param border_value: the value at the border of the costmap to extrapolate
    :return: returns the egocentric costmap, with the robot in the middle.
    """
    ego_pose = np.asarray(ego_position_in_world)
    pixel_origin = costmap_2d.world_to_pixel(np.array(ego_pose[:2], dtype=np.float64))

    transform = cv2.getRotationMatrix2D(tuple(pixel_origin), 180 * ego_pose[2] / np.pi, scale=1)

    if resulting_size is None:
        resulting_size = costmap_2d.get_data().shape[:2][::-1]
    else:
        resulting_size = tuple(world_to_pixel(np.array(resulting_size, dtype=np.float64), np.array((0., 0.)), costmap_2d.get_resolution()))

    if resulting_origin is not None:
        resulting_origin = np.asarray(resulting_origin)
        assert resulting_origin.shape[0] == 2
        delta_shift = resulting_origin - (costmap_2d.get_origin() - ego_pose[:2])
        delta_shift_pixel = tuple(world_to_pixel(delta_shift, np.array((0., 0.)), costmap_2d.get_resolution()))
        shift_matrix = np.float32([[1, 0, -delta_shift_pixel[0]], [0, 1, -delta_shift_pixel[1]]])

        def _compose_affine_transforms(t1, t2):
            # http://stackoverflow.com/questions/13557066/built-in-function-to-combine-affine-transforms-in-opencv
            t1_expanded = np.array((t1[0], t1[1], (0, 0, 1)), dtype=np.float32)
            t2_expanded = np.array((t2[0], t2[1], (0, 0, 1)), dtype=np.float32)
            combined = np.dot(t2_expanded, t1_expanded)
            return combined[:2, :]

        transform = _compose_affine_transforms(transform, shift_matrix)
    else:
        resulting_origin = costmap_2d.get_origin() - ego_pose[:2]

    with single_threaded_opencv():
        rotated_data = cv2.warpAffine(costmap_2d.get_data(), transform, resulting_size,
                                      # this mode doesn't change the value of pixels during rotation
                                      flags=cv2.INTER_NEAREST, borderValue=border_value)

    return CostMap2D(rotated_data, costmap_2d.get_resolution(),
                     origin=resulting_origin)
Exemple #14
0
def generate_trajectory_and_map_from_config(config):
    """ Based on given MapConfig,
    generate (trajectory to follow, CostMap2D) pair.
    :param config MapConfig: map config based on which we will make a map.
    :return (path_to_follow, CostMap2D) pair: path following task specification
    """

    static_map = CostMap2D.create_empty(world_size=config.size,
                                        resolution=config.resolution,
                                        world_origin=config.origin)

    for obs in config.obstacles:
        static_map = obs.render(static_map)

    return config.trajectory, static_map
Exemple #15
0
def test_costmap_2d_extract_egocentric_costmap_with_nonzero_origin():
    costmap2d = CostMap2D(np.zeros((100, 100), dtype=np.float64), 0.05,
                          np.array([1.0, 2.0]))
    costmap2d.get_data()[10, 20] = CostMap2D.LETHAL_OBSTACLE

    # rotate, shift and cut -> extract ego costmap centered on the robot
    cut_map = extract_egocentric_costmap(costmap2d, (3.5, 3.5, -np.pi / 4),
                                         resulting_origin=np.array(
                                             [-2, -2], dtype=np.float64),
                                         resulting_size=(4, 4))
    assert cut_map.get_resolution() == costmap2d.get_resolution()
    np.testing.assert_array_equal(cut_map.get_origin(), (-2, -2))
    np.testing.assert_array_equal(cut_map.get_data().shape, (80, 80))
    np.testing.assert_array_almost_equal(cut_map.world_bounds(),
                                         (-2, 2, -2, 2))
    assert_mark_at(cut_map, 33, 5)
Exemple #16
0
def test_costmap_2d_extract_egocentric_binary_costmap():
    costmap = CostMap2D.create_empty((5, 5), 0.05)
    costmap.get_data()[30:32, 30:32] = CostMap2D.LETHAL_OBSTACLE

    cut_map = extract_egocentric_costmap(costmap, (1.5, 1.5, -np.pi / 4),
                                         resulting_origin=np.array(
                                             [-2.0, -2.0], dtype=np.float64),
                                         resulting_size=(4., 4))

    rotated_data = cut_map.get_data()
    non_free_indices = np.where(rotated_data != 0)
    np.testing.assert_array_equal(non_free_indices[0], [40, 41, 41, 41, 42])
    np.testing.assert_array_equal(non_free_indices[1], [40, 39, 40, 41, 40])

    assert (
        rotated_data[non_free_indices[0],
                     non_free_indices[1]] == CostMap2D.LETHAL_OBSTACLE).all()
def inflate_costmap(costmap, cost_scaling_factor, footprint):
    '''
    Inflate data with costs
    Costmap inflation is explained here:
    http://wiki.ros.org/costmap_2d#Inflation
    :param costmap CostMap2D: obstacle map
    :param cost_scaling_factor Float: how to scale the inflated costs
    :param footprint np.ndarray(N, 2)[Float]: footprint of the robot
    :return CostMap2D: inflated costs
    '''
    image_for_dist_transform = CostMap2D.LETHAL_OBSTACLE - costmap.get_data()
    distance = distance_transform(image_for_dist_transform)
    inscribed_rad = inscribed_radius(footprint)
    inflated_data = _pixel_distance_to_cost(distance, costmap.get_resolution(),
                                            inscribed_rad, cost_scaling_factor)

    return CostMap2D(data=inflated_data,
                     origin=costmap.get_origin(),
                     resolution=costmap.get_resolution())
def visualize_in_gym(gym_env, exp_map, path, pose):
    """
    Alternative visualization method using gym rendering function
    :param gym_env RandomAisleTurnEnv: object storing the robot and environment state in bc_gym_planning_env standard
    :param exp_map Costmap: occupancy map in bc_exploration standard
    :param path array(N, 3)[float]: containing an array of poses for the robot to follow
    :param pose array(3)[float]: corresponds to the pose of the robot [x, y, theta]
    """

    gym_compat_map = np.zeros(exp_map.data.shape, dtype=np.uint8)
    gym_compat_map[exp_map.data ==
                   Costmap.OCCUPIED] = CostMap2D.LETHAL_OBSTACLE
    gym_compat_map[exp_map.data == Costmap.FREE] = CostMap2D.FREE_SPACE
    gym_compat_map[exp_map.data ==
                   Costmap.UNEXPLORED] = CostMap2D.NO_INFORMATION

    gym_costmap = CostMap2D(np.flipud(gym_compat_map), exp_map.resolution,
                            exp_map.origin.copy())

    gym_state = gym_env.get_state()

    if np.array(path).shape[0]:
        gym_state.path = path
        gym_state.original_path = path
    else:
        gym_state.path = pose[None, :]
        gym_state.original_path = pose[None, :]

    gym_state.costmap = gym_costmap

    gym_state.pose = pose

    gym_state.robot_state.x = pose[0]
    gym_state.robot_state.y = pose[1]
    gym_state.robot_state.angle = pose[2]

    gym_env.set_state(gym_state)

    gym_env.render(mode='human')
Exemple #19
0
def test_draw_trajectory():
    costmap = CostMap2D(data=np.zeros((400, 400), dtype=np.uint8),
                        origin=np.array([-10., -10.]),
                        resolution=0.05)
    trajectory_picture = np.zeros((costmap.get_data().shape + (3, )),
                                  dtype=np.uint8)

    trajectory = np.array([[-5, -2, np.pi / 4], [-4.5, -1.5, np.pi / 3]])
    draw_trajectory(trajectory_picture,
                    costmap.get_resolution(),
                    costmap.get_origin(),
                    trajectory,
                    color=(0, 255, 0))

    idy, idx = np.where(np.all(trajectory_picture == (0, 255, 0), axis=2))
    np.testing.assert_array_equal(
        idy, [229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239])
    np.testing.assert_array_equal(
        idx, [110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100])

    draw_trajectory(trajectory_picture, costmap.get_resolution(),
                    costmap.get_origin(), [])
Exemple #20
0
def test_is_robot_colliding():
    costmap = CostMap2D.create_empty((10, 6), 0.05, (-1, -3))
    wall_pos_x = 3.9
    add_wall_to_static_map(costmap, (wall_pos_x, -4.), (wall_pos_x, -1 + 1.5))
    wall_pos_x = 1.5
    add_wall_to_static_map(costmap, (wall_pos_x, -4.), (wall_pos_x, -1 + 1.5))
    add_wall_to_static_map(costmap, (5., -4.), (5. + 1, -1 + 4.5))
    footprint = _rectangular_footprint()

    poses = np.array([
        (0., 0., 0.2),
        (1., 0., 0.2),
        (2., 0., 0.2),
        (3., 0., 0.2),
        (4., 0., 0.2),
        (5., 0., 0.2),
        (6., 0., 0.2),
        (0., 1.2, np.pi / 2 + 0.4),
        (1., 1.2, np.pi / 2 + 0.4),
        (2., 1.2, np.pi / 2 + 0.4),
        (3., 1.2, np.pi / 2 + 0.4),
        (4., 1.2, np.pi / 2 + 0.4),
        (5., 1.2, np.pi / 2 + 0.4),
        (6., 1.2, np.pi / 2 + 0.4),
        (0., -3, 0.2),
        (1., -3, 0.2),
        (2., -3, 0.2),
        # These cases should be colliding but because of the current bug,
        # they are not because robot's center is off bounds and we do not want to change behavior at this point
        (0., -3.2, 0.2),
        (1., -3.2, 0.2),
        (2., -3.2, 0.2),
    ])

    expected_collisions = [
        False,
        True,
        True,
        False,
        True,
        True,
        True,
        False,
        False,
        False,
        False,
        True,
        True,
        True,
        False,
        True,
        True,
        False,
        False,
        False,
    ]

    assert len(poses) == len(expected_collisions)

    for robot_pose, expected in zip(poses, expected_collisions):
        is_colliding = is_robot_colliding(robot_pose, footprint,
                                          costmap.get_data(),
                                          costmap.get_origin(),
                                          costmap.get_resolution())
        assert is_colliding == expected

    random_poses = np.random.rand(1000, 3)
    random_poses[:, :2] *= costmap.world_size() + costmap.get_origin(
    ) + np.array([1., 1.])
    for pose in random_poses:
        is_colliding = is_robot_colliding(pose, footprint, costmap.get_data(),
                                          costmap.get_origin(),
                                          costmap.get_resolution())
        is_colliding_ref = is_robot_colliding_reference(
            pose, footprint, costmap.get_data(), costmap.get_origin(),
            costmap.get_resolution())
        assert is_colliding == is_colliding_ref
Exemple #21
0
def test_costmap_2d_extract_egocentric_costmap():
    costmap2d = CostMap2D(np.zeros((100, 100), dtype=np.float64), 0.05,
                          np.array([0.0, 0.0]))
    costmap2d.get_data()[10, 20] = CostMap2D.LETHAL_OBSTACLE

    np.testing.assert_array_equal(costmap2d.world_bounds(), (0, 5, 0, 5))
    assert_mark_at(costmap2d, 20, 10)

    # # dummy cut
    cut_map = extract_egocentric_costmap(costmap2d, (0., 0., 0.))
    assert cut_map.get_resolution() == costmap2d.get_resolution()
    np.testing.assert_array_equal(cut_map.get_origin(), (0.0, 0.0))
    np.testing.assert_array_equal(cut_map.get_data().shape, (100, 100))
    np.testing.assert_array_equal(cut_map.world_bounds(), (0.0, 5, 0.0, 5))
    assert_mark_at(cut_map, 20, 10)

    # shift
    cut_map = extract_egocentric_costmap(costmap2d, (0.2, 0.2, 0.0))
    assert cut_map.get_resolution() == costmap2d.get_resolution()
    np.testing.assert_array_equal(cut_map.get_origin(), (-0.2, -0.2))
    np.testing.assert_array_equal(cut_map.get_data().shape, (100, 100))
    np.testing.assert_array_equal(cut_map.world_bounds(),
                                  (-0.2, 4.8, -0.2, 4.8))

    # ego centric view doesn't shift the data itself if not rotated
    assert_mark_at(cut_map, 20, 10)

    # rotate so that mark is almost in the front of the robot
    cut_map = extract_egocentric_costmap(costmap2d,
                                         (0.0, 0.0, np.pi / 6 - 0.05))
    assert cut_map.get_resolution() == costmap2d.get_resolution()
    np.testing.assert_array_equal(cut_map.get_origin(), (-0., -0.))
    np.testing.assert_array_equal(cut_map.get_data().shape, (100, 100))
    np.testing.assert_array_equal(cut_map.world_bounds(), (0.0, 5, 0.0, 5))

    assert_mark_at(cut_map, 22, 0, check_single=False)

    # rotate as if robot is in the center of the costmap
    cut_map = extract_egocentric_costmap(costmap2d, (2.5, 2.5, -np.pi / 2.))
    assert cut_map.get_resolution() == costmap2d.get_resolution()
    np.testing.assert_array_equal(cut_map.get_origin(), (-2.5, -2.5))
    np.testing.assert_array_equal(cut_map.get_data().shape, (100, 100))
    np.testing.assert_array_equal(cut_map.world_bounds(),
                                  (-2.5, 2.5, -2.5, 2.5))
    assert_mark_at(cut_map, 90, 20)

    # rotate as if robot is in the center of the costmap with explicit parameters
    cut_map = extract_egocentric_costmap(costmap2d, (2.5, 2.5, -np.pi / 2),
                                         resulting_origin=np.array(
                                             [-2.5, -2.5], dtype=np.float64),
                                         resulting_size=np.array((5., 5.)))
    assert cut_map.get_resolution() == costmap2d.get_resolution()
    np.testing.assert_array_equal(cut_map.get_origin(), (-2.5, -2.5))
    np.testing.assert_array_equal(cut_map.get_data().shape, (100, 100))
    np.testing.assert_array_equal(cut_map.world_bounds(),
                                  (-2.5, 2.5, -2.5, 2.5))
    assert_mark_at(cut_map, 90, 20)

    # rotate as if robot is in the center of the costmap with smaller size
    cut_map = extract_egocentric_costmap(costmap2d, (2.5, 2.5, -np.pi / 2),
                                         resulting_origin=np.array(
                                             [-2.5, -2.5], dtype=np.float64),
                                         resulting_size=(4.6, 4.9))
    assert cut_map.get_resolution() == costmap2d.get_resolution()
    np.testing.assert_array_equal(cut_map.get_origin(), (-2.5, -2.5))
    np.testing.assert_array_equal(cut_map.get_data().shape, (98, 92))
    np.testing.assert_array_almost_equal(cut_map.world_bounds(),
                                         (-2.5, 2.1, -2.5, 2.4))
    assert_mark_at(cut_map, 90, 20)

    # do not rotate but shift
    cut_map = extract_egocentric_costmap(costmap2d, (2.5, 2.5, 0.0),
                                         resulting_origin=np.array(
                                             [-5, -4], dtype=np.float64),
                                         resulting_size=(5, 5))
    assert cut_map.get_resolution() == costmap2d.get_resolution()
    np.testing.assert_array_equal(cut_map.get_origin(), (-5, -4))
    np.testing.assert_array_equal(cut_map.get_data().shape, (100, 100))
    np.testing.assert_array_almost_equal(cut_map.world_bounds(),
                                         (-5, 0, -4, 1))
    assert_mark_at(cut_map, 70, 40)

    # do not rotate but shift and cut
    cut_map = extract_egocentric_costmap(costmap2d, (2.5, 2.5, 0.0),
                                         resulting_origin=np.array(
                                             [-5, -4], dtype=np.float64),
                                         resulting_size=(4, 4))
    assert cut_map.get_resolution() == costmap2d.get_resolution()
    np.testing.assert_array_equal(cut_map.get_origin(), (-5, -4))
    np.testing.assert_array_equal(cut_map.get_data().shape, (80, 80))
    np.testing.assert_array_almost_equal(cut_map.world_bounds(),
                                         (-5, -1, -4, 0))
    assert_mark_at(cut_map, 70, 40)

    # rotate, shift and cut -> extract ego costmap centered on the robot
    cut_map = extract_egocentric_costmap(costmap2d, (1.5, 1.5, -np.pi / 4),
                                         resulting_origin=np.array(
                                             [-2, -2], dtype=np.float64),
                                         resulting_size=(4, 4))
    assert cut_map.get_resolution() == costmap2d.get_resolution()
    np.testing.assert_array_equal(cut_map.get_origin(), (-2, -2))
    np.testing.assert_array_equal(cut_map.get_data().shape, (80, 80))
    np.testing.assert_array_almost_equal(cut_map.world_bounds(),
                                         (-2, 2, -2, 2))
    assert_mark_at(cut_map, 47, 19)

    # rotate, shift and expand -> extract ego costmap centered on the robot, going off the limits of original map
    cut_map = extract_egocentric_costmap(costmap2d, (1., 1.5, -np.pi / 4),
                                         resulting_origin=np.array(
                                             [-3, -3], dtype=np.float64),
                                         resulting_size=(7, 6))
    assert cut_map.get_resolution() == costmap2d.get_resolution()
    np.testing.assert_array_equal(cut_map.get_origin(), (-3, -3))
    np.testing.assert_array_equal(cut_map.get_data().shape, (120, 140))
    np.testing.assert_array_almost_equal(cut_map.world_bounds(),
                                         (-3, 4, -3, 3))
    assert_mark_at(cut_map, 74, 46)

    costmap_with_image = CostMap2D(np.zeros((100, 100, 3), dtype=np.float64),
                                   0.05, np.array([0., 0.]))
    extract_egocentric_costmap(costmap_with_image, [0., 0., np.pi / 4])
Exemple #22
0
def path_and_costmap_from_config(params):
    """
    Generate the actual path and  turn

    :param params TurnParams: information about the turn
    :return: Tuple[ndarray(N, 3), Costmap2D]
    """
    # we assume right turn, we can always flip it
    turn_params = params.turn_params

    hh = turn_params.main_corridor_length / 2
    w = turn_params.turn_corridor_length / 2
    alpha = turn_params.turn_corridor_angle
    dd = turn_params.main_corridor_width
    z = turn_params.turn_corridor_width
    margin = turn_params.margin
    flip_arnd_oy = turn_params.flip_arnd_oy
    flip_arnd_ox = turn_params.flip_arnd_ox
    rot_theta = turn_params.rot_theta

    pts = _draw_pts_in_standard_coords(dd, hh, alpha, z, w)
    oriented_way_pts = _generate_path_in_standard_coords(dd, hh, alpha, z, w)

    # Maybe transform the points
    rot_mtx = _rotation_matrix(rot_theta)

    flipping_mtx = np.array([[-1. if flip_arnd_oy else 1., 0.],
                             [0., -1. if flip_arnd_ox else 1.]], )
    transform_mtx = np.dot(rot_mtx, flipping_mtx)

    new_pts = []

    for pt in pts:
        new_pt = np.dot(transform_mtx, pt)
        new_pts.append(new_pt)

    new_oriented_way_pts = []
    for pt in oriented_way_pts:
        x, y, t = pt
        nx, ny = np.dot(transform_mtx, np.array([x, y]))
        new_angle = t
        if flip_arnd_ox:
            new_angle = -new_angle
        if flip_arnd_oy:
            new_angle = np.pi - new_angle
        new_angle = np.mod(new_angle + rot_theta, 2 * np.pi)
        new_pt = np.array([nx, ny, new_angle])
        new_oriented_way_pts.append(new_pt)

    a, _, c, d, e, _, g, h, i, j = new_pts  # pylint: disable=unbalanced-tuple-unpacking
    rb, rk, rl, rf = new_oriented_way_pts  # pylint: disable=unbalanced-tuple-unpacking
    all_pts = np.array(list(new_pts))

    min_x = all_pts[:, 0].min()
    max_x = all_pts[:, 0].max()
    min_y = all_pts[:, 1].min()
    max_y = all_pts[:, 1].max()

    world_size = abs(max_x - min_x) + 2 * margin, abs(max_y -
                                                      min_y) + 2 * margin
    world_origin = min_x - margin, min_y - margin

    obstacles = [
        Wall(from_pt=a, to_pt=i),
        Wall(from_pt=c, to_pt=d),
        Wall(from_pt=d, to_pt=e),
        Wall(from_pt=j, to_pt=g),
        Wall(from_pt=g, to_pt=h)
    ]

    static_path = np.array([rb, rk, rl, rf])

    static_map = CostMap2D.create_empty(
        world_size=world_size,  # x width, y height
        resolution=params.env_params.resolution,
        world_origin=world_origin)

    for obs in obstacles:
        static_map = obs.render(static_map)

    return static_path, static_map
def box_2d_planning(debug):
    costmap = CostMap2D.create_empty((4, 4), 0.2, np.zeros((2,)))

    gap = 1.2
    add_wall_to_static_map(costmap, (0, 2), (2, 2), width=0.0)
    add_wall_to_static_map(costmap, (2+gap, 2), (4, 2), width=0.0)

    footprint_width = 0.79
    footprint = np.array(
        [[0.5*footprint_width, 0.5*footprint_width],
         [-0.5 * footprint_width+1e-6, 0.5 * footprint_width],
         [-0.5 * footprint_width+1e-6, -0.5 * footprint_width+1e-6],
         [0.5 * footprint_width, -0.5 * footprint_width+1e-6]]
    )

    start_theta_discrete = 0
    number_of_intermediate_states = 2
    number_of_angles = 1
    batch = []
    action_cost_multiplier = 1
    for i, end_cell in enumerate([[1, 0, 0],
                                  [0, 1, 0],
                                  [-1, 0, 0],
                                  [0, -1, 0]]):
        batch.append(create_linear_primitive(
            primitive_id=i,
            start_theta_discrete=start_theta_discrete,
            action_cost_multiplier=action_cost_multiplier,
            end_cell=end_cell,
            number_of_intermediate_states=number_of_intermediate_states,
            resolution=costmap.get_resolution(),
            number_of_angles=number_of_angles))

    motion_primitives = MotionPrimitives(
        resolution=costmap.get_resolution(),
        number_of_angles=1,
        mprim_list=batch
    )

    start_pose = np.array([2.3, 1.3, 0.])
    goal_pose = np.array([2.6, 2.8, 0.])
    plan_xytheta, plan_xytheta_cell, controls, plan_time, solution_eps, environment = perform_single_planning(
        planner_name='arastar',
        footprint=footprint,
        motion_primitives=motion_primitives,
        forward_search=True,
        costmap=costmap,
        start_pose=start_pose,
        goal_pose=goal_pose,
        target_v=0.65,
        target_w=1.0,
        allocated_time=np.inf,
        cost_scaling_factor=40.,
        debug=False)

    if debug:

        print(environment.xytheta_real_to_cell(start_pose))
        print(environment.xytheta_real_to_cell(goal_pose))

        print(plan_xytheta_cell)
        print("done with the solution of size=%d and sol. eps=%f" % (len(plan_xytheta_cell), solution_eps))
        print("actual path (with intermediate poses) size=%d" % len(plan_xytheta))

        params = environment.get_params()
        costmap = environment.get_costmap()
        img = prepare_canvas(costmap.shape)
        draw_world_map_with_inflation(img, costmap)
        for pose in plan_xytheta:
            draw_robot(img, footprint, pose, params.cellsize_m, np.zeros((2,)),
                       color=70, color_axis=(1, 2))
        draw_trajectory(img, params.cellsize_m, np.zeros((2,)), plan_xytheta)
        draw_robot(img, footprint, start_pose, params.cellsize_m, np.zeros((2,)))
        draw_robot(img, footprint, goal_pose, params.cellsize_m, np.zeros((2,)))
        magnify = 16
        img = cv2.resize(img, dsize=(0, 0), fx=magnify, fy=magnify, interpolation=cv2.INTER_NEAREST)
        cv2.imshow("planning result", img)
        cv2.waitKey(-1)