Skip to content

Commit

Permalink
refacor: refactor viewer class
Browse files Browse the repository at this point in the history
Signed-off-by: ktro2828 <[email protected]>
  • Loading branch information
ktro2828 committed Nov 21, 2024
1 parent 68ecfcc commit ac205cd
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 54 deletions.
2 changes: 1 addition & 1 deletion t4_devkit/tier4.py
Original file line number Diff line number Diff line change
Expand Up @@ -904,7 +904,7 @@ def _init_viewer(
else None
)

viewer = Tier4Viewer(application_id, cameras=cameras, without_3d=not render_3d, spawn=spawn)
viewer = Tier4Viewer(application_id, cameras=cameras, with_3d=render_3d, spawn=spawn)

if render_annotation:
viewer = viewer.with_labels(self._label2id)
Expand Down
97 changes: 44 additions & 53 deletions t4_devkit/viewer/viewer.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,9 +71,9 @@ class Tier4Viewer:
def __init__(
self,
app_id: str,
cameras: Sequence[str] | None = None,
*,
without_3d: bool = False,
cameras: Sequence[str] | None = None,
with_3d: bool = True,
spawn: bool = True,
) -> None:
"""Construct a new object.
Expand All @@ -82,7 +82,7 @@ def __init__(
app_id (str): Application ID.
cameras (Sequence[str] | None, optional): Sequence of camera names.
If `None`, any 2D spaces will not be visualized.
without_3d (bool, optional): Whether to render objects without the 3D space.
with_3d (bool, optional): Whether to render objects with the 3D space.
spawn (bool, optional): Whether to spawn the viewer.
Examples:
Expand All @@ -92,16 +92,18 @@ def __init__(
# Rendering 3D space only
>>> viewer = Tier4Viewer("myapp")
# Rendering 2D space only
>>> viewer = Tier4Viewer("myapp", cameras=["camera0", "camera1"], without_3d=True)
>>> viewer = Tier4Viewer("myapp", cameras=["camera0", "camera1"], with_3d=False)
"""
self.app_id = app_id
self.without_3d = without_3d
self.cameras = cameras
self.with_3d = with_3d
self.with_2d = self.cameras is not None

assert self.cameras is not None or not without_3d
if not self.with_3d and not self.with_2d:
raise ValueError("At least one of 3D or 2D spaces must be rendered.")

