Exemplo n.º 1
0
def test_quaternion_renormalized():
    """Make sure that a quaternion is correctly re-normalized.

    Normalized and unnormalized quaternion variants should generate the same 3d rotation matrix.
    """
    q1 = np.array([0.0, 0.0, 0.0, 1.0])
    R1 = quat2rotmat(q1)

    q2 = np.array([0.0, 0.0, 0.0, 2.0])
    R2 = quat2rotmat(q2)

    assert np.allclose(R1, R2)
Exemplo n.º 2
0
def label_to_bbox(label: _LabelType) -> Tuple[np.ndarray, float]:
    """Convert a label into a parameterized bounding box that lives in the ego-vehicle
        coordinate frame.

    Args:
        label: _LabelType

    Returns:
        bbox: Numpmy array for bounding box itself
        orientation: angle in radians, representing bounding box yaw

    """
    length = label["length"]
    width = label["width"]
    height = label["height"]

    p0 = np.array([-length / 2, -width / 2, -height / 2])[:, np.newaxis]
    p1 = np.array([+length / 2, -width / 2, -height / 2])[:, np.newaxis]
    p2 = np.array([-length / 2, +width / 2, -height / 2])[:, np.newaxis]

    bbox = np.array([p0, p1, p2, height])

    R = quat2rotmat((label["rotation"]["w"], label["rotation"]["x"],
                     label["rotation"]["y"], label["rotation"]["z"]))
    t = np.array(
        [label["center"]["x"], label["center"]["y"],
         label["center"]["z"]])[:, np.newaxis]

    v = np.array([1, 0, 0])[:, np.newaxis]
    orientation = np.matmul(R, v)
    orientation = np.arctan2(orientation[1, 0], orientation[0, 0])

    return transform_bounding_box_3d(bbox, R, t), orientation
Exemplo n.º 3
0
def test_quat2rotmat_1() -> None:
    """Test receiving a quaternion in (w, x, y, z) from a camera extrinsic matrix."""
    q = np.array([1.0, 0.0, 0.0, 0.0])
    R = quat2rotmat(q)
    assert np.allclose(R, quat2rotmat_numpy(q))
    R_gt = np.array([[1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]])
    assert np.allclose(R_gt, R)
Exemplo n.º 4
0
def label_to_bbox(label: _LabelType) -> Tuple[np.ndarray, np.ndarray]:
    """Convert a label into a bounding box.

    Args:
        label: _LabelType

    Returns:
        bbox: nupmy array for bounding box itself
        orientation: numpy array for bounding box orientation

    """

    length = label["length"]
    width = label["width"]
    height = label["height"]

    p0 = np.array([-length / 2, -width / 2, -height / 2])[:, np.newaxis]
    p1 = np.array([+length / 2, -width / 2, -height / 2])[:, np.newaxis]
    p2 = np.array([-length / 2, +width / 2, -height / 2])[:, np.newaxis]

    bbox = np.array([p0, p1, p2, height])

    R = quat2rotmat((label["rotation"]["w"], label["rotation"]["x"],
                     label["rotation"]["y"], label["rotation"]["z"]))
    t = np.array(
        [label["center"]["x"], label["center"]["y"],
         label["center"]["z"]])[:, np.newaxis]

    v = np.array([1, 0, 0])[:, np.newaxis]
    orientation = np.matmul(R, v)
    orientation = np.arctan2(orientation[1, 0], orientation[0, 0])

    return transform_bounding_box_3d(bbox, R, t), orientation
Exemplo n.º 5
0
    def as_3d_bbox(self) -> np.ndarray:
        r"""Calculate the 8 bounding box corners.

        Args:
            None

        Returns:
            Numpy array of shape (8,3)

        Corner numbering::

             5------4
             |\\    |\\
             | \\   | \\
             6--\\--7  \\
             \\  \\  \\ \\
         l    \\  1-------0    h
          e    \\ ||   \\ ||   e
           n    \\||    \\||   i
            g    \\2------3    g
             t      width.     h
              h.               t.

        First four corners are the ones facing forward.
        The last four are the ones facing backwards.
        """
        # 3D bounding box corners. (Convention: x points forward, y to the left, z up.)
        x_corners = self.length / 2 * np.array([1, 1, 1, 1, -1, -1, -1, -1])
        y_corners = self.width / 2 * np.array([1, -1, -1, 1, 1, -1, -1, 1])
        z_corners = self.height / 2 * np.array([1, 1, -1, -1, 1, 1, -1, -1])
        corners_object_frame = np.vstack((x_corners, y_corners, z_corners)).T

        egovehicle_SE3_object = SE3(rotation=quat2rotmat(self.quaternion), translation=self.translation)
        corners_egovehicle_frame = egovehicle_SE3_object.transform_point_cloud(corners_object_frame)
        return corners_egovehicle_frame
