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):
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")
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)."))
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")
class
PhysicsLevel(enum.IntEnum):
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.)
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")
ROBOLIB_COMPONENTS =
[<class 'HasTag'>, <class 'HasModel'>, <class 'HasPose'>, <class 'HasFPV'>, <class 'HasMotion'>, <class 'HasCollision'>, <class 'GroundFloor'>]