view_container = []
if not without_3d:
view_container: list[rrb.Container | rrb.SpaceView] = []
if self.with_3d:
view_container.extend(
[
rrb.Horizontal(
Expand All @@ -112,7 +114,7 @@ def __init__(
]
)

if self.cameras is not None:
if self.with_2d:
camera_space_views = [
rrb.Spatial2DView(name=name, origin=format_entity(self.ego_entity, name))
for name in self.cameras
Expand Down Expand Up @@ -169,12 +171,17 @@ def save(self, save_dir: str) -> None:
rr.save(filepath, default_blueprint=self.blueprint)

def render_box3ds(self, seconds: float, boxes: Sequence[Box3D]) -> None:
"""Render 3D boxes.
"""Render 3D boxes. Note that if the viewer initialized with `with_3d=False`,
no 3D box will be rendered.
Args:
seconds (float): Timestamp in [sec].
boxes (Sequence[Box3D]): Sequence of `Box3D`s.
"""
if not self.with_3d:
warnings.warn("There is no camera space.")
return

rr.set_time_seconds(self.timeline, seconds)

box_data: dict[str, BoxData3D] = {}
Expand All @@ -197,13 +204,14 @@ def render_box3ds(self, seconds: float, boxes: Sequence[Box3D]) -> None:
)

def render_box2ds(self, seconds: float, boxes: Sequence[Box2D]) -> None:
"""Render 2D boxes.
"""Render 2D boxes. Note that if the viewer initialized without `cameras=None`,
no 2D box will be rendered.
Args:
seconds (float): Timestamp in [sec].
boxes (Sequence[Box2D]): Sequence of `Box2D`s.
"""
if self.cameras is None:
if not self.with_2d:
warnings.warn("There is no camera space.")
return

Expand Down Expand Up @@ -240,7 +248,7 @@ def render_segmentation2d(
class_ids (Sequence[int]): Sequence of label ids.
uuids (Sequence[str | None] | None, optional): Sequence of each instance ID.
"""
if self.cameras is None or camera not in self.cameras:
if not self.with_2d or camera not in self.cameras:
warnings.warn(f"There is no camera space: {camera}")
return

Expand All @@ -265,6 +273,7 @@ def render_pointcloud(self, seconds: float, channel: str, pointcloud: PointCloud
channel (str): Name of the pointcloud sensor channel.
pointcloud (PointCloudLike): Inherence object of `PointCloud`.
"""
# TODO(ktro2828): add support of rendering pointcloud on images
rr.set_time_seconds(self.timeline, seconds)

colors = distance_color(np.linalg.norm(pointcloud.points[:3].T, axis=1))
Expand All @@ -284,7 +293,7 @@ def render_image(self, seconds: float, camera: str, image: str | NDArrayU8) -> N
camera (str): Name of the camera channel.
image (str | NDArrayU8): Image tensor or path of the image file.
"""
if self.cameras is None or camera not in self.cameras:
if not self.with_2d or camera not in self.cameras:
warnings.warn(f"There is no camera space: {camera}")
return

Expand All @@ -306,25 +315,13 @@ def _render_ego_with_schema(self, ego_pose: EgoPose) -> None:
Args:
ego_pose (EgoPose): `EgoPose` object.
"""
rr.set_time_seconds(self.timeline, us2sec(ego_pose.timestamp))

rotation_xyzw = np.roll(ego_pose.rotation.q, shift=-1)
rr.log(
self.ego_entity,
rr.Transform3D(
translation=ego_pose.translation,
rotation=rr.Quaternion(xyzw=rotation_xyzw),
relation=rr.TransformRelation.ParentFromChild,
),
self._render_ego_without_schema(
seconds=us2sec(ego_pose.timestamp),
translation=ego_pose.translation,
rotation=ego_pose.rotation,
geocoordinate=ego_pose.geocoordinate,
)

if ego_pose.geocoordinate is not None:
latitude, longitude, _ = ego_pose.geocoordinate
rr.log(
self.geocoordinate_entity,
rr.GeoPoints(lat_lon=(latitude, longitude), radii=rr.Radius.ui_points(10.0)),
)

@render_ego.register
def _render_ego_without_schema(
self,
Expand All @@ -333,6 +330,16 @@ def _render_ego_without_schema(
rotation: RotationType,
geocoordinate: GeoCoordinateType | None = None,
) -> None:
"""Render an ego pose.
Args:
seconds (float): Timestamp in [sec].
translation (TranslationType): 3D position in the map coordinate system
, in the order of (x, y, z) in [m].
rotation (RotationType): Rotation in the map coordinate system.
geocoordinate (GeoCoordinateType | None, optional): Coordinates in the WGS 84
reference ellipsoid (latitude, longitude, altitude) in degrees and meters.
"""
rr.set_time_seconds(self.timeline, seconds)

rotation_xyzw = np.roll(rotation.q, shift=-1)
Expand Down Expand Up @@ -368,24 +375,14 @@ def _render_calibration_with_schema(
sensor (Sensor): `Sensor` object.
calibration (CalibratedSensor): `CalibratedSensor` object.
"""
rotation_xyzw = np.roll(calibration.rotation.q, shift=-1)

rr.log(
format_entity(self.ego_entity, sensor.channel),
rr.Transform3D(
translation=calibration.translation,
rotation=rr.Quaternion(xyzw=rotation_xyzw),
),
static=True,
self._render_calibration_without_schema(
channel=sensor.channel,
modality=sensor.modality,
translation=calibration.translation,
rotation=calibration.rotation,
camera_intrinsic=calibration.camera_intrinsic,
)

if sensor.modality == SensorModality.CAMERA:
rr.log(
format_entity(self.ego_entity, sensor.channel),
rr.Pinhole(image_from_camera=calibration.camera_intrinsic),
static=True,
)

@render_calibration.register
def _render_calibration_without_schema(
self,
Expand Down Expand Up @@ -419,9 +416,3 @@ def _render_calibration_without_schema(
rr.Pinhole(image_from_camera=camera_intrinsic),
static=True,
)
if modality == SensorModality.CAMERA:
rr.log(
format_entity(self.ego_entity, channel),
rr.Pinhole(image_from_camera=camera_intrinsic),
static=True,
)

0 comments on commit ac205cd

Please sign in to comment.