Esempio n. 1
0
def __get_goal_location_airsim(goal):
    units = UnrealUnits()
    goal_x = goal[0]
    goal_y = goal[1]
    pt = np.asarray([goal_x, goal_y])
    pt_as = np.zeros(2)
    pt_as[0:2] = units.pos2d_to_as(pt)
    return pt_as
Esempio n. 2
0
 def __get_goal_location_airsim(self, path_array):
     units = UnrealUnits(1.0)
     goal_x = path_array[-1][0]
     goal_y = path_array[-1][1]
     pt = np.asarray([goal_x, goal_y])
     pt_as = np.zeros(3)
     pt_as[0:2] = units.pos2d_to_as(pt)
     return pt_as
Esempio n. 3
0
    def __init__(self, instance=0, flight_height=100.0):
        self.instance = instance
        self.port = PORTS[instance]
        self.clock_speed = self._read_clock_speed()
        self.control_interval = 0.5
        self.flight_height = flight_height  # Flight height is in config units, as with everything
        self.units = UnrealUnits()
        print("DroneController Initialize")
        self.rate = Rate(0.1 / self.clock_speed)

        self.samples = []

        killAirSim()
        self._write_airsim_settings()
        startAirSim(self, instance, self.port)
Esempio n. 4
0
def faux_dataset_random_pt(eval_envs):
    print("Generating faux dataset")
    units = UnrealUnits(scale=1.0)
    dataset = []
    for env_id in eval_envs:
        segment_dataset = []
        config = load_env_config(env_id)
        template = load_template(env_id)

        start_pt = np.asarray(config["startPos"])
        second_pt = np.asarray(config["startHeading"])
        end_x = random.uniform(0, 1000)
        end_y = random.uniform(0, 1000)
        end_pt = np.asarray([end_x, end_y])

        state1 = DroneState(None, start_pt)
        state2 = DroneState(None, second_pt)
        state3 = DroneState(None, end_pt)

        segment_dataset.append(bare_min_sample(state1, False, env_id))
        segment_dataset.append(bare_min_sample(state2, False, env_id))
        segment_dataset.append(bare_min_sample(state3, True, env_id))

        dataset.append(segment_dataset)

    return dataset
Esempio n. 5
0
    def plot_path(self, env_id, paths, interactive=False, show=True, bg=True):
        if interactive:
            plt.ion()
            plt.clf()
        else:
            plt.ioff()

        config_size = UnrealUnits().get_config_size()

        if bg:
            try:
                img = load_env_img(env_id)
                plt.imshow(img, extent=(0, config_size[0], 0, config_size[1]))
            except Exception as e:
                print("Error in loading and plotting path!")
                print(e)

        colors = ["r", "g", "b", "y", "c", "m"]

        for path, color in zip(paths, colors):
            # Note that x and y are swapped
            x_targets, y_targets = list(zip(*path))

            y_targets = config_size[1] - y_targets

            plt.plot(y_targets, x_targets, color)
            plt.plot(y_targets[-1], x_targets[-1], color + "o")

        plt.axis([0, config_size[0], 0, config_size[1]])

        if show:
            plt.show()
            plt.pause(0.0001)
Esempio n. 6
0
def get_landmark_locations_airsim(config_json, add_empty=False):
    landmark_names = []
    landmark_positions = []
    units = UnrealUnits()
    for i, landmarkName in enumerate(config_json["landmarkName"]):
        x_pos = config_json["xPos"][i]
        y_pos = config_json["zPos"][i]
        pt = np.asarray([x_pos, y_pos])
        pt_as = np.zeros(3)
        pt_as[0:2] = units.pos2d_to_as(pt)
        pt_as[2] = -1.0  # Landmarks assumed to be floating 1m above ground.
        landmark_names.append(landmarkName)
        landmark_positions.append(pt_as)

    landmark_indices = get_landmark_name_to_index(add_empty=add_empty)
    landmark_indices = [landmark_indices[name] for name in landmark_names]

    return landmark_names, landmark_indices, landmark_positions