Exemplo n.º 6
0
def visualize_ground_lidar_pts(log_id: str, dataset_dir: str,
                               experiment_prefix: str):
    """Process a log by drawing the LiDAR returns that are classified as belonging
    to the ground surface in a red to green colormap in the image.

    Args:
        log_id: The ID of a log
        dataset_dir: Where the dataset is stored
        experiment_prefix: Output prefix
    """
    sdb = SynchronizationDB(dataset_dir, collect_single_log_id=log_id)

    city_info_fpath = f"{dataset_dir}/{log_id}/city_info.json"
    city_info = read_json_file(city_info_fpath)
    city_name = city_info["city_name"]
    avm = ArgoverseMap()

    ply_fpaths = sorted(glob.glob(f"{dataset_dir}/{log_id}/lidar/PC_*.ply"))

    for i, ply_fpath in enumerate(ply_fpaths):
        if i % 500 == 0:
            print(f"\tOn file {i} of {log_id}")
        lidar_timestamp_ns = ply_fpath.split("/")[-1].split(".")[0].split(
            "_")[-1]

        pose_fpath = f"{dataset_dir}/{log_id}/poses/city_SE3_egovehicle_{lidar_timestamp_ns}.json"
        if not Path(pose_fpath).exists():
            continue

        pose_data = read_json_file(pose_fpath)
        rotation = np.array(pose_data["rotation"])
        translation = np.array(pose_data["translation"])
        city_to_egovehicle_se3 = SE3(rotation=quat2rotmat(rotation),
                                     translation=translation)

        lidar_pts = load_ply(ply_fpath)

        lidar_timestamp_ns = int(lidar_timestamp_ns)
        draw_ground_pts_in_image(
            sdb,
            lidar_pts,
            city_to_egovehicle_se3,
            avm,
            log_id,
            lidar_timestamp_ns,
            city_name,
            dataset_dir,
            experiment_prefix,
        )

    for camera_name in CAMERA_LIST:
        if "stereo" in camera_name:
            fps = 5
        else:
            fps = 10
        cmd = f"ffmpeg -r {fps} -f image2 -i '{experiment_prefix}_ground_viz/{log_id}/{camera_name}/%*.jpg' {experiment_prefix}_ground_viz/{experiment_prefix}_{log_id}_{camera_name}_{fps}fps.mp4"

        print(cmd)
        run_command(cmd)
Exemplo n.º 7
0
def test_leave_only_roi_region():
    """
        test leave_only_roi_region function
        (lidar_pts,egovehicle_to_city_se3,ground_removal_method, city_name='MIA')
        """
    pc = ply_loader.load_ply(TEST_DATA_LOC / "1/lidar/PC_0.ply")
    pose_data = read_json_file(TEST_DATA_LOC / "1/poses/city_SE3_egovehicle_0.json")
    rotation = np.array(pose_data["rotation"])
    translation = np.array(pose_data["translation"])
    ego_R = quat2rotmat(rotation)
    ego_t = translation
    egovehicle_to_city_se3 = SE3(rotation=ego_R, translation=ego_t)
    pts = eval_utils.leave_only_roi_region(pc, egovehicle_to_city_se3, ground_removal_method="map")
Exemplo n.º 8
0
def test_quat2rotmat_4() -> None:
    """Test receiving a quaternion in (w, x, y, z) from an object trajectory."""
    q = np.array([
        0.0036672729619914197, -1.3748614058859026e-05,
        -0.00023389080405946338, 0.9999932480847505
    ])
    R = quat2rotmat(q)
    assert np.allclose(R, quat2rotmat_numpy(q))

    R_gt = np.array([
        [-9.99973102e-01, -7.33448997e-03, -2.92125253e-05],
        [7.33450283e-03, -9.99972993e-01, -4.67677610e-04],
        [-2.57815596e-05, -4.67879290e-04, 9.99999890e-01],
    ])
    assert np.allclose(R_gt, R)
