robolib.entities
entites.py Helpers to make various entities, like cubes, robots, meshes Import level: 3
1""" 2entites.py Helpers to make various entities, like cubes, robots, meshes 3Import level: 3 4""" 5from pathlib import Path 6from typing import Any 7import numpy as np 8from microecs import World, EntityId, ComponentType 9from robolib.utils import RlModelWithTexture, get_project_root, make_radius, ecs_data_as_np 10from robolib.components import HasModel, HasPose, HasFPV 11 12def make_nonserializable_data(components: list[ComponentType], data: dict[str, Any]) -> dict[str, np.ndarray]: 13 """ 14 Given the serializable data (e.g. from entity_to_dict()), create the live non-serializable (e.g. gpu model). 15 This is the missing link that allows us to spawn new entities (via world.add_entity). 16 """ 17 res = {} 18 for component in components: 19 if component == HasModel: 20 model = RlModelWithTexture.from_path(data["model_path"], data["texture_path"]) 21 top_left, bottom_right = model.bbox 22 res["model"] = np.array([model], "object") 23 res["model_bbox"] = np.float32([top_left, bottom_right]) 24 res["model_radius"] = np.float32([make_radius(size=bottom_right - top_left)]) 25 elif component == HasPose: 26 res["candidate_pose"] = data["pose"].copy() 27 elif component == HasFPV: 28 res["fpv_camera"] = np.array([None], "object") 29 res["fpv_data"] = np.array([None], "object") 30 res["fpv_texture"] = np.array([None], "object") 31 return res 32 33def add_entity(world: World, components: list[ComponentType], **kwargs) -> EntityId: 34 """calls world.make_entity() but only after calling make_nonserializable_data. Bridges robosim with microecs""" 35 for key in ("model_path", "texture_path"): # store portable, root-relative strings 36 if kwargs.get(key) is not None: 37 p = Path(kwargs[key]) 38 kwargs[key] = str(p.relative_to(get_project_root()) if p.is_absolute() else p) 39 kwargs = {**kwargs, **make_nonserializable_data(components, kwargs)} 40 field_dtype = {name: dt for c in components 41 for name, dt in zip(world.component_to_field_names[c], world.component_to_dtypes[c])} 42 entity_data = {k: ecs_data_as_np(v, dtype=field_dtype[k]) for k, v in kwargs.items()} 43 return world.add_entity(components, **entity_data)
def
make_nonserializable_data( components: list[type[microecs.component.Component]], data: dict[str, typing.Any]) -> dict[str, numpy.ndarray]:
13def make_nonserializable_data(components: list[ComponentType], data: dict[str, Any]) -> dict[str, np.ndarray]: 14 """ 15 Given the serializable data (e.g. from entity_to_dict()), create the live non-serializable (e.g. gpu model). 16 This is the missing link that allows us to spawn new entities (via world.add_entity). 17 """ 18 res = {} 19 for component in components: 20 if component == HasModel: 21 model = RlModelWithTexture.from_path(data["model_path"], data["texture_path"]) 22 top_left, bottom_right = model.bbox 23 res["model"] = np.array([model], "object") 24 res["model_bbox"] = np.float32([top_left, bottom_right]) 25 res["model_radius"] = np.float32([make_radius(size=bottom_right - top_left)]) 26 elif component == HasPose: 27 res["candidate_pose"] = data["pose"].copy() 28 elif component == HasFPV: 29 res["fpv_camera"] = np.array([None], "object") 30 res["fpv_data"] = np.array([None], "object") 31 res["fpv_texture"] = np.array([None], "object") 32 return res
Given the serializable data (e.g. from entity_to_dict()), create the live non-serializable (e.g. gpu model). This is the missing link that allows us to spawn new entities (via world.add_entity).
def
add_entity( world: microecs.world.World, components: list[type[microecs.component.Component]], **kwargs) -> int:
34def add_entity(world: World, components: list[ComponentType], **kwargs) -> EntityId: 35 """calls world.make_entity() but only after calling make_nonserializable_data. Bridges robosim with microecs""" 36 for key in ("model_path", "texture_path"): # store portable, root-relative strings 37 if kwargs.get(key) is not None: 38 p = Path(kwargs[key]) 39 kwargs[key] = str(p.relative_to(get_project_root()) if p.is_absolute() else p) 40 kwargs = {**kwargs, **make_nonserializable_data(components, kwargs)} 41 field_dtype = {name: dt for c in components 42 for name, dt in zip(world.component_to_field_names[c], world.component_to_dtypes[c])} 43 entity_data = {k: ecs_data_as_np(v, dtype=field_dtype[k]) for k, v in kwargs.items()} 44 return world.add_entity(components, **entity_data)
calls world.make_entity() but only after calling make_nonserializable_data. Bridges robosim with microecs