Source code for grutopia.core.robot.sensor
from abc import ABC, abstractmethod
from functools import wraps
from typing import Dict
from grutopia.core.config.robot import RobotUserConfig
from grutopia.core.config.robot.params import SensorParams
from grutopia.core.robot.robot import BaseRobot, Scene
from grutopia.core.robot.robot_model import RobotModel, SensorModel
from grutopia.core.util import log
[docs]class BaseSensor(ABC):
"""Base class of sensor."""
sensors = {}
def __init__(self, config: SensorModel, robot: BaseRobot, scene: Scene):
"""Initialize the sensor.
Args:
config (SensorModel): merged config (from user config and robot model) of the sensor.
robot (BaseRobot): robot owning the sensor.
scene (Scene): scene from isaac sim.
"""
if config.name is None:
raise ValueError('must specify sensor name.')
self.name = config.name
self.config = config
self._scene = scene
self._robot = robot
@abstractmethod
def sensor_init(self):
raise NotImplementedError()
[docs] @abstractmethod
def get_data(self) -> Dict:
"""Get data from sensor.
Returns:
Dict: data dict of sensor.
"""
raise NotImplementedError()
[docs] @classmethod
def register(cls, name: str):
"""
Register a sensor class with the given name(decorator).
Args:
name(str): name of the sensor class.
"""
def decorator(sensor_class):
cls.sensors[name] = sensor_class
@wraps(sensor_class)
def wrapped_function(*args, **kwargs):
return sensor_class(*args, **kwargs)
return wrapped_function
return decorator
[docs]def config_inject(params: SensorParams, model: SensorModel) -> SensorModel:
"""Merge sensor config from user config and robot model.
Args:
params (SensorParams): user config.
model (SensorModel): sensor config from robot model.
Returns:
SensorModel: merged sensor config.
"""
if params is None:
return model
config = model.dict()
user = params.dict()
for k, v in user.items():
if v is not None:
config[k] = v
conf = SensorModel(**config)
return conf
[docs]def create_sensors(config: RobotUserConfig, robot_model: RobotModel, robot: BaseRobot,
scene: Scene) -> Dict[str, BaseSensor]:
"""Create all sensors of one robot.
Args:
config (RobotUserConfig): user config of the robot.
robot_model (RobotModel): model of the robot.
robot (BaseRobot): robot instance.
scene (Scene): scene from isaac sim.
Returns:
Dict[str, BaseSensor]: dict of sensors with sensor name as key.
"""
sensor_map = {}
if robot_model.sensors is not None:
available_sensors = {a.name: a for a in robot_model.sensors}
for sensor_name, sensor in available_sensors.items():
if sensor.type not in BaseSensor.sensors:
raise KeyError(f'unknown sensor type "{sensor.type}"')
sensor_cls = BaseSensor.sensors[sensor.type]
# Find if user param exists for this sensor.
param = None
if config.sensor_params is not None:
for p in config.sensor_params:
if p.name == sensor_name:
param = p
break
sensor_ins = sensor_cls(config=config_inject(param, sensor), robot=robot, name=sensor_name, scene=scene)
sensor_map[sensor_name] = sensor_ins
sensor_ins.sensor_init()
log.debug(f'==================== {sensor_name} loaded==========================')
return sensor_map