Exemplo n.º 9
0
def test_quat2rotmat_3() -> None:
    """Test receiving a quaternion in (w, x, y, z) from a camera extrinsic matrix."""
    q = np.array([
        0.6115111374269877, -0.6173269265351116, -0.3480540121107544,
        0.3518806604959585
    ])
    R = quat2rotmat(q)
    assert np.allclose(R, quat2rotmat_numpy(q))

    R_gt = np.array([
        [5.10076811e-01, -6.31658748e-04, -8.60128623e-01],
        [8.60084113e-01, -9.82506691e-03, 5.10057631e-01],
        [-8.77300364e-03, -9.99951533e-01, -4.46825914e-03],
    ])
    assert np.allclose(R_gt, R)
Exemplo n.º 10
0
def test_quat2rotmat_2() -> None:
    """Test receiving a quaternion in (w, x, y, z) from a camera extrinsic matrix."""
    q = np.array([
        0.4962730586309743, -0.503110985154011, 0.4964713836540661,
        -0.5040918101963521
    ])
    R = quat2rotmat(q)
    assert np.allclose(R, quat2rotmat_numpy(q))

    R_gt = np.array([
        [-1.18477579e-03, 7.73955092e-04, 9.99998999e-01],
        [-9.99894783e-01, -1.44584330e-02, -1.17346213e-03],
        [1.44575103e-02, -9.99895172e-01, 7.91003660e-04],
    ])
    assert np.allclose(R_gt, R)
Exemplo n.º 11
0
def test_quat2rotmat_5() -> None:
    """Test receiving a quaternion in (w, x, y, z) from an object trajectory."""
    q = np.array([
        0.9998886199825181, -0.002544078377693514, -0.0028621717588219564,
        -0.01442509159370476
    ])
    R = quat2rotmat(q)
    assert np.allclose(R, quat2rotmat_numpy(q))

    R_gt = np.array([
        [0.99956745, 0.02886153, -0.00565031],
        [-0.02883241, 0.99957089, 0.00517016],
        [0.0057971, -0.00500502, 0.99997067],
    ])
    assert np.allclose(R_gt, R)
Exemplo n.º 12
0
def test_rotmat2quat() -> None:
    """Ensure `rotmat2quat()` correctly converts rotation matrices to scalar-first quaternions."""
    num_trials = 1000
    for trial in range(num_trials):

        # generate random rotation matrices by sampling quaternion elements from normal distribution
        # https://en.wikipedia.org/wiki/Rotation_matrix#Uniform_random_rotation_matrices

        q = np.random.randn(4)
        q /= np.linalg.norm(q)

        R = quat2rotmat(q)
        q_ = rotmat2quat(R)

        # Note: A unit quaternion multiplied by 1 or -1 represents the same 3d rotation
        # https://math.stackexchange.com/questions/2016282/negative-quaternion
        # https://math.stackexchange.com/questions/1790521/unit-quaternion-multiplied-by-1
        assert np.allclose(q, q_) or np.allclose(-q, q_)
    def get_city_to_egovehicle_se3(self, log_id: str,
                                   timestamp: int) -> Optional[SE3]:
        """
        Args:
            log_id: str, unique ID of vehicle log
            timestamp: int, timestamp of sensor observation, in nanoseconds

        Returns:
            city_to_egovehicle_se3: SE3 transformation to bring egovehicle frame point into city frame.
        """
        pose_fpath = f"{self.data_dir}/{log_id}/poses/city_SE3_egovehicle_{timestamp}.json"
        if not Path(pose_fpath).exists():
            return None
        pose_data = read_json_file(pose_fpath)
        rotation = np.array(pose_data["rotation"])
        translation = np.array(pose_data["translation"])
        city_to_egovehicle_se3 = SE3(rotation=quat2rotmat(rotation),
                                     translation=translation)
        return city_to_egovehicle_se3
