Skip to content

Commit

Permalink
Set default sensor (camera) offset to avoid the camera being inside t…
Browse files Browse the repository at this point in the history
…he objects (#658)

* Set default sensor (camera) offset to avoid the camera being inside the objects

* update docstring
  • Loading branch information
pengzhenghao authored Feb 23, 2024
1 parent 6504392 commit 5ca5bb8
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 15 deletions.
31 changes: 24 additions & 7 deletions metadrive/component/sensors/base_camera.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import numpy as np
from typing import Union
from panda3d.core import NodePath

import cv2
import numpy as np
from panda3d.core import NodePath

from metadrive.component.sensors.base_sensor import BaseSensor
from metadrive.utils.cuda import check_cudart_err

Expand All @@ -17,6 +19,7 @@
from panda3d.core import Vec3

from metadrive.engine.core.image_buffer import ImageBuffer
from metadrive import constants


class BaseCamera(ImageBuffer, BaseSensor):
Expand Down Expand Up @@ -118,7 +121,7 @@ def perceive(
self, to_float=True, new_parent_node: Union[NodePath, None] = None, position=None, hpr=None
) -> np.ndarray:
"""
When clip is set to False, the image will be represented by unit8 with component value ranging from [0-255].
When to_float is set to False, the image will be represented by unit8 with component value ranging from [0-255].
Otherwise, it will be float type with component value ranging from [0.-1.]. By default, the reset parameters are
all None. In this case, the camera will render the result with poses and position set by track() function.
Expand All @@ -127,15 +130,29 @@ def perceive(
camera to capture a new image and return the camera to the owner. This usually happens when using one camera to
render multiple times from different positions and poses.
new_parent_node should be a NodePath like object.origin and vehicle.origin or self.engine.origin, which
means the world origin. When new_parent_node is set, both position and hpr have to be set as well. The position
new_parent_node should be a NodePath like object.origin or vehicle.origin or self.engine.origin, which
means the world origin. When new_parent_node is set, both position and hpr have to be set as well. The position
and hpr are all 3-dim vector representing:
1) the relative position to the reparent node
2) the heading/pitch/roll of the sensor
"""
Args:
to_float: When to_float is set to False, the image will be represented by unit8 with component value ranging
from [0-255]. Otherwise, it will be float type with component value ranging from [0.-1.].
new_parent_node: new_parent_node should be a NodePath like object.origin or vehicle.origin or
self.engine.origin, which means the world origin. When new_parent_node is set, both position and hpr
have to be set as well. The position and hpr are all 3-dim vector representing:
position: the relative position to the reparent node
hpr: the heading/pitch/roll of the sensor
Return:
Array representing the image.
"""
if new_parent_node:
assert position and hpr, "When new_parent_node is set, both position and hpr should be set as well"
if position is None:
position = constants.DEFAULT_SENSOR_OFFSET
if hpr is None:
position = constants.DEFAULT_SENSOR_HPR

# return camera to original state
original_object = self.cam.getParent()
Expand Down
4 changes: 4 additions & 0 deletions metadrive/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -542,3 +542,7 @@ class CameraTagStateKey:
RGB = "rgb"
Depth = "depth"
Semantic = "semantic"


DEFAULT_SENSOR_OFFSET = (0., 0.8, 1.5)
DEFAULT_SENSOR_HPR = (0., 0.0, 0.0)
22 changes: 19 additions & 3 deletions metadrive/engine/core/main_camera.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
except ImportError:
_cuda_enable = False
from metadrive.component.sensors.base_sensor import BaseSensor
from metadrive import constants


class MainCamera(BaseSensor):
Expand Down Expand Up @@ -451,7 +452,7 @@ def perceive(
self, to_float=True, new_parent_node: Union[NodePath, None] = None, position=None, hpr=None
) -> np.ndarray:
"""
When clip is set to False, the image will be represented by unit8 with component value ranging from [0-255].
When to_float is set to False, the image will be represented by unit8 with component value ranging from [0-255].
Otherwise, it will be float type with component value ranging from [0.-1.]. By default, the reset parameters are
all None. In this case, the camera will render the result with poses and position set by track() function.
Expand All @@ -460,15 +461,30 @@ def perceive(
camera to capture a new image and return the camera to the owner. This usually happens when using one camera to
render multiple times from different positions and poses.
new_parent_node should be a NodePath like object.origin and vehicle.origin or self.engine.origin, which
new_parent_node should be a NodePath like object.origin or vehicle.origin or self.engine.origin, which
means the world origin. When new_parent_node is set, both position and hpr have to be set as well. The position
and hpr are all 3-dim vector representing:
1) the relative position to the reparent node
2) the heading/pitch/roll of the sensor
Args:
to_float: When to_float is set to False, the image will be represented by unit8 with component value ranging
from [0-255]. Otherwise, it will be float type with component value ranging from [0.-1.].
new_parent_node: new_parent_node should be a NodePath like object.origin or vehicle.origin or
self.engine.origin, which means the world origin. When new_parent_node is set, both position and hpr
have to be set as well. The position and hpr are all 3-dim vector representing:
position: the relative position to the reparent node
hpr: the heading/pitch/roll of the sensor
Return:
Array representing the image.
"""

if new_parent_node:
assert position and hpr, "When new_parent_node is set, both position and hpr should be set as well"
if position is None:
position = constants.DEFAULT_SENSOR_OFFSET
if hpr is None:
position = constants.DEFAULT_SENSOR_HPR

# return camera to original state
original_object = self.camera.getParent()
Expand Down
12 changes: 7 additions & 5 deletions metadrive/envs/base_env.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
import logging
from metadrive.obs.image_obs import ImageStateObservation
from metadrive.obs.state_obs import LidarStateObservation
import time
from collections import defaultdict
from typing import Union, Dict, AnyStr, Optional, Tuple, Callable
Expand All @@ -9,6 +7,7 @@
import numpy as np
from panda3d.core import PNMImage

from metadrive import constants
from metadrive.component.sensors.base_camera import BaseCamera
from metadrive.component.sensors.dashboard import DashBoard
from metadrive.component.sensors.distance_detector import LaneLineDetector, SideDetector
Expand All @@ -22,8 +21,10 @@
from metadrive.manager.agent_manager import VehicleAgentManager
from metadrive.manager.record_manager import RecordManager
from metadrive.manager.replay_manager import ReplayManager
from metadrive.obs.observation_base import DummyObservation
from metadrive.obs.image_obs import ImageStateObservation
from metadrive.obs.observation_base import BaseObservation
from metadrive.obs.observation_base import DummyObservation
from metadrive.obs.state_obs import LidarStateObservation
from metadrive.policy.env_input_policy import EnvInputPolicy
from metadrive.scenario.utils import convert_recorded_scenario_exported
from metadrive.utils import Config, merge_dicts, get_np_random, concat_step_infos
Expand Down Expand Up @@ -434,7 +435,7 @@ def step(self, actions: Union[Union[np.ndarray, list], Dict[AnyStr, Union[list,
return self._get_step_return(actions, engine_info=engine_info) # collect observation, reward, termination

def _preprocess_actions(self, actions: Union[np.ndarray, Dict[AnyStr, np.ndarray], int]) \
-> Union[np.ndarray, Dict[AnyStr, np.ndarray], int]:
-> Union[np.ndarray, Dict[AnyStr, np.ndarray], int]:
if not self.is_multi_agent:
actions = {v_id: actions for v_id in self.agents.keys()}
else:
Expand Down Expand Up @@ -887,7 +888,8 @@ def switch_to_third_person_view(self):
self.main_camera.track(current_track_agent)
for name, sensor in self.engine.sensors.items():
if hasattr(sensor, "track") and name != "main_camera":
sensor.track(current_track_agent.origin, [0., 0.8, 1.5], [0, 0.59681, 0])
camera_video_posture = [0, 0.59681, 0]
sensor.track(current_track_agent.origin, constants.DEFAULT_SENSOR_OFFSET, camera_video_posture)
return

def next_seed_reset(self):
Expand Down

0 comments on commit 5ca5bb8

Please sign in to comment.