diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..3d0ddfa --- /dev/null +++ b/Makefile @@ -0,0 +1,44 @@ +.PHONY: dist examples license wheel installer + +version = $(shell perl -ne '/__version__ = "([^"]+)/ && print $$1;' anki_vector/version.py) + +license_targets = anki_vector/LICENSE.txt examples/LICENSE.txt +example_targets = dist/anki_vector_sdk_examples.tar.gz dist/anki_vector_sdk_examples.zip + +example_filenames = $(shell cd examples && find . -name '*.py' -o -name '*.txt' -o -name '*.png' -o -name '*.jpg' -o -name '*.md' -o -name '*.json') +example_pathnames = $(shell find examples -name '*.py' -o -name '*.txt' -o -name '*.png' -o -name '*.jpg' -o -name '*.md' -o -name '*.json') +sdist_filename = dist/anki_vector-$(version).tar.gz +wheel_filename = dist/anki_vector-$(version)-py3-none-any.whl + +license: $(license_targets) + +$(license_targets): LICENSE.txt + for fn in $(license_targets); do \ + cp LICENSE.txt $$fn; \ + done + +$(sdist_filename): anki_vector/LICENSE.txt anki_vector/assets/LICENSE.txt $(shell find anki_vector -name '*.py' -o -name '*.mtl' -o -name '*.obj' -o -name '*.jpg') + python3 setup.py sdist + +$(wheel_filename): anki_vector/LICENSE.txt anki_vector/assets/LICENSE.txt $(shell find anki_vector -name '*.py' -o -name '*.mtl' -o -name '*.obj' -o -name '*.jpg') + python3 setup.py bdist_wheel + +dist/anki_vector_sdk_examples.zip: examples/LICENSE.txt $(example_pathnames) + rm -f dist/anki_vector_sdk_examples.zip dist/anki_vector_sdk_examples_$(version).zip + rm -rf dist/anki_vector_sdk_examples_$(version) + mkdir dist/anki_vector_sdk_examples_$(version) + tar -C examples -c $(example_filenames) | tar -C dist/anki_vector_sdk_examples_$(version) -xv + cd dist && zip -r anki_vector_sdk_examples.zip anki_vector_sdk_examples_$(version) + cd dist && zip -r anki_vector_sdk_examples_$(version).zip anki_vector_sdk_examples_$(version) + +dist/anki_vector_sdk_examples.tar.gz: examples/LICENSE.txt $(example_pathnames) + rm -f dist/anki_vector_sdk_examples.tar.gz dist/anki_vector_sdk_examples_$(version).tar.gz + rm -rf dist/anki_vector_sdk_examples_$(version) + mkdir dist/anki_vector_sdk_examples_$(version) + tar -C examples -c $(example_filenames) | tar -C dist/anki_vector_sdk_examples_$(version) -xv + cd dist && tar -cvzf anki_vector_sdk_examples.tar.gz anki_vector_sdk_examples_$(version) + cp -a dist/anki_vector_sdk_examples.tar.gz dist/anki_vector_sdk_examples_$(version).tar.gz + +examples: dist/anki_vector_sdk_examples.tar.gz dist/anki_vector_sdk_examples.zip + +dist: $(sdist_filename) $(wheel_filename) examples diff --git a/README.md b/README.md index 6ef477b..cd655ae 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ Before connecting, you will need: * Vector's IP Address: The ip address can be found by first placing Vector on the charger, then double-clicking the button on his back, and finally raising and lowering his arms. It is possible for your ip to change based on your network settings, so it must be updated accordingly. Example: `192.168.43.48` * Vector's Serial Number: You may find this number on the underside of your robot. Example: `00e20115` -These will be needed to run the configure.py script and set up authentication from your device to your Vector. +These will be needed to run the `anki_vector.configure` executable submodule and set up authentication from your device to your Vector. Your device must have Python 3.6.1 or later installed. Please see the documentation pages mentioned below for instructions to install Python. @@ -19,7 +19,7 @@ Check out the documentation for setup instructions by opening docs/build/html/in --- -During setup, you will configure your `anki_vector` SDK authentication from a terminal using `configure.py`. +During setup, you will configure your `anki_vector` SDK authentication from a terminal using `'python3 -m anki_vector.configure`. By running this script, you will be asked to provide your Anki account credentials, and the script will download an authentication token and cert that will grant you access to the robot and his capabilities (such as camera and audio) as well as data stored on the robot (such as faces and photos). diff --git a/anki_vector/behavior.py b/anki_vector/behavior.py index 632797c..c904050 100644 --- a/anki_vector/behavior.py +++ b/anki_vector/behavior.py @@ -34,8 +34,9 @@ functions for all the behaviors. """ -__all__ = ["BehaviorComponent", "MAX_HEAD_ANGLE", "MAX_LIFT_HEIGHT", "MAX_LIFT_HEIGHT_MM", - "MIN_HEAD_ANGLE", "MIN_LIFT_HEIGHT", "MIN_LIFT_HEIGHT_MM"] +__all__ = ["MAX_HEAD_ANGLE", "MIN_HEAD_ANGLE", + "MAX_LIFT_HEIGHT", "MAX_LIFT_HEIGHT_MM", "MIN_LIFT_HEIGHT", "MIN_LIFT_HEIGHT_MM", + "BehaviorComponent"] from . import connection, objects, util @@ -43,13 +44,11 @@ # Constants -#: The minimum angle the robot's head can be set to -# TODO Clamp to this value. -MIN_HEAD_ANGLE = util.degrees(-22) +#: The minimum angle the robot's head can be set to. +MIN_HEAD_ANGLE = util.degrees(-22.0) #: The maximum angle the robot's head can be set to -# TODO Clamp to this value. -MAX_HEAD_ANGLE = util.degrees(45) +MAX_HEAD_ANGLE = util.degrees(45.0) # The lowest height-above-ground that lift can be moved to in millimeters. MIN_LIFT_HEIGHT_MM = 32.0 @@ -390,7 +389,6 @@ async def turn_in_place(self, return await self.grpc_interface.TurnInPlace(turn_in_place_request) - # TODO Clamp angle to MIN_HEAD_ANGLE and MAX_HEAD_ANGLE. @connection.on_connection_thread() async def set_head_angle(self, angle: util.Angle, @@ -402,6 +400,7 @@ async def set_head_angle(self, :param angle: Desired angle for Vector's head. (:const:`MIN_HEAD_ANGLE` to :const:`MAX_HEAD_ANGLE`). + (we clamp it to this range internally). :param accel: Acceleration of Vector's head in radians per second squared. :param max_speed: Maximum speed of Vector's head in radians per second. :param duration: Time for Vector's head to move in seconds. A value @@ -415,11 +414,24 @@ async def set_head_angle(self, import anki_vector from anki_vector.util import degrees + from anki_vector.behavior import MIN_HEAD_ANGLE, MAX_HEAD_ANGLE with anki_vector.Robot() as robot: - robot.behavior.set_head_angle(degrees(-22.0)) - robot.behavior.set_head_angle(degrees(45.0)) + # move head from minimum to maximum angle + robot.behavior.set_head_angle(MIN_HEAD_ANGLE) + robot.behavior.set_head_angle(MAX_HEAD_ANGLE) + # move head to middle + robot.behavior.set_head_angle(degrees(35.0)) """ + if angle < MIN_HEAD_ANGLE: + self.logger.warning("head angle %s too small, should be in %f..%f range - clamping", + angle.degrees, MIN_HEAD_ANGLE.degrees, MAX_HEAD_ANGLE.degrees) + angle = MIN_HEAD_ANGLE + elif angle > MAX_HEAD_ANGLE: + self.logger.warning("head angle %s too large, should be in %f..%f range - clamping", + angle.degrees, MIN_HEAD_ANGLE.degrees, MAX_HEAD_ANGLE.degrees) + angle = MAX_HEAD_ANGLE + set_head_angle_request = protocol.SetHeadAngleRequest(angle_rad=angle.radians, max_speed_rad_per_sec=max_speed, accel_rad_per_sec2=accel, diff --git a/configure.py b/anki_vector/configure/__main__.py similarity index 100% rename from configure.py rename to anki_vector/configure/__main__.py diff --git a/anki_vector/connection.py b/anki_vector/connection.py index 155c688..6671aaa 100644 --- a/anki_vector/connection.py +++ b/anki_vector/connection.py @@ -704,7 +704,7 @@ async def log_handler(conn: Connection, func: Coroutine, logger: logging.Logger, if not conn.requires_behavior_control: raise VectorControlException(func.__name__) logger.info(f"Delaying {func.__name__} until behavior control is granted") - await conn.control_granted_event.wait() + await asyncio.wait([conn.control_granted_event.wait()], timeout=10) logger.debug(f'Outgoing {func.__name__}: {args[1:] if log_messaging else "size = {} bytes".format(sys.getsizeof(args[1:]))}') try: result = await func(*args, **kwargs) @@ -735,7 +735,8 @@ def result(*args: List[Any], **kwargs: Dict[str, Any]) -> Any: self.conn.active_commands.append(future) def clear_when_done(fut): - self.conn.active_commands.remove(fut) + if fut in self.conn.active_commands: + self.conn.active_commands.remove(fut) future.add_done_callback(clear_when_done) if self.force_async: return future diff --git a/anki_vector/events.py b/anki_vector/events.py index 91c8f55..4b51c64 100644 --- a/anki_vector/events.py +++ b/anki_vector/events.py @@ -21,6 +21,7 @@ import asyncio from concurrent.futures import CancelledError from enum import Enum +import threading from typing import Callable import uuid @@ -63,6 +64,29 @@ class Events(Enum): nav_map_update = "nav_map_update" #: Python event containing nav map data. +class _EventCallback: + def __init__(self, callback, on_connection_thread: bool = False): + self._callback = callback + self._on_connection_thread = on_connection_thread + + @property + def on_connection_thread(self): + return self._on_connection_thread + + @property + def callback(self): + return self._callback + + def __eq__(self, other): + other_cb = other + if hasattr(other, "callback"): + other_cb = other.callback + return other_cb == self.callback + + def __hash__(self): + return self._callback.__hash__() + + class EventHandler: """Listen for Vector events.""" @@ -72,7 +96,10 @@ def __init__(self): self._conn_id = None self.listening_for_events = False self.event_future = None + self._thread: threading.Thread = None + self._loop: asyncio.BaseEventLoop = None self.subscribers = {} + self._done_signal: asyncio.Event = None def start(self, connection: Connection): """Start listening for events. Automatically called by the :class:`anki_vector.robot.Robot` class. @@ -82,7 +109,16 @@ def start(self, connection: Connection): """ self._conn = connection self.listening_for_events = True - self.event_future = asyncio.run_coroutine_threadsafe(self._handle_events(), self._conn.loop) + self._thread = threading.Thread(target=self._run_thread, daemon=True, name="Event Stream Handler Thread") + self._thread.start() + + def _run_thread(self): + self._loop = asyncio.new_event_loop() + asyncio.set_event_loop(self._loop) + self._done_signal = asyncio.Event(loop=self._loop) + # create an event stream handler on the connection thread + self.event_future = asyncio.run_coroutine_threadsafe(self._handle_event_stream(), self._conn.loop) + self._loop.run_until_complete(self._done_signal.wait()) def close(self): """Stop listening for events. Automatically called by the :class:`anki_vector.robot.Robot` class. @@ -93,6 +129,32 @@ def close(self): self.event_future.result() except CancelledError: pass + self._loop.call_soon_threadsafe(self._done_signal.set) + + def _notify(self, event_callback, event_name, event_data): + loop = self._loop + thread = self._thread + # For high priority events that shouldn't be blocked by user callbacks + # they will run directly on the connection thread. This should typically + # be used when setting robot properties from events. + if event_callback.on_connection_thread: + loop = self._conn.loop + thread = self._conn.thread + callback = event_callback.callback + if threading.current_thread() is thread: + if asyncio.iscoroutinefunction(callback): + asyncio.ensure_future(callback(event_name, event_data), loop=loop) + elif asyncio.iscoroutine(callback): + asyncio.ensure_future(callback, loop=loop) + else: + loop.call_soon(callback, event_name, event_data) + else: + if asyncio.iscoroutinefunction(callback): + asyncio.run_coroutine_threadsafe(callback(event_name, event_data), loop=loop) + elif asyncio.iscoroutine(callback): + asyncio.run_coroutine_threadsafe(callback, loop=loop) + else: + loop.call_soon_threadsafe(callback, event_name, event_data) async def dispatch_event_by_name(self, event_data, event_name: str = None): """Dispatches event to event listeners by name. @@ -101,8 +163,9 @@ async def dispatch_event_by_name(self, event_data, event_name: str = None): import anki_vector - def event_listener(_, msg): - print(msg) + def event_listener(name, msg): + print(name) # will print 'my_event' + print(msg) # will print 'my_event dispatched' with anki_vector.Robot() as robot: robot.events.subscribe_by_name(event_listener, event_name='my_event') @@ -116,13 +179,8 @@ def event_listener(_, msg): if event_name in self.subscribers.keys(): subscribers = self.subscribers[event_name].copy() - for func in subscribers: - if asyncio.iscoroutinefunction(func): - self._conn.run_soon(func(event_name, event_data)) - elif asyncio.iscoroutine(func): - self._conn.run_soon(func) - else: - func(event_name, event_data) + for callback in subscribers: + self._notify(callback, event_name, event_data) async def dispatch_event(self, event_data, event_type: Events): """Dispatches event to event listeners.""" @@ -147,7 +205,7 @@ def _unpackage_event(self, enum_key: str, event): return event_key, event_data - async def _handle_events(self): + async def _handle_event_stream(self): self._conn_id = bytes(uuid.uuid4().hex, "utf-8") try: req = protocol.EventRequest(connection_id=self._conn_id) @@ -162,14 +220,16 @@ async def _handle_events(self): except CancelledError: self.logger.debug('Event handler task was cancelled. This is expected during disconnection.') - def subscribe_by_name(self, func: Callable, event_name: str = None): + def subscribe_by_name(self, func: Callable, event_name: str = None, **kwargs): """Receive a method call when the specified event occurs. .. testcode:: - def event_listener(robot, msg): - print(msg) - robot.events.unsubscribe_by_name(event_listener, event_name='my_event') + import anki_vector + + def event_listener(name, msg): + print(name) # will print 'my_event' + print(msg) # will print 'my_event dispatched' with anki_vector.Robot() as robot: robot.events.subscribe_by_name(event_listener, event_name='my_event') @@ -180,12 +240,13 @@ def event_listener(robot, msg): """ if not event_name: self.logger.error('Bad event_name in subscribe.') + on_connection_thread = kwargs["on_connection_thread"] if "on_connection_thread" in kwargs else False if event_name not in self.subscribers.keys(): self.subscribers[event_name] = set() - self.subscribers[event_name].add(func) + self.subscribers[event_name].add(_EventCallback(func, on_connection_thread)) - def subscribe(self, func: Callable, event_type: Events = None): + def subscribe(self, func: Callable, event_type: Events = None, **kwargs): """Receive a method call when the specified event occurs. .. testcode:: @@ -193,26 +254,28 @@ def subscribe(self, func: Callable, event_type: Events = None): import anki_vector from anki_vector.events import Events from anki_vector.util import degrees + import functools import threading said_text = False + evt = threading.Event() + + def on_robot_observed_face(robot, event_type, event): + print("Vector sees a face") + global said_text + if not said_text: + said_text = True + robot.say_text("I see a face!") + evt.set() args = anki_vector.util.parse_command_args() with anki_vector.Robot(enable_face_detection=True) as robot: - evt = threading.Event() - - async def on_robot_observed_face(event_type, event): - print("Vector sees a face") - global said_text - if not said_text: - said_text = True - await robot.say_text("I see a face!") - evt.set() # If necessary, move Vector's Head and Lift to make it easy to see his face robot.behavior.set_head_angle(degrees(50.0)) robot.behavior.set_lift_height(0.0) + on_robot_observed_face = functools.partial(on_robot_observed_face, robot) robot.events.subscribe(on_robot_observed_face, Events.robot_observed_face) print("------ waiting for face events, press ctrl+c to exit early ------") @@ -233,16 +296,18 @@ async def on_robot_observed_face(event_type, event): event_name = event_type.value - self.subscribe_by_name(func, event_name) + self.subscribe_by_name(func, event_name, **kwargs) def unsubscribe_by_name(self, func: Callable, event_name: str = None): """Unregister a previously subscribed method from an event. .. testcode:: - def event_listener(robot, msg): - print(msg) - robot.events.unsubscribe_by_name(event_listener, event_name='my_event') + import anki_vector + + def event_listener(name, msg): + print(name) # will print 'my_event' + print(msg) # will print 'my_event dispatched' with anki_vector.Robot() as robot: robot.events.subscribe_by_name(event_listener, event_name='my_event') @@ -274,27 +339,28 @@ def unsubscribe(self, func: Callable, event_type: Events = None): import anki_vector from anki_vector.events import Events from anki_vector.util import degrees + import functools import threading said_text = False + evt = threading.Event() + + def on_robot_observed_face(robot, event_type, event): + print("Vector sees a face") + global said_text + if not said_text: + said_text = True + robot.say_text("I see a face!") + evt.set() args = anki_vector.util.parse_command_args() with anki_vector.Robot(enable_face_detection=True) as robot: - evt = threading.Event() - - async def on_robot_observed_face(event_type, event): - print("Vector sees a face") - global said_text - if not said_text: - said_text = True - await robot.say_text("I see a face!") - evt.set() # If necessary, move Vector's Head and Lift to make it easy to see his face robot.behavior.set_head_angle(degrees(50.0)) robot.behavior.set_lift_height(0.0) - + on_robot_observed_face = functools.partial(on_robot_observed_face, robot) robot.events.subscribe(on_robot_observed_face, Events.robot_observed_face) print("------ waiting for face events, press ctrl+c to exit early ------") diff --git a/anki_vector/exceptions.py b/anki_vector/exceptions.py index 37448a0..bed9463 100644 --- a/anki_vector/exceptions.py +++ b/anki_vector/exceptions.py @@ -137,7 +137,7 @@ class VectorNotReadyException(_VectorGenericException): class VectorControlTimeoutException(_VectorGenericException): """Failed to get control of Vector. -Please verify that Vector is connected to the internet, and consider trying to request a higher control level. +Please verify that Vector is connected to the internet, is on a flat surface, and is fully charged. """ diff --git a/anki_vector/messaging/messages.proto b/anki_vector/messaging/messages.proto index fee32c2..5792cbe 100644 --- a/anki_vector/messaging/messages.proto +++ b/anki_vector/messaging/messages.proto @@ -20,7 +20,6 @@ package Anki.Vector.external_interface; import "anki_vector/messaging/response_status.proto"; import "anki_vector/messaging/extensions.proto"; -import "anki_vector/messaging/onboarding_steps.proto"; // A null message used by streams to verify that the client is // still connected. @@ -176,6 +175,28 @@ message RobotState { TouchData touch_data = 17; } +enum RobotStatus +{ + ROBOT_STATUS_NONE = 0x0; + ROBOT_STATUS_IS_MOVING = 0x1; + ROBOT_STATUS_IS_CARRYING_BLOCK = 0x2; + ROBOT_STATUS_IS_PICKING_OR_PLACING = 0x4; + ROBOT_STATUS_IS_PICKED_UP = 0x8; + ROBOT_STATUS_IS_BUTTON_PRESSED = 0x10; + ROBOT_STATUS_IS_FALLING = 0x20; + ROBOT_STATUS_IS_ANIMATING = 0x40; + ROBOT_STATUS_IS_PATHING = 0x80; + ROBOT_STATUS_LIFT_IN_POS = 0x100; + ROBOT_STATUS_HEAD_IN_POS = 0x200; + ROBOT_STATUS_CALM_POWER_MODE = 0x400; + ROBOT_STATUS_IS_ON_CHARGER = 0x1000; + ROBOT_STATUS_IS_CHARGING = 0x2000; + ROBOT_STATUS_CLIFF_DETECTED = 0x4000; + ROBOT_STATUS_ARE_WHEELS_MOVING = 0x8000; + ROBOT_STATUS_IS_BEING_HELD = 0x10000; + ROBOT_STATUS_IS_MOTION_DETECTED = 0x20000; +} + message CladPoint { float x = 1; diff --git a/anki_vector/messaging/messages_pb2.py b/anki_vector/messaging/messages_pb2.py index c29df6b..7133b77 100644 --- a/anki_vector/messaging/messages_pb2.py +++ b/anki_vector/messaging/messages_pb2.py @@ -16,17 +16,103 @@ from anki_vector.messaging import response_status_pb2 as anki__vector_dot_messaging_dot_response__status__pb2 from anki_vector.messaging import extensions_pb2 as anki__vector_dot_messaging_dot_extensions__pb2 -from anki_vector.messaging import onboarding_steps_pb2 as anki__vector_dot_messaging_dot_onboarding__steps__pb2 DESCRIPTOR = _descriptor.FileDescriptor( name='anki_vector/messaging/messages.proto', package='Anki.Vector.external_interface', syntax='proto3', - serialized_pb=_b('\n$anki_vector/messaging/messages.proto\x12\x1e\x41nki.Vector.external_interface\x1a+anki_vector/messaging/response_status.proto\x1a&anki_vector/messaging/extensions.proto\x1a,anki_vector/messaging/onboarding_steps.proto\"\x0f\n\rKeepAlivePing\"\x19\n\tAnimation\x12\x0c\n\x04name\x18\x01 \x01(\t\"|\n\x12\x44riveWheelsRequest\x12\x17\n\x0fleft_wheel_mmps\x18\x01 \x01(\x02\x12\x18\n\x10right_wheel_mmps\x18\x02 \x01(\x02\x12\x18\n\x10left_wheel_mmps2\x18\x03 \x01(\x02\x12\x19\n\x11right_wheel_mmps2\x18\x04 \x01(\x02\"U\n\x13\x44riveWheelsResponse\x12>\n\x06status\x18\x01 \x01(\x0b\x32..Anki.Vector.external_interface.ResponseStatus\",\n\x0fMoveHeadRequest\x12\x19\n\x11speed_rad_per_sec\x18\x01 \x01(\x02\"R\n\x10MoveHeadResponse\x12>\n\x06status\x18\x01 \x01(\x0b\x32..Anki.Vector.external_interface.ResponseStatus\",\n\x0fMoveLiftRequest\x12\x19\n\x11speed_rad_per_sec\x18\x01 \x01(\x02\"R\n\x10MoveLiftResponse\x12>\n\x06status\x18\x01 \x01(\x0b\x32..Anki.Vector.external_interface.ResponseStatus\"\xb4\x01\n\x14PlayAnimationRequest\x12<\n\tanimation\x18\x01 \x01(\x0b\x32).Anki.Vector.external_interface.Animation\x12\r\n\x05loops\x18\x02 \x01(\r\x12\x19\n\x11ignore_body_track\x18\x03 \x01(\x08\x12\x19\n\x11ignore_head_track\x18\x04 \x01(\x08\x12\x19\n\x11ignore_lift_track\x18\x05 \x01(\x08\"\x98\x01\n\x15PlayAnimationResponse\x12>\n\x06status\x18\x01 \x01(\x0b\x32..Anki.Vector.external_interface.ResponseStatus\x12?\n\x06result\x18\x02 \x01(\x0e\x32/.Anki.Vector.external_interface.BehaviorResults\"\x17\n\x15ListAnimationsRequest\"\x9c\x01\n\x16ListAnimationsResponse\x12>\n\x06status\x18\x01 \x01(\x0b\x32..Anki.Vector.external_interface.ResponseStatus\x12\x42\n\x0f\x61nimation_names\x18\x02 \x03(\x0b\x32).Anki.Vector.external_interface.Animation\"_\n\x1a\x44isplayFaceImageRGBRequest\x12\x11\n\tface_data\x18\x01 \x01(\x0c\x12\x13\n\x0b\x64uration_ms\x18\x02 \x01(\r\x12\x19\n\x11interrupt_running\x18\x03 \x01(\x08\"]\n\x1b\x44isplayFaceImageRGBResponse\x12>\n\x06status\x18\x01 \x01(\x0b\x32..Anki.Vector.external_interface.ResponseStatus\"\x1b\n\x19MeetVictorFaceScanStarted\"\x1c\n\x1aMeetVictorFaceScanComplete\"\xbf\x02\n\x06Status\x12\x62\n\x1dmeet_victor_face_scan_started\x18\x02 \x01(\x0b\x32\x39.Anki.Vector.external_interface.MeetVictorFaceScanStartedH\x00\x12\x64\n\x1emeet_victor_face_scan_complete\x18\x03 \x01(\x0b\x32:.Anki.Vector.external_interface.MeetVictorFaceScanCompleteH\x00\x12\\\n\x19\x66\x61\x63\x65_enrollment_completed\x18\x04 \x01(\x0b\x32\x37.Anki.Vector.external_interface.FaceEnrollmentCompletedH\x00\x42\r\n\x0bstatus_type\"\xac\x01\n\x08WakeWord\x12H\n\x0fwake_word_begin\x18\x01 \x01(\x0b\x32-.Anki.Vector.external_interface.WakeWordBeginH\x00\x12\x44\n\rwake_word_end\x18\x02 \x01(\x0b\x32+.Anki.Vector.external_interface.WakeWordEndH\x00\x42\x10\n\x0ewake_word_type\"b\n\x11TimeStampedStatus\x12\x36\n\x06status\x18\x01 \x01(\x0b\x32&.Anki.Vector.external_interface.Status\x12\x15\n\rtimestamp_utc\x18\x02 \x01(\r\"p\n\nPoseStruct\x12\t\n\x01x\x18\x01 \x01(\x02\x12\t\n\x01y\x18\x02 \x01(\x02\x12\t\n\x01z\x18\x03 \x01(\x02\x12\n\n\x02q0\x18\x04 \x01(\x02\x12\n\n\x02q1\x18\x05 \x01(\x02\x12\n\n\x02q2\x18\x06 \x01(\x02\x12\n\n\x02q3\x18\x07 \x01(\x02\x12\x11\n\torigin_id\x18\x08 \x01(\r\",\n\tAccelData\x12\t\n\x01x\x18\x01 \x01(\x02\x12\t\n\x01y\x18\x02 \x01(\x02\x12\t\n\x01z\x18\x03 \x01(\x02\"+\n\x08GyroData\x12\t\n\x01x\x18\x01 \x01(\x02\x12\t\n\x01y\x18\x02 \x01(\x02\x12\t\n\x01z\x18\x03 \x01(\x02\"\xa3\x01\n\x08ProxData\x12\x13\n\x0b\x64istance_mm\x18\x01 \x01(\r\x12\x16\n\x0esignal_quality\x18\x02 \x01(\x02\x12\x19\n\x11is_in_valid_range\x18\x03 \x01(\x08\x12\x1f\n\x17is_valid_signal_quality\x18\x04 \x01(\x08\x12\x16\n\x0eis_lift_in_fov\x18\x05 \x01(\x08\x12\x16\n\x0eis_too_pitched\x18\x06 \x01(\x08\">\n\tTouchData\x12\x17\n\x0fraw_touch_value\x18\x01 \x01(\r\x12\x18\n\x10is_being_touched\x18\x02 \x01(\x08\"\x82\x05\n\nRobotState\x12\x38\n\x04pose\x18\x01 \x01(\x0b\x32*.Anki.Vector.external_interface.PoseStruct\x12\x16\n\x0epose_angle_rad\x18\x02 \x01(\x02\x12\x16\n\x0epose_pitch_rad\x18\x03 \x01(\x02\x12\x1d\n\x15left_wheel_speed_mmps\x18\x04 \x01(\x02\x12\x1e\n\x16right_wheel_speed_mmps\x18\x05 \x01(\x02\x12\x16\n\x0ehead_angle_rad\x18\x06 \x01(\x02\x12\x16\n\x0elift_height_mm\x18\x07 \x01(\x02\x12\x38\n\x05\x61\x63\x63\x65l\x18\x08 \x01(\x0b\x32).Anki.Vector.external_interface.AccelData\x12\x36\n\x04gyro\x18\t \x01(\x0b\x32(.Anki.Vector.external_interface.GyroData\x12\x1a\n\x12\x63\x61rrying_object_id\x18\n \x01(\x05\x12!\n\x19\x63\x61rrying_object_on_top_id\x18\x0b \x01(\x05\x12\x1f\n\x17head_tracking_object_id\x18\x0c \x01(\x05\x12\x1e\n\x16localized_to_object_id\x18\r \x01(\x05\x12\x1d\n\x15last_image_time_stamp\x18\x0e \x01(\r\x12\x0e\n\x06status\x18\x0f \x01(\r\x12;\n\tprox_data\x18\x10 \x01(\x0b\x32(.Anki.Vector.external_interface.ProxData\x12=\n\ntouch_data\x18\x11 \x01(\x0b\x32).Anki.Vector.external_interface.TouchData\"!\n\tCladPoint\x12\t\n\x01x\x18\x01 \x01(\x02\x12\t\n\x01y\x18\x02 \x01(\x02\"Q\n\x08\x43ladRect\x12\x12\n\nx_top_left\x18\x01 \x01(\x02\x12\x12\n\ny_top_left\x18\x02 \x01(\x02\x12\r\n\x05width\x18\x03 \x01(\x02\x12\x0e\n\x06height\x18\x04 \x01(\x02\"\x8a\x04\n\x11RobotObservedFace\x12\x0f\n\x07\x66\x61\x63\x65_id\x18\x01 \x01(\x05\x12\x11\n\ttimestamp\x18\x02 \x01(\r\x12\x38\n\x04pose\x18\x03 \x01(\x0b\x32*.Anki.Vector.external_interface.PoseStruct\x12:\n\x08img_rect\x18\x04 \x01(\x0b\x32(.Anki.Vector.external_interface.CladRect\x12\x0c\n\x04name\x18\x05 \x01(\t\x12\x44\n\nexpression\x18\x06 \x01(\x0e\x32\x30.Anki.Vector.external_interface.FacialExpression\x12\x19\n\x11\x65xpression_values\x18\x07 \x03(\r\x12;\n\x08left_eye\x18\x08 \x03(\x0b\x32).Anki.Vector.external_interface.CladPoint\x12<\n\tright_eye\x18\t \x03(\x0b\x32).Anki.Vector.external_interface.CladPoint\x12\x37\n\x04nose\x18\n \x03(\x0b\x32).Anki.Vector.external_interface.CladPoint\x12\x38\n\x05mouth\x18\x0b \x03(\x0b\x32).Anki.Vector.external_interface.CladPoint\"<\n\x1aRobotChangedObservedFaceID\x12\x0e\n\x06old_id\x18\x01 \x01(\x05\x12\x0e\n\x06new_id\x18\x02 \x01(\x05\"1\n\x10\x41ppIntentRequest\x12\x0e\n\x06intent\x18\x01 \x01(\t\x12\r\n\x05param\x18\x02 \x01(\t\"\x11\n\x0f\x41ppDisconnected\"S\n\x11\x41ppIntentResponse\x12>\n\x06status\x18\x01 \x01(\x0b\x32..Anki.Vector.external_interface.ResponseStatus\"~\n\x17\x46\x61\x63\x65\x45nrollmentCompleted\x12\x44\n\x06result\x18\x01 \x01(\x0e\x32\x34.Anki.Vector.external_interface.FaceEnrollmentResult\x12\x0f\n\x07\x66\x61\x63\x65_id\x18\x02 \x01(\x05\x12\x0c\n\x04name\x18\x03 \x01(\t\"\x1d\n\x1b\x43\x61ncelFaceEnrollmentRequest\"^\n\x1c\x43\x61ncelFaceEnrollmentResponse\x12>\n\x06status\x18\x01 \x01(\x0b\x32..Anki.Vector.external_interface.ResponseStatus\"\x1d\n\x1bRequestEnrolledNamesRequest\"\xc2\x01\n\x0fLoadedKnownFace\x12$\n\x1cseconds_since_first_enrolled\x18\x01 \x01(\x03\x12\"\n\x1aseconds_since_last_updated\x18\x02 \x01(\x03\x12\x1f\n\x17seconds_since_last_seen\x18\x03 \x01(\x03\x12%\n\x1dlast_seen_seconds_since_epoch\x18\x04 \x01(\x03\x12\x0f\n\x07\x66\x61\x63\x65_id\x18\x05 \x01(\x05\x12\x0c\n\x04name\x18\x06 \x01(\t\"9\n\x18RobotRenamedEnrolledFace\x12\x0f\n\x07\x66\x61\x63\x65_id\x18\x01 \x01(\x05\x12\x0c\n\x04name\x18\x02 \x01(\t\"\x9e\x01\n\x1cRequestEnrolledNamesResponse\x12>\n\x06status\x18\x01 \x01(\x0b\x32..Anki.Vector.external_interface.ResponseStatus\x12>\n\x05\x66\x61\x63\x65s\x18\x02 \x03(\x0b\x32/.Anki.Vector.external_interface.LoadedKnownFace\"T\n\x1dUpdateEnrolledFaceByIDRequest\x12\x0f\n\x07\x66\x61\x63\x65_id\x18\x01 \x01(\x05\x12\x10\n\x08old_name\x18\x02 \x01(\t\x12\x10\n\x08new_name\x18\x03 \x01(\t\"`\n\x1eUpdateEnrolledFaceByIDResponse\x12>\n\x06status\x18\x01 \x01(\x0b\x32..Anki.Vector.external_interface.ResponseStatus\"/\n\x1c\x45raseEnrolledFaceByIDRequest\x12\x0f\n\x07\x66\x61\x63\x65_id\x18\x01 \x01(\x05\"_\n\x1d\x45raseEnrolledFaceByIDResponse\x12>\n\x06status\x18\x01 \x01(\x0b\x32..Anki.Vector.external_interface.ResponseStatus\"\x1e\n\x1c\x45raseAllEnrolledFacesRequest\"_\n\x1d\x45raseAllEnrolledFacesResponse\x12>\n\x06status\x18\x01 \x01(\x0b\x32..Anki.Vector.external_interface.ResponseStatus\"\x88\x01\n\x16SetFaceToEnrollRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x13\n\x0bobserved_id\x18\x02 \x01(\x05\x12\x0f\n\x07save_id\x18\x03 \x01(\x05\x12\x15\n\rsave_to_robot\x18\x04 \x01(\x08\x12\x10\n\x08say_name\x18\x05 \x01(\x08\x12\x11\n\tuse_music\x18\x06 \x01(\x08\"Y\n\x17SetFaceToEnrollResponse\x12>\n\x06status\x18\x01 \x01(\x0b\x32..Anki.Vector.external_interface.ResponseStatus\"\x18\n\x16\x44riveOffChargerRequest\"\x9a\x01\n\x17\x44riveOffChargerResponse\x12>\n\x06status\x18\x01 \x01(\x0b\x32..Anki.Vector.external_interface.ResponseStatus\x12?\n\x06result\x18\x02 \x01(\x0e\x32/.Anki.Vector.external_interface.BehaviorResults\"\x17\n\x15\x44riveOnChargerRequest\"\x99\x01\n\x16\x44riveOnChargerResponse\x12>\n\x06status\x18\x01 \x01(\x0b\x32..Anki.Vector.external_interface.ResponseStatus\x12?\n\x06result\x18\x02 \x01(\x0e\x32/.Anki.Vector.external_interface.BehaviorResults\"\x0f\n\rWakeWordBegin\"8\n\x0bWakeWordEnd\x12\x14\n\x0cintent_heard\x18\x01 \x01(\x08\x12\x13\n\x0bintent_json\x18\x02 \x01(\t\"n\n\tPhotoInfo\x12\x10\n\x08photo_id\x18\x01 \x01(\r\x12\x15\n\rtimestamp_utc\x18\x02 \x01(\r\x12\x1b\n\x13photo_copied_to_app\x18\x03 \x01(\x08\x12\x1b\n\x13thumb_copied_to_app\x18\x04 \x01(\x08\"\x13\n\x11PhotosInfoRequest\"\x94\x01\n\x12PhotosInfoResponse\x12>\n\x06status\x18\x01 \x01(\x0b\x32..Anki.Vector.external_interface.ResponseStatus\x12>\n\x0bphoto_infos\x18\x02 \x03(\x0b\x32).Anki.Vector.external_interface.PhotoInfo\" \n\x0cPhotoRequest\x12\x10\n\x08photo_id\x18\x01 \x01(\r\"6\n\x10PhotoPathMessage\x12\x0f\n\x07success\x18\x01 \x01(\x08\x12\x11\n\tfull_path\x18\x02 \x01(\t\"o\n\rPhotoResponse\x12>\n\x06status\x18\x01 \x01(\x0b\x32..Anki.Vector.external_interface.ResponseStatus\x12\x0f\n\x07success\x18\x02 \x01(\x08\x12\r\n\x05image\x18\x03 \x01(\x0c\"$\n\x10ThumbnailRequest\x12\x10\n\x08photo_id\x18\x01 \x01(\r\":\n\x14ThumbnailPathMessage\x12\x0f\n\x07success\x18\x01 \x01(\x08\x12\x11\n\tfull_path\x18\x02 \x01(\t\"s\n\x11ThumbnailResponse\x12>\n\x06status\x18\x01 \x01(\x0b\x32..Anki.Vector.external_interface.ResponseStatus\x12\x0f\n\x07success\x18\x02 \x01(\x08\x12\r\n\x05image\x18\x03 \x01(\x0c\"&\n\x12\x44\x65letePhotoRequest\x12\x10\n\x08photo_id\x18\x01 \x01(\r\"f\n\x13\x44\x65letePhotoResponse\x12>\n\x06status\x18\x01 \x01(\x0b\x32..Anki.Vector.external_interface.ResponseStatus\x12\x0f\n\x07success\x18\x02 \x01(\x08\"\x1e\n\nPhotoTaken\x12\x10\n\x08photo_id\x18\x01 \x01(\r\"\xc1\x02\n\x11PathMotionProfile\x12\x12\n\nspeed_mmps\x18\x01 \x01(\x02\x12\x13\n\x0b\x61\x63\x63\x65l_mmps2\x18\x02 \x01(\x02\x12\x13\n\x0b\x64\x65\x63\x65l_mmps2\x18\x03 \x01(\x02\x12$\n\x1cpoint_turn_speed_rad_per_sec\x18\x04 \x01(\x02\x12%\n\x1dpoint_turn_accel_rad_per_sec2\x18\x05 \x01(\x02\x12%\n\x1dpoint_turn_decel_rad_per_sec2\x18\x06 \x01(\x02\x12\x17\n\x0f\x64ock_speed_mmps\x18\x07 \x01(\x02\x12\x18\n\x10\x64ock_accel_mmps2\x18\x08 \x01(\x02\x12\x18\n\x10\x64ock_decel_mmps2\x18\t \x01(\x02\x12\x1a\n\x12reverse_speed_mmps\x18\n \x01(\x02\x12\x11\n\tis_custom\x18\x0b \x01(\x08\"\xf8\x0c\n\x0c\x41\x63tionResult\x12K\n\x04\x63ode\x18\x01 \x01(\x0e\x32=.Anki.Vector.external_interface.ActionResult.ActionResultCode\"\x9a\x0c\n\x10\x41\x63tionResultCode\x12\x19\n\x15\x41\x43TION_RESULT_SUCCESS\x10\x00\x12\x1c\n\x15\x41\x43TION_RESULT_RUNNING\x10\x80\x80\x80\x08\x12,\n%ACTION_RESULT_CANCELLED_WHILE_RUNNING\x10\x80\x80\x80\x10\x12\x12\n\x0bNOT_STARTED\x10\x81\x80\x80\x10\x12\x0c\n\x05\x41\x42ORT\x10\x80\x80\x80\x18\x12\x13\n\x0c\x41NIM_ABORTED\x10\x81\x80\x80\x18\x12\x11\n\nBAD_MARKER\x10\x82\x80\x80\x18\x12\x16\n\x0f\x42\x41\x44_MESSAGE_TAG\x10\x83\x80\x80\x18\x12\x11\n\nBAD_OBJECT\x10\x84\x80\x80\x18\x12\x0f\n\x08\x42\x41\x44_POSE\x10\x85\x80\x80\x18\x12\x0e\n\x07\x42\x41\x44_TAG\x10\x86\x80\x80\x18\x12\x1e\n\x17\x43HARGER_UNPLUGGED_ABORT\x10\x87\x80\x80\x18\x12!\n\x1a\x43LIFF_ALIGN_FAILED_TIMEOUT\x10\x88\x80\x80\x18\x12$\n\x1d\x43LIFF_ALIGN_FAILED_NO_TURNING\x10\x89\x80\x80\x18\x12&\n\x1f\x43LIFF_ALIGN_FAILED_OVER_TURNING\x10\x8a\x80\x80\x18\x12\"\n\x1b\x43LIFF_ALIGN_FAILED_NO_WHITE\x10\x8b\x80\x80\x18\x12!\n\x1a\x43LIFF_ALIGN_FAILED_STOPPED\x10\x8c\x80\x80\x18\x12!\n\x1a\x46\x41ILED_SETTING_CALIBRATION\x10\x8d\x80\x80\x18\x12(\n!FOLLOWING_PATH_BUT_NOT_TRAVERSING\x10\x8e\x80\x80\x18\x12\x12\n\x0bINTERRUPTED\x10\x8f\x80\x80\x18\x12\x1f\n\x18INVALID_OFF_TREADS_STATE\x10\x90\x80\x80\x18\x12\x19\n\x12MISMATCHED_UP_AXIS\x10\x91\x80\x80\x18\x12\x13\n\x0cNO_ANIM_NAME\x10\x92\x80\x80\x18\x12\x16\n\x0fNO_DISTANCE_SET\x10\x93\x80\x80\x18\x12\x0e\n\x07NO_FACE\x10\x94\x80\x80\x18\x12\x12\n\x0bNO_GOAL_SET\x10\x95\x80\x80\x18\x12\x19\n\x12NO_PREACTION_POSES\x10\x96\x80\x80\x18\x12 \n\x19NOT_CARRYING_OBJECT_ABORT\x10\x97\x80\x80\x18\x12\x1b\n\x14NOT_ON_CHARGER_ABORT\x10\x98\x80\x80\x18\x12\x15\n\x0eNULL_SUBACTION\x10\x99\x80\x80\x18\x12!\n\x1aPATH_PLANNING_FAILED_ABORT\x10\x9a\x80\x80\x18\x12(\n!PICKUP_OBJECT_UNEXPECTEDLY_MOVING\x10\x9b\x80\x80\x18\x12#\n\x1cSEND_MESSAGE_TO_ROBOT_FAILED\x10\x9c\x80\x80\x18\x12\x1c\n\x15STILL_CARRYING_OBJECT\x10\x9d\x80\x80\x18\x12\x0e\n\x07TIMEOUT\x10\x9e\x80\x80\x18\x12\x14\n\rTRACKS_LOCKED\x10\x9f\x80\x80\x18\x12\x1d\n\x16UNEXPECTED_DOCK_ACTION\x10\xa0\x80\x80\x18\x12\x18\n\x11UNKNOWN_TOOL_CODE\x10\xa1\x80\x80\x18\x12\x1c\n\x15UPDATE_DERIVED_FAILED\x10\xa2\x80\x80\x18\x12 \n\x19VISUAL_OBSERVATION_FAILED\x10\xa3\x80\x80\x18\x12 \n\x19SHOULDNT_DRIVE_ON_CHARGER\x10\xa4\x80\x80\x18\x12\x0c\n\x05RETRY\x10\x80\x80\x80 \x12#\n\x1c\x44ID_NOT_REACH_PREACTION_POSE\x10\x81\x80\x80 \x12\x1d\n\x16\x46\x41ILED_TRAVERSING_PATH\x10\x82\x80\x80 \x12!\n\x1aLAST_PICK_AND_PLACE_FAILED\x10\x83\x80\x80 \x12$\n\x1dMOTOR_STOPPED_MAKING_PROGRESS\x10\x84\x80\x80 \x12 \n\x19NOT_CARRYING_OBJECT_RETRY\x10\x85\x80\x80 \x12\x1b\n\x14NOT_ON_CHARGER_RETRY\x10\x86\x80\x80 \x12!\n\x1aPATH_PLANNING_FAILED_RETRY\x10\x87\x80\x80 \x12\x1e\n\x17PLACEMENT_GOAL_NOT_FREE\x10\x88\x80\x80 \x12,\n%PICKUP_OBJECT_UNEXPECTEDLY_NOT_MOVING\x10\x89\x80\x80 \x12\x17\n\x10STILL_ON_CHARGER\x10\x8a\x80\x80 \x12\x1d\n\x16UNEXPECTED_PITCH_ANGLE\x10\x8b\x80\x80 \"\xa7\x01\n\x0fGoToPoseRequest\x12\x0c\n\x04x_mm\x18\x01 \x01(\x02\x12\x0c\n\x04y_mm\x18\x02 \x01(\x02\x12\x0b\n\x03rad\x18\x03 \x01(\x02\x12\x46\n\x0bmotion_prof\x18\x04 \x01(\x0b\x32\x31.Anki.Vector.external_interface.PathMotionProfile\x12\x0e\n\x06id_tag\x18\x05 \x01(\x05\x12\x13\n\x0bnum_retries\x18\x06 \x01(\x05\"\x90\x01\n\x10GoToPoseResponse\x12>\n\x06status\x18\x01 \x01(\x0b\x32..Anki.Vector.external_interface.ResponseStatus\x12<\n\x06result\x18\x02 \x01(\x0b\x32,.Anki.Vector.external_interface.ActionResult\"\xd0\x02\n\x13\x44ockWithCubeRequest\x12\x11\n\tobject_id\x18\x01 \x01(\x05\x12\x1f\n\x17\x64istance_from_marker_mm\x18\x02 \x01(\x02\x12\x1a\n\x12\x61pproach_angle_rad\x18\x03 \x01(\x02\x12\x45\n\x0e\x61lignment_type\x18\x04 \x01(\x0e\x32-.Anki.Vector.external_interface.AlignmentType\x12\x1a\n\x12use_approach_angle\x18\x05 \x01(\x08\x12\x19\n\x11use_pre_dock_pose\x18\x06 \x01(\x08\x12\x46\n\x0bmotion_prof\x18\x07 \x01(\x0b\x32\x31.Anki.Vector.external_interface.PathMotionProfile\x12\x0e\n\x06id_tag\x18\x08 \x01(\x05\x12\x13\n\x0bnum_retries\x18\t \x01(\x05\"\x94\x01\n\x14\x44ockWithCubeResponse\x12>\n\x06status\x18\x01 \x01(\x0b\x32..Anki.Vector.external_interface.ResponseStatus\x12<\n\x06result\x18\x02 \x01(\x0b\x32,.Anki.Vector.external_interface.ActionResult\"\x7f\n\x14\x44riveStraightRequest\x12\x12\n\nspeed_mmps\x18\x01 \x01(\x02\x12\x0f\n\x07\x64ist_mm\x18\x02 \x01(\x02\x12\x1d\n\x15should_play_animation\x18\x03 \x01(\x08\x12\x0e\n\x06id_tag\x18\x04 \x01(\x05\x12\x13\n\x0bnum_retries\x18\x05 \x01(\x05\"\x95\x01\n\x15\x44riveStraightResponse\x12>\n\x06status\x18\x01 \x01(\x0b\x32..Anki.Vector.external_interface.ResponseStatus\x12<\n\x06result\x18\x02 \x01(\x0b\x32,.Anki.Vector.external_interface.ActionResult\"\xa9\x01\n\x12TurnInPlaceRequest\x12\x11\n\tangle_rad\x18\x01 \x01(\x02\x12\x19\n\x11speed_rad_per_sec\x18\x02 \x01(\x02\x12\x1a\n\x12\x61\x63\x63\x65l_rad_per_sec2\x18\x03 \x01(\x02\x12\x0f\n\x07tol_rad\x18\x04 \x01(\x02\x12\x13\n\x0bis_absolute\x18\x05 \x01(\r\x12\x0e\n\x06id_tag\x18\x06 \x01(\x05\x12\x13\n\x0bnum_retries\x18\x07 \x01(\x05\"\x93\x01\n\x13TurnInPlaceResponse\x12>\n\x06status\x18\x01 \x01(\x0b\x32..Anki.Vector.external_interface.ResponseStatus\x12<\n\x06result\x18\x02 \x01(\x0b\x32,.Anki.Vector.external_interface.ActionResult\"\x9e\x01\n\x13SetHeadAngleRequest\x12\x11\n\tangle_rad\x18\x01 \x01(\x02\x12\x1d\n\x15max_speed_rad_per_sec\x18\x02 \x01(\x02\x12\x1a\n\x12\x61\x63\x63\x65l_rad_per_sec2\x18\x03 \x01(\x02\x12\x14\n\x0c\x64uration_sec\x18\x04 \x01(\x02\x12\x0e\n\x06id_tag\x18\x05 \x01(\x05\x12\x13\n\x0bnum_retries\x18\x06 \x01(\x05\"\x94\x01\n\x14SetHeadAngleResponse\x12>\n\x06status\x18\x01 \x01(\x0b\x32..Anki.Vector.external_interface.ResponseStatus\x12<\n\x06result\x18\x02 \x01(\x0b\x32,.Anki.Vector.external_interface.ActionResult\"\x9f\x01\n\x14SetLiftHeightRequest\x12\x11\n\theight_mm\x18\x01 \x01(\x02\x12\x1d\n\x15max_speed_rad_per_sec\x18\x02 \x01(\x02\x12\x1a\n\x12\x61\x63\x63\x65l_rad_per_sec2\x18\x03 \x01(\x02\x12\x14\n\x0c\x64uration_sec\x18\x04 \x01(\x02\x12\x0e\n\x06id_tag\x18\x05 \x01(\x05\x12\x13\n\x0bnum_retries\x18\x06 \x01(\x05\"\x95\x01\n\x15SetLiftHeightResponse\x12>\n\x06status\x18\x01 \x01(\x0b\x32..Anki.Vector.external_interface.ResponseStatus\x12<\n\x06result\x18\x02 \x01(\x0b\x32,.Anki.Vector.external_interface.ActionResult\"\xb9\x03\n\x0cNetworkStats\x12#\n\x1bg_net_stat1_num_connections\x18\x01 \x01(\x05\x12\x1f\n\x17g_net_stat2_latency_avg\x18\x02 \x01(\x02\x12\x1e\n\x16g_net_stat3_latency_sd\x18\x03 \x01(\x02\x12\x1f\n\x17g_net_stat4_latency_min\x18\x04 \x01(\x02\x12\x1f\n\x17g_net_stat5_latency_max\x18\x05 \x01(\x02\x12#\n\x1bg_net_stat6_ping_arrived_pc\x18\x06 \x01(\x02\x12%\n\x1dg_net_stat7_ext_queued_avg_ms\x18\x07 \x01(\x02\x12%\n\x1dg_net_stat8_ext_queued_min_ms\x18\x08 \x01(\x02\x12%\n\x1dg_net_stat9_ext_queued_max_ms\x18\t \x01(\x02\x12!\n\x19g_net_stata_queued_avg_ms\x18\n \x01(\x02\x12!\n\x19g_net_statb_queued_min_ms\x18\x0b \x01(\x02\x12!\n\x19g_net_statc_queued_max_ms\x18\x0c \x01(\x02\"\x15\n\x13\x42\x61tteryStateRequest\"\xc9\x02\n\x14\x42\x61tteryStateResponse\x12>\n\x06status\x18\x01 \x01(\x0b\x32..Anki.Vector.external_interface.ResponseStatus\x12\x43\n\rbattery_level\x18\x02 \x01(\x0e\x32,.Anki.Vector.external_interface.BatteryLevel\x12\x15\n\rbattery_volts\x18\x03 \x01(\x02\x12\x13\n\x0bis_charging\x18\x04 \x01(\x08\x12\x1e\n\x16is_on_charger_platform\x18\x05 \x01(\x08\x12\x1d\n\x15suggested_charger_sec\x18\x06 \x01(\x02\x12\x41\n\x0c\x63ube_battery\x18\x07 \x01(\x0b\x32+.Anki.Vector.external_interface.CubeBattery\"\xd3\x01\n\x0b\x43ubeBattery\x12K\n\x05level\x18\x01 \x01(\x0e\x32<.Anki.Vector.external_interface.CubeBattery.CubeBatteryLevel\x12\x12\n\nfactory_id\x18\x02 \x01(\t\x12\x15\n\rbattery_volts\x18\x03 \x01(\x02\x12#\n\x1btime_since_last_reading_sec\x18\x04 \x01(\x02\"\'\n\x10\x43ubeBatteryLevel\x12\x07\n\x03Low\x10\x00\x12\n\n\x06Normal\x10\x01\"\x15\n\x13VersionStateRequest\"\x83\x01\n\x14VersionStateResponse\x12>\n\x06status\x18\x01 \x01(\x0b\x32..Anki.Vector.external_interface.ResponseStatus\x12\x12\n\nos_version\x18\x02 \x01(\t\x12\x17\n\x0f\x65ngine_build_id\x18\x03 \x01(\t\"\x15\n\x13NetworkStateRequest\"\x9b\x01\n\x14NetworkStateResponse\x12>\n\x06status\x18\x01 \x01(\x0b\x32..Anki.Vector.external_interface.ResponseStatus\x12\x43\n\rnetwork_stats\x18\x02 \x01(\x0b\x32,.Anki.Vector.external_interface.NetworkStats\"Q\n\x0eSayTextRequest\x12\x0c\n\x04text\x18\x01 \x01(\t\x12\x18\n\x10use_vector_voice\x18\x02 \x01(\x08\x12\x17\n\x0f\x64uration_scalar\x18\x03 \x01(\x02\"\xf5\x01\n\x0fSayTextResponse\x12>\n\x06status\x18\x01 \x01(\x0b\x32..Anki.Vector.external_interface.ResponseStatus\x12M\n\x05state\x18\x02 \x01(\x0e\x32>.Anki.Vector.external_interface.SayTextResponse.UtteranceState\"S\n\x0eUtteranceState\x12\x0b\n\x07INVALID\x10\x00\x12\x0e\n\nGENERATING\x10\x01\x12\t\n\x05READY\x10\x02\x12\x0b\n\x07PLAYING\x10\x03\x12\x0c\n\x08\x46INISHED\x10\x04\"\x9b\x01\n\x0fStimulationInfo\x12\x16\n\x0e\x65motion_events\x18\x01 \x03(\t\x12\r\n\x05value\x18\x02 \x01(\x02\x12\x10\n\x08velocity\x18\x03 \x01(\x02\x12\r\n\x05\x61\x63\x63\x65l\x18\x04 \x01(\x02\x12\x1a\n\x12value_before_event\x18\x05 \x01(\x02\x12\x11\n\tmin_value\x18\x06 \x01(\x02\x12\x11\n\tmax_value\x18\x07 \x01(\x02\"Y\n\x14\x41udioSendModeRequest\x12\x41\n\x04mode\x18\x01 \x01(\x0e\x32\x33.Anki.Vector.external_interface.AudioProcessingMode\"Y\n\x14\x41udioSendModeChanged\x12\x41\n\x04mode\x18\x01 \x01(\x0e\x32\x33.Anki.Vector.external_interface.AudioProcessingMode\"\xe8\x01\n\nAudioChunk\x12\x18\n\x10robot_time_stamp\x18\x01 \x01(\r\x12\x10\n\x08group_id\x18\x02 \x01(\r\x12\x10\n\x08\x63hunk_id\x18\x03 \x01(\r\x12\x19\n\x11\x61udio_chunk_count\x18\x04 \x01(\r\x12\x14\n\x0csignal_power\x18\x05 \x01(\x0c\x12\x1b\n\x13\x64irection_strengths\x18\x06 \x01(\x0c\x12\x18\n\x10source_direction\x18\x07 \x01(\r\x12\x19\n\x11source_confidence\x18\x08 \x01(\r\x12\x19\n\x11noise_floor_power\x18\t \x01(\r\"\x12\n\x10\x41udioFeedRequest\"\xc8\x01\n\x11\x41udioFeedResponse\x12\x18\n\x10robot_time_stamp\x18\x01 \x01(\r\x12\x10\n\x08group_id\x18\x02 \x01(\r\x12\x14\n\x0csignal_power\x18\x03 \x01(\x0c\x12\x1b\n\x13\x64irection_strengths\x18\x04 \x01(\x0c\x12\x18\n\x10source_direction\x18\x05 \x01(\r\x12\x19\n\x11source_confidence\x18\x06 \x01(\r\x12\x19\n\x11noise_floor_power\x18\x07 \x01(\r:\x04\x80\xa6\x1d\x01\".\n\x1c\x45nableMarkerDetectionRequest\x12\x0e\n\x06\x65nable\x18\x01 \x01(\x08\"_\n\x1d\x45nableMarkerDetectionResponse\x12>\n\x06status\x18\x01 \x01(\x0b\x32..Anki.Vector.external_interface.ResponseStatus\"\xb1\x01\n\x1a\x45nableFaceDetectionRequest\x12\x0e\n\x06\x65nable\x18\x01 \x01(\x08\x12\x1e\n\x16\x65nable_smile_detection\x18\x02 \x01(\x08\x12$\n\x1c\x65nable_expression_estimation\x18\x03 \x01(\x08\x12\x1e\n\x16\x65nable_blink_detection\x18\x04 \x01(\x08\x12\x1d\n\x15\x65nable_gaze_detection\x18\x05 \x01(\x08\"]\n\x1b\x45nableFaceDetectionResponse\x12>\n\x06status\x18\x01 \x01(\x0b\x32..Anki.Vector.external_interface.ResponseStatus\".\n\x1c\x45nableMotionDetectionRequest\x12\x0e\n\x06\x65nable\x18\x01 \x01(\x08\"_\n\x1d\x45nableMotionDetectionResponse\x12>\n\x06status\x18\x01 \x01(\x0b\x32..Anki.Vector.external_interface.ResponseStatus\")\n\x17\x45nableMirrorModeRequest\x12\x0e\n\x06\x65nable\x18\x01 \x01(\x08\"Z\n\x18\x45nableMirrorModeResponse\x12>\n\x06status\x18\x01 \x01(\x0b\x32..Anki.Vector.external_interface.ResponseStatus\"\x14\n\x12MirrorModeDisabled\"-\n\x1b\x45nableImageStreamingRequest\x12\x0e\n\x06\x65nable\x18\x01 \x01(\x08\"^\n\x1c\x45nableImageStreamingResponse\x12>\n\x06status\x18\x01 \x01(\x0b\x32..Anki.Vector.external_interface.ResponseStatus\"\x19\n\x17VisionModesAutoDisabled\"\xd1\x03\n\nImageChunk\x12\x18\n\x10\x66rame_time_stamp\x18\x01 \x01(\r\x12\x10\n\x08image_id\x18\x02 \x01(\r\x12\r\n\x05width\x18\x03 \x01(\r\x12\x0e\n\x06height\x18\x04 \x01(\r\x12P\n\x0eimage_encoding\x18\x05 \x01(\x0e\x32\x38.Anki.Vector.external_interface.ImageChunk.ImageEncoding\x12\x15\n\rdisplay_index\x18\x06 \x01(\r\x12\x19\n\x11image_chunk_count\x18\x07 \x01(\r\x12\x10\n\x08\x63hunk_id\x18\x08 \x01(\r\x12\x0c\n\x04\x64\x61ta\x18\t \x01(\x0c\"\xd3\x01\n\rImageEncoding\x12\x17\n\x13NONE_IMAGE_ENCODING\x10\x00\x12\x0c\n\x08RAW_GRAY\x10\x01\x12\x0b\n\x07RAW_RGB\x10\x02\x12\x08\n\x04YUYV\x10\x03\x12\x0c\n\x08YUV420SP\x10\x04\x12\t\n\x05\x42\x41YER\x10\x05\x12\r\n\tJPEG_GRAY\x10\x06\x12\x0e\n\nJPEG_COLOR\x10\x07\x12\x19\n\x15JPEG_COLOR_HALF_WIDTH\x10\x08\x12\x17\n\x13JPEG_MINIMIZED_GRAY\x10\t\x12\x18\n\x14JPEG_MINIMIZED_COLOR\x10\n\"\x13\n\x11\x43\x61meraFeedRequest\"\xa6\x01\n\x12\x43\x61meraFeedResponse\x12\x18\n\x10\x66rame_time_stamp\x18\x01 \x01(\r\x12\x10\n\x08image_id\x18\x02 \x01(\r\x12P\n\x0eimage_encoding\x18\x03 \x01(\x0e\x32\x38.Anki.Vector.external_interface.ImageChunk.ImageEncoding\x12\x0c\n\x04\x64\x61ta\x18\x04 \x01(\x0c:\x04\x80\xa6\x1d\x01\"5\n\x12SetEyeColorRequest\x12\x0b\n\x03hue\x18\x01 \x01(\x02\x12\x12\n\nsaturation\x18\x02 \x01(\x02\"U\n\x13SetEyeColorResponse\x12>\n\x06status\x18\x01 \x01(\x0b\x32..Anki.Vector.external_interface.ResponseStatus\"\x96\x01\n\x18SDKInitializationRequest\x12\x1a\n\x12sdk_module_version\x18\x01 \x01(\t\x12\x16\n\x0epython_version\x18\x02 \x01(\t\x12\x1d\n\x15python_implementation\x18\x03 \x01(\t\x12\x12\n\nos_version\x18\x04 \x01(\t\x12\x13\n\x0b\x63pu_version\x18\x05 \x01(\t\"[\n\x19SDKInitializationResponse\x12>\n\x06status\x18\x01 \x01(\x0b\x32..Anki.Vector.external_interface.ResponseStatus*\xbd\x01\n\x10\x46\x61\x63ialExpression\x12\x16\n\x12\x45XPRESSION_UNKNOWN\x10\x00\x12\x16\n\x12\x45XPRESSION_NEUTRAL\x10\x01\x12\x18\n\x14\x45XPRESSION_HAPPINESS\x10\x02\x12\x17\n\x13\x45XPRESSION_SURPRISE\x10\x03\x12\x14\n\x10\x45XPRESSION_ANGER\x10\x04\x12\x16\n\x12\x45XPRESSION_SADNESS\x10\x05\x12\x14\n\x10\x45XPRESSION_COUNT\x10\x05\x1a\x02\x10\x01*\xcc\x01\n\x14\x46\x61\x63\x65\x45nrollmentResult\x12\x0b\n\x07SUCCESS\x10\x00\x12\x12\n\x0eSAW_WRONG_FACE\x10\x01\x12\x16\n\x12SAW_MULTIPLE_FACES\x10\x02\x12\r\n\tTIMED_OUT\x10\x03\x12\x0f\n\x0bSAVE_FAILED\x10\x04\x12\x0e\n\nINCOMPLETE\x10\x05\x12\r\n\tCANCELLED\x10\x06\x12\x0f\n\x0bNAME_IN_USE\x10\x07\x12\x16\n\x12NAMED_STORAGE_FULL\x10\x08\x12\x13\n\x0fUNKNOWN_FAILURE\x10\t*l\n\x0f\x42\x65haviorResults\x12\x1a\n\x16\x42\x45HAVIOR_INVALID_STATE\x10\x00\x12\x1b\n\x17\x42\x45HAVIOR_COMPLETE_STATE\x10\x01\x12 \n\x1c\x42\x45HAVIOR_WONT_ACTIVATE_STATE\x10\x02*S\n\x12\x41\x63tionTagConstants\x12\x13\n\x0fINVALID_SDK_TAG\x10\x00\x12\x13\n\rFIRST_SDK_TAG\x10\x81\x89z\x12\x13\n\x0cLAST_SDK_TAG\x10\xc0\x8d\xb7\x01*\x9e\x01\n\rAlignmentType\x12\x1a\n\x16\x41LIGNMENT_TYPE_UNKNOWN\x10\x00\x12\x1e\n\x1a\x41LIGNMENT_TYPE_LIFT_FINGER\x10\x01\x12\x1d\n\x19\x41LIGNMENT_TYPE_LIFT_PLATE\x10\x02\x12\x17\n\x13\x41LIGNMENT_TYPE_BODY\x10\x03\x12\x19\n\x15\x41LIGNMENT_TYPE_CUSTOM\x10\x04*s\n\x0c\x42\x61tteryLevel\x12\x19\n\x15\x42\x41TTERY_LEVEL_UNKNOWN\x10\x00\x12\x15\n\x11\x42\x41TTERY_LEVEL_LOW\x10\x01\x12\x19\n\x15\x42\x41TTERY_LEVEL_NOMINAL\x10\x02\x12\x16\n\x12\x42\x41TTERY_LEVEL_FULL\x10\x03*\xcc\x01\n\x0e\x41udioConstants\x12\x18\n\x14\x41UDIO_CONSTANTS_NULL\x10\x00\x12\x1c\n\x18MIC_DETECTION_DIRECTIONS\x10\x0c\x12%\n SAMPLE_COUNTS_PER_ENGINE_MESSAGE\x10\xa0\x01\x12\"\n\x1dSAMPLE_COUNTS_PER_SDK_MESSAGE\x10\xc0\x0c\x12\x1b\n\x16MICROPHONE_SAMPLE_RATE\x10\x89z\x12\x1a\n\x15PROCESSED_SAMPLE_RATE\x10\x80}*\x85\x01\n\x13\x41udioProcessingMode\x12\x11\n\rAUDIO_UNKNOWN\x10\x00\x12\r\n\tAUDIO_OFF\x10\x01\x12\x13\n\x0f\x41UDIO_FAST_MODE\x10\x02\x12\x1a\n\x16\x41UDIO_DIRECTIONAL_MODE\x10\x03\x12\x1b\n\x17\x41UDIO_VOICE_DETECT_MODE\x10\x04\x62\x06proto3') + serialized_pb=_b('\n$anki_vector/messaging/messages.proto\x12\x1e\x41nki.Vector.external_interface\x1a+anki_vector/messaging/response_status.proto\x1a&anki_vector/messaging/extensions.proto\"\x0f\n\rKeepAlivePing\"\x19\n\tAnimation\x12\x0c\n\x04name\x18\x01 \x01(\t\"|\n\x12\x44riveWheelsRequest\x12\x17\n\x0fleft_wheel_mmps\x18\x01 \x01(\x02\x12\x18\n\x10right_wheel_mmps\x18\x02 \x01(\x02\x12\x18\n\x10left_wheel_mmps2\x18\x03 \x01(\x02\x12\x19\n\x11right_wheel_mmps2\x18\x04 \x01(\x02\"U\n\x13\x44riveWheelsResponse\x12>\n\x06status\x18\x01 \x01(\x0b\x32..Anki.Vector.external_interface.ResponseStatus\",\n\x0fMoveHeadRequest\x12\x19\n\x11speed_rad_per_sec\x18\x01 \x01(\x02\"R\n\x10MoveHeadResponse\x12>\n\x06status\x18\x01 \x01(\x0b\x32..Anki.Vector.external_interface.ResponseStatus\",\n\x0fMoveLiftRequest\x12\x19\n\x11speed_rad_per_sec\x18\x01 \x01(\x02\"R\n\x10MoveLiftResponse\x12>\n\x06status\x18\x01 \x01(\x0b\x32..Anki.Vector.external_interface.ResponseStatus\"\xb4\x01\n\x14PlayAnimationRequest\x12<\n\tanimation\x18\x01 \x01(\x0b\x32).Anki.Vector.external_interface.Animation\x12\r\n\x05loops\x18\x02 \x01(\r\x12\x19\n\x11ignore_body_track\x18\x03 \x01(\x08\x12\x19\n\x11ignore_head_track\x18\x04 \x01(\x08\x12\x19\n\x11ignore_lift_track\x18\x05 \x01(\x08\"\x98\x01\n\x15PlayAnimationResponse\x12>\n\x06status\x18\x01 \x01(\x0b\x32..Anki.Vector.external_interface.ResponseStatus\x12?\n\x06result\x18\x02 \x01(\x0e\x32/.Anki.Vector.external_interface.BehaviorResults\"\x17\n\x15ListAnimationsRequest\"\x9c\x01\n\x16ListAnimationsResponse\x12>\n\x06status\x18\x01 \x01(\x0b\x32..Anki.Vector.external_interface.ResponseStatus\x12\x42\n\x0f\x61nimation_names\x18\x02 \x03(\x0b\x32).Anki.Vector.external_interface.Animation\"_\n\x1a\x44isplayFaceImageRGBRequest\x12\x11\n\tface_data\x18\x01 \x01(\x0c\x12\x13\n\x0b\x64uration_ms\x18\x02 \x01(\r\x12\x19\n\x11interrupt_running\x18\x03 \x01(\x08\"]\n\x1b\x44isplayFaceImageRGBResponse\x12>\n\x06status\x18\x01 \x01(\x0b\x32..Anki.Vector.external_interface.ResponseStatus\"\x1b\n\x19MeetVictorFaceScanStarted\"\x1c\n\x1aMeetVictorFaceScanComplete\"\xbf\x02\n\x06Status\x12\x62\n\x1dmeet_victor_face_scan_started\x18\x02 \x01(\x0b\x32\x39.Anki.Vector.external_interface.MeetVictorFaceScanStartedH\x00\x12\x64\n\x1emeet_victor_face_scan_complete\x18\x03 \x01(\x0b\x32:.Anki.Vector.external_interface.MeetVictorFaceScanCompleteH\x00\x12\\\n\x19\x66\x61\x63\x65_enrollment_completed\x18\x04 \x01(\x0b\x32\x37.Anki.Vector.external_interface.FaceEnrollmentCompletedH\x00\x42\r\n\x0bstatus_type\"\xac\x01\n\x08WakeWord\x12H\n\x0fwake_word_begin\x18\x01 \x01(\x0b\x32-.Anki.Vector.external_interface.WakeWordBeginH\x00\x12\x44\n\rwake_word_end\x18\x02 \x01(\x0b\x32+.Anki.Vector.external_interface.WakeWordEndH\x00\x42\x10\n\x0ewake_word_type\"b\n\x11TimeStampedStatus\x12\x36\n\x06status\x18\x01 \x01(\x0b\x32&.Anki.Vector.external_interface.Status\x12\x15\n\rtimestamp_utc\x18\x02 \x01(\r\"p\n\nPoseStruct\x12\t\n\x01x\x18\x01 \x01(\x02\x12\t\n\x01y\x18\x02 \x01(\x02\x12\t\n\x01z\x18\x03 \x01(\x02\x12\n\n\x02q0\x18\x04 \x01(\x02\x12\n\n\x02q1\x18\x05 \x01(\x02\x12\n\n\x02q2\x18\x06 \x01(\x02\x12\n\n\x02q3\x18\x07 \x01(\x02\x12\x11\n\torigin_id\x18\x08 \x01(\r\",\n\tAccelData\x12\t\n\x01x\x18\x01 \x01(\x02\x12\t\n\x01y\x18\x02 \x01(\x02\x12\t\n\x01z\x18\x03 \x01(\x02\"+\n\x08GyroData\x12\t\n\x01x\x18\x01 \x01(\x02\x12\t\n\x01y\x18\x02 \x01(\x02\x12\t\n\x01z\x18\x03 \x01(\x02\"\xa3\x01\n\x08ProxData\x12\x13\n\x0b\x64istance_mm\x18\x01 \x01(\r\x12\x16\n\x0esignal_quality\x18\x02 \x01(\x02\x12\x19\n\x11is_in_valid_range\x18\x03 \x01(\x08\x12\x1f\n\x17is_valid_signal_quality\x18\x04 \x01(\x08\x12\x16\n\x0eis_lift_in_fov\x18\x05 \x01(\x08\x12\x16\n\x0eis_too_pitched\x18\x06 \x01(\x08\">\n\tTouchData\x12\x17\n\x0fraw_touch_value\x18\x01 \x01(\r\x12\x18\n\x10is_being_touched\x18\x02 \x01(\x08\"\x82\x05\n\nRobotState\x12\x38\n\x04pose\x18\x01 \x01(\x0b\x32*.Anki.Vector.external_interface.PoseStruct\x12\x16\n\x0epose_angle_rad\x18\x02 \x01(\x02\x12\x16\n\x0epose_pitch_rad\x18\x03 \x01(\x02\x12\x1d\n\x15left_wheel_speed_mmps\x18\x04 \x01(\x02\x12\x1e\n\x16right_wheel_speed_mmps\x18\x05 \x01(\x02\x12\x16\n\x0ehead_angle_rad\x18\x06 \x01(\x02\x12\x16\n\x0elift_height_mm\x18\x07 \x01(\x02\x12\x38\n\x05\x61\x63\x63\x65l\x18\x08 \x01(\x0b\x32).Anki.Vector.external_interface.AccelData\x12\x36\n\x04gyro\x18\t \x01(\x0b\x32(.Anki.Vector.external_interface.GyroData\x12\x1a\n\x12\x63\x61rrying_object_id\x18\n \x01(\x05\x12!\n\x19\x63\x61rrying_object_on_top_id\x18\x0b \x01(\x05\x12\x1f\n\x17head_tracking_object_id\x18\x0c \x01(\x05\x12\x1e\n\x16localized_to_object_id\x18\r \x01(\x05\x12\x1d\n\x15last_image_time_stamp\x18\x0e \x01(\r\x12\x0e\n\x06status\x18\x0f \x01(\r\x12;\n\tprox_data\x18\x10 \x01(\x0b\x32(.Anki.Vector.external_interface.ProxData\x12=\n\ntouch_data\x18\x11 \x01(\x0b\x32).Anki.Vector.external_interface.TouchData\"!\n\tCladPoint\x12\t\n\x01x\x18\x01 \x01(\x02\x12\t\n\x01y\x18\x02 \x01(\x02\"Q\n\x08\x43ladRect\x12\x12\n\nx_top_left\x18\x01 \x01(\x02\x12\x12\n\ny_top_left\x18\x02 \x01(\x02\x12\r\n\x05width\x18\x03 \x01(\x02\x12\x0e\n\x06height\x18\x04 \x01(\x02\"\x8a\x04\n\x11RobotObservedFace\x12\x0f\n\x07\x66\x61\x63\x65_id\x18\x01 \x01(\x05\x12\x11\n\ttimestamp\x18\x02 \x01(\r\x12\x38\n\x04pose\x18\x03 \x01(\x0b\x32*.Anki.Vector.external_interface.PoseStruct\x12:\n\x08img_rect\x18\x04 \x01(\x0b\x32(.Anki.Vector.external_interface.CladRect\x12\x0c\n\x04name\x18\x05 \x01(\t\x12\x44\n\nexpression\x18\x06 \x01(\x0e\x32\x30.Anki.Vector.external_interface.FacialExpression\x12\x19\n\x11\x65xpression_values\x18\x07 \x03(\r\x12;\n\x08left_eye\x18\x08 \x03(\x0b\x32).Anki.Vector.external_interface.CladPoint\x12<\n\tright_eye\x18\t \x03(\x0b\x32).Anki.Vector.external_interface.CladPoint\x12\x37\n\x04nose\x18\n \x03(\x0b\x32).Anki.Vector.external_interface.CladPoint\x12\x38\n\x05mouth\x18\x0b \x03(\x0b\x32).Anki.Vector.external_interface.CladPoint\"<\n\x1aRobotChangedObservedFaceID\x12\x0e\n\x06old_id\x18\x01 \x01(\x05\x12\x0e\n\x06new_id\x18\x02 \x01(\x05\"1\n\x10\x41ppIntentRequest\x12\x0e\n\x06intent\x18\x01 \x01(\t\x12\r\n\x05param\x18\x02 \x01(\t\"\x11\n\x0f\x41ppDisconnected\"S\n\x11\x41ppIntentResponse\x12>\n\x06status\x18\x01 \x01(\x0b\x32..Anki.Vector.external_interface.ResponseStatus\"~\n\x17\x46\x61\x63\x65\x45nrollmentCompleted\x12\x44\n\x06result\x18\x01 \x01(\x0e\x32\x34.Anki.Vector.external_interface.FaceEnrollmentResult\x12\x0f\n\x07\x66\x61\x63\x65_id\x18\x02 \x01(\x05\x12\x0c\n\x04name\x18\x03 \x01(\t\"\x1d\n\x1b\x43\x61ncelFaceEnrollmentRequest\"^\n\x1c\x43\x61ncelFaceEnrollmentResponse\x12>\n\x06status\x18\x01 \x01(\x0b\x32..Anki.Vector.external_interface.ResponseStatus\"\x1d\n\x1bRequestEnrolledNamesRequest\"\xc2\x01\n\x0fLoadedKnownFace\x12$\n\x1cseconds_since_first_enrolled\x18\x01 \x01(\x03\x12\"\n\x1aseconds_since_last_updated\x18\x02 \x01(\x03\x12\x1f\n\x17seconds_since_last_seen\x18\x03 \x01(\x03\x12%\n\x1dlast_seen_seconds_since_epoch\x18\x04 \x01(\x03\x12\x0f\n\x07\x66\x61\x63\x65_id\x18\x05 \x01(\x05\x12\x0c\n\x04name\x18\x06 \x01(\t\"9\n\x18RobotRenamedEnrolledFace\x12\x0f\n\x07\x66\x61\x63\x65_id\x18\x01 \x01(\x05\x12\x0c\n\x04name\x18\x02 \x01(\t\"\x9e\x01\n\x1cRequestEnrolledNamesResponse\x12>\n\x06status\x18\x01 \x01(\x0b\x32..Anki.Vector.external_interface.ResponseStatus\x12>\n\x05\x66\x61\x63\x65s\x18\x02 \x03(\x0b\x32/.Anki.Vector.external_interface.LoadedKnownFace\"T\n\x1dUpdateEnrolledFaceByIDRequest\x12\x0f\n\x07\x66\x61\x63\x65_id\x18\x01 \x01(\x05\x12\x10\n\x08old_name\x18\x02 \x01(\t\x12\x10\n\x08new_name\x18\x03 \x01(\t\"`\n\x1eUpdateEnrolledFaceByIDResponse\x12>\n\x06status\x18\x01 \x01(\x0b\x32..Anki.Vector.external_interface.ResponseStatus\"/\n\x1c\x45raseEnrolledFaceByIDRequest\x12\x0f\n\x07\x66\x61\x63\x65_id\x18\x01 \x01(\x05\"_\n\x1d\x45raseEnrolledFaceByIDResponse\x12>\n\x06status\x18\x01 \x01(\x0b\x32..Anki.Vector.external_interface.ResponseStatus\"\x1e\n\x1c\x45raseAllEnrolledFacesRequest\"_\n\x1d\x45raseAllEnrolledFacesResponse\x12>\n\x06status\x18\x01 \x01(\x0b\x32..Anki.Vector.external_interface.ResponseStatus\"\x88\x01\n\x16SetFaceToEnrollRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x13\n\x0bobserved_id\x18\x02 \x01(\x05\x12\x0f\n\x07save_id\x18\x03 \x01(\x05\x12\x15\n\rsave_to_robot\x18\x04 \x01(\x08\x12\x10\n\x08say_name\x18\x05 \x01(\x08\x12\x11\n\tuse_music\x18\x06 \x01(\x08\"Y\n\x17SetFaceToEnrollResponse\x12>\n\x06status\x18\x01 \x01(\x0b\x32..Anki.Vector.external_interface.ResponseStatus\"\x18\n\x16\x44riveOffChargerRequest\"\x9a\x01\n\x17\x44riveOffChargerResponse\x12>\n\x06status\x18\x01 \x01(\x0b\x32..Anki.Vector.external_interface.ResponseStatus\x12?\n\x06result\x18\x02 \x01(\x0e\x32/.Anki.Vector.external_interface.BehaviorResults\"\x17\n\x15\x44riveOnChargerRequest\"\x99\x01\n\x16\x44riveOnChargerResponse\x12>\n\x06status\x18\x01 \x01(\x0b\x32..Anki.Vector.external_interface.ResponseStatus\x12?\n\x06result\x18\x02 \x01(\x0e\x32/.Anki.Vector.external_interface.BehaviorResults\"\x0f\n\rWakeWordBegin\"8\n\x0bWakeWordEnd\x12\x14\n\x0cintent_heard\x18\x01 \x01(\x08\x12\x13\n\x0bintent_json\x18\x02 \x01(\t\"n\n\tPhotoInfo\x12\x10\n\x08photo_id\x18\x01 \x01(\r\x12\x15\n\rtimestamp_utc\x18\x02 \x01(\r\x12\x1b\n\x13photo_copied_to_app\x18\x03 \x01(\x08\x12\x1b\n\x13thumb_copied_to_app\x18\x04 \x01(\x08\"\x13\n\x11PhotosInfoRequest\"\x94\x01\n\x12PhotosInfoResponse\x12>\n\x06status\x18\x01 \x01(\x0b\x32..Anki.Vector.external_interface.ResponseStatus\x12>\n\x0bphoto_infos\x18\x02 \x03(\x0b\x32).Anki.Vector.external_interface.PhotoInfo\" \n\x0cPhotoRequest\x12\x10\n\x08photo_id\x18\x01 \x01(\r\"6\n\x10PhotoPathMessage\x12\x0f\n\x07success\x18\x01 \x01(\x08\x12\x11\n\tfull_path\x18\x02 \x01(\t\"o\n\rPhotoResponse\x12>\n\x06status\x18\x01 \x01(\x0b\x32..Anki.Vector.external_interface.ResponseStatus\x12\x0f\n\x07success\x18\x02 \x01(\x08\x12\r\n\x05image\x18\x03 \x01(\x0c\"$\n\x10ThumbnailRequest\x12\x10\n\x08photo_id\x18\x01 \x01(\r\":\n\x14ThumbnailPathMessage\x12\x0f\n\x07success\x18\x01 \x01(\x08\x12\x11\n\tfull_path\x18\x02 \x01(\t\"s\n\x11ThumbnailResponse\x12>\n\x06status\x18\x01 \x01(\x0b\x32..Anki.Vector.external_interface.ResponseStatus\x12\x0f\n\x07success\x18\x02 \x01(\x08\x12\r\n\x05image\x18\x03 \x01(\x0c\"&\n\x12\x44\x65letePhotoRequest\x12\x10\n\x08photo_id\x18\x01 \x01(\r\"f\n\x13\x44\x65letePhotoResponse\x12>\n\x06status\x18\x01 \x01(\x0b\x32..Anki.Vector.external_interface.ResponseStatus\x12\x0f\n\x07success\x18\x02 \x01(\x08\"\x1e\n\nPhotoTaken\x12\x10\n\x08photo_id\x18\x01 \x01(\r\"\xc1\x02\n\x11PathMotionProfile\x12\x12\n\nspeed_mmps\x18\x01 \x01(\x02\x12\x13\n\x0b\x61\x63\x63\x65l_mmps2\x18\x02 \x01(\x02\x12\x13\n\x0b\x64\x65\x63\x65l_mmps2\x18\x03 \x01(\x02\x12$\n\x1cpoint_turn_speed_rad_per_sec\x18\x04 \x01(\x02\x12%\n\x1dpoint_turn_accel_rad_per_sec2\x18\x05 \x01(\x02\x12%\n\x1dpoint_turn_decel_rad_per_sec2\x18\x06 \x01(\x02\x12\x17\n\x0f\x64ock_speed_mmps\x18\x07 \x01(\x02\x12\x18\n\x10\x64ock_accel_mmps2\x18\x08 \x01(\x02\x12\x18\n\x10\x64ock_decel_mmps2\x18\t \x01(\x02\x12\x1a\n\x12reverse_speed_mmps\x18\n \x01(\x02\x12\x11\n\tis_custom\x18\x0b \x01(\x08\"\xf8\x0c\n\x0c\x41\x63tionResult\x12K\n\x04\x63ode\x18\x01 \x01(\x0e\x32=.Anki.Vector.external_interface.ActionResult.ActionResultCode\"\x9a\x0c\n\x10\x41\x63tionResultCode\x12\x19\n\x15\x41\x43TION_RESULT_SUCCESS\x10\x00\x12\x1c\n\x15\x41\x43TION_RESULT_RUNNING\x10\x80\x80\x80\x08\x12,\n%ACTION_RESULT_CANCELLED_WHILE_RUNNING\x10\x80\x80\x80\x10\x12\x12\n\x0bNOT_STARTED\x10\x81\x80\x80\x10\x12\x0c\n\x05\x41\x42ORT\x10\x80\x80\x80\x18\x12\x13\n\x0c\x41NIM_ABORTED\x10\x81\x80\x80\x18\x12\x11\n\nBAD_MARKER\x10\x82\x80\x80\x18\x12\x16\n\x0f\x42\x41\x44_MESSAGE_TAG\x10\x83\x80\x80\x18\x12\x11\n\nBAD_OBJECT\x10\x84\x80\x80\x18\x12\x0f\n\x08\x42\x41\x44_POSE\x10\x85\x80\x80\x18\x12\x0e\n\x07\x42\x41\x44_TAG\x10\x86\x80\x80\x18\x12\x1e\n\x17\x43HARGER_UNPLUGGED_ABORT\x10\x87\x80\x80\x18\x12!\n\x1a\x43LIFF_ALIGN_FAILED_TIMEOUT\x10\x88\x80\x80\x18\x12$\n\x1d\x43LIFF_ALIGN_FAILED_NO_TURNING\x10\x89\x80\x80\x18\x12&\n\x1f\x43LIFF_ALIGN_FAILED_OVER_TURNING\x10\x8a\x80\x80\x18\x12\"\n\x1b\x43LIFF_ALIGN_FAILED_NO_WHITE\x10\x8b\x80\x80\x18\x12!\n\x1a\x43LIFF_ALIGN_FAILED_STOPPED\x10\x8c\x80\x80\x18\x12!\n\x1a\x46\x41ILED_SETTING_CALIBRATION\x10\x8d\x80\x80\x18\x12(\n!FOLLOWING_PATH_BUT_NOT_TRAVERSING\x10\x8e\x80\x80\x18\x12\x12\n\x0bINTERRUPTED\x10\x8f\x80\x80\x18\x12\x1f\n\x18INVALID_OFF_TREADS_STATE\x10\x90\x80\x80\x18\x12\x19\n\x12MISMATCHED_UP_AXIS\x10\x91\x80\x80\x18\x12\x13\n\x0cNO_ANIM_NAME\x10\x92\x80\x80\x18\x12\x16\n\x0fNO_DISTANCE_SET\x10\x93\x80\x80\x18\x12\x0e\n\x07NO_FACE\x10\x94\x80\x80\x18\x12\x12\n\x0bNO_GOAL_SET\x10\x95\x80\x80\x18\x12\x19\n\x12NO_PREACTION_POSES\x10\x96\x80\x80\x18\x12 \n\x19NOT_CARRYING_OBJECT_ABORT\x10\x97\x80\x80\x18\x12\x1b\n\x14NOT_ON_CHARGER_ABORT\x10\x98\x80\x80\x18\x12\x15\n\x0eNULL_SUBACTION\x10\x99\x80\x80\x18\x12!\n\x1aPATH_PLANNING_FAILED_ABORT\x10\x9a\x80\x80\x18\x12(\n!PICKUP_OBJECT_UNEXPECTEDLY_MOVING\x10\x9b\x80\x80\x18\x12#\n\x1cSEND_MESSAGE_TO_ROBOT_FAILED\x10\x9c\x80\x80\x18\x12\x1c\n\x15STILL_CARRYING_OBJECT\x10\x9d\x80\x80\x18\x12\x0e\n\x07TIMEOUT\x10\x9e\x80\x80\x18\x12\x14\n\rTRACKS_LOCKED\x10\x9f\x80\x80\x18\x12\x1d\n\x16UNEXPECTED_DOCK_ACTION\x10\xa0\x80\x80\x18\x12\x18\n\x11UNKNOWN_TOOL_CODE\x10\xa1\x80\x80\x18\x12\x1c\n\x15UPDATE_DERIVED_FAILED\x10\xa2\x80\x80\x18\x12 \n\x19VISUAL_OBSERVATION_FAILED\x10\xa3\x80\x80\x18\x12 \n\x19SHOULDNT_DRIVE_ON_CHARGER\x10\xa4\x80\x80\x18\x12\x0c\n\x05RETRY\x10\x80\x80\x80 \x12#\n\x1c\x44ID_NOT_REACH_PREACTION_POSE\x10\x81\x80\x80 \x12\x1d\n\x16\x46\x41ILED_TRAVERSING_PATH\x10\x82\x80\x80 \x12!\n\x1aLAST_PICK_AND_PLACE_FAILED\x10\x83\x80\x80 \x12$\n\x1dMOTOR_STOPPED_MAKING_PROGRESS\x10\x84\x80\x80 \x12 \n\x19NOT_CARRYING_OBJECT_RETRY\x10\x85\x80\x80 \x12\x1b\n\x14NOT_ON_CHARGER_RETRY\x10\x86\x80\x80 \x12!\n\x1aPATH_PLANNING_FAILED_RETRY\x10\x87\x80\x80 \x12\x1e\n\x17PLACEMENT_GOAL_NOT_FREE\x10\x88\x80\x80 \x12,\n%PICKUP_OBJECT_UNEXPECTEDLY_NOT_MOVING\x10\x89\x80\x80 \x12\x17\n\x10STILL_ON_CHARGER\x10\x8a\x80\x80 \x12\x1d\n\x16UNEXPECTED_PITCH_ANGLE\x10\x8b\x80\x80 \"\xa7\x01\n\x0fGoToPoseRequest\x12\x0c\n\x04x_mm\x18\x01 \x01(\x02\x12\x0c\n\x04y_mm\x18\x02 \x01(\x02\x12\x0b\n\x03rad\x18\x03 \x01(\x02\x12\x46\n\x0bmotion_prof\x18\x04 \x01(\x0b\x32\x31.Anki.Vector.external_interface.PathMotionProfile\x12\x0e\n\x06id_tag\x18\x05 \x01(\x05\x12\x13\n\x0bnum_retries\x18\x06 \x01(\x05\"\x90\x01\n\x10GoToPoseResponse\x12>\n\x06status\x18\x01 \x01(\x0b\x32..Anki.Vector.external_interface.ResponseStatus\x12<\n\x06result\x18\x02 \x01(\x0b\x32,.Anki.Vector.external_interface.ActionResult\"\xd0\x02\n\x13\x44ockWithCubeRequest\x12\x11\n\tobject_id\x18\x01 \x01(\x05\x12\x1f\n\x17\x64istance_from_marker_mm\x18\x02 \x01(\x02\x12\x1a\n\x12\x61pproach_angle_rad\x18\x03 \x01(\x02\x12\x45\n\x0e\x61lignment_type\x18\x04 \x01(\x0e\x32-.Anki.Vector.external_interface.AlignmentType\x12\x1a\n\x12use_approach_angle\x18\x05 \x01(\x08\x12\x19\n\x11use_pre_dock_pose\x18\x06 \x01(\x08\x12\x46\n\x0bmotion_prof\x18\x07 \x01(\x0b\x32\x31.Anki.Vector.external_interface.PathMotionProfile\x12\x0e\n\x06id_tag\x18\x08 \x01(\x05\x12\x13\n\x0bnum_retries\x18\t \x01(\x05\"\x94\x01\n\x14\x44ockWithCubeResponse\x12>\n\x06status\x18\x01 \x01(\x0b\x32..Anki.Vector.external_interface.ResponseStatus\x12<\n\x06result\x18\x02 \x01(\x0b\x32,.Anki.Vector.external_interface.ActionResult\"\x7f\n\x14\x44riveStraightRequest\x12\x12\n\nspeed_mmps\x18\x01 \x01(\x02\x12\x0f\n\x07\x64ist_mm\x18\x02 \x01(\x02\x12\x1d\n\x15should_play_animation\x18\x03 \x01(\x08\x12\x0e\n\x06id_tag\x18\x04 \x01(\x05\x12\x13\n\x0bnum_retries\x18\x05 \x01(\x05\"\x95\x01\n\x15\x44riveStraightResponse\x12>\n\x06status\x18\x01 \x01(\x0b\x32..Anki.Vector.external_interface.ResponseStatus\x12<\n\x06result\x18\x02 \x01(\x0b\x32,.Anki.Vector.external_interface.ActionResult\"\xa9\x01\n\x12TurnInPlaceRequest\x12\x11\n\tangle_rad\x18\x01 \x01(\x02\x12\x19\n\x11speed_rad_per_sec\x18\x02 \x01(\x02\x12\x1a\n\x12\x61\x63\x63\x65l_rad_per_sec2\x18\x03 \x01(\x02\x12\x0f\n\x07tol_rad\x18\x04 \x01(\x02\x12\x13\n\x0bis_absolute\x18\x05 \x01(\r\x12\x0e\n\x06id_tag\x18\x06 \x01(\x05\x12\x13\n\x0bnum_retries\x18\x07 \x01(\x05\"\x93\x01\n\x13TurnInPlaceResponse\x12>\n\x06status\x18\x01 \x01(\x0b\x32..Anki.Vector.external_interface.ResponseStatus\x12<\n\x06result\x18\x02 \x01(\x0b\x32,.Anki.Vector.external_interface.ActionResult\"\x9e\x01\n\x13SetHeadAngleRequest\x12\x11\n\tangle_rad\x18\x01 \x01(\x02\x12\x1d\n\x15max_speed_rad_per_sec\x18\x02 \x01(\x02\x12\x1a\n\x12\x61\x63\x63\x65l_rad_per_sec2\x18\x03 \x01(\x02\x12\x14\n\x0c\x64uration_sec\x18\x04 \x01(\x02\x12\x0e\n\x06id_tag\x18\x05 \x01(\x05\x12\x13\n\x0bnum_retries\x18\x06 \x01(\x05\"\x94\x01\n\x14SetHeadAngleResponse\x12>\n\x06status\x18\x01 \x01(\x0b\x32..Anki.Vector.external_interface.ResponseStatus\x12<\n\x06result\x18\x02 \x01(\x0b\x32,.Anki.Vector.external_interface.ActionResult\"\x9f\x01\n\x14SetLiftHeightRequest\x12\x11\n\theight_mm\x18\x01 \x01(\x02\x12\x1d\n\x15max_speed_rad_per_sec\x18\x02 \x01(\x02\x12\x1a\n\x12\x61\x63\x63\x65l_rad_per_sec2\x18\x03 \x01(\x02\x12\x14\n\x0c\x64uration_sec\x18\x04 \x01(\x02\x12\x0e\n\x06id_tag\x18\x05 \x01(\x05\x12\x13\n\x0bnum_retries\x18\x06 \x01(\x05\"\x95\x01\n\x15SetLiftHeightResponse\x12>\n\x06status\x18\x01 \x01(\x0b\x32..Anki.Vector.external_interface.ResponseStatus\x12<\n\x06result\x18\x02 \x01(\x0b\x32,.Anki.Vector.external_interface.ActionResult\"\xb9\x03\n\x0cNetworkStats\x12#\n\x1bg_net_stat1_num_connections\x18\x01 \x01(\x05\x12\x1f\n\x17g_net_stat2_latency_avg\x18\x02 \x01(\x02\x12\x1e\n\x16g_net_stat3_latency_sd\x18\x03 \x01(\x02\x12\x1f\n\x17g_net_stat4_latency_min\x18\x04 \x01(\x02\x12\x1f\n\x17g_net_stat5_latency_max\x18\x05 \x01(\x02\x12#\n\x1bg_net_stat6_ping_arrived_pc\x18\x06 \x01(\x02\x12%\n\x1dg_net_stat7_ext_queued_avg_ms\x18\x07 \x01(\x02\x12%\n\x1dg_net_stat8_ext_queued_min_ms\x18\x08 \x01(\x02\x12%\n\x1dg_net_stat9_ext_queued_max_ms\x18\t \x01(\x02\x12!\n\x19g_net_stata_queued_avg_ms\x18\n \x01(\x02\x12!\n\x19g_net_statb_queued_min_ms\x18\x0b \x01(\x02\x12!\n\x19g_net_statc_queued_max_ms\x18\x0c \x01(\x02\"\x15\n\x13\x42\x61tteryStateRequest\"\xc9\x02\n\x14\x42\x61tteryStateResponse\x12>\n\x06status\x18\x01 \x01(\x0b\x32..Anki.Vector.external_interface.ResponseStatus\x12\x43\n\rbattery_level\x18\x02 \x01(\x0e\x32,.Anki.Vector.external_interface.BatteryLevel\x12\x15\n\rbattery_volts\x18\x03 \x01(\x02\x12\x13\n\x0bis_charging\x18\x04 \x01(\x08\x12\x1e\n\x16is_on_charger_platform\x18\x05 \x01(\x08\x12\x1d\n\x15suggested_charger_sec\x18\x06 \x01(\x02\x12\x41\n\x0c\x63ube_battery\x18\x07 \x01(\x0b\x32+.Anki.Vector.external_interface.CubeBattery\"\xd3\x01\n\x0b\x43ubeBattery\x12K\n\x05level\x18\x01 \x01(\x0e\x32<.Anki.Vector.external_interface.CubeBattery.CubeBatteryLevel\x12\x12\n\nfactory_id\x18\x02 \x01(\t\x12\x15\n\rbattery_volts\x18\x03 \x01(\x02\x12#\n\x1btime_since_last_reading_sec\x18\x04 \x01(\x02\"\'\n\x10\x43ubeBatteryLevel\x12\x07\n\x03Low\x10\x00\x12\n\n\x06Normal\x10\x01\"\x15\n\x13VersionStateRequest\"\x83\x01\n\x14VersionStateResponse\x12>\n\x06status\x18\x01 \x01(\x0b\x32..Anki.Vector.external_interface.ResponseStatus\x12\x12\n\nos_version\x18\x02 \x01(\t\x12\x17\n\x0f\x65ngine_build_id\x18\x03 \x01(\t\"\x15\n\x13NetworkStateRequest\"\x9b\x01\n\x14NetworkStateResponse\x12>\n\x06status\x18\x01 \x01(\x0b\x32..Anki.Vector.external_interface.ResponseStatus\x12\x43\n\rnetwork_stats\x18\x02 \x01(\x0b\x32,.Anki.Vector.external_interface.NetworkStats\"Q\n\x0eSayTextRequest\x12\x0c\n\x04text\x18\x01 \x01(\t\x12\x18\n\x10use_vector_voice\x18\x02 \x01(\x08\x12\x17\n\x0f\x64uration_scalar\x18\x03 \x01(\x02\"\xf5\x01\n\x0fSayTextResponse\x12>\n\x06status\x18\x01 \x01(\x0b\x32..Anki.Vector.external_interface.ResponseStatus\x12M\n\x05state\x18\x02 \x01(\x0e\x32>.Anki.Vector.external_interface.SayTextResponse.UtteranceState\"S\n\x0eUtteranceState\x12\x0b\n\x07INVALID\x10\x00\x12\x0e\n\nGENERATING\x10\x01\x12\t\n\x05READY\x10\x02\x12\x0b\n\x07PLAYING\x10\x03\x12\x0c\n\x08\x46INISHED\x10\x04\"\x9b\x01\n\x0fStimulationInfo\x12\x16\n\x0e\x65motion_events\x18\x01 \x03(\t\x12\r\n\x05value\x18\x02 \x01(\x02\x12\x10\n\x08velocity\x18\x03 \x01(\x02\x12\r\n\x05\x61\x63\x63\x65l\x18\x04 \x01(\x02\x12\x1a\n\x12value_before_event\x18\x05 \x01(\x02\x12\x11\n\tmin_value\x18\x06 \x01(\x02\x12\x11\n\tmax_value\x18\x07 \x01(\x02\"Y\n\x14\x41udioSendModeRequest\x12\x41\n\x04mode\x18\x01 \x01(\x0e\x32\x33.Anki.Vector.external_interface.AudioProcessingMode\"Y\n\x14\x41udioSendModeChanged\x12\x41\n\x04mode\x18\x01 \x01(\x0e\x32\x33.Anki.Vector.external_interface.AudioProcessingMode\"\xe8\x01\n\nAudioChunk\x12\x18\n\x10robot_time_stamp\x18\x01 \x01(\r\x12\x10\n\x08group_id\x18\x02 \x01(\r\x12\x10\n\x08\x63hunk_id\x18\x03 \x01(\r\x12\x19\n\x11\x61udio_chunk_count\x18\x04 \x01(\r\x12\x14\n\x0csignal_power\x18\x05 \x01(\x0c\x12\x1b\n\x13\x64irection_strengths\x18\x06 \x01(\x0c\x12\x18\n\x10source_direction\x18\x07 \x01(\r\x12\x19\n\x11source_confidence\x18\x08 \x01(\r\x12\x19\n\x11noise_floor_power\x18\t \x01(\r\"\x12\n\x10\x41udioFeedRequest\"\xc8\x01\n\x11\x41udioFeedResponse\x12\x18\n\x10robot_time_stamp\x18\x01 \x01(\r\x12\x10\n\x08group_id\x18\x02 \x01(\r\x12\x14\n\x0csignal_power\x18\x03 \x01(\x0c\x12\x1b\n\x13\x64irection_strengths\x18\x04 \x01(\x0c\x12\x18\n\x10source_direction\x18\x05 \x01(\r\x12\x19\n\x11source_confidence\x18\x06 \x01(\r\x12\x19\n\x11noise_floor_power\x18\x07 \x01(\r:\x04\x80\xa6\x1d\x01\".\n\x1c\x45nableMarkerDetectionRequest\x12\x0e\n\x06\x65nable\x18\x01 \x01(\x08\"_\n\x1d\x45nableMarkerDetectionResponse\x12>\n\x06status\x18\x01 \x01(\x0b\x32..Anki.Vector.external_interface.ResponseStatus\"\xb1\x01\n\x1a\x45nableFaceDetectionRequest\x12\x0e\n\x06\x65nable\x18\x01 \x01(\x08\x12\x1e\n\x16\x65nable_smile_detection\x18\x02 \x01(\x08\x12$\n\x1c\x65nable_expression_estimation\x18\x03 \x01(\x08\x12\x1e\n\x16\x65nable_blink_detection\x18\x04 \x01(\x08\x12\x1d\n\x15\x65nable_gaze_detection\x18\x05 \x01(\x08\"]\n\x1b\x45nableFaceDetectionResponse\x12>\n\x06status\x18\x01 \x01(\x0b\x32..Anki.Vector.external_interface.ResponseStatus\".\n\x1c\x45nableMotionDetectionRequest\x12\x0e\n\x06\x65nable\x18\x01 \x01(\x08\"_\n\x1d\x45nableMotionDetectionResponse\x12>\n\x06status\x18\x01 \x01(\x0b\x32..Anki.Vector.external_interface.ResponseStatus\")\n\x17\x45nableMirrorModeRequest\x12\x0e\n\x06\x65nable\x18\x01 \x01(\x08\"Z\n\x18\x45nableMirrorModeResponse\x12>\n\x06status\x18\x01 \x01(\x0b\x32..Anki.Vector.external_interface.ResponseStatus\"\x14\n\x12MirrorModeDisabled\"-\n\x1b\x45nableImageStreamingRequest\x12\x0e\n\x06\x65nable\x18\x01 \x01(\x08\"^\n\x1c\x45nableImageStreamingResponse\x12>\n\x06status\x18\x01 \x01(\x0b\x32..Anki.Vector.external_interface.ResponseStatus\"\x19\n\x17VisionModesAutoDisabled\"\xd1\x03\n\nImageChunk\x12\x18\n\x10\x66rame_time_stamp\x18\x01 \x01(\r\x12\x10\n\x08image_id\x18\x02 \x01(\r\x12\r\n\x05width\x18\x03 \x01(\r\x12\x0e\n\x06height\x18\x04 \x01(\r\x12P\n\x0eimage_encoding\x18\x05 \x01(\x0e\x32\x38.Anki.Vector.external_interface.ImageChunk.ImageEncoding\x12\x15\n\rdisplay_index\x18\x06 \x01(\r\x12\x19\n\x11image_chunk_count\x18\x07 \x01(\r\x12\x10\n\x08\x63hunk_id\x18\x08 \x01(\r\x12\x0c\n\x04\x64\x61ta\x18\t \x01(\x0c\"\xd3\x01\n\rImageEncoding\x12\x17\n\x13NONE_IMAGE_ENCODING\x10\x00\x12\x0c\n\x08RAW_GRAY\x10\x01\x12\x0b\n\x07RAW_RGB\x10\x02\x12\x08\n\x04YUYV\x10\x03\x12\x0c\n\x08YUV420SP\x10\x04\x12\t\n\x05\x42\x41YER\x10\x05\x12\r\n\tJPEG_GRAY\x10\x06\x12\x0e\n\nJPEG_COLOR\x10\x07\x12\x19\n\x15JPEG_COLOR_HALF_WIDTH\x10\x08\x12\x17\n\x13JPEG_MINIMIZED_GRAY\x10\t\x12\x18\n\x14JPEG_MINIMIZED_COLOR\x10\n\"\x13\n\x11\x43\x61meraFeedRequest\"\xa6\x01\n\x12\x43\x61meraFeedResponse\x12\x18\n\x10\x66rame_time_stamp\x18\x01 \x01(\r\x12\x10\n\x08image_id\x18\x02 \x01(\r\x12P\n\x0eimage_encoding\x18\x03 \x01(\x0e\x32\x38.Anki.Vector.external_interface.ImageChunk.ImageEncoding\x12\x0c\n\x04\x64\x61ta\x18\x04 \x01(\x0c:\x04\x80\xa6\x1d\x01\"5\n\x12SetEyeColorRequest\x12\x0b\n\x03hue\x18\x01 \x01(\x02\x12\x12\n\nsaturation\x18\x02 \x01(\x02\"U\n\x13SetEyeColorResponse\x12>\n\x06status\x18\x01 \x01(\x0b\x32..Anki.Vector.external_interface.ResponseStatus\"\x96\x01\n\x18SDKInitializationRequest\x12\x1a\n\x12sdk_module_version\x18\x01 \x01(\t\x12\x16\n\x0epython_version\x18\x02 \x01(\t\x12\x1d\n\x15python_implementation\x18\x03 \x01(\t\x12\x12\n\nos_version\x18\x04 \x01(\t\x12\x13\n\x0b\x63pu_version\x18\x05 \x01(\t\"[\n\x19SDKInitializationResponse\x12>\n\x06status\x18\x01 \x01(\x0b\x32..Anki.Vector.external_interface.ResponseStatus*\xdc\x04\n\x0bRobotStatus\x12\x15\n\x11ROBOT_STATUS_NONE\x10\x00\x12\x1a\n\x16ROBOT_STATUS_IS_MOVING\x10\x01\x12\"\n\x1eROBOT_STATUS_IS_CARRYING_BLOCK\x10\x02\x12&\n\"ROBOT_STATUS_IS_PICKING_OR_PLACING\x10\x04\x12\x1d\n\x19ROBOT_STATUS_IS_PICKED_UP\x10\x08\x12\"\n\x1eROBOT_STATUS_IS_BUTTON_PRESSED\x10\x10\x12\x1b\n\x17ROBOT_STATUS_IS_FALLING\x10 \x12\x1d\n\x19ROBOT_STATUS_IS_ANIMATING\x10@\x12\x1c\n\x17ROBOT_STATUS_IS_PATHING\x10\x80\x01\x12\x1d\n\x18ROBOT_STATUS_LIFT_IN_POS\x10\x80\x02\x12\x1d\n\x18ROBOT_STATUS_HEAD_IN_POS\x10\x80\x04\x12!\n\x1cROBOT_STATUS_CALM_POWER_MODE\x10\x80\x08\x12\x1f\n\x1aROBOT_STATUS_IS_ON_CHARGER\x10\x80 \x12\x1d\n\x18ROBOT_STATUS_IS_CHARGING\x10\x80@\x12!\n\x1bROBOT_STATUS_CLIFF_DETECTED\x10\x80\x80\x01\x12$\n\x1eROBOT_STATUS_ARE_WHEELS_MOVING\x10\x80\x80\x02\x12 \n\x1aROBOT_STATUS_IS_BEING_HELD\x10\x80\x80\x04\x12%\n\x1fROBOT_STATUS_IS_MOTION_DETECTED\x10\x80\x80\x08*\xbd\x01\n\x10\x46\x61\x63ialExpression\x12\x16\n\x12\x45XPRESSION_UNKNOWN\x10\x00\x12\x16\n\x12\x45XPRESSION_NEUTRAL\x10\x01\x12\x18\n\x14\x45XPRESSION_HAPPINESS\x10\x02\x12\x17\n\x13\x45XPRESSION_SURPRISE\x10\x03\x12\x14\n\x10\x45XPRESSION_ANGER\x10\x04\x12\x16\n\x12\x45XPRESSION_SADNESS\x10\x05\x12\x14\n\x10\x45XPRESSION_COUNT\x10\x05\x1a\x02\x10\x01*\xcc\x01\n\x14\x46\x61\x63\x65\x45nrollmentResult\x12\x0b\n\x07SUCCESS\x10\x00\x12\x12\n\x0eSAW_WRONG_FACE\x10\x01\x12\x16\n\x12SAW_MULTIPLE_FACES\x10\x02\x12\r\n\tTIMED_OUT\x10\x03\x12\x0f\n\x0bSAVE_FAILED\x10\x04\x12\x0e\n\nINCOMPLETE\x10\x05\x12\r\n\tCANCELLED\x10\x06\x12\x0f\n\x0bNAME_IN_USE\x10\x07\x12\x16\n\x12NAMED_STORAGE_FULL\x10\x08\x12\x13\n\x0fUNKNOWN_FAILURE\x10\t*l\n\x0f\x42\x65haviorResults\x12\x1a\n\x16\x42\x45HAVIOR_INVALID_STATE\x10\x00\x12\x1b\n\x17\x42\x45HAVIOR_COMPLETE_STATE\x10\x01\x12 \n\x1c\x42\x45HAVIOR_WONT_ACTIVATE_STATE\x10\x02*S\n\x12\x41\x63tionTagConstants\x12\x13\n\x0fINVALID_SDK_TAG\x10\x00\x12\x13\n\rFIRST_SDK_TAG\x10\x81\x89z\x12\x13\n\x0cLAST_SDK_TAG\x10\xc0\x8d\xb7\x01*\x9e\x01\n\rAlignmentType\x12\x1a\n\x16\x41LIGNMENT_TYPE_UNKNOWN\x10\x00\x12\x1e\n\x1a\x41LIGNMENT_TYPE_LIFT_FINGER\x10\x01\x12\x1d\n\x19\x41LIGNMENT_TYPE_LIFT_PLATE\x10\x02\x12\x17\n\x13\x41LIGNMENT_TYPE_BODY\x10\x03\x12\x19\n\x15\x41LIGNMENT_TYPE_CUSTOM\x10\x04*s\n\x0c\x42\x61tteryLevel\x12\x19\n\x15\x42\x41TTERY_LEVEL_UNKNOWN\x10\x00\x12\x15\n\x11\x42\x41TTERY_LEVEL_LOW\x10\x01\x12\x19\n\x15\x42\x41TTERY_LEVEL_NOMINAL\x10\x02\x12\x16\n\x12\x42\x41TTERY_LEVEL_FULL\x10\x03*\xcc\x01\n\x0e\x41udioConstants\x12\x18\n\x14\x41UDIO_CONSTANTS_NULL\x10\x00\x12\x1c\n\x18MIC_DETECTION_DIRECTIONS\x10\x0c\x12%\n SAMPLE_COUNTS_PER_ENGINE_MESSAGE\x10\xa0\x01\x12\"\n\x1dSAMPLE_COUNTS_PER_SDK_MESSAGE\x10\xc0\x0c\x12\x1b\n\x16MICROPHONE_SAMPLE_RATE\x10\x89z\x12\x1a\n\x15PROCESSED_SAMPLE_RATE\x10\x80}*\x85\x01\n\x13\x41udioProcessingMode\x12\x11\n\rAUDIO_UNKNOWN\x10\x00\x12\r\n\tAUDIO_OFF\x10\x01\x12\x13\n\x0f\x41UDIO_FAST_MODE\x10\x02\x12\x1a\n\x16\x41UDIO_DIRECTIONAL_MODE\x10\x03\x12\x1b\n\x17\x41UDIO_VOICE_DETECT_MODE\x10\x04\x62\x06proto3') , - dependencies=[anki__vector_dot_messaging_dot_response__status__pb2.DESCRIPTOR,anki__vector_dot_messaging_dot_extensions__pb2.DESCRIPTOR,anki__vector_dot_messaging_dot_onboarding__steps__pb2.DESCRIPTOR,]) + dependencies=[anki__vector_dot_messaging_dot_response__status__pb2.DESCRIPTOR,anki__vector_dot_messaging_dot_extensions__pb2.DESCRIPTOR,]) +_ROBOTSTATUS = _descriptor.EnumDescriptor( + name='RobotStatus', + full_name='Anki.Vector.external_interface.RobotStatus', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='ROBOT_STATUS_NONE', index=0, number=0, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='ROBOT_STATUS_IS_MOVING', index=1, number=1, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='ROBOT_STATUS_IS_CARRYING_BLOCK', index=2, number=2, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='ROBOT_STATUS_IS_PICKING_OR_PLACING', index=3, number=4, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='ROBOT_STATUS_IS_PICKED_UP', index=4, number=8, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='ROBOT_STATUS_IS_BUTTON_PRESSED', index=5, number=16, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='ROBOT_STATUS_IS_FALLING', index=6, number=32, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='ROBOT_STATUS_IS_ANIMATING', index=7, number=64, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='ROBOT_STATUS_IS_PATHING', index=8, number=128, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='ROBOT_STATUS_LIFT_IN_POS', index=9, number=256, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='ROBOT_STATUS_HEAD_IN_POS', index=10, number=512, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='ROBOT_STATUS_CALM_POWER_MODE', index=11, number=1024, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='ROBOT_STATUS_IS_ON_CHARGER', index=12, number=4096, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='ROBOT_STATUS_IS_CHARGING', index=13, number=8192, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='ROBOT_STATUS_CLIFF_DETECTED', index=14, number=16384, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='ROBOT_STATUS_ARE_WHEELS_MOVING', index=15, number=32768, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='ROBOT_STATUS_IS_BEING_HELD', index=16, number=65536, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='ROBOT_STATUS_IS_MOTION_DETECTED', index=17, number=131072, + options=None, + type=None), + ], + containing_type=None, + options=None, + serialized_start=15131, + serialized_end=15735, +) +_sym_db.RegisterEnumDescriptor(_ROBOTSTATUS) + +RobotStatus = enum_type_wrapper.EnumTypeWrapper(_ROBOTSTATUS) _FACIALEXPRESSION = _descriptor.EnumDescriptor( name='FacialExpression', full_name='Anki.Vector.external_interface.FacialExpression', @@ -64,8 +150,8 @@ ], containing_type=None, options=_descriptor._ParseOptions(descriptor_pb2.EnumOptions(), _b('\020\001')), - serialized_start=15177, - serialized_end=15366, + serialized_start=15738, + serialized_end=15927, ) _sym_db.RegisterEnumDescriptor(_FACIALEXPRESSION) @@ -119,8 +205,8 @@ ], containing_type=None, options=None, - serialized_start=15369, - serialized_end=15573, + serialized_start=15930, + serialized_end=16134, ) _sym_db.RegisterEnumDescriptor(_FACEENROLLMENTRESULT) @@ -146,8 +232,8 @@ ], containing_type=None, options=None, - serialized_start=15575, - serialized_end=15683, + serialized_start=16136, + serialized_end=16244, ) _sym_db.RegisterEnumDescriptor(_BEHAVIORRESULTS) @@ -173,8 +259,8 @@ ], containing_type=None, options=None, - serialized_start=15685, - serialized_end=15768, + serialized_start=16246, + serialized_end=16329, ) _sym_db.RegisterEnumDescriptor(_ACTIONTAGCONSTANTS) @@ -208,8 +294,8 @@ ], containing_type=None, options=None, - serialized_start=15771, - serialized_end=15929, + serialized_start=16332, + serialized_end=16490, ) _sym_db.RegisterEnumDescriptor(_ALIGNMENTTYPE) @@ -239,8 +325,8 @@ ], containing_type=None, options=None, - serialized_start=15931, - serialized_end=16046, + serialized_start=16492, + serialized_end=16607, ) _sym_db.RegisterEnumDescriptor(_BATTERYLEVEL) @@ -278,8 +364,8 @@ ], containing_type=None, options=None, - serialized_start=16049, - serialized_end=16253, + serialized_start=16610, + serialized_end=16814, ) _sym_db.RegisterEnumDescriptor(_AUDIOCONSTANTS) @@ -313,12 +399,30 @@ ], containing_type=None, options=None, - serialized_start=16256, - serialized_end=16389, + serialized_start=16817, + serialized_end=16950, ) _sym_db.RegisterEnumDescriptor(_AUDIOPROCESSINGMODE) AudioProcessingMode = enum_type_wrapper.EnumTypeWrapper(_AUDIOPROCESSINGMODE) +ROBOT_STATUS_NONE = 0 +ROBOT_STATUS_IS_MOVING = 1 +ROBOT_STATUS_IS_CARRYING_BLOCK = 2 +ROBOT_STATUS_IS_PICKING_OR_PLACING = 4 +ROBOT_STATUS_IS_PICKED_UP = 8 +ROBOT_STATUS_IS_BUTTON_PRESSED = 16 +ROBOT_STATUS_IS_FALLING = 32 +ROBOT_STATUS_IS_ANIMATING = 64 +ROBOT_STATUS_IS_PATHING = 128 +ROBOT_STATUS_LIFT_IN_POS = 256 +ROBOT_STATUS_HEAD_IN_POS = 512 +ROBOT_STATUS_CALM_POWER_MODE = 1024 +ROBOT_STATUS_IS_ON_CHARGER = 4096 +ROBOT_STATUS_IS_CHARGING = 8192 +ROBOT_STATUS_CLIFF_DETECTED = 16384 +ROBOT_STATUS_ARE_WHEELS_MOVING = 32768 +ROBOT_STATUS_IS_BEING_HELD = 65536 +ROBOT_STATUS_IS_MOTION_DETECTED = 131072 EXPRESSION_UNKNOWN = 0 EXPRESSION_NEUTRAL = 1 EXPRESSION_HAPPINESS = 2 @@ -585,8 +689,8 @@ ], containing_type=None, options=None, - serialized_start=7158, - serialized_end=8720, + serialized_start=7112, + serialized_end=8674, ) _sym_db.RegisterEnumDescriptor(_ACTIONRESULT_ACTIONRESULTCODE) @@ -607,8 +711,8 @@ ], containing_type=None, options=None, - serialized_start=11730, - serialized_end=11769, + serialized_start=11684, + serialized_end=11723, ) _sym_db.RegisterEnumDescriptor(_CUBEBATTERY_CUBEBATTERYLEVEL) @@ -641,8 +745,8 @@ ], containing_type=None, options=None, - serialized_start=12355, - serialized_end=12438, + serialized_start=12309, + serialized_end=12392, ) _sym_db.RegisterEnumDescriptor(_SAYTEXTRESPONSE_UTTERANCESTATE) @@ -699,8 +803,8 @@ ], containing_type=None, options=None, - serialized_start=14385, - serialized_end=14596, + serialized_start=14339, + serialized_end=14550, ) _sym_db.RegisterEnumDescriptor(_IMAGECHUNK_IMAGEENCODING) @@ -724,8 +828,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=203, - serialized_end=218, + serialized_start=157, + serialized_end=172, ) @@ -755,8 +859,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=220, - serialized_end=245, + serialized_start=174, + serialized_end=199, ) @@ -807,8 +911,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=247, - serialized_end=371, + serialized_start=201, + serialized_end=325, ) @@ -838,8 +942,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=373, - serialized_end=458, + serialized_start=327, + serialized_end=412, ) @@ -869,8 +973,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=460, - serialized_end=504, + serialized_start=414, + serialized_end=458, ) @@ -900,8 +1004,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=506, - serialized_end=588, + serialized_start=460, + serialized_end=542, ) @@ -931,8 +1035,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=590, - serialized_end=634, + serialized_start=544, + serialized_end=588, ) @@ -962,8 +1066,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=636, - serialized_end=718, + serialized_start=590, + serialized_end=672, ) @@ -1021,8 +1125,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=721, - serialized_end=901, + serialized_start=675, + serialized_end=855, ) @@ -1059,8 +1163,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=904, - serialized_end=1056, + serialized_start=858, + serialized_end=1010, ) @@ -1083,8 +1187,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=1058, - serialized_end=1081, + serialized_start=1012, + serialized_end=1035, ) @@ -1121,8 +1225,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=1084, - serialized_end=1240, + serialized_start=1038, + serialized_end=1194, ) @@ -1166,8 +1270,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=1242, - serialized_end=1337, + serialized_start=1196, + serialized_end=1291, ) @@ -1197,8 +1301,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=1339, - serialized_end=1432, + serialized_start=1293, + serialized_end=1386, ) @@ -1221,8 +1325,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=1434, - serialized_end=1461, + serialized_start=1388, + serialized_end=1415, ) @@ -1245,8 +1349,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=1463, - serialized_end=1491, + serialized_start=1417, + serialized_end=1445, ) @@ -1293,8 +1397,8 @@ name='status_type', full_name='Anki.Vector.external_interface.Status.status_type', index=0, containing_type=None, fields=[]), ], - serialized_start=1494, - serialized_end=1813, + serialized_start=1448, + serialized_end=1767, ) @@ -1334,8 +1438,8 @@ name='wake_word_type', full_name='Anki.Vector.external_interface.WakeWord.wake_word_type', index=0, containing_type=None, fields=[]), ], - serialized_start=1816, - serialized_end=1988, + serialized_start=1770, + serialized_end=1942, ) @@ -1372,8 +1476,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=1990, - serialized_end=2088, + serialized_start=1944, + serialized_end=2042, ) @@ -1452,8 +1556,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=2090, - serialized_end=2202, + serialized_start=2044, + serialized_end=2156, ) @@ -1497,8 +1601,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=2204, - serialized_end=2248, + serialized_start=2158, + serialized_end=2202, ) @@ -1542,8 +1646,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=2250, - serialized_end=2293, + serialized_start=2204, + serialized_end=2247, ) @@ -1608,8 +1712,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=2296, - serialized_end=2459, + serialized_start=2250, + serialized_end=2413, ) @@ -1646,8 +1750,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=2461, - serialized_end=2523, + serialized_start=2415, + serialized_end=2477, ) @@ -1789,8 +1893,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=2526, - serialized_end=3168, + serialized_start=2480, + serialized_end=3122, ) @@ -1827,8 +1931,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=3170, - serialized_end=3203, + serialized_start=3124, + serialized_end=3157, ) @@ -1879,8 +1983,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=3205, - serialized_end=3286, + serialized_start=3159, + serialized_end=3240, ) @@ -1980,8 +2084,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=3289, - serialized_end=3811, + serialized_start=3243, + serialized_end=3765, ) @@ -2018,8 +2122,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=3813, - serialized_end=3873, + serialized_start=3767, + serialized_end=3827, ) @@ -2056,8 +2160,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=3875, - serialized_end=3924, + serialized_start=3829, + serialized_end=3878, ) @@ -2080,8 +2184,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=3926, - serialized_end=3943, + serialized_start=3880, + serialized_end=3897, ) @@ -2111,8 +2215,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=3945, - serialized_end=4028, + serialized_start=3899, + serialized_end=3982, ) @@ -2156,8 +2260,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=4030, - serialized_end=4156, + serialized_start=3984, + serialized_end=4110, ) @@ -2180,8 +2284,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=4158, - serialized_end=4187, + serialized_start=4112, + serialized_end=4141, ) @@ -2211,8 +2315,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=4189, - serialized_end=4283, + serialized_start=4143, + serialized_end=4237, ) @@ -2235,8 +2339,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=4285, - serialized_end=4314, + serialized_start=4239, + serialized_end=4268, ) @@ -2301,8 +2405,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=4317, - serialized_end=4511, + serialized_start=4271, + serialized_end=4465, ) @@ -2339,8 +2443,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=4513, - serialized_end=4570, + serialized_start=4467, + serialized_end=4524, ) @@ -2377,8 +2481,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=4573, - serialized_end=4731, + serialized_start=4527, + serialized_end=4685, ) @@ -2422,8 +2526,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=4733, - serialized_end=4817, + serialized_start=4687, + serialized_end=4771, ) @@ -2453,8 +2557,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=4819, - serialized_end=4915, + serialized_start=4773, + serialized_end=4869, ) @@ -2484,8 +2588,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=4917, - serialized_end=4964, + serialized_start=4871, + serialized_end=4918, ) @@ -2515,8 +2619,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=4966, - serialized_end=5061, + serialized_start=4920, + serialized_end=5015, ) @@ -2539,8 +2643,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=5063, - serialized_end=5093, + serialized_start=5017, + serialized_end=5047, ) @@ -2570,8 +2674,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=5095, - serialized_end=5190, + serialized_start=5049, + serialized_end=5144, ) @@ -2636,8 +2740,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=5193, - serialized_end=5329, + serialized_start=5147, + serialized_end=5283, ) @@ -2667,8 +2771,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=5331, - serialized_end=5420, + serialized_start=5285, + serialized_end=5374, ) @@ -2691,8 +2795,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=5422, - serialized_end=5446, + serialized_start=5376, + serialized_end=5400, ) @@ -2729,8 +2833,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=5449, - serialized_end=5603, + serialized_start=5403, + serialized_end=5557, ) @@ -2753,8 +2857,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=5605, - serialized_end=5628, + serialized_start=5559, + serialized_end=5582, ) @@ -2791,8 +2895,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=5631, - serialized_end=5784, + serialized_start=5585, + serialized_end=5738, ) @@ -2815,8 +2919,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=5786, - serialized_end=5801, + serialized_start=5740, + serialized_end=5755, ) @@ -2853,8 +2957,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=5803, - serialized_end=5859, + serialized_start=5757, + serialized_end=5813, ) @@ -2905,8 +3009,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=5861, - serialized_end=5971, + serialized_start=5815, + serialized_end=5925, ) @@ -2929,8 +3033,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=5973, - serialized_end=5992, + serialized_start=5927, + serialized_end=5946, ) @@ -2967,8 +3071,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=5995, - serialized_end=6143, + serialized_start=5949, + serialized_end=6097, ) @@ -2998,8 +3102,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=6145, - serialized_end=6177, + serialized_start=6099, + serialized_end=6131, ) @@ -3036,8 +3140,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=6179, - serialized_end=6233, + serialized_start=6133, + serialized_end=6187, ) @@ -3081,8 +3185,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=6235, - serialized_end=6346, + serialized_start=6189, + serialized_end=6300, ) @@ -3112,8 +3216,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=6348, - serialized_end=6384, + serialized_start=6302, + serialized_end=6338, ) @@ -3150,8 +3254,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=6386, - serialized_end=6444, + serialized_start=6340, + serialized_end=6398, ) @@ -3195,8 +3299,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=6446, - serialized_end=6561, + serialized_start=6400, + serialized_end=6515, ) @@ -3226,8 +3330,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=6563, - serialized_end=6601, + serialized_start=6517, + serialized_end=6555, ) @@ -3264,8 +3368,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=6603, - serialized_end=6705, + serialized_start=6557, + serialized_end=6659, ) @@ -3295,8 +3399,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=6707, - serialized_end=6737, + serialized_start=6661, + serialized_end=6691, ) @@ -3396,8 +3500,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=6740, - serialized_end=7061, + serialized_start=6694, + serialized_end=7015, ) @@ -3428,8 +3532,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=7064, - serialized_end=8720, + serialized_start=7018, + serialized_end=8674, ) @@ -3494,8 +3598,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=8723, - serialized_end=8890, + serialized_start=8677, + serialized_end=8844, ) @@ -3532,8 +3636,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=8893, - serialized_end=9037, + serialized_start=8847, + serialized_end=8991, ) @@ -3619,8 +3723,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=9040, - serialized_end=9376, + serialized_start=8994, + serialized_end=9330, ) @@ -3657,8 +3761,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=9379, - serialized_end=9527, + serialized_start=9333, + serialized_end=9481, ) @@ -3716,8 +3820,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=9529, - serialized_end=9656, + serialized_start=9483, + serialized_end=9610, ) @@ -3754,8 +3858,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=9659, - serialized_end=9808, + serialized_start=9613, + serialized_end=9762, ) @@ -3827,8 +3931,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=9811, - serialized_end=9980, + serialized_start=9765, + serialized_end=9934, ) @@ -3865,8 +3969,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=9983, - serialized_end=10130, + serialized_start=9937, + serialized_end=10084, ) @@ -3931,8 +4035,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=10133, - serialized_end=10291, + serialized_start=10087, + serialized_end=10245, ) @@ -3969,8 +4073,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=10294, - serialized_end=10442, + serialized_start=10248, + serialized_end=10396, ) @@ -4035,8 +4139,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=10445, - serialized_end=10604, + serialized_start=10399, + serialized_end=10558, ) @@ -4073,8 +4177,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=10607, - serialized_end=10756, + serialized_start=10561, + serialized_end=10710, ) @@ -4181,8 +4285,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=10759, - serialized_end=11200, + serialized_start=10713, + serialized_end=11154, ) @@ -4205,8 +4309,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=11202, - serialized_end=11223, + serialized_start=11156, + serialized_end=11177, ) @@ -4278,8 +4382,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=11226, - serialized_end=11555, + serialized_start=11180, + serialized_end=11509, ) @@ -4331,8 +4435,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=11558, - serialized_end=11769, + serialized_start=11512, + serialized_end=11723, ) @@ -4355,8 +4459,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=11771, - serialized_end=11792, + serialized_start=11725, + serialized_end=11746, ) @@ -4400,8 +4504,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=11795, - serialized_end=11926, + serialized_start=11749, + serialized_end=11880, ) @@ -4424,8 +4528,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=11928, - serialized_end=11949, + serialized_start=11882, + serialized_end=11903, ) @@ -4462,8 +4566,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=11952, - serialized_end=12107, + serialized_start=11906, + serialized_end=12061, ) @@ -4507,8 +4611,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=12109, - serialized_end=12190, + serialized_start=12063, + serialized_end=12144, ) @@ -4546,8 +4650,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=12193, - serialized_end=12438, + serialized_start=12147, + serialized_end=12392, ) @@ -4619,8 +4723,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=12441, - serialized_end=12596, + serialized_start=12395, + serialized_end=12550, ) @@ -4650,8 +4754,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=12598, - serialized_end=12687, + serialized_start=12552, + serialized_end=12641, ) @@ -4681,8 +4785,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=12689, - serialized_end=12778, + serialized_start=12643, + serialized_end=12732, ) @@ -4768,8 +4872,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=12781, - serialized_end=13013, + serialized_start=12735, + serialized_end=12967, ) @@ -4792,8 +4896,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=13015, - serialized_end=13033, + serialized_start=12969, + serialized_end=12987, ) @@ -4865,8 +4969,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=13036, - serialized_end=13236, + serialized_start=12990, + serialized_end=13190, ) @@ -4896,8 +5000,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=13238, - serialized_end=13284, + serialized_start=13192, + serialized_end=13238, ) @@ -4927,8 +5031,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=13286, - serialized_end=13381, + serialized_start=13240, + serialized_end=13335, ) @@ -4986,8 +5090,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=13384, - serialized_end=13561, + serialized_start=13338, + serialized_end=13515, ) @@ -5017,8 +5121,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=13563, - serialized_end=13656, + serialized_start=13517, + serialized_end=13610, ) @@ -5048,8 +5152,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=13658, - serialized_end=13704, + serialized_start=13612, + serialized_end=13658, ) @@ -5079,8 +5183,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=13706, - serialized_end=13801, + serialized_start=13660, + serialized_end=13755, ) @@ -5110,8 +5214,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=13803, - serialized_end=13844, + serialized_start=13757, + serialized_end=13798, ) @@ -5141,8 +5245,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=13846, - serialized_end=13936, + serialized_start=13800, + serialized_end=13890, ) @@ -5165,8 +5269,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=13938, - serialized_end=13958, + serialized_start=13892, + serialized_end=13912, ) @@ -5196,8 +5300,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=13960, - serialized_end=14005, + serialized_start=13914, + serialized_end=13959, ) @@ -5227,8 +5331,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=14007, - serialized_end=14101, + serialized_start=13961, + serialized_end=14055, ) @@ -5251,8 +5355,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=14103, - serialized_end=14128, + serialized_start=14057, + serialized_end=14082, ) @@ -5339,8 +5443,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=14131, - serialized_end=14596, + serialized_start=14085, + serialized_end=14550, ) @@ -5363,8 +5467,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=14598, - serialized_end=14617, + serialized_start=14552, + serialized_end=14571, ) @@ -5415,8 +5519,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=14620, - serialized_end=14786, + serialized_start=14574, + serialized_end=14740, ) @@ -5453,8 +5557,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=14788, - serialized_end=14841, + serialized_start=14742, + serialized_end=14795, ) @@ -5484,8 +5588,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=14843, - serialized_end=14928, + serialized_start=14797, + serialized_end=14882, ) @@ -5543,8 +5647,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=14931, - serialized_end=15081, + serialized_start=14885, + serialized_end=15035, ) @@ -5574,8 +5678,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=15083, - serialized_end=15174, + serialized_start=15037, + serialized_end=15128, ) _DRIVEWHEELSRESPONSE.fields_by_name['status'].message_type = anki__vector_dot_messaging_dot_response__status__pb2._RESPONSESTATUS @@ -5792,6 +5896,7 @@ DESCRIPTOR.message_types_by_name['SetEyeColorResponse'] = _SETEYECOLORRESPONSE DESCRIPTOR.message_types_by_name['SDKInitializationRequest'] = _SDKINITIALIZATIONREQUEST DESCRIPTOR.message_types_by_name['SDKInitializationResponse'] = _SDKINITIALIZATIONRESPONSE +DESCRIPTOR.enum_types_by_name['RobotStatus'] = _ROBOTSTATUS DESCRIPTOR.enum_types_by_name['FacialExpression'] = _FACIALEXPRESSION DESCRIPTOR.enum_types_by_name['FaceEnrollmentResult'] = _FACEENROLLMENTRESULT DESCRIPTOR.enum_types_by_name['BehaviorResults'] = _BEHAVIORRESULTS diff --git a/anki_vector/messaging/onboarding_steps.proto b/anki_vector/messaging/onboarding_steps.proto deleted file mode 100644 index 37c40bb..0000000 --- a/anki_vector/messaging/onboarding_steps.proto +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) 2018 Anki, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License in the file LICENSE.txt or at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// Onboarding messages - -syntax = "proto3"; - -package Anki.Vector.external_interface; - diff --git a/anki_vector/messaging/onboarding_steps_pb2.py b/anki_vector/messaging/onboarding_steps_pb2.py deleted file mode 100644 index 014a556..0000000 --- a/anki_vector/messaging/onboarding_steps_pb2.py +++ /dev/null @@ -1,30 +0,0 @@ -# Generated by the protocol buffer compiler. DO NOT EDIT! -# source: anki_vector/messaging/onboarding_steps.proto - -import sys -_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1')) -from google.protobuf import descriptor as _descriptor -from google.protobuf import message as _message -from google.protobuf import reflection as _reflection -from google.protobuf import symbol_database as _symbol_database -from google.protobuf import descriptor_pb2 -# @@protoc_insertion_point(imports) - -_sym_db = _symbol_database.Default() - - - - -DESCRIPTOR = _descriptor.FileDescriptor( - name='anki_vector/messaging/onboarding_steps.proto', - package='Anki.Vector.external_interface', - syntax='proto3', - serialized_pb=_b('\n,anki_vector/messaging/onboarding_steps.proto\x12\x1e\x41nki.Vector.external_interfaceb\x06proto3') -) - - - -_sym_db.RegisterFileDescriptor(DESCRIPTOR) - - -# @@protoc_insertion_point(module_scope) diff --git a/anki_vector/messaging/onboarding_steps_pb2_grpc.py b/anki_vector/messaging/onboarding_steps_pb2_grpc.py deleted file mode 100644 index a894352..0000000 --- a/anki_vector/messaging/onboarding_steps_pb2_grpc.py +++ /dev/null @@ -1,3 +0,0 @@ -# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT! -import grpc - diff --git a/anki_vector/messaging/settings.proto b/anki_vector/messaging/settings.proto index 0e6f8f4..d3d35cf 100644 --- a/anki_vector/messaging/settings.proto +++ b/anki_vector/messaging/settings.proto @@ -18,7 +18,6 @@ syntax = "proto3"; package Anki.Vector.external_interface; -import "anki_vector/messaging/response_status.proto"; enum ApiVersion { INVALID = 0; diff --git a/anki_vector/messaging/settings_pb2.py b/anki_vector/messaging/settings_pb2.py index edccd54..f5dff10 100644 --- a/anki_vector/messaging/settings_pb2.py +++ b/anki_vector/messaging/settings_pb2.py @@ -14,16 +14,14 @@ _sym_db = _symbol_database.Default() -from anki_vector.messaging import response_status_pb2 as anki__vector_dot_messaging_dot_response__status__pb2 DESCRIPTOR = _descriptor.FileDescriptor( name='anki_vector/messaging/settings.proto', package='Anki.Vector.external_interface', syntax='proto3', - serialized_pb=_b('\n$anki_vector/messaging/settings.proto\x12\x1e\x41nki.Vector.external_interface\x1a+anki_vector/messaging/response_status.proto*%\n\nApiVersion\x12\x0b\n\x07INVALID\x10\x00\x12\n\n\x06LATEST\x10\x01*R\n\x06Volume\x12\x08\n\x04MUTE\x10\x00\x12\x07\n\x03LOW\x10\x01\x12\x0e\n\nMEDIUM_LOW\x10\x02\x12\n\n\x06MEDIUM\x10\x03\x12\x0f\n\x0bMEDIUM_HIGH\x10\x04\x12\x08\n\x04HIGH\x10\x05\x62\x06proto3') - , - dependencies=[anki__vector_dot_messaging_dot_response__status__pb2.DESCRIPTOR,]) + serialized_pb=_b('\n$anki_vector/messaging/settings.proto\x12\x1e\x41nki.Vector.external_interface*%\n\nApiVersion\x12\x0b\n\x07INVALID\x10\x00\x12\n\n\x06LATEST\x10\x01*R\n\x06Volume\x12\x08\n\x04MUTE\x10\x00\x12\x07\n\x03LOW\x10\x01\x12\x0e\n\nMEDIUM_LOW\x10\x02\x12\n\n\x06MEDIUM\x10\x03\x12\x0f\n\x0bMEDIUM_HIGH\x10\x04\x12\x08\n\x04HIGH\x10\x05\x62\x06proto3') +) _APIVERSION = _descriptor.EnumDescriptor( name='ApiVersion', @@ -42,8 +40,8 @@ ], containing_type=None, options=None, - serialized_start=117, - serialized_end=154, + serialized_start=72, + serialized_end=109, ) _sym_db.RegisterEnumDescriptor(_APIVERSION) @@ -81,8 +79,8 @@ ], containing_type=None, options=None, - serialized_start=156, - serialized_end=238, + serialized_start=111, + serialized_end=193, ) _sym_db.RegisterEnumDescriptor(_VOLUME) diff --git a/anki_vector/opengl.py b/anki_vector/opengl.py index df885d5..7bc8bb2 100644 --- a/anki_vector/opengl.py +++ b/anki_vector/opengl.py @@ -21,7 +21,9 @@ This package requires Python to have the PyOpenGL package installed, along with an implementation of GLUT (OpenGL Utility Toolkit). - To install the Python packages do ``pip install .[3dviewer]`` + To install the Python packages on Mac and Linux do ``python3 -m pip install --user "anki_vector[3dviewer]"`` + + To install the Python packages on Windows do ``py -3 -m pip install --user "anki_vector[3dviewer]"`` On Windows and Linux you must also install freeglut (macOS / OSX has one preinstalled). @@ -34,8 +36,6 @@ script to use it." """ -# TODO Update install line above to: ``pip3 install --user "anki_vector[3dviewer]"`` - # __all__ should order by constants, event classes, other classes, functions. __all__ = ['Camera', 'DynamicTexture', 'MaterialLibrary', 'MeshData', 'MeshFace', 'MeshGroup', 'OpenGLWindow', 'PrecomputedView', 'ResourceManager', @@ -60,10 +60,9 @@ def raise_opengl_or_pillow_import_error(opengl_import_exc): raise NotImplementedError('GLUT (OpenGL Utility Toolkit) is not available:\n%s' % opengl_import_exc) else: - # TODO Update to: 'Do `pip3 install --user anki_vector[3dviewer]` from `pip3 install PyOpenGL` raise NotImplementedError('OpenGL is not available; ' 'make sure the PyOpenGL and Pillow packages are installed:\n' - 'Do `pip3 install PyOpenGL Pillow` to install. Error: %s' % opengl_import_exc) + 'Do `pip3 install --user "anki_vector[3dviewer]"` to install. Error: %s' % opengl_import_exc) try: diff --git a/anki_vector/opengl_vector.py b/anki_vector/opengl_vector.py index 8875a1b..72e5359 100644 --- a/anki_vector/opengl_vector.py +++ b/anki_vector/opengl_vector.py @@ -15,8 +15,6 @@ """This module provides Vector-specific 3D support classes for OpenGL, used by opengl_viewer.py. """ -# TODO Update install line above to: ``pip3 install --user "anki_vector[3dviewer]"`` - # __all__ should order by constants, event classes, other classes, functions. __all__ = ['CubeRenderFrame', 'FaceRenderFrame', 'LightCubeView', 'RobotRenderFrame', 'RobotView', 'UnitCubeView', 'VectorViewManifest', 'WorldRenderFrame'] diff --git a/anki_vector/opengl_viewer.py b/anki_vector/opengl_viewer.py index 2203e51..31d77b9 100644 --- a/anki_vector/opengl_viewer.py +++ b/anki_vector/opengl_viewer.py @@ -43,7 +43,9 @@ async def my_function(robot): This package requires Python to have the PyOpenGL package installed, along with an implementation of GLUT (OpenGL Utility Toolkit). - To install the Python packages do ``pip install .[3dviewer]`` + To install the Python packages on Mac and Linux do ``python3 -m pip install --user "anki_vector[3dviewer]"`` + + To install the Python packages on Windows do ``py -3 -m pip install --user "anki_vector[3dviewer]"`` On Windows and Linux you must also install freeglut (macOS / OSX has one preinstalled). @@ -56,8 +58,6 @@ async def my_function(robot): script to use it." """ -# TODO Update install line above to: ``pip3 install --user "anki_vector[3dviewer]"`` - # __all__ should order by constants, event classes, other classes, functions. __all__ = ['OpenGLViewer'] @@ -248,16 +248,16 @@ def update(self, robot: Robot): if (old_intents.left_wheel_speed != input_intents.left_wheel_speed or old_intents.right_wheel_speed != input_intents.right_wheel_speed): - robot.conn.run_soon(robot.motors.set_wheel_motors(input_intents.left_wheel_speed, - input_intents.right_wheel_speed, - input_intents.left_wheel_speed * 4, - input_intents.right_wheel_speed * 4)) + robot.motors.set_wheel_motors(input_intents.left_wheel_speed, + input_intents.right_wheel_speed, + input_intents.left_wheel_speed * 4, + input_intents.right_wheel_speed * 4) if old_intents.lift_speed != input_intents.lift_speed: - robot.conn.run_soon(robot.motors.set_lift_motor(input_intents.lift_speed)) + robot.motors.set_lift_motor(input_intents.lift_speed) if old_intents.head_speed != input_intents.head_speed: - robot.conn.run_soon(robot.motors.set_head_motor(input_intents.head_speed)) + robot.motors.set_head_motor(input_intents.head_speed) #### Private Methods #### @@ -778,6 +778,7 @@ async def my_function(robot): try: robot.conn.run_coroutine(delegate_function(*function_args)) + # @TODO: Unsubscribe and shut down when the delegate function finishes # This became an issue when the concurrent.future changes were added. @@ -817,7 +818,6 @@ def _on_robot_state_update(self, _, msg): # pylint: disable=unused-argument We can safely capture any robot and world state here, and push to OpenGL (main) thread via a thread-safe queue. """ - world_frame = opengl_vector.WorldRenderFrame(self._robot) self._world_frame_queue.append(world_frame) self._view_controller.update(self._robot) diff --git a/anki_vector/proximity.py b/anki_vector/proximity.py index 07f6fdf..b956df4 100755 --- a/anki_vector/proximity.py +++ b/anki_vector/proximity.py @@ -186,7 +186,8 @@ def __init__(self, robot): # Subscribe to a callback that updates the robot's local properties - which includes proximity data. self._robot.events.subscribe(self._on_robot_state, - Events.robot_state) + Events.robot_state, + on_connection_thread=True) def close(self): """Closing the touch component will unsubscribe from robot state updates.""" diff --git a/anki_vector/robot.py b/anki_vector/robot.py index a7a3395..28a19e8 100755 --- a/anki_vector/robot.py +++ b/anki_vector/robot.py @@ -27,7 +27,7 @@ from . import (animation, audio, behavior, camera, connection, events, exceptions, faces, motors, nav_map, screen, photos, proximity, - touch, util, viewer, vision, world) + status, touch, util, viewer, vision, world) from .messaging import protocol @@ -118,7 +118,7 @@ def __init__(self, self._port = config["port"] if self._name is None or self._ip is None or self._cert_file is None or self._guid is None: - raise ValueError("The Robot object requires a serial and for Vector to be logged in (using the app then configure.py).\n" + raise ValueError("The Robot object requires a serial and for Vector to be logged in (using the app then running the anki_vector.configure executable submodule).\n" "You may also provide the values necessary for connection through the config parameter. ex: " '{"name":"Vector-XXXX", "ip":"XX.XX.XX.XX", "cert":"/path/to/cert_file", "guid":""}') @@ -161,7 +161,7 @@ def __init__(self, self._head_tracking_object_id: float = None self._localized_to_object_id: float = None self._last_image_time_stamp: float = None - self._status: float = None + self._status: status.RobotStatus = status.RobotStatus() self.pending = [] self._enable_camera_feed = enable_camera_feed @@ -181,7 +181,7 @@ def _read_configuration(self, serial: str) -> dict: sections = parser.sections() if not sections: - raise Exception('\n\nCould not find the sdk configuration file. Please run ./configure.py to set up your Vector for SDK usage.') + raise Exception('\n\nCould not find the sdk configuration file. Please run `python3 -m anki_vector.configure` to set up your Vector for SDK usage.') elif serial is None and len(sections) == 1: serial = sections[0] self.logger.warning("No serial number provided. Automatically selecting {}".format(serial)) @@ -527,37 +527,22 @@ def last_image_time_stamp(self) -> int: return self._last_image_time_stamp @property - @util.block_while_none() - def status(self) -> float: - """Describes Vector's status. - - Possible values include: - | NoneRobotStatusFlag = 0 - | IS_MOVING = 0x1 - | IS_CARRYING_BLOCK = 0x2 - | IS_PICKING_OR_PLACING = 0x4 - | IS_PICKED_UP = 0x8 - | IS_BUTTON_PRESSED = 0x10 - | IS_FALLING = 0x20 - | IS_ANIMATING = 0x40 - | IS_PATHING = 0x80 - | LIFT_IN_POS = 0x100 - | HEAD_IN_POS = 0x200 - | CALM_POWER_MODE = 0x400 - | IS_BATTERY_DISCONNECTED = 0x800 - | IS_ON_CHARGER = 0x1000 - | IS_CHARGING = 0x2000 - | CLIFF_DETECTED = 0x4000 - | ARE_WHEELS_MOVING = 0x8000 - | IS_BEING_HELD = 0x10000 - | IS_MOTION_DETECTED = 0x20000 - | IS_BATTERY_OVERHEATED = 0x40000 + def status(self) -> status.RobotStatus: + """A property that exposes various status properties of the robot. + + This status provides a simple mechanism to, for example, detect if any + of Vector's motors are moving, determine if Vector is being held, or if + he is on the charger. The full list is available in the + :class:`RobotStatus ` class documentation. .. testcode:: import anki_vector with anki_vector.Robot() as robot: - current_status = robot.status + if robot.status.is_being_held: + print("Vector is being held!") + else: + print("Vector is not being held.") """ return self._status @@ -636,7 +621,7 @@ def _unpack_robot_state(self, _, msg): self._head_tracking_object_id = msg.head_tracking_object_id self._localized_to_object_id = msg.localized_to_object_id self._last_image_time_stamp = msg.last_image_time_stamp - self._status = msg.status + self._status.set(msg.status) def connect(self, timeout: int = 10) -> None: """Start the connection to Vector. @@ -703,7 +688,9 @@ def connect(self, timeout: int = 10) -> None: object_detection.result() # Subscribe to a callback that updates the robot's local properties - self.events.subscribe(self._unpack_robot_state, events.Events.robot_state) + self.events.subscribe(self._unpack_robot_state, + events.Events.robot_state, + on_connection_thread=True) def disconnect(self) -> None: """Close the connection with Vector. diff --git a/anki_vector/status.py b/anki_vector/status.py new file mode 100644 index 0000000..88e4354 --- /dev/null +++ b/anki_vector/status.py @@ -0,0 +1,314 @@ +# Copyright (c) 2018 Anki, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License in the file LICENSE.txt or at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +""" +.. _status: + +Robot Status class and exposed properties for Vector's various states. + +The :class:`RobotStatus` class in this module exposes properties +about the robot status like :py:attr:`is_charging `, +:py:attr:`is_being_held `, etc. +""" + +# __all__ should order by constants, event classes, other classes, functions. +__all__ = ['ROBOT_STATUS_NONE', 'ROBOT_STATUS_ARE_MOTORS_MOVING', 'ROBOT_STATUS_IS_CARRYING_BLOCK', + 'ROBOT_STATUS_IS_DOCKING_TO_MARKER', 'ROBOT_STATUS_IS_PICKED_UP', 'ROBOT_STATUS_IS_BUTTON_PRESSED', + 'ROBOT_STATUS_IS_FALLING', 'ROBOT_STATUS_IS_ANIMATING', 'ROBOT_STATUS_IS_PATHING', + 'ROBOT_STATUS_LIFT_IN_POS', 'ROBOT_STATUS_HEAD_IN_POS', 'ROBOT_STATUS_CALM_POWER_MODE', + 'ROBOT_STATUS_IS_ON_CHARGER', 'ROBOT_STATUS_IS_CHARGING', 'ROBOT_STATUS_CLIFF_DETECTED', + 'ROBOT_STATUS_ARE_WHEELS_MOVING', 'ROBOT_STATUS_IS_BEING_HELD', 'ROBOT_STATUS_IS_ROBOT_MOVING', + 'RobotStatus'] + +from . import util +from .messaging import protocol + +ROBOT_STATUS_NONE = protocol.RobotStatus.Value("ROBOT_STATUS_NONE") +ROBOT_STATUS_ARE_MOTORS_MOVING = protocol.RobotStatus.Value("ROBOT_STATUS_IS_MOVING") +ROBOT_STATUS_IS_CARRYING_BLOCK = protocol.RobotStatus.Value("ROBOT_STATUS_IS_CARRYING_BLOCK") +ROBOT_STATUS_IS_DOCKING_TO_MARKER = protocol.RobotStatus.Value("ROBOT_STATUS_IS_PICKING_OR_PLACING") +ROBOT_STATUS_IS_PICKED_UP = protocol.RobotStatus.Value("ROBOT_STATUS_IS_PICKED_UP") +ROBOT_STATUS_IS_BUTTON_PRESSED = protocol.RobotStatus.Value("ROBOT_STATUS_IS_BUTTON_PRESSED") +ROBOT_STATUS_IS_FALLING = protocol.RobotStatus.Value("ROBOT_STATUS_IS_FALLING") +ROBOT_STATUS_IS_ANIMATING = protocol.RobotStatus.Value("ROBOT_STATUS_IS_ANIMATING") +ROBOT_STATUS_IS_PATHING = protocol.RobotStatus.Value("ROBOT_STATUS_IS_PATHING") +ROBOT_STATUS_LIFT_IN_POS = protocol.RobotStatus.Value("ROBOT_STATUS_LIFT_IN_POS") +ROBOT_STATUS_HEAD_IN_POS = protocol.RobotStatus.Value("ROBOT_STATUS_HEAD_IN_POS") +ROBOT_STATUS_CALM_POWER_MODE = protocol.RobotStatus.Value("ROBOT_STATUS_CALM_POWER_MODE") +ROBOT_STATUS_IS_ON_CHARGER = protocol.RobotStatus.Value("ROBOT_STATUS_IS_ON_CHARGER") +ROBOT_STATUS_IS_CHARGING = protocol.RobotStatus.Value("ROBOT_STATUS_IS_CHARGING") +ROBOT_STATUS_CLIFF_DETECTED = protocol.RobotStatus.Value("ROBOT_STATUS_CLIFF_DETECTED") +ROBOT_STATUS_ARE_WHEELS_MOVING = protocol.RobotStatus.Value("ROBOT_STATUS_ARE_WHEELS_MOVING") +ROBOT_STATUS_IS_BEING_HELD = protocol.RobotStatus.Value("ROBOT_STATUS_IS_BEING_HELD") +ROBOT_STATUS_IS_ROBOT_MOVING = protocol.RobotStatus.Value("ROBOT_STATUS_IS_MOTION_DETECTED") + + +class RobotStatus(): + """A class to expose various status properties of the robot.""" + + def __init__(self): + # Default robot status + self._status: int = None + + def set(self, status: int): + self._status = status + + @util.block_while_none() + def __get(self) -> int: + return self._status + + @property + def are_motors_moving(self) -> bool: + """True if Vector is currently moving any of his motors (head, arm or + wheels/treads). + + .. testcode:: + + import anki_vector + + with anki_vector.Robot() as robot: + if robot.status.are_motors_moving: + print("Vector is moving.") + """ + return (self.__get() & ROBOT_STATUS_ARE_MOTORS_MOVING) != 0 + + @property + def is_carrying_block(self) -> bool: + """True if Vector is currently carrying a block. + + .. testcode:: + + import anki_vector + + with anki_vector.Robot() as robot: + if robot.status.is_carrying_block: + print("Vector is carrying his block.") + """ + return (self.__get() & ROBOT_STATUS_IS_CARRYING_BLOCK) != 0 + + @property + def is_docking_to_marker(self) -> bool: + """True if Vector has seen a marker and is actively heading toward it + (for example his charger or cube). + + .. testcode:: + + import anki_vector + + with anki_vector.Robot() as robot: + if robot.status.is_docking_to_marker: + print("Vector has found a marker and is docking to it.") + """ + return (self.__get() & ROBOT_STATUS_IS_DOCKING_TO_MARKER) != 0 + + @property + def is_picked_up(self) -> bool: + """True if Vector is currently picked up (in the air). + + .. testcode:: + + import anki_vector + + with anki_vector.Robot() as robot: + if robot.status.is_picked_up: + print("Vector is picked up.") + """ + return (self.__get() & ROBOT_STATUS_IS_PICKED_UP) != 0 + + @property + def is_button_pressed(self) -> bool: + """True if Vector's button is pressed. + + .. testcode:: + + import anki_vector + + with anki_vector.Robot() as robot: + if robot.status.is_button_pressed: + print("Vector's button was button pressed.") + """ + return (self.__get() & ROBOT_STATUS_IS_BUTTON_PRESSED) != 0 + + @property + def is_falling(self) -> bool: + """True if Vector is currently falling. + + .. testcode:: + + import anki_vector + + with anki_vector.Robot() as robot: + if robot.status.is_falling: + print("Vector is falling.") + """ + return (self.__get() & ROBOT_STATUS_IS_FALLING) != 0 + + @property + def is_animating(self) -> bool: + """True if Vector is currently playing an animation. + + .. testcode:: + + import anki_vector + + with anki_vector.Robot() as robot: + if robot.status.is_animating: + print("Vector is animating.") + """ + return (self.__get() & ROBOT_STATUS_IS_ANIMATING) != 0 + + @property + def is_pathing(self) -> bool: + """True if Vector is currently traversing a path. + + .. testcode:: + + import anki_vector + + with anki_vector.Robot() as robot: + if robot.status.is_pathing: + print("Vector is traversing a path.") + """ + return (self.__get() & ROBOT_STATUS_IS_PATHING) != 0 + + @property + def is_lift_in_pos(self) -> bool: + """True if Vector's arm is in the desired position (False if still + trying to move it there). + + .. testcode:: + + import anki_vector + + with anki_vector.Robot() as robot: + if robot.status.is_lift_in_pos: + print("Vector's arm is in position.") + """ + return (self.__get() & ROBOT_STATUS_LIFT_IN_POS) != 0 + + @property + def is_head_in_pos(self) -> bool: + """True if Vector's head is in the desired position (False if still + trying to move there). + + .. testcode:: + + import anki_vector + + with anki_vector.Robot() as robot: + if robot.status.is_head_in_pos: + print("Vector's head is in position.") + """ + return (self.__get() & ROBOT_STATUS_HEAD_IN_POS) != 0 + + @property + def is_in_calm_power_mode(self) -> bool: + """True if Vector is in calm power mode. Calm power mode is generally + when Vector is sleeping or charging. + + .. testcode:: + + import anki_vector + + with anki_vector.Robot() as robot: + if robot.status.is_in_calm_power_mode: + print("Vector is in calm power mode.") + """ + return (self.__get() & ROBOT_STATUS_CALM_POWER_MODE) != 0 + + @property + def is_on_charger(self) -> bool: + """True if Vector is currently on the charger. + + .. testcode:: + + import anki_vector + + with anki_vector.Robot() as robot: + if robot.status.is_on_charger: + print("Vector is on the charger.") + """ + return (self.__get() & ROBOT_STATUS_IS_ON_CHARGER) != 0 + + @property + def is_charging(self) -> bool: + """True if Vector is currently charging. + + .. testcode:: + + import anki_vector + + with anki_vector.Robot() as robot: + if robot.status.is_charging: + print("Vector is currently charging.") + """ + return (self.__get() & ROBOT_STATUS_IS_CHARGING) != 0 + + @property + def is_cliff_detected(self) -> bool: + """True if Vector detected a cliff using any of his four cliff sensors. + + .. testcode:: + + import anki_vector + + with anki_vector.Robot() as robot: + if robot.status.is_cliff_detected: + print("Vector has detected a cliff.") + """ + return (self.__get() & ROBOT_STATUS_CLIFF_DETECTED) != 0 + + @property + def are_wheels_moving(self) -> bool: + """True if Vector's wheels/treads are currently moving. + + .. testcode:: + + import anki_vector + + with anki_vector.Robot() as robot: + if robot.status.are_wheels_moving: + print("Vector's wheels are moving.") + """ + return (self.__get() & ROBOT_STATUS_ARE_WHEELS_MOVING) != 0 + + @property + def is_being_held(self) -> bool: + """True if Vector is being held. + + .. testcode:: + + import anki_vector + + with anki_vector.Robot() as robot: + if robot.status.is_being_held: + print("Vector is being held.") + """ + return (self.__get() & ROBOT_STATUS_IS_BEING_HELD) != 0 + + @property + def is_robot_moving(self) -> bool: + """True if Vector is in motion. This includes any of his motors + (head, arm, wheels/tracks) and if he is being lifted, carried, + or falling. + + .. testcode:: + + import anki_vector + + with anki_vector.Robot() as robot: + if robot.status.is_robot_moving: + print("Vector has is in motion.") + """ + return (self.__get() & ROBOT_STATUS_IS_ROBOT_MOVING) != 0 diff --git a/anki_vector/touch.py b/anki_vector/touch.py index a59b31b..d5bfca5 100755 --- a/anki_vector/touch.py +++ b/anki_vector/touch.py @@ -93,15 +93,14 @@ def __init__(self, robot): self._last_sensor_reading = None # Subscribe to a callback that updates the robot's local properties - which includes touch data. - self._robot.events.subscribe( - self._on_robot_state, - Events.robot_state) + self._robot.events.subscribe(self._on_robot_state, + Events.robot_state, + on_connection_thread=True) def close(self): """Closing the touch component will unsubscribe from robot state updates.""" - self._robot.events.unsubscribe( - self._on_robot_state, - Events.robot_state) + self._robot.events.unsubscribe(self._on_robot_state, + Events.robot_state) @property def last_sensor_reading(self) -> TouchSensorData: diff --git a/anki_vector/util.py b/anki_vector/util.py index 6a5a670..57a6338 100644 --- a/anki_vector/util.py +++ b/anki_vector/util.py @@ -31,6 +31,7 @@ 'Vector2', 'Vector3', 'angle_z_to_quaternion', + 'block_while_none', 'degrees', 'distance_mm', 'distance_inches', @@ -67,7 +68,7 @@ def parse_command_args(parser: argparse.ArgumentParser = None): is specified, we next attempt to read the robot serial number from environment variable ANKI_ROBOT_SERIAL. If ANKI_ROBOT_SERIAL is specified, the value will be used as the robot's serial number. - ..code-block :: + .. code-block:: python import anki_vector @@ -90,16 +91,8 @@ def parse_command_args(parser: argparse.ArgumentParser = None): def block_while_none(interval: float = 0.1, max_iterations: int = 50): """Use this to denote a property that may need some delay before it appears. - ..code-block :: - - class TestClass: - def __init__(self): - self._thing = None - - @property - @block_while_none(interval=0.5, max_iterations=10) - def thing(self): - return self._thing + :param interval: how often to check if the property is no longer None + :param max_iterations: how many times to check the property before raising an error """ def blocker(func: Callable): @wraps(func) @@ -374,6 +367,42 @@ def __mul__(self, other): raise TypeError("Unsupported type for * expected number") return Angle(radians=(self.radians * other)) + def __truediv__(self, other): + if not isinstance(other, (int, float)): + raise TypeError("Unsupported type for / expected number") + return radians(self.radians / other) + + def _cmp_int(self, other): + if not isinstance(other, Angle): + raise TypeError("Unsupported type for comparison expected Angle") + return self.radians - other.radians + + def __eq__(self, other): + return self._cmp_int(other) == 0 + + def __ne__(self, other): + return self._cmp_int(other) != 0 + + def __gt__(self, other): + return self._cmp_int(other) > 0 + + def __lt__(self, other): + return self._cmp_int(other) < 0 + + def __ge__(self, other): + return self._cmp_int(other) >= 0 + + def __le__(self, other): + return self._cmp_int(other) <= 0 + + @property + def abs_value(self): + """:class:`anki_vector.util.Angle`: The absolute value of the angle. + + If the Angle is positive then it returns a copy of this Angle, otherwise it returns -Angle. + """ + return Angle(radians=abs(self._radians)) + def angle_z_to_quaternion(angle_z: Angle): """This function converts an angle in the z axis (Euler angle z component) to a quaternion. diff --git a/anki_vector/version.py b/anki_vector/version.py index dc39182..89b7528 100644 --- a/anki_vector/version.py +++ b/anki_vector/version.py @@ -12,4 +12,4 @@ # See the License for the specific language governing permissions and # limitations under the License. -__version__ = "0.5.0" +__version__ = "0.5.1" diff --git a/anki_vector/viewer.py b/anki_vector/viewer.py index 40735b7..5fe437e 100644 --- a/anki_vector/viewer.py +++ b/anki_vector/viewer.py @@ -18,7 +18,6 @@ # __all__ should order by constants, event classes, other classes, functions. __all__ = ['ViewerComponent'] -import asyncio import multiprocessing as mp import sys @@ -62,8 +61,8 @@ class ViewerComponent(util.Component): def __init__(self, robot): super().__init__(robot) self.overlays: list = [] + self._close_event: mp.Event = None self._frame_queue: mp.Queue = None - self._loop: asyncio.BaseEventLoop = None self._process = None def show_video(self, timeout: float = 10.0) -> None: @@ -85,8 +84,9 @@ def show_video(self, timeout: float = 10.0) -> None: :param timeout: Render video for the given time. (Renders forever, if timeout not given) """ ctx = mp.get_context('spawn') + self._close_event = ctx.Event() self._frame_queue = ctx.Queue(maxsize=4) - self._process = ctx.Process(target=ViewerComponent._render_frames, args=(self._frame_queue, self.overlays, timeout), daemon=True) + self._process = ctx.Process(target=ViewerComponent._render_frames, args=(self._frame_queue, self._close_event, self.overlays, timeout), daemon=True) self._process.start() def stop_video(self) -> None: @@ -101,8 +101,14 @@ def stop_video(self) -> None: time.sleep(10) robot.viewer.stop_video() """ + if self._close_event: + self._close_event.set() + self._close_event = None if self._frame_queue: - self._frame_queue.put(None, False) + try: + self._frame_queue.put(None, False) + except mp.queues.Full: + pass self._frame_queue = None if self._process: self._process.join(timeout=5) @@ -128,7 +134,8 @@ def enqueue_frame(self, image: Image.Image): :param image: A frame from Vector's camera. """ - if self._frame_queue is not None: + close_event = self._close_event + if self._frame_queue is not None and close_event is not None and not close_event.is_set(): try: self._frame_queue.put(image, False) except mp.queues.Full: @@ -141,7 +148,7 @@ def _apply_overlays(self, image: Image.Image) -> None: return image @staticmethod - def _render_frames(queue: mp.Queue, overlays: list = None, timeout: float = 10.0) -> None: + def _render_frames(queue: mp.Queue, event: mp.Event, overlays: list = None, timeout: float = 10.0) -> None: """Rendering the frames in another process. This allows the UI to have the main thread of its process while the user code continues to execute. @@ -154,6 +161,8 @@ def _render_frames(queue: mp.Queue, overlays: list = None, timeout: float = 10.0 try: image = queue.get(True, timeout=timeout) while image: + if event.is_set(): + break if overlays: for overlay in overlays: overlay.apply_overlay(image) @@ -167,6 +176,7 @@ def _render_frames(queue: mp.Queue, overlays: list = None, timeout: float = 10.0 pass except KeyboardInterrupt: pass - - cv2.destroyWindow(window_name) - cv2.waitKey(1) + finally: + event.set() + cv2.destroyWindow(window_name) + cv2.waitKey(1) diff --git a/anki_vector/world.py b/anki_vector/world.py index de75bd4..fa8a470 100644 --- a/anki_vector/world.py +++ b/anki_vector/world.py @@ -75,13 +75,13 @@ def __init__(self, robot): self._objects = {} # Subscribe to callbacks that updates the world view - self._robot.events.subscribe( - self._on_face_observed, - Events.robot_observed_face) + self._robot.events.subscribe(self._on_face_observed, + Events.robot_observed_face, + on_connection_thread=True) - self._robot.events.subscribe( - self._on_object_observed, - Events.robot_observed_object) + self._robot.events.subscribe(self._on_object_observed, + Events.robot_observed_object, + on_connection_thread=True) #### Public Properties #### @@ -245,13 +245,11 @@ def close(self): for obj in self._objects.values(): obj.teardown() - self._robot.events.unsubscribe( - self._on_face_observed, - Events.robot_observed_face) + self._robot.events.unsubscribe(self._on_face_observed, + Events.robot_observed_face) - self._robot.events.unsubscribe( - self._on_object_observed, - Events.robot_observed_object) + self._robot.events.unsubscribe(self._on_object_observed, + Events.robot_observed_object) def get_object(self, object_id: int): """Fetches an object instance with the given id. diff --git a/docs/source/advanced-tips.rst b/docs/source/advanced-tips.rst index 30ad600..54e434b 100644 --- a/docs/source/advanced-tips.rst +++ b/docs/source/advanced-tips.rst @@ -12,14 +12,14 @@ Moving Vector between WiFi networks When you move Vector from one WiFi network to another (using the Vector App), or if your Vector's IP changes, you will also need to make some changes to -your SDK setup. To assist in this migration, ``configure.py`` provides a ``-u`` -parameter to quickly reconnect to Vector. +your SDK setup. To assist in this migration, the ``anki_vector.configure`` +executable submodule provides a ``-u`` parameter to quickly reconnect to Vector. To update your connection, you will need to find the IP address on Vector's face, and the serial number of the robot you are updating. Then from your terminal run:: - python3 configure.py -u "" -s "" + python3 -m anki_vector.configure -u "" -s "" ^^^^^^^^^^^^^^^^^^^^^^ @@ -57,9 +57,9 @@ and set it to Vector's serial number:: Set ANKI_ROBOT_HOST and VECTOR_ROBOT_NAME ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -When running ``configure.py``, you must provide Vector's ip and name. +When running the ``anki_vector.configure`` executable submodule, you must provide Vector's ip and name. To avoid typing these in, you can instead create environment variables -ANKI_ROBOT_HOST and VECTOR_ROBOT_NAME. Then ``configure.py`` will automatically pick +ANKI_ROBOT_HOST and VECTOR_ROBOT_NAME. Then ``anki_vector.configure`` will automatically pick up those settings:: export ANKI_ROBOT_HOST="192.168.42.42" diff --git a/docs/source/api.rst b/docs/source/api.rst index 69e41ed..1602ab9 100644 --- a/docs/source/api.rst +++ b/docs/source/api.rst @@ -27,6 +27,7 @@ The API anki_vector.proximity anki_vector.robot anki_vector.screen + anki_vector.status anki_vector.touch anki_vector.util anki_vector.viewer diff --git a/docs/source/conf.py b/docs/source/conf.py index e81da14..505b9d5 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -77,7 +77,7 @@ def fetch_sdk_version(): #'sphinx.ext.napoleon' ] -verlink_base_url = 'http://vectorsdk.anki.com/%s/' % sdk_version +verlink_base_url = 'http://developer.anki.com/vector/%s/' % sdk_version verlink_version = sdk_version intersphinx_mapping = { @@ -382,7 +382,7 @@ def fetch_sdk_version(): texinfo_documents = [ (master_doc, 'VectorSDK', 'Vector SDK Documentation', author, 'VectorSDK', 'The SDK for directly controlling your Vector', - 'Miscellaneous'), # TODO: clean this up + 'Miscellaneous'), ] # Documents to append as an appendix to all manuals. diff --git a/docs/source/downloads.rst b/docs/source/downloads.rst new file mode 100644 index 0000000..863c571 --- /dev/null +++ b/docs/source/downloads.rst @@ -0,0 +1,25 @@ +######### +Downloads +######### + +------------ +SDK Examples +------------ + +Download Python example scripts that use the Vector SDK. + +:verlink:`macOS/Linux SDK Examples ` + +:verlink:`Windows SDK Examples ` + +------ +GitHub +------ + +Clone, fork, or report issues on the `GitHub vector-python-sdk repository `_. + +---- + +`Terms and Conditions `_ and `Privacy Policy `_ + +`Click here to return to the Anki Developer website. `_ diff --git a/docs/source/getstarted.rst b/docs/source/getstarted.rst index f115b8c..4f61616 100644 --- a/docs/source/getstarted.rst +++ b/docs/source/getstarted.rst @@ -4,11 +4,11 @@ Getting Started With the Vector SDK To make sure you get the best experience possible out of the SDK, please ensure you have followed the steps in the :doc:`Initial Setup `. ------------------ -Anki SDK Forums ------------------ +--------------------- +Anki Developer Forums +--------------------- -Please visit our `Anki SDK Forums `_ where you can: +Please visit our `Anki Developer Forums `_ where you can: * Get assistance with your code @@ -26,7 +26,6 @@ Prerequisites ------------- * You have completed the Installation steps, found here: :ref:`initial` -* You have updated Vector to OS 1.0.1 or later. Check the OS version by putting Vector on the charger, double-tapping his backpack button, and raising and lowering his arms once. * The Vector companion app is *not* currently connected to Vector. * Vector is connected to the same network as your computer. * You can see Vector's eyes on his screen. @@ -35,7 +34,7 @@ Prerequisites Starting Up the SDK ------------------- -On the computer, open Terminal (macOS/Linux) or Command Prompt (Windows) and navigate into your ``vector_python_sdk_0.5.0`` folder by typing ``cd vector_python_sdk_0.5.0``, and press **Enter**. +On the computer, open Terminal (macOS/Linux) or Command Prompt (Windows) and type ``cd anki_vector_sdk_examples``, where *anki_vector_sdk_examples* is the directory you extracted the examples into, and press **Enter**. ---------------- Example Program @@ -65,11 +64,11 @@ First, change to the ``tutorials`` sub-directory of the ``examples`` directory. Then, run the program. - a. For macOS and Linux systems, type the following and press **Enter**:: + a. For macOS and Ubuntu 18.04 systems, type the following and press **Enter**:: ./01_hello_world.py - The same can also be achieved on macOS/Linux with:: + The same can also be achieved with:: python3 01_hello_world.py @@ -77,6 +76,11 @@ Then, run the program. py 01_hello_world.py + c. For Ubuntu 16.04 systems, type the following and press **Enter**:: + + python3.6 01_hello_world.py + + 2. If done correctly, Vector will say "Hello, World!" .. warning:: If Vector does not perform as expected, look at the first Terminal window and make sure no error messages appeared. If you continue to have issues, please seek help in the Forums. diff --git a/docs/source/images/vector-sdk-alpha.jpg b/docs/source/images/vector-sdk-alpha.jpg new file mode 100644 index 0000000..91c5389 Binary files /dev/null and b/docs/source/images/vector-sdk-alpha.jpg differ diff --git a/docs/source/images/vector-sdk-img.png b/docs/source/images/vector-sdk-img.png deleted file mode 100644 index 55e42b0..0000000 Binary files a/docs/source/images/vector-sdk-img.png and /dev/null differ diff --git a/docs/source/index.rst b/docs/source/index.rst index a4b7d77..a1b1ef1 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -1,10 +1,16 @@ -.. image:: images/vector-sdk-img.png +.. image:: images/vector-sdk-alpha.jpg | -========================== -Welcome to the Vector SDK! -========================== +=============================== +Welcome to the Vector SDK Alpha +=============================== + +The Vector SDK gives you direct access to Vector's unprecedented set of advanced sensors, AI capabilities, and robotics technologies including computer vision, intelligent mapping and navigation, and a groundbreaking collection of expressive animations. + +It's powerful but easy to use, complex but not complicated, and versatile enough to be used across a wide range of domains including enterprise, research, and entertainment. + +Please note this is an alpha version of the Vector SDK that is not yet feature complete, but already provides access to many of Vector's hardware and software features. Please visit the official `Anki Developer Forums `_ for more details. .. toctree:: :maxdepth: 1 @@ -17,6 +23,12 @@ Welcome to the Vector SDK! troubleshooting.rst advanced-tips.rst +.. toctree:: + :maxdepth: 2 + :caption: Downloads + + downloads.rst + .. toctree:: :maxdepth: 2 :caption: Get Started diff --git a/docs/source/initial.rst b/docs/source/initial.rst index 1b30e8e..719a450 100644 --- a/docs/source/initial.rst +++ b/docs/source/initial.rst @@ -14,15 +14,28 @@ To install the SDK on your system, select the instructions for your computer's o * :ref:`install-windows` * :ref:`install-linux` + +-------------------- +SDK Example Programs +-------------------- + +Anki provides example programs for novice and advanced users to run with the SDK. Download the SDK example programs here: + + * :verlink:`macOS/Linux SDK Examples ` + + * :verlink:`Windows SDK Examples ` + +Once downloaded, extract the packaged files to a new directory. + .. .. _trouble: -^^^^^^^^^^^^^^^^^ -Anki SDK Forums -^^^^^^^^^^^^^^^^^ +^^^^^^^^^^^^^^^^^^^^^ +Anki Developer Forums +^^^^^^^^^^^^^^^^^^^^^ -Please visit the `Anki SDK Forums `_ to ask questions, find solutions and for general discussion. +Please visit the `Anki Developer Forums `_ to ask questions, find solutions and for general discussion. ---- diff --git a/docs/source/install-linux.rst b/docs/source/install-linux.rst index 6e4afdb..5032c0e 100644 --- a/docs/source/install-linux.rst +++ b/docs/source/install-linux.rst @@ -11,7 +11,6 @@ Prerequisites * Vector is powered on. * You have successfully created an Anki account. * Vector has been set up with the Vector companion app. -* You have updated Vector to OS 1.0.1 or later. Check the OS version by putting Vector on the charger, double-tapping his backpack button, and raising and lowering his arms once. * The Vector companion app is *not* currently connected to Vector. * Vector is connected to the same network as your computer. * You can see Vector's eyes on his screen. @@ -19,16 +18,16 @@ Prerequisites This guide provides instructions on installing the Vector SDK for computers running with an Ubuntu Linux operating system. -.. warning:: The Vector SDK is tested and and supported on Ubuntu 16.04 and 18.04. Anki makes no guarantee the Vector SDK will work on other versions of Linux. If you wish to try the Vector SDK on versions of Linux *other than* Ubuntu 16.04 or 18.04, please ensure the following dependencies are installed: +.. warning:: The Vector SDK is tested and and supported on Ubuntu 18.04 and 16.04. Anki makes no guarantee the Vector SDK will work on other versions of Linux. If you wish to try the Vector SDK on versions of Linux *other than* Ubuntu 18.04 or 16.04, please ensure the following dependencies are installed: * Python 3.6.1 or later * pip for Python 3 (Python package installer) -^^^^^^^^^^^^^^^^^^^^^^ -Ubuntu 16.04 and 18.04 -^^^^^^^^^^^^^^^^^^^^^^ +^^^^^^^^^^^^ +Ubuntu 18.04 +^^^^^^^^^^^^ """"""""""""""""""" Python Installation @@ -49,8 +48,7 @@ SDK Installation To install the SDK, type the following into the Terminal window:: - cd vector_python_sdk_0.5.0 - python3 -m pip install . + python3 -m pip install --user anki_vector ^^^^^^^^^^^^^^^^^^^^^ Vector Authentication @@ -58,22 +56,71 @@ Vector Authentication To authenticate with the robot, type the following into the Terminal window:: - cd vector_python_sdk_0.5.0 - ./configure.py + python3 -m anki_vector.configure You will be prompted for your robot's name, ip address and serial number. You will also be asked for your Anki login and password. Make sure to use the same account that was used to set up your Vector. You will see "SUCCESS!" when this script successfully completes. -.. note:: Running ``configure.py`` will automatically download the Vector robot certificate to your computer and store credentials to allow you to connect to Vector. These credentials will be stored under your home directory in folder ``.anki_vector``. +.. note:: Running ``anki_vector.configure`` executable submodule will automatically download the Vector robot certificate to your computer and store credentials to allow you to connect to Vector. These credentials will be stored under your home directory in folder ``.anki_vector``. .. warning:: These credentials give full access to your robot, including camera stream, audio stream and data. Do not share these credentials. + + +^^^^^^^^^^^^ +Ubuntu 16.04 +^^^^^^^^^^^^ + +"""""""""""""""""""""""""""""" +Python and Module Installation +"""""""""""""""""""""""""""""" + +1. Type the following into your Terminal window to install Python 3.6:: + + sudo add-apt-repository ppa:deadsnakes/ppa + sudo apt-get update + sudo apt-get install python3.6 + +2. Then install pip by typing in the following into the Terminal window:: + + sudo apt install python3-pip + +3. Install the following additional packages:: + + sudo apt-get install build-essential libssl-dev libffi-dev python3.6-dev + + +"""""""""""""""" +SDK Installation +"""""""""""""""" + +To install the SDK, type the following into the Terminal window:: + + python3.6 -m pip install --user anki_vector + +^^^^^^^^^^^^^^^^^^^^^ +Vector Authentication +^^^^^^^^^^^^^^^^^^^^^ + +To authenticate with the robot, type the following into the Terminal window:: + + python3.6 -m anki_vector.configure + +You will be prompted for your robot's name, ip address and serial number. You will also be asked for your Anki login and password. Make sure to use the same account that was used to set up your Vector. + +You will see "SUCCESS!" when this script successfully completes. + +.. note:: Running ``anki_vector.configure`` executable submodule will automatically download the Vector robot certificate to your computer and store credentials to allow you to connect to Vector. These credentials will be stored under your home directory in folder ``.anki_vector``. + +.. warning:: These credentials give full access to your robot, including camera stream, audio stream and data. Do not share these credentials. + + ^^^^^^^^^^^^^^^ Troubleshooting ^^^^^^^^^^^^^^^ -Please see the :doc:`Troubleshooting ` page for tips, or visit the `Anki SDK Forums `_ to ask questions, find solutions, or for general discussion. +Please see the :doc:`Troubleshooting ` page for tips, or visit the `Anki Developer Forums `_ to ask questions, find solutions, or for general discussion. ---- diff --git a/docs/source/install-macos.rst b/docs/source/install-macos.rst index 44a868a..48768c0 100644 --- a/docs/source/install-macos.rst +++ b/docs/source/install-macos.rst @@ -13,7 +13,6 @@ Prerequisites * Vector is powered on. * You have successfully created an Anki account. * Vector has been set up with the Vector companion app. -* You have updated Vector to OS 1.0.1 or later. Check the OS version by putting Vector on the charger, double-tapping his backpack button, and raising and lowering his arms once. * The Vector companion app is *not* currently connected to Vector. * Vector is connected to the same network as your computer. * You can see Vector's eyes on his screen. @@ -40,8 +39,7 @@ SDK Installation To install the SDK, navigate into the SDK folder and type the following into a Terminal window:: - cd vector_python_sdk_0.5.0 - python3 -m pip install . + python3 -m pip install --user anki_vector ^^^^^^^^^^^^^^^^^^^^^ Vector Authentication @@ -49,14 +47,13 @@ Vector Authentication To authenticate with the robot, type the following into the Terminal window:: - cd vector_python_sdk_0.5.0 - ./configure.py + python3 -m anki_vector.configure You will be prompted for your robot's name, ip address and serial number. You will also be asked for your Anki login and password. Make sure to use the same account that was used to set up your Vector. You will see "SUCCESS!" when this script successfully completes. -.. note:: Running ``configure.py`` will automatically download the Vector robot certificate to your computer and store credentials to allow you to connect to Vector. These credentials will be stored under your home directory in folder ``.anki_vector``. +.. note:: Running the ``anki_vector.configure`` executable submodule will automatically download the Vector robot certificate to your computer and store credentials to allow you to connect to Vector. These credentials will be stored under your home directory in folder ``.anki_vector``. .. warning:: These credentials give full access to your robot, including camera stream, audio stream and data. Do not share these credentials. @@ -64,7 +61,7 @@ You will see "SUCCESS!" when this script successfully completes. Troubleshooting ^^^^^^^^^^^^^^^ -Please see the :doc:`Troubleshooting ` page for tips, or visit the `Anki SDK Forums `_ to ask questions, find solutions, or for general discussion. +Please see the :doc:`Troubleshooting ` page for tips, or visit the `Anki Developer Forums `_ to ask questions, find solutions, or for general discussion. ---- diff --git a/docs/source/install-windows.rst b/docs/source/install-windows.rst index 54ccd89..19aaef3 100644 --- a/docs/source/install-windows.rst +++ b/docs/source/install-windows.rst @@ -13,7 +13,6 @@ Prerequisites * Vector is powered on. * You have successfully created an Anki account. * Vector has been set up with the Vector companion app. -* You have updated Vector to OS 1.0.1 or later. Check the OS version by putting Vector on the charger, double-tapping his backpack button, and raising and lowering his arms once. * The Vector companion app is *not* currently connected to Vector. * Vector is connected to the same network as your computer. * You can see Vector's eyes on his screen. @@ -34,8 +33,7 @@ SDK Installation To install the SDK, navigate into the SDK folder and type the following into a Command Prompt window:: - cd vector_python_sdk_0.5.0 - py -3 -m pip install . + py -3 -m pip install --user anki_vector .. note:: If you encounter an error during SDK installation, you may need to upgrade your pip install. Try ``python -m pip install --upgrade pip`` or ``py -3 -m pip install --upgrade pip`` @@ -47,14 +45,13 @@ Vector Authentication To authenticate with the robot, type the following into the Terminal window:: - cd vector_python_sdk_0.5.0 - py configure.py + py -m anki_vector.configure You will be prompted for your robot's name, ip address and serial number. You will also be asked for your Anki login and password. Make sure to use the same account that was used to set up your Vector. You will see "SUCCESS!" when this script successfully completes. -.. note:: Running ``configure.py`` will automatically download the Vector robot certificate to your computer and store credentials to allow you to connect to Vector. These credentials will be stored under your home directory in folder ``.anki_vector``. +.. note:: Running the ``anki_vector.configure`` executable submodule will automatically download the Vector robot certificate to your computer and store credentials to allow you to connect to Vector. These credentials will be stored under your home directory in folder ``.anki_vector``. .. warning:: These credentials give full access to your robot, including camera stream, audio stream and data. Do not share these credentials. @@ -62,7 +59,7 @@ You will see "SUCCESS!" when this script successfully completes. Troubleshooting ^^^^^^^^^^^^^^^ -Please see the :doc:`Troubleshooting ` page for tips, or visit the `Anki SDK Forums `_ to ask questions, find solutions, or for general discussion. +Please see the :doc:`Troubleshooting ` page for tips, or visit the `Anki Developer Forums `_ to ask questions, find solutions, or for general discussion. ---- diff --git a/docs/source/troubleshooting.rst b/docs/source/troubleshooting.rst index e566e76..7b9da20 100644 --- a/docs/source/troubleshooting.rst +++ b/docs/source/troubleshooting.rst @@ -36,21 +36,20 @@ Tutorial program does not run Before running a Python program, be sure you can see Vector's eyes. If instead you see an image of a mobile device, the Customer Care Info screen, a missing Wifi icon, or something else, please complete setup of your Vector first and then you will be ready set up the SDK. -Also, check whether Vector's IP address has changed since the last time you ran ``configure.py``. If so, see :ref:`moving_between_wifi` to set up the robot with the new IP address. +Also, check whether Vector's IP address has changed since the last time you ran ``anki_vector.configure``. If so, see :ref:`moving_between_wifi` to set up the robot with the new IP address. -^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Failure to run configure.py -^^^^^^^^^^^^^^^^^^^^^^^^^^^ +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Failure to run anki_vector.configure +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -The prerequisites to run ``configure.py`` are: +The prerequisites to run the ``anki_vector.configure`` executable submodule successfully are: -* Vector is powered on. * You have successfully created an Anki account. * Vector has been set up with the Vector companion app. -* You have updated Vector to OS 1.0.1 or later. Check the OS version by putting Vector on the charger, double-tapping his backpack button, and raising and lowering his arms once. * The Vector companion app is *not* currently connected to Vector. * Vector is connected to the same network as your computer. +* The ``anki_vector`` Python package must be installed. * You can see Vector's eyes on his screen. @@ -82,11 +81,11 @@ Can't find Vector's IP address Your Vector IP address looks like "192.168.40.134". Find the IP address from Vector's debug screen: double-click his backpack, move his arms up and down, then look for "IP" on his screen. -^^^^^^^^^^^^^^^ -Anki SDK Forums -^^^^^^^^^^^^^^^ +^^^^^^^^^^^^^^^^^^^^^ +Anki Developer Forums +^^^^^^^^^^^^^^^^^^^^^ -Please visit the `Anki SDK Forums `_ to ask questions, find solutions and for general discussion. +Please visit the `Anki Developer Forums `_ to ask questions, find solutions and for general discussion. ---- diff --git a/examples/README.md b/examples/README.md new file mode 100644 index 0000000..195e77a --- /dev/null +++ b/examples/README.md @@ -0,0 +1,5 @@ +# Example programs for the anki_vector Python SDK + +See the [tutorials](tutorials) directory for a progression of example programs all the way from [hello_world](tutorials/01_hello_world.py) through to more advanced examples. + +See the [apps](apps) directory for some fun fully-featured programs like a remote control. diff --git a/examples/apps/3d_viewer/3d_viewer.py b/examples/apps/3d_viewer/3d_viewer.py index 6752867..ebed01f 100755 --- a/examples/apps/3d_viewer/3d_viewer.py +++ b/examples/apps/3d_viewer/3d_viewer.py @@ -27,8 +27,7 @@ async def my_function(): - await asyncio.sleep(20) - print("done") + pass def main(): diff --git a/examples/apps/proximity_mapper/proximity_mapper.py b/examples/apps/proximity_mapper/proximity_mapper.py index a472b27..c423750 100755 --- a/examples/apps/proximity_mapper/proximity_mapper.py +++ b/examples/apps/proximity_mapper/proximity_mapper.py @@ -317,6 +317,8 @@ def open_point_sort_func(position: Vector3): # Creates the 3D Viewer for the connected robot. viewerInstance = OpenGLViewer(robot=robotInstance, show_viewer_controls=False) + robotInstance.behavior.drive_off_charger() + # The OpenGLViewer has to run on the main thread, so control is given to # it via the blocking 'run' call. The core loop of our program is injected into # this call to run in parallel on a secondary thread. When the injected function diff --git a/examples/apps/remote_control/remote_control.py b/examples/apps/remote_control/remote_control.py index 8f3b688..a98adc8 100755 --- a/examples/apps/remote_control/remote_control.py +++ b/examples/apps/remote_control/remote_control.py @@ -25,6 +25,10 @@ import time from lib import flask_helpers +import anki_vector +from anki_vector import util + + try: from flask import Flask, request except ImportError: @@ -35,13 +39,6 @@ except ImportError: sys.exit("Cannot import from PIL: Do `pip3 install --user Pillow` to install") -try: - import anki_vector - from anki_vector import util -except ImportError: - sys.exit("Cannot import anki_vector: Do `pip3 install -e .` in the vector home folder to install") - - def create_default_image(image_width, image_height, do_gradient=False): """Create a place-holder PIL image to use until we have a live feed from Vector""" image_bytes = bytearray([0x70, 0x70, 0x70]) * image_width * image_height diff --git a/examples/tutorials/07_dock_with_cube.py b/examples/tutorials/07_dock_with_cube.py index 3f36366..104388c 100755 --- a/examples/tutorials/07_dock_with_cube.py +++ b/examples/tutorials/07_dock_with_cube.py @@ -38,6 +38,7 @@ def main(): robot.behavior.set_head_angle(degrees(-5.0)) robot.behavior.set_lift_height(0.0) + print("Connecting to a cube...") robot.world.connect_cube() if robot.world.connected_light_cube: diff --git a/examples/tutorials/11_face_event_subscription.py b/examples/tutorials/11_face_event_subscription.py index d20018f..d90d2bb 100755 --- a/examples/tutorials/11_face_event_subscription.py +++ b/examples/tutorials/11_face_event_subscription.py @@ -23,6 +23,7 @@ he finishes speaking. """ +import functools import threading import anki_vector @@ -33,22 +34,24 @@ def main(): + evt = threading.Event() + + def on_robot_observed_face(robot, event_type, event): + print("Vector sees a face") + global said_text + if not said_text: + said_text = True + robot.say_text("I see a face!") + evt.set() + args = anki_vector.util.parse_command_args() with anki_vector.Robot(args.serial, enable_face_detection=True) as robot: - evt = threading.Event() - - async def on_robot_observed_face(event_type, event): - print("Vector sees a face") - global said_text - if not said_text: - said_text = True - await robot.say_text("I see a face!") - evt.set() # If necessary, move Vector's Head and Lift to make it easy to see his face robot.behavior.set_head_angle(degrees(50.0)) robot.behavior.set_lift_height(0.0) + on_robot_observed_face = functools.partial(on_robot_observed_face, robot) robot.events.subscribe(on_robot_observed_face, Events.robot_observed_face) print("------ waiting for face events, press ctrl+c to exit early ------") @@ -59,6 +62,8 @@ async def on_robot_observed_face(event_type, event): except KeyboardInterrupt: pass + robot.events.unsubscribe(on_robot_observed_face, Events.robot_observed_face) + if __name__ == '__main__': main() diff --git a/examples/tutorials/12_wake_word_subscription.py b/examples/tutorials/12_wake_word_subscription.py index bdf3525..86b0565 100755 --- a/examples/tutorials/12_wake_word_subscription.py +++ b/examples/tutorials/12_wake_word_subscription.py @@ -23,7 +23,7 @@ connection.py for more information. """ - +import functools import threading import anki_vector @@ -33,19 +33,20 @@ def main(): - args = anki_vector.util.parse_command_args() - with anki_vector.Robot(args.serial, requires_behavior_control=False, cache_animation_list=False) as robot: - evt = threading.Event() + evt = threading.Event() - async def on_wake_word(event_type, event): - await robot.conn.request_control() + def on_wake_word(robot, event_type, event): + robot.conn.request_control() - global wake_word_heard - if not wake_word_heard: - wake_word_heard = True - await robot.say_text("Hello") - evt.set() + global wake_word_heard + if not wake_word_heard: + wake_word_heard = True + robot.say_text("Hello") + evt.set() + args = anki_vector.util.parse_command_args() + with anki_vector.Robot(args.serial, requires_behavior_control=False, cache_animation_list=False) as robot: + on_wake_word = functools.partial(on_wake_word, robot) robot.events.subscribe(on_wake_word, Events.wake_word) print('------ Vector is waiting to hear "Hey Vector!" Press ctrl+c to exit early ------') diff --git a/setup.py b/setup.py index 8d3e3bc..6c283d2 100644 --- a/setup.py +++ b/setup.py @@ -1,41 +1,31 @@ # Copyright (c) 2018 Anki, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License in the file LICENSE.txt or at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. """ Vector SDK, by Anki. -Vector is the home robot who hangs out and helps out. +The Vector SDK is a connected vision- and character-based robotics platform for everyone. -This library lets you take command of Vector and write programs for him. +The Vector SDK gives you direct access to Vector's unprecedented set of advanced sensors, AI capabilities, and robotics technologies including computer vision, intelligent mapping and navigation, and a groundbreaking collection of expressive animations. -Vector features: +It's powerful but easy to use, complex but not complicated, and versatile enough to be used across a wide range of domains including enterprise, research, and entertainment. Find out more at https://developer.anki.com - * A camera with advanced vision system - * A robotic lifter - * Independent tank treads - * Pivotable head - * An accelerometer - * A gyroscope - * Cliff detection - * Face recognition - * Path planning - * Animation and behavior systems - * Light cube, with LEDs, an accelerometer and tap detection - * Single point time-of-flight NIR Laser - * Capactive casing - -This SDK provides users with access to take control of Vector and write simple -or advanced programs with him. +Vector SDK documentation: https://developer.anki.com/vector/docs/ +Official developer forum: https://forums.anki.com/ Requirements: * Python 3.6.1 or later - -Optional requirements for camera image processing/display: - * Pillow - * NumPy - -Optional requirements for 3D viewer/visualization: - * PyOpenGL - * Pillow """ import os.path @@ -43,7 +33,7 @@ from setuptools import setup if sys.version_info < (3, 6, 1): - sys.exit('The Anki Vector SDK requires Python 3.6.1 or later') + sys.exit('The Vector SDK requires Python 3.6.1 or later') HERE = os.path.abspath(os.path.dirname(__file__)) @@ -68,7 +58,7 @@ def get_requirements(): setup( name='anki_vector', version=VERSION, - description="SDK for Anki's Vector robot, the home robot who hangs out and helps out", + description="The Vector SDK is a connected vision- and character-based robotics platform for everyone.", long_description=__doc__, url='https://developer.anki.com', author='Anki, Inc', @@ -84,7 +74,7 @@ def get_requirements(): ], zip_safe=True, keywords='anki vector robot robotics sdk'.split(), - packages=['anki_vector', 'anki_vector.messaging'], + packages=['anki_vector', 'anki_vector.configure', 'anki_vector.messaging'], package_data={ 'anki_vector': ['LICENSE.txt', 'assets/*.obj', 'assets/*.mtl', 'assets/*.jpg', 'assets/LICENSE.txt']