Skip to content

robot

RobotEntity #

Bases: AssetEntity

The robot entity displayed on the table.

Attributes:

Name Type Description
sensors_update_interval int

Interval in milliseconds between each sensors update

sensors_emit_interval int

Interval in milliseconds between each sensors data emission

sensors_emit_data_signal Signal

Qt Signal emitting sensors data

order_robot RobotOrderEntity

: Entity that represents the robot next destination

Source code in cogip/entities/robot.py
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
class RobotEntity(AssetEntity):
    """
    The robot entity displayed on the table.

    Attributes:
        sensors_update_interval: Interval in milliseconds between each sensors update
        sensors_emit_interval: Interval in milliseconds between each sensors data emission
        sensors_emit_data_signal: Qt Signal emitting sensors data
        order_robot:: Entity that represents the robot next destination
    """

    sensors_update_interval: int = 5
    sensors_emit_interval: int = 20
    sensors_emit_data_signal: qtSignal = qtSignal(int, list)
    order_robot: RobotOrderEntity = None

    def __init__(self, robot_id: int, parent: Qt3DCore.QEntity | None = None):
        """
        Class constructor.

        Inherits [AssetEntity][cogip.entities.asset.AssetEntity].
        """
        asset_path = Path(f"assets/{'robot' if robot_id == 1 else 'pami'}2024.dae")
        super().__init__(asset_path, parent=parent)
        self.robot_id = robot_id
        self.sensors = []
        self.rect_obstacles_pool = []
        self.round_obstacles_pool = []
        self.beacon_entity: Qt3DCore.QEntity | None = None

        if robot_id == 1:
            self.beacon_entity = Qt3DCore.QEntity(self)
            self.beacon_mesh = Qt3DExtras.QCylinderMesh(self.beacon_entity)
            self.beacon_mesh.setLength(80)
            self.beacon_mesh.setRadius(40)
            self.beacon_entity.addComponent(self.beacon_mesh)

            self.beacon_transform = Qt3DCore.QTransform(self.beacon_entity)
            self.beacon_transform.setTranslation(QtGui.QVector3D(0, 0, 350 + self.beacon_mesh.length() / 2))
            self.beacon_transform.setRotationX(90)
            self.beacon_entity.addComponent(self.beacon_transform)

            # Create a layer used by sensors to activate detection on the beacon
            self.beacon_entity.layer = Qt3DRender.QLayer(self.beacon_entity)
            self.beacon_entity.layer.setRecursive(True)
            self.beacon_entity.layer.setEnabled(True)
            self.beacon_entity.addComponent(self.beacon_entity.layer)

        # Use a timer to trigger sensors update
        self.sensors_update_timer = QtCore.QTimer()

        self.sensors_emit_timer = QtCore.QTimer()
        self.sensors_emit_timer.timeout.connect(self.emit_sensors_data)

    def post_init(self):
        """
        Function called once the asset has been loaded.

        Set the color and enable sensors.
        """
        super().post_init()

        if self.robot_id == 1:
            self.add_lidar_sensors()
        else:
            self.add_tof_sensor()

        self.order_robot = RobotOrderEntity(self.parent(), self.robot_id)

        if self.beacon_entity:
            Sensor.add_obstacle(self.beacon_entity)

    def add_lidar_sensors(self):
        """
        Add LIDAR sensors to the robot entity,
        one by degree around the top of the robot.
        """

        radius = 65.0 / 2

        sensors_properties = []

        for i in range(0, 360):
            angle = (360 - i) % 360
            origin_x = radius * math.sin(math.radians(90 - angle))
            origin_y = radius * math.cos(math.radians(90 - angle))
            sensors_properties.append(
                {
                    "name": f"Lidar {angle}",
                    "origin_x": origin_x,
                    "origin_y": origin_y,
                    "direction_x": origin_x,
                    "direction_y": origin_y,
                }
            )

        # Add sensors
        for prop in sensors_properties:
            sensor = LidarSensor(asset_entity=self, **prop)
            self.sensors_update_timer.timeout.connect(sensor.update_hit)
            self.sensors.append(sensor)

    def add_tof_sensor(self):
        """
        Add a ToF sensor in front of the robot entity.
        """
        sensor = ToFSensor(asset_entity=self, name="ToF", origin_x=106, origin_y=0)
        self.sensors_update_timer.timeout.connect(sensor.update_hit)
        self.sensors.append(sensor)

    @qtSlot(Pose)
    def new_robot_pose_current(self, new_pose: Pose) -> None:
        """
        Qt slot called to set the robot's new pose current.

        Arguments:
            new_pose: new robot pose
        """
        self.transform_component.setTranslation(QtGui.QVector3D(new_pose.x, new_pose.y, 0))
        self.transform_component.setRotationZ(new_pose.O)

    @qtSlot(Pose)
    def new_robot_pose_order(self, new_pose: Pose) -> None:
        """
        Qt slot called to set the robot's new pose order.

        Arguments:
            new_pose: new robot pose
        """
        if self.order_robot:
            self.order_robot.transform.setTranslation(QtGui.QVector3D(new_pose.x, new_pose.y, 0))
            self.order_robot.transform.setRotationZ(new_pose.O)

    def start_sensors_emulation(self) -> None:
        """
        Start timers triggering sensors update and Lidar data emission.
        """
        self.sensors_update_timer.start(RobotEntity.sensors_update_interval)
        self.sensors_emit_timer.start(RobotEntity.sensors_emit_interval)

    def stop_sensors_emulation(self) -> None:
        """
        Stop timers triggering sensors update and sensors data emission.
        """
        self.sensors_update_timer.stop()
        self.sensors_emit_timer.stop()

    def sensors_data(self) -> list[int]:
        """
        Return a list of distances for each 360 Lidar angles or ToF distance.
        """
        return [sensor.distance for sensor in self.sensors]

    @qtSlot()
    def emit_sensors_data(self) -> None:
        """
        Qt Slot called to emit sensors data.
        """
        self.sensors_emit_data_signal.emit(self.robot_id, self.sensors_data())