Exemplo n.º 14
0
def get_city_SE3_egovehicle_at_sensor_t(sensor_timestamp: int, dataset_dir: str, log_id: str) -> Optional[SE3]:
    """Get transformation from ego-vehicle to city coordinates at a given timestamp.

    Args:
        sensor_timestamp: integer representing timestamp when sensor measurement captured, in nanoseconds
        dataset_dir:
        log_id: string representing unique log identifier

    Returns:
        SE3 for translating ego-vehicle coordinates to city coordinates if found, else None.
    """
    pose_fpath = f"{dataset_dir}/{log_id}/poses/city_SE3_egovehicle_{sensor_timestamp}.json"
    if not Path(pose_fpath).exists():
        logger.error(f"missing pose {sensor_timestamp}")
        return None

    pose_city_to_ego = read_json_file(pose_fpath)
    rotation = np.array(pose_city_to_ego["rotation"])
    translation = np.array(pose_city_to_ego["translation"])
    city_to_egovehicle_se3 = SE3(rotation=quat2rotmat(rotation), translation=translation)
    return city_to_egovehicle_se3
Exemplo n.º 15
0
def get_camera_extrinsic_matrix(config: Dict[str, Any]) -> np.ndarray:
    """Load camera calibration rotation and translation.

    Note that the camera calibration file contains the SE3 for sensor frame to the vehicle frame, i.e.
        pt_egovehicle = egovehicle_SE3_sensor * pt_sensor

    Then build extrinsic matrix from rotation matrix and translation, a member
    of SE3. Then we return the inverse of the SE3 transformation.

    Args:
       config: Calibration config in json, or calibration file path.

    Returns:
       Camera rotation and translation matrix.
    """
    vehicle_SE3_sensor = config["vehicle_SE3_camera_"]
    egovehicle_t_camera = np.array(vehicle_SE3_sensor["translation"])
    egovehicle_q_camera = vehicle_SE3_sensor["rotation"]["coefficients"]
    egovehicle_R_camera = quat2rotmat(egovehicle_q_camera)
    egovehicle_T_camera = SE3(rotation=egovehicle_R_camera, translation=egovehicle_t_camera)

    return egovehicle_T_camera.inverse().transform_matrix
    def as_2d_bbox(self) -> np.ndarray:
        """Construct a 2D bounding box from this label.

        Length is x, width is y, and z is height

        Alternatively could write code like::

            x_corners = l / 2 * np.array([1,  1,  1,  1, -1, -1, -1, -1])
            y_corners = w / 2 * np.array([1, -1, -1,  1,  1, -1, -1,  1])
            z_corners = h / 2 * np.array([1,  1, -1, -1,  1,  1, -1, -1])
            corners = np.vstack((x_corners, y_corners, z_corners))
        """
        bbox_object_frame = np.array([
            [self.length / 2.0, self.width / 2.0, self.height / 2.0],
            [self.length / 2.0, -self.width / 2.0, self.height / 2.0],
            [-self.length / 2.0, self.width / 2.0, self.height / 2.0],
            [-self.length / 2.0, -self.width / 2.0, self.height / 2.0],
        ])

        egovehicle_SE3_object = SE3(rotation=quat2rotmat(self.quaternion),
                                    translation=self.translation)
        bbox_in_egovehicle_frame = egovehicle_SE3_object.transform_point_cloud(
            bbox_object_frame)
        return bbox_in_egovehicle_frame
