robolib.components

components.py - The basic componens that the simulator supports. New custom ones can be added in server or plugins. Import level: 1

  1"""
  2components.py - The basic componens that the simulator supports. New custom ones can be added in server or plugins.
  3Import level: 1
  4"""
  5# pylint: disable=missing-class-docstring
  6
  7from enum import IntEnum, StrEnum
  8from microecs import Component, zeros, f32, i32, boolf, obj
  9import numpy as np
 10
 11# constants copied from constants.py. TODO: we may need to reorganize things. Components should be level 1 - no imports
 12# ColliderKinds or PhysicsLevel should not be part of this. Components should just be plain data
 13# Moreover, physics module shouldn't import components - it should be pure math... that is systems' jobs (to call it)
 14LVL2_MAX_ACCELERATIONS = (3, 3, 3, 3, 3, 3) # [m/s^2]
 15LVL2_DRAG_COEFF = 1 # [m/s^2] snappy drag coefficient: so it goes to 0 quite fast
 16LVL1_MAX_VELOCITIES = (4.2, 4.2, 4.2, 1.8, 1.8, 1.8) # [m/s, rad/s]
 17
 18# tags (no fields), e.g. GroundFloor
 19
 20class GroundFloor(Component):
 21    """component used to tag the floor so we don't render it in collision mode"""
 22
 23ROBOLIB_TAGS = [GroundFloor]
 24
 25# components (data only)
 26
 27class HasTag(Component):
 28    tag: np.ndarray = obj(
 29        shape=(1, ), serializable=True, default=None,
 30        comment="The tag of this entity (e.g. robot, ground floor etc.)")
 31
 32class HasModel(Component):
 33    model_path: np.ndarray = obj(
 34        shape=(1, ), serializable=True, default=None,
 35        comment="The model path on the disk")
 36    texture_path: np.ndarray = obj(
 37        shape=(1, ), serializable=True, default=None,
 38        comment="The texture path on the disk (optional)")
 39    scale: np.ndarray = f32(
 40        shape=(1, ), serializable=True, default=None,
 41        comment="The scale of the model to project in world space")
 42    model: np.ndarray = obj(
 43        shape=(1, ), serializable=False, default=None,
 44        comment="The model object (not serializable)")
 45    model_bbox: np.ndarray = f32(
 46        shape=(2, 3), serializable=False, default=zeros,
 47        comment="The bbox of the object derived from the model itself")
 48    model_radius: np.ndarray = f32(
 49        shape=(1, ), serializable=False, default=zeros,
 50        comment="The radius of the model, derived from the model itself")
 51
 52# State/Motion-related components
 53
 54class HasPose(Component):
 55    pose: np.ndarray = f32(
 56        shape=(4, 4), serializable=True, default=np.eye(4, dtype="float32"),
 57        comment="The pose of the entity (rotation & translation) as 4x4 homogeneous matrix")
 58    candidate_pose: np.ndarray = f32(
 59        shape=(4, 4), serializable=False, default=None,
 60        comment=("The future (t+1) 4x4 pose. Used for post-collision. "
 61                "Needs to be updated at each frame (system)."))
 62
 63# network or dynamic objects
 64
 65class HasFPV(Component):
 66    fpv_camera: np.ndarray = obj(
 67        shape=(1, ), serializable=False, default=None,
 68        comment="The FPV camera object, instantiated in the server.")
 69    fpv_data: np.ndarray = obj(
 70        shape=(1, ), serializable=False, default=None,
 71        comment="The frame currently displayed in the world in this FPV camera.")
 72    fpv_texture: np.ndarray = obj(
 73        shape=(1, ), serializable=False, default=None,
 74        comment="The texture where the fpv_data of this camera is rendered")
 75
 76# movable objects
 77
 78class PhysicsLevel(IntEnum):
 79    LEVEL_1 = 1
 80    LEVEL_2 = 2
 81
 82class HasMotion(Component):
 83    """Motion component: Adding this to an entity makes it movable. It goes into the physics loop, can be moved via
 84    motion_input (6dof input vector), and adheres to a physics level (velocity only, acceleration etc.)"""
 85    velocity: np.ndarray = f32(
 86        shape=(6, ), serializable=True, default=zeros,
 87        comment=("The committed velocity of this entity. 6DoF: (vx, vy, vz, wx, wy, wz). "
 88                "Owned by the physics system (written at commit), not an input surface."))
 89    acceleration: np.ndarray = f32(
 90        shape=(6, ), serializable=True, default=zeros,
 91        comment=("The committed acceleration of this entity. 6DoF: (ax, ay, az, wax, way, waz). "
 92                "Owned by the physics system (written at commit), not an input surface."))
 93    motion_input: np.ndarray = f32(
 94        shape=(6, ), serializable=False, default=zeros,
 95        comment=("The motion input (to change vel/acc) of this entity. "
 96                "Usually sent from keyboard or the entity's channel (tcp)"))
 97    physics_level: np.ndarray = i32(shape=(1, ), serializable=True, default=2, comment="The physics level")
 98    max_velocities: np.ndarray = f32(
 99        shape=(6, ), serializable=True, default=LVL1_MAX_VELOCITIES,
100        comment="The maximum velocities for physics_level 1 (level-1 cap; unused at level 2)")
101    max_accelerations: np.ndarray = f32(
102        shape=(6, ), serializable=True, default=LVL2_MAX_ACCELERATIONS,
103        comment="The maximum accelerations for physics_level 2 (unused at level 1)")
104    drag_coefficient: np.ndarray = f32(
105        shape=(1, ), serializable=True, default=LVL2_DRAG_COEFF,
106        comment="The drag coefficient for physics_level 2 (unused at level 1)")
107    candidate_velocity: np.ndarray = f32(
108        shape=(6, ), serializable=False, default=zeros,
109        comment=("The future (t+1) velocity. Used for collision checking in the physics system "
110                "before updating pose. Internal staging buffer: not serialized, recomputed every tick by "
111                "the physics system, and overwritten by it (write it in a per-tick system, not once)"))
112    candidate_acceleration: np.ndarray = f32(
113        shape=(6, ), serializable=False, default=zeros,
114        comment=("The future (t+1) acceleration. Used for collision checking in the physics system "
115                "before updating pose. Internal staging buffer: not serialized, recomputed every tick by "
116                "the physics system, and overwritten by it (write it in a per-tick system, not once)"))
117
118# collision
119
120class ColliderKinds(StrEnum):
121    """The types of colliders. Used by HasCollision components."""
122    SPHERE = "SPHERE"
123    AABB = "AABB"
124
125class HasCollision(Component):
126    is_colliding: np.ndarray = boolf(
127        shape=(1, ), serializable=False, default=zeros,
128        comment="Whether this entity is colliding now with something")
129    collider_kind: np.ndarray = obj(
130        shape=(1, ), serializable=True, default=None,
131        comment="The collider kind. see ColliderKinds enum for options.")
132    collider_bbox: np.ndarray = f32(
133        shape=(2, 3), serializable=False, default=zeros,
134        comment="Note: already in world space (scaled) by physics system")
135    collider_radii: np.ndarray = f32(
136        shape=(1, ), serializable=False, default=zeros,
137        comment="Note: already in world space (scaled) by physics system")
138
139ROBOLIB_COMPONENTS = [HasTag, HasModel, HasPose, HasFPV, # model/object
140                      HasMotion, HasCollision,           # motion/physics
141                      *ROBOLIB_TAGS]                     # tags, e.g. GroundFloor
LVL2_MAX_ACCELERATIONS = (3, 3, 3, 3, 3, 3)
LVL2_DRAG_COEFF = 1
LVL1_MAX_VELOCITIES = (4.2, 4.2, 4.2, 1.8, 1.8, 1.8)
class GroundFloor(microecs.component.Component):
21class GroundFloor(Component):
22    """component used to tag the floor so we don't render it in collision mode"""