__init__(robot_id, parent=None) #

Class constructor.

Inherits AssetEntity.

Source code in cogip/entities/robot.py
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
def __init__(self, robot_id: int, parent: Qt3DCore.QEntity | None = None):
    """
    Class constructor.

    Inherits [AssetEntity][cogip.entities.asset.AssetEntity].
    """
    asset_path = Path(f"assets/{'robot' if robot_id == 1 else 'pami'}2024.dae")
    super().__init__(asset_path, parent=parent)
    self.robot_id = robot_id
    self.sensors = []
    self.rect_obstacles_pool = []
    self.round_obstacles_pool = []
    self.beacon_entity: Qt3DCore.QEntity | None = None

    if robot_id == 1:
        self.beacon_entity = Qt3DCore.QEntity(self)
        self.beacon_mesh = Qt3DExtras.QCylinderMesh(self.beacon_entity)
        self.beacon_mesh.setLength(80)
        self.beacon_mesh.setRadius(40)
        self.beacon_entity.addComponent(self.beacon_mesh)

        self.beacon_transform = Qt3DCore.QTransform(self.beacon_entity)
        self.beacon_transform.setTranslation(QtGui.QVector3D(0, 0, 350 + self.beacon_mesh.length() / 2))
        self.beacon_transform.setRotationX(90)
        self.beacon_entity.addComponent(self.beacon_transform)

        # Create a layer used by sensors to activate detection on the beacon
        self.beacon_entity.layer = Qt3DRender.QLayer(self.beacon_entity)
        self.beacon_entity.layer.setRecursive(True)
        self.beacon_entity.layer.setEnabled(True)
        self.beacon_entity.addComponent(self.beacon_entity.layer)

    # Use a timer to trigger sensors update
    self.sensors_update_timer = QtCore.QTimer()

    self.sensors_emit_timer = QtCore.QTimer()
    self.sensors_emit_timer.timeout.connect(self.emit_sensors_data)

add_lidar_sensors() #

Add LIDAR sensors to the robot entity, one by degree around the top of the robot.