Exemplo n.º 17
0
def main(args: argparse.Namespace) -> None:
    OUTPUT_ROOT = args.argo_dir
    NUSCENES_ROOT = args.nuscenes_dir
    NUSCENES_VERSION = args.nuscenes_version

    if not os.path.exists(OUTPUT_ROOT):
        os.makedirs(OUTPUT_ROOT)

    nusc = NuScenes(version=NUSCENES_VERSION,
                    dataroot=NUSCENES_ROOT,
                    verbose=True)
    for scene in nusc.scene:
        scene_token = scene["token"]
        sample_token = scene["first_sample_token"]
        scene_path = os.path.join(OUTPUT_ROOT, scene_token)

        if not os.path.exists(scene_path):
            os.makedirs(scene_path)

        log_token = scene["log_token"]
        nusc_log = nusc.get("log", log_token)
        nusc_city = nusc_log["location"]
        with open(os.path.join(scene_path, f"city_info.json"), "w") as f:
            json.dump({"city_name": CITY_TO_ID[nusc_city]}, f)

        # Calibration info for all the sensors
        calibration_info = get_calibration_info(nusc, scene)
        calib_path = os.path.join(scene_path, f"vehicle_calibration_info.json")
        with open(calib_path, "w") as f:
            json.dump(calibration_info, f)

        while sample_token != "":
            sample = nusc.get("sample", sample_token)
            timestamp = round_to_micros(sample["timestamp"])
            tracked_labels = []

            # city_SE3_vehicle pose
            ego_pose = None

            # Copy nuscenes sensor data into argoverse format and get the pose of the vehicle in the city frame
            for sensor, sensor_token in sample["data"].items():
                if sensor in SENSOR_NAMES:
                    argo_sensor = SENSOR_NAMES[sensor]
                    output_sensor_path = os.path.join(scene_path, argo_sensor)
                    if not os.path.exists(output_sensor_path):
                        os.makedirs(output_sensor_path)
                    sensor_data = nusc.get("sample_data", sensor_token)
                    file_path = os.path.join(NUSCENES_ROOT,
                                             sensor_data["filename"])
                    if sensor == "LIDAR_TOP":
                        # nuscenes lidar data is stored as (x, y, z, intensity, ring index)
                        scan = np.fromfile(file_path, dtype=np.float32)
                        points = scan.reshape((-1, 5))

                        # Transform lidar points from point sensor frame to egovehicle frame
                        calibration = nusc.get(
                            "calibrated_sensor",
                            sensor_data["calibrated_sensor_token"])
                        egovehicle_R_lidar = quat2rotmat(
                            calibration["rotation"])
                        egovehicle_t_lidar = np.array(
                            calibration["translation"])
                        egovehicle_SE3_lidar = SE3(
                            rotation=egovehicle_R_lidar,
                            translation=egovehicle_t_lidar)
                        points_egovehicle = egovehicle_SE3_lidar.transform_point_cloud(
                            points[:, :3])

                        extract_pc(points_egovehicle, points,
                                   output_sensor_path, timestamp)
                    else:
                        shutil.copy(
                            file_path,
                            os.path.join(output_sensor_path,
                                         f"{argo_sensor}_{timestamp}.jpg"),
                        )

                    if ego_pose is None:
                        ego_pose = nusc.get("ego_pose",
                                            sensor_data["ego_pose_token"])

            # Save ego pose to json file
            poses_path = os.path.join(scene_path, f"poses")
            if not os.path.exists(poses_path):
                os.makedirs(poses_path)

            ego_pose_dict = {
                "rotation": ego_pose["rotation"],
                "translation": ego_pose["translation"],
            }
            with open(
                    os.path.join(poses_path,
                                 f"city_SE3_egovehicle_{timestamp}.json"),
                    "w") as f:
                json.dump(ego_pose_dict, f)

            # Object annotations
            labels_path = os.path.join(scene_path,
                                       f"per_sweep_annotations_amodal")
            if not os.path.exists(labels_path):
                os.makedirs(labels_path)

            for ann_token in sample["anns"]:
                annotation = nusc.get("sample_annotation", ann_token)
                city_SE3_object = SE3(
                    quat2rotmat(annotation["rotation"]),
                    np.array(annotation["translation"]),
                )
                city_SE3_egovehicle = SE3(quat2rotmat(ego_pose["rotation"]),
                                          np.array(ego_pose["translation"]))
                egovehicle_SE3_city = city_SE3_egovehicle.inverse()
                egovehicle_SE3_object = egovehicle_SE3_city.right_multiply_with_se3(
                    city_SE3_object)

                x, y, z = egovehicle_SE3_object.translation
                qw, qx, qy, qz = Quaternion(
                    matrix=egovehicle_SE3_object.rotation)
                width, length, height = annotation["size"]
                label_class = annotation["category_name"]

                tracked_labels.append({
                    "center": {
                        "x": x,
                        "y": y,
                        "z": z
                    },
                    "rotation": {
                        "x": qx,
                        "y": qy,
                        "z": qz,
                        "w": qw
                    },
                    "length":
                    length,
                    "width":
                    width,
                    "height":
                    height,
                    "track_label_uuid":
                    annotation["instance_token"],
                    "timestamp":
                    timestamp,
                    "label_class":
                    get_argo_label(label_class),
                })

            json_fpath = os.path.join(
                labels_path, f"tracked_object_labels_{timestamp}.json")
            with open(json_fpath, "w") as f:
                json.dump(tracked_labels, f)

            sample_token = sample["next"]