component used to tag the floor so we don't render it in collision mode

ROBOLIB_TAGS = [<class 'GroundFloor'>]
class HasTag(microecs.component.Component):
28class HasTag(Component):
29    tag: np.ndarray = obj(
30        shape=(1, ), serializable=True, default=None,
31        comment="The tag of this entity (e.g. robot, ground floor etc.)")
HasTag(*, tag: numpy.ndarray)
tag: numpy.ndarray
class HasModel(microecs.component.Component):
33class HasModel(Component):
34    model_path: np.ndarray = obj(
35        shape=(1, ), serializable=True, default=None,
36        comment="The model path on the disk")
37    texture_path: np.ndarray = obj(
38        shape=(1, ), serializable=True, default=None,
39        comment="The texture path on the disk (optional)")
40    scale: np.ndarray = f32(
41        shape=(1, ), serializable=True, default=None,
42        comment="The scale of the model to project in world space")
43    model: np.ndarray = obj(
44        shape=(1, ), serializable=False, default=None,
45        comment="The model object (not serializable)")
46    model_bbox: np.ndarray = f32(
47        shape=(2, 3), serializable=False, default=zeros,
48        comment="The bbox of the object derived from the model itself")
49    model_radius: np.ndarray = f32(
50        shape=(1, ), serializable=False, default=zeros,
51        comment="The radius of the model, derived from the model itself")
HasModel( *, model_path: numpy.ndarray, texture_path: numpy.ndarray, scale: numpy.ndarray, model: numpy.ndarray, model_bbox: numpy.ndarray, model_radius: numpy.ndarray)
model_path: numpy.ndarray
texture_path: numpy.ndarray
scale: numpy.ndarray
model: numpy.ndarray
model_bbox: numpy.ndarray
model_radius: numpy.ndarray
class HasPose(microecs.component.Component):
55class HasPose(Component):
56    pose: np.ndarray = f32(
57        shape=(4, 4), serializable=True, default=np.eye(4, dtype="float32"),
58        comment="The pose of the entity (rotation & translation) as 4x4 homogeneous matrix")
59    candidate_pose: np.ndarray = f32(
60        shape=(4, 4), serializable=False, default=None,
61        comment=("The future (t+1) 4x4 pose. Used for post-collision. "
62                "Needs to be updated at each frame (system)."))
HasPose(*, pose: numpy.ndarray, candidate_pose: numpy.ndarray)
pose: numpy.ndarray
candidate_pose: numpy.ndarray
class HasFPV(microecs.component.Component):
66class HasFPV(Component):
67    fpv_camera: np.ndarray = obj(
68        shape=(1, ), serializable=False, default=None,
69        comment="The FPV camera object, instantiated in the server.")
70    fpv_data: np.ndarray = obj(
71        shape=(1, ), serializable=False, default=None,
72        comment="The frame currently displayed in the world in this FPV camera.")
73    fpv_texture: np.ndarray = obj(
74        shape=(1, ), serializable=False, default=None,
75        comment="The texture where the fpv_data of this camera is rendered")
HasFPV( *, fpv_camera: numpy.ndarray, fpv_data: numpy.ndarray, fpv_texture: numpy.ndarray)
fpv_camera: numpy.ndarray
fpv_data: numpy.ndarray
fpv_texture: numpy.ndarray
class PhysicsLevel(enum.IntEnum):
79class PhysicsLevel(IntEnum):
80    LEVEL_1 = 1
81    LEVEL_2 = 2
LEVEL_1 = <PhysicsLevel.LEVEL_1: 1>
LEVEL_2 = <PhysicsLevel.LEVEL_2: 2>
class HasMotion(microecs.component.Component):
 83class HasMotion(Component):
 84    """Motion component: Adding this to an entity makes it movable. It goes into the physics loop, can be moved via
 85    motion_input (6dof input vector), and adheres to a physics level (velocity only, acceleration etc.)"""
 86    velocity: np.ndarray = f32(
 87        shape=(6, ), serializable=True, default=zeros,
 88        comment=("The committed velocity of this entity. 6DoF: (vx, vy, vz, wx, wy, wz). "
 89                "Owned by the physics system (written at commit), not an input surface."))
 90    acceleration: np.ndarray = f32(
 91        shape=(6, ), serializable=True, default=zeros,
 92        comment=("The committed acceleration of this entity. 6DoF: (ax, ay, az, wax, way, waz). "
 93                "Owned by the physics system (written at commit), not an input surface."))
 94    motion_input: np.ndarray = f32(
 95        shape=(6, ), serializable=False, default=zeros,
 96        comment=("The motion input (to change vel/acc) of this entity. "
 97                "Usually sent from keyboard or the entity's channel (tcp)"))
 98    physics_level: np.ndarray = i32(shape=(1, ), serializable=True, default=2, comment="The physics level")
 99    max_velocities: np.ndarray = f32(
100        shape=(6, ), serializable=True, default=LVL1_MAX_VELOCITIES,
101        comment="The maximum velocities for physics_level 1 (level-1 cap; unused at level 2)")
102    max_accelerations: np.ndarray = f32(
103        shape=(6, ), serializable=True, default=LVL2_MAX_ACCELERATIONS,
104        comment="The maximum accelerations for physics_level 2 (unused at level 1)")
105    drag_coefficient: np.ndarray = f32(
106        shape=(1, ), serializable=True, default=LVL2_DRAG_COEFF,
107        comment="The drag coefficient for physics_level 2 (unused at level 1)")
108    candidate_velocity: np.ndarray = f32(
109        shape=(6, ), serializable=False, default=zeros,
110        comment=("The future (t+1) velocity. Used for collision checking in the physics system "
111                "before updating pose. Internal staging buffer: not serialized, recomputed every tick by "
112                "the physics system, and overwritten by it (write it in a per-tick system, not once)"))
113    candidate_acceleration: np.ndarray = f32(
114        shape=(6, ), serializable=False, default=zeros,
115        comment=("The future (t+1) acceleration. Used for collision checking in the physics system "
116                "before updating pose. Internal staging buffer: not serialized, recomputed every tick by "
117                "the physics system, and overwritten by it (write it in a per-tick system, not once)"))

