wirepod-vector-sdk-audio 0.9.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (71) hide show
  1. anki_vector/__init__.py +43 -0
  2. anki_vector/animation.py +272 -0
  3. anki_vector/annotate.py +590 -0
  4. anki_vector/audio.py +212 -0
  5. anki_vector/audio_stream.py +335 -0
  6. anki_vector/behavior.py +1135 -0
  7. anki_vector/camera.py +670 -0
  8. anki_vector/camera_viewer/__init__.py +121 -0
  9. anki_vector/color.py +88 -0
  10. anki_vector/configure/__main__.py +331 -0
  11. anki_vector/connection.py +838 -0
  12. anki_vector/events.py +420 -0
  13. anki_vector/exceptions.py +185 -0
  14. anki_vector/faces.py +819 -0
  15. anki_vector/lights.py +210 -0
  16. anki_vector/mdns.py +131 -0
  17. anki_vector/messaging/__init__.py +45 -0
  18. anki_vector/messaging/alexa_pb2.py +36 -0
  19. anki_vector/messaging/alexa_pb2_grpc.py +3 -0
  20. anki_vector/messaging/behavior_pb2.py +40 -0
  21. anki_vector/messaging/behavior_pb2_grpc.py +3 -0
  22. anki_vector/messaging/client.py +33 -0
  23. anki_vector/messaging/cube_pb2.py +113 -0
  24. anki_vector/messaging/cube_pb2_grpc.py +3 -0
  25. anki_vector/messaging/extensions_pb2.py +25 -0
  26. anki_vector/messaging/extensions_pb2_grpc.py +3 -0
  27. anki_vector/messaging/external_interface_pb2.py +169 -0
  28. anki_vector/messaging/external_interface_pb2_grpc.py +1267 -0
  29. anki_vector/messaging/messages_pb2.py +431 -0
  30. anki_vector/messaging/messages_pb2_grpc.py +3 -0
  31. anki_vector/messaging/nav_map_pb2.py +33 -0
  32. anki_vector/messaging/nav_map_pb2_grpc.py +3 -0
  33. anki_vector/messaging/protocol.py +33 -0
  34. anki_vector/messaging/response_status_pb2.py +27 -0
  35. anki_vector/messaging/response_status_pb2_grpc.py +3 -0
  36. anki_vector/messaging/settings_pb2.py +72 -0
  37. anki_vector/messaging/settings_pb2_grpc.py +3 -0
  38. anki_vector/messaging/shared_pb2.py +54 -0
  39. anki_vector/messaging/shared_pb2_grpc.py +3 -0
  40. anki_vector/motors.py +127 -0
  41. anki_vector/nav_map.py +409 -0
  42. anki_vector/objects.py +1782 -0
  43. anki_vector/opengl/__init__.py +103 -0
  44. anki_vector/opengl/assets/LICENSE.txt +21 -0
  45. anki_vector/opengl/assets/cube.jpg +0 -0
  46. anki_vector/opengl/assets/cube.mtl +9 -0
  47. anki_vector/opengl/assets/cube.obj +1000 -0
  48. anki_vector/opengl/assets/vector.mtl +67 -0
  49. anki_vector/opengl/assets/vector.obj +13220 -0
  50. anki_vector/opengl/opengl.py +864 -0
  51. anki_vector/opengl/opengl_vector.py +620 -0
  52. anki_vector/opengl/opengl_viewer.py +689 -0
  53. anki_vector/photos.py +145 -0
  54. anki_vector/proximity.py +176 -0
  55. anki_vector/reserve_control/__main__.py +36 -0
  56. anki_vector/robot.py +930 -0
  57. anki_vector/screen.py +201 -0
  58. anki_vector/status.py +322 -0
  59. anki_vector/touch.py +119 -0
  60. anki_vector/user_intent.py +186 -0
  61. anki_vector/util.py +1132 -0
  62. anki_vector/version.py +15 -0
  63. anki_vector/viewer.py +403 -0
  64. anki_vector/vision.py +202 -0
  65. anki_vector/world.py +899 -0
  66. wirepod_vector_sdk_audio-0.9.0.dist-info/METADATA +80 -0
  67. wirepod_vector_sdk_audio-0.9.0.dist-info/RECORD +71 -0
  68. wirepod_vector_sdk_audio-0.9.0.dist-info/WHEEL +5 -0
  69. wirepod_vector_sdk_audio-0.9.0.dist-info/licenses/LICENSE.txt +180 -0
  70. wirepod_vector_sdk_audio-0.9.0.dist-info/top_level.txt +1 -0
  71. wirepod_vector_sdk_audio-0.9.0.dist-info/zip-safe +1 -0