Exemplo n.º 18
0
def eval_tracks(
    path_tracker_output: str,
    path_dataset: _PathLike,
    d_min: float,
    d_max: float,
    out_file: TextIO,
    centroid_method: str,
) -> None:
    """Evaluate tracking output.

    Args:
        path_tracker_output: path to tracker output
        path_dataset: path to dataset
        d_min: minimum distance range
        d_max: maximum distance range
        out_file: output file object
        centroid_method: method for ground truth centroid estimation
    """
    acc = mm.MOTAccumulator(auto_id=True)

    path_track_data = sorted(glob.glob(os.fspath(path_tracker_output) + "/*"))

    log_id = pathlib.Path(path_dataset).name
    logger.info("log_id = %s", log_id)

    city_info_fpath = f"{path_dataset}/city_info.json"
    city_info = read_json_file(city_info_fpath)
    city_name = city_info["city_name"]
    logger.info("city name = %s", city_name)

    ID_gt_all: List[str] = []

    for ind_frame in range(len(path_track_data)):
        if ind_frame % 50 == 0:
            logger.info("%d/%d" % (ind_frame, len(path_track_data)))

        timestamp_lidar = int(path_track_data[ind_frame].split("/")[-1].split("_")[-1].split(".")[0])
        path_gt = os.path.join(
            path_dataset, "per_sweep_annotations_amodal", f"tracked_object_labels_{timestamp_lidar}.json"
        )

        if not os.path.exists(path_gt):
            logger.warning("Missing ", path_gt)
            continue

        gt_data = read_json_file(path_gt)

        pose_data = read_json_file(f"{path_dataset}/poses/city_SE3_egovehicle_{timestamp_lidar}.json")
        rotation = np.array(pose_data["rotation"])
        translation = np.array(pose_data["translation"])
        ego_R = quat2rotmat(rotation)
        ego_t = translation
        egovehicle_to_city_se3 = SE3(rotation=ego_R, translation=ego_t)

        pc_raw0 = load_ply(os.path.join(path_dataset, f"lidar/PC_{timestamp_lidar}.ply"))
        pc_raw_roi = leave_only_roi_region(
            pc_raw0, egovehicle_to_city_se3, ground_removal_method="no", city_name=city_name
        )

        gt: Dict[str, Dict[str, Any]] = {}
        id_gts = []
        for i in range(len(gt_data)):

            if gt_data[i]["label_class"] != "VEHICLE":
                continue

            bbox, orientation = label_to_bbox(gt_data[i])
            pc_segment = get_pc_inside_bbox(pc_raw_roi, bbox)

            center = np.array([gt_data[i]["center"]["x"], gt_data[i]["center"]["y"], gt_data[i]["center"]["z"]])
            if (
                len(pc_segment) >= min_point_num
                and bbox[3] > 0
                and in_distance_range_pose(np.zeros(3), center, d_min, d_max)
            ):
                track_label_uuid = gt_data[i]["track_label_uuid"]
                gt[track_label_uuid] = {}
                if centroid_method == "average":
                    gt[track_label_uuid]["centroid"] = pc_segment.sum(axis=0) / len(pc_segment)
                elif centroid_method == "label_center":
                    gt[track_label_uuid]["centroid"] = center

                else:
                    logger.warning("Not implemented")

                gt[track_label_uuid]["bbox"] = bbox
                gt[track_label_uuid]["orientation"] = orientation

                if track_label_uuid not in ID_gt_all:
                    ID_gt_all.append(track_label_uuid)

                id_gts.append(track_label_uuid)

        tracks: Dict[str, Dict[str, Any]] = {}
        id_tracks: List[str] = []

        track_data = read_json_file(path_track_data[ind_frame])

        for track in track_data:
            key = track["track_label_uuid"]

            if track["label_class"] != "VEHICLE" or track["height"] == 0:
                continue

            center = np.array([track["center"]["x"], track["center"]["y"], track["center"]["z"]])

            if in_distance_range_pose(np.zeros(3), center, d_min, d_max):
                tracks[key] = {}
                tracks[key]["centroid"] = center

                id_tracks.append(key)

        dists: List[List[float]] = []
        for gt_key, gt_value in gt.items():
            gt_track_data: List[float] = []
            dists.append(gt_track_data)
            for track_key, track_value in tracks.items():
                gt_track_data.append(get_distance(gt_value, track_value, "centroid"))

        acc.update(id_gts, id_tracks, dists)

    mh = mm.metrics.create()
    summary = mh.compute(
        acc,
        metrics=[
            "num_frames",
            "mota",
            "motp",
            "idf1",
            "mostly_tracked",
            "mostly_lost",
            "num_false_positives",
            "num_misses",
            "num_switches",
            "num_fragmentations",
        ],
        name="acc",
    )
    logger.info("summary = %s", summary)
    num_tracks = len(ID_gt_all)

    fn = os.path.basename(path_tracker_output)
    num_frames = summary["num_frames"][0]
    mota = summary["mota"][0] * 100
    motp = summary["motp"][0]
    idf1 = summary["idf1"][0]
    most_track = summary["mostly_tracked"][0] / num_tracks
    most_lost = summary["mostly_lost"][0] / num_tracks
    num_fp = summary["num_false_positives"][0]
    num_miss = summary["num_misses"][0]
    num_switch = summary["num_switches"][0]
    num_flag = summary["num_fragmentations"][0]

    out_string = (
        f"{fn} {num_frames} {mota:.2f} {motp:.2f} {idf1:.2f} {most_track:.2f} "
        f"{most_lost:.2f} {num_fp} {num_miss} {num_switch} {num_flag} \n"
    )
    out_file.write(out_string)