Esempio n. 7
0
def faux_dataset_random_landmark(eval_envs):
    print("Generating faux dataset")
    units = UnrealUnits(scale=1.0)
    dataset = []
    for env_id in eval_envs:
        segment_dataset = []
        config = load_env_config(env_id)
        template = load_template(env_id)
        path = load_path(env_id)

        landmark_radii = config["radius"]

        start_pt = np.asarray(config["startPos"])
        second_pt = np.asarray(config["startHeading"])

        landmark_choice_ids = list(range(len(config["landmarkName"])))
        choice_id = random.choice(landmark_choice_ids)

        target_x = config["xPos"][choice_id]
        target_y = config["zPos"][choice_id]
        target_lm_pos = np.asarray([target_x, target_y])

        landmark_dir = target_lm_pos - start_pt

        method = template["side"]

        theta = math.atan2(landmark_dir[1], landmark_dir[0]) + math.pi
        if method == "infront":
            theta = theta
        elif method == "random":
            theta = random.random() * 2 * math.pi
        elif method == "behind":
            theta = theta + math.pi
        elif method == "left":
            theta = theta - math.pi / 2
        elif method == "right":
            theta = theta + math.pi / 2

        x, z = target_lm_pos[0], target_lm_pos[1]
        landmark_radius = landmark_radii[choice_id]
        sample_point = np.array([
            x + math.cos(theta) * landmark_radius,
            z + math.sin(theta) * landmark_radius
        ])

        state1 = DroneState(None, start_pt)
        state2 = DroneState(None, second_pt)
        state3 = DroneState(None, sample_point)

        segment_dataset.append(bare_min_sample(state1, False, env_id))
        segment_dataset.append(bare_min_sample(state2, False, env_id))
        segment_dataset.append(bare_min_sample(state3, True, env_id))

        dataset.append(segment_dataset)

    return dataset
Esempio n. 8
0
def get_landmark_locations_airsim(config_json):
    landmark_names = []
    landmark_positions = []
    units = UnrealUnits()
    for i, landmarkName in enumerate(config_json["landmarkName"]):
        x_pos = config_json["xPos"][i]
        y_pos = config_json["zPos"][i]
        pt = np.asarray([x_pos, y_pos])
        pt_as = np.zeros(3)
        pt_as[0:2] = units.pos2d_to_as(pt)
        # TODO: Grab this from the parameter server
        pt_as[
            2] = 0.0 if LANDMARKS_ON_FLOOR else -1.0  # Landmarks assumed to be floating 1m above ground.
        landmark_names.append(landmarkName)
        landmark_positions.append(pt_as)

    landmark_indices = get_landmark_name_to_index()
    landmark_indices = [landmark_indices[name] for name in landmark_names]

    return landmark_names, landmark_indices, landmark_positions