Source code in cogip/entities/robot.py
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
def add_lidar_sensors(self):
    """
    Add LIDAR sensors to the robot entity,
    one by degree around the top of the robot.
    """

    radius = 65.0 / 2

    sensors_properties = []

    for i in range(0, 360):
        angle = (360 - i) % 360
        origin_x = radius * math.sin(math.radians(90 - angle))
        origin_y = radius * math.cos(math.radians(90 - angle))
        sensors_properties.append(
            {
                "name": f"Lidar {angle}",
                "origin_x": origin_x,
                "origin_y": origin_y,
                "direction_x": origin_x,
                "direction_y": origin_y,
            }
        )

    # Add sensors
    for prop in sensors_properties:
        sensor = LidarSensor(asset_entity=self, **prop)
        self.sensors_update_timer.timeout.connect(sensor.update_hit)
        self.sensors.append(sensor)

add_tof_sensor() #

Add a ToF sensor in front of the robot entity.

Source code in cogip/entities/robot.py
120
121
122
123
124
125
126
def add_tof_sensor(self):
    """
    Add a ToF sensor in front of the robot entity.
    """
    sensor = ToFSensor(asset_entity=self, name="ToF", origin_x=106, origin_y=0)
    self.sensors_update_timer.timeout.connect(sensor.update_hit)
    self.sensors.append(sensor)

emit_sensors_data() #

Qt Slot called to emit sensors data.

Source code in cogip/entities/robot.py
171
172
173
174
175
176
@qtSlot()
def emit_sensors_data(self) -> None:
    """
    Qt Slot called to emit sensors data.
    """
    self.sensors_emit_data_signal.emit(self.robot_id, self.sensors_data())

new_robot_pose_current(new_pose) #

Qt slot called to set the robot's new pose current.

Parameters:

Name Type Description Default
new_pose Pose

new robot pose

required
Source code in cogip/entities/robot.py
128
129
130
131
132
133
134
135
136
137
@qtSlot(Pose)
def new_robot_pose_current(self, new_pose: Pose) -> None:
    """
    Qt slot called to set the robot's new pose current.

    Arguments:
        new_pose: new robot pose
    """
    self.transform_component.setTranslation(QtGui.QVector3D(new_pose.x, new_pose.y, 0))
    self.transform_component.setRotationZ(new_pose.O)

new_robot_pose_order(new_pose) #

Qt slot called to set the robot's new pose order.

Parameters:

Name Type Description Default
new_pose Pose

new robot pose

required
Source code in cogip/entities/robot.py
139
140
141
142
143
144
145
146
147
148
149
@qtSlot(Pose)
def new_robot_pose_order(self, new_pose: Pose) -> None:
    """
    Qt slot called to set the robot's new pose order.

    Arguments:
        new_pose: new robot pose
    """
    if self.order_robot:
        self.order_robot.transform.setTranslation(QtGui.QVector3D(new_pose.x, new_pose.y, 0))
        self.order_robot.transform.setRotationZ(new_pose.O)

post_init() #

Function called once the asset has been loaded.

Set the color and enable sensors.

Source code in cogip/entities/robot.py
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
def post_init(self):
    """
    Function called once the asset has been loaded.

    Set the color and enable sensors.
    """
    super().post_init()

    if self.robot_id == 1:
        self.add_lidar_sensors()
    else:
        self.add_tof_sensor()

    self.order_robot = RobotOrderEntity(self.parent(), self.robot_id)

    if self.beacon_entity:
        Sensor.add_obstacle(self.beacon_entity)

sensors_data() #

Return a list of distances for each 360 Lidar angles or ToF distance.

Source code in cogip/entities/robot.py
165
166
167
168
169
def sensors_data(self) -> list[int]:
    """
    Return a list of distances for each 360 Lidar angles or ToF distance.
    """
    return [sensor.distance for sensor in self.sensors]

start_sensors_emulation() #

Start timers triggering sensors update and Lidar data emission.

Source code in cogip/entities/robot.py
151
152
153
154
155
156
def start_sensors_emulation(self) -> None:
    """
    Start timers triggering sensors update and Lidar data emission.
    """
    self.sensors_update_timer.start(RobotEntity.sensors_update_interval)
    self.sensors_emit_timer.start(RobotEntity.sensors_emit_interval)

stop_sensors_emulation() #

Stop timers triggering sensors update and sensors data emission.

Source code in cogip/entities/robot.py
158
159
160
161
162
163
def stop_sensors_emulation(self) -> None:
    """
    Stop timers triggering sensors update and sensors data emission.
    """
    self.sensors_update_timer.stop()
    self.sensors_emit_timer.stop()