Motion component: Adding this to an entity makes it movable. It goes into the physics loop, can be moved via motion_input (6dof input vector), and adheres to a physics level (velocity only, acceleration etc.)

HasMotion( *, velocity: numpy.ndarray, acceleration: numpy.ndarray, motion_input: numpy.ndarray, physics_level: numpy.ndarray, max_velocities: numpy.ndarray, max_accelerations: numpy.ndarray, drag_coefficient: numpy.ndarray, candidate_velocity: numpy.ndarray, candidate_acceleration: numpy.ndarray)
velocity: numpy.ndarray
acceleration: numpy.ndarray
motion_input: numpy.ndarray
physics_level: numpy.ndarray
max_velocities: numpy.ndarray
max_accelerations: numpy.ndarray
drag_coefficient: numpy.ndarray
candidate_velocity: numpy.ndarray
candidate_acceleration: numpy.ndarray
class ColliderKinds(enum.StrEnum):
121class ColliderKinds(StrEnum):
122    """The types of colliders. Used by HasCollision components."""
123    SPHERE = "SPHERE"
124    AABB = "AABB"

The types of colliders. Used by HasCollision components.

SPHERE = <ColliderKinds.SPHERE: 'SPHERE'>
AABB = <ColliderKinds.AABB: 'AABB'>
class HasCollision(microecs.component.Component):
126class HasCollision(Component):
127    is_colliding: np.ndarray = boolf(
128        shape=(1, ), serializable=False, default=zeros,
129        comment="Whether this entity is colliding now with something")
130    collider_kind: np.ndarray = obj(
131        shape=(1, ), serializable=True, default=None,
132        comment="The collider kind. see ColliderKinds enum for options.")
133    collider_bbox: np.ndarray = f32(
134        shape=(2, 3), serializable=False, default=zeros,
135        comment="Note: already in world space (scaled) by physics system")
136    collider_radii: np.ndarray = f32(
137        shape=(1, ), serializable=False, default=zeros,
138        comment="Note: already in world space (scaled) by physics system")
HasCollision( *, is_colliding: numpy.ndarray, collider_kind: numpy.ndarray, collider_bbox: numpy.ndarray, collider_radii: numpy.ndarray)
is_colliding: numpy.ndarray
collider_kind: numpy.ndarray
collider_bbox: numpy.ndarray
collider_radii: numpy.ndarray
ROBOLIB_COMPONENTS = [<class 'HasTag'>, <class 'HasModel'>, <class 'HasPose'>, <class 'HasFPV'>, <class 'HasMotion'>, <class 'HasCollision'>, <class 'GroundFloor'>]