Esempio n. 9
0
    def plot_paths(self,
                   segment_dataset,
                   segment_path=None,
                   file=None,
                   interactive=False,
                   bg=True,
                   texts=[],
                   entire_trajectory=False):
        if interactive:
            plt.ion()
        else:
            plt.ioff()

        if len(segment_dataset) == 0:
            print("Empty segment. Not plotting!")
            return

        path_key = "path" if entire_trajectory else "seg_path"

        env_id = segment_dataset[0]["metadata"]["env_id"]
        if segment_path is None:
            segment_path = segment_dataset[0]["metadata"][path_key]

        config_size = UnrealUnits().get_config_size()
        y_targets, x_targets = list(zip(*cf_to_img(segment_path, [512, 512])))
        y_targets = np.asarray(y_targets) * config_size[1] / 512
        x_targets = np.asarray(x_targets) * config_size[0] / 512
        y_targets = config_size[1] - y_targets
        #x_targets = CONFIG_SIZE[1] - x_targets

        # Note that x and y are swapped
        #x_targets, y_targets = list(zip(*segment_path))

        if entire_trajectory:
            instructions = [
                segment_dataset[i]["instruction"]
                for i in range(len(segment_dataset))
            ]
            unique_instructions = [instructions[0]]
            for instruction in instructions:
                if instruction != unique_instructions[-1]:
                    unique_instructions.append(instruction)
            instruction = "; ".join(unique_instructions)
        else:
            instruction = segment_dataset[0]["instruction"]

        if bg:
            try:
                img = load_env_img(env_id)
                plt.imshow(img, extent=(0, config_size[0], 0, config_size[1]))
            except Exception as e:
                print("Error in plotting paths!")
                print(e)

        #y_targets = CONFIG_SIZE[1] - y_targets
        plt.plot(x_targets, y_targets, "r")
        plt.plot(x_targets[-1], y_targets[-1], "ro")

        # Plot segment endpoints
        #for segment in segment_dataset:
        #    end = segment.metadata["seg_path"][-1]
        #    end_x = end[0]
        #    end_y = CONFIG_SIZE[1] - end[1]
        #    plt.plot(end_y, end_x, "ro")

        x_actual = []
        y_actual = []
        for sample in segment_dataset:
            x_actual.append(sample["state"].state[0])
            y_actual.append(sample["state"].state[1])
        x_actual = np.asarray(x_actual)
        y_actual = np.asarray(y_actual)
        """if len(segment_dataset) > 0:
            instruction, drone_states, actions, rewards, finished = zip(*segment_dataset)
            drone_states = np.asarray(drone_states)
            x_actual = drone_states[:, 0]
            y_actual = drone_states[:, 1]"""

        plt.plot(x_actual, y_actual, "b")
        plt.plot(x_actual[-1], y_actual[-1], "bo")

        plt.axis([0, config_size[0], 0, config_size[1]])

        instruction_split = self.split_lines(instruction, maxchars=40)
        title = "\n".join(instruction_split)

        plt.title("env: " + str(env_id) + " - " + title)

        x = 10
        y = 5
        for text in texts:
            if not DONT_DRAW_TEXT:
                plt.text(x, y, text)
            y += 40

        y += len(instruction_split) * 40 + 40
        for line in instruction_split:
            if not DONT_DRAW_TEXT:
                plt.text(x, y, line)
            y -= 40

        if interactive:
            plt.show()
            plt.pause(0.0001)
Esempio n. 10
0
def get_top_down_ground_truth_dynamic_global(env_id, start_idx, end_idx,
                                             drone_pos_as, img_w, img_h, map_w,
                                             map_h):
    """
    Returns the ground-truth label oriented in the global map frame
    :param env_id:
    :param start_idx:
    :param img_w:
    :param img_h:
    :param map_w:
    :param map_h:
    :return:
    """
    PROFILE = False
    prof = SimpleProfiler(False, PROFILE)
    path = load_path(env_id, anno=True)
    #print(len(path), start_idx, end_idx)

    path = path[start_idx:end_idx]
    #instruction_segments = [self.all_instr[env_id][set_idx]["instructions"][seg_idx]]

    prof.tick("load_path")
    units = UnrealUnits(1.0)
    drone_pos_cf = units.pos3d_from_as(drone_pos_as)

    #print("Dynamic ground truth for ", env_id, start_idx, end_idx)
    gt_dynamic = get_dynamic_ground_truth_v2(path, drone_pos_cf[:2])
    #Presenter().plot_path(env_id, [path[start_idx:end_idx], gt_dynamic])

    prof.tick("gen_gt_path")

    seg_labels = np.zeros([img_w, img_h, 2]).astype(float)
    path_in_img = cf_to_img(gt_dynamic, np.array([map_w, map_h]))
    gauss_sigma = map_w / 96

    seg_labels[:, :, 0] = tdd.plot_path_on_img(seg_labels[:, :, 0],
                                               path_in_img)
    if len(path_in_img) > 1:
        seg_labels[:, :, 1] = tdd.plot_dot_on_img(seg_labels[:, :, 1],
                                                  path_in_img[-1], gauss_sigma)

    prof.tick("plot_path")

    seg_labels[:, :, 0] = gaussian_filter(seg_labels[:, :, 0], gauss_sigma)
    seg_labels[:, :, 1] = gaussian_filter(seg_labels[:, :, 1], gauss_sigma)

    # Standardize both channels separately (each has mean zero, unit variance)
    seg_labels_path = standardize_2d_prob_dist(seg_labels[:, :, 0:1])
    seg_labels_endpt = standardize_2d_prob_dist(seg_labels[:, :, 1:2])

    prof.tick("process_img")

    DEBUG = False
    if DEBUG:
        gt_path_in_img = cf_to_img(path, np.asarray([map_w, map_h]))
        dbg_labels_gt = np.zeros([img_w, img_h, 1])
        dbg_labels_gt[:, :, 0] = tdd.plot_path_on_img(dbg_labels_gt[:, :, 0],
                                                      gt_path_in_img)
        Presenter().show_image(dbg_labels_gt,
                               "dbg",
                               torch=False,
                               waitkey=10,
                               scale=4)
        Presenter().show_image(torch.from_numpy(seg_labels_path),
                               "l_path",
                               torch=True,
                               waitkey=10,
                               scale=4)
        Presenter().show_image(torch.from_numpy(seg_labels_endpt),
                               "l_endp",
                               torch=True,
                               waitkey=100,
                               scale=4)

    seg_labels = np.concatenate((seg_labels_path, seg_labels_endpt), axis=0)

    seg_labels_t = torch.from_numpy(seg_labels).unsqueeze(0).float()

    prof.tick("prep_out")
    prof.print_stats()

    return seg_labels_t
