├── docs ├── ext │ ├── __init__.py │ ├── custopoleon │ │ └── __init__.py │ └── verlink.py ├── source │ ├── .gitignore │ ├── _static │ │ └── .gitignore │ ├── images │ │ ├── annotate.jpg │ │ ├── cozmo-sdk-img.jpg │ │ └── custom_markers │ │ │ ├── SDK_2Circles.png │ │ │ ├── SDK_3Circles.png │ │ │ ├── SDK_4Circles.png │ │ │ ├── SDK_5Circles.png │ │ │ ├── SDK_2Diamonds.png │ │ │ ├── SDK_2Hexagons.png │ │ │ ├── SDK_2Triangles.png │ │ │ ├── SDK_3Diamonds.png │ │ │ ├── SDK_3Hexagons.png │ │ │ ├── SDK_3Triangles.png │ │ │ ├── SDK_4Diamonds.png │ │ │ ├── SDK_4Hexagons.png │ │ │ ├── SDK_4Triangles.png │ │ │ ├── SDK_5Diamonds.png │ │ │ ├── SDK_5Hexagons.png │ │ │ ├── SDK_5Triangles.png │ │ │ └── LICENSE.txt │ ├── _templates │ │ └── layout.html │ ├── downloads.rst │ ├── api.rst │ ├── index.rst │ ├── initial.rst │ ├── install-macos.rst │ ├── install-windows.rst │ ├── sdk-versions.rst │ ├── install-linux.rst │ ├── adb.rst │ └── vagrant.rst ├── .gitignore └── build │ └── .gitignore ├── vagrant ├── .gitignore ├── Vagrantfile └── setup-vm.sh ├── setup.cfg ├── examples ├── .gitignore ├── face_images │ ├── cozmosdk.png │ ├── hello_world.png │ ├── ifttt_gmail.png │ ├── ifttt_sports.png │ └── ifttt_stocks.png ├── README.md ├── apps │ ├── quiz_questions.json │ ├── 3d_viewer.py │ └── cli.py ├── tutorials │ ├── 01_basics │ │ ├── 01_hello_world.py │ │ ├── 03_count.py │ │ ├── 02_drive_and_turn.py │ │ ├── 04_drive_square.py │ │ ├── 07_backpack_lights.py │ │ ├── 06_sing_scales.py │ │ ├── 09_cube_lights.py │ │ ├── 12_random_animation.py │ │ ├── 08_animation.py │ │ ├── 05_motors.py │ │ ├── 10_play_sound.py │ │ └── 11_play_song.py │ ├── 04_cubes_and_objects │ │ ├── 01_go_to_pose_test.py │ │ ├── 13_pop_a_wheelie.py │ │ ├── 12_roll_cube.py │ │ ├── 02_create_wall.py │ │ ├── 11_dock_with_cube.py │ │ ├── 04_stack_or_roll.py │ │ ├── 06_pickup_furthest.py │ │ ├── 03_go_to_object_test.py │ │ ├── 07_lookaround.py │ │ ├── 05_cube_stack.py │ │ ├── 10_object_moved.py │ │ ├── 08_drive_to_charger_test.py │ │ └── 09_custom_objects.py │ ├── 03_vision │ │ ├── 01_light_when_face.py │ │ ├── 02_face_follower.py │ │ ├── 03_annotate.py │ │ └── 04_exposure.py │ ├── 05_async_python │ │ ├── 01_cube_blinker_sync.py │ │ └── 02_cube_blinker.py │ ├── 02_cozmo_face │ │ ├── 01_cozmo_face_image.py │ │ └── 02_cozmo_face_mirror.py │ └── 06_actions │ │ └── 01_parallel_actions.py ├── tools │ └── cubes │ │ ├── connect_cubes.py │ │ ├── disconnect_cubes.py │ │ ├── log_cube_battery_levels.py │ │ └── auto_cube_disconnect.py ├── multi_robot │ ├── multi_robot_independent.py │ └── multi_robot_unified.py ├── if_this_then_that │ └── common │ │ └── __init__.py └── lib │ └── flask_helpers.py ├── src └── cozmo │ ├── .gitignore │ ├── assets │ ├── cube1.jpg │ ├── cube2.jpg │ ├── cube3.jpg │ ├── cube1.mtl │ ├── cube2.mtl │ ├── cube3.mtl │ ├── cozmo.mtl │ └── LICENSE.txt │ ├── usbmux │ └── __init__.py │ ├── version.py │ ├── robot_alignment.py │ ├── __init__.py │ ├── exceptions.py │ ├── clad_protocol.py │ ├── song.py │ ├── oled_face.py │ └── tkview.py ├── dist └── .gitignore ├── .gitignore ├── README.md ├── CONTRIBUTING.md ├── tests ├── __init__.py └── lint │ └── run-sdk-pylint-tests.sh ├── tox.ini ├── setup.py ├── Makefile └── CODESTYLE.md /docs/ext/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /vagrant/.gitignore: -------------------------------------------------------------------------------- 1 | .vagrant 2 | -------------------------------------------------------------------------------- /docs/source/.gitignore: -------------------------------------------------------------------------------- 1 | generated/ 2 | -------------------------------------------------------------------------------- /setup.cfg: -------------------------------------------------------------------------------- 1 | [wheel] 2 | universal = 0 3 | -------------------------------------------------------------------------------- /docs/.gitignore: -------------------------------------------------------------------------------- 1 | *.sw? 2 | __pycache__ 3 | *.pyc 4 | -------------------------------------------------------------------------------- /examples/.gitignore: -------------------------------------------------------------------------------- 1 | # copied in by Makefile 2 | LICENSE.txt 3 | -------------------------------------------------------------------------------- /src/cozmo/.gitignore: -------------------------------------------------------------------------------- 1 | # Copied in by Makefile 2 | LICENSE.txt 3 | !assets/LICENSE.txt 4 | -------------------------------------------------------------------------------- /dist/.gitignore: -------------------------------------------------------------------------------- 1 | # No files should be checked into this directory 2 | * 3 | !.gitignore 4 | -------------------------------------------------------------------------------- /docs/build/.gitignore: -------------------------------------------------------------------------------- 1 | # No files should be checked into this directory 2 | * 3 | !.gitignore 4 | -------------------------------------------------------------------------------- /docs/source/_static/.gitignore: -------------------------------------------------------------------------------- 1 | # No files should be checked into this directory 2 | * 3 | !.gitignore 4 | -------------------------------------------------------------------------------- /src/cozmo/assets/cube1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cozmoroot/cozmo-python-sdk/HEAD/src/cozmo/assets/cube1.jpg -------------------------------------------------------------------------------- /src/cozmo/assets/cube2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cozmoroot/cozmo-python-sdk/HEAD/src/cozmo/assets/cube2.jpg -------------------------------------------------------------------------------- /src/cozmo/assets/cube3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cozmoroot/cozmo-python-sdk/HEAD/src/cozmo/assets/cube3.jpg -------------------------------------------------------------------------------- /docs/source/images/annotate.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cozmoroot/cozmo-python-sdk/HEAD/docs/source/images/annotate.jpg -------------------------------------------------------------------------------- /examples/face_images/cozmosdk.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cozmoroot/cozmo-python-sdk/HEAD/examples/face_images/cozmosdk.png -------------------------------------------------------------------------------- /docs/source/images/cozmo-sdk-img.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cozmoroot/cozmo-python-sdk/HEAD/docs/source/images/cozmo-sdk-img.jpg -------------------------------------------------------------------------------- /examples/face_images/hello_world.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cozmoroot/cozmo-python-sdk/HEAD/examples/face_images/hello_world.png -------------------------------------------------------------------------------- /examples/face_images/ifttt_gmail.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cozmoroot/cozmo-python-sdk/HEAD/examples/face_images/ifttt_gmail.png -------------------------------------------------------------------------------- /examples/face_images/ifttt_sports.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cozmoroot/cozmo-python-sdk/HEAD/examples/face_images/ifttt_sports.png -------------------------------------------------------------------------------- /examples/face_images/ifttt_stocks.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cozmoroot/cozmo-python-sdk/HEAD/examples/face_images/ifttt_stocks.png -------------------------------------------------------------------------------- /docs/source/images/custom_markers/SDK_2Circles.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cozmoroot/cozmo-python-sdk/HEAD/docs/source/images/custom_markers/SDK_2Circles.png -------------------------------------------------------------------------------- /docs/source/images/custom_markers/SDK_3Circles.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cozmoroot/cozmo-python-sdk/HEAD/docs/source/images/custom_markers/SDK_3Circles.png -------------------------------------------------------------------------------- /docs/source/images/custom_markers/SDK_4Circles.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cozmoroot/cozmo-python-sdk/HEAD/docs/source/images/custom_markers/SDK_4Circles.png -------------------------------------------------------------------------------- /docs/source/images/custom_markers/SDK_5Circles.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cozmoroot/cozmo-python-sdk/HEAD/docs/source/images/custom_markers/SDK_5Circles.png -------------------------------------------------------------------------------- /docs/source/images/custom_markers/SDK_2Diamonds.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cozmoroot/cozmo-python-sdk/HEAD/docs/source/images/custom_markers/SDK_2Diamonds.png -------------------------------------------------------------------------------- /docs/source/images/custom_markers/SDK_2Hexagons.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cozmoroot/cozmo-python-sdk/HEAD/docs/source/images/custom_markers/SDK_2Hexagons.png -------------------------------------------------------------------------------- /docs/source/images/custom_markers/SDK_2Triangles.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cozmoroot/cozmo-python-sdk/HEAD/docs/source/images/custom_markers/SDK_2Triangles.png -------------------------------------------------------------------------------- /docs/source/images/custom_markers/SDK_3Diamonds.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cozmoroot/cozmo-python-sdk/HEAD/docs/source/images/custom_markers/SDK_3Diamonds.png -------------------------------------------------------------------------------- /docs/source/images/custom_markers/SDK_3Hexagons.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cozmoroot/cozmo-python-sdk/HEAD/docs/source/images/custom_markers/SDK_3Hexagons.png -------------------------------------------------------------------------------- /docs/source/images/custom_markers/SDK_3Triangles.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cozmoroot/cozmo-python-sdk/HEAD/docs/source/images/custom_markers/SDK_3Triangles.png -------------------------------------------------------------------------------- /docs/source/images/custom_markers/SDK_4Diamonds.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cozmoroot/cozmo-python-sdk/HEAD/docs/source/images/custom_markers/SDK_4Diamonds.png -------------------------------------------------------------------------------- /docs/source/images/custom_markers/SDK_4Hexagons.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cozmoroot/cozmo-python-sdk/HEAD/docs/source/images/custom_markers/SDK_4Hexagons.png -------------------------------------------------------------------------------- /docs/source/images/custom_markers/SDK_4Triangles.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cozmoroot/cozmo-python-sdk/HEAD/docs/source/images/custom_markers/SDK_4Triangles.png -------------------------------------------------------------------------------- /docs/source/images/custom_markers/SDK_5Diamonds.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cozmoroot/cozmo-python-sdk/HEAD/docs/source/images/custom_markers/SDK_5Diamonds.png -------------------------------------------------------------------------------- /docs/source/images/custom_markers/SDK_5Hexagons.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cozmoroot/cozmo-python-sdk/HEAD/docs/source/images/custom_markers/SDK_5Hexagons.png -------------------------------------------------------------------------------- /docs/source/images/custom_markers/SDK_5Triangles.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cozmoroot/cozmo-python-sdk/HEAD/docs/source/images/custom_markers/SDK_5Triangles.png -------------------------------------------------------------------------------- /src/cozmo/assets/cube1.mtl: -------------------------------------------------------------------------------- 1 | newmtl cube_mtl 2 | map_Kd cube1.jpg 3 | illum 4 4 | Kd 0.65 0.65 0.65 5 | Ka 0.15 0.15 0.15 6 | Tf 1.00 1.00 1.00 7 | Ni 1.00 8 | Ks 0.99 0.99 0.99 9 | Ns 10 10 | -------------------------------------------------------------------------------- /src/cozmo/assets/cube2.mtl: -------------------------------------------------------------------------------- 1 | newmtl cube_mtl 2 | map_Kd cube2.jpg 3 | illum 4 4 | Kd 0.65 0.65 0.65 5 | Ka 0.15 0.15 0.15 6 | Tf 1.00 1.00 1.00 7 | Ni 1.00 8 | Ks 0.99 0.99 0.99 9 | Ns 10 10 | -------------------------------------------------------------------------------- /src/cozmo/assets/cube3.mtl: -------------------------------------------------------------------------------- 1 | newmtl cube_mtl 2 | map_Kd cube3.jpg 3 | illum 4 4 | Kd 0.65 0.65 0.65 5 | Ka 0.15 0.15 0.15 6 | Tf 1.00 1.00 1.00 7 | Ni 1.00 8 | Ks 0.99 0.99 0.99 9 | Ns 10 10 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | *.sw? 3 | __pycache__ 4 | *.pyc 5 | *.tox 6 | *.egg 7 | *.egg-info 8 | .cache 9 | /build 10 | htmlcov 11 | .coverage 12 | 13 | /tests/lint/logs 14 | # pycharm 15 | .idea 16 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Anki Cozmo - Python SDK 2 | 3 | ![Cozmo](docs/source/images/cozmo-sdk-img.jpg) 4 | 5 | Learn more about Cozmo: https://anki.com/cozmo 6 | 7 | Learn more about the SDK: https://developer.anki.com/ 8 | 9 | SDK documentation: http://cozmosdk.anki.com/docs/ 10 | 11 | Forums: https://forums.anki.com/ 12 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | We accept contributions from 3rd parties as long as you first complete an individual CLA (Contributor License Agreement): 2 | 3 | http://go.anki.com/individual-cla 4 | 5 | If your employer(s) have rights to intellectual property that you create, and that includes your contributions, then we also require a separate Corporate CLA from them: 6 | 7 | http://go.anki.com/corporate-cla 8 | 9 | Please also review our: [Code Style Guide](CODESTYLE.md) 10 | -------------------------------------------------------------------------------- /docs/source/_templates/layout.html: -------------------------------------------------------------------------------- 1 | {% extends "!layout.html" %} 2 | {% block extrahead %} 3 | 4 | 11 | 12 | 13 | {{ super() }} 14 | {% endblock %} 15 | -------------------------------------------------------------------------------- /tests/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2016 Anki, Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License in the file LICENSE.txt or at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | -------------------------------------------------------------------------------- /src/cozmo/usbmux/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2016 Anki, Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License in the file LICENSE.txt or at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | from .usbmux import * 16 | -------------------------------------------------------------------------------- /examples/README.md: -------------------------------------------------------------------------------- 1 | # Example programs for the Anki Cozmo Python SDK 2 | 3 | See the [tutorials](tutorials) directory for a progression of example programs all the way from [hello_world](tutorials/01_basics/01_hello_world.py) in the [01_basics](tutorials/01_basics) sub-directory, through to more advanced vision and action examples. 4 | 5 | See the [apps](apps) directory for some fun fully-featured programs like a remote control and a desk security guard. 6 | 7 | See the [if_this_then_that](if_this_then_that) directory for some examples that connect Cozmo to the "If This Then That" service. 8 | 9 | See the [multi_robot](multi_robot) directory for an example of how to connect the SDK to multiple devices and robots. 10 | 11 | -------------------------------------------------------------------------------- /tox.ini: -------------------------------------------------------------------------------- 1 | # Tox (http://tox.testrun.org/) is a tool for running tests 2 | # in multiple virtualenvs. This configuration file will run the 3 | # test suite on all supported python versions. To use it, "pip install tox" 4 | # and then run "tox" from this directory. 5 | 6 | [tox] 7 | envlist = py35,coverage,docs 8 | 9 | [testenv] 10 | commands = py.test 11 | deps = 12 | pytest 13 | pytest-cov 14 | 15 | [testenv:coverage] 16 | changedir=tests 17 | commands=pytest --cov=cozmo 18 | 19 | [testenv:docs] 20 | changedir = docs 21 | deps = 22 | sphinx 23 | sphinx-rtd-theme 24 | numpy 25 | Pillow 26 | PyOpenGL 27 | commands = 28 | sphinx-build -W -b html -d {envtmpdir}/doctrees source {envtmpdir}/html 29 | -------------------------------------------------------------------------------- /docs/source/downloads.rst: -------------------------------------------------------------------------------- 1 | ######### 2 | Downloads 3 | ######### 4 | 5 | ------------ 6 | SDK Examples 7 | ------------ 8 | 9 | Download Python example scripts that use the Cozmo SDK. 10 | 11 | :verlink:`macOS/Linux SDK Examples ` 12 | 13 | :verlink:`Windows SDK Examples ` 14 | 15 | ------ 16 | GitHub 17 | ------ 18 | 19 | Clone, fork, or report issues on the `GitHub cozmo-python-sdk repository `_. 20 | 21 | ---- 22 | 23 | `Terms and Conditions `_ and `Privacy Policy `_ 24 | 25 | `Click here to return to the Anki Developer website. `_ 26 | -------------------------------------------------------------------------------- /examples/apps/quiz_questions.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "question": "What is 3 times 4?", 4 | "answer_options": ["12", "9", "15", "14"] 5 | }, 6 | { 7 | "question": "Which of these is not a type of penguin?", 8 | "answer_options": ["Rigatoni", "Fairy", "Macaroni", "Adelie"] 9 | }, 10 | { 11 | "question": "Which of these is not a species of rodent?", 12 | "answer_options": ["Rabbit", "Beaver", "Lemming", "Capybara"] 13 | }, 14 | { 15 | "question": "In physics, which of these forces is real?", 16 | "answer_options": ["Centripetal", "Coriolis", "Centrifugal", "Euler"] 17 | }, 18 | { 19 | "question": "What is the 8th digit of Pi?", 20 | "answer_options": ["6", "5", "2", "3"] 21 | } 22 | ] 23 | -------------------------------------------------------------------------------- /docs/source/api.rst: -------------------------------------------------------------------------------- 1 | The API 2 | ======= 3 | 4 | 5 | .. autosummary:: 6 | :nosignatures: 7 | :toctree: generated 8 | 9 | cozmo 10 | cozmo.action 11 | cozmo.anim 12 | cozmo.annotate 13 | cozmo.audio 14 | cozmo.behavior 15 | cozmo.camera 16 | cozmo.conn 17 | cozmo.event 18 | cozmo.exceptions 19 | cozmo.faces 20 | cozmo.lights 21 | cozmo.nav_memory_map 22 | cozmo.objects 23 | cozmo.oled_face 24 | cozmo.opengl 25 | cozmo.pets 26 | cozmo.robot 27 | cozmo.robot_alignment 28 | cozmo.run 29 | cozmo.song 30 | cozmo.tkview 31 | cozmo.util 32 | cozmo.world 33 | 34 | .. 35 | 36 | ---- 37 | 38 | `Terms and Conditions `_ and `Privacy Policy `_ 39 | 40 | `Click here to return to the Anki Developer website. `_ 41 | -------------------------------------------------------------------------------- /examples/tutorials/01_basics/01_hello_world.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # Copyright (c) 2016 Anki, Inc. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License in the file LICENSE.txt or at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | '''Hello World 18 | 19 | Make Cozmo say 'Hello World' in this simple Cozmo SDK example program. 20 | ''' 21 | 22 | import cozmo 23 | 24 | 25 | def cozmo_program(robot: cozmo.robot.Robot): 26 | robot.say_text("Hello World").wait_for_completed() 27 | 28 | 29 | cozmo.run_program(cozmo_program) 30 | -------------------------------------------------------------------------------- /docs/ext/custopoleon/__init__.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Due to deficiencies in the design of Sphinx, two modules cannot both 3 | observe the same event. Napaleon hooks the autodoc-skip-member event 4 | to determine which memembers to show.. We want to use the same thing 5 | to special case the AnimTriggers and BehaviorTypes classes so that 6 | their undocumented memebers show up in the docs. 7 | 8 | As a workaround this module monkey patches Napoleon to wrap their 9 | autodoc-skip-member implementation and special case the response for 10 | our classes. 11 | ''' 12 | 13 | 14 | import sphinx.ext.napoleon 15 | 16 | 17 | _org_skip_member = sphinx.ext.napoleon._skip_member 18 | 19 | def _skip_member(app, what, name, obj, skip, options): 20 | clsname = obj.__class__.__name__ 21 | if clsname in ('_AnimTrigger', '_BehaviorType'): 22 | return False 23 | return _org_skip_member(app, what, name, obj, skip, options) 24 | 25 | sphinx.ext.napoleon._skip_member = _skip_member 26 | 27 | def setup(app): 28 | return sphinx.ext.napoleon.setup(app) 29 | 30 | -------------------------------------------------------------------------------- /tests/lint/run-sdk-pylint-tests.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | trap "exit" INT 3 | TODAY=`date +%Y-%m-%d_%H.%M.%S` 4 | 5 | python3 -c "import pylint" 6 | if [ "$?" = "1" ]; then 7 | echo "Aborting pylint pass - pylint not installed" 8 | exit 1 9 | fi 10 | 11 | mkdir -p logs 12 | LOG_FILE="logs/pylint_log_$TODAY.txt" 13 | SCAN_FILE_PATTERN="../../src/cozmo/*.py" 14 | 15 | echo "Running Pylint on \"${SCAN_FILE_PATTERN}\"" > ${LOG_FILE} 16 | 17 | FILES_TO_SCAN=`ls -1q ${SCAN_FILE_PATTERN} | wc -l | sed -e 's/ //g'` 18 | FILES_SCANNED=0 19 | 20 | pylint -j 4 --rcfile pylintrc ${SCAN_FILE_PATTERN} | grep 'W:\|E:\|Module' >> ${LOG_FILE} 2>&1 21 | 22 | PROBLEMS_FOUND=`cat ${LOG_FILE} | grep 'W:\|E:' | wc -l | sed -e 's/ //g'` 23 | 24 | if ((${PROBLEMS_FOUND} > 0)); then 25 | echo "Pylint pass found ${PROBLEMS_FOUND} problems, refer to ${LOG_FILE} for more information" 26 | echo "- found ${PROBLEMS_FOUND} problems" >> ${LOG_FILE} 27 | exit 1 28 | else 29 | echo "Pylint pass completed successfully" 30 | echo "- found no problems" >> ${LOG_FILE} 31 | exit 0 32 | fi 33 | -------------------------------------------------------------------------------- /src/cozmo/version.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2016-2017 Anki, Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License in the file LICENSE.txt or at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | __version__ = "1.4.11.dev0" 16 | 17 | # Specify the version of cozmoclad that this package requires 18 | # Releases of the Cozmo package must specify an exact cozmoclad release 19 | # to ensure compatibility with a specific release of the ios/android app. 20 | __cozmoclad_version__ = None 21 | #__cozmoclad_version__ = "1.7.1" 22 | 23 | # Minimum cozmoclad version supported by the API 24 | __min_cozmoclad_version__ = "2.0.0" 25 | -------------------------------------------------------------------------------- /examples/tools/cubes/connect_cubes.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # Copyright (c) 2017 Anki, Inc. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License in the file LICENSE.txt or at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | '''Connect to Cozmo's cubes. 18 | 19 | This script instructs Cozmo to connect to the cubes. This is necessary if you 20 | have previously disconnected from the cubes (to preserve battery life). The 21 | connection process can take up to about 5 seconds. 22 | ''' 23 | 24 | import cozmo 25 | 26 | 27 | async def cozmo_program(robot: cozmo.robot.Robot): 28 | await robot.world.connect_to_cubes() 29 | 30 | 31 | cozmo.robot.Robot.drive_off_charger_on_connect = False 32 | cozmo.run_program(cozmo_program) 33 | -------------------------------------------------------------------------------- /examples/apps/3d_viewer.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # Copyright (c) 2017 Anki, Inc. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License in the file LICENSE.txt or at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | '''3d Viewer example, with remote control. 18 | 19 | This is an example of how you can use the 3D viewer with a program, and the 20 | 3D viewer and controls will work automatically. 21 | ''' 22 | 23 | import asyncio 24 | 25 | import cozmo 26 | 27 | 28 | async def cozmo_program(robot: cozmo.robot.Robot): 29 | while True: 30 | await asyncio.sleep(1) 31 | 32 | 33 | cozmo.robot.Robot.drive_off_charger_on_connect = False 34 | cozmo.run_program(cozmo_program, use_3d_viewer=True, use_viewer=True) 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /examples/tools/cubes/disconnect_cubes.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # Copyright (c) 2017 Anki, Inc. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License in the file LICENSE.txt or at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | '''Disconnect from Cozmo's cubes. 18 | 19 | This script instructs Cozmo to disconnect from the cubes. This can be used to 20 | conserve cube battery life if you're not actively using them in your programs. 21 | You can use `connect_cubes.py` late to re-connect to the cubes. 22 | ''' 23 | 24 | import cozmo 25 | 26 | 27 | async def cozmo_program(robot: cozmo.robot.Robot): 28 | robot.world.disconnect_from_cubes() 29 | 30 | 31 | cozmo.robot.Robot.drive_off_charger_on_connect = False 32 | cozmo.run_program(cozmo_program) 33 | -------------------------------------------------------------------------------- /examples/tutorials/04_cubes_and_objects/01_go_to_pose_test.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # Copyright (c) 2016 Anki, Inc. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License in the file LICENSE.txt or at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | '''Tell Cozmo to drive to the specified pose and orientation. 18 | 19 | Define a destination pose for Cozmo. If relative_to_robot is set to true, 20 | the given pose will assume the robot's pose as its origin. 21 | ''' 22 | 23 | import cozmo 24 | from cozmo.util import degrees, Pose 25 | 26 | 27 | def cozmo_program(robot: cozmo.robot.Robot): 28 | robot.go_to_pose(Pose(100, 100, 0, angle_z=degrees(45)), relative_to_robot=True).wait_for_completed() 29 | 30 | 31 | cozmo.run_program(cozmo_program) 32 | -------------------------------------------------------------------------------- /src/cozmo/assets/cozmo.mtl: -------------------------------------------------------------------------------- 1 | # rim around the screen 2 | newmtl ScreenOp_matSG 3 | illum 4 4 | Kd 0.00 0.00 0.00 0.2 5 | Ka 0.00 0.00 0.00 0.2 6 | Tf 1.00 1.00 1.00 7 | Ni 1.00 8 | Ks 0.08 0.08 0.08 0.2 9 | Ns 10 10 | 11 | # glass screen 12 | newmtl anisotropic1SG 13 | illum 4 14 | Kd 0.00 0.00 0.00 0.2 15 | Ka 0.00 0.00 0.00 0.2 16 | Tf 0.09 0.09 0.09 17 | Ni 1.00 18 | Ks 0.1 0.1 0.1 0.2 19 | Ns 10 20 | 21 | # head, arms+fork, wheels (but not treads) 22 | newmtl blinn2SG 23 | illum 4 24 | Kd 0.82 0.82 0.82 25 | Ka 0.00 0.00 0.00 26 | Tf 1.00 1.00 1.00 27 | Ni 1.00 28 | Ks 0.50 0.50 0.50 29 | Ns 10 30 | 31 | # Treads 32 | newmtl blinn3SG 33 | illum 4 34 | Kd 0.10 0.10 0.10 35 | Ka 0.00 0.00 0.00 36 | Tf 1.00 1.00 1.00 37 | Ni 1.00 38 | Ks 0.5 0.5 0.5 39 | Ns 10 40 | 41 | # Body and wheel-spacers 42 | newmtl blinn4SG 43 | illum 4 44 | Kd 0.70 0.70 0.70 45 | Ka 0.00 0.00 0.00 46 | Tf 1.00 1.00 1.00 47 | Ni 1.00 48 | Ks 0.50 0.50 0.50 49 | Ns 10 50 | 51 | # Eyelids 52 | newmtl lambert2SG 53 | illum 4 54 | Kd 0.00 0.00 0.00 55 | Ka 0.00 0.00 0.00 56 | Tf 1.00 1.00 1.00 57 | Ni 1.00 58 | Ks 0.50 0.50 0.50 59 | Ns 10 60 | 61 | # eyes 62 | newmtl shadingMap1SG 63 | illum 4 64 | Kd 0.00 1.00 1.00 65 | Ka 0.00 1.00 1.00 66 | Tf 1.00 1.00 1.00 67 | Ni 0.00 68 | -------------------------------------------------------------------------------- /examples/tutorials/01_basics/03_count.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # Copyright (c) 2016 Anki, Inc. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License in the file LICENSE.txt or at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | '''Count to 5 18 | 19 | Make Cozmo count from 1 to 5 20 | ''' 21 | 22 | import cozmo 23 | 24 | 25 | def cozmo_program(robot: cozmo.robot.Robot): 26 | # A "for loop" runs for each value i in the given range - in this example 27 | # starting from 0, while i is less than 5 (so 0,1,2,3,4). 28 | for i in range(5): 29 | # Add 1 to the number (so that we count from 1 to 5, not 0 to 4), 30 | # then convert the number to a string and make Cozmo say it. 31 | robot.say_text(str(i+1)).wait_for_completed() 32 | 33 | 34 | cozmo.run_program(cozmo_program) 35 | -------------------------------------------------------------------------------- /vagrant/Vagrantfile: -------------------------------------------------------------------------------- 1 | # -*- mode: ruby -*- 2 | # vi: set ft=ruby : 3 | 4 | # All Vagrant configuration is done below. The "2" in Vagrant.configure 5 | # configures the configuration version (we support older styles for 6 | # backwards compatibility). Please don't change it unless you know what 7 | # you're doing. 8 | Vagrant.configure(2) do |config| 9 | # The most common configuration options are documented and commented below. 10 | # For a complete reference, please see the online documentation at 11 | # https://docs.vagrantup.com. 12 | 13 | # Every Vagrant development environment requires a box. You can search for 14 | # boxes at https://atlas.hashicorp.com/search. 15 | config.vm.box = "bento/ubuntu-16.04" #<--16.04 LTS 16 | config.vm.provider "virtualbox" do |v| 17 | v.memory = 2028 18 | v.cpus = 2 19 | v.customize ["modifyvm", :id, "--usb", "on"] 20 | v.customize ["modifyvm", :id, "--usbehci", "on"] 21 | v.customize ["usbfilter", "add", "0", 22 | "--target", :id, 23 | "--name", "iOS", 24 | "--manufacturer", "Apple Inc.", 25 | "--product", "iPhone"] 26 | v.customize ["usbfilter", "add", "1", 27 | "--target", :id, 28 | "--name", "Android", 29 | "--manufacturer", "SAMSUNG", 30 | "--product", "SAMSUNG_Android"] 31 | v.gui = true 32 | end 33 | end 34 | -------------------------------------------------------------------------------- /examples/tutorials/01_basics/02_drive_and_turn.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # Copyright (c) 2016 Anki, Inc. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License in the file LICENSE.txt or at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | '''Drive And Turn 18 | 19 | Make Cozmo drive forwards and then turn 90 degrees to the left. 20 | ''' 21 | 22 | import cozmo 23 | from cozmo.util import degrees, distance_mm, speed_mmps 24 | 25 | 26 | def cozmo_program(robot: cozmo.robot.Robot): 27 | # Drive forwards for 150 millimeters at 50 millimeters-per-second. 28 | robot.drive_straight(distance_mm(150), speed_mmps(50)).wait_for_completed() 29 | 30 | # Turn 90 degrees to the left. 31 | # Note: To turn to the right, just use a negative number. 32 | robot.turn_in_place(degrees(90)).wait_for_completed() 33 | 34 | 35 | cozmo.run_program(cozmo_program) 36 | -------------------------------------------------------------------------------- /examples/tutorials/04_cubes_and_objects/13_pop_a_wheelie.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # Copyright (c) 2017 Anki, Inc. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License in the file LICENSE.txt or at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | '''Tell Cozmo to pop a wheelie on a cube that is placed in front of him. 18 | 19 | This example demonstrates Cozmo driving to a cube and pushing himself onto 20 | his back by pushing his lift against that cube. 21 | ''' 22 | 23 | import cozmo 24 | 25 | async def pop_a_wheelie(robot: cozmo.robot.Robot): 26 | print("Cozmo is waiting until he sees a cube") 27 | cube = await robot.world.wait_for_observed_light_cube() 28 | 29 | print("Cozmo found a cube, and will now attempt to pop a wheelie on it") 30 | 31 | action = robot.pop_a_wheelie(cube, num_retries=2) 32 | await action.wait_for_completed() 33 | 34 | 35 | cozmo.run_program(pop_a_wheelie) 36 | -------------------------------------------------------------------------------- /docs/source/index.rst: -------------------------------------------------------------------------------- 1 | .. Cozmo SDK documentation master file, created by 2 | sphinx-quickstart on Tue Jul 19 17:16:49 2016. 3 | You can adapt this file completely to your liking, but it should at least 4 | contain the root `toctree` directive. 5 | 6 | .. image:: images/cozmo-sdk-img.jpg 7 | 8 | | 9 | 10 | ========================= 11 | Welcome to the Cozmo SDK! 12 | ========================= 13 | 14 | .. toctree:: 15 | :maxdepth: 1 16 | :caption: Installation 17 | 18 | initial 19 | install-macos.rst 20 | install-windows.rst 21 | install-linux.rst 22 | adb.rst 23 | 24 | .. toctree:: 25 | :maxdepth: 2 26 | :caption: Downloads 27 | 28 | downloads.rst 29 | 30 | .. toctree:: 31 | :maxdepth: 2 32 | :caption: Get Started 33 | 34 | getstarted.rst 35 | 36 | .. toctree:: 37 | :maxdepth: 2 38 | :caption: SDK Versions 39 | 40 | sdk-versions.rst 41 | 42 | .. toctree:: 43 | :maxdepth: 2 44 | :caption: API Reference 45 | 46 | api 47 | 48 | ------------------ 49 | Indices and tables 50 | ------------------ 51 | 52 | * :ref:`genindex` 53 | * :ref:`modindex` 54 | * :ref:`search` 55 | 56 | ---- 57 | 58 | `Terms and Conditions `_ and `Privacy Policy `_ 59 | 60 | `Click here to return to the Anki Developer website. `_ 61 | -------------------------------------------------------------------------------- /vagrant/setup-vm.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | echo ">>> Updating apt-get" 4 | sudo apt-get -y -q update 5 | 6 | echo ">>> Installing Dependencies" 7 | sudo apt-get -y -q install default-jdk \ 8 | default-jre \ 9 | curl \ 10 | python3-pip \ 11 | expect \ 12 | python3-pil \ 13 | python3-pil.imagetk \ 14 | freeglut3 15 | pip3 install numpy \ 16 | pillow \ 17 | flask \ 18 | PyOpenGL 19 | sudo localectl set-locale LANG="en_US.UTF-8" 20 | 21 | echo ">>> Installing Android Command Line Tools" 22 | curl -o /tmp/android-sdk_r24.4.1-linux.tgz https://dl.google.com/android/android-sdk_r24.4.1-linux.tgz 23 | tar -xzf /tmp/android-sdk_r24.4.1-linux.tgz -C /home/vagrant 24 | sudo chown -R vagrant /home/vagrant/android-sdk-linux/ 25 | echo "ANDROID_HOME=~/android-sdk-linux" >> /home/vagrant/.bashrc 26 | echo "export JAVA_HOME=/usr/lib/jvm/java-8-oracle" >> /home/vagrant/.bashrc 27 | echo "PATH=\$PATH:~/android-sdk-linux/tools:~/android-sdk-linux/platform-tools" >> /home/vagrant/.bashrc 28 | 29 | echo ">>> Installing SDK Android 24" 30 | /home/vagrant/android-sdk-linux/tools/android update sdk -u --all --filter platform-tool 31 | 32 | echo ">>> Extracting Cozmo SDK" 33 | pushd /vagrant 34 | tar -xzf cozmo_sdk_examples.tar.gz 35 | popd 36 | pip3 install cozmo[camera] 37 | 38 | echo ">>> Turn Screensaver Lock OFF" 39 | gsettings set org.gnome.desktop.screensaver lock-enabled false 40 | gsettings set org.gnome.desktop.screensaver idle-activation-enabled false 41 | 42 | exec bash 43 | -------------------------------------------------------------------------------- /examples/tutorials/01_basics/04_drive_square.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # Copyright (c) 2016 Anki, Inc. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License in the file LICENSE.txt or at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | '''Make Cozmo drive in a square. 18 | 19 | This script combines the two previous examples (02_drive_and_turn.py and 20 | 03_count.py) to make Cozmo drive in a square by going forward and turning 21 | left 4 times in a row. 22 | ''' 23 | 24 | import cozmo 25 | from cozmo.util import degrees, distance_mm, speed_mmps 26 | 27 | 28 | def cozmo_program(robot: cozmo.robot.Robot): 29 | # Use a "for loop" to repeat the indented code 4 times 30 | # Note: the _ variable name can be used when you don't need the value 31 | for _ in range(4): 32 | robot.drive_straight(distance_mm(150), speed_mmps(50)).wait_for_completed() 33 | robot.turn_in_place(degrees(90)).wait_for_completed() 34 | 35 | 36 | cozmo.run_program(cozmo_program) 37 | -------------------------------------------------------------------------------- /examples/tutorials/04_cubes_and_objects/12_roll_cube.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # Copyright (c) 2017 Anki, Inc. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License in the file LICENSE.txt or at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | '''Tell Cozmo to roll a cube that is placed in front of him. 18 | 19 | This example demonstrates Cozmo driving to and rolling a cube. 20 | You must place a cube in front of Cozmo so that he can see it. 21 | The cube should be centered in front of him. 22 | ''' 23 | 24 | import cozmo 25 | from cozmo.util import degrees 26 | 27 | async def roll_a_cube(robot: cozmo.robot.Robot): 28 | await robot.set_head_angle(degrees(-5.0)).wait_for_completed() 29 | 30 | print("Cozmo is waiting until he sees a cube") 31 | cube = await robot.world.wait_for_observed_light_cube() 32 | 33 | print("Cozmo found a cube, and will now attempt to roll with it:") 34 | # Cozmo will approach the cube he has seen and roll it 35 | # check_for_object_on_top=True enforces that Cozmo will not roll cubes with anything on top 36 | action = robot.roll_cube(cube, check_for_object_on_top=True, num_retries=2) 37 | await action.wait_for_completed() 38 | print("result:", action.result) 39 | 40 | cozmo.run_program(roll_a_cube) 41 | -------------------------------------------------------------------------------- /examples/tutorials/01_basics/07_backpack_lights.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # Copyright (c) 2016 Anki, Inc. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License in the file LICENSE.txt or at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | '''Control Cozmo's Backpack lights 18 | 19 | This script shows how you can control Cozmo's backpack lights and set 20 | them to different colors. 21 | ''' 22 | 23 | import time 24 | 25 | import cozmo 26 | 27 | 28 | def cozmo_program(robot: cozmo.robot.Robot): 29 | # set all of Cozmo's backpack lights to red, and wait for 2 seconds 30 | robot.set_all_backpack_lights(cozmo.lights.red_light) 31 | time.sleep(2) 32 | # set all of Cozmo's backpack lights to green, and wait for 2 seconds 33 | robot.set_all_backpack_lights(cozmo.lights.green_light) 34 | time.sleep(2) 35 | # set all of Cozmo's backpack lights to blue, and wait for 2 seconds 36 | robot.set_all_backpack_lights(cozmo.lights.blue_light) 37 | time.sleep(2) 38 | # set just Cozmo's center backpack lights to white, and wait for 2 seconds 39 | robot.set_center_backpack_lights(cozmo.lights.white_light) 40 | time.sleep(2) 41 | # turn off Cozmo's backpack lights and wait for 2 seconds 42 | robot.set_all_backpack_lights(cozmo.lights.off_light) 43 | time.sleep(2) 44 | 45 | 46 | cozmo.run_program(cozmo_program) 47 | -------------------------------------------------------------------------------- /examples/tutorials/04_cubes_and_objects/02_create_wall.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # Copyright (c) 2016-2017 Anki, Inc. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License in the file LICENSE.txt or at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | '''Use custom objects to create a wall in front of Cozmo. 18 | 19 | This example demonstrates how you can create custom objects in the world, and 20 | automatically have Cozmo path around them as if they are real obstacles. 21 | 22 | It creates a wall in front of cozmo and tells him to drive around it. 23 | He will plan a path to drive 200mm in front of himself after these objects are created. 24 | 25 | The `use_3d_viewer=True` argument causes the 3D visualizer to open in a new 26 | window - this shows where Cozmo believes this imaginary object is. 27 | ''' 28 | 29 | import cozmo 30 | from cozmo.util import degrees, Pose 31 | 32 | 33 | def cozmo_program(robot: cozmo.robot.Robot): 34 | fixed_object = robot.world.create_custom_fixed_object(Pose(100, 0, 0, angle_z=degrees(0)), 35 | 10, 100, 100, relative_to_robot=True) 36 | if fixed_object: 37 | print("fixed_object created successfully") 38 | 39 | robot.go_to_pose(Pose(200, 0, 0, angle_z=degrees(0)), relative_to_robot=True).wait_for_completed() 40 | 41 | 42 | cozmo.run_program(cozmo_program, use_3d_viewer=True) 43 | -------------------------------------------------------------------------------- /examples/tutorials/04_cubes_and_objects/11_dock_with_cube.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # Copyright (c) 2017 Anki, Inc. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License in the file LICENSE.txt or at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | '''Tell Cozmo to drive up to a cube that he sees placed in front of him. 18 | 19 | This example demonstrates Cozmo driving to and docking with a cube, without 20 | picking it up. You must place a cube in front of Cozmo so that he can see it. 21 | The cube should be centered in front of him. 22 | ''' 23 | 24 | import cozmo 25 | from cozmo.util import degrees 26 | 27 | async def dock_with_cube(robot: cozmo.robot.Robot): 28 | await robot.set_head_angle(degrees(-5.0)).wait_for_completed() 29 | 30 | print("Cozmo is waiting until he sees a cube.") 31 | cube = await robot.world.wait_for_observed_light_cube() 32 | 33 | print("Cozmo found a cube, and will now attempt to dock with it:") 34 | # Cozmo will approach the cube he has seen 35 | # using a 180 approach angle will cause him to drive past the cube and approach from the opposite side 36 | # num_retries allows us to specify how many times Cozmo will retry the action in the event of it failing 37 | action = robot.dock_with_cube(cube, approach_angle=cozmo.util.degrees(180), num_retries=2) 38 | await action.wait_for_completed() 39 | print("result:", action.result) 40 | 41 | cozmo.run_program(dock_with_cube) 42 | -------------------------------------------------------------------------------- /src/cozmo/robot_alignment.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2017 Anki, Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License in the file LICENSE.txt or at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | ''' 16 | RobotAlignment related classes, functions, events and values. 17 | ''' 18 | 19 | # __all__ should order by constants, event classes, other classes, functions. 20 | __all__ = ['RobotAlignmentTypes'] 21 | 22 | import collections 23 | 24 | from ._clad import _clad_to_engine_cozmo, CladEnumWrapper 25 | 26 | _RobotAlignmentType = collections.namedtuple('_RobotAlignmentType', ['name', 'id']) 27 | 28 | 29 | class RobotAlignmentTypes(CladEnumWrapper): 30 | '''Defines all robot alignment types. 31 | ''' 32 | _clad_enum = _clad_to_engine_cozmo.AlignmentType 33 | _entry_type = _RobotAlignmentType 34 | 35 | #: Align the tips of the lift fingers with the target object 36 | LiftFinger = _entry_type("LiftFinger", _clad_enum.LIFT_FINGER) 37 | 38 | #: Align the flat part of the lift with the object 39 | #: (Useful for getting the fingers in the cube's grooves) 40 | LiftPlate = _entry_type("LiftPlate", _clad_enum.LIFT_PLATE) 41 | 42 | #: Align the front of cozmo's body 43 | #: (Useful for when the lift is up) 44 | Body = _entry_type("Body", _clad_enum.BODY) 45 | 46 | #: For use with distanceFromMarker parameter 47 | Custom = _entry_type("Custom", _clad_enum.CUSTOM) 48 | 49 | RobotAlignmentTypes._init_class() 50 | -------------------------------------------------------------------------------- /examples/tutorials/04_cubes_and_objects/04_stack_or_roll.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # Copyright (c) 2016 Anki, Inc. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License in the file LICENSE.txt or at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | '''Make Cozmo perform different actions based on the number of Cubes he finds. 18 | 19 | This script shows off simple decision making. 20 | It tells Cozmo to look around, and then wait until he sees a certain amount of objects. 21 | Based on how many object he sees before he times out, he will do different actions. 22 | 0-> be angry 23 | 1-> roll block (the block must not be face up) 24 | 2-> stack blocks (the blocks must all be face up) 25 | ''' 26 | 27 | import cozmo 28 | 29 | 30 | def cozmo_program(robot: cozmo.robot.Robot): 31 | lookaround = robot.start_behavior(cozmo.behavior.BehaviorTypes.LookAroundInPlace) 32 | 33 | cubes = robot.world.wait_until_observe_num_objects(num=2, object_type=cozmo.objects.LightCube, timeout=10) 34 | 35 | print("Found %s cubes" % len(cubes)) 36 | 37 | lookaround.stop() 38 | 39 | if len(cubes) == 0: 40 | robot.play_anim_trigger(cozmo.anim.Triggers.MajorFail).wait_for_completed() 41 | elif len(cubes) == 1: 42 | robot.run_timed_behavior(cozmo.behavior.BehaviorTypes.RollBlock, active_time=60) 43 | else: 44 | robot.run_timed_behavior(cozmo.behavior.BehaviorTypes.StackBlocks, active_time=60) 45 | 46 | 47 | cozmo.run_program(cozmo_program) 48 | -------------------------------------------------------------------------------- /examples/tutorials/03_vision/01_light_when_face.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # Copyright (c) 2016 Anki, Inc. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License in the file LICENSE.txt or at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | '''Wait for Cozmo to see a face, and then turn on his backpack light. 18 | 19 | This is a script to show off faces, and how they are easy to use. 20 | It waits for a face, and then will light up his backpack when that face is visible. 21 | ''' 22 | 23 | import asyncio 24 | import time 25 | 26 | import cozmo 27 | 28 | 29 | def light_when_face(robot: cozmo.robot.Robot): 30 | '''The core of the light_when_face program''' 31 | 32 | # Move lift down and tilt the head up 33 | robot.move_lift(-3) 34 | robot.set_head_angle(cozmo.robot.MAX_HEAD_ANGLE).wait_for_completed() 35 | 36 | face = None 37 | 38 | print("Press CTRL-C to quit") 39 | while True: 40 | if face and face.is_visible: 41 | robot.set_all_backpack_lights(cozmo.lights.blue_light) 42 | else: 43 | robot.set_backpack_lights_off() 44 | 45 | # Wait until we we can see another face 46 | try: 47 | face = robot.world.wait_for_observed_face(timeout=30) 48 | except asyncio.TimeoutError: 49 | print("Didn't find a face.") 50 | return 51 | 52 | time.sleep(.1) 53 | 54 | 55 | cozmo.run_program(light_when_face, use_viewer=True, force_viewer_on_top=True) 56 | -------------------------------------------------------------------------------- /examples/tutorials/01_basics/06_sing_scales.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # Copyright (c) 2016 Anki, Inc. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License in the file LICENSE.txt or at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | '''Make Cozmo sing Do Re Mi. 18 | 19 | Make Cozmo "sing" the scales. 20 | This is a small extension of the 03_count.py example. 21 | ''' 22 | 23 | import cozmo 24 | from cozmo.util import degrees 25 | 26 | 27 | def cozmo_program(robot: cozmo.robot.Robot): 28 | # scales is a list of the words for Cozmo to sing 29 | scales = ["Doe", "Ray", "Mi", "Fa", "So", "La", "Ti", "Doe"] 30 | 31 | # Find voice_pitch_delta value that will range the pitch from -1 to 1 over all of the scales 32 | voice_pitch = -1.0 33 | voice_pitch_delta = 2.0 / (len(scales) - 1) 34 | 35 | # Move head and lift down to the bottom, and wait until that's achieved 36 | robot.move_head(-5) # start moving head down so it mostly happens in parallel with lift 37 | robot.set_lift_height(0.0).wait_for_completed() 38 | robot.set_head_angle(degrees(-25.0)).wait_for_completed() 39 | 40 | # Start slowly raising lift and head 41 | robot.move_lift(0.15) 42 | robot.move_head(0.15) 43 | 44 | # "Sing" each note of the scale at increasingly high pitch 45 | for note in scales: 46 | robot.say_text(note, voice_pitch=voice_pitch, duration_scalar=0.3).wait_for_completed() 47 | voice_pitch += voice_pitch_delta 48 | 49 | 50 | cozmo.run_program(cozmo_program) 51 | -------------------------------------------------------------------------------- /examples/tutorials/04_cubes_and_objects/06_pickup_furthest.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # Copyright (c) 2016 Anki, Inc. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License in the file LICENSE.txt or at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | '''Make Cozmo pick up the furthest Cube. 18 | 19 | This script shows simple math with object's poses. 20 | 21 | The robot attempts to find three Cubes within his view, which 22 | you can see in the camera window that opens when the script 23 | is run. Each Cube will show with an outline and cube number 24 | if the Cube is in the frame. 25 | 26 | The robot waits until 3 Cubes are found, and then attempts to 27 | pick up the furthest one. It calculates this based on the 28 | reported poses of the Cubes. 29 | ''' 30 | 31 | import cozmo 32 | 33 | 34 | def cozmo_program(robot: cozmo.robot.Robot): 35 | lookaround = robot.start_behavior(cozmo.behavior.BehaviorTypes.LookAroundInPlace) 36 | cubes = robot.world.wait_until_observe_num_objects(num=3, object_type=cozmo.objects.LightCube, timeout=60) 37 | lookaround.stop() 38 | 39 | max_dst, targ = 0, None 40 | for cube in cubes: 41 | translation = robot.pose - cube.pose 42 | dst = translation.position.x ** 2 + translation.position.y ** 2 43 | if dst > max_dst: 44 | max_dst, targ = dst, cube 45 | 46 | if len(cubes) < 3: 47 | print("Error: need 3 Cubes but only found", len(cubes), "Cube(s)") 48 | else: 49 | robot.pickup_object(targ, num_retries=3).wait_for_completed() 50 | 51 | 52 | cozmo.run_program(cozmo_program, use_viewer=True) 53 | -------------------------------------------------------------------------------- /examples/multi_robot/multi_robot_independent.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # Copyright (c) 2016 Anki, Inc. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License in the file LICENSE.txt or at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | '''An example of running independent concurrent routines on multiple Cozmos. 18 | 19 | Each robot requires its own device to control it. 20 | ''' 21 | 22 | import asyncio 23 | import sys 24 | 25 | import cozmo 26 | from cozmo.util import degrees 27 | 28 | 29 | async def turn_left(sdk_conn): 30 | robot = await sdk_conn.wait_for_robot() 31 | cozmo.logger.info("Turning robot 1") 32 | await robot.turn_in_place(degrees(90)).wait_for_completed() 33 | 34 | async def turn_right(sdk_conn): 35 | robot = await sdk_conn.wait_for_robot() 36 | cozmo.logger.info("Turning robot 2") 37 | await robot.turn_in_place(degrees(-90)).wait_for_completed() 38 | 39 | 40 | if __name__ == '__main__': 41 | cozmo.setup_basic_logging() 42 | loop = asyncio.get_event_loop() 43 | 44 | # Connect to both robots 45 | try: 46 | conn1 = cozmo.connect_on_loop(loop) 47 | conn2 = cozmo.connect_on_loop(loop) 48 | except cozmo.ConnectionError as e: 49 | sys.exit("A connection error occurred: %s" % e) 50 | 51 | # Run two independent coroutines concurrently, one on each connection 52 | task1 = asyncio.ensure_future(turn_left(conn1), loop=loop) 53 | task2 = asyncio.ensure_future(turn_right(conn2), loop=loop) 54 | 55 | # wait for both coroutines to complete before exiting the program 56 | loop.run_until_complete(asyncio.gather(task1, task2)) 57 | -------------------------------------------------------------------------------- /examples/tutorials/01_basics/09_cube_lights.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # Copyright (c) 2017 Anki, Inc. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License in the file LICENSE.txt or at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | '''Control Cozmo's Cube lights 18 | 19 | This script shows how you can control Cozmo's cube lights and set 20 | them to different colors - to red, green and blue in this case. 21 | ''' 22 | 23 | import time 24 | 25 | import cozmo 26 | from cozmo.objects import LightCube1Id, LightCube2Id, LightCube3Id 27 | 28 | 29 | def cozmo_program(robot: cozmo.robot.Robot): 30 | cube1 = robot.world.get_light_cube(LightCube1Id) # looks like a paperclip 31 | cube2 = robot.world.get_light_cube(LightCube2Id) # looks like a lamp / heart 32 | cube3 = robot.world.get_light_cube(LightCube3Id) # looks like the letters 'ab' over 'T' 33 | 34 | if cube1 is not None: 35 | cube1.set_lights(cozmo.lights.red_light) 36 | else: 37 | cozmo.logger.warning("Cozmo is not connected to a LightCube1Id cube - check the battery.") 38 | 39 | if cube2 is not None: 40 | cube2.set_lights(cozmo.lights.green_light) 41 | else: 42 | cozmo.logger.warning("Cozmo is not connected to a LightCube2Id cube - check the battery.") 43 | 44 | if cube3 is not None: 45 | cube3.set_lights(cozmo.lights.blue_light) 46 | else: 47 | cozmo.logger.warning("Cozmo is not connected to a LightCube3Id cube - check the battery.") 48 | 49 | # Keep the lights on for 10 seconds until the program exits 50 | time.sleep(10) 51 | 52 | 53 | cozmo.run_program(cozmo_program) 54 | -------------------------------------------------------------------------------- /examples/tutorials/01_basics/12_random_animation.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # Copyright (c) 2018 Anki, Inc. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License in the file LICENSE.txt or at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | '''Play some animations on Cozmo 18 | 19 | Plays animations by fetching lists of supported triggers from the robot, 20 | and playing 2 selections of them: one random selection and one by filtering 21 | for a name. 22 | ''' 23 | 24 | import cozmo 25 | import random 26 | 27 | def cozmo_program(robot: cozmo.robot.Robot): 28 | # grab a list of animation triggers 29 | all_animation_triggers = robot.anim_triggers 30 | 31 | # randomly shuffle the animations 32 | random.shuffle(all_animation_triggers) 33 | 34 | # select the first three animations from the shuffled list 35 | triggers = 3 36 | chosen_triggers = all_animation_triggers[:triggers] 37 | print('Playing {} random animations:'.format(triggers)) 38 | 39 | # play the three random animations one after the other, waiting for each to complete 40 | for trigger in chosen_triggers: 41 | print('Playing {}'.format(trigger.name)) 42 | robot.play_anim_trigger(trigger).wait_for_completed() 43 | 44 | 45 | # grab animation triggers that have 'WinGame' in their name 46 | chosen_triggers = [trigger for trigger in robot.anim_triggers if 'WinGame' in trigger.name] 47 | 48 | # play the three random animations one after the other, waiting for each to complete 49 | for trigger in chosen_triggers: 50 | print('Playing {}'.format(trigger.name)) 51 | robot.play_anim_trigger(trigger).wait_for_completed() 52 | 53 | cozmo.run_program(cozmo_program) 54 | -------------------------------------------------------------------------------- /examples/tutorials/03_vision/02_face_follower.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # Copyright (c) 2016 Anki, Inc. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License in the file LICENSE.txt or at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | '''Make Cozmo turn toward a face. 18 | 19 | This script shows off the turn_towards_face action. It will wait for a face 20 | and then constantly turn towards it to keep it in frame. 21 | ''' 22 | 23 | import asyncio 24 | import time 25 | 26 | import cozmo 27 | 28 | 29 | def follow_faces(robot: cozmo.robot.Robot): 30 | '''The core of the follow_faces program''' 31 | 32 | # Move lift down and tilt the head up 33 | robot.move_lift(-3) 34 | robot.set_head_angle(cozmo.robot.MAX_HEAD_ANGLE).wait_for_completed() 35 | 36 | face_to_follow = None 37 | 38 | print("Press CTRL-C to quit") 39 | while True: 40 | turn_action = None 41 | if face_to_follow: 42 | # start turning towards the face 43 | turn_action = robot.turn_towards_face(face_to_follow) 44 | 45 | if not (face_to_follow and face_to_follow.is_visible): 46 | # find a visible face, timeout if nothing found after a short while 47 | try: 48 | face_to_follow = robot.world.wait_for_observed_face(timeout=30) 49 | except asyncio.TimeoutError: 50 | print("Didn't find a face - exiting!") 51 | return 52 | 53 | if turn_action: 54 | # Complete the turn action if one was in progress 55 | turn_action.wait_for_completed() 56 | 57 | time.sleep(.1) 58 | 59 | 60 | cozmo.run_program(follow_faces, use_viewer=True, force_viewer_on_top=True) 61 | -------------------------------------------------------------------------------- /examples/tutorials/01_basics/08_animation.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # Copyright (c) 2016 Anki, Inc. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License in the file LICENSE.txt or at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | '''Play some animations on Cozmo 18 | 19 | Play an animation using a trigger, and then another animation by name. 20 | ''' 21 | 22 | import cozmo 23 | 24 | 25 | def cozmo_program(robot: cozmo.robot.Robot): 26 | # Play an animation via a Trigger - see: 27 | # http://cozmosdk.anki.com/docs/generated/cozmo.anim.html#cozmo.anim.Triggers 28 | # for a list of available triggers. 29 | # A trigger can pick from several appropriate animations for variety. 30 | print("Playing Animation Trigger 1:") 31 | robot.play_anim_trigger(cozmo.anim.Triggers.CubePounceLoseSession).wait_for_completed() 32 | 33 | # Play the same trigger, but this time ignore the track that plays on the 34 | # body (i.e. don't move the wheels). See the play_anim_trigger documentation 35 | # for other available settings. 36 | print("Playing Animation Trigger 2: (Ignoring the body track)") 37 | robot.play_anim_trigger(cozmo.anim.Triggers.CubePounceLoseSession, ignore_body_track=True).wait_for_completed() 38 | 39 | # Play an animation via its Name. 40 | # Warning: Future versions of the app might change these, so for future-proofing 41 | # we recommend using play_anim_trigger above instead. 42 | # See the remote_control_cozmo.py example in apps for an easy way to see 43 | # the available animations. 44 | print("Playing Animation 3:") 45 | robot.play_anim(name="anim_poked_giggle").wait_for_completed() 46 | 47 | 48 | cozmo.run_program(cozmo_program) 49 | -------------------------------------------------------------------------------- /docs/source/initial.rst: -------------------------------------------------------------------------------- 1 | .. _initial: 2 | 3 | ############# 4 | Initial Setup 5 | ############# 6 | 7 | To use the Cozmo SDK, the Cozmo mobile app must be installed on your mobile device and that device must be tethered to a computer via USB cable. 8 | 9 | ------------- 10 | Prerequisites 11 | ------------- 12 | 13 | * Python 3.5.1 or later 14 | * WiFi connection 15 | * An iOS or Android mobile device with the Cozmo app installed, connected to the computer via USB cable 16 | 17 | -------------------- 18 | SDK Example Programs 19 | -------------------- 20 | 21 | Anki provides example programs for novice and advanced users to run with the SDK. Download the SDK example programs here: 22 | 23 | * :verlink:`macOS/Linux SDK Examples ` 24 | 25 | * :verlink:`Windows SDK Examples ` 26 | 27 | Once downloaded, extract the packaged files to a new directory. 28 | 29 | ------------ 30 | Installation 31 | ------------ 32 | 33 | To install the SDK on your system, select the instructions for your computer's operating system. 34 | 35 | * :ref:`install-macos` 36 | * :ref:`install-windows` 37 | * :ref:`install-linux` 38 | 39 | .. 40 | 41 | .. _trouble: 42 | 43 | --------------- 44 | Troubleshooting 45 | --------------- 46 | 47 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 48 | Failure to Install Python Package 49 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 50 | 51 | If your attempt to install Python packages such as NumPy fails, please upgrade your pip install as follows: 52 | 53 | On macOS and Linux:: 54 | 55 | pip3 install -U pip 56 | 57 | On Windows:: 58 | 59 | py -3 -m pip install -U pip 60 | 61 | Once the pip command is upgraded, retry your Python package installation. 62 | 63 | ^^^^^^^^^^^^^^^^ 64 | Cozmo SDK Forums 65 | ^^^^^^^^^^^^^^^^ 66 | 67 | Please visit the `Cozmo SDK Forums `_ to ask questions, find solutions and for general discussion. 68 | 69 | ---- 70 | 71 | `Terms and Conditions `_ and `Privacy Policy `_ 72 | 73 | `Click here to return to the Anki Developer website. `_ 74 | -------------------------------------------------------------------------------- /examples/tutorials/01_basics/05_motors.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # Copyright (c) 2016 Anki, Inc. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License in the file LICENSE.txt or at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | '''Drive Cozmo's wheels, lift and head motors directly 18 | 19 | This is an example of how you can also have low-level control of Cozmo's motors 20 | (wheels, lift and head) for fine-grained control and ease of controlling 21 | multiple things at once. 22 | ''' 23 | 24 | import time 25 | 26 | import cozmo 27 | 28 | 29 | def cozmo_program(robot: cozmo.robot.Robot): 30 | # Tell the head motor to start lowering the head (at 5 radians per second) 31 | robot.move_head(-5) 32 | # Tell the lift motor to start lowering the lift (at 5 radians per second) 33 | robot.move_lift(-5) 34 | # Tell Cozmo to drive the left wheel at 25 mmps (millimeters per second), 35 | # and the right wheel at 50 mmps (so Cozmo will drive Forwards while also 36 | # turning to the left 37 | robot.drive_wheels(25, 50) 38 | 39 | # wait for 3 seconds (the head, lift and wheels will move while we wait) 40 | time.sleep(3) 41 | 42 | # Tell the head motor to start raising the head (at 5 radians per second) 43 | robot.move_head(5) 44 | # Tell the lift motor to start raising the lift (at 5 radians per second) 45 | robot.move_lift(5) 46 | # Tell Cozmo to drive the left wheel at 50 mmps (millimeters per second), 47 | # and the right wheel at -50 mmps (so Cozmo will turn in-place to the right) 48 | robot.drive_wheels(50, -50) 49 | 50 | # wait for 3 seconds (the head, lift and wheels will move while we wait) 51 | time.sleep(3) 52 | 53 | 54 | cozmo.run_program(cozmo_program) 55 | -------------------------------------------------------------------------------- /examples/apps/cli.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # Copyright (c) 2017 Anki, Inc. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License in the file LICENSE.txt or at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | '''Command Line Interface for Cozmo 18 | 19 | This is an example of integrating Cozmo with an ipython-based command line interface. 20 | ''' 21 | 22 | import sys 23 | 24 | try: 25 | from IPython.terminal.embed import InteractiveShellEmbed 26 | from IPython.terminal.prompts import Prompts, Token 27 | except ImportError: 28 | sys.exit('Cannot import from ipython: Do `pip3 install ipython` to install') 29 | 30 | import cozmo 31 | 32 | usage = ('This is an IPython interactive shell for Cozmo.\n' 33 | 'All commands are executed within cozmo\'s running program loop.\n' 34 | 'Use the [tab] key to auto-complete commands, and see all available methods.\n' 35 | 'All IPython commands work as usual. See below for some useful syntax:\n' 36 | ' ? -> Introduction and overview of IPython\'s features.\n' 37 | ' object? -> Details about \'object\'.\n' 38 | ' object?? -> More detailed, verbose information about \'object\'.') 39 | 40 | # Creating IPython's history database on the main thread 41 | ipyshell = InteractiveShellEmbed(banner1='\nWelcome to the Cozmo Shell', 42 | exit_msg='Goodbye\n') 43 | 44 | def cozmo_program(robot: cozmo.robot.Robot): 45 | '''Invoke the ipython shell while connected to cozmo''' 46 | default_log_level = cozmo.logger.level 47 | cozmo.logger.setLevel('WARN') 48 | ipyshell(usage) 49 | cozmo.logger.setLevel(default_log_level) 50 | 51 | cozmo.run_program(cozmo_program, use_3d_viewer=True, use_viewer=True) 52 | -------------------------------------------------------------------------------- /examples/tutorials/04_cubes_and_objects/03_go_to_object_test.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # Copyright (c) 2016 Anki, Inc. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License in the file LICENSE.txt or at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | '''Tell Cozmo to find a cube, and then drive up to it 18 | 19 | This is a test / example usage of the robot.go_to_object call which creates a 20 | GoToObject action, that can be used to drive within a given distance of an 21 | object (e.g. a LightCube). 22 | ''' 23 | 24 | import asyncio 25 | 26 | import cozmo 27 | from cozmo.util import degrees, distance_mm 28 | 29 | 30 | def go_to_object_test(robot: cozmo.robot.Robot): 31 | '''The core of the go to object test program''' 32 | 33 | # Move lift down and tilt the head up 34 | robot.move_lift(-3) 35 | robot.set_head_angle(degrees(0)).wait_for_completed() 36 | 37 | # look around and try to find a cube 38 | look_around = robot.start_behavior(cozmo.behavior.BehaviorTypes.LookAroundInPlace) 39 | 40 | cube = None 41 | 42 | try: 43 | cube = robot.world.wait_for_observed_light_cube(timeout=30) 44 | print("Found cube: %s" % cube) 45 | except asyncio.TimeoutError: 46 | print("Didn't find a cube") 47 | finally: 48 | # whether we find it or not, we want to stop the behavior 49 | look_around.stop() 50 | 51 | if cube: 52 | # Drive to 70mm away from the cube (much closer and Cozmo 53 | # will likely hit the cube) and then stop. 54 | action = robot.go_to_object(cube, distance_mm(70.0)) 55 | action.wait_for_completed() 56 | print("Completed action: result = %s" % action) 57 | print("Done.") 58 | 59 | 60 | cozmo.run_program(go_to_object_test) 61 | -------------------------------------------------------------------------------- /examples/tools/cubes/log_cube_battery_levels.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # Copyright (c) 2017 Anki, Inc. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License in the file LICENSE.txt or at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | '''Log the battery level of all connected cubes. 18 | 19 | This script can be used to verify which cubes are connected, and the current 20 | battery levels of each cube. This script can take several seconds to get the 21 | battery levels as they're only sent intermittently. 22 | ''' 23 | 24 | import asyncio 25 | 26 | import cozmo 27 | from cozmo.objects import LightCube1Id, LightCube2Id, LightCube3Id 28 | 29 | 30 | async def log_cube_info(robot: cozmo.robot.Robot, cube_id): 31 | cube = robot.world.get_light_cube(cube_id) 32 | if cube is not None: 33 | # Wait for up to few seconds for the cube to have received battery level info 34 | for i in range(30): 35 | if cube.battery_voltage is None: 36 | if i == 0: 37 | cozmo.logger.info("Cube %s waiting for battery info...", cube_id) 38 | await asyncio.sleep(0.5) 39 | else: 40 | break 41 | cozmo.logger.info("Cube %s battery = %s", cube_id, cube.battery_str) 42 | else: 43 | cozmo.logger.warning("Cube %s is not connected - check the battery.", cube_id) 44 | 45 | 46 | async def cozmo_program(robot: cozmo.robot.Robot): 47 | await log_cube_info(robot, LightCube1Id) # looks like a paperclip 48 | await log_cube_info(robot, LightCube2Id) # looks like a lamp / heart 49 | await log_cube_info(robot, LightCube3Id) # looks like the letters 'ab' over 'T' 50 | 51 | 52 | cozmo.robot.Robot.drive_off_charger_on_connect = False 53 | cozmo.run_program(cozmo_program) 54 | -------------------------------------------------------------------------------- /examples/tools/cubes/auto_cube_disconnect.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # Copyright (c) 2017 Anki, Inc. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License in the file LICENSE.txt or at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | '''Set whether Cozmo should automatically disconnect from cubes after each SDK program. 18 | 19 | This script can be used to turn auto cube disconnection on or off (using command 20 | line arguments -e or -d). Automatic disconnection can be used to help conserve 21 | cube battery life between SDK program runs. You can use `connect_cubes.py` later 22 | to re-connect to the cubes. 23 | ''' 24 | 25 | import argparse 26 | 27 | import cozmo 28 | 29 | 30 | async def cozmo_program(robot: cozmo.robot.Robot): 31 | parser = argparse.ArgumentParser() 32 | parser.add_argument('-e', '--enable', 33 | dest='enable_auto_disconnect', 34 | default=False, 35 | action='store_const', 36 | const=True, 37 | help='Enable auto cube disconnection') 38 | parser.add_argument('-d', '--disable', 39 | dest='disable_auto_disconnect', 40 | default=False, 41 | action='store_const', 42 | const=True, 43 | help='Disable auto cube disconnection') 44 | options = parser.parse_args() 45 | 46 | if options.enable_auto_disconnect: 47 | robot.world.auto_disconnect_from_cubes_at_end(True) 48 | elif options.disable_auto_disconnect: 49 | robot.world.auto_disconnect_from_cubes_at_end(False) 50 | else: 51 | cozmo.logger.error("Incorrect options provided, see:") 52 | parser.print_help() 53 | 54 | 55 | cozmo.robot.Robot.drive_off_charger_on_connect = False 56 | cozmo.run_program(cozmo_program) 57 | -------------------------------------------------------------------------------- /examples/multi_robot/multi_robot_unified.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # Copyright (c) 2016 Anki, Inc. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License in the file LICENSE.txt or at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | '''An example of controlling two robots from within the same routine. 18 | 19 | Each robot requires its own device to control it. 20 | ''' 21 | 22 | import asyncio 23 | import sys 24 | 25 | import cozmo 26 | from cozmo.util import degrees 27 | 28 | 29 | async def run(sdk_conn1, sdk_conn2): 30 | robot1 = await sdk_conn1.wait_for_robot() 31 | robot2 = await sdk_conn2.wait_for_robot() 32 | 33 | # First have one turn left and one turn right, one after the other 34 | cozmo.logger.info("Turning robot 1") 35 | await robot1.turn_in_place(degrees(90)).wait_for_completed() 36 | cozmo.logger.info("Turning robot 2") 37 | await robot2.turn_in_place(degrees(-90)).wait_for_completed() 38 | 39 | # Then have them both turn back to the original position at the same time 40 | cozmo.logger.info("Turning both robots") 41 | turn1 = robot1.turn_in_place(degrees(-90)) 42 | turn2 = robot2.turn_in_place(degrees(90)) 43 | await turn1.wait_for_completed() 44 | await turn2.wait_for_completed() 45 | 46 | 47 | if __name__ == '__main__': 48 | cozmo.setup_basic_logging() 49 | loop = asyncio.get_event_loop() 50 | 51 | # Connect to both robots 52 | # NOTE: to connect to a specific device with a specific serial number, 53 | # create a connector (eg. `cozmo.IOSConnector(serial='abc')) and pass it 54 | # explicitly to `connect` or `connect_on_loop` 55 | try: 56 | conn1 = cozmo.connect_on_loop(loop) 57 | conn2 = cozmo.connect_on_loop(loop) 58 | except cozmo.ConnectionError as e: 59 | sys.exit("A connection error occurred: %s" % e) 60 | 61 | # Run a coroutine controlling both connections 62 | loop.run_until_complete(run(conn1, conn2)) 63 | -------------------------------------------------------------------------------- /examples/tutorials/04_cubes_and_objects/07_lookaround.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # Copyright (c) 2016 Anki, Inc. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License in the file LICENSE.txt or at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | '''Make Cozmo look around for a cube. 18 | 19 | Cozmo looks around, reacts, and picks up and puts down a cube if found. 20 | ''' 21 | 22 | import asyncio 23 | 24 | import cozmo 25 | from cozmo.util import degrees 26 | 27 | 28 | def cozmo_program(robot: cozmo.robot.Robot): 29 | look_around = robot.start_behavior(cozmo.behavior.BehaviorTypes.LookAroundInPlace) 30 | 31 | # try to find a block 32 | cube = None 33 | 34 | try: 35 | cube = robot.world.wait_for_observed_light_cube(timeout=30) 36 | print("Found cube", cube) 37 | 38 | except asyncio.TimeoutError: 39 | print("Didn't find a cube :-(") 40 | 41 | finally: 42 | # whether we find it or not, we want to stop the behavior 43 | look_around.stop() 44 | 45 | if cube is None: 46 | robot.play_anim_trigger(cozmo.anim.Triggers.MajorFail) 47 | return 48 | 49 | print("Yay, found cube") 50 | 51 | cube.set_lights(cozmo.lights.green_light.flash()) 52 | 53 | anim = robot.play_anim_trigger(cozmo.anim.Triggers.BlockReact) 54 | anim.wait_for_completed() 55 | 56 | 57 | action = robot.pickup_object(cube) 58 | print("got action", action) 59 | result = action.wait_for_completed(timeout=30) 60 | print("got action result", result) 61 | 62 | robot.turn_in_place(degrees(90)).wait_for_completed() 63 | 64 | action = robot.place_object_on_ground_here(cube) 65 | print("got action", action) 66 | result = action.wait_for_completed(timeout=30) 67 | print("got action result", result) 68 | 69 | anim = robot.play_anim_trigger(cozmo.anim.Triggers.MajorWin) 70 | cube.set_light_corners(None, None, None, None) 71 | anim.wait_for_completed() 72 | 73 | 74 | cozmo.run_program(cozmo_program) 75 | -------------------------------------------------------------------------------- /examples/tutorials/04_cubes_and_objects/05_cube_stack.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # Copyright (c) 2016-2017 Anki, Inc. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License in the file LICENSE.txt or at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | '''Make Cozmo stack Cubes. 18 | 19 | This script is meant to show off how easy it is to do high level robot actions. 20 | Cozmo will wait until he sees two Cubes, and then will pick up one and place it on the other. 21 | He will pick up the first one he sees, and place it on the second one. 22 | ''' 23 | 24 | import cozmo 25 | 26 | 27 | def cozmo_program(robot: cozmo.robot.Robot): 28 | # Attempt to stack 2 cubes 29 | 30 | # Lookaround until Cozmo knows where at least 2 cubes are: 31 | lookaround = robot.start_behavior(cozmo.behavior.BehaviorTypes.LookAroundInPlace) 32 | cubes = robot.world.wait_until_observe_num_objects(num=2, object_type=cozmo.objects.LightCube, timeout=60) 33 | lookaround.stop() 34 | 35 | if len(cubes) < 2: 36 | print("Error: need 2 Cubes but only found", len(cubes), "Cube(s)") 37 | else: 38 | # Try and pickup the 1st cube 39 | current_action = robot.pickup_object(cubes[0], num_retries=3) 40 | current_action.wait_for_completed() 41 | if current_action.has_failed: 42 | code, reason = current_action.failure_reason 43 | result = current_action.result 44 | print("Pickup Cube failed: code=%s reason='%s' result=%s" % (code, reason, result)) 45 | return 46 | 47 | # Now try to place that cube on the 2nd one 48 | current_action = robot.place_on_object(cubes[1], num_retries=3) 49 | current_action.wait_for_completed() 50 | if current_action.has_failed: 51 | code, reason = current_action.failure_reason 52 | result = current_action.result 53 | print("Place On Cube failed: code=%s reason='%s' result=%s" % (code, reason, result)) 54 | return 55 | 56 | print("Cozmo successfully stacked 2 blocks!") 57 | 58 | cozmo.run_program(cozmo_program) 59 | -------------------------------------------------------------------------------- /examples/if_this_then_that/common/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2016 Anki, Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License in the file LICENSE.txt or at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | '''If This Then That helper common code. 16 | 17 | This module include a subclass of Robot to add some helper methods that are 18 | useful to the IFTTT examples. 19 | 20 | This class includes the following: 21 | 1) get_in_position moves Cozmo's lift down and face up if necessary. 22 | 2) display_image_on_face displays the requested image file on his face after 23 | the If This Then That trigger has been received. 24 | ''' 25 | 26 | import sys 27 | 28 | import cozmo 29 | 30 | 31 | try: 32 | from PIL import Image, ImageDraw, ImageFont 33 | except ImportError: 34 | sys.exit("Cannot import from PIL: Do `pip3 install --user Pillow` to install") 35 | 36 | 37 | class IFTTTRobot(cozmo.robot.Robot): 38 | '''Add some methods to the base Robot class.''' 39 | async def get_in_position(self): 40 | '''If necessary, Move Cozmo's Head and Lift to make it easy to see Cozmo's face''' 41 | if (self.lift_height.distance_mm > 45) or (self.head_angle.degrees < 40): 42 | async with self.perform_off_charger(): 43 | lift_action = self.set_lift_height(0.0, in_parallel=True) 44 | head_action = self.set_head_angle(cozmo.robot.MAX_HEAD_ANGLE, 45 | in_parallel=True) 46 | await lift_action.wait_for_completed() 47 | await head_action.wait_for_completed() 48 | 49 | def display_image_file_on_face(self, image_name): 50 | # load image and convert it for display on cozmo's face 51 | image = Image.open(image_name) 52 | 53 | # resize to fit on Cozmo's face screen 54 | resized_image = image.resize(cozmo.oled_face.dimensions(), Image.NEAREST) 55 | 56 | # convert the image to the format used by the oled screen 57 | face_image = cozmo.oled_face.convert_image_to_screen_data(resized_image, 58 | invert_image=True) 59 | 60 | # display image for 5 seconds 61 | self.display_oled_face_image(face_image, 5000.0) 62 | -------------------------------------------------------------------------------- /examples/tutorials/01_basics/10_play_sound.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # Copyright (c) 2018 Anki, Inc. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License in the file LICENSE.txt or at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | '''Play Sounds through various methods 18 | 19 | A) Play a one-off sound on the device 20 | B) Play a music loop which will be interrupted while playing 21 | C) Play one of the Tiny Orchestra loops by bringing in 2 instruments one at a 22 | time. 23 | ''' 24 | 25 | import time 26 | 27 | import cozmo 28 | 29 | def cozmo_program(robot: cozmo.robot.Robot): 30 | # Play a sound that ends on its own 31 | robot.play_audio(cozmo.audio.AudioEvents.SfxGameWin) 32 | time.sleep(1.0) 33 | 34 | # Play a sound for us to interrupt after two seconds 35 | # This sound "MusicStyle80S1159BpmLoop" is: 36 | # - "80S" style music #"1", at "159Bpm" (beats per minute) 37 | # - if the song is played repeatedly, the beginning and end 38 | # line up making it possible to play in a "Loop" 39 | robot.play_audio(cozmo.audio.AudioEvents.MusicStyle80S1159BpmLoop) 40 | 41 | # Most sounds have an accompanying (name + "Stop") event to cancel it 42 | # before it finishes. 43 | time.sleep(2.0) 44 | robot.play_audio(cozmo.audio.AudioEvents.MusicStyle80S1159BpmLoopStop) 45 | 46 | # Start the tiny orchestra system. 47 | # By itself, the tiny orchestra system will not make any sound, but 48 | # allows us to turn synchronized audio channels on and off until 49 | # we tell it to stop. 50 | robot.play_audio(cozmo.audio.AudioEvents.MusicTinyOrchestraInit) 51 | 52 | # Turn on the bass_mode_1 channel in the tiny orchestra system. 53 | robot.play_audio(cozmo.audio.AudioEvents.MusicTinyOrchestraBassMode1) 54 | 55 | # After 5 seconds... 56 | time.sleep(5.0) 57 | 58 | # Turn on the strings_mode_3 channel. 59 | robot.play_audio(cozmo.audio.AudioEvents.MusicTinyOrchestraStringsMode3) 60 | 61 | # After 5 seconds... 62 | time.sleep(5.0) 63 | 64 | # Stop the tiny orchestra system. 65 | # This will cause all tinyOrchestra music to stop playing. 66 | robot.play_audio(cozmo.audio.AudioEvents.MusicTinyOrchestraStop) 67 | 68 | 69 | cozmo.run_program(cozmo_program) 70 | -------------------------------------------------------------------------------- /docs/source/install-macos.rst: -------------------------------------------------------------------------------- 1 | .. _install-macos: 2 | 3 | ########################### 4 | Installation - macOS / OS X 5 | ########################### 6 | 7 | This guide provides instructions on installing the Cozmo SDK for computers running with a macOS operating system. 8 | 9 | ^^^^^^^^^^^^^^^^^^^ 10 | Installation Videos 11 | ^^^^^^^^^^^^^^^^^^^ 12 | 13 | For your convenience, videos are provided showing the installation steps being followed on a macOS / OS X computer; one using an iOS device, and one using an Android device. There is also full text-based documentation below these. 14 | 15 | .. raw:: html 16 | 17 | 18 | 19 | 20 | 21 | | 22 | 23 | ^^^^^^^^^^^^^^^^^^^ 24 | Python Installation 25 | ^^^^^^^^^^^^^^^^^^^ 26 | 27 | 1. Install `Homebrew `_ on your system according to the latest instructions. If you already had brew installed then update it by opening a Terminal window and typing in the following:: 28 | 29 | brew update 30 | 31 | 2. Once Homebrew is installed and updated, type the following into the Terminal window to install the latest version of Python 3:: 32 | 33 | brew install python3 34 | 35 | ^^^^^^^^^^^^^^^^ 36 | SDK Installation 37 | ^^^^^^^^^^^^^^^^ 38 | 39 | To install the SDK, type the following into the Terminal window:: 40 | 41 | pip3 install --user 'cozmo[camera]' 42 | 43 | Note that the [camera] option adds support for processing images from Cozmo's camera. 44 | 45 | """"""""""" 46 | SDK Upgrade 47 | """"""""""" 48 | 49 | To upgrade the SDK from a previous install, enter this command:: 50 | 51 | pip3 install --user --upgrade cozmo 52 | 53 | ^^^^^^^^^^^^^^^^^^^ 54 | Mobile Device Setup 55 | ^^^^^^^^^^^^^^^^^^^ 56 | 57 | * **iOS** devices do not require any special setup in order to run the Cozmo SDK on a macOS system. 58 | * **Android** devices require installation of :ref:`adb` (adb) in order to run the Cozmo SDK. This is required for the computer to communicate with the Android mobile device over a USB cable and runs automatically when required. 59 | 60 | ^^^^^^^^^^^^^^^ 61 | Troubleshooting 62 | ^^^^^^^^^^^^^^^ 63 | 64 | Please see the :ref:`trouble` section of the Initial Setup page for tips, or visit the `Cozmo SDK Forums `_ to ask questions, find solutions, or for general discussion. 65 | 66 | ---- 67 | 68 | `Terms and Conditions `_ and `Privacy Policy `_ 69 | 70 | `Click here to return to the Anki Developer website. `_ 71 | -------------------------------------------------------------------------------- /examples/tutorials/04_cubes_and_objects/10_object_moved.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # Copyright (c) 2017 Anki, Inc. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License in the file LICENSE.txt or at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | '''Demonstrate the use of Object Moving events to detect when the cubes are moved. 18 | 19 | This script is a simple example of how to subscribe to Object Moving events to 20 | track when Cozmo detects that a cube is being moved. 21 | ''' 22 | 23 | import time 24 | 25 | import cozmo 26 | 27 | 28 | def handle_object_moving_started(evt, **kw): 29 | # This will be called whenever an EvtObjectMovingStarted event is dispatched - 30 | # whenever we detect a cube starts moving (via an accelerometer in the cube) 31 | print("Object %s started moving: acceleration=%s" % 32 | (evt.obj.object_id, evt.acceleration)) 33 | 34 | 35 | def handle_object_moving(evt, **kw): 36 | # This will be called whenever an EvtObjectMoving event is dispatched - 37 | # whenever we detect a cube is still moving a (via an accelerometer in the cube) 38 | print("Object %s is moving: acceleration=%s, duration=%.1f seconds" % 39 | (evt.obj.object_id, evt.acceleration, evt.move_duration)) 40 | 41 | 42 | def handle_object_moving_stopped(evt, **kw): 43 | # This will be called whenever an EvtObjectMovingStopped event is dispatched - 44 | # whenever we detect a cube stopped moving (via an accelerometer in the cube) 45 | print("Object %s stopped moving: duration=%.1f seconds" % 46 | (evt.obj.object_id, evt.move_duration)) 47 | 48 | 49 | def cozmo_program(robot: cozmo.robot.Robot): 50 | # Add event handlers that will be called for the corresponding event 51 | robot.add_event_handler(cozmo.objects.EvtObjectMovingStarted, handle_object_moving_started) 52 | robot.add_event_handler(cozmo.objects.EvtObjectMoving, handle_object_moving) 53 | robot.add_event_handler(cozmo.objects.EvtObjectMovingStopped, handle_object_moving_stopped) 54 | 55 | # keep the program running until user closes / quits it 56 | print("Press CTRL-C to quit") 57 | while True: 58 | time.sleep(1.0) 59 | 60 | 61 | cozmo.robot.Robot.drive_off_charger_on_connect = False # Cozmo can stay on his charger for this example 62 | cozmo.run_program(cozmo_program) 63 | -------------------------------------------------------------------------------- /docs/source/install-windows.rst: -------------------------------------------------------------------------------- 1 | .. _install-windows: 2 | 3 | ###################### 4 | Installation - Windows 5 | ###################### 6 | 7 | This guide provides instructions on installing the Cozmo SDK for computers running with a Windows operating system. 8 | 9 | ^^^^^^^^^^^^^^^^^^^ 10 | Installation Videos 11 | ^^^^^^^^^^^^^^^^^^^ 12 | 13 | For your convenience, videos are provided showing the installation steps being followed on a Windows computer; one using an iOS device, and one using an Android device. There is also full text-based documentation below these. 14 | 15 | .. raw:: html 16 | 17 | 18 | 19 | 20 | 21 | | 22 | 23 | ^^^^^^^^^^^^^^^^^^^ 24 | Python Installation 25 | ^^^^^^^^^^^^^^^^^^^ 26 | 27 | Download the `Python 3.5.1 (or later) executable file from Python.org `_ and 28 | run it on your computer. 29 | 30 | .. important:: We recommend that you tick the "Add Python 3.5 to PATH" checkbox on the Setup screen. 31 | 32 | ^^^^^^^^^^^^^^^^ 33 | SDK Installation 34 | ^^^^^^^^^^^^^^^^ 35 | 36 | To install the SDK, type the following into the Command Prompt window:: 37 | 38 | pip3 install --user cozmo[camera] 39 | 40 | Note that the [camera] option adds support for processing images from Cozmo's camera. 41 | 42 | """"""""""" 43 | SDK Upgrade 44 | """"""""""" 45 | 46 | To upgrade the SDK from a previous install, enter this command:: 47 | 48 | pip3 install --user --upgrade cozmo 49 | 50 | ^^^^^^^^^^^^^^^^^^^ 51 | Mobile Device Setup 52 | ^^^^^^^^^^^^^^^^^^^ 53 | 54 | * **iOS** devices require `iTunes `_ to ensure that the usbmuxd service is installed on your computer. Usbmuxd is required for the computer to communicate with the iOS device over a USB cable. While iTunes needs to be installed, it does not need to be running. 55 | 56 | * **Android** devices require installation of :ref:`adb` (adb) in order to run the Cozmo SDK. This is required for the computer to communicate with the Android mobile device over a USB cable and runs automatically when required. 57 | 58 | ^^^^^^^^^^^^^^^ 59 | Troubleshooting 60 | ^^^^^^^^^^^^^^^ 61 | 62 | Please see the :ref:`trouble` section of the Initial Setup page for tips, or visit the `Cozmo SDK Forums `_ to ask questions, find solutions, or for general discussion. 63 | 64 | ---- 65 | 66 | `Terms and Conditions `_ and `Privacy Policy `_ 67 | 68 | `Click here to return to the Anki Developer website. `_ 69 | -------------------------------------------------------------------------------- /docs/ext/verlink.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2016 Anki, Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License in the file LICENSE.txt or at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | '''Generate versioned links for example files. 16 | 17 | This extension adds a new role to generate links to the correct version 18 | of files referenced by the documentation. 19 | 20 | It substitutes the string "0.0.0" with a version number defined by the 21 | "verlink_version" configuration value. 22 | 23 | Roles can optionally include text to use for the link, else it defaults 24 | to the supplied filename. the URL is prefixed with the 25 | "verlink_base_url" value to make a complete URL. 26 | 27 | For example, if verlink_base_url="http://example.com/files/0.0.0/" 28 | and verlink_version="1.2.3" then 29 | 30 | :verlink:`examples-0.0.0.zip` will display "examples-1.2.3.zip" and link 31 | to http:/example.com/files/1.2.3/examples-1.2.3.zip 32 | 33 | :verlink:`Examples for 0.0.0 ` will display 34 | "Examples for 1.2.3" and link to http:/example.com/files/1.2.3/examples-1.2.3.zip 35 | ''' 36 | 37 | 38 | from docutils import nodes, utils 39 | 40 | import sphinx 41 | from sphinx.util.nodes import split_explicit_title 42 | 43 | 44 | def replace_version(app, str): 45 | try: 46 | ver = app.config.verlink_version 47 | except AttributeError as err: 48 | raise ValueError("verlink_version configuration value is not set") 49 | return str.replace('0.0.0', ver) 50 | 51 | 52 | def verlink_role(typ, rawtext, text, lineno, inliner, options={}, content=[]): 53 | app = inliner.document.settings.env.app 54 | try: 55 | base_url = app.config.verlink_base_url 56 | except AttributeError as err: 57 | raise ValueError("verlink_base_url configuration value is not set") 58 | 59 | text = utils.unescape(text) 60 | has_explicit_title, title, fn = split_explicit_title(text) 61 | full_url = replace_version(app, base_url + fn) 62 | if not has_explicit_title: 63 | title = fn 64 | title = replace_version(app, title) 65 | pnode = nodes.reference(title, title, internal=False, refuri=full_url) 66 | return [pnode], [] 67 | 68 | 69 | def setup(app): 70 | app.add_role('verlink', verlink_role) 71 | app.add_config_value('verlink_base_url', None, {}) 72 | app.add_config_value('verlink_version', None, {}) 73 | -------------------------------------------------------------------------------- /examples/tutorials/05_async_python/01_cube_blinker_sync.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # Copyright (c) 2016 Anki, Inc. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License in the file LICENSE.txt or at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | '''Cube Blinker synchronous example 18 | 19 | Cozmo first looks around for a cube. Once a cube is found, 20 | the cube's lights blink green in a circular fashion. The 21 | script then waits for the cube to be tapped. 22 | ''' 23 | 24 | import asyncio 25 | import sys 26 | 27 | import cozmo 28 | 29 | class BlinkyCube(cozmo.objects.LightCube): 30 | '''Subclass LightCube and add a light-chaser effect.''' 31 | def __init__(self, *a, **kw): 32 | super().__init__(*a, **kw) 33 | self._chaser = None 34 | 35 | def start_light_chaser(self): 36 | '''Cycles the lights around the cube with 1 corner lit up green, 37 | changing to the next corner every 0.1 seconds. 38 | ''' 39 | if self._chaser: 40 | raise ValueError("Light chaser already running") 41 | async def _chaser(): 42 | while True: 43 | for i in range(4): 44 | cols = [cozmo.lights.off_light] * 4 45 | cols[i] = cozmo.lights.green_light 46 | self.set_light_corners(*cols) 47 | await asyncio.sleep(0.1, loop=self._loop) 48 | self._chaser = asyncio.ensure_future(_chaser(), loop=self._loop) 49 | 50 | def stop_light_chaser(self): 51 | if self._chaser: 52 | self._chaser.cancel() 53 | self._chaser = None 54 | 55 | 56 | # Make sure World knows how to instantiate the subclass 57 | cozmo.world.World.light_cube_factory = BlinkyCube 58 | 59 | 60 | def cozmo_program(robot: cozmo.robot.Robot): 61 | cube = None 62 | look_around = robot.start_behavior(cozmo.behavior.BehaviorTypes.LookAroundInPlace) 63 | 64 | try: 65 | cube = robot.world.wait_for_observed_light_cube(timeout=60) 66 | except asyncio.TimeoutError: 67 | print("Didn't find a cube :-(") 68 | return 69 | finally: 70 | look_around.stop() 71 | 72 | cube.start_light_chaser() 73 | try: 74 | print("Waiting for cube to be tapped") 75 | cube.wait_for_tap(timeout=10) 76 | print("Cube tapped") 77 | except asyncio.TimeoutError: 78 | print("No-one tapped our cube :-(") 79 | finally: 80 | cube.stop_light_chaser() 81 | cube.set_lights_off() 82 | 83 | 84 | cozmo.run_program(cozmo_program) 85 | -------------------------------------------------------------------------------- /docs/source/sdk-versions.rst: -------------------------------------------------------------------------------- 1 | .. _sdk-versions: 2 | 3 | #################### 4 | SDK vs. App Versions 5 | #################### 6 | 7 | The Cozmo SDK is updated often in order to provide you with the best possible user experience. The SDK and Cozmo app do not always update at the same frequency. Check this list to see if the version of the SDK you wish to use matches up with the version of the app you are using. 8 | 9 | +---------------+---------------+ 10 | | App Version # | SDK Version # | 11 | +===============+===============+ 12 | | 1.0.1 | 0.7.0 | 13 | +---------------+---------------+ 14 | | 1.0.2 | 0.8.0 | 15 | +---------------+---------------+ 16 | | 1.0.3 | 0.8.1 | 17 | +---------------+---------------+ 18 | | 1.1.0 | 0.9.0 | 19 | +---------------+---------------+ 20 | | 1.1.0 | 0.10.0 | 21 | +---------------+---------------+ 22 | | 1.2.0 | 0.11.0 | 23 | +---------------+---------------+ 24 | | 1.3.0 | 0.12.0 | 25 | +---------------+---------------+ 26 | | 1.4.1 | 0.13.0 | 27 | +---------------+---------------+ 28 | | 1.5.0 | 0.14.0 | 29 | +---------------+---------------+ 30 | | 1.6.0 | 0.15.0 | 31 | +---------------+---------------+ 32 | | 1.7.1 | 0.15.1 | 33 | +---------------+---------------+ 34 | | 1.7.1 | 0.16.0 | 35 | +---------------+---------------+ 36 | | 2.0.0 | 1.0.0 | 37 | +---------------+---------------+ 38 | | 2.0.1 | 1.0.1 | 39 | +---------------+---------------+ 40 | | 2.0.1 | 1.1.0 | 41 | +---------------+---------------+ 42 | | 2.1.0 | 1.2.0 | 43 | +---------------+---------------+ 44 | | 2.1.0 | 1.2.1 | 45 | +---------------+---------------+ 46 | | 2.2.0 | 1.3.0 | 47 | +---------------+---------------+ 48 | | 2.3.0 | 1.3.1 | 49 | +---------------+---------------+ 50 | | 2.4.0 | 1.3.2 | 51 | +---------------+---------------+ 52 | | 2.5.0 | 1.4.0 | 53 | +---------------+---------------+ 54 | | 2.6.0 | 1.4.1 | 55 | +---------------+---------------+ 56 | | 2.7.0 | 1.4.2 | 57 | +---------------+---------------+ 58 | | 2.8.0 | 1.4.3 | 59 | +---------------+---------------+ 60 | | 2.9.0 | 1.4.4 | 61 | +---------------+---------------+ 62 | | 2.10.0 | 1.4.5 | 63 | +---------------+---------------+ 64 | | 3.0.1 | 1.4.6 | 65 | +---------------+---------------+ 66 | | 3.1.0 | 1.4.7 | 67 | +---------------+---------------+ 68 | | 3.2.0 | 1.4.8 | 69 | +---------------+---------------+ 70 | | 3.3.0 | 1.4.9 | 71 | +---------------+---------------+ 72 | | 3.4.0 | 1.4.10 | 73 | +---------------+---------------+ 74 | 75 | If you have incompatible versions of the app and the SDK, please update the app and SDK. 76 | 77 | ---- 78 | 79 | `Terms and Conditions `_ and `Privacy Policy `_ 80 | 81 | `Click here to return to the Anki Developer website. `_ 82 | -------------------------------------------------------------------------------- /examples/tutorials/01_basics/11_play_song.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # Copyright (c) 2018 Anki, Inc. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License in the file LICENSE.txt or at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | '''Cozmo sings different musical notes 18 | 19 | A) Plays a rising scale of quarter notes 20 | B) Plays the same pitch at different durations 21 | ''' 22 | 23 | import asyncio 24 | import time 25 | 26 | import cozmo 27 | 28 | def cozmo_program(robot: cozmo.robot.Robot): 29 | 30 | # Create an array of SongNote objects, consisting of all notes from C2 to C3_Sharp 31 | notes = [ 32 | cozmo.song.SongNote(cozmo.song.NoteTypes.C2, cozmo.song.NoteDurations.Quarter), 33 | cozmo.song.SongNote(cozmo.song.NoteTypes.C2_Sharp, cozmo.song.NoteDurations.Quarter), 34 | cozmo.song.SongNote(cozmo.song.NoteTypes.D2, cozmo.song.NoteDurations.Quarter), 35 | cozmo.song.SongNote(cozmo.song.NoteTypes.D2_Sharp, cozmo.song.NoteDurations.Quarter), 36 | cozmo.song.SongNote(cozmo.song.NoteTypes.E2, cozmo.song.NoteDurations.Quarter), 37 | cozmo.song.SongNote(cozmo.song.NoteTypes.F2, cozmo.song.NoteDurations.Quarter), 38 | cozmo.song.SongNote(cozmo.song.NoteTypes.F2_Sharp, cozmo.song.NoteDurations.Quarter), 39 | cozmo.song.SongNote(cozmo.song.NoteTypes.G2, cozmo.song.NoteDurations.Quarter), 40 | cozmo.song.SongNote(cozmo.song.NoteTypes.G2_Sharp, cozmo.song.NoteDurations.Quarter), 41 | cozmo.song.SongNote(cozmo.song.NoteTypes.A2, cozmo.song.NoteDurations.Quarter), 42 | cozmo.song.SongNote(cozmo.song.NoteTypes.A2_Sharp, cozmo.song.NoteDurations.Quarter), 43 | cozmo.song.SongNote(cozmo.song.NoteTypes.B2, cozmo.song.NoteDurations.Quarter), 44 | cozmo.song.SongNote(cozmo.song.NoteTypes.C3, cozmo.song.NoteDurations.Quarter), 45 | cozmo.song.SongNote(cozmo.song.NoteTypes.C3_Sharp, cozmo.song.NoteDurations.Quarter), 46 | cozmo.song.SongNote(cozmo.song.NoteTypes.Rest, cozmo.song.NoteDurations.Quarter) ] 47 | 48 | # Play the ascending notes 49 | robot.play_song(notes, loop_count=1).wait_for_completed() 50 | 51 | # Create an array of SongNote objects, consisting of the C3 pitch with varying durations 52 | notes = [ 53 | cozmo.song.SongNote(cozmo.song.NoteTypes.C3, cozmo.song.NoteDurations.Half), 54 | cozmo.song.SongNote(cozmo.song.NoteTypes.C3, cozmo.song.NoteDurations.ThreeQuarter), 55 | cozmo.song.SongNote(cozmo.song.NoteTypes.Rest, cozmo.song.NoteDurations.Quarter), 56 | cozmo.song.SongNote(cozmo.song.NoteTypes.C3, cozmo.song.NoteDurations.Quarter), 57 | cozmo.song.SongNote(cozmo.song.NoteTypes.C3, cozmo.song.NoteDurations.Whole) ] 58 | 59 | # Play the notes with varying durations 60 | robot.play_song(notes, loop_count=1).wait_for_completed() 61 | 62 | cozmo.run_program(cozmo_program) 63 | -------------------------------------------------------------------------------- /src/cozmo/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2016 Anki, Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License in the file LICENSE.txt or at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | import sys 16 | if sys.version_info < (3,5,1): 17 | sys.exit('cozmo requires Python 3.5.1 or later') 18 | 19 | # Verify cozmoclad version before any other imports, so we can catch a mismatch 20 | # before triggering any exceptions from missing clad definitions 21 | try: 22 | from cozmoclad import __build_version__ as __installed_cozmoclad_build_version__ 23 | except ImportError as e: 24 | sys.exit("%s\nCannot import from cozmoclad: Do `pip3 install --user cozmoclad` to install" % e) 25 | 26 | from .version import __version__, __cozmoclad_version__, __min_cozmoclad_version__ 27 | 28 | def verify_min_clad_version(): 29 | def _make_sortable_version_string(ver_string): 30 | # pad out an x.y.z version to a 5.5.5 string with leading zeroes 31 | ver_elements = [str(int(x)).zfill(5) for x in ver_string.split(".")] 32 | return '.'.join(ver_elements) 33 | 34 | def _trimmed_version(ver_string): 35 | # Trim leading zeros from the version string 36 | trimmed_parts = [str(int(x)) for x in ver_string.split(".")] 37 | return '.'.join(trimmed_parts) 38 | 39 | min_cozmoclad_version_str = _make_sortable_version_string(__min_cozmoclad_version__) 40 | if __installed_cozmoclad_build_version__ < min_cozmoclad_version_str: 41 | sys.exit("Incompatible cozmoclad version %s for SDK %s - needs at least %s\n" 42 | "Do `pip3 install --user --upgrade cozmoclad` to upgrade" % ( 43 | _trimmed_version(__installed_cozmoclad_build_version__), 44 | __version__, 45 | __min_cozmoclad_version__)) 46 | 47 | 48 | verify_min_clad_version() 49 | 50 | 51 | import logging as _logging 52 | 53 | #: The general purpose logger logs high level information about Cozmo events. 54 | logger = _logging.getLogger('cozmo.general') 55 | 56 | #: The protocol logger logs low level messages that are sent back and forth to Cozmo. 57 | logger_protocol = _logging.getLogger('cozmo.protocol') 58 | 59 | del _logging 60 | 61 | from . import action 62 | from . import anim 63 | from . import annotate 64 | from . import behavior 65 | from . import conn 66 | from . import event 67 | from . import exceptions 68 | from . import lights 69 | from . import nav_memory_map 70 | from . import objects 71 | from . import oled_face 72 | from . import robot 73 | from . import robot_alignment 74 | from . import run 75 | from . import util 76 | from . import world 77 | 78 | from .exceptions import * 79 | from .run import * 80 | 81 | 82 | __all__ = ['logger', 'logger_protocol', 83 | 'action', 'anim', 'annotate', 'behavior', 'conn', 'event', 84 | 'exceptions', 'lights', 'objects', 'oled_face', 'nav_memory_map', 85 | 'robot', 'robot_alignment', 'run', 'util', 'world'] + \ 86 | (run.__all__ + exceptions.__all__) 87 | -------------------------------------------------------------------------------- /examples/tutorials/04_cubes_and_objects/08_drive_to_charger_test.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # Copyright (c) 2016 Anki, Inc. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License in the file LICENSE.txt or at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | '''Make Cozmo drive towards his charger. 18 | 19 | The script shows an example of accessing the charger object from 20 | Cozmo's world, and driving towards it. 21 | ''' 22 | 23 | import asyncio 24 | import time 25 | 26 | import cozmo 27 | from cozmo.util import degrees, distance_mm, speed_mmps 28 | 29 | 30 | def drive_to_charger(robot): 31 | '''The core of the drive_to_charger program''' 32 | 33 | # If the robot was on the charger, drive them forward and clear of the charger 34 | if robot.is_on_charger: 35 | # drive off the charger 36 | robot.drive_off_charger_contacts().wait_for_completed() 37 | robot.drive_straight(distance_mm(100), speed_mmps(50)).wait_for_completed() 38 | # Start moving the lift down 39 | robot.move_lift(-3) 40 | # turn around to look at the charger 41 | robot.turn_in_place(degrees(180)).wait_for_completed() 42 | # Tilt the head to be level 43 | robot.set_head_angle(degrees(0)).wait_for_completed() 44 | # wait half a second to ensure Cozmo has seen the charger 45 | time.sleep(0.5) 46 | # drive backwards away from the charger 47 | robot.drive_straight(distance_mm(-60), speed_mmps(50)).wait_for_completed() 48 | 49 | # try to find the charger 50 | charger = None 51 | 52 | # see if Cozmo already knows where the charger is 53 | if robot.world.charger: 54 | if robot.world.charger.pose.is_comparable(robot.pose): 55 | print("Cozmo already knows where the charger is!") 56 | charger = robot.world.charger 57 | else: 58 | # Cozmo knows about the charger, but the pose is not based on the 59 | # same origin as the robot (e.g. the robot was moved since seeing 60 | # the charger) so try to look for the charger first 61 | pass 62 | 63 | if not charger: 64 | # Tell Cozmo to look around for the charger 65 | look_around = robot.start_behavior(cozmo.behavior.BehaviorTypes.LookAroundInPlace) 66 | try: 67 | charger = robot.world.wait_for_observed_charger(timeout=30) 68 | print("Found charger: %s" % charger) 69 | except asyncio.TimeoutError: 70 | print("Didn't see the charger") 71 | finally: 72 | # whether we find it or not, we want to stop the behavior 73 | look_around.stop() 74 | 75 | if charger: 76 | # Attempt to drive near to the charger, and then stop. 77 | action = robot.go_to_object(charger, distance_mm(65.0)) 78 | action.wait_for_completed() 79 | print("Completed action: result = %s" % action) 80 | print("Done.") 81 | 82 | 83 | cozmo.robot.Robot.drive_off_charger_on_connect = False # Cozmo can stay on charger for now 84 | cozmo.run_program(drive_to_charger, use_viewer=True, force_viewer_on_top=True) 85 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2016 Anki, Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License in the file LICENSE.txt or at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | ''' 16 | The Cozmo SDK is a flexible vision-based robotics platform used in enterprise, education, and entertainment. 17 | 18 | Cozmo’s pioneering combination of advanced robotics hardware and software are part of what make him an innovative consumer experience. But it’s also what makes him, in conjunction with the Cozmo SDK, a groundbreaking robotics platform that’s expressive, engaging, and entertaining. 19 | 20 | We built the Cozmo SDK to be robust enough for enterprise and research, but simple enough for anyone with a bit of technical know-how to tap into our sophisticated robotics and AI technologies. Organizations and institutions using the Cozmo SDK include SAP, Oracle, Carnegie Mellon University, and Georgia Tech. Find out more at developer.anki.com 21 | 22 | Cozmo SDK documentation: http://cozmosdk.anki.com/docs/ 23 | 24 | Official developer forum: https://forums.anki.com/ 25 | 26 | Requirements: 27 | * Python 3.5.1 or later 28 | ''' 29 | 30 | 31 | from setuptools import setup, find_packages 32 | import os.path 33 | import sys 34 | 35 | if sys.version_info < (3,5,1): 36 | sys.exit('cozmo requires Python 3.5.1 or later') 37 | 38 | here = os.path.abspath(os.path.dirname(__file__)) 39 | 40 | 41 | def fetch_version(): 42 | with open(os.path.join(here, 'src', 'cozmo', 'version.py')) as f: 43 | ns = {} 44 | exec(f.read(), ns) 45 | return ns 46 | 47 | version_data = fetch_version() 48 | version = version_data['__version__'] 49 | cozmoclad_version = version_data['__cozmoclad_version__'] 50 | 51 | if cozmoclad_version is None: 52 | install_requires = ['cozmoclad'] 53 | else: 54 | install_requires = ['cozmoclad==' + cozmoclad_version] 55 | 56 | setup( 57 | name='cozmo', 58 | version=version, 59 | description='SDK for Anki Cozmo, the small robot with the big personality', 60 | long_description=__doc__, 61 | url='https://developer.anki.com', 62 | author='Anki, Inc', 63 | author_email='developer@anki.com', 64 | license='Apache License, Version 2.0', 65 | # See https://pypi.python.org/pypi?%3Aaction=list_classifiers 66 | classifiers=[ 67 | 'Development Status :: 5 - Production/Stable', 68 | 'Intended Audience :: Developers', 69 | 'Topic :: Software Development :: Libraries', 70 | 'License :: OSI Approved :: Apache Software License', 71 | 'Programming Language :: Python :: 3.5', 72 | ], 73 | zip_safe=True, 74 | keywords='anki cozmo robot robotics sdk'.split(), 75 | package_dir={'': 'src'}, 76 | packages=find_packages('src'), 77 | package_data={ 78 | 'cozmo': ['LICENSE.txt', 'assets/*.obj', 'assets/*.mtl', 'assets/*.jpg', 79 | 'assets/LICENSE.txt'] 80 | }, 81 | install_requires=install_requires, 82 | extras_require={ 83 | '3dviewer': ['PyOpenGL>=3.1', 84 | 'Pillow>=3.3', 'numpy>=1.11'], 85 | 'camera': ['Pillow>=3.3', 'numpy>=1.11'], 86 | 'test': ['tox', 'pytest'], 87 | } 88 | ) 89 | -------------------------------------------------------------------------------- /src/cozmo/exceptions.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2016 Anki, Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License in the file LICENSE.txt or at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | '''SDK-specific exception classes.''' 16 | 17 | # __all__ should order by constants, event classes, other classes, functions. 18 | __all__ = ['CozmoSDKException', 'SDKShutdown', 'StopPropogation', 19 | 'AnimationsNotLoaded', 'ActionError', 'ConnectionError', 20 | 'ConnectionAborted', 'ConnectionCheckFailed', 'NoDevicesFound', 21 | 'SDKVersionMismatch', 'NotPickupable', 'CannotPlaceObjectsOnThis', 22 | 'RobotBusy', 'InvalidOpenGLGlutImplementation'] 23 | 24 | 25 | class CozmoSDKException(Exception): 26 | '''Base class of all Cozmo SDK exceptions.''' 27 | 28 | class SDKShutdown(CozmoSDKException): 29 | '''Raised when the SDK is being shut down''' 30 | 31 | class StopPropogation(CozmoSDKException): 32 | '''Raised by event handlers to prevent further handlers from being triggered.''' 33 | 34 | class AnimationsNotLoaded(CozmoSDKException): 35 | '''Raised if an attempt is made to play a named animation before animations have been received.''' 36 | 37 | class ActionError(CozmoSDKException): 38 | '''Base class for errors that occur with robot actions.''' 39 | 40 | class ConnectionError(CozmoSDKException): 41 | '''Base class for errors regarding connection to the device.''' 42 | 43 | class ConnectionAborted(ConnectionError): 44 | '''Raised if the connection to the device is unexpectedly lost.''' 45 | 46 | class ConnectionCheckFailed(ConnectionError): 47 | '''Raised if the connection check has failed.''' 48 | 49 | class NoDevicesFound(ConnectionError): 50 | '''Raised if no devices connected running Cozmo in SDK mode''' 51 | 52 | class SDKVersionMismatch(ConnectionError): 53 | '''Raised if the Cozmo SDK version is not compatible with the software running on the device.''' 54 | def __init__(self, message, sdk_version, sdk_app_version, app_version, *args): 55 | super().__init__(message, sdk_version, sdk_app_version, app_version, *args) 56 | #: str: The SDK version number in Major.Minor.Patch format. 57 | #: See :ref:`sdk-versions` for which App version is compatible with each SDK version. 58 | self.sdk_version = sdk_version 59 | #: str: The version of the App that this SDK is compatible with in Major.Minor.Patch format. 60 | self.sdk_app_version = sdk_app_version 61 | #: str: The version of the App that was detected, and is incompatible, in Major.Minor.Patch format. 62 | self.app_version = app_version 63 | 64 | class NotPickupable(ActionError): 65 | '''Raised if an attempt is made to pick up or place an object that can't be picked up by Cozmo''' 66 | 67 | class CannotPlaceObjectsOnThis(ActionError): 68 | '''Raised if an attempt is made to place an object on top of an invalid object''' 69 | 70 | class RobotBusy(ActionError): 71 | '''Raised if an attempt is made to perform an action while another action is still running.''' 72 | 73 | class InvalidOpenGLGlutImplementation(ImportError): 74 | '''Raised by opengl viewer if no valid GLUT implementation available.''' 75 | -------------------------------------------------------------------------------- /examples/tutorials/03_vision/03_annotate.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # Copyright (c) 2016 Anki, Inc. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License in the file LICENSE.txt or at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | '''Display a GUI window showing an annotated camera view. 18 | 19 | Note: 20 | This example requires Python to have Tkinter installed to display the GUI. 21 | It also requires the Pillow and numpy python packages to be pip installed. 22 | 23 | The :class:`cozmo.world.World` object collects raw images from Cozmo's camera 24 | and makes them available as a property (:attr:`~cozmo.world.World.latest_image`) 25 | and by generating :class:`cozmo.world.EvtNewCamerImages` events as they come in. 26 | 27 | Each image is an instance of :class:`cozmo.world.CameraImage` which provides 28 | access both to the raw camera image, and to a scalable annotated image which 29 | can show where Cozmo sees faces and objects, along with any other information 30 | your program may wish to display. 31 | 32 | This example uses the tkviewer to display the annotated camera on the screen 33 | and adds a couple of custom annotations of its own using two different methods. 34 | ''' 35 | 36 | 37 | import sys 38 | import time 39 | 40 | try: 41 | from PIL import ImageDraw, ImageFont 42 | except ImportError: 43 | sys.exit('run `pip3 install --user Pillow numpy` to run this example') 44 | 45 | import cozmo 46 | 47 | 48 | # Define an annotator using the annotator decorator 49 | @cozmo.annotate.annotator 50 | def clock(image, scale, annotator=None, world=None, **kw): 51 | d = ImageDraw.Draw(image) 52 | bounds = (0, 0, image.width, image.height) 53 | text = cozmo.annotate.ImageText(time.strftime("%H:%m:%S"), 54 | position=cozmo.annotate.TOP_LEFT) 55 | text.render(d, bounds) 56 | 57 | # Define another decorator as a subclass of Annotator 58 | class Battery(cozmo.annotate.Annotator): 59 | def apply(self, image, scale): 60 | d = ImageDraw.Draw(image) 61 | bounds = (0, 0, image.width, image.height) 62 | batt = self.world.robot.battery_voltage 63 | text = cozmo.annotate.ImageText('BATT %.1fv' % batt, color='green') 64 | text.render(d, bounds) 65 | 66 | 67 | def cozmo_program(robot: cozmo.robot.Robot): 68 | robot.world.image_annotator.add_static_text('text', 'Coz-Cam', position=cozmo.annotate.TOP_RIGHT) 69 | robot.world.image_annotator.add_annotator('clock', clock) 70 | robot.world.image_annotator.add_annotator('battery', Battery) 71 | 72 | time.sleep(2) 73 | 74 | print("Turning off all annotations for 2 seconds") 75 | robot.world.image_annotator.annotation_enabled = False 76 | time.sleep(2) 77 | 78 | print('Re-enabling all annotations') 79 | robot.world.image_annotator.annotation_enabled = True 80 | 81 | # Disable the face annotator after 10 seconds 82 | time.sleep(10) 83 | print("Disabling face annotations (light cubes still annotated)") 84 | robot.world.image_annotator.disable_annotator('faces') 85 | 86 | # Shutdown the program after 100 seconds 87 | time.sleep(100) 88 | 89 | 90 | cozmo.run_program(cozmo_program, use_viewer=True, force_viewer_on_top=True) 91 | -------------------------------------------------------------------------------- /examples/tutorials/02_cozmo_face/01_cozmo_face_image.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # Copyright (c) 2016 Anki, Inc. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License in the file LICENSE.txt or at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | '''Display images on Cozmo's face (oled screen) 18 | ''' 19 | 20 | import os 21 | import sys 22 | import time 23 | 24 | try: 25 | from PIL import Image 26 | except ImportError: 27 | sys.exit("Cannot import from PIL: Do `pip3 install --user Pillow` to install") 28 | 29 | import cozmo 30 | 31 | 32 | def get_in_position(robot: cozmo.robot.Robot): 33 | '''If necessary, Move Cozmo's Head and Lift to make it easy to see Cozmo's face''' 34 | if (robot.lift_height.distance_mm > 45) or (robot.head_angle.degrees < 40): 35 | with robot.perform_off_charger(): 36 | lift_action = robot.set_lift_height(0.0, in_parallel=True) 37 | head_action = robot.set_head_angle(cozmo.robot.MAX_HEAD_ANGLE, 38 | in_parallel=True) 39 | lift_action.wait_for_completed() 40 | head_action.wait_for_completed() 41 | 42 | 43 | def cozmo_program(robot: cozmo.robot.Robot): 44 | current_directory = os.path.dirname(os.path.realpath(__file__)) 45 | get_in_position(robot) 46 | sdk_png = os.path.join(current_directory, "..", "..", "face_images", "cozmosdk.png") 47 | hello_png = os.path.join(current_directory, "..", "..", "face_images", "hello_world.png") 48 | 49 | # load some images and convert them for display cozmo's face 50 | image_settings = [(sdk_png, Image.BICUBIC), 51 | (hello_png, Image.NEAREST)] 52 | face_images = [] 53 | for image_name, resampling_mode in image_settings: 54 | image = Image.open(image_name) 55 | 56 | # resize to fit on Cozmo's face screen 57 | resized_image = image.resize(cozmo.oled_face.dimensions(), resampling_mode) 58 | 59 | # convert the image to the format used by the oled screen 60 | face_image = cozmo.oled_face.convert_image_to_screen_data(resized_image, 61 | invert_image=True) 62 | face_images.append(face_image) 63 | 64 | # display each image on Cozmo's face for duration_s seconds (Note: this 65 | # is clamped at 30 seconds max within the engine to prevent burn-in) 66 | # repeat this num_loops times 67 | 68 | num_loops = 10 69 | duration_s = 2.0 70 | 71 | print("Press CTRL-C to quit (or wait %s seconds to complete)" % int(num_loops*duration_s) ) 72 | 73 | for _ in range(num_loops): 74 | for image in face_images: 75 | robot.display_oled_face_image(image, duration_s * 1000.0) 76 | time.sleep(duration_s) 77 | 78 | 79 | # Cozmo is moved off his charger contacts by default at the start of any program. 80 | # This is because not all motor movement is possible whilst drawing current from 81 | # the charger. In cases where motor movement is not required, such as this example 82 | # we can specify that Cozmo can stay on his charger at the start: 83 | cozmo.robot.Robot.drive_off_charger_on_connect = False 84 | 85 | cozmo.run_program(cozmo_program) 86 | 87 | -------------------------------------------------------------------------------- /examples/tutorials/05_async_python/02_cube_blinker.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # Copyright (c) 2016 Anki, Inc. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License in the file LICENSE.txt or at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | '''Cube Blinker asynchronous example 18 | 19 | Cozmo first looks around for a cube. Once a cube is found, 20 | the cube's lights blink green in a circular fashion. The 21 | script then waits for the cube to be tapped. 22 | ''' 23 | 24 | import asyncio 25 | import sys 26 | 27 | import cozmo 28 | 29 | class BlinkyCube(cozmo.objects.LightCube): 30 | '''Subclass LightCube and add a light-chaser effect.''' 31 | def __init__(self, *a, **kw): 32 | super().__init__(*a, **kw) 33 | self._chaser = None 34 | 35 | def start_light_chaser(self): 36 | '''Cycles the lights around the cube with 1 corner lit up green, 37 | changing to the next corner every 0.1 seconds. 38 | ''' 39 | if self._chaser: 40 | raise ValueError("Light chaser already running") 41 | async def _chaser(): 42 | while True: 43 | for i in range(4): 44 | cols = [cozmo.lights.off_light] * 4 45 | cols[i] = cozmo.lights.green_light 46 | self.set_light_corners(*cols) 47 | await asyncio.sleep(0.1, loop=self._loop) 48 | self._chaser = asyncio.ensure_future(_chaser(), loop=self._loop) 49 | 50 | def stop_light_chaser(self): 51 | if self._chaser: 52 | self._chaser.cancel() 53 | self._chaser = None 54 | 55 | 56 | # Make sure World knows how to instantiate the subclass 57 | cozmo.world.World.light_cube_factory = BlinkyCube 58 | 59 | 60 | async def cozmo_program(robot: cozmo.robot.Robot): 61 | '''The async equivalent of 01_cube_blinker_sync. 62 | 63 | The usage of ``async def`` makes the cozmo_program method a coroutine. 64 | Within a coroutine, ``await`` can be used. With ``await``, the statement 65 | blocks until the request being waited for has completed. Meanwhile 66 | the event loop continues in the background. 67 | 68 | For instance, the statement 69 | ``await robot.world.wait_for_observed_light_cube(timeout=60)`` 70 | blocks until Cozmo discovers a light cube or the 60 second timeout 71 | elapses, whichever occurs first. 72 | 73 | Likewise, the statement ``await cube.wait_for_tap(timeout=10)`` 74 | blocks until the tap event is received or the 10 second timeout occurs, 75 | whichever occurs first. 76 | 77 | For more information, see 78 | https://docs.python.org/3/library/asyncio-task.html 79 | ''' 80 | 81 | cube = None 82 | look_around = robot.start_behavior(cozmo.behavior.BehaviorTypes.LookAroundInPlace) 83 | 84 | try: 85 | cube = await robot.world.wait_for_observed_light_cube(timeout=60) 86 | except asyncio.TimeoutError: 87 | print("Didn't find a cube :-(") 88 | return 89 | finally: 90 | look_around.stop() 91 | 92 | cube.start_light_chaser() 93 | try: 94 | print("Waiting for cube to be tapped") 95 | await cube.wait_for_tap(timeout=10) 96 | print("Cube tapped") 97 | except asyncio.TimeoutError: 98 | print("No-one tapped our cube :-(") 99 | finally: 100 | cube.stop_light_chaser() 101 | cube.set_lights_off() 102 | 103 | 104 | cozmo.run_program(cozmo_program) 105 | -------------------------------------------------------------------------------- /examples/tutorials/02_cozmo_face/02_cozmo_face_mirror.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # Copyright (c) 2016 Anki, Inc. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License in the file LICENSE.txt or at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | '''Display Cozmo's camera feed back on his face (like a mirror) 18 | ''' 19 | 20 | import sys 21 | import time 22 | 23 | try: 24 | import numpy as np 25 | except ImportError: 26 | sys.exit("Cannot import numpy: Do `pip3 install --user numpy` to install") 27 | 28 | try: 29 | from PIL import Image 30 | except ImportError: 31 | sys.exit("Cannot import from PIL: Do `pip3 install --user Pillow` to install") 32 | 33 | import cozmo 34 | 35 | 36 | def get_in_position(robot: cozmo.robot.Robot): 37 | '''If necessary, Move Cozmo's Head and Lift to make it easy to see Cozmo's face.''' 38 | if (robot.lift_height.distance_mm > 45) or (robot.head_angle.degrees < 40): 39 | with robot.perform_off_charger(): 40 | lift_action = robot.set_lift_height(0.0, in_parallel=True) 41 | head_action = robot.set_head_angle(cozmo.robot.MAX_HEAD_ANGLE, 42 | in_parallel=True) 43 | lift_action.wait_for_completed() 44 | head_action.wait_for_completed() 45 | 46 | 47 | def calc_pixel_threshold(image: Image): 48 | '''Calculate a pixel threshold based on the image. 49 | 50 | Anything brighter than this will be shown on (light blue). 51 | Anything darker will be shown off (black). 52 | ''' 53 | 54 | # Convert image to gray scale 55 | grayscale_image = image.convert('L') 56 | 57 | # Calculate the mean (average) value 58 | mean_value = np.mean(grayscale_image.getdata()) 59 | return mean_value 60 | 61 | 62 | def cozmo_face_mirror(robot: cozmo.robot.Robot): 63 | '''Continuously display Cozmo's camera feed back on his face.''' 64 | 65 | robot.camera.image_stream_enabled = True 66 | get_in_position(robot) 67 | 68 | face_dimensions = cozmo.oled_face.SCREEN_WIDTH, cozmo.oled_face.SCREEN_HALF_HEIGHT 69 | 70 | print("Press CTRL-C to quit") 71 | 72 | while True: 73 | duration_s = 0.1 # time to display each camera frame on Cozmo's face 74 | 75 | latest_image = robot.world.latest_image 76 | 77 | if latest_image is not None: 78 | # Scale the camera image down to fit on Cozmo's face 79 | resized_image = latest_image.raw_image.resize(face_dimensions, 80 | Image.BICUBIC) 81 | 82 | # Flip the image left/right so it displays mirrored 83 | resized_image = resized_image.transpose(Image.FLIP_LEFT_RIGHT) 84 | 85 | # Calculate the pixel threshold for this image. This threshold 86 | # will define how bright a pixel needs to be in the source image 87 | # for it to be displayed as lit-up on Cozmo's face. 88 | pixel_threshold = calc_pixel_threshold(resized_image) 89 | 90 | # Convert the image to the format to display on Cozmo's face. 91 | screen_data = cozmo.oled_face.convert_image_to_screen_data( 92 | resized_image, 93 | pixel_threshold=pixel_threshold) 94 | 95 | # display the image on Cozmo's face 96 | robot.display_oled_face_image(screen_data, duration_s * 1000.0) 97 | 98 | time.sleep(duration_s) 99 | 100 | 101 | cozmo.robot.Robot.drive_off_charger_on_connect = False # Cozmo can stay on his charger for this example 102 | cozmo.run_program(cozmo_face_mirror) 103 | -------------------------------------------------------------------------------- /docs/source/install-linux.rst: -------------------------------------------------------------------------------- 1 | .. _install-linux: 2 | 3 | #################### 4 | Installation - Linux 5 | #################### 6 | 7 | This guide provides instructions on installing the Cozmo SDK for computers running with an Ubuntu Linux operating system. 8 | 9 | .. warning:: The Cozmo SDK is tested and and supported on Ubuntu 14.04 and 16.04. Anki makes no guarantee the Cozmo SDK will work on other versions of Linux. If you wish to try the Cozmo SDK on versions of Linux *other than* Ubuntu 14.04 or 16.04, please ensure the following dependencies are installed: 10 | 11 | * Python 3.5.1 or later 12 | * pip for Python 3 (Python package installer) 13 | * Android command-line tools (https://developer.android.com/studio/index.html#Other) 14 | * usbmuxd for iOS / :ref:`adb` for Android 15 | 16 | 17 | ^^^^^^^^^^^^ 18 | Ubuntu 14.04 19 | ^^^^^^^^^^^^ 20 | 21 | """"""""""""""""""" 22 | Python Installation 23 | """"""""""""""""""" 24 | 25 | 1. Type the following into your Terminal window to install Python 3.5:: 26 | 27 | sudo add-apt-repository ppa:deadsnakes 28 | sudo apt-get update 29 | sudo apt-get install python3.5 python3.5-tk 30 | 31 | 2. Then, install and set up virtualenv:: 32 | 33 | sudo apt-get install python-pip 34 | pip install virtualenv 35 | virtualenv -p python3.5 ~/cozmo-env 36 | 37 | 3. Last, make sure to activate the virtualenv any time you use cozmo:: 38 | 39 | source ~/cozmo-env/bin/activate 40 | 41 | .. note:: You'll need to activate the virtualenv before running any python or pip commands. Learn more about virtualenv `here `_. 42 | 43 | """""""""""""""" 44 | SDK Installation 45 | """""""""""""""" 46 | 47 | To install the SDK, type the following into the Terminal window:: 48 | 49 | pip install 'cozmo[camera]' 50 | 51 | Note that the [camera] option adds support for processing images from Cozmo's camera. 52 | 53 | """"""""""" 54 | SDK Upgrade 55 | """"""""""" 56 | 57 | To upgrade the SDK from a previous install, enter this command:: 58 | 59 | pip install --upgrade cozmo 60 | 61 | ^^^^^^^^^^^^ 62 | Ubuntu 16.04 63 | ^^^^^^^^^^^^ 64 | 65 | """"""""""""""""""" 66 | Python Installation 67 | """"""""""""""""""" 68 | 69 | 1. Type the following into your Terminal window to install Python:: 70 | 71 | sudo apt-get update 72 | sudo apt-get install python3 73 | 74 | 2. Then install pip by typing in the following into the Terminal window:: 75 | 76 | sudo apt install python3-pip 77 | 78 | 3. Last, install Tkinter:: 79 | 80 | sudo apt-get install python3-pil.imagetk 81 | 82 | """""""""""""""" 83 | SDK Installation 84 | """""""""""""""" 85 | 86 | To install the SDK, type the following into the Terminal window:: 87 | 88 | pip3 install --user 'cozmo[camera]' 89 | 90 | Note that the [camera] option adds support for processing images from Cozmo's camera. 91 | 92 | """"""""""" 93 | SDK Upgrade 94 | """"""""""" 95 | 96 | To upgrade the SDK from a previous install, enter this command:: 97 | 98 | pip3 install --user --upgrade cozmo 99 | 100 | ^^^^^^^^^^^^^^^^^^^ 101 | Mobile Device Setup 102 | ^^^^^^^^^^^^^^^^^^^ 103 | 104 | * **iOS** devices require `usbmuxd `_ in order to run the Cozmo SDK. Usbmuxd is required for the computer to communicate with the iOS device over a USB cable. 105 | 106 | * **Android** devices require installation of :ref:`adb` (adb) in order to run the Cozmo SDK. This is required for the computer to communicate with the Android mobile device over a USB cable and runs automatically when required. 107 | 108 | ^^^^^^^^^^^^^^^ 109 | Troubleshooting 110 | ^^^^^^^^^^^^^^^ 111 | 112 | Please see the :ref:`trouble` section of the Initial Setup page for tips, or visit the `Cozmo SDK Forums `_ to ask questions, find solutions, or for general discussion. 113 | 114 | ---- 115 | 116 | `Terms and Conditions `_ and `Privacy Policy `_ 117 | 118 | `Click here to return to the Anki Developer website. `_ 119 | -------------------------------------------------------------------------------- /src/cozmo/clad_protocol.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2016 Anki, Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License in the file LICENSE.txt or at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | __all__ = [] 16 | 17 | 18 | import asyncio 19 | import struct 20 | import sys 21 | from threading import Lock 22 | 23 | from . import logger_protocol 24 | 25 | LOG_ALL = 'all' 26 | 27 | if sys.byteorder != 'little': 28 | raise ImportError("Cozmo SDK doesn't support byte order '%s' - contact Anki support to request this", sys.byteorder) 29 | 30 | 31 | class CLADProtocol(asyncio.Protocol): 32 | '''Low level CLAD codec''' 33 | _send_mutex = Lock() 34 | 35 | clad_decode_union = None 36 | clad_encode_union = None 37 | _clad_log_which = None 38 | 39 | def __init__(self): 40 | super().__init__() 41 | 42 | self._buf = bytearray() 43 | self._abort_connection = False # abort connection on failed handshake, ignore subsequent messages! 44 | 45 | def connection_made(self, transport): 46 | self.transport = transport 47 | logger_protocol.debug('Connected to transport') 48 | 49 | def connection_lost(self, exc): 50 | logger_protocol.debug("Connnection to transport lost: %s" % exc) 51 | 52 | def data_received(self, data): 53 | self._buf.extend(data) 54 | # pull clad messages out 55 | 56 | while not self._abort_connection: 57 | msg = self.decode_msg() 58 | # must compare msg against None, not just "if not msg" as the latter 59 | # would match against any message with len==0 (which is the case 60 | # for deliberately empty messages where the tag alone is the signal). 61 | if msg is None: 62 | return 63 | name = msg.tag_name 64 | if self._clad_log_which is LOG_ALL or (self._clad_log_which is not None and name in self._clad_log_which): 65 | logger_protocol.debug('RECV %s', msg._data) 66 | self.msg_received(msg) 67 | 68 | def decode_msg(self): 69 | if len(self._buf) < 2: 70 | return None 71 | 72 | # TODO: handle error 73 | # messages are prefixed by a 2 byte length 74 | msg_size = struct.unpack_from('H', self._buf)[0] 75 | if len(self._buf) < 2 + msg_size: 76 | return None 77 | 78 | buf, self._buf = self._buf[2:2+msg_size], self._buf[2+msg_size:] 79 | 80 | try: 81 | return self.clad_decode_union.unpack(buf) 82 | except ValueError as e: 83 | logger_protocol.warn("Failed to decode CLAD message for buflen=%d: %s", len(buf), e) 84 | 85 | def eof_received(self): 86 | logger_protocol.info("EOF received on connection") 87 | 88 | def send_msg(self, msg, **params): 89 | if self.transport.is_closing(): 90 | return 91 | 92 | name = msg.__class__.__name__ 93 | msg = self.clad_encode_union(**{name: msg}) 94 | msg_buf = msg.pack() 95 | msg_size = struct.pack('H', len(msg_buf)) 96 | 97 | self._send_mutex.acquire() 98 | try: 99 | self.transport.write(msg_size) 100 | self.transport.write(msg_buf) 101 | if self._clad_log_which is LOG_ALL or (self._clad_log_which is not None and name in self._clad_log_which): 102 | logger_protocol.debug("SENT %s", msg) 103 | 104 | finally: 105 | self._send_mutex.release() 106 | 107 | def send_msg_new(self, msg): 108 | name = msg.__class__.__name__ 109 | return self.send_msg(name, msg) 110 | 111 | def msg_received(self, msg): 112 | pass 113 | 114 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: copy-clad dist examples license wheel vagrant installer 2 | 3 | version = $(shell perl -ne '/__version__ = "([^"]+)/ && print $$1;' src/cozmo/version.py) 4 | cladversion = $(shell perl -ne '/__version__ = "([^"]+)/ && print $$1;' ../cozmoclad/src/cozmoclad/__init__.py) 5 | 6 | copy-clad: 7 | rm -rf src/cozmo/_internal/clad/* 8 | rm -rf src/cozmo/_internal/msgbuffers/* 9 | cp -r ../../generated/cladPython/clad src/cozmo/_internal/ 10 | cp -r ../message-buffers/support/python/msgbuffers src/cozmo/_internal/ 11 | 12 | 13 | license_targets = src/cozmo/LICENSE.txt examples/LICENSE.txt 14 | example_targets = dist/cozmo_sdk_examples.tar.gz dist/cozmo_sdk_examples.zip 15 | 16 | example_filenames = $(shell cd examples && find . -name '*.py' -o -name '*.txt' -o -name '*.png' -o -name '*.md' -o -name '*.json') 17 | example_pathnames = $(shell find examples -name '*.py' -o -name '*.txt' -o -name '*.png' -o -name '*.md' -o -name '*.json') 18 | sdist_filename = dist/cozmo-$(version).tar.gz 19 | wheel_filename = dist/cozmo-$(version)-py3-none-any.whl 20 | 21 | license: $(license_targets) 22 | 23 | $(license_targets): LICENSE.txt 24 | for fn in $(license_targets); do \ 25 | cp LICENSE.txt $$fn; \ 26 | done 27 | 28 | $(sdist_filename): src/cozmo/LICENSE.txt $(shell find src/cozmo -name '*.py') 29 | python3 setup.py sdist 30 | 31 | $(wheel_filename): src/cozmo/LICENSE.txt $(shell find src/cozmo -name '*.py') 32 | python3 setup.py bdist_wheel 33 | 34 | dist/cozmo_sdk_examples.zip: examples/LICENSE.txt $(example_pathnames) 35 | rm -f dist/cozmo_sdk_examples.zip dist/cozmo_sdk_examples_$(version).zip 36 | rm -rf dist/cozmo_sdk_examples_$(version) 37 | mkdir dist/cozmo_sdk_examples_$(version) 38 | tar -C examples -c $(example_filenames) | tar -C dist/cozmo_sdk_examples_$(version) -xv 39 | cd dist && zip -r cozmo_sdk_examples.zip cozmo_sdk_examples_$(version) 40 | cd dist && zip -r cozmo_sdk_examples_$(version).zip cozmo_sdk_examples_$(version) 41 | 42 | dist/cozmo_sdk_examples.tar.gz: examples/LICENSE.txt $(example_pathnames) 43 | rm -f dist/cozmo_sdk_examples.tar.gz dist/cozmo_sdk_examples_$(version).tar.gz 44 | rm -rf dist/cozmo_sdk_examples_$(version) 45 | mkdir dist/cozmo_sdk_examples_$(version) 46 | tar -C examples -c $(example_filenames) | tar -C dist/cozmo_sdk_examples_$(version) -xv 47 | cd dist && tar -cvzf cozmo_sdk_examples.tar.gz cozmo_sdk_examples_$(version) 48 | cp -a dist/cozmo_sdk_examples.tar.gz dist/cozmo_sdk_examples_$(version).tar.gz 49 | 50 | examples: dist/cozmo_sdk_examples.tar.gz dist/cozmo_sdk_examples.zip 51 | 52 | dist/vagrant_bundle.tar.gz: $(sdist_filename) $(example_targets) 53 | rm -rf dist/vagrant_bundle 54 | mkdir dist/vagrant_bundle 55 | cp dist/cozmo_sdk_examples.tar.gz dist/vagrant_bundle/ 56 | cp vagrant/Vagrantfile dist/vagrant_bundle/ 57 | cp vagrant/setup-vm.sh dist/vagrant_bundle/ 58 | cd dist && tar -czvf vagrant_bundle.tar.gz vagrant_bundle 59 | cp -a dist/vagrant_bundle.tar.gz dist/vagrant_bundle_$(version).tar.gz 60 | 61 | dist/vagrant_bundle.zip: dist/vagrant_bundle.tar.gz 62 | cd dist && zip -r vagrant_bundle.zip vagrant_bundle/ 63 | cp -a dist/vagrant_bundle.zip dist/vagrant_bundle_$(version).zip 64 | 65 | vagrant: dist/vagrant_bundle.tar.gz dist/vagrant_bundle.zip 66 | 67 | dist: $(sdist_filename) $(wheel_filename) examples vagrant 68 | 69 | clad_wheel_filename = dist/cozmoclad-$(cladversion)-py3-none-any.whl 70 | $(clad_wheel_filename): 71 | make -C ../cozmoclad dist 72 | cp ../cozmoclad/$(clad_wheel_filename) $(clad_wheel_filename) 73 | 74 | installer_filename = sdk_installer_$(version)_clad_$(cladversion) 75 | installer: $(wheel_filename) $(clad_wheel_filename) 76 | mkdir -p dist/ 77 | mkdir -p dist/$(installer_filename) 78 | $(shell echo "#!/bin/bash\n\nworking_dir=\"\`dirname \\\"\$$0\\\"\`\"\n\npip3 uninstall -y cozmoclad\npip3 uninstall -y cozmo\npip3 install \"\$$working_dir/$(clad_wheel_filename)\"\npip3 install \"\$$working_dir/$(wheel_filename)\"" > dist/install.sh) 79 | tar -c $(wheel_filename) $(clad_wheel_filename) | tar -C dist/$(installer_filename) -xv 80 | mv dist/install.sh dist/$(installer_filename)/install 81 | chmod +x dist/$(installer_filename)/install 82 | cd dist && zip -r $(installer_filename).zip $(installer_filename) 83 | rm -rf dist/$(installer_filename) 84 | -------------------------------------------------------------------------------- /src/cozmo/song.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2018 Anki, Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License in the file LICENSE.txt or at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | ''' 16 | Song related classes, functions, events and values. 17 | ''' 18 | 19 | # __all__ should order by constants, event classes, other classes, functions. 20 | __all__ = ['NoteTypes', 'NoteDurations', 'SongNote'] 21 | 22 | import collections 23 | 24 | from . import logger 25 | 26 | from . import action 27 | from . import exceptions 28 | from . import event 29 | 30 | from ._clad import _clad_to_engine_iface, _clad_to_engine_cozmo, _clad_to_engine_anki, CladEnumWrapper 31 | 32 | # generate names for each CLAD defined Note Type 33 | class _NoteType(collections.namedtuple('_NoteType', 'name id')): 34 | # Tuple mapping between CLAD SongNoteType. name and ID 35 | # All instances will be members of NoteTypes 36 | 37 | # Keep _NoteType as lightweight as a normal namedtuple 38 | __slots__ = () 39 | 40 | def __str__(self): 41 | return 'NoteTypes.%s' % self.name 42 | 43 | 44 | class NoteTypes(CladEnumWrapper): 45 | """The possible values for an NoteType. 46 | 47 | A pitch between C2 and C3_Sharp can be specified, 48 | as well as a rest (for timed silence), giving 49 | cozmo a vocal range of slightly more than one 50 | octave. 51 | 52 | B_Flat and E_Flat are represented as their corresponding 53 | sharps. 54 | """ 55 | _clad_enum = _clad_to_engine_iface.SongNoteType 56 | _entry_type = _NoteType 57 | 58 | #: 59 | C2 = _entry_type("C2", _clad_enum.C2) 60 | #: 61 | C2_Sharp = _entry_type("C2_Sharp", _clad_enum.C2_Sharp) 62 | #: 63 | D2 = _entry_type("D2", _clad_enum.D2) 64 | #: 65 | D2_Sharp = _entry_type("D2_Sharp", _clad_enum.D2_Sharp) 66 | #: 67 | E2 = _entry_type("E2", _clad_enum.E2) 68 | #: 69 | F2 = _entry_type("F2", _clad_enum.F2) 70 | #: 71 | F2_Sharp = _entry_type("F2_Sharp", _clad_enum.F2_Sharp) 72 | #: 73 | G2 = _entry_type("G2", _clad_enum.G2) 74 | #: 75 | G2_Sharp = _entry_type("G2_Sharp", _clad_enum.G2_Sharp) 76 | #: 77 | A2 = _entry_type("A2", _clad_enum.A2) 78 | #: 79 | A2_Sharp = _entry_type("A2_Sharp", _clad_enum.A2_Sharp) 80 | #: 81 | B2 = _entry_type("B2", _clad_enum.B2) 82 | #: 83 | C3 = _entry_type("C3", _clad_enum.C3) 84 | #: 85 | C3_Sharp = _entry_type("C3_Sharp", _clad_enum.C3_Sharp) 86 | #: 87 | Rest = _entry_type("Rest", _clad_enum.Rest) 88 | 89 | NoteTypes._init_class(warn_on_missing_definitions=True) 90 | 91 | 92 | # generate names for each CLAD defined Note Duration 93 | class _NoteDuration(collections.namedtuple('_NoteDuration', 'name id')): 94 | # Tuple mapping between CLAD SongNoteDuration. name and ID 95 | # All instances will be members of NoteTypes 96 | 97 | # Keep _NoteDuration as lightweight as a normal namedtuple 98 | __slots__ = () 99 | 100 | def __str__(self): 101 | return 'NoteDurations.%s' % self.name 102 | 103 | 104 | class NoteDurations(CladEnumWrapper): 105 | """The possible values for a NoteDuration. 106 | """ 107 | _clad_enum = _clad_to_engine_iface.SongNoteDuration 108 | _entry_type = _NoteDuration 109 | 110 | #: 111 | Whole = _entry_type("Whole", _clad_enum.Whole) 112 | #: 113 | ThreeQuarter = _entry_type("ThreeQuarter", _clad_enum.ThreeQuarter) 114 | #: 115 | Half = _entry_type("Half", _clad_enum.Half) 116 | #: 117 | Quarter = _entry_type("Quarter", _clad_enum.Quarter) 118 | 119 | NoteDurations._init_class(warn_on_missing_definitions=True) 120 | 121 | 122 | class SongNote(_clad_to_engine_iface.SongNote): 123 | """Represents on element in a song. Consists of a :class:`cozmo.song.NoteTypes` which specifies 124 | either a pitch or rest, and a :class:`cozmo.song.NoteDurations` specifying the length of the 125 | note. 126 | """ 127 | def __init__(self, noteType=NoteTypes.C2, noteDuration=NoteDurations.Whole): 128 | super(SongNote, self).__init__(noteType.id, noteDuration.id) 129 | -------------------------------------------------------------------------------- /examples/lib/flask_helpers.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2016 Anki, Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License in the file LICENSE.txt or at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | '''Wrappers and helpers for using Flask with Cozmo. 16 | 17 | Flask is a Python web framework. remote_control_cozmo.py and other scripts may use 18 | these utility functions to interact with a web browser. 19 | ''' 20 | 21 | import logging 22 | import sys 23 | from threading import Thread 24 | import webbrowser 25 | from time import sleep 26 | from io import BytesIO 27 | try: 28 | from flask import make_response, Response, send_file 29 | except ImportError: 30 | sys.exit("Cannot import from flask: Do `pip3 install --user flask` to install") 31 | 32 | 33 | 34 | def _delayed_open_web_browser(url, delay, new=0, autoraise=True, specific_browser=None): 35 | ''' 36 | Spawn a thread and call sleep_and_open_web_browser from within it so that main thread can keep executing at the 37 | same time. Insert a small sleep before opening a web-browser 38 | this gives Flask a chance to start running before the browser starts requesting data from Flask. 39 | ''' 40 | 41 | def _sleep_and_open_web_browser(url, delay, new, autoraise, specific_browser): 42 | sleep(delay) 43 | browser = webbrowser 44 | 45 | # E.g. On OSX the following would use the Chrome browser app from that location 46 | # specific_browser = 'open -a /Applications/Google\ Chrome.app %s' 47 | if specific_browser: 48 | browser = webbrowser.get(specific_browser) 49 | 50 | browser.open(url, new=new, autoraise=autoraise) 51 | 52 | thread = Thread(target=_sleep_and_open_web_browser, 53 | kwargs=dict(url=url, new=new, autoraise=autoraise, delay=delay, specific_browser=specific_browser)) 54 | thread.daemon = True # Force to quit on main quitting 55 | thread.start() 56 | 57 | 58 | def run_flask(flask_app, host_ip="127.0.0.1", host_port=5000, enable_flask_logging=False, 59 | open_page=True, open_page_delay=1.0): 60 | ''' 61 | Run the Flask webserver on specified host and port 62 | optionally also open that same host:port page in your browser to connect 63 | ''' 64 | 65 | if not enable_flask_logging: 66 | # disable logging in Flask (it's enabled by default) 67 | log = logging.getLogger('werkzeug') 68 | log.setLevel(logging.ERROR) 69 | 70 | if open_page: 71 | # we add a delay (dispatched in another thread) to open the page so that the flask webserver is open 72 | # before the webpage requests any data 73 | _delayed_open_web_browser("http://" + host_ip + ":" + str(host_port), delay=open_page_delay) 74 | 75 | flask_app.run(host=host_ip, port=host_port, use_evalex=False, threaded=True) 76 | 77 | 78 | def shutdown_flask(request): 79 | func = request.environ.get('werkzeug.server.shutdown') 80 | if func is None: 81 | sys.exit('SDK Shutdown') 82 | func() 83 | 84 | 85 | def stream_video(streaming_function, url_root): 86 | return Response(streaming_function(url_root), mimetype='multipart/x-mixed-replace; boundary=frame') 87 | 88 | 89 | def make_uncached_response(in_file): 90 | response = make_response(in_file) 91 | response.headers['Pragma-Directive'] = 'no-cache' 92 | response.headers['Cache-Directive'] = 'no-cache' 93 | response.headers['Cache-Control'] = 'no-cache, no-store, must-revalidate' 94 | response.headers['Pragma'] = 'no-cache' 95 | response.headers['Expires'] = '0' 96 | return response 97 | 98 | 99 | def serve_pil_image(pil_img, serve_as_jpeg=False, jpeg_quality=70): 100 | '''Convert PIL image to relevant image file and send it''' 101 | img_io = BytesIO() 102 | 103 | if serve_as_jpeg: 104 | pil_img.save(img_io, 'JPEG', quality=jpeg_quality) 105 | img_io.seek(0) 106 | return make_uncached_response(send_file(img_io, mimetype='image/jpeg', 107 | add_etags=False)) 108 | else: 109 | pil_img.save(img_io, 'PNG') 110 | img_io.seek(0) 111 | return make_uncached_response(send_file(img_io, mimetype='image/png', 112 | add_etags=False)) 113 | -------------------------------------------------------------------------------- /CODESTYLE.md: -------------------------------------------------------------------------------- 1 | # Code Style Guide 2 | 3 | The code should generally follow [PEP8](https://www.python.org/dev/peps/pep-0008/) 4 | 5 | Code documentation should be written using Google style, which can be extracted 6 | using Sphinx: 7 | * http://google.github.io/styleguide/pyguide.html 8 | * http://sphinxcontrib-napoleon.readthedocs.io/en/latest/example_google.html 9 | 10 | 11 | Main style points to consider: 12 | 13 | ## Line Length 14 | 15 | PEP8 recommends a maximum line length of 80 characters. While some lines 16 | are easier to read if they're a bit longer than that, generally try to stay 17 | within the 80 character limit. 18 | 19 | Parameter lists can be wrapped and long strings can be split by enclosing them 20 | in parentheses: 21 | 22 | ````python 23 | long_string = ('First long line...' 24 | 'Second long line') 25 | ```` 26 | 27 | or by using triple quotes. 28 | 29 | ## White Space 30 | 31 | Indentation should be made using 4 space characters. 32 | 33 | * Two blank lines between class definitions and top-level functions 34 | * One blank line between methods (generally) 35 | 36 | Follow [PEP8 guidelines](https://www.python.org/dev/peps/pep-0008/#whitespace-in-expressions-and-statements) 37 | for whitespace in expressions and statements. 38 | 39 | ## Imports 40 | 41 | Import statements should be arranged in three blocks at the head of the file 42 | (though after the module documentation). Each block of imports should be in 43 | alphabetical order. 44 | 45 | 1. The first block should be Python-provided packages (eg. `sys`) 46 | 2. The second block should be third-party packages (eg. `numpy`) 47 | 3. The final block should be local packages and module (eg. `from . import camera`) 48 | 49 | ````python 50 | import os 51 | import sys 52 | 53 | import numpy 54 | 55 | from . import camera 56 | from . import event 57 | ```` 58 | 59 | Wildcard imports (`from module import *`) should not be used outside of tests. 60 | 61 | Additionally it is generally useful to avoid importing variables from modules 62 | directly into the local namespace (`from module import some_object`) - Doing 63 | so means you now have two references to to the same thing, which impedes 64 | mocking during unit tests. 65 | 66 | Better instead to import the module and reference a qualified name (`import module` 67 | and `module.some_object`). 68 | 69 | ## Names 70 | 71 | * Module level constants should be in CAPS 72 | * Class names should be CamelCase 73 | * Variables, attributes, functions, methods and properties should be lowercase_with_underscores 74 | * Variables, attributes, functions, methods and properties can be named with a 75 | leading underscore to indicate that they're "private" 76 | 77 | ## Documentation 78 | 79 | See http://sphinxcontrib-napoleon.readthedocs.io/en/latest/example_google.html 80 | for documentation examples. 81 | 82 | * Module-level documentation should appear first in the file, before imports 83 | * All public-facing classes, functions, methods etc should be documented 84 | * The first line of a docstring should contain the summary of what the item does. 85 | This should be followed by a blank line and the extended description, if any. 86 | * Use Sphinx-friendly markup (per the Google guide above) so that cross-references 87 | work automatically and examples are formatted correctly. 88 | 89 | ### Documenting properties and attributes 90 | 91 | For class and object attributes, use the `#:` comment syntax rather than a 92 | trailing docstring. Instance attributes can be documented in the `__init__` 93 | constructor. 94 | 95 | Properties should use a docstring like any other method, but should be 96 | written in the same style as an attribute, as that's how they'll be presented 97 | in Sphinx (ie. as `return_type: description`). 98 | 99 | Properties with setters must have the docstring on the getter rather than 100 | the setter. 101 | 102 | 103 | ```python 104 | class MyClass: 105 | '''One line summary of class. 106 | 107 | Docstring for constructor should appear in the class description 108 | 109 | Args: 110 | default_timeout (int): Default number of seconds for operations to 111 | wait for timeout. 112 | ''' 113 | #: string: Description of a class-level attribute. The description 114 | #: may span multiple lines as long as they all begin with #: 115 | class_level_attr = '' 116 | 117 | def __init__(self, default_timeout=None): 118 | #: int: The default number of seconds for operations to wait for timeout. 119 | self.default_timeout = default_timeout 120 | 121 | @property 122 | def timeout_enabled(self): 123 | '''bool: True if a value for :attr:`default_timeout` has been set.''' 124 | return self.default_timeout is not None 125 | ``` 126 | 127 | 128 | ## Exceptions 129 | 130 | Wherever practical, catch explicit exception classes rather than using 131 | a bare try/except statement (or matching `Exception`). 132 | 133 | To re-raise the original exception use `raise` by itself or 134 | `raise MyException() from exc` 135 | (rather than `raise exc`) to maintain the original stack trace. 136 | -------------------------------------------------------------------------------- /examples/tutorials/04_cubes_and_objects/09_custom_objects.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # Copyright (c) 2017 Anki, Inc. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License in the file LICENSE.txt or at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | '''This example demonstrates how you can define custom objects. 18 | 19 | The example defines several custom objects (2 cubes, a wall and a box). When 20 | Cozmo sees the markers for those objects he will report that he observed an 21 | object of that size and shape there. 22 | 23 | You can adjust the markers, marker sizes, and object sizes to fit whatever 24 | object you have and the exact size of the markers that you print out. 25 | ''' 26 | 27 | import time 28 | 29 | import cozmo 30 | from cozmo.objects import CustomObject, CustomObjectMarkers, CustomObjectTypes 31 | 32 | 33 | def handle_object_appeared(evt, **kw): 34 | # This will be called whenever an EvtObjectAppeared is dispatched - 35 | # whenever an Object comes into view. 36 | if isinstance(evt.obj, CustomObject): 37 | print("Cozmo started seeing a %s" % str(evt.obj.object_type)) 38 | 39 | 40 | def handle_object_disappeared(evt, **kw): 41 | # This will be called whenever an EvtObjectDisappeared is dispatched - 42 | # whenever an Object goes out of view. 43 | if isinstance(evt.obj, CustomObject): 44 | print("Cozmo stopped seeing a %s" % str(evt.obj.object_type)) 45 | 46 | 47 | def custom_objects(robot: cozmo.robot.Robot): 48 | # Add event handlers for whenever Cozmo sees a new object 49 | robot.add_event_handler(cozmo.objects.EvtObjectAppeared, handle_object_appeared) 50 | robot.add_event_handler(cozmo.objects.EvtObjectDisappeared, handle_object_disappeared) 51 | 52 | # define a unique cube (44mm x 44mm x 44mm) (approximately the same size as a light cube) 53 | # with a 30mm x 30mm Diamonds2 image on every face 54 | cube_obj = robot.world.define_custom_cube(CustomObjectTypes.CustomType00, 55 | CustomObjectMarkers.Diamonds2, 56 | 44, 57 | 30, 30, True) 58 | 59 | # define a unique cube (88mm x 88mm x 88mm) (approximately 2x the size of a light cube) 60 | # with a 50mm x 50mm Diamonds3 image on every face 61 | big_cube_obj = robot.world.define_custom_cube(CustomObjectTypes.CustomType01, 62 | CustomObjectMarkers.Diamonds3, 63 | 88, 64 | 50, 50, True) 65 | 66 | # define a unique wall (150mm x 120mm (x10mm thick for all walls) 67 | # with a 50mm x 30mm Circles2 image on front and back 68 | wall_obj = robot.world.define_custom_wall(CustomObjectTypes.CustomType02, 69 | CustomObjectMarkers.Circles2, 70 | 150, 120, 71 | 50, 30, True) 72 | 73 | # define a unique box (60mm deep x 140mm width x100mm tall) 74 | # with a different 30mm x 50mm image on each of the 6 faces 75 | box_obj = robot.world.define_custom_box(CustomObjectTypes.CustomType03, 76 | CustomObjectMarkers.Hexagons2, # front 77 | CustomObjectMarkers.Circles3, # back 78 | CustomObjectMarkers.Circles4, # top 79 | CustomObjectMarkers.Circles5, # bottom 80 | CustomObjectMarkers.Triangles2, # left 81 | CustomObjectMarkers.Triangles3, # right 82 | 60, 140, 100, 83 | 30, 50, True) 84 | 85 | if ((cube_obj is not None) and (big_cube_obj is not None) and 86 | (wall_obj is not None) and (box_obj is not None)): 87 | print("All objects defined successfully!") 88 | else: 89 | print("One or more object definitions failed!") 90 | return 91 | 92 | print("Show the above markers to Cozmo and you will see the related objects " 93 | "annotated in Cozmo's view window, you will also see print messages " 94 | "everytime a custom object enters or exits Cozmo's view.") 95 | 96 | print("Press CTRL-C to quit") 97 | while True: 98 | time.sleep(0.1) 99 | 100 | 101 | cozmo.run_program(custom_objects, use_3d_viewer=True, use_viewer=True) 102 | -------------------------------------------------------------------------------- /examples/tutorials/03_vision/04_exposure.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # Copyright (c) 2017 Anki, Inc. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License in the file LICENSE.txt or at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | '''Demonstrate the manual and auto exposure settings of Cozmo's camera. 18 | 19 | This example demonstrates the use of auto exposure and manual exposure for 20 | Cozmo's camera. The current camera settings are overlayed onto the camera 21 | viewer window. 22 | ''' 23 | 24 | 25 | import sys 26 | import time 27 | 28 | try: 29 | from PIL import ImageDraw, ImageFont 30 | import numpy as np 31 | except ImportError: 32 | sys.exit('run `pip3 install --user Pillow numpy` to run this example') 33 | 34 | import cozmo 35 | 36 | 37 | # A global string value to display in the camera viewer window to make it more 38 | # obvious what the example program is currently doing. 39 | example_mode = "" 40 | 41 | 42 | # An annotator for live-display of all of the camera info on top of the camera 43 | # viewer window. 44 | @cozmo.annotate.annotator 45 | def camera_info(image, scale, annotator=None, world=None, **kw): 46 | d = ImageDraw.Draw(image) 47 | bounds = [3, 0, image.width, image.height] 48 | 49 | camera = world.robot.camera 50 | text_to_display = "Example Mode: " + example_mode + "\n\n" 51 | text_to_display += "Fixed Camera Settings (Calibrated for this Robot):\n\n" 52 | text_to_display += 'focal_length: %s\n' % camera.config.focal_length 53 | text_to_display += 'center: %s\n' % camera.config.center 54 | text_to_display += 'fov: <%.3f, %.3f> degrees\n' % (camera.config.fov_x.degrees, 55 | camera.config.fov_y.degrees) 56 | text_to_display += "\n" 57 | text_to_display += "Valid exposure and gain ranges:\n\n" 58 | text_to_display += 'exposure: %s..%s\n' % (camera.config.min_exposure_time_ms, 59 | camera.config.max_exposure_time_ms) 60 | text_to_display += 'gain: %.3f..%.3f\n' % (camera.config.min_gain, 61 | camera.config.max_gain) 62 | text_to_display += "\n" 63 | text_to_display += "Current settings:\n\n" 64 | text_to_display += 'Auto Exposure Enabled: %s\n' % camera.is_auto_exposure_enabled 65 | text_to_display += 'Exposure: %s ms\n' % camera.exposure_ms 66 | text_to_display += 'Gain: %.3f\n' % camera.gain 67 | color_mode_str = "Color" if camera.color_image_enabled else "Grayscale" 68 | text_to_display += 'Color Mode: %s\n' % color_mode_str 69 | 70 | text = cozmo.annotate.ImageText(text_to_display, 71 | position=cozmo.annotate.TOP_LEFT, 72 | line_spacing=2, 73 | color="white", 74 | outline_color="black", full_outline=True) 75 | text.render(d, bounds) 76 | 77 | 78 | def demo_camera_exposure(robot: cozmo.robot.Robot): 79 | global example_mode 80 | 81 | # Ensure camera is in auto exposure mode and demonstrate auto exposure for 5 seconds 82 | camera = robot.camera 83 | camera.enable_auto_exposure() 84 | example_mode = "Auto Exposure" 85 | time.sleep(5) 86 | 87 | # Demonstrate manual exposure, linearly increasing the exposure time, while 88 | # keeping the gain fixed at a medium value. 89 | example_mode = "Manual Exposure - Increasing Exposure, Fixed Gain" 90 | fixed_gain = (camera.config.min_gain + camera.config.max_gain) * 0.5 91 | for exposure in range(camera.config.min_exposure_time_ms, camera.config.max_exposure_time_ms+1, 1): 92 | camera.set_manual_exposure(exposure, fixed_gain) 93 | time.sleep(0.1) 94 | 95 | # Demonstrate manual exposure, linearly increasing the gain, while keeping 96 | # the exposure fixed at a relatively low value. 97 | example_mode = "Manual Exposure - Increasing Gain, Fixed Exposure" 98 | fixed_exposure_ms = 10 99 | for gain in np.arange(camera.config.min_gain, camera.config.max_gain, 0.05): 100 | camera.set_manual_exposure(fixed_exposure_ms, gain) 101 | time.sleep(0.1) 102 | 103 | # Switch back to auto exposure, demo for a final 5 seconds and then return 104 | camera.enable_auto_exposure() 105 | example_mode = "Mode: Auto Exposure" 106 | time.sleep(5) 107 | 108 | 109 | def cozmo_program(robot: cozmo.robot.Robot): 110 | robot.world.image_annotator.add_annotator('camera_info', camera_info) 111 | 112 | # Demo with default grayscale camera images 113 | robot.camera.color_image_enabled = False 114 | demo_camera_exposure(robot) 115 | 116 | # Demo with color camera images 117 | robot.camera.color_image_enabled = True 118 | demo_camera_exposure(robot) 119 | 120 | 121 | cozmo.robot.Robot.drive_off_charger_on_connect = False # Cozmo can stay on his charger for this example 122 | cozmo.run_program(cozmo_program, use_viewer=True, force_viewer_on_top=True) 123 | -------------------------------------------------------------------------------- /docs/source/adb.rst: -------------------------------------------------------------------------------- 1 | .. _adb: 2 | 3 | #################### 4 | Android Debug Bridge 5 | #################### 6 | 7 | .. important:: Android Debug Bridge (adb) is required ONLY for those users pairing an Android mobile device with Cozmo. 8 | 9 | Android Debug Bridge (adb) is necessary in order for the Cozmo SDK to work with Android mobile devices. Please ensure adb is installed before attempting to run the Cozmo SDK with a paired Android device. 10 | 11 | ^^^^^^^^^^^^^^^^^^ 12 | macOS Installation 13 | ^^^^^^^^^^^^^^^^^^ 14 | 15 | 1. Type the following into a Terminal window (requires Homebrew to be installed):: 16 | 17 | brew tap caskroom/cask 18 | brew cask install android-platform-tools 19 | 20 | 2. Continue to :ref:`final-install` below to complete installation. 21 | 22 | ^^^^^^^^^^^^^^^^^^^^ 23 | Windows Installation 24 | ^^^^^^^^^^^^^^^^^^^^ 25 | 26 | 1. In your internet browser, navigate to this `link `__ and download file ``platform-tools-latest-windows.zip`` to your Downloads folder. 27 | 2. Open a File Explorer window to your Downloads folder and see that your downloaded file ``platform-tools-latest-windows.zip`` is there. 28 | 3. Open a new File Explorer window and create a new folder in ``C:\Users\your_name`` named ``Android``. Then, navigate into your new Android folder. You should now be inside folder ``C:\Users\your_name\Android``. 29 | 4. Move the zip file you downloaded in step 1, ``platform-tools-latest-windows.zip``, to your new Android folder at ``C:\Users\your_name\Android``. 30 | 5. Right-click the ``platform-tools-latest-windows.zip`` file in ``C:\Users\your_name\Android`` and select Extract All. 31 | 6. With File Explorer, navigate to ``C:\Users\your_name\Android\platform-tools-latest-windows\platform-tools`` and confirm that the adb is there. You will now add this path to your PATH environment variable in the next step. 32 | 7. Add adb to your PATH environment variable. 33 | 34 | a. Right-click the Start menu and select *System*. 35 | b. Select *Advanced System Settings -> Advanced -> Environment Variables*. 36 | c. Under *User Variables*, select *PATH* and click **Edit**. 37 | d. Under *Edit Environment Variables*, click **New** and add the path to the folder containing adb (e.g. ``C:\Users\your_name\Android\platform-tools-latest-windows\platform-tools``). Click OK on all dialog boxes to confirm your change. 38 | 39 | 8. Confirm that the PATH is correctly pointing to adb. 40 | 41 | a. Open new a Command Prompt window. (To find the Command Prompt, you may use the search box in the lower left-hand corner of your screen.) 42 | b. Type ``adb`` and adb instructions should print out. 43 | 44 | 9. Continue to :ref:`final-install` below to complete installation. 45 | 46 | ^^^^^^^^^^^^^^^^^^ 47 | Linux Installation 48 | ^^^^^^^^^^^^^^^^^^ 49 | 50 | 1. In your internet browser, navigate to this `link `__ and download file ``platform-tools-latest-linux.zip``. You may need to accept the license before downloading. 51 | 2. Navigate to the zip file download location (e.g., ~/Downloads) and extract the files. The files will be extracted to folder ``platform-tools``. 52 | 3. In your home directory, create folder ``android-sdk-linux``:: 53 | 54 | cd ~ 55 | mkdir android-sdk-linux 56 | 57 | 4. Move the extracted ``platform-tools`` folder to your new ``android-sdk-linux`` folder:: 58 | 59 | mv Downloads/platform-tools android-sdk-linux 60 | 61 | 5. Confirm you see adb inside ``platform-tools``:: 62 | 63 | cd android-sdk-linux/platform-tools 64 | ls adb 65 | 66 | 6. Add adb to your PATH. 67 | 68 | a. Edit your `~/.bashrc` file and add this line:: 69 | 70 | export PATH=${PATH}:~/android-sdk-linux/platform-tools 71 | 72 | b. Save `.bashrc` and then call:: 73 | 74 | source .bashrc 75 | 76 | c. Confirm that adb is in your PATH by calling the following command:: 77 | 78 | which adb 79 | 80 | d. The result of this command should be the path where adb is installed. 81 | 82 | 7. Continue to :ref:`final-install` below to complete installation. 83 | 84 | 85 | .. _final-install: 86 | 87 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 88 | Final Installation (All Platforms) 89 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 90 | 91 | 1. Enable USB Debugging on your phone. 92 | 93 | a. On Android devices: 94 | 95 | 1. Tap seven (7) times on the Build Number listed under *Settings -> About Phone*. 96 | 2. Then, under *Settings -> Developer Options*, enable USB debugging. 97 | 98 | b. On Amazon Kindle Fire: 99 | 100 | 1. Tap seven (7) times on the Serial Number listed under *Settings -> Device Options*. 101 | 2. Then, under *Settings -> Device Options -> Developer Options*, turn on Enable ADB. 102 | 103 | 2. Connect your Android device to your computer via USB. When the *Allow USB Debugging?* popup displays, tap **OK**. 104 | 3. At the command line, type this command to confirm that your device shows:: 105 | 106 | adb devices 107 | 108 | .. 109 | 110 | At least one device should show in the result, for example:: 111 | 112 | List of devices attached 113 | 88148a08 device 114 | 115 | If you are required to accept the connection request on the mobile device itself, a message will appear saying the device is unauthorized. For example:: 116 | 117 | List of devices attached 118 | 88148a08 unauthorized 119 | 120 | `Terms and Conditions `_ and `Privacy Policy `_ 121 | 122 | `Click here to return to the Anki Developer website. `_ -------------------------------------------------------------------------------- /docs/source/vagrant.rst: -------------------------------------------------------------------------------- 1 | .. _vagrant-guide: 2 | 3 | :orphan: 4 | 5 | ##################################### 6 | Alternate Install via Virtual Machine 7 | ##################################### 8 | 9 | .. important:: The installation steps on this page are intended only for people that are having difficulties installing the SDK using the main Installation Guide steps. 10 | 11 | If you have difficulties using the regular Installation Guide steps (e.g. you are using an unsupported Operating System / OS Version), then we also provide a self-contained VM (Virtual Machine) setup using Vagrant that you can install to run entirely inside VirtualBox. The steps are listed below. 12 | 13 | To use the Cozmo SDK, the Cozmo mobile app must be installed on your mobile device and that device must be tethered to a computer via USB cable. 14 | 15 | ^^^^^^^^^^^^ 16 | Installation 17 | ^^^^^^^^^^^^ 18 | 19 | """"""""""""" 20 | Prerequisites 21 | """"""""""""" 22 | 23 | * WiFi connection 24 | * An iOS or Android mobile device with the Cozmo app installed, connected to the computer via USB cable 25 | 26 | """"""" 27 | Install 28 | """"""" 29 | 30 | 1. Install `VirtualBox and the VirtualBox Extension Pack `_ from the official webpage. Both of these *must* be installed in order for Vagrant to work properly. 31 | 2. Install `Vagrant `_ from the official webpage. 32 | 3. Install the Cozmo app on your mobile device. 33 | 4. Plug the mobile device containing the Cozmo app into your computer. 34 | 5. For **Windows**: 35 | 36 | a. Download :verlink:`vagrant_bundle_0.0.0.zip `. 37 | b. Unzip the ``vagrant_bundle_***.zip`` file into a folder of your choosing. 38 | c. Open a Command Prompt window. 39 | 40 | 1. Enter the following commands:: 41 | 42 | cd (location you extracted the .zip file) 43 | cd vagrant_bundle 44 | 45 | 2. Enter the following command:: 46 | 47 | vagrant up 48 | 49 | .. important:: Wait for `vagrant up` to completely finish before continuing to the next step. 50 | 51 | d. Navigate to where the Virtual Machine is currently running. 52 | 53 | .. raw:: html 54 | 55 |
56 |
57 |

