-
Notifications
You must be signed in to change notification settings - Fork 704
Open
Description
Hi,
For some personal work, I was trying to figure out the range of vertical angle each channel spans. I wrote a simple script in which for a given point
- field of View (Vertical): +10.67° to -30.67° (41.33°)
- Angular Resolution (Vertical): 1.33.
Here is result for some of channels -
{
"0": {
"min_theta": -4.142869472503662,
"max_theta": 4.17689847946167
},
"1": {
"min_theta": -4.026743412017822,
"max_theta": 4.176898002624512
},
"2": {
"min_theta": -4.027475833892822,
"max_theta": 4.17689847946167
},
"3": {
"min_theta": -4.273198127746582,
"max_theta": 4.176898002624512
},
"4": {
"min_theta": -4.0284247398376465,
"max_theta": 4.176896572113037
},
}Can someone tell me what is going wrong here? I expected the ranges should go monotonically from -30.67° to +10.67°
Here is my angle estimation code -
import os
import json
import random
import numpy as np
from tqdm import tqdm
from pyquaternion import Quaternion
from nuscenes.nuscenes import NuScenes
from nuscenes.utils.geometry_utils import transform_matrix
DATA_ROOT = "/home/saksham/samsad/mtech-project/datasets/nuscenes"
OUTPUT_DIR = os.path.dirname(os.path.abspath(__file__))
VERSION = "v1.0-mini"
RANDOM_SEED = 42
def load_lidar_with_ring(path):
points = np.fromfile(path, dtype=np.float32).reshape(-1, 5)
return points # x,y,z,intensity,ring
def transform_to_lidar_frame(nusc, token):
sd = nusc.get("sample_data", token)
cs = nusc.get("calibrated_sensor", sd["calibrated_sensor_token"])
ep = nusc.get("ego_pose", sd["ego_pose_token"])
filepath = os.path.join(DATA_ROOT, sd["filename"])
pts = load_lidar_with_ring(filepath)
xyz = pts[:, :3]
ones = np.ones((xyz.shape[0], 1))
xyz_h = np.hstack((xyz, ones))
# Global → ego
global_from_ego = transform_matrix(ep["translation"], Quaternion(ep["rotation"]), inverse=False)
ego_from_global = np.linalg.inv(global_from_ego)
xyz_h = xyz_h @ ego_from_global.T
# Ego → lidar
ego_from_lidar = transform_matrix(cs["translation"], Quaternion(cs["rotation"]), inverse=False)
lidar_from_ego = np.linalg.inv(ego_from_lidar)
xyz_h = xyz_h @ lidar_from_ego.T
pts[:, :3] = xyz_h[:, :3]
return pts
def compute_vertical_angles(xyz):
x, y, z = xyz[:, 0], xyz[:, 1], xyz[:, 2]
theta = np.arctan2(z, np.sqrt(x**2 + y**2))
return np.degrees(theta)
def get_all_lidar_tokens(nusc):
visited = set()
infos = []
for sample in nusc.sample:
token = sample["data"]["LIDAR_TOP"]
while token != "":
sd = nusc.get("sample_data", token)
fname = sd["filename"]
if fname not in visited:
visited.add(fname)
infos.append((token, fname))
token = sd["next"]
return infos
def split_train_test(infos, train_ratio=0.8):
random.seed(RANDOM_SEED)
random.shuffle(infos)
split = int(len(infos) * train_ratio)
return infos[:split], infos[split:]
def estimate_channel_ranges(nusc, train_infos):
channel_min = {}
channel_max = {}
for token, fname in tqdm(train_infos, desc="Processing train lidar files"):
pts = transform_to_lidar_frame(nusc, token)
xyz = pts[:, :3]
channel = pts[:, 4].astype(int)
theta = compute_vertical_angles(xyz)
for ch in np.unique(channel):
ch_angles = theta[channel == ch]
if ch not in channel_min:
channel_min[ch] = np.min(ch_angles)
channel_max[ch] = np.max(ch_angles)
else:
channel_min[ch] = min(channel_min[ch], np.min(ch_angles))
channel_max[ch] = max(channel_max[ch], np.max(ch_angles))
return {
int(ch): {
"min_theta": float(channel_min[ch]),
"max_theta": float(channel_max[ch])
}
for ch in sorted(channel_min.keys())
}
def save_split_files(train_infos, test_infos):
with open(os.path.join(OUTPUT_DIR, "train.txt"), "w") as f:
for _, fname in train_infos:
f.write(os.path.basename(fname) + "\n")
with open(os.path.join(OUTPUT_DIR, "test.txt"), "w") as f:
for _, fname in test_infos:
f.write(os.path.basename(fname) + "\n")
def save_json(data):
with open(os.path.join(OUTPUT_DIR, "channel_angle_ranges.json"), "w") as f:
json.dump(data, f, indent=4)
def main():
print("Loading nuScenes...")
nusc = NuScenes(version=VERSION, dataroot=DATA_ROOT, verbose=True)
print("Collecting unique lidar sweeps and samples...")
infos = get_all_lidar_tokens(nusc)
print(f"Total unique lidar files: {len(infos)}")
train_infos, test_infos = split_train_test(infos)
print(f"Train: {len(train_infos)} | Test: {len(test_infos)}")
save_split_files(train_infos, test_infos)
print("Estimating per-channel vertical angle ranges...")
channel_ranges = estimate_channel_ranges(nusc, train_infos)
save_json(channel_ranges)
print("Done. Outputs saved in script directory.")
if __name__ == "__main__":
main()Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels