Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Standardize ego_dist and ego_translation in detection and tracking eval code #270

Merged
merged 1 commit into from
Jan 7, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Standardize ego_dist and ego_translation
  • Loading branch information
holger-motional committed Jan 6, 2020
commit b6eca828ba8dfc897671fa43b646e9a4dbb401b8
10 changes: 10 additions & 0 deletions python-sdk/nuscenes/eval/common/data_classes.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ def __init__(self,
size: Tuple[float, float, float] = (0, 0, 0),
rotation: Tuple[float, float, float, float] = (0, 0, 0, 0),
velocity: Tuple[float, float] = (0, 0),
ego_translation: Tuple[float, float, float] = (0, 0, 0), # Translation to ego vehicle in meters.
num_pts: int = -1): # Nbr. LIDAR or RADAR inside the box. Only for gt boxes.

# Assert data for shape and NaNs.
Expand All @@ -34,6 +35,9 @@ def __init__(self,
# Velocity can be NaN from our database for certain annotations.
assert len(velocity) == 2, 'Error: Velocity must have 2 elements!'

assert len(ego_translation) == 3, 'Error: Translation must have 3 elements!'
assert not np.any(np.isnan(ego_translation)), 'Error: Translation may not be NaN!'

assert type(num_pts) == int, 'Error: num_pts must be int!'
assert not np.any(np.isnan(num_pts)), 'Error: num_pts may not be NaN!'

Expand All @@ -43,8 +47,14 @@ def __init__(self,
self.size = size
self.rotation = rotation
self.velocity = velocity
self.ego_translation = ego_translation
self.num_pts = num_pts

@property
def ego_dist(self) -> float:
""" Compute the distance from this box to the ego vehicle in 2D. """
return np.sqrt(np.sum(np.array(self.ego_translation[:2]) ** 2))

def __repr__(self):
return str(self.serialize())

Expand Down
4 changes: 1 addition & 3 deletions python-sdk/nuscenes/eval/common/loaders.py
Original file line number Diff line number Diff line change
Expand Up @@ -195,9 +195,7 @@ def add_center_dist(nusc: NuScenes,
ego_translation = (box.translation[0] - pose_record['translation'][0],
box.translation[1] - pose_record['translation'][1],
box.translation[2] - pose_record['translation'][2])
if isinstance(box, DetectionBox):
box.ego_dist = np.sqrt(np.sum(np.array(ego_translation[:2]) ** 2))
elif isinstance(box, TrackingBox):
if isinstance(box, DetectionBox) or isinstance(box, TrackingBox):
box.ego_translation = ego_translation
else:
raise NotImplementedError
Expand Down
8 changes: 1 addition & 7 deletions python-sdk/nuscenes/eval/detection/algo.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,9 +63,7 @@ def accumulate(gt_boxes: EvalBoxes,
'scale_err': [],
'orient_err': [],
'attr_err': [],
'conf': [],
'ego_dist': [],
'vel_magn': []}
'conf': []}

# ---------------------------------------------
# Match and accumulate match data.
Expand Down Expand Up @@ -111,10 +109,6 @@ def accumulate(gt_boxes: EvalBoxes,
match_data['attr_err'].append(1 - attr_acc(gt_box_match, pred_box))
match_data['conf'].append(pred_box.detection_score)

# For debugging only.
match_data['ego_dist'].append(gt_box_match.ego_dist)
match_data['vel_magn'].append(np.sqrt(np.sum(np.array(gt_box_match.velocity) ** 2)))

else:
# No match. Mark this as a false positive.
tp.append(0)
Expand Down
12 changes: 6 additions & 6 deletions python-sdk/nuscenes/eval/detection/data_classes.py
Original file line number Diff line number Diff line change
Expand Up @@ -321,13 +321,13 @@ def __init__(self,
size: Tuple[float, float, float] = (0, 0, 0),
rotation: Tuple[float, float, float, float] = (0, 0, 0, 0),
velocity: Tuple[float, float] = (0, 0),
ego_dist: float = 0.0, # Distance to ego vehicle in meters.
ego_translation: [float, float, float] = (0, 0, 0), # Translation to ego vehicle in meters.
num_pts: int = -1, # Nbr. LIDAR or RADAR inside the box. Only for gt boxes.
detection_name: str = 'car', # The class name used in the detection challenge.
detection_score: float = -1.0, # GT samples do not have a score.
attribute_name: str = ''): # Box attribute. Each box can have at most 1 attribute.

super().__init__(sample_token, translation, size, rotation, velocity, num_pts)
super().__init__(sample_token, translation, size, rotation, velocity, ego_translation, num_pts)

assert detection_name is not None, 'Error: detection_name cannot be empty!'
assert detection_name in DETECTION_NAMES, 'Error: Unknown detection_name %s' % detection_name
Expand All @@ -339,7 +339,6 @@ def __init__(self,
assert not np.any(np.isnan(detection_score)), 'Error: detection_score may not be NaN!'

# Assign.
self.ego_dist = ego_dist
self.detection_name = detection_name
self.detection_score = detection_score
self.attribute_name = attribute_name
Expand All @@ -350,7 +349,7 @@ def __eq__(self, other):
self.size == other.size and
self.rotation == other.rotation and
self.velocity == other.velocity and
self.ego_dist == other.ego_dist and
self.ego_translation == other.ego_translation and
self.num_pts == other.num_pts and
self.detection_name == other.detection_name and
self.detection_score == other.detection_score and
Expand All @@ -364,7 +363,7 @@ def serialize(self) -> dict:
'size': self.size,
'rotation': self.rotation,
'velocity': self.velocity,
'ego_dist': self.ego_dist,
'ego_translation': self.ego_translation,
'num_pts': self.num_pts,
'detection_name': self.detection_name,
'detection_score': self.detection_score,
Expand All @@ -379,7 +378,8 @@ def deserialize(cls, content: dict):
size=tuple(content['size']),
rotation=tuple(content['rotation']),
velocity=tuple(content['velocity']),
ego_dist=0.0 if 'ego_dist' not in content else float(content['ego_dist']),
ego_translation=(0.0, 0.0, 0.0) if 'ego_translation' not in content
else tuple(content['ego_translation']),
num_pts=-1 if 'num_pts' not in content else int(content['num_pts']),
detection_name=content['detection_name'],
detection_score=-1.0 if 'detection_score' not in content else float(content['detection_score']),
Expand Down
4 changes: 2 additions & 2 deletions python-sdk/nuscenes/eval/detection/tests/test_algo.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ def random_attr():
detection_name=detection_name,
detection_score=random.random(),
attribute_name=random_attr(),
ego_dist=random.random()*10,
ego_translation=(random.random() * 10, 0, 0),
))
gt.add_boxes(str(sample_itt), this_gt)

Expand All @@ -76,7 +76,7 @@ def random_attr():
detection_name=detection_name,
detection_score=random.random(),
attribute_name=random_attr(),
ego_dist=random.random() * 10,
ego_translation=(random.random() * 10, 0, 0),
))

pred.add_boxes(str(sample_itt), this_pred)
Expand Down
13 changes: 7 additions & 6 deletions python-sdk/nuscenes/eval/detection/tests/test_loader.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,12 +88,13 @@ def test_filter_eval_boxes(self):
self.assertEqual(filtered_boxes.boxes[sample_token][1].detection_name, 'bicycle')
self.assertEqual(filtered_boxes.boxes[sample_token][1].translation[0], 68.681)

# Add another bike on the bike rack center but set the ego_dist higher than what's defined in max_dist
# Add another bike on the bike rack center,
# but set the ego_dist (derived from ego_translation) higher than what's defined in max_dist
box5 = DetectionBox(sample_token=sample_token,
translation=(683.681, 1592.002, 0.809),
size=(1, 1, 1),
detection_name='bicycle',
ego_dist=100.0)
ego_translation=(100.0, 0.0, 0.0))

eval_boxes = EvalBoxes()
eval_boxes.add_boxes(sample_token, [box1, box2, box3, box4, box5])
Expand Down Expand Up @@ -127,25 +128,25 @@ def test_filter_eval_boxes(self):
translation=(683.681, 1592.002, 0.809),
size=(1, 1, 1),
detection_name='bicycle',
ego_dist=25.0)
ego_translation=(25.0, 0.0, 0.0))

box2 = DetectionBox(sample_token=sample_token,
translation=(683.681, 1592.002, 0.809),
size=(1, 1, 1),
detection_name='motorcycle',
ego_dist=45.0)
ego_translation=(45.0, 0.0, 0.0))

box3 = DetectionBox(sample_token=sample_token,
translation=(683.681, 1592.002, 0.809),
size=(1, 1, 1),
detection_name='car',
ego_dist=45.0)
ego_translation=(45.0, 0.0, 0.0))

box4 = DetectionBox(sample_token=sample_token,
translation=(683.681, 1592.002, 0.809),
size=(1, 1, 1),
detection_name='car',
ego_dist=55.0)
ego_translation=(55.0, 0.0, 0.0))

box5 = DetectionBox(sample_token=sample_token,
translation=(683.681, 1592.002, 0.809),
Expand Down
13 changes: 2 additions & 11 deletions python-sdk/nuscenes/eval/tracking/data_classes.py
Original file line number Diff line number Diff line change
Expand Up @@ -258,16 +258,13 @@ def __init__(self,
size: Tuple[float, float, float] = (0, 0, 0),
rotation: Tuple[float, float, float, float] = (0, 0, 0, 0),
velocity: Tuple[float, float] = (0, 0),
ego_translation: [float, float, float] = (0, 0, 0), # Translation to ego vehicle in meters.
ego_translation: Tuple[float, float, float] = (0, 0, 0), # Translation to ego vehicle in meters.
num_pts: int = -1, # Nbr. LIDAR or RADAR inside the box. Only for gt boxes.
tracking_id: str = '', # Instance id of this object.
tracking_name: str = '', # The class name used in the tracking challenge.
tracking_score: float = -1.0): # Does not apply to GT.

super().__init__(sample_token, translation, size, rotation, velocity, num_pts)

assert len(ego_translation) == 3, 'Error: Translation must have 3 elements!'
assert not np.any(np.isnan(ego_translation)), 'Error: Translation may not be NaN!'
super().__init__(sample_token, translation, size, rotation, velocity, ego_translation, num_pts)

assert tracking_name is not None, 'Error: tracking_name cannot be empty!'
assert tracking_name in TRACKING_NAMES, 'Error: Unknown tracking_name %s' % tracking_name
Expand All @@ -276,16 +273,10 @@ def __init__(self,
assert not np.any(np.isnan(tracking_score)), 'Error: tracking_score may not be NaN!'

# Assign.
self.ego_translation = ego_translation
self.tracking_id = tracking_id
self.tracking_name = tracking_name
self.tracking_score = tracking_score

@ property
def ego_dist(self) -> float:
""" Compute the distance from this box to the ego vehicle in 2D. """
return np.sqrt(np.sum(np.array(self.ego_translation[:2]) ** 2))

def __eq__(self, other):
return (self.sample_token == other.sample_token and
self.translation == other.translation and
Expand Down