Exemplo n.º 19
0
def main(nusc: NuScenes, args: argparse.Namespace, start_index: int,
         end_index: int) -> None:
    """
    Convert sweeps and samples into (unannotated) Argoverse format. Overview of algorithm:

    1) Iterate over all scenes in the NuScenes dataset. For each scene, obtain first sample in the scene.
    2) Get the sample_data corresponding to each of the channels from the sample, and convert it to argo format.
    3) While the sample_data is not corresponding to a key_frame, get the next sample_data, and repeat step 2.
    4) Go to the next sample while we are in the same scene.
    """
    OUTPUT_ROOT = args.argo_dir
    NUSCENES_ROOT = args.nuscenes_dir
    NUSCENES_VERSION = args.nuscenes_version

    if not os.path.exists(OUTPUT_ROOT):
        os.makedirs(OUTPUT_ROOT)

    tot_scenes = len(nusc.scene)
    for scene in nusc.scene[start_index:min(end_index, tot_scenes)]:
        scene_token = scene["token"]
        sample_token = scene["first_sample_token"]
        scene_path = os.path.join(OUTPUT_ROOT, scene_token)

        if not os.path.exists(scene_path):
            os.makedirs(scene_path)

        log_token = scene["log_token"]
        nusc_log = nusc.get("log", log_token)
        nusc_city = nusc_log["location"]
        save_json_dict(os.path.join(scene_path, f"city_info.json"),
                       {"city_name": CITY_TO_ID[nusc_city]})

        # Calibration info for all the sensors
        calibration_info = get_calibration_info(nusc, scene)
        calib_path = os.path.join(scene_path, f"vehicle_calibration_info.json")
        save_json_dict(calib_path, calibration_info)

        while sample_token != "":
            sample = nusc.get("sample", sample_token)
            timestamp = round_to_micros(sample["timestamp"])
            tracked_labels = []

            # city_SE3_vehicle pose
            ego_pose = None
            nsweeps_lidar = 10
            nsweeps_cam = 6

            # Save ego pose to json file
            poses_path = os.path.join(scene_path, f"poses")
            if not os.path.exists(poses_path):
                os.makedirs(poses_path)

            # Copy nuscenes sensor data into argoverse format and get the pose of the vehicle in the city frame
            for sensor, sensor_token in sample["data"].items():
                if sensor in SENSOR_NAMES:
                    argo_sensor = SENSOR_NAMES[sensor]
                    output_sensor_path = os.path.join(scene_path, argo_sensor)
                    if not os.path.exists(output_sensor_path):
                        os.makedirs(output_sensor_path)
                    sensor_data = nusc.get("sample_data", sensor_token)
                    file_path = os.path.join(NUSCENES_ROOT,
                                             sensor_data["filename"])
                    i = 0
                    if sensor == "LIDAR_TOP":
                        # nuscenes lidar data is stored as (x, y, z, intensity, ring index)
                        while i < nsweeps_lidar and sensor_token != "":
                            sensor_data = nusc.get("sample_data", sensor_token)
                            file_path = os.path.join(NUSCENES_ROOT,
                                                     sensor_data["filename"])
                            timestamp = round_to_micros(
                                sensor_data["timestamp"])
                            # Not always exactly 10
                            if (sensor_data["is_key_frame"]
                                    and i != 0) or sample_token == "":
                                break
                            scan = np.fromfile(file_path, dtype=np.float32)
                            points = scan.reshape((-1, 5))

                            # Transform lidar points from point sensor frame to egovehicle frame
                            calibration = nusc.get(
                                "calibrated_sensor",
                                sensor_data["calibrated_sensor_token"],
                            )
                            egovehicle_R_lidar = quat2rotmat(
                                calibration["rotation"])
                            egovehicle_t_lidar = np.array(
                                calibration["translation"])
                            egovehicle_SE3_lidar = SE3(
                                rotation=egovehicle_R_lidar,
                                translation=egovehicle_t_lidar,
                            )
                            points_egovehicle = egovehicle_SE3_lidar.transform_point_cloud(
                                points[:, :3])

                            write_ply(points_egovehicle, points,
                                      output_sensor_path, timestamp)

                            if not os.path.isfile(
                                    os.path.join(
                                        poses_path,
                                        f"city_SE3_egovehicle_{timestamp}.json"
                                    )):
                                ego_pose = nusc.get(
                                    "ego_pose", sensor_data["ego_pose_token"])
                                ego_pose_dict = {
                                    "rotation": ego_pose["rotation"],
                                    "translation": ego_pose["translation"],
                                }

                                save_json_dict(
                                    os.path.join(
                                        poses_path,
                                        f"city_SE3_egovehicle_{timestamp}.json"
                                    ), ego_pose_dict)

                            sensor_token = sensor_data["next"]
                    else:
                        while i < nsweeps_cam and sensor_token != "":
                            sensor_data = nusc.get("sample_data", sensor_token)
                            file_path = os.path.join(NUSCENES_ROOT,
                                                     sensor_data["filename"])
                            timestamp = round_to_micros(
                                sensor_data["timestamp"])
                            # Not always exactly 6
                            if sensor_data["is_key_frame"] and i != 0:
                                break
                            shutil.copy(
                                file_path,
                                os.path.join(output_sensor_path,
                                             f"{argo_sensor}_{timestamp}.jpg"),
                            )
                            sensor_token = sensor_data["next"]

                            if not os.path.isfile(
                                    os.path.join(
                                        poses_path,
                                        f"city_SE3_egovehicle_{timestamp}.json"
                                    )):
                                ego_pose = nusc.get(
                                    "ego_pose", sensor_data["ego_pose_token"])
                                ego_pose_dict = {
                                    "rotation": ego_pose["rotation"],
                                    "translation": ego_pose["translation"],
                                }
                                save_json_dict(
                                    os.path.join(
                                        poses_path,
                                        f"city_SE3_egovehicle_{timestamp}.json"
                                    ), ego_pose_dict)

            sample_token = sample["next"]
Exemplo n.º 20
0
def test_invalid_quaternion_zero_norm():
    """Ensure that passing a zero-norm quaternion raises an error, as normalization would divide by 0."""
    q = np.array([0.0, 0.0, 0.0, 0.0])

    with pytest.raises(ZeroDivisionError) as e_info:
        R = quat2rotmat(q)