Note

58 |

The Virtual Machine is set up with the following credentials: 59 |

user - vagrant 60 |
password - vagrant

61 |
62 |
63 | 64 | | 65 | 66 | e. Within the VM, open xterm. Once xterm is open, run the following commands in order. Please wait for each command to finish before entering the next one. This step may take several minutes. :: 67 | 68 | /vagrant/setup-vm.sh 69 | 70 | .. important:: Be sure to accept the Android SDK license prompt before continuing. 71 | .. important:: If using an Android device, the device will will prompt with *"Allow USB Debugging?"*. Tap **OK** to allow this option. 72 | 73 | .. code-block:: python 74 | 75 | cd /vagrant/cozmo_sdk_examples_*** 76 | 77 | .. 78 | 79 | 6. For **macOS/Linux**: 80 | 81 | a. Download :verlink:`vagrant_bundle_0.0.0.tar.gz `. 82 | b. Open a Terminal window. 83 | 84 | 1. Enter the following commands:: 85 | 86 | cd (location you downloaded the vagrant_bundle_***.tar.gz file) 87 | tar -xzf vagrant_bundle_***.tar.gz 88 | cd vagrant_bundle 89 | 90 | 2. Enter the following command:: 91 | 92 | vagrant up 93 | 94 | .. important:: Wait for `vagrant up` to completely finish before continuing to the next step. 95 | 96 | d. Navigate to where the Virtual Machine is currently running. 97 | 98 | .. raw:: html 99 | 100 |
101 |
102 |