Esempio n. 11
0
class DroneController():
    def __init__(self, instance=0, flight_height=100.0):
        self.instance = instance
        self.port = PORTS[instance]
        self.clock_speed = self._read_clock_speed()
        self.control_interval = 0.5
        self.flight_height = flight_height  # Flight height is in config units, as with everything
        self.units = UnrealUnits()
        print("DroneController Initialize")
        self.rate = Rate(0.1 / self.clock_speed)

        self.samples = []

        killAirSim()
        self._write_airsim_settings()
        startAirSim(self, instance, self.port)

    def _get_config(self, name, i=None, instance_id=None):
        config = load_env_config(id)
        return config

    def _set_config(self,
                    json_data,
                    subfolder,
                    name,
                    i=None,
                    instance_id=None):
        folder = paths.get_current_config_folder(i, instance_id)
        id = "" if i is None else "_" + str(i)
        path = os.path.join(paths.get_sim_config_dir(), folder, subfolder,
                            name + id + ".json")

        if not os.path.isdir(os.path.dirname(path)):
            try:
                os.makedirs(os.path.dirname(path))
            except Exception:
                pass

        if os.path.isfile(path):
            os.remove(path)

        # print("Dumping config in: " + path)
        with open(path, 'w') as fp:
            json.dump(json_data, fp)

        subprocess.check_call(["touch", path])

    def _load_drone_config(self, i, instance_id=None):
        conf_json = load_env_config(i)
        self._set_config(conf_json,
                         "",
                         "random_config",
                         i=None,
                         instance_id=instance_id)

    def _start_call(self):
        try:
            self.client.enableApiControl(True)
            self.client.armDisarm(True)
        except Exception as e:
            import traceback
            from utils.colors import print_error
            print_error("Error encountered during policy rollout!")
            print_error(e)
            print_error(traceback.format_exc())

            startAirSim(self, self.instance, self.port)

            raise RolloutException(
                "Exception encountered during start_call. Rollout should be re-tried"
            )

    def _start(self):
        self.client = MultirotorClient('127.0.0.1', self.port)
        self.client.confirmConnection()
        self._start_call()

        # got to initial height
        pos_as = self.client.getPosition()
        pos_as = [pos_as.x_val, pos_as.y_val, pos_as.z_val]
        pos = self.units.pos3d_from_as(pos_as)
        pos[2] = self.units.height_to_as(self.flight_height)
        print("Telporting to initial position in cfg: ", pos)
        self.teleport_3d(pos, [0, 0, 0])

    def _read_clock_speed(self):
        speed = 1.0
        if "ClockSpeed" in P.get_current_parameters()["AirSim"]:
            speed = P.get_current_parameters()["AirSim"]["ClockSpeed"]
        print("Read clock speed: " + str(speed))
        return speed

    def _write_airsim_settings(self):
        airsim_settings = P.get_current_parameters()["AirSim"]
        airsim_settings_path = P.get_current_parameters(
        )["Environment"]["airsim_settings_path"]
        airsim_settings_path = os.path.expanduser(airsim_settings_path)
        save_json(airsim_settings, airsim_settings_path)
        print("Wrote new AirSim settings to " + str(airsim_settings_path))

    def _action_to_global(self, action):
        drone_yaw = self.get_yaw()
        action_global = np.zeros(3)
        # TODO: Add action[1]
        action_global[0] = action[0] * math.cos(drone_yaw)
        action_global[1] = action[0] * math.sin(drone_yaw)
        action_global[2] = action[2]
        return action_global

    def _try_teleport_to(self, position, yaw, pitch=None, roll=None):
        pos_as = self.units.pos2d_to_as(position[:2])
        yaw_as = self.units.yaw_to_as(yaw)
        tgt_h = self.units.height_to_as(self.flight_height)

        tele_orientation = self.client.toQuaternion(0, 0, yaw_as)
        self.send_local_velocity_command([0, 0, 0])
        self.rate.sleep_n_intervals(3)
        pos1 = self.client.getPosition()
        current_z = pos1.z_val
        pos1.z_val = tgt_h - 50

        self.client.simSetPose(pos1, tele_orientation)
        self.rate.sleep_n_intervals(2)

        tele_pos = Vector3r()
        tele_pos.x_val = pos_as[0]
        tele_pos.y_val = pos_as[1]
        tele_pos.z_val = tgt_h - 50

        self.client.simSetPose(tele_pos, tele_orientation)
        self.rate.sleep_n_intervals(2)

        tele_pos.z_val = tgt_h

        self.client.simSetPose(tele_pos, tele_orientation)
        self.send_local_velocity_command([0, 0, 0])
        self.rate.sleep_n_intervals(3)
        time.sleep(0.1)

    def get_yaw(self):
        o = self.client.getOrientation()
        vec, theta = quaternions.quat2axangle(
            [o.w_val, o.x_val, o.y_val, o.z_val])
        new_vec = self.units.vel3d_from_as(vec)
        roll, pitch, yaw = euler.axangle2euler(new_vec, theta)
        return yaw

    def send_local_velocity_command(self, cmd_vel):
        # Convert the drone reference frame command to a global command as understood by AirSim
        cmd_vel = self._action_to_global(cmd_vel)
        #print("                  global action: ", cmd_vel)
        if len(cmd_vel) == 3:
            cmd_vel_as = self.units.vel2d_to_as(cmd_vel[:2])
            cmd_yaw_as = self.units.yaw_rate_to_as(cmd_vel[2])
            #print("                         AirSim command: ", cmd_vel_as, "yaw rate: ", cmd_yaw_as)
            vel_x = cmd_vel_as[0]
            vel_y = cmd_vel_as[1]
            yaw_rate = cmd_yaw_as
            z = self.units.height_to_as(self.flight_height)
            yaw_mode = YawMode(is_rate=True, yaw_or_rate=yaw_rate)
            self.client.moveByVelocityZ(vel_x,
                                        vel_y,
                                        z,
                                        self.control_interval,
                                        yaw_mode=yaw_mode)

    def teleport_to(self, position, yaw):
        pos_as = self.units.pos2d_to_as(position[0:2])
        tgt_h = self.units.height_to_as(self.flight_height)
        teleported = False
        for i in range(10):
            self._try_teleport_to(position, yaw)
            curr_pos = self.client.getPosition()
            curr_pos_np = np.asarray([curr_pos.x_val, curr_pos.y_val])

            if np.linalg.norm(pos_as - curr_pos_np) < 1.0 and math.fabs(
                    tgt_h - curr_pos.z_val) < 1.0:
                teleported = True
                break
        if not teleported:
            print("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!")
            print("Failed to teleport after 10 attempts!")
            print("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!")

    def teleport_3d(self, position, rpy, pos_in_airsim=True, fast=False):
        pos_as = position if pos_in_airsim else self.units.pos3d_to_as(
            position)
        # TODO: This is broken. p and r should also be converted ideally
        if not pos_in_airsim:
            rpy[2] = self.units.yaw_to_as(rpy[2])

        tele_rot = self.client.toQuaternion(rpy[0], rpy[1], rpy[2])
        self.send_local_velocity_command([0, 0, 0])
        self.rate.sleep_n_intervals(1)
        tele_pos = Vector3r()
        tele_pos.x_val = pos_as[0]
        tele_pos.y_val = pos_as[1]
        tele_pos.z_val = pos_as[2]

        self.client.simSetPose(tele_pos, tele_rot)
        self.send_local_velocity_command([0, 0, 0])
        if not fast:
            time.sleep(0.2)
        self.client.simSetPose(tele_pos, tele_rot)
        self.send_local_velocity_command([0, 0, 0])
        if not fast:
            time.sleep(0.2)

    def get_state(self, depth=False, segmentation=False):
        # Get images
        request = [ImageRequest(0, AirSimImageType.Scene, False, False)]
        if depth:
            request.append(ImageRequest(0, AirSimImageType.DepthPlanner, True))
        if segmentation:
            request.append(
                ImageRequest(0, AirSimImageType.Segmentation, False, False))

        response = self.client.simGetImages(request)

        pos_dict = response[0].camera_position
        rot_dict = response[0].camera_orientation

        cam_pos = [pos_dict[b"x_val"], pos_dict[b"y_val"], pos_dict[b"z_val"]]
        cam_rot = [
            rot_dict[b"w_val"], rot_dict[b"x_val"], rot_dict[b"y_val"],
            rot_dict[b"z_val"]
        ]

        img_data = np.frombuffer(response[0].image_data_uint8, np.uint8)
        image_raw = img_data.reshape(response[0].height, response[0].width, 4)
        image_raw = image_raw[:, :, 0:3]

        concat = [image_raw]

        if depth:
            # Depth is cast to uint8, because otherwise it takes up a lot of space and we don't need such fine-grained
            # resolution
            depth_data = np.asarray(response[1].image_data_float)
            depth_raw = depth_data.reshape(response[1].height,
                                           response[1].width, 1)
            depth_raw = np.clip(depth_raw, 0, 254 / DEPTH_SCALE)
            depth_raw *= DEPTH_SCALE
            depth_raw = depth_raw.astype(np.uint8)
            concat.append(depth_raw)

        if segmentation:
            seg_data = np.frombuffer(response[2].image_data_uint8, np.uint8)
            seg_raw = seg_data.reshape(response[2].height, response[2].width,
                                       4)
            concat.append(seg_raw)

        img_state = np.concatenate(concat, axis=2)

        # Get drone's physical location, orientation and velocity
        pos = self.client.getPosition()
        vel = self.client.getVelocity()
        o = self.client.getOrientation()
        # Turn it into a nice 9-D vector with euler angles
        r_as, p_as, y_as = euler.quat2euler(
            [o.w_val, o.x_val, o.y_val, o.z_val])
        roll, pitch, yaw = self.units.euler_from_as(r_as, p_as, y_as)
        pos_3d_as = np.asarray([pos.x_val, pos.y_val, pos.z_val])
        pos_state = self.units.pos3d_from_as(pos_3d_as)
        vel_state = self.units.vel3d_from_as(
            np.asarray([vel.x_val, vel.y_val, vel.z_val]))
        ori_state = [roll, pitch, yaw]

        drone_state = np.concatenate(
            (pos_state, ori_state, vel_state, cam_pos, cam_rot), axis=0)

        return drone_state, img_state

    def set_current_env_from_config(self, config, instance_id=None):
        """
        Store the provided dict representation of a random_config.json into the
        correct folder for instance_id simulator instance to read it when resetting it's pomdp.
        :param config: Random pomdp configuration to store
        :param instance_id: Simulator instance for which to store it.
        """
        self._set_config(config, "", "random_config", instance_id=instance_id)

    def set_current_env_id(self, env_id, instance_id=None):
        # TODO: This was used before to render the path in the simulator, but now that feature is unused anyways
        env_confs = ["config"]  # , "random_curve"]
        folders = ["configs"]  # , "paths"]

        #for env_conf, folder in zip(env_confs, folders):
        self._load_drone_config(env_id, instance_id)

        gc.collect()

    def reset_environment(self):
        self._start_call()
        self.client.simResetEnv()
        self._start_call()