Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 44 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -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
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.

Expand All @@ -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).

Expand Down
32 changes: 22 additions & 10 deletions anki_vector/behavior.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,22 +34,21 @@
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
from .messaging import protocol

# 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
Expand Down Expand Up @@ -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,
Expand All @@ -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
Expand All @@ -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,
Expand Down
File renamed without changes.
5 changes: 3 additions & 2 deletions anki_vector/connection.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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
Expand Down
Loading