@@ -0,0 +1,620 @@
1
+ # Copyright (c) 2018 Anki, Inc.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License in the file LICENSE.txt or at
6
+ #
7
+ # https://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ """This module provides Vector-specific 3D support classes for OpenGL, used by opengl_viewer.py.
16
+
17
+ Warning:
18
+ This package requires Python to have the PyOpenGL package installed, along
19
+ with an implementation of GLUT (OpenGL Utility Toolkit).
20
+
21
+ To install the Python packages on Mac and Linux do ``python3 -m pip install --user "wirepod_vector_sdk[3dviewer]"``
22
+
23
+ To install the Python packages on Windows do ``py -3 -m pip install --user "wirepod_vector_sdk[3dviewer]"``
24
+
25
+ On Windows and Linux you must also install freeglut (macOS / OSX has one
26
+ preinstalled).
27
+
28
+ On Linux: ``sudo apt-get install freeglut3``
29
+
30
+ On Windows: Go to http://freeglut.sourceforge.net/ to get a ``freeglut.dll``
31
+ file. It's included in any of the `Windows binaries` downloads. Place the DLL
32
+ next to your Python script, or install it somewhere in your PATH to allow any
33
+ script to use it."
34
+ """
35
+
36
+ # __all__ should order by constants, event classes, other classes, functions.
37
+ __all__ = ['CubeRenderFrame', 'FaceRenderFrame', 'LightCubeView', 'RobotRenderFrame', 'RobotView',
38
+ 'UnitCubeView', 'VectorViewManifest', 'WorldRenderFrame']
39
+
40
+ import math
41
+ import time
42
+ from typing import List
43
+
44
+ from anki_vector.faces import Face
45
+ from anki_vector.objects import CustomObject, FixedCustomObject, LightCube, ObservableObject
46
+ from anki_vector import nav_map, util
47
+ from . import opengl
48
+
49
+ try:
50
+ from OpenGL.GL import (GL_AMBIENT, GL_BLEND, GL_COMPILE, GL_DIFFUSE, GL_FILL, GL_FRONT, GL_FRONT_AND_BACK, GL_LIGHTING, GL_LINE, GL_LINE_STRIP,
51
+ GL_ONE_MINUS_SRC_ALPHA, GL_POLYGON, GL_SHININESS, GL_SPECULAR, GL_SRC_ALPHA, GL_TRIANGLE_STRIP,
52
+ glBegin, glBlendFunc, glCallList, glColor, glColor3f, glColor4f, glDisable, glEnable, glEnd, glEndList, glGenLists,
53
+ glMaterialfv, glMultMatrixf, glNewList, glNormal3fv, glPolygonMode, glPopMatrix, glPushMatrix, glRotatef, glScalef,
54
+ glTranslatef, glVertex3f, glVertex3fv)
55
+
56
+ except ImportError as import_exc:
57
+ opengl.raise_opengl_or_pillow_import_error(import_exc)
58
+
59
+
60
+ #: The object file used to render the robot.
61
+ VECTOR_MODEL_FILE = "vector.obj"
62
+
63
+ #: The object file used to render the cube.
64
+ CUBE_MODEL_FILE = "cube.obj"
65
+
66
+ # The following offsets are used in displaying the Vector 3d model.
67
+ # These values are tuned to reflect the vector.obj file, and do not
68
+ # necessarily reflect the actual measurements of the physical robot.
69
+
70
+ #: The length of Vector's lift arm
71
+ LIFT_ARM_LENGTH_MM = 66.0
72
+
73
+ #: The height above ground of Vector's lift arm's pivot
74
+ LIFT_PIVOT_HEIGHT_MM = 45.0
75
+
76
+ #: Angle of the lift in the object's initial default pose.
77
+ LIFT_ANGLE_IN_DEFAULT_POSE = -0.1136
78
+
79
+ #: Pivot offset for where the fork rotates around itself
80
+ FORK_PIVOT_X = 3.0
81
+ FORK_PIVOT_Z = 3.4
82
+
83
+ #: Offset for the axel that the upper arm rotates around.
84
+ UPPER_ARM_PIVOT_X = -3.73
85
+ UPPER_ARM_PIVOT_Z = 4.47
86
+
87
+ #: Offset for the axel that the lower arm rotates around.
88
+ LOWER_ARM_PIVOT_X = -3.74
89
+ LOWER_ARM_PIVOT_Z = 3.27
90
+
91
+ #: Offset for the pivot that the head rotates around.
92
+ HEAD_PIVOT_X = -1.1
93
+ HEAD_PIVOT_Z = 4.75
94
+
95
+
96
+ _resource_package = __name__ # All resources are in subdirectories from this file's location
97
+
98
+
99
+ class UnitCubeView(opengl.PrecomputedView):
100
+ """A view containing a cube of unit size at the origin."""
101
+
102
+ def __init__(self):
103
+
104
+ self._display_list_name = 'cube'
105
+
106
+ super(UnitCubeView, self).__init__()
107
+ self.build_from_render_function(self._display_list_name, self._render_cube)
108
+
109
+ @staticmethod
110
+ def _render_cube():
111
+ """Pre renders a unit-size cube, with normals, centered at the origin.
112
+ """
113
+ # build each of the 6 faces
114
+ for face_index in range(6):
115
+ # calculate normal and vertices for this face
116
+ vertex_normal = [0.0, 0.0, 0.0]
117
+ vertex_pos_options1 = [-1.0, 1.0, 1.0, -1.0]
118
+ vertex_pos_options2 = [1.0, 1.0, -1.0, -1.0]
119
+ face_index_even = ((face_index % 2) == 0)
120
+ # odd and even faces point in opposite directions
121
+ normal_dir = 1.0 if face_index_even else -1.0
122
+ if face_index < 2:
123
+ # -X and +X faces (vert positions differ in Y,Z)
124
+ vertex_normal[0] = normal_dir
125
+ v1i = 1
126
+ v2i = 2
127
+ elif face_index < 4:
128
+ # -Y and +Y faces (vert positions differ in X,Z)
129
+ vertex_normal[1] = normal_dir
130
+ v1i = 0
131
+ v2i = 2
132
+ else:
133
+ # -Z and +Z faces (vert positions differ in X,Y)
134
+ vertex_normal[2] = normal_dir
135
+ v1i = 0
136
+ v2i = 1
137
+
138
+ vertex_pos = list(vertex_normal)
139
+
140
+ # Polygon (N verts) with optional normals and tex coords
141
+ glBegin(GL_POLYGON)
142
+ for vert_index in range(4):
143
+ vertex_pos[v1i] = vertex_pos_options1[vert_index]
144
+ vertex_pos[v2i] = vertex_pos_options2[vert_index]
145
+ glNormal3fv(vertex_normal)
146
+ glVertex3fv(vertex_pos)
147
+ glEnd()
148
+
149
+ def display(self, color: List[float], draw_solid: bool):
150
+ """Displays the cube with a specific color.
151
+
152
+ :param color: Color to display the cube.
153
+ :param draw_solid: Whether to draw solid polygons (False to draw wireframe).
154
+ """
155
+ glColor(color)
156
+
157
+ if draw_solid:
158
+ ambient_color = [color[0] * 0.1, color[1] * 0.1, color[2] * 0.1, 1.0]
159
+ else:
160
+ ambient_color = color
161
+ glMaterialfv(GL_FRONT, GL_AMBIENT, ambient_color)
162
+ glMaterialfv(GL_FRONT, GL_DIFFUSE, color)
163
+ glMaterialfv(GL_FRONT, GL_SPECULAR, color)
164
+
165
+ glMaterialfv(GL_FRONT, GL_SHININESS, 10.0)
166
+
167
+ if draw_solid:
168
+ glPolygonMode(GL_FRONT_AND_BACK, GL_FILL)
169
+ else:
170
+ glPolygonMode(GL_FRONT_AND_BACK, GL_LINE)
171
+
172
+ self.display_by_key(self._display_list_name)
173
+
174
+
175
+ class LightCubeView(opengl.PrecomputedView):
176
+ """A view containing the Vector Light Cube 3D Model.
177
+
178
+ :param mesh_data: Source Mesh Data for the light cube.
179
+ """
180
+
181
+ def __init__(self, mesh_data: opengl.MeshData):
182
+
183
+ super(LightCubeView, self).__init__()
184
+ self.build_from_mesh_data(mesh_data)
185
+
186
+ def display(self, pose: util.Pose):
187
+ """Displays the precomputed view at a specific pose in 3d space.
188
+
189
+ :param pose: Where to display the cube.
190
+ """
191
+ glPushMatrix()
192
+
193
+ # TODO if cube_pose.is_accurate is False, render half-translucent?
194
+ # (This would require using a shader, or having duplicate objects)
195
+
196
+ cube_matrix = pose.to_matrix()
197
+ glMultMatrixf(cube_matrix.in_row_order)
198
+
199
+ # Cube is drawn slightly larger than the 10mm to 1 cm scale, as the model looks small otherwise
200
+ cube_scale_amt = 10.7
201
+ glScalef(cube_scale_amt, cube_scale_amt, cube_scale_amt)
202
+
203
+ self.display_all()
204
+ glPopMatrix()
205
+
206
+
207
+ class RobotView(opengl.PrecomputedView):
208
+ """A view containing the Vector robot 3D Model.
209
+
210
+ :param mesh_data: Source Mesh Data for the robot.
211
+ """
212
+
213
+ def __init__(self, mesh_data: opengl.MeshData):
214
+
215
+ super(RobotView, self).__init__()
216
+ self.build_from_mesh_data(mesh_data)
217
+
218
+ def _display_vector_body(self):
219
+ """Displays the robot's body to the current OpenGL context
220
+ """
221
+
222
+ # Render the static body meshes - first the main body:
223
+ self.display_by_key("body_geo")
224
+ # Render the left treads and wheels
225
+ self.display_by_key("trackBase_L_geo")
226
+ self.display_by_key("wheel_BL_geo")
227
+ self.display_by_key("wheel_FL_geo")
228
+ self.display_by_key("tracks_L_geo")
229
+ # Render the right treads and wheels
230
+ self.display_by_key("trackBase_R_geo")
231
+ self.display_by_key("wheel_BR_geo")
232
+ self.display_by_key("wheel_FR_geo")
233
+ self.display_by_key("tracks_R_geo")
234
+
235
+ def _display_vector_lift(self, lift_angle: float):
236
+ """Displays the robot's lift to the current OpenGL context
237
+
238
+ :param lift_angle: the angle of the lift in radians
239
+ """
240
+
241
+ # Render the fork at the front (but not the arms)
242
+ glPushMatrix()
243
+ # The fork rotates first around upper arm (to get it to the correct position).
244
+ glTranslatef(UPPER_ARM_PIVOT_X, 0.0, UPPER_ARM_PIVOT_Z)
245
+ glRotatef(lift_angle, 0, 1, 0)
246
+ glTranslatef(-UPPER_ARM_PIVOT_X, 0.0, -UPPER_ARM_PIVOT_Z)
247
+ # The fork then rotates back around itself as it always hangs vertically.
248
+ glTranslatef(FORK_PIVOT_X, 0.0, FORK_PIVOT_Z)
249
+ glRotatef(-lift_angle, 0, 1, 0)
250
+ glTranslatef(-FORK_PIVOT_X, 0.0, -FORK_PIVOT_Z)
251
+ # Render
252
+ self.display_by_key("fork_geo")
253
+ glPopMatrix()
254
+
255
+ # Render the upper arms:
256
+ glPushMatrix()
257
+ # Rotate the upper arms around the upper arm joint
258
+ glTranslatef(UPPER_ARM_PIVOT_X, 0.0, UPPER_ARM_PIVOT_Z)
259
+ glRotatef(lift_angle, 0, 1, 0)
260
+ glTranslatef(-UPPER_ARM_PIVOT_X, 0.0, -UPPER_ARM_PIVOT_Z)
261
+ # Render
262
+ self.display_by_key("uprArm_L_geo")
263
+ self.display_by_key("uprArm_geo")
264
+ glPopMatrix()
265
+
266
+ # Render the lower arms:
267
+ glPushMatrix()
268
+ # Rotate the lower arms around the lower arm joint
269
+ glTranslatef(LOWER_ARM_PIVOT_X, 0.0, LOWER_ARM_PIVOT_Z)
270
+ glRotatef(lift_angle, 0, 1, 0)
271
+ glTranslatef(-LOWER_ARM_PIVOT_X, 0.0, -LOWER_ARM_PIVOT_Z)
272
+ # Render
273
+ self.display_by_key("lwrArm_L_geo")
274
+ self.display_by_key("lwrArm_R_geo")
275
+ glPopMatrix()
276
+
277
+ def _display_vector_head(self, head_angle: float):
278
+ """Displays the robot's head to the current OpenGL context
279
+
280
+ :param head_angle: the angle of the lift in radians
281
+ """
282
+
283
+ glPushMatrix()
284
+ # Rotate the head around the pivot
285
+ glTranslatef(HEAD_PIVOT_X, 0.0, HEAD_PIVOT_Z)
286
+ glRotatef(-head_angle, 0, 1, 0)
287
+ glTranslatef(-HEAD_PIVOT_X, 0.0, -HEAD_PIVOT_Z)
288
+ # Render all of the head meshes
289
+ self.display_by_key("head_geo")
290
+ # Screen
291
+ self.display_by_key("backScreen_mat")
292
+ self.display_by_key("screenEdge_geo")
293
+ self.display_by_key("overscan_1_geo")
294
+ # Eyes
295
+ self.display_by_key("eye_L_geo")
296
+ self.display_by_key("eye_R_geo")
297
+ # Eyelids
298
+ self.display_by_key("eyeLid_R_top_geo")
299
+ self.display_by_key("eyeLid_L_top_geo")
300
+ self.display_by_key("eyeLid_L_btm_geo")
301
+ self.display_by_key("eyeLid_R_btm_geo")
302
+ # Face cover (drawn last as it's translucent):
303
+ self.display_by_key("front_Screen_geo")
304
+ glPopMatrix()
305
+
306
+ def display(self, pose: util.Pose, head_angle: util.Angle, lift_position: util.Distance):
307
+ """Displays the precomputed view at a specific pose in 3d space.
308
+
309
+ :param pose: Where to display the robot.
310
+ """
311
+ if not self._display_lists:
312
+ return
313
+
314
+ robot_matrix = pose.to_matrix()
315
+ head_angle_degrees = head_angle.degrees
316
+
317
+ # Get the angle of Vector's lift for rendering - we subtract the angle
318
+ # of the lift in the default pose in the object, and apply the inverse
319
+ # rotation
320
+ sin_angle = (lift_position.distance_mm - LIFT_PIVOT_HEIGHT_MM) / LIFT_ARM_LENGTH_MM
321
+ angle_radians = math.asin(sin_angle)
322
+
323
+ lift_angle = -(angle_radians - LIFT_ANGLE_IN_DEFAULT_POSE)
324
+ lift_angle_degrees = math.degrees(lift_angle)
325
+
326
+ glPushMatrix()
327
+ glEnable(GL_LIGHTING)
328
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
329
+ glEnable(GL_BLEND)
330
+
331
+ glMultMatrixf(robot_matrix.in_row_order)
332
+
333
+ robot_scale_amt = 10.0 # cm to mm
334
+ glScalef(robot_scale_amt, robot_scale_amt, robot_scale_amt)
335
+ glPolygonMode(GL_FRONT_AND_BACK, GL_FILL)
336
+
337
+ self._display_vector_body()
338
+ self._display_vector_lift(lift_angle_degrees)
339
+ self._display_vector_head(head_angle_degrees)
340
+
341
+ glDisable(GL_LIGHTING)
342
+ glPopMatrix()
343
+
344
+
345
+ class NavMapView(opengl.PrecomputedView):
346
+ """A view containing a cube of unit size at the origin."""
347
+
348
+ def __init__(self):
349
+ self.logger = util.get_class_logger(__name__, self)
350
+ super(NavMapView, self).__init__()
351
+
352
+ def build_from_nav_map(self, new_nav_map: nav_map.NavMapGrid):
353
+ """Reconstructs the display list for the NavMapView based on a :class:`anki_vector.nav_map.NavMapGrid` object.
354
+
355
+ :param new_nav_map: nav map source data to be referenced for the new display list.
356
+ """
357
+ cen = new_nav_map.center
358
+ half_size = new_nav_map.size * 0.5
359
+
360
+ self._display_lists['_navmap'] = glGenLists(1) # pylint: disable=assignment-from-no-return
361
+ glNewList(self._display_lists['_navmap'], GL_COMPILE)
362
+
363
+ glPushMatrix()
364
+
365
+ color_light_gray = (0.65, 0.65, 0.65)
366
+ glColor3f(*color_light_gray)
367
+ glBegin(GL_LINE_STRIP)
368
+ glVertex3f(cen.x + half_size, cen.y + half_size, cen.z) # TL
369
+ glVertex3f(cen.x + half_size, cen.y - half_size, cen.z) # TR
370
+ glVertex3f(cen.x - half_size, cen.y - half_size, cen.z) # BR
371
+ glVertex3f(cen.x - half_size, cen.y + half_size, cen.z) # BL
372
+ glVertex3f(cen.x + half_size, cen.y + half_size,
373
+ cen.z) # TL (close loop)
374
+ glEnd()
375
+
376
+ def color_for_content(content):
377
+ nct = nav_map.NavNodeContentTypes
378
+ colors = {nct.Unknown.value: (0.3, 0.3, 0.3), # dark gray
379
+ nct.ClearOfObstacle.value: (0.0, 1.0, 0.0), # green
380
+ nct.ClearOfCliff.value: (0.0, 0.5, 0.0), # dark green
381
+ nct.ObstacleCube.value: (1.0, 0.0, 0.0), # red
382
+ nct.ObstacleProximity.value: (1.0, 0.5, 0.0), # orange
383
+ nct.ObstacleProximityExplored.value: (0.5, 1.0, 0.0), # yellow-green
384
+ nct.ObstacleUnrecognized.value: (0.5, 0.0, 0.0), # dark red
385
+ nct.Cliff.value: (0.0, 0.0, 0.0), # black
386
+ nct.InterestingEdge.value: (1.0, 1.0, 0.0), # yellow
387
+ nct.NonInterestingEdge.value: (0.5, 0.5, 0.0), # dark-yellow
388
+ }
389
+
390
+ col = colors.get(content)
391
+ if col is None:
392
+ col = (1.0, 1.0, 1.0) # white
393
+ return col
394
+
395
+ fill_z = cen.z - 0.4
396
+
397
+ def _recursive_draw(grid_node: nav_map.NavMapGridNode):
398
+ if grid_node.children is not None:
399
+ for child in grid_node.children:
400
+ _recursive_draw(child)
401
+ else:
402
+ # leaf node - render as a quad
403
+ map_alpha = 0.5
404
+ cen = grid_node.center
405
+ half_size = grid_node.size * 0.5
406
+
407
+ # Draw outline
408
+ glColor4f(*color_light_gray, 1.0) # fully opaque
409
+ glBegin(GL_LINE_STRIP)
410
+ glVertex3f(cen.x + half_size, cen.y + half_size, cen.z)
411
+ glVertex3f(cen.x + half_size, cen.y - half_size, cen.z)
412
+ glVertex3f(cen.x - half_size, cen.y - half_size, cen.z)
413
+ glVertex3f(cen.x - half_size, cen.y + half_size, cen.z)
414
+ glVertex3f(cen.x + half_size, cen.y + half_size, cen.z)
415
+ glEnd()
416
+
417
+ # Draw filled contents
418
+ glColor4f(*color_for_content(grid_node.content), map_alpha)
419
+ glBegin(GL_TRIANGLE_STRIP)
420
+ glVertex3f(cen.x + half_size, cen.y - half_size, fill_z)
421
+ glVertex3f(cen.x + half_size, cen.y + half_size, fill_z)
422
+ glVertex3f(cen.x - half_size, cen.y - half_size, fill_z)
423
+ glVertex3f(cen.x - half_size, cen.y + half_size, fill_z)
424
+ glEnd()
425
+
426
+ _recursive_draw(new_nav_map.root_node)
427
+
428
+ glPopMatrix()
429
+ glEndList()
430
+
431
+ def display(self):
432
+ """Displays the precomputed nav map view.
433
+ This function will do nothing if no display list has yet been built.
434
+ """
435
+ if '_navmap' in self._display_lists:
436
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
437
+ glEnable(GL_BLEND)
438
+ glPushMatrix()
439
+ glCallList(self._display_lists['_navmap'])
440
+ glPopMatrix()
441
+
442
+
443
+ class VectorViewManifest():
444
+ """A collection of Vector-specific source data containing views to display.
445
+ """
446
+
447
+ def __init__(self):
448
+ self._light_cube_view: LightCubeView = None
449
+ self._unit_cube_view: UnitCubeView = None
450
+ self._robot_view: RobotView = None
451
+ self._nav_map_view: NavMapView = None
452
+
453
+ @property
454
+ def light_cube_view(self) -> LightCubeView:
455
+ """A precomputed view of Vector's light cube."""
456
+ return self._light_cube_view
457
+
458
+ @property
459
+ def unit_cube_view(self) -> UnitCubeView:
460
+ """A precomputed view of a unit cube.
461
+
462
+ This is used for representing detected faces.
463
+ """
464
+ return self._unit_cube_view
465
+
466
+ @property
467
+ def robot_view(self) -> RobotView:
468
+ """A precomputed view of the robot."""
469
+ return self._robot_view
470
+
471
+ @property
472
+ def nav_map_view(self) -> NavMapView:
473
+ """A precomputable view of the navigation map. This will be updated
474
+ as new content comes in.
475
+ """
476
+ return self._nav_map_view
477
+
478
+ def load_assets(self):
479
+ """Loads all assets needed for the view manifest, and precomputes them
480
+ into cached views.
481
+ """
482
+ resource_context = opengl.ResourceManager(_resource_package)
483
+
484
+ # Load 3D objects
485
+ robot_mesh_data = opengl.MeshData(resource_context, VECTOR_MODEL_FILE)
486
+ self._robot_view = RobotView(robot_mesh_data)
487
+
488
+ # Load the cube
489
+ cube_mesh_data = opengl.MeshData(resource_context, CUBE_MODEL_FILE)
490
+ self._light_cube_view = LightCubeView(cube_mesh_data)
491
+
492
+ self._unit_cube_view = UnitCubeView()
493
+
494
+ self._nav_map_view = NavMapView()
495
+
496
+
497
+ class ObservableObjectRenderFrame(): # pylint: disable=too-few-public-methods
498
+ """Minimal copy of an object's state for 1 frame of rendering.
499
+
500
+ :param obj: the cube object to be rendered.
501
+ """
502
+
503
+ def __init__(self, obj: ObservableObject):
504
+ self.pose = obj.pose
505
+ self.is_visible = obj.is_visible
506
+ self.last_observed_time = obj.last_observed_time
507
+
508
+ @property
509
+ def time_since_last_seen(self) -> float:
510
+ # Equivalent of ObservableObject's method
511
+ """time since this obj was last seen (math.inf if never)"""
512
+ if self.last_observed_time is None:
513
+ return math.inf
514
+ return time.time() - self.last_observed_time
515
+
516
+
517
+ class CubeRenderFrame(ObservableObjectRenderFrame): # pylint: disable=too-few-public-methods
518
+ """Minimal copy of a Cube's state for 1 frame of rendering.
519
+
520
+ :param cube: the cube object to be rendered.
521
+ """
522
+
523
+ def __init__(self, cube: LightCube): # pylint: disable=useless-super-delegation
524
+ super().__init__(cube)
525
+
526
+
527
+ class FaceRenderFrame(ObservableObjectRenderFrame): # pylint: disable=too-few-public-methods
528
+ """Minimal copy of a Face's state for 1 frame of rendering.
529
+
530
+ :param face: The face object to be rendered.
531
+ """
532
+
533
+ def __init__(self, face: Face): # pylint: disable=useless-super-delegation
534
+ super().__init__(face)
535
+
536
+
537
+ class CustomObjectRenderFrame(ObservableObjectRenderFrame): # pylint: disable=too-few-public-methods
538
+ """Minimal copy of a CustomObject's state for 1 frame of rendering.
539
+
540
+ :param custom_object: The custom object to be rendered. Either :class:`anki_vector.objects.CustomObject` or :class:`anki_vector.objects.FixedCustomObject`.
541
+ :param is_fixed: Whether the custom object is permanently defined rather than an observable archetype.
542
+ """
543
+
544
+ def __init__(self, custom_object, is_fixed: bool):
545
+ if is_fixed:
546
+ # Not an observable, so init directly
547
+ self.pose = custom_object.pose
548
+ self.is_visible = None
549
+ self.last_observed_time = None
550
+ else:
551
+ super().__init__(custom_object)
552
+
553
+ self.is_fixed = is_fixed
554
+
555
+ if self.is_fixed:
556
+ self.x_size_mm = custom_object.x_size_mm
557
+ self.y_size_mm = custom_object.y_size_mm
558
+ self.z_size_mm = custom_object.z_size_mm
559
+ else:
560
+ self.x_size_mm = custom_object.archetype.x_size_mm
561
+ self.y_size_mm = custom_object.archetype.y_size_mm
562
+ self.z_size_mm = custom_object.archetype.z_size_mm
563
+
564
+
565
+ class RobotRenderFrame(): # pylint: disable=too-few-public-methods
566
+ """Minimal copy of a Robot's state for 1 frame of rendering.
567
+
568
+ :param robot: the robot object to be rendered.
569
+ """
570
+
571
+ def __init__(self, robot):
572
+ self.pose = robot.pose
573
+ if robot.head_angle_rad is None:
574
+ self.head_angle = util.radians(0.0)
575
+ else:
576
+ self.head_angle = util.radians(robot.head_angle_rad)
577
+ if robot.lift_height_mm is None:
578
+ self.lift_position = util.distance_mm(0.0)
579
+ else:
580
+ self.lift_position = util.distance_mm(robot.lift_height_mm)
581
+
582
+
583
+ class WorldRenderFrame(): # pylint: disable=too-few-public-methods
584
+ """Minimal copy of the World's state for 1 frame of rendering.
585
+
586
+ :param robot: the robot object to be rendered, which also has handles to the other objects
587
+ defined in it's world class.
588
+ """
589
+
590
+ def __init__(self, robot, connecting_to_cube):
591
+
592
+ self.connected_cube = robot.world.connected_light_cube is not None
593
+ self.connecting_to_cube = connecting_to_cube
594
+ self.robot_frame = RobotRenderFrame(robot)
595
+
596
+ self.cube_frames: List[CubeRenderFrame] = []
597
+ if robot.world.connected_light_cube is not None:
598
+ self.cube_frames.append(CubeRenderFrame(robot.world.connected_light_cube))
599
+
600
+ self.face_frames: List[FaceRenderFrame] = []
601
+ for face in robot.world.visible_faces:
602
+ # Ignore faces that have a newer version (with updated id)
603
+ # or if they haven't been seen in a while.
604
+ if not face.has_updated_face_id and (face.time_since_last_seen < 60):
605
+ self.face_frames.append(FaceRenderFrame(face))
606
+
607
+ self.custom_object_frames = []
608
+ for obj in robot.world.all_objects:
609
+ is_custom = isinstance(obj, CustomObject)
610
+ is_fixed = isinstance(obj, FixedCustomObject)
611
+ if is_custom or is_fixed:
612
+ self.custom_object_frames.append(CustomObjectRenderFrame(obj, is_fixed))
613
+
614
+ def cube_connected(self):
615
+ '''Is there a light cube connected to Vector'''
616
+ return self.connected_cube
617
+
618
+ def cube_connecting(self):
619
+ '''Is there a current attempt to connect to a light cube'''
620
+ return self.connecting_to_cube