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
anki_vector/nav_map.py ADDED
@@ -0,0 +1,409 @@
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
+ """A 2D navigation memory map of the world around Vector.
16
+
17
+ Vector builds a memory map of the navigable world around him as he drives
18
+ around. This is mostly based on where objects are seen (the cubes, charger, and
19
+ any custom objects), and also includes where Vector detects cliffs/drops, and
20
+ visible edges (e.g. sudden changes in color).
21
+
22
+ This differs from a standard occupancy map in that it doesn't deal with
23
+ probabilities of occupancy, but instead encodes what type of content is there.
24
+
25
+ To use the map you must first call :meth:`anki_vector.nav_map.NavMapComponent.init_nav_map_feed`
26
+ with a positive frequency so that the data is streamed to the SDK.
27
+ """
28
+
29
+ # __all__ should order by constants, event classes, other classes, functions.
30
+ __all__ = ['EvtNavMapUpdate',
31
+ 'NavMapComponent', 'NavMapGrid', 'NavMapGridNode',
32
+ 'NavNodeContentTypes']
33
+
34
+ import asyncio
35
+ from concurrent.futures import CancelledError
36
+ from enum import Enum
37
+ from logging import Logger
38
+ from typing import List
39
+
40
+ from . import util
41
+ from .events import Events
42
+ from .exceptions import VectorException
43
+ from .messaging import protocol
44
+
45
+
46
+ class EvtNavMapUpdate(): # pylint: disable=too-few-public-methods
47
+ """Dispatched when a new nav map is received.
48
+
49
+ :param nav_map: The current state of the robot's nav map.
50
+ """
51
+
52
+ def __init__(self, nav_map):
53
+ self.nav_map = nav_map
54
+
55
+
56
+ class NavNodeContentTypes(Enum): # pylint: disable=too-few-public-methods
57
+ """The content types for a :class:`NavMapGridNode`.
58
+ """
59
+
60
+ #: The contents of the node is unknown.
61
+ Unknown = protocol.NavNodeContentType.Value("NAV_NODE_UNKNOWN")
62
+
63
+ #: The node is clear of obstacles, because Vector has seen objects on the
64
+ #: other side, but it might contain a cliff. The node will be marked as
65
+ #: either :attr:`Cliff` or :attr:`ClearOfCliff` once Vector has driven there.
66
+ ClearOfObstacle = protocol.NavNodeContentType.Value("NAV_NODE_CLEAR_OF_OBSTACLE")
67
+
68
+ #: The node is clear of any cliffs (a sharp drop) or obstacles.
69
+ ClearOfCliff = protocol.NavNodeContentType.Value("NAV_NODE_CLEAR_OF_CLIFF")
70
+
71
+ #: The node contains a :class:`~anki_vector.objects.LightCube`.
72
+ ObstacleCube = protocol.NavNodeContentType.Value("NAV_NODE_OBSTACLE_CUBE")
73
+
74
+ #: The node contains a proximity detected obstacle which has not been explored.
75
+ ObstacleProximity = protocol.NavNodeContentType.Value("NAV_NODE_OBSTACLE_PROXIMITY")
76
+
77
+ #: The node contains a proximity detected obstacle which has been explored.
78
+ ObstacleProximityExplored = protocol.NavNodeContentType.Value("NAV_NODE_OBSTACLE_PROXIMITY_EXPLORED")
79
+
80
+ #: The node contains an unrecognized obstacle.
81
+ ObstacleUnrecognized = protocol.NavNodeContentType.Value("NAV_NODE_OBSTACLE_UNRECOGNIZED")
82
+
83
+ #: The node contains a cliff (a sharp drop).
84
+ Cliff = protocol.NavNodeContentType.Value("NAV_NODE_CLIFF")
85
+
86
+ #: The node contains a visible edge (based on the camera feed).
87
+ InterestingEdge = protocol.NavNodeContentType.Value("NAV_NODE_INTERESTING_EDGE")
88
+
89
+ # This entry is undocumented and not currently used
90
+ NonInterestingEdge = protocol.NavNodeContentType.Value("NAV_NODE_NON_INTERESTING_EDGE")
91
+
92
+
93
+ class NavMapGridNode:
94
+ """A node in a :class:`NavMapGrid`.
95
+
96
+ Leaf nodes contain content, all other nodes are split into 4 equally sized
97
+ children.
98
+
99
+ Child node indices are stored in the following X,Y orientation:
100
+
101
+ +---+----+---+
102
+ | ^ | 2 | 0 |
103
+ +---+----+---+
104
+ | Y | 3 | 1 |
105
+ +---+----+---+
106
+ | | X->| |
107
+ +---+----+---+
108
+ """
109
+
110
+ def __init__(self, depth: int, size: float, center: util.Vector3, parent: 'NavMapGridNode', logger: Logger):
111
+ #: The depth of this node (i.e. how far down the quad-tree it is).
112
+ self.depth = depth
113
+
114
+ #: The size (width or length) of this square node.
115
+ self.size = size
116
+
117
+ #: The center of this node.
118
+ self.center = center
119
+
120
+ #: The parent of this node. Is ``None`` for the root node.
121
+ self.parent = parent
122
+
123
+ #: ``None`` for leaf nodes, a list of 4 child nodes otherwise.
124
+ self.children: List[NavMapGridNode] = None
125
+
126
+ #: The content type in this node. Only leaf nodes have content,
127
+ #: this is ``None`` for all other nodes.
128
+ self.content: protocol.NavNodeContentType = None
129
+
130
+ self._next_child = 0 # Used when building to track which branch to follow
131
+
132
+ self._logger = logger
133
+
134
+ def __repr__(self):
135
+ return '<%s center: %s size: %s content: %s>' % (
136
+ self.__class__.__name__, self.center, self.size, self.content)
137
+
138
+ def contains_point(self, x: float, y: float) -> bool:
139
+ """Test if the node contains the given x,y coordinates.
140
+
141
+ :param x: x coordinate for the point.
142
+ :param y: y coordinate for the point.
143
+
144
+ Returns:
145
+ True if the node contains the point, False otherwise.
146
+ """
147
+ half_size = self.size * 0.5
148
+ dist_x = abs(self.center.x - x)
149
+ dist_y = abs(self.center.y - y)
150
+ return (dist_x <= half_size) and (dist_y <= half_size)
151
+
152
+ def _get_node(self, x: float, y: float, assumed_in_bounds: bool) -> 'NavMapGridNode':
153
+ if not assumed_in_bounds and not self.contains_point(x, y):
154
+ # point is out of bounds
155
+ return None
156
+
157
+ if self.children is None:
158
+ return self
159
+
160
+ x_offset = 2 if x < self.center.x else 0
161
+ y_offset = 1 if y < self.center.y else 0
162
+ child_node = self.children[x_offset + y_offset]
163
+ # child node is by definition in bounds / on boundary
164
+ return child_node._get_node(x, y, True) # pylint: disable=protected-access
165
+
166
+ def get_node(self, x: float, y: float) -> 'NavMapGridNode':
167
+ """Get the node at the given x,y coordinates.
168
+
169
+ :param x: x coordinate for the point.
170
+ :param y: y coordinate for the point.
171
+
172
+ Returns:
173
+ The smallest node that includes the point.
174
+ Will be ``None`` if the point is outside of the map.
175
+ """
176
+ return self._get_node(x, y, assumed_in_bounds=False)
177
+
178
+ def get_content(self, x: float, y: float) -> protocol.NavNodeContentType:
179
+ """Get the node's content at the given x,y coordinates.
180
+
181
+ :param x: x coordinate for the point.
182
+ :param y: y coordinate for the point.
183
+
184
+ Returns:
185
+ The content included at that point. Will be :attr:`NavNodeContentTypes.Unknown`
186
+ if the point is outside of the map.
187
+ """
188
+ node = self.get_node(x, y)
189
+ if node:
190
+ return node.content
191
+
192
+ return NavNodeContentTypes.Unknown
193
+
194
+ def add_child(self, content: protocol.NavNodeContentType, depth: int) -> bool:
195
+ """Add a child node to the quad tree.
196
+
197
+ The quad-tree is serialized to a flat list of nodes, we deserialize
198
+ back to a quad-tree structure here, with the depth of each node
199
+ indicating where it is placed.
200
+
201
+ :param content: The content to store in the leaf node.
202
+ :param depth: The depth that this leaf node is located at.
203
+
204
+ Returns:
205
+ True if parent should use the next child for future add_child
206
+ calls.
207
+ """
208
+ if depth > self.depth:
209
+ self._logger.error("NavMapGridNode depth %s > %s", depth, self.depth)
210
+ if self._next_child > 3:
211
+ self._logger.error("NavMapGridNode _next_child %s (>3) at depth %s", self._next_child, self.depth)
212
+
213
+ if self.depth == depth:
214
+ if self.content is not None:
215
+ self._logger.error("NavMapGridNode: Clobbering %s at depth %s with %s",
216
+ self.content, self.depth, content)
217
+ self.content = content
218
+ # This node won't be further subdivided, and is now full
219
+ return True
220
+
221
+ if self.children is None:
222
+ # Create 4 child nodes for quad-tree structure
223
+ next_depth = self.depth - 1
224
+ next_size = self.size * 0.5
225
+ offset = next_size * 0.5
226
+ center1 = util.Vector3(self.center.x + offset, self.center.y + offset, self.center.z)
227
+ center2 = util.Vector3(self.center.x + offset, self.center.y - offset, self.center.z)
228
+ center3 = util.Vector3(self.center.x - offset, self.center.y + offset, self.center.z)
229
+ center4 = util.Vector3(self.center.x - offset, self.center.y - offset, self.center.z)
230
+ self.children = [NavMapGridNode(next_depth, next_size, center1, self, self._logger),
231
+ NavMapGridNode(next_depth, next_size, center2, self, self._logger),
232
+ NavMapGridNode(next_depth, next_size, center3, self, self._logger),
233
+ NavMapGridNode(next_depth, next_size, center4, self, self._logger)]
234
+ if self.children[self._next_child].add_child(content, depth):
235
+ # Child node is now full, start using the next child
236
+ self._next_child += 1
237
+
238
+ if self._next_child > 3:
239
+ # All children are now full - parent should start using the next child
240
+ return True
241
+
242
+ # Empty children remain - parent can keep using this child
243
+ return False
244
+
245
+
246
+ class NavMapGrid:
247
+ """A navigation memory map, stored as a quad-tree."""
248
+
249
+ def __init__(self, msg: protocol.NavMapFeedResponse, logger: Logger):
250
+ #: The origin ID for the map. Only maps and :class:`~anki_vector.util.Pose`
251
+ #: objects of the same origin ID are in the same coordinate frame and
252
+ #: can therefore be compared.
253
+ self.origin_id = msg.origin_id
254
+ root_center = util.Vector3(msg.map_info.root_center_x, msg.map_info.root_center_y, msg.map_info.root_center_z)
255
+ self._root_node = NavMapGridNode(msg.map_info.root_depth, msg.map_info.root_size_mm, root_center, None, logger)
256
+ for quad in msg.quad_infos:
257
+ self.add_quad(quad.content, quad.depth)
258
+
259
+ self._logger = logger
260
+
261
+ def __repr__(self):
262
+ return '<%s center: %s size: %s>' % (
263
+ self.__class__.__name__, self.center, self.size)
264
+
265
+ @property
266
+ def root_node(self) -> NavMapGridNode:
267
+ """The root node for the grid, contains all other nodes."""
268
+ return self._root_node
269
+
270
+ @property
271
+ def size(self) -> float:
272
+ """The size (width or length) of the square grid."""
273
+ return self._root_node.size
274
+
275
+ @property
276
+ def center(self) -> util.Vector3:
277
+ """The center of this map."""
278
+ return self._root_node.center
279
+
280
+ def contains_point(self, x: float, y: float) -> bool:
281
+ """Test if the map contains the given x,y coordinates.
282
+
283
+ :param x: x coordinate for the point.
284
+ :param y: y coordinate for the point.
285
+
286
+ Returns:
287
+ True if the map contains the point, False otherwise.
288
+ """
289
+ return self._root_node.contains_point(x, y)
290
+
291
+ def get_node(self, x: float, y: float) -> NavMapGridNode:
292
+ """Get the node at the given x,y coordinates.
293
+
294
+ :param x: x coordinate for the point.
295
+ :param y: y coordinate for the point.
296
+
297
+ Returns:
298
+ The smallest node that includes the point.
299
+ Will be ``None`` if the point is outside of the map.
300
+ """
301
+ return self._root_node.get_node(x, y)
302
+
303
+ def get_content(self, x: float, y: float) -> protocol.NavNodeContentType:
304
+ """Get the map's content at the given x,y coordinates.
305
+
306
+ :param x: x coordinate for the point.
307
+ :param y: y coordinate for the point.
308
+
309
+ .. testcode::
310
+
311
+ import anki_vector
312
+
313
+ with anki_vector.Robot(enable_nav_map_feed=True) as robot:
314
+ # Make sure Vector drives around so the nav map will update
315
+ robot.behavior.drive_off_charger()
316
+ robot.motors.set_wheel_motors(-100, 100)
317
+ latest_nav_map = robot.nav_map.latest_nav_map
318
+ content = latest_nav_map.get_content(0.0, 100.0)
319
+ print(f"Sampling point at 0.0, 100.0 and found content: {content}")
320
+
321
+ Returns:
322
+ The content included at that point. Will be :attr:`NavNodeContentTypes.Unknown`
323
+ if the point is outside of the map.
324
+ """
325
+ return self._root_node.get_content(x, y)
326
+
327
+ def add_quad(self, content: protocol.NavNodeContentType, depth: int):
328
+ """Adds a new quad to the nav map.
329
+
330
+ :param content: What content this node contains.
331
+ :param depth: How deep in the navMap this node is.
332
+ """
333
+ self._root_node.add_child(content, depth)
334
+
335
+
336
+ class NavMapComponent(util.Component):
337
+ """Represents Vector's navigation memory map.
338
+
339
+ The NavMapComponent object subscribes for nav memory map updates from the robot to store and dispatch.
340
+
341
+ The :class:`anki_vector.robot.Robot` or :class:`anki_vector.robot.AsyncRobot` instance hosts this component.
342
+
343
+ .. testcode::
344
+
345
+ import anki_vector
346
+
347
+ with anki_vector.Robot(enable_nav_map_feed=True) as robot:
348
+ # Make sure Vector drives around so the nav map will update
349
+ robot.behavior.drive_off_charger()
350
+ robot.motors.set_wheel_motors(-100, 100)
351
+ latest_nav_map = robot.nav_map.latest_nav_map
352
+
353
+ :param robot: A reference to the owner Robot object.
354
+ """
355
+
356
+ def __init__(self, robot):
357
+ super().__init__(robot)
358
+
359
+ self._latest_nav_map: NavMapGrid = None
360
+ self._nav_map_feed_task: asyncio.Task = None
361
+
362
+ @property
363
+ @util.block_while_none()
364
+ def latest_nav_map(self) -> NavMapGrid:
365
+ """:class:`NavMapGrid`: The most recently processed image received from the robot.
366
+
367
+ .. testcode::
368
+
369
+ import anki_vector
370
+
371
+ with anki_vector.Robot(enable_nav_map_feed=True) as robot:
372
+ # Make sure Vector drives around so the nav map will update
373
+ robot.behavior.drive_off_charger()
374
+ robot.motors.set_wheel_motors(-100, 100)
375
+ latest_nav_map = robot.nav_map.latest_nav_map
376
+ """
377
+ if not self._nav_map_feed_task or self._nav_map_feed_task.done():
378
+ raise VectorException("Nav map not initialized. Check that Robot parameter enable_nav_map_feed is set to True.")
379
+ return self._latest_nav_map
380
+
381
+ def init_nav_map_feed(self, frequency: float = 0.5) -> None:
382
+ """Begin nav map feed task.
383
+
384
+ :param frequency: How frequently to send nav map updates.
385
+ """
386
+ if not self._nav_map_feed_task or self._nav_map_feed_task.done():
387
+ self._nav_map_feed_task = self.conn.loop.create_task(self._request_and_handle_nav_maps(frequency))
388
+
389
+ def close_nav_map_feed(self) -> None:
390
+ """Cancel nav map feed task."""
391
+ if self._nav_map_feed_task:
392
+ self._nav_map_feed_task.cancel()
393
+ future = self.conn.run_coroutine(self._nav_map_feed_task)
394
+ future.result()
395
+ self._nav_map_feed_task = None
396
+
397
+ async def _request_and_handle_nav_maps(self, frequency: float) -> None:
398
+ """Queries and listens for nav map feed events from the robot.
399
+ Received events are parsed by a helper function.
400
+
401
+ :param frequency: How frequently to send nav map updates.
402
+ """
403
+ try:
404
+ req = protocol.NavMapFeedRequest(frequency=frequency)
405
+ async for evt in self.grpc_interface.NavMapFeed(req):
406
+ self._latest_nav_map = NavMapGrid(evt, self.logger)
407
+ await self._robot.events.dispatch_event(evt, Events.nav_map_update)
408
+ except CancelledError:
409
+ self.logger.debug('Nav Map feed task was cancelled. This is expected during disconnection.')