Note

103 |

The Virtual Machine is set up with the following credentials: 104 |

user - vagrant 105 |
password - vagrant

106 |
107 |
108 | 109 | | 110 | 111 | e. Within the VM, open xterm. Once xterm is open, run the following commands in order. Please wait for each command to finish before entering the next one. This step may take several minutes. :: 112 | 113 | /vagrant/setup-vm.sh 114 | 115 | .. important:: Be sure to accept the Android SDK license prompt before continuing. 116 | 117 | .. important:: If using an Android device, the device will will prompt with *"Allow USB Debugging?"*. Tap **OK** to allow this option. 118 | 119 | .. code-block:: python 120 | 121 | cd /vagrant/cozmo_sdk_examples_*** 122 | 123 | 7. Make sure Cozmo is powered on and charged. Connect to the Cozmo robot's WiFi from the mobile device and then connect to the Cozmo robot within the app. 124 | 8. Enter SDK mode on the app. 125 | 126 | a. On the Cozmo app, tap the gear icon at the top right corner to open the Settings menu. 127 | b. Swipe left to show the Cozmo SDK option and tap the **Enable SDK** button. 128 | 129 | 9. To run a program enter the following into the virtual machine's Terminal prompt:: 130 | 131 | ./program_name.py 132 | 133 | For example, to run the Hello World example program, you would type ``./hello_world.py``. 134 | 135 | .. important:: You must either relaunch with "vagrant up" or save your virtual machine's state when shutting down. Otherwise the /vagrant/ folder on the virtual machine will be empty on subsequent runs. 136 | 137 | ---- 138 | 139 | `Terms and Conditions `_ and `Privacy Policy `_ 140 | 141 | `Click here to return to the Anki Developer website. `_ 142 | -------------------------------------------------------------------------------- /src/cozmo/oled_face.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2016 Anki, Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License in the file LICENSE.txt or at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | ''' Cozmo's OLED screen that displays his face - related functions and values. 16 | ''' 17 | 18 | # __all__ should order by constants, event classes, other classes, functions. 19 | __all__ = ['dimensions', 'convert_pixels_to_screen_data', 20 | 'convert_image_to_screen_data'] 21 | 22 | 23 | SCREEN_WIDTH = 128 24 | SCREEN_HALF_HEIGHT = 32 25 | SCREEN_HEIGHT = SCREEN_HALF_HEIGHT * 2 26 | 27 | 28 | def dimensions(): 29 | '''Return the dimension (width, height) of the oled screen. 30 | 31 | Note: The screen is displayed interlaced, with only every other line displayed 32 | This alternates every time the image is changed (no longer than 30 seconds) 33 | to prevent screen burn-in. Therefore to ensure the image looks correct on 34 | either scan-line offset we use half the vertical resolution 35 | 36 | Returns: 37 | A tuple of ints (width, height) 38 | ''' 39 | return SCREEN_WIDTH, SCREEN_HALF_HEIGHT 40 | 41 | 42 | def convert_pixels_to_screen_data(pixel_data, image_width, image_height): 43 | '''Convert a sequence of pixel data to the correct format to display on Cozmo's face. 44 | 45 | Args: 46 | pixel_data (:class:`bytes`): sequence of pixel values, should be in binary (1s or 0s) 47 | image_width (int): width of the image defined by the pixel_data 48 | image_height (int): height of the image defined by the pixel_data 49 | 50 | Returns: 51 | A :class:`bytearray` object representing all of the pixels (8 pixels packed per byte) 52 | 53 | Raises: 54 | ValueError: Invalid Dimensions 55 | ValueError: Bad image_width 56 | ValueError: Bad image_height 57 | ''' 58 | 59 | if len(pixel_data) != (image_width * image_height): 60 | raise ValueError('Invalid Dimensions: len(pixel_data) {0} != image_width={1} * image_height={2} (== {3})'. 61 | format(len(pixel_data), image_width, image_height, image_width * image_height)) 62 | 63 | num_columns_per_pixel = int(SCREEN_WIDTH / image_width) 64 | num_rows_per_pixel = int(SCREEN_HEIGHT / image_height) 65 | 66 | if (image_width * num_columns_per_pixel) != SCREEN_WIDTH: 67 | raise ValueError('Bad image_width: image_width {0} must be an exact integer divisor of {1}'. 68 | format(image_width, SCREEN_WIDTH)) 69 | 70 | if (image_height * num_rows_per_pixel) != SCREEN_HEIGHT: 71 | raise ValueError('Bad image_height: image_height {0} must be an exact integer divisor of {1}'. 72 | format(image_height, SCREEN_HEIGHT)) 73 | 74 | pixel_chunks = zip(*[iter(pixel_data)] * 8) # convert into 8 pixel chunks - we'll pack each as 1 byte later 75 | pixel_chunks_per_row = int(SCREEN_WIDTH / 8) # 8 pixels per byte (pixel-chunk) 76 | 77 | result_bytes = bytearray() 78 | 79 | x = 0 80 | y = 0 81 | for pixel_chunk in pixel_chunks: 82 | # convert the 8 pixels in the chunk into bits to write out 83 | # write each pixel bit num_columns_per_pixel times in a row 84 | pixel_byte = 0 85 | for pixel in pixel_chunk: 86 | for _ in range(num_columns_per_pixel): 87 | pixel_byte <<= 1 88 | pixel_byte += pixel 89 | x += 1 90 | if (x % 8) == 0: 91 | result_bytes.append(pixel_byte) 92 | pixel_byte = 0 93 | 94 | # check if this is the end of a row 95 | if x == SCREEN_WIDTH: 96 | x = 0 97 | y += 1 98 | 99 | if (x == 0) and (num_rows_per_pixel > 0): 100 | # at the end of a row - copy that row for every extra row-per-pixel 101 | for _ in range(num_rows_per_pixel-1): 102 | start_of_last_row = len(result_bytes) - pixel_chunks_per_row 103 | result_bytes.extend(result_bytes[start_of_last_row:]) 104 | 105 | return result_bytes 106 | 107 | 108 | def convert_image_to_screen_data(image, invert_image=False, pixel_threshold=127): 109 | ''' Convert an image into the correct format to display on Cozmo's face. 110 | 111 | Args: 112 | image (:class:`~PIL.Image.Image`): The image to display on Cozmo's face 113 | invert_image (bool): If true then pixels darker than the threshold are set on 114 | pixel_threshold (int): The grayscale threshold for what to consider on or off (0..255) 115 | 116 | Returns: 117 | A :class:`bytearray` object representing all of the pixels (8 pixels packed per byte) 118 | ''' 119 | 120 | # convert to grayscale 121 | grayscale_image = image.convert('L') 122 | 123 | # convert to binary white/black (1/0) 124 | if invert_image: 125 | def pixel_func(x): return 1 if x <= pixel_threshold else 0 126 | else: 127 | def pixel_func(x): return 1 if x >= pixel_threshold else 0 128 | bw = grayscale_image.point(pixel_func, '1') 129 | 130 | # convert to a flattened 1D bytes object of pixel values (1s or 0s in this case) 131 | pixel_data = bytes(bw.getdata()) 132 | 133 | return convert_pixels_to_screen_data(pixel_data, image.width, image.height) 134 | -------------------------------------------------------------------------------- /docs/source/images/custom_markers/LICENSE.txt: -------------------------------------------------------------------------------- 1 | Anki, Inc. Image License Agreement Version 1.0 (last updated March 28, 2017) 2 | 3 | This Image License Agreement (this "Agreement") governs the terms and conditions of your access to and use of Licensed Materials (as defined below), and is made between you, as an individual or entity ("you"), and Anki, Inc. ("we," "us" or "Licensor"). You accept and agree to be bound by this Agreement by your access to or use of any of the Licensed Materials. 4 | 5 | The "Licensed Materials" are the digital images that we make available to you from time to time in connection with this Agreement. 6 | 7 | 1. License. Subject to the terms and conditions of this Agreement, we hereby grant you a limited, revocable, worldwide, fully-paid, royalty free, non-exclusive, non-transferable copyright license during the term of this Agreement to access, copy, display, perform, modify the size of, and distribute, in any of the Licensed Materials, in each case: (A) solely in connection with your use of the Cozmo SDK in accordance with our separate SDK license agreement(s) or the applicable Anki hardware products (e.g. Cozmo) and/or the Cozmo App, and (B) only provided that you comply with the Anki Terms of Use at www.anki.com/terms and any other terms that may apply to the Cozmo device and/or Cozmo mobile application and that we may from time to time modify. Licensee may not sublicense any of the foregoing rights, except for the right to access, copy, display perform and distribute the Licensed Materials only in connection with the SDK in an app created by the Licensee. For clarity, this license does not include the right to commercially distribute the Licensed Materials in print form. 8 | 9 | 2. Reservation. Licensor (or its suppliers) owns and retains all right, title, and interest in and to each of the Licensed Materials worldwide including, but not limited to, ownership of all copyrights and other intellectual property rights therein. We reserve all rights not explicitly licensed in this Agreement. 10 | 11 | 3. DISCLAIMER OF WARRANTY AND LIMITATION OF LIABILITY. THE LICENSED MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NONINFRINGEMENT. IN NO EVENT WILL LICENSOR BE LIABLE TO YOU OR TO ANY THIRD PARTY FOR ANY DIRECT, INDIRECT, SPECIAL, INCIDENTAL, PUNITIVE OR CONSEQUENTIAL DAMAGES, OR LOST REVENUE, SAVINGS OR PROFITS, WHETHER BASED ON BREACH OF CONTRACT, TORT (INCLUDING NEGLIGENCE) OR OTHERWISE, ARISING FROM OR IN CONNECTION WITH ANY OF THE LICENSED MATERIALS, WHETHER OR NOT THAT PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 12 | 13 | 4. Indemnification. You will defend, indemnify and hold harmless Licensor and its officers, directors, shareholders, employees, and agents from any loss, liability, cost or expense, including attorneys' fees ("Liabilities") that arises from any claim, action or proceeding in connection with your use of the Licensed Materials or your breach of this Agreement. You shall have control of the defense and all related settlement negotiations for such claim, action or proceeding; provided that we shall have the right to consent to any settlement or entry of judgment, such consent not to be unreasonably withheld, and we may participate in such defense using our own counsel at our own expense. 14 | 15 | 5. Termination. You may terminate this Agreement at any time by deleting or destroying all copies of the Licensed Materials that you possess or control. We may terminate this Agreement and/or your license to any or all of the Licensed Materials at any time without prior notice to you. In case of termination, you must cease all access and use of, and delete or destroy, all copies of the Licensed Materials that you possess or control. Sections 2 through 8 of this Agreement will survive termination of this Agreement. 16 | 17 | 6. Modifications to this Agreement and Licensed Materials. We may amend this Agreement at any time by posting an amended version online and/or sending information regarding the amendment to your email address of record with us. You shall be deemed to have accepted such amendments by continuing to access and/or use any Licensed Materials after such amendments have been posted or information regarding such amendments has been sent to you. If you do not agree to any of such changes, you may terminate this Agreement and immediately cease all access to and use of Licensed Materials. You agree that such termination will be your exclusive remedy in such event. No other waiver or modification of this Agreement shall be valid unless in writing and signed by both parties. We also reserve the right at any time and from time to time to modify or discontinue all or any portion of any Licensed Materials without notice to you. We shall not be liable to you or any third party should we exercise such rights. 18 | 19 | 7. Assignment. You may not assign this Agreement, in whole or in part, without our prior written consent, and any attempt by you to assign this Agreement without such consent shall be void. Subject to the foregoing, this Agreement shall benefit and bind both parties, and their successors and permitted assigns. 20 | 21 | 8. General. You shall comply with all laws, rules and regulations applicable to your activities under this Agreement. This Agreement shall be governed by and construed in accordance with the laws of the State of California, U.S.A., except for its conflicts of laws principles. The application of the United Nations Convention on Contracts for the International Sale of Goods is expressly excluded. This Agreement will not be construed to create or imply any partnership, agency or joint venture between the parties. If any provision of this Agreement is found illegal or unenforceable, it will be enforced to the maximum extent permissible, and the legality and enforceability of the other provisions of this Agreement will not be affected. This Agreement is the complete agreement between the parties with respect to its subject matter, and supersedes any prior agreements and communications (both written and oral) regarding such subject matter. 22 | -------------------------------------------------------------------------------- /src/cozmo/assets/LICENSE.txt: -------------------------------------------------------------------------------- 1 | Anki, Inc. Image and 3D Model License Agreement Version 1.0 (last updated March 28, 2017) 2 | 3 | This Image and 3D Model License Agreement (this "Agreement") governs the terms and conditions of your access to and use of Licensed Materials (as defined below), and is made between you, as an individual or entity ("you"), and Anki, Inc. ("we," "us" or "Licensor"). You accept and agree to be bound by this Agreement by your access to or use of any of the Licensed Materials. 4 | 5 | The "Licensed Materials" are the digital images, and 3D models, that we make available to you from time to time in connection with this Agreement. 6 | 7 | 1. License. Subject to the terms and conditions of this Agreement, we hereby grant you a limited, revocable, worldwide, fully-paid, royalty free, non-exclusive, non-transferable copyright license during the term of this Agreement to access, copy, display, perform, modify the size of, and distribute, in any of the Licensed Materials, in each case: (A) solely in connection with your use of the Cozmo SDK in accordance with our separate SDK license agreement(s) or the applicable Anki hardware products (e.g. Cozmo) and/or the Cozmo App, and (B) only provided that you comply with the Anki Terms of Use at www.anki.com/terms and any other terms that may apply to the Cozmo device and/or Cozmo mobile application and that we may from time to time modify. Licensee may not sublicense any of the foregoing rights, except for the right to access, copy, display perform and distribute the Licensed Materials only in connection with the SDK in an app created by the Licensee. For clarity, this license does not include the right to commercially distribute the Licensed Materials in print form. 8 | 9 | 2. Reservation. Licensor (or its suppliers) owns and retains all right, title, and interest in and to each of the Licensed Materials worldwide including, but not limited to, ownership of all copyrights and other intellectual property rights therein. We reserve all rights not explicitly licensed in this Agreement. 10 | 11 | 3. DISCLAIMER OF WARRANTY AND LIMITATION OF LIABILITY. THE LICENSED MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NONINFRINGEMENT. IN NO EVENT WILL LICENSOR BE LIABLE TO YOU OR TO ANY THIRD PARTY FOR ANY DIRECT, INDIRECT, SPECIAL, INCIDENTAL, PUNITIVE OR CONSEQUENTIAL DAMAGES, OR LOST REVENUE, SAVINGS OR PROFITS, WHETHER BASED ON BREACH OF CONTRACT, TORT (INCLUDING NEGLIGENCE) OR OTHERWISE, ARISING FROM OR IN CONNECTION WITH ANY OF THE LICENSED MATERIALS, WHETHER OR NOT THAT PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 12 | 13 | 4. Indemnification. You will defend, indemnify and hold harmless Licensor and its officers, directors, shareholders, employees, and agents from any loss, liability, cost or expense, including attorneys' fees ("Liabilities") that arises from any claim, action or proceeding in connection with your use of the Licensed Materials or your breach of this Agreement. You shall have control of the defense and all related settlement negotiations for such claim, action or proceeding; provided that we shall have the right to consent to any settlement or entry of judgment, such consent not to be unreasonably withheld, and we may participate in such defense using our own counsel at our own expense. 14 | 15 | 5. Termination. You may terminate this Agreement at any time by deleting or destroying all copies of the Licensed Materials that you possess or control. We may terminate this Agreement and/or your license to any or all of the Licensed Materials at any time without prior notice to you. In case of termination, you must cease all access and use of, and delete or destroy, all copies of the Licensed Materials that you possess or control. Sections 2 through 8 of this Agreement will survive termination of this Agreement. 16 | 17 | 6. Modifications to this Agreement and Licensed Materials. We may amend this Agreement at any time by posting an amended version online and/or sending information regarding the amendment to your email address of record with us. You shall be deemed to have accepted such amendments by continuing to access and/or use any Licensed Materials after such amendments have been posted or information regarding such amendments has been sent to you. If you do not agree to any of such changes, you may terminate this Agreement and immediately cease all access to and use of Licensed Materials. You agree that such termination will be your exclusive remedy in such event. No other waiver or modification of this Agreement shall be valid unless in writing and signed by both parties. We also reserve the right at any time and from time to time to modify or discontinue all or any portion of any Licensed Materials without notice to you. We shall not be liable to you or any third party should we exercise such rights. 18 | 19 | 7. Assignment. You may not assign this Agreement, in whole or in part, without our prior written consent, and any attempt by you to assign this Agreement without such consent shall be void. Subject to the foregoing, this Agreement shall benefit and bind both parties, and their successors and permitted assigns. 20 | 21 | 8. General. You shall comply with all laws, rules and regulations applicable to your activities under this Agreement. This Agreement shall be governed by and construed in accordance with the laws of the State of California, U.S.A., except for its conflicts of laws principles. The application of the United Nations Convention on Contracts for the International Sale of Goods is expressly excluded. This Agreement will not be construed to create or imply any partnership, agency or joint venture between the parties. If any provision of this Agreement is found illegal or unenforceable, it will be enforced to the maximum extent permissible, and the legality and enforceability of the other provisions of this Agreement will not be affected. This Agreement is the complete agreement between the parties with respect to its subject matter, and supersedes any prior agreements and communications (both written and oral) regarding such subject matter. 22 | -------------------------------------------------------------------------------- /src/cozmo/tkview.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2016-2017 Anki, Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License in the file LICENSE.txt or at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | '''This module provides a simple GUI viewer for Cozmo's camera. 16 | 17 | It uses Tkinter, the standard Python GUI toolkit which is optionally available 18 | on most platforms, and also depends on the Pillow and numpy libraries for 19 | image processing. 20 | 21 | 22 | See the online SDK documentation for details on how to install these extra 23 | packages on your platform. 24 | 25 | The easiest way to make use of this viewer is to call 26 | :func:`cozmo.run.connect_with_tkviewer`. 27 | 28 | Warning: 29 | This package requires Python to have Tkinter installed to display the GUI. 30 | ''' 31 | 32 | 33 | # __all__ should order by constants, event classes, other classes, functions. 34 | __all__ = ['TkImageViewer'] 35 | 36 | import cozmo 37 | import collections 38 | import functools 39 | import queue 40 | import platform 41 | import time 42 | 43 | from PIL import Image, ImageDraw, ImageTk 44 | import tkinter 45 | 46 | from . import world 47 | 48 | 49 | class TkThreadable: 50 | '''A mixin for adding threadsafe calls to tkinter methods.''' 51 | #pylint: disable=no-member 52 | # no-member errors are raised in pylint regarding members/methods called but not defined in our mixin. 53 | def __init__(self, *a, **kw): 54 | self._thread_queue = queue.Queue() 55 | self.after(50, self._thread_call_dispatch) 56 | 57 | def call_threadsafe(self, method, *a, **kw): 58 | self._thread_queue.put((method, a, kw)) 59 | 60 | def _thread_call_dispatch(self): 61 | while True: 62 | try: 63 | method, a, kw = self._thread_queue.get(block=False) 64 | self.after_idle(method, *a, **kw) 65 | except queue.Empty: 66 | break 67 | self.after(50, self._thread_call_dispatch) 68 | 69 | 70 | class TkImageViewer(tkinter.Frame, TkThreadable): 71 | '''Simple Tkinter camera viewer.''' 72 | 73 | # TODO: rewrite this whole thing. Make a generic camera widget 74 | # that can be used in other Tk applications. Also handle resizing 75 | # the window properly. 76 | def __init__(self, 77 | tk_root=None, refresh_interval=10, image_scale = 2, 78 | window_name = "CozmoView", force_on_top=True): 79 | if tk_root is None: 80 | tk_root = tkinter.Tk() 81 | tkinter.Frame.__init__(self, tk_root) 82 | TkThreadable.__init__(self) 83 | self._img_queue = collections.deque(maxlen=1) 84 | 85 | self._refresh_interval = refresh_interval 86 | self.scale = image_scale 87 | self.width = None 88 | self.height = None 89 | 90 | self.tk_root = tk_root 91 | tk_root.wm_title(window_name) 92 | # Tell the TK root not to resize based on the contents of the window. 93 | # Necessary to get the resizing to function properly 94 | tk_root.pack_propagate(False) 95 | # Set the starting window size 96 | tk_root.geometry('{}x{}'.format(720, 540)) 97 | 98 | self.label = tkinter.Label(self.tk_root,image=None) 99 | self.tk_root.protocol("WM_DELETE_WINDOW", self._delete_window) 100 | self._isRunning = True 101 | self.robot = None 102 | self.handler = None 103 | self._first_image = True 104 | tk_root.aspect(4,3,4,3) 105 | 106 | if force_on_top: 107 | # force window on top of all others, regardless of focus 108 | tk_root.wm_attributes("-topmost", 1) 109 | 110 | self.tk_root.bind("", self.configure) 111 | self._repeat_draw_frame() 112 | 113 | async def connect(self, coz_conn): 114 | self.robot = await coz_conn.wait_for_robot() 115 | self.robot.camera.image_stream_enabled = True 116 | self.handler = self.robot.world.add_event_handler( 117 | world.EvtNewCameraImage, self.image_event) 118 | 119 | def disconnect(self): 120 | if self.handler: 121 | self.handler.disable() 122 | self.call_threadsafe(self.quit) 123 | 124 | # The base class configure doesn't take an event 125 | #pylint: disable=arguments-differ 126 | def configure(self, event): 127 | if event.width < 50 or event.height < 50: 128 | return 129 | self.height = event.height 130 | self.width = event.width 131 | 132 | 133 | def image_event(self, evt, *, image, **kw): 134 | if self._first_image or self.width is None: 135 | img = image.annotate_image(scale=self.scale) 136 | else: 137 | img = image.annotate_image(fit_size=(self.width, self.height)) 138 | self._img_queue.append(img) 139 | 140 | def _delete_window(self): 141 | self.tk_root.destroy() 142 | self.quit() 143 | self._isRunning = False 144 | 145 | def _draw_frame(self): 146 | if ImageTk is None: 147 | return 148 | 149 | try: 150 | image = self._img_queue.popleft() 151 | except IndexError: 152 | # no new image 153 | return 154 | 155 | self._first_image = False 156 | photoImage = ImageTk.PhotoImage(image) 157 | 158 | self.label.configure(image=photoImage) 159 | self.label.image = photoImage 160 | # Dynamically expand the image to fit the window. And fill in both X and Y directions. 161 | self.label.pack(fill=tkinter.BOTH, expand=True) 162 | 163 | def _repeat_draw_frame(self, event=None): 164 | self._draw_frame() 165 | self.after(self._refresh_interval, self._repeat_draw_frame) 166 | -------------------------------------------------------------------------------- /examples/tutorials/06_actions/01_parallel_actions.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # Copyright (c) 2016 Anki, Inc. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License in the file LICENSE.txt or at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | '''Parallel Action Examples. 18 | 19 | This script shows how to run actions in parallel instead of in sequence, 20 | how some actions will fail to run if another action is already using that 21 | animation track, and how you can abort individual, or all, actions. 22 | ''' 23 | 24 | import sys 25 | import time 26 | 27 | try: 28 | from PIL import Image 29 | except ImportError: 30 | sys.exit("Cannot import from PIL: Do `pip3 install --user Pillow` to install") 31 | 32 | import cozmo 33 | from cozmo.util import degrees, distance_mm, speed_mmps 34 | 35 | 36 | # load an image to display on Cozmo's face 37 | face_image = Image.open("../../face_images/cozmosdk.png") 38 | # resize to fit on Cozmo's face screen 39 | face_image = face_image.resize(cozmo.oled_face.dimensions(), Image.BICUBIC) 40 | # convert the image to the format used by the oled screen 41 | face_image = cozmo.oled_face.convert_image_to_screen_data(face_image, 42 | invert_image=True) 43 | 44 | 45 | def example1_lift_head(robot: cozmo.robot.Robot): 46 | cozmo.logger.info("----------------------------------------") 47 | cozmo.logger.info("Example 1: Move Lift and Head in Parallel") 48 | cozmo.logger.info("First, move the lift and head down, in sequence.") 49 | robot.set_head_angle(cozmo.robot.MIN_HEAD_ANGLE).wait_for_completed() 50 | robot.set_lift_height(0.0).wait_for_completed() 51 | 52 | cozmo.logger.info("Now, move the lift and head back up, in parallel " 53 | "- we no longer have to wait for the 1st action to complete " 54 | "before starting the 2nd one because the 2nd action is in_parallel") 55 | action1 = robot.set_head_angle(cozmo.robot.MAX_HEAD_ANGLE) 56 | action2 = robot.set_lift_height(1.0, in_parallel=True) 57 | action1.wait_for_completed() 58 | action2.wait_for_completed() 59 | cozmo.logger.info("action1 = %s", action1) 60 | cozmo.logger.info("action2 = %s", action2) 61 | 62 | 63 | def example2_conflicting_actions(robot: cozmo.robot.Robot): 64 | cozmo.logger.info("----------------------------------------") 65 | cozmo.logger.info("Example 2: Conflicting actions.") 66 | cozmo.logger.info("Try to drive straight and turn in parallel. This is not " 67 | "allowed, as both actions require use of the wheels, so the 2nd action " 68 | "will report failure due to tracks_locked.") 69 | action1 = robot.drive_straight(distance_mm(50), speed_mmps(25), should_play_anim=False, in_parallel=True) 70 | action2 = robot.turn_in_place(degrees(90), in_parallel=True) 71 | action2.wait_for_completed() 72 | cozmo.logger.info("action2 = %s", action2) 73 | action1.wait_for_completed() 74 | cozmo.logger.info("action1 = %s", action1) 75 | 76 | 77 | def example3_abort_one_action(robot: cozmo.robot.Robot): 78 | cozmo.logger.info("----------------------------------------") 79 | cozmo.logger.info("Example 3: Abort some parallel actions.") 80 | cozmo.logger.info("Start multiple parallel actions:") 81 | action1 = robot.set_lift_height(0.0, in_parallel=True) 82 | action2 = robot.set_head_angle(cozmo.robot.MIN_HEAD_ANGLE, duration=6.0, in_parallel=True) 83 | action3 = robot.drive_straight(distance_mm(75), speed_mmps(25), should_play_anim=False, in_parallel=True) 84 | action4 = robot.display_oled_face_image(face_image, 30000.0) # Note: face image is in_parallel by default 85 | # Lift-lowering is aborted immediately 86 | action1.abort(log_abort_messages=True) 87 | # Head-lowering is aborted shortly afterwards 88 | time.sleep(0.1) 89 | action2.abort(log_abort_messages=True) 90 | # Image on Cozmo's face is aborted another 2 seconds later 91 | time.sleep(2) 92 | action4.abort(log_abort_messages=True) 93 | # We wait for the one remaining action to complete 94 | action3.wait_for_completed() 95 | # Only action3 should succeed (as long as Cozmo had enough space to drive) 96 | cozmo.logger.info("action1 = %s", action1) 97 | cozmo.logger.info("action2 = %s", action2) 98 | cozmo.logger.info("action3 = %s", action3) 99 | cozmo.logger.info("action4 = %s", action4) 100 | 101 | 102 | def example4_abort_all_actions(robot: cozmo.robot.Robot): 103 | cozmo.logger.info("----------------------------------------") 104 | cozmo.logger.info("Example 4: Abort all parallel actions.") 105 | cozmo.logger.info("Start multiple parallel actions:") 106 | action1 = robot.set_lift_height(0.0, in_parallel=True, duration=6.0) 107 | action2 = robot.set_head_angle(cozmo.robot.MAX_HEAD_ANGLE, duration=6.0, in_parallel=True) 108 | action3 = robot.drive_straight(distance_mm(75), speed_mmps(25), should_play_anim=False, in_parallel=True) 109 | action4 = robot.display_oled_face_image(face_image, 30000.0) # Note: face image is in_parallel by default 110 | # wait two seconds and abort everything 111 | time.sleep(2) 112 | robot.abort_all_actions(log_abort_messages=True) 113 | # wait for results to come back for all actions 114 | robot.wait_for_all_actions_completed() 115 | # All actions should have aborted 116 | cozmo.logger.info("action1 res = %s", action1) 117 | cozmo.logger.info("action2 res = %s", action2) 118 | cozmo.logger.info("action3 res = %s", action3) 119 | cozmo.logger.info("action4 res = %s", action4) 120 | 121 | 122 | def cozmo_program(robot: cozmo.robot.Robot): 123 | example1_lift_head(robot) 124 | example2_conflicting_actions(robot) 125 | example3_abort_one_action(robot) 126 | example4_abort_all_actions(robot) 127 | cozmo.logger.info("----------------------------------------") 128 | 129 | 130 | cozmo.run_program(cozmo_program) 131 | --------------------------------------------------------------------------------