Browse Source

Add python pycharm project

Development
Tobi 5 years ago
parent
commit
bacd6125d5
100 changed files with 30157 additions and 0 deletions
  1. 13
    0
      Cozmo_LineFollow/.idea/Cozmo_LineFollow.iml
  2. 7
    0
      Cozmo_LineFollow/.idea/misc.xml
  3. 8
    0
      Cozmo_LineFollow/.idea/modules.xml
  4. 252
    0
      Cozmo_LineFollow/.idea/workspace.xml
  5. 1
    0
      Cozmo_LineFollow/venv/Lib/site-packages/cozmo-1.4.10.dist-info/INSTALLER
  6. 180
    0
      Cozmo_LineFollow/venv/Lib/site-packages/cozmo-1.4.10.dist-info/LICENSE.txt
  7. 42
    0
      Cozmo_LineFollow/venv/Lib/site-packages/cozmo-1.4.10.dist-info/METADATA
  8. 78
    0
      Cozmo_LineFollow/venv/Lib/site-packages/cozmo-1.4.10.dist-info/RECORD
  9. 5
    0
      Cozmo_LineFollow/venv/Lib/site-packages/cozmo-1.4.10.dist-info/WHEEL
  10. 1
    0
      Cozmo_LineFollow/venv/Lib/site-packages/cozmo-1.4.10.dist-info/top_level.txt
  11. 1
    0
      Cozmo_LineFollow/venv/Lib/site-packages/cozmo-1.4.10.dist-info/zip-safe
  12. 180
    0
      Cozmo_LineFollow/venv/Lib/site-packages/cozmo/LICENSE.txt
  13. 86
    0
      Cozmo_LineFollow/venv/Lib/site-packages/cozmo/__init__.py
  14. BIN
      Cozmo_LineFollow/venv/Lib/site-packages/cozmo/__pycache__/__init__.cpython-36.pyc
  15. BIN
      Cozmo_LineFollow/venv/Lib/site-packages/cozmo/__pycache__/_clad.cpython-36.pyc
  16. BIN
      Cozmo_LineFollow/venv/Lib/site-packages/cozmo/__pycache__/action.cpython-36.pyc
  17. BIN
      Cozmo_LineFollow/venv/Lib/site-packages/cozmo/__pycache__/anim.cpython-36.pyc
  18. BIN
      Cozmo_LineFollow/venv/Lib/site-packages/cozmo/__pycache__/annotate.cpython-36.pyc
  19. BIN
      Cozmo_LineFollow/venv/Lib/site-packages/cozmo/__pycache__/audio.cpython-36.pyc
  20. BIN
      Cozmo_LineFollow/venv/Lib/site-packages/cozmo/__pycache__/base.cpython-36.pyc
  21. BIN
      Cozmo_LineFollow/venv/Lib/site-packages/cozmo/__pycache__/behavior.cpython-36.pyc
  22. BIN
      Cozmo_LineFollow/venv/Lib/site-packages/cozmo/__pycache__/camera.cpython-36.pyc
  23. BIN
      Cozmo_LineFollow/venv/Lib/site-packages/cozmo/__pycache__/clad_protocol.cpython-36.pyc
  24. BIN
      Cozmo_LineFollow/venv/Lib/site-packages/cozmo/__pycache__/conn.cpython-36.pyc
  25. BIN
      Cozmo_LineFollow/venv/Lib/site-packages/cozmo/__pycache__/event.cpython-36.pyc
  26. BIN
      Cozmo_LineFollow/venv/Lib/site-packages/cozmo/__pycache__/exceptions.cpython-36.pyc
  27. BIN
      Cozmo_LineFollow/venv/Lib/site-packages/cozmo/__pycache__/faces.cpython-36.pyc
  28. BIN
      Cozmo_LineFollow/venv/Lib/site-packages/cozmo/__pycache__/lights.cpython-36.pyc
  29. BIN
      Cozmo_LineFollow/venv/Lib/site-packages/cozmo/__pycache__/nav_memory_map.cpython-36.pyc
  30. BIN
      Cozmo_LineFollow/venv/Lib/site-packages/cozmo/__pycache__/objects.cpython-36.pyc
  31. BIN
      Cozmo_LineFollow/venv/Lib/site-packages/cozmo/__pycache__/oled_face.cpython-36.pyc
  32. BIN
      Cozmo_LineFollow/venv/Lib/site-packages/cozmo/__pycache__/opengl.cpython-36.pyc
  33. BIN
      Cozmo_LineFollow/venv/Lib/site-packages/cozmo/__pycache__/pets.cpython-36.pyc
  34. BIN
      Cozmo_LineFollow/venv/Lib/site-packages/cozmo/__pycache__/robot.cpython-36.pyc
  35. BIN
      Cozmo_LineFollow/venv/Lib/site-packages/cozmo/__pycache__/robot_alignment.cpython-36.pyc
  36. BIN
      Cozmo_LineFollow/venv/Lib/site-packages/cozmo/__pycache__/run.cpython-36.pyc
  37. BIN
      Cozmo_LineFollow/venv/Lib/site-packages/cozmo/__pycache__/song.cpython-36.pyc
  38. BIN
      Cozmo_LineFollow/venv/Lib/site-packages/cozmo/__pycache__/tkview.cpython-36.pyc
  39. BIN
      Cozmo_LineFollow/venv/Lib/site-packages/cozmo/__pycache__/util.cpython-36.pyc
  40. BIN
      Cozmo_LineFollow/venv/Lib/site-packages/cozmo/__pycache__/version.cpython-36.pyc
  41. BIN
      Cozmo_LineFollow/venv/Lib/site-packages/cozmo/__pycache__/world.cpython-36.pyc
  42. 153
    0
      Cozmo_LineFollow/venv/Lib/site-packages/cozmo/_clad.py
  43. 667
    0
      Cozmo_LineFollow/venv/Lib/site-packages/cozmo/action.py
  44. 223
    0
      Cozmo_LineFollow/venv/Lib/site-packages/cozmo/anim.py
  45. 578
    0
      Cozmo_LineFollow/venv/Lib/site-packages/cozmo/annotate.py
  46. 21
    0
      Cozmo_LineFollow/venv/Lib/site-packages/cozmo/assets/LICENSE.txt
  47. 67
    0
      Cozmo_LineFollow/venv/Lib/site-packages/cozmo/assets/cozmo.mtl
  48. 13220
    0
      Cozmo_LineFollow/venv/Lib/site-packages/cozmo/assets/cozmo.obj
  49. 1000
    0
      Cozmo_LineFollow/venv/Lib/site-packages/cozmo/assets/cube.obj
  50. BIN
      Cozmo_LineFollow/venv/Lib/site-packages/cozmo/assets/cube1.jpg
  51. 9
    0
      Cozmo_LineFollow/venv/Lib/site-packages/cozmo/assets/cube1.mtl
  52. BIN
      Cozmo_LineFollow/venv/Lib/site-packages/cozmo/assets/cube2.jpg
  53. 9
    0
      Cozmo_LineFollow/venv/Lib/site-packages/cozmo/assets/cube2.mtl
  54. BIN
      Cozmo_LineFollow/venv/Lib/site-packages/cozmo/assets/cube3.jpg
  55. 9
    0
      Cozmo_LineFollow/venv/Lib/site-packages/cozmo/assets/cube3.mtl
  56. 379
    0
      Cozmo_LineFollow/venv/Lib/site-packages/cozmo/audio.py
  57. 241
    0
      Cozmo_LineFollow/venv/Lib/site-packages/cozmo/base.py
  58. 206
    0
      Cozmo_LineFollow/venv/Lib/site-packages/cozmo/behavior.py
  59. 579
    0
      Cozmo_LineFollow/venv/Lib/site-packages/cozmo/camera.py
  60. 113
    0
      Cozmo_LineFollow/venv/Lib/site-packages/cozmo/clad_protocol.py
  61. 486
    0
      Cozmo_LineFollow/venv/Lib/site-packages/cozmo/conn.py
  62. 618
    0
      Cozmo_LineFollow/venv/Lib/site-packages/cozmo/event.py
  63. 74
    0
      Cozmo_LineFollow/venv/Lib/site-packages/cozmo/exceptions.py
  64. 445
    0
      Cozmo_LineFollow/venv/Lib/site-packages/cozmo/faces.py
  65. 195
    0
      Cozmo_LineFollow/venv/Lib/site-packages/cozmo/lights.py
  66. 322
    0
      Cozmo_LineFollow/venv/Lib/site-packages/cozmo/nav_memory_map.py
  67. 939
    0
      Cozmo_LineFollow/venv/Lib/site-packages/cozmo/objects.py
  68. 133
    0
      Cozmo_LineFollow/venv/Lib/site-packages/cozmo/oled_face.py
  69. 1489
    0
      Cozmo_LineFollow/venv/Lib/site-packages/cozmo/opengl.py
  70. 181
    0
      Cozmo_LineFollow/venv/Lib/site-packages/cozmo/pets.py
  71. 2335
    0
      Cozmo_LineFollow/venv/Lib/site-packages/cozmo/robot.py
  72. 49
    0
      Cozmo_LineFollow/venv/Lib/site-packages/cozmo/robot_alignment.py
  73. 857
    0
      Cozmo_LineFollow/venv/Lib/site-packages/cozmo/run.py
  74. 128
    0
      Cozmo_LineFollow/venv/Lib/site-packages/cozmo/song.py
  75. 165
    0
      Cozmo_LineFollow/venv/Lib/site-packages/cozmo/tkview.py
  76. 15
    0
      Cozmo_LineFollow/venv/Lib/site-packages/cozmo/usbmux/__init__.py
  77. BIN
      Cozmo_LineFollow/venv/Lib/site-packages/cozmo/usbmux/__pycache__/__init__.cpython-36.pyc
  78. BIN
      Cozmo_LineFollow/venv/Lib/site-packages/cozmo/usbmux/__pycache__/usbmux.cpython-36.pyc
  79. 470
    0
      Cozmo_LineFollow/venv/Lib/site-packages/cozmo/usbmux/usbmux.py
  80. 1023
    0
      Cozmo_LineFollow/venv/Lib/site-packages/cozmo/util.py
  81. 24
    0
      Cozmo_LineFollow/venv/Lib/site-packages/cozmo/version.py
  82. 1141
    0
      Cozmo_LineFollow/venv/Lib/site-packages/cozmo/world.py
  83. 1
    0
      Cozmo_LineFollow/venv/Lib/site-packages/cozmoclad-3.4.0.dist-info/INSTALLER
  84. 14
    0
      Cozmo_LineFollow/venv/Lib/site-packages/cozmoclad-3.4.0.dist-info/LICENSE-header-cs.txt
  85. 14
    0
      Cozmo_LineFollow/venv/Lib/site-packages/cozmoclad-3.4.0.dist-info/LICENSE-header-py.txt
  86. 180
    0
      Cozmo_LineFollow/venv/Lib/site-packages/cozmoclad-3.4.0.dist-info/LICENSE.txt
  87. 24
    0
      Cozmo_LineFollow/venv/Lib/site-packages/cozmoclad-3.4.0.dist-info/METADATA
  88. 218
    0
      Cozmo_LineFollow/venv/Lib/site-packages/cozmoclad-3.4.0.dist-info/RECORD
  89. 5
    0
      Cozmo_LineFollow/venv/Lib/site-packages/cozmoclad-3.4.0.dist-info/WHEEL
  90. 1
    0
      Cozmo_LineFollow/venv/Lib/site-packages/cozmoclad-3.4.0.dist-info/top_level.txt
  91. 1
    0
      Cozmo_LineFollow/venv/Lib/site-packages/cozmoclad-3.4.0.dist-info/zip-safe
  92. 180
    0
      Cozmo_LineFollow/venv/Lib/site-packages/cozmoclad/LICENSE.txt
  93. 74
    0
      Cozmo_LineFollow/venv/Lib/site-packages/cozmoclad/__init__.py
  94. BIN
      Cozmo_LineFollow/venv/Lib/site-packages/cozmoclad/__pycache__/__init__.cpython-36.pyc
  95. 14
    0
      Cozmo_LineFollow/venv/Lib/site-packages/cozmoclad/clad/__init__.py
  96. BIN
      Cozmo_LineFollow/venv/Lib/site-packages/cozmoclad/clad/__pycache__/__init__.cpython-36.pyc
  97. 14
    0
      Cozmo_LineFollow/venv/Lib/site-packages/cozmoclad/clad/audio/__init__.py
  98. BIN
      Cozmo_LineFollow/venv/Lib/site-packages/cozmoclad/clad/audio/__pycache__/__init__.cpython-36.pyc
  99. BIN
      Cozmo_LineFollow/venv/Lib/site-packages/cozmoclad/clad/audio/__pycache__/audioBusTypes.cpython-36.pyc
  100. 0
    0
      Cozmo_LineFollow/venv/Lib/site-packages/cozmoclad/clad/audio/__pycache__/audioCallbackMessage.cpython-36.pyc

+ 13
- 0
Cozmo_LineFollow/.idea/Cozmo_LineFollow.iml View File

@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="PYTHON_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$">
<excludeFolder url="file://$MODULE_DIR$/venv" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
<component name="TestRunnerService">
<option name="PROJECT_TEST_RUNNER" value="Unittests" />
</component>
</module>

+ 7
- 0
Cozmo_LineFollow/.idea/misc.xml View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.6 (Cozmo_LineFollow)" project-jdk-type="Python SDK" />
<component name="PyCharmProfessionalAdvertiser">
<option name="shown" value="true" />
</component>
</project>

+ 8
- 0
Cozmo_LineFollow/.idea/modules.xml View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/Cozmo_LineFollow.iml" filepath="$PROJECT_DIR$/.idea/Cozmo_LineFollow.iml" />
</modules>
</component>
</project>

+ 252
- 0
Cozmo_LineFollow/.idea/workspace.xml View File

@@ -0,0 +1,252 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ChangeListManager">
<list default="true" id="6890b9c1-6701-47f4-b269-98dc98eee6bc" name="Default Changelist" comment="" />
<option name="EXCLUDED_CONVERTED_TO_IGNORED" value="true" />
<option name="SHOW_DIALOG" value="false" />
<option name="HIGHLIGHT_CONFLICTS" value="true" />
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
<option name="LAST_RESOLUTION" value="IGNORE" />
</component>
<component name="FileEditorManager">
<leaf SIDE_TABS_SIZE_LIMIT_KEY="300">
<file pinned="false" current-in-tab="true">
<entry file="file://$PROJECT_DIR$/venv/Scripts/CozmoDrive.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="207">
<caret line="16" column="60" lean-forward="true" selection-start-line="16" selection-start-column="60" selection-end-line="16" selection-end-column="60" />
<folding>
<element signature="e#0#12#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
</file>
<file pinned="false" current-in-tab="false">
<entry file="file://$USER_HOME$/Downloads/Cozmo-Explorer-Tool-master/remote_control.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="4182">
<caret line="276" selection-start-line="276" selection-end-line="276" />
</state>
</provider>
</entry>
</file>
</leaf>
</component>
<component name="FileTemplateManagerImpl">
<option name="RECENT_TEMPLATES">
<list>
<option value="Python Script" />
</list>
</option>
</component>
<component name="IdeDocumentHistory">
<option name="CHANGED_PATHS">
<list>
<option value="$PROJECT_DIR$/venv/Scripts/CozmoDrive.py" />
</list>
</option>
</component>
<component name="ProjectFrameBounds" extendedState="6">
<option name="x" value="948" />
<option name="width" value="981" />
<option name="height" value="1032" />
</component>
<component name="ProjectView">
<navigator proportions="" version="1">
<foldersAlwaysOnTop value="true" />
</navigator>
<panes>
<pane id="Scope" />
<pane id="ProjectPane">
<subPane>
<expand>
<path>
<item name="Cozmo_LineFollow" type="b2602c69:ProjectViewProjectNode" />
<item name="Cozmo_LineFollow" type="462c0819:PsiDirectoryNode" />
</path>
<path>
<item name="Cozmo_LineFollow" type="b2602c69:ProjectViewProjectNode" />
<item name="Cozmo_LineFollow" type="462c0819:PsiDirectoryNode" />
<item name="venv" type="462c0819:PsiDirectoryNode" />
</path>
<path>
<item name="Cozmo_LineFollow" type="b2602c69:ProjectViewProjectNode" />
<item name="Cozmo_LineFollow" type="462c0819:PsiDirectoryNode" />
<item name="venv" type="462c0819:PsiDirectoryNode" />
<item name="Scripts" type="462c0819:PsiDirectoryNode" />
</path>
<path>
<item name="Cozmo_LineFollow" type="b2602c69:ProjectViewProjectNode" />
<item name="External Libraries" type="cb654da1:ExternalLibrariesNode" />
</path>
<path>
<item name="Cozmo_LineFollow" type="b2602c69:ProjectViewProjectNode" />
<item name="External Libraries" type="cb654da1:ExternalLibrariesNode" />
<item name="&lt; Python 3.6 (Cozmo_LineFollow) &gt;" type="70bed36:NamedLibraryElementNode" />
</path>
<path>
<item name="Cozmo_LineFollow" type="b2602c69:ProjectViewProjectNode" />
<item name="External Libraries" type="cb654da1:ExternalLibrariesNode" />
<item name="&lt; Python 3.6 (Cozmo_LineFollow) &gt;" type="70bed36:NamedLibraryElementNode" />
<item name="venv" type="462c0819:PsiDirectoryNode" />
</path>
<path>
<item name="Cozmo_LineFollow" type="b2602c69:ProjectViewProjectNode" />
<item name="External Libraries" type="cb654da1:ExternalLibrariesNode" />
<item name="&lt; Python 3.6 (Cozmo_LineFollow) &gt;" type="70bed36:NamedLibraryElementNode" />
<item name="venv" type="462c0819:PsiDirectoryNode" />
<item name="Scripts" type="462c0819:PsiDirectoryNode" />
</path>
</expand>
<select />
</subPane>
</pane>
</panes>
</component>
<component name="PropertiesComponent">
<property name="last_opened_file_path" value="$USER_HOME$/Desktop/cozmoTest.py" />
<property name="settings.editor.selected.configurable" value="com.jetbrains.python.configuration.PyActiveSdkModuleConfigurable" />
</component>
<component name="RunDashboard">
<option name="ruleStates">
<list>
<RuleState>
<option name="name" value="ConfigurationTypeDashboardGroupingRule" />
</RuleState>
<RuleState>
<option name="name" value="StatusDashboardGroupingRule" />
</RuleState>
</list>
</option>
</component>
<component name="RunManager" selected="Python.CozmoDrive">
<configuration name="CozmoDrive" type="PythonConfigurationType" factoryName="Python" temporary="true">
<module name="Cozmo_LineFollow" />
<option name="INTERPRETER_OPTIONS" value="" />
<option name="PARENT_ENVS" value="true" />
<envs>
<env name="PYTHONUNBUFFERED" value="1" />
</envs>
<option name="SDK_HOME" value="" />
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/venv/Scripts" />
<option name="IS_MODULE_SDK" value="true" />
<option name="ADD_CONTENT_ROOTS" value="true" />
<option name="ADD_SOURCE_ROOTS" value="true" />
<option name="SCRIPT_NAME" value="$PROJECT_DIR$/venv/Scripts/CozmoDrive.py" />
<option name="PARAMETERS" value="" />
<option name="SHOW_COMMAND_LINE" value="false" />
<option name="EMULATE_TERMINAL" value="false" />
<option name="MODULE_MODE" value="false" />
<option name="REDIRECT_INPUT" value="false" />
<option name="INPUT_FILE" value="" />
<method v="2" />
</configuration>
<configuration name="canny_test" type="PythonConfigurationType" factoryName="Python" temporary="true">
<module name="Cozmo_LineFollow" />
<option name="INTERPRETER_OPTIONS" value="" />
<option name="PARENT_ENVS" value="true" />
<envs>
<env name="PYTHONUNBUFFERED" value="1" />
</envs>
<option name="SDK_HOME" value="" />
<option name="WORKING_DIRECTORY" value="$USER_HOME$/Desktop" />
<option name="IS_MODULE_SDK" value="false" />
<option name="ADD_CONTENT_ROOTS" value="true" />
<option name="ADD_SOURCE_ROOTS" value="true" />
<option name="SCRIPT_NAME" value="$USER_HOME$/Desktop/canny_test.py" />
<option name="PARAMETERS" value="" />
<option name="SHOW_COMMAND_LINE" value="false" />
<option name="EMULATE_TERMINAL" value="false" />
<option name="MODULE_MODE" value="false" />
<option name="REDIRECT_INPUT" value="false" />
<option name="INPUT_FILE" value="" />
<method v="2" />
</configuration>
<recent_temporary>
<list>
<item itemvalue="Python.CozmoDrive" />
<item itemvalue="Python.canny_test" />
</list>
</recent_temporary>
</component>
<component name="SvnConfiguration">
<configuration />
</component>
<component name="TaskManager">
<task active="true" id="Default" summary="Default task">
<changelist id="6890b9c1-6701-47f4-b269-98dc98eee6bc" name="Default Changelist" comment="" />
<created>1556208118986</created>
<option name="number" value="Default" />
<option name="presentableId" value="Default" />
<updated>1556208118986</updated>
</task>
<servers />
</component>
<component name="ToolWindowManager">
<frame x="-7" y="-7" width="1295" height="695" extended-state="6" />
<layout>
<window_info content_ui="combo" id="Project" order="0" visible="true" weight="0.1223193" />
<window_info id="Structure" order="1" side_tool="true" weight="0.25" />
<window_info id="Favorites" order="2" side_tool="true" />
<window_info anchor="bottom" id="Message" order="0" />
<window_info anchor="bottom" id="Find" order="1" weight="0.32978722" />
<window_info anchor="bottom" id="Run" order="2" weight="0.18439716" />
<window_info anchor="bottom" id="Debug" order="3" weight="0.4" />
<window_info anchor="bottom" id="Cvs" order="4" weight="0.25" />
<window_info anchor="bottom" id="Inspection" order="5" weight="0.4" />
<window_info anchor="bottom" id="TODO" order="6" />
<window_info anchor="bottom" id="Version Control" order="7" />
<window_info anchor="bottom" id="Terminal" order="8" />
<window_info anchor="bottom" id="Event Log" order="9" side_tool="true" />
<window_info anchor="bottom" id="Python Console" order="10" />
<window_info anchor="right" id="Commander" internal_type="SLIDING" order="0" type="SLIDING" weight="0.4" />
<window_info anchor="right" id="Ant Build" order="1" weight="0.25" />
<window_info anchor="right" content_ui="combo" id="Hierarchy" order="2" weight="0.25" />
</layout>
</component>
<component name="editorHistoryManager">
<entry file="file://$USER_HOME$/Desktop/cozmoTest.py">
<provider selected="true" editor-type-id="text-editor">
<state>
<caret selection-end-line="17" selection-end-column="32" />
<folding>
<element signature="e#0#12#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$USER_HOME$/Downloads/Cozmo-Explorer-Tool-master/explorer_tool.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="-620" />
</provider>
</entry>
<entry file="file://$USER_HOME$/Downloads/Cozmo-Explorer-Tool-master/remote_control.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="4182">
<caret line="276" selection-start-line="276" selection-end-line="276" />
</state>
</provider>
</entry>
<entry file="file://$USER_HOME$/Desktop/canny_test.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="68">
<caret line="4" column="30" selection-start-line="4" selection-start-column="30" selection-end-line="4" selection-end-column="30" />
<folding>
<element signature="e#0#10#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/venv/Scripts/CozmoDrive.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="207">
<caret line="16" column="60" lean-forward="true" selection-start-line="16" selection-start-column="60" selection-end-line="16" selection-end-column="60" />
<folding>
<element signature="e#0#12#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
</component>
</project>

+ 1
- 0
Cozmo_LineFollow/venv/Lib/site-packages/cozmo-1.4.10.dist-info/INSTALLER View File

@@ -0,0 +1 @@
pip

+ 180
- 0
Cozmo_LineFollow/venv/Lib/site-packages/cozmo-1.4.10.dist-info/LICENSE.txt View File

@@ -0,0 +1,180 @@
Unless otherwise stated in that file, or the folder containing that file, all
files in the Cozmo SDK are Copyright (c) 2016-2017 Anki Inc. and licensed under
the Apache 2.0 License:

Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/

TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION

1. Definitions.

"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.

"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.

"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.

"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.

"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.

"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.

"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).

"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.

"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."

"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.

2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.

3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.

4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:

(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and

(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and

(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and

(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.

You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.

5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.

6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.

7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.

8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.

9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.

END OF TERMS AND CONDITIONS

+ 42
- 0
Cozmo_LineFollow/venv/Lib/site-packages/cozmo-1.4.10.dist-info/METADATA View File

@@ -0,0 +1,42 @@
Metadata-Version: 2.1
Name: cozmo
Version: 1.4.10
Summary: SDK for Anki Cozmo, the small robot with the big personality
Home-page: https://developer.anki.com
Author: Anki, Inc
Author-email: developer@anki.com
License: Apache License, Version 2.0
Keywords: anki,cozmo,robot,robotics,sdk
Platform: UNKNOWN
Classifier: Development Status :: 5 - Production/Stable
Classifier: Intended Audience :: Developers
Classifier: Topic :: Software Development :: Libraries
Classifier: License :: OSI Approved :: Apache Software License
Classifier: Programming Language :: Python :: 3.5
Requires-Dist: cozmoclad (==3.4.0)
Provides-Extra: 3dviewer
Requires-Dist: PyOpenGL (>=3.1) ; extra == '3dviewer'
Requires-Dist: Pillow (>=3.3) ; extra == '3dviewer'
Requires-Dist: numpy (>=1.11) ; extra == '3dviewer'
Provides-Extra: camera
Requires-Dist: Pillow (>=3.3) ; extra == 'camera'
Requires-Dist: numpy (>=1.11) ; extra == 'camera'
Provides-Extra: test
Requires-Dist: tox ; extra == 'test'
Requires-Dist: pytest ; extra == 'test'


The Cozmo SDK is a flexible vision-based robotics platform used in enterprise, education, and entertainment.

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.

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

Cozmo SDK documentation: http://cozmosdk.anki.com/docs/

Official developer forum: https://forums.anki.com/

Requirements:
* Python 3.5.1 or later



+ 78
- 0
Cozmo_LineFollow/venv/Lib/site-packages/cozmo-1.4.10.dist-info/RECORD View File

@@ -0,0 +1,78 @@
cozmo/LICENSE.txt,sha256=THPe12iw4yd8mbwjmhwsGiCsmC2QDopJnGNSbSh9hkc,10356
cozmo/__init__.py,sha256=VqMKC1E1d4zJQh5P4ezQ9mdqbat8Tq25yOsGN0SnuxE,3118
cozmo/_clad.py,sha256=jZ_8SzcTtXiZGmd7QNgJMBZPCoYp8ryUGs_FixVaLSA,6643
cozmo/action.py,sha256=nabVR7VhR9FJPukMGDzHANsPwWvSDQUleKimiYouQx0,27723
cozmo/anim.py,sha256=W3YbvFW5yz7hw2MGR9_1rOzVKnTNTWUJ_P6nMBAvI4M,8451
cozmo/annotate.py,sha256=7Ewbp5iF8BwnY83tSP9cd79cm20aezz5WjxJzKOuwz0,20962
cozmo/audio.py,sha256=2XcawlEve8rujB07Rm_INTPg-5UbwynlU1vD-h_pQ5w,26063
cozmo/base.py,sha256=EX_oNAph_jXkz_PnLUvxmfXWvHlQbwZRsXSM8rW40MY,8752
cozmo/behavior.py,sha256=1vSpuKrsnKSwTJDI_jxFiJfI3WBrvT1MZc2XlMQQfm0,7610
cozmo/camera.py,sha256=qbh8o1EA9DO9dgcvQ-Gigxkikmppa_6NeTNaAh8pctc,24340
cozmo/clad_protocol.py,sha256=IPVM2Fq1kVV7IVg2-TIhKBD6eyQO7ggy6a7SzeM2rdE,3663
cozmo/conn.py,sha256=PtIp70ChvgHXKLm0T6Z65WvMgan3oeR1SUErixL0b3o,20614
cozmo/event.py,sha256=i8yQ3rdQLE1eYg8Pfmmj-W6JKtwK_Zyyy6CnT7haUB8,23195
cozmo/exceptions.py,sha256=sPQjj1M5wcZxr5m0a9tRUh5B6iF1-JbiAC436hX8swI,3382
cozmo/faces.py,sha256=ZRjL9B_u974uUkMbmS4Bbx9JGVOLsZ6z0Ue5OBP4Z0I,17356
cozmo/lights.py,sha256=ICuKMv2CrtA-vvGWtEiDBhD3zbwfsEkufGoP8tVhReA,6945
cozmo/nav_memory_map.py,sha256=rJS5ylI0YmeARmvcRjdJgJHvtRDI8FrHZ47m6kE0KmE,12361
cozmo/objects.py,sha256=gTCYvkan6YLKHaFW10l7uDZMVEOawoZpIwXqkkCPxAA,36156
cozmo/oled_face.py,sha256=INkcT0JYbP5MfHMa4kZbFxfgLwzn-jCfuzpMKxpUu2Y,5228
cozmo/opengl.py,sha256=lTId8lLcls18JPL24scyghaKTVMAhi9s_TFykVmnGU0,59378
cozmo/pets.py,sha256=xREwNU3Leq4B207-h89kIo4q_wSswgWcAeMG1r9mmKY,6446
cozmo/robot.py,sha256=Cxdn1zuvEIsaBrj9shH9rwn0CcqQcyVbmig7JGSNFTw,104347
cozmo/robot_alignment.py,sha256=zjrZfd-a6b-_NE8agKC5kBVjhx9WhLRAXQOgGeccjMI,1722
cozmo/run.py,sha256=JFksm2Zlrb5Cc1H8xTo-OOfwFeh1vhV1ezcE_v9VDkc,34333
cozmo/song.py,sha256=TDVWjqGtirWHcU5OneWumOWDsrw70dZ08s5DZj6H4XE,4096
cozmo/tkview.py,sha256=iDjcSbPAEOk-H4dyzEdju0EjKUxDzBSIigYNQYwrupE,5480
cozmo/util.py,sha256=WzYuT5ZMofNVBDPFUl2EkESct6yHglRo-seLIbHByLI,35350
cozmo/version.py,sha256=RRMB8PZ3nosD8JyOFz7yrH2eunw9ZdMQbqm_O3ghTyE,994
cozmo/world.py,sha256=HLQpFvQPFSP3R2GiawsXWPdrH8_mW9fYOVmf21LnYpA,51745
cozmo/assets/LICENSE.txt,sha256=Pal4SZLGFSDAQsf_BIEfhIryYHphbdX6CXlvNzIoFko,6211
cozmo/assets/cozmo.mtl,sha256=qplYD-9bnluRy-Nb0-6boK3_o-dFtN-UC1GyD1aA7aM,922
cozmo/assets/cozmo.obj,sha256=JjLdx6On5oGMnQn3XQvwVb8pPpUJCgiPcAsPbrjMLF8,418388
cozmo/assets/cube.obj,sha256=uzM98bsfoptt6IpINTSkDbDuW-mOf6GG-66R6u59Htc,27246
cozmo/assets/cube1.jpg,sha256=xMTp74T7PWf6BHLQGNwnZfCGaDcIvPSpnOxogl_TN6Q,36785
cozmo/assets/cube1.mtl,sha256=dPiG9-BmeLpk5MGjwoJ1FIfz6K-xxIpn8lvX1SQnRfY,127
cozmo/assets/cube2.jpg,sha256=2SckIUYkvdYzUQYmllNROmro3qZakVD3tc9cxFmhvVk,36852
cozmo/assets/cube2.mtl,sha256=1koNkJAPWrxABA8oe_rNT_nHUE1tIx9nPPuIjK9gGHw,127
cozmo/assets/cube3.jpg,sha256=n0JJa5Vr9P6ZqJ88TbVH4pHCuuKRACNBXLQYCOkTmtE,37652
cozmo/assets/cube3.mtl,sha256=CSqFZhKNlW-IMsPCYmYo9UTEetznkUhQ44rgkk9_4-c,127
cozmo/usbmux/__init__.py,sha256=kcvhyDtwVb3dWaFwmyhISp1VUzYinjaHrYJOZoge22s,628
cozmo/usbmux/usbmux.py,sha256=Piv6vRfWHtOLNhC50XT_Oe3vF7FHWffvAhXwP07CdQc,17161
cozmo-1.4.10.dist-info/LICENSE.txt,sha256=THPe12iw4yd8mbwjmhwsGiCsmC2QDopJnGNSbSh9hkc,10356
cozmo-1.4.10.dist-info/METADATA,sha256=aXWZywcKBSM1Dk6slfL9nYzZ59700vG4Skc3m38j5Qg,1914
cozmo-1.4.10.dist-info/WHEEL,sha256=U88EhGIw8Sj2_phqajeu_EAi3RAo8-C6zV3REsWbWbs,92
cozmo-1.4.10.dist-info/top_level.txt,sha256=N7B-F2_miE1pnrFjxvVoCSTGOaBYufBSIsm6LZ6GdrM,6
cozmo-1.4.10.dist-info/zip-safe,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
cozmo-1.4.10.dist-info/RECORD,,
cozmo-1.4.10.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
cozmo/usbmux/__pycache__/usbmux.cpython-36.pyc,,
cozmo/usbmux/__pycache__/__init__.cpython-36.pyc,,
cozmo/__pycache__/action.cpython-36.pyc,,
cozmo/__pycache__/anim.cpython-36.pyc,,
cozmo/__pycache__/annotate.cpython-36.pyc,,
cozmo/__pycache__/audio.cpython-36.pyc,,
cozmo/__pycache__/base.cpython-36.pyc,,
cozmo/__pycache__/behavior.cpython-36.pyc,,
cozmo/__pycache__/camera.cpython-36.pyc,,
cozmo/__pycache__/clad_protocol.cpython-36.pyc,,
cozmo/__pycache__/conn.cpython-36.pyc,,
cozmo/__pycache__/event.cpython-36.pyc,,
cozmo/__pycache__/exceptions.cpython-36.pyc,,
cozmo/__pycache__/faces.cpython-36.pyc,,
cozmo/__pycache__/lights.cpython-36.pyc,,
cozmo/__pycache__/nav_memory_map.cpython-36.pyc,,
cozmo/__pycache__/objects.cpython-36.pyc,,
cozmo/__pycache__/oled_face.cpython-36.pyc,,
cozmo/__pycache__/opengl.cpython-36.pyc,,
cozmo/__pycache__/pets.cpython-36.pyc,,
cozmo/__pycache__/robot.cpython-36.pyc,,
cozmo/__pycache__/robot_alignment.cpython-36.pyc,,
cozmo/__pycache__/run.cpython-36.pyc,,
cozmo/__pycache__/song.cpython-36.pyc,,
cozmo/__pycache__/tkview.cpython-36.pyc,,
cozmo/__pycache__/util.cpython-36.pyc,,
cozmo/__pycache__/version.cpython-36.pyc,,
cozmo/__pycache__/world.cpython-36.pyc,,
cozmo/__pycache__/_clad.cpython-36.pyc,,
cozmo/__pycache__/__init__.cpython-36.pyc,,

+ 5
- 0
Cozmo_LineFollow/venv/Lib/site-packages/cozmo-1.4.10.dist-info/WHEEL View File

@@ -0,0 +1,5 @@
Wheel-Version: 1.0
Generator: bdist_wheel (0.33.1)
Root-Is-Purelib: true
Tag: py3-none-any


+ 1
- 0
Cozmo_LineFollow/venv/Lib/site-packages/cozmo-1.4.10.dist-info/top_level.txt View File

@@ -0,0 +1 @@
cozmo

+ 1
- 0
Cozmo_LineFollow/venv/Lib/site-packages/cozmo-1.4.10.dist-info/zip-safe View File

@@ -0,0 +1 @@


+ 180
- 0
Cozmo_LineFollow/venv/Lib/site-packages/cozmo/LICENSE.txt View File

@@ -0,0 +1,180 @@
Unless otherwise stated in that file, or the folder containing that file, all
files in the Cozmo SDK are Copyright (c) 2016-2017 Anki Inc. and licensed under
the Apache 2.0 License:

Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/

TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION

1. Definitions.

"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.

"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.

"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.

"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.

"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.

"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.

"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).

"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.

"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."

"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.

2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.

3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.

4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:

(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and

(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and

(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and

(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.

You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.

5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.

6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.

7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.

8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.

9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.

END OF TERMS AND CONDITIONS

+ 86
- 0
Cozmo_LineFollow/venv/Lib/site-packages/cozmo/__init__.py View File

@@ -0,0 +1,86 @@
# Copyright (c) 2016 Anki, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License in the file LICENSE.txt or at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import sys
if sys.version_info < (3,5,1):
sys.exit('cozmo requires Python 3.5.1 or later')

# Verify cozmoclad version before any other imports, so we can catch a mismatch
# before triggering any exceptions from missing clad definitions
try:
from cozmoclad import __build_version__ as __installed_cozmoclad_build_version__
except ImportError as e:
sys.exit("%s\nCannot import from cozmoclad: Do `pip3 install --user cozmoclad` to install" % e)

from .version import __version__, __cozmoclad_version__, __min_cozmoclad_version__

def verify_min_clad_version():
def _make_sortable_version_string(ver_string):
# pad out an x.y.z version to a 5.5.5 string with leading zeroes
ver_elements = [str(int(x)).zfill(5) for x in ver_string.split(".")]
return '.'.join(ver_elements)

def _trimmed_version(ver_string):
# Trim leading zeros from the version string
trimmed_parts = [str(int(x)) for x in ver_string.split(".")]
return '.'.join(trimmed_parts)

min_cozmoclad_version_str = _make_sortable_version_string(__min_cozmoclad_version__)
if __installed_cozmoclad_build_version__ < min_cozmoclad_version_str:
sys.exit("Incompatible cozmoclad version %s for SDK %s - needs at least %s\n"
"Do `pip3 install --user --upgrade cozmoclad` to upgrade" % (
_trimmed_version(__installed_cozmoclad_build_version__),
__version__,
__min_cozmoclad_version__))


verify_min_clad_version()


import logging as _logging

#: The general purpose logger logs high level information about Cozmo events.
logger = _logging.getLogger('cozmo.general')

#: The protocol logger logs low level messages that are sent back and forth to Cozmo.
logger_protocol = _logging.getLogger('cozmo.protocol')

del _logging

from . import action
from . import anim
from . import annotate
from . import behavior
from . import conn
from . import event
from . import exceptions
from . import lights
from . import nav_memory_map
from . import objects
from . import oled_face
from . import robot
from . import robot_alignment
from . import run
from . import util
from . import world

from .exceptions import *
from .run import *


__all__ = ['logger', 'logger_protocol',
'action', 'anim', 'annotate', 'behavior', 'conn', 'event',
'exceptions', 'lights', 'objects', 'oled_face', 'nav_memory_map',
'robot', 'robot_alignment', 'run', 'util', 'world'] + \
(run.__all__ + exceptions.__all__)

BIN
Cozmo_LineFollow/venv/Lib/site-packages/cozmo/__pycache__/__init__.cpython-36.pyc View File


BIN
Cozmo_LineFollow/venv/Lib/site-packages/cozmo/__pycache__/_clad.cpython-36.pyc View File


BIN
Cozmo_LineFollow/venv/Lib/site-packages/cozmo/__pycache__/action.cpython-36.pyc View File


BIN
Cozmo_LineFollow/venv/Lib/site-packages/cozmo/__pycache__/anim.cpython-36.pyc View File


BIN
Cozmo_LineFollow/venv/Lib/site-packages/cozmo/__pycache__/annotate.cpython-36.pyc View File


BIN
Cozmo_LineFollow/venv/Lib/site-packages/cozmo/__pycache__/audio.cpython-36.pyc View File


BIN
Cozmo_LineFollow/venv/Lib/site-packages/cozmo/__pycache__/base.cpython-36.pyc View File


BIN
Cozmo_LineFollow/venv/Lib/site-packages/cozmo/__pycache__/behavior.cpython-36.pyc View File


BIN
Cozmo_LineFollow/venv/Lib/site-packages/cozmo/__pycache__/camera.cpython-36.pyc View File


BIN
Cozmo_LineFollow/venv/Lib/site-packages/cozmo/__pycache__/clad_protocol.cpython-36.pyc View File


BIN
Cozmo_LineFollow/venv/Lib/site-packages/cozmo/__pycache__/conn.cpython-36.pyc View File


BIN
Cozmo_LineFollow/venv/Lib/site-packages/cozmo/__pycache__/event.cpython-36.pyc View File


BIN
Cozmo_LineFollow/venv/Lib/site-packages/cozmo/__pycache__/exceptions.cpython-36.pyc View File


BIN
Cozmo_LineFollow/venv/Lib/site-packages/cozmo/__pycache__/faces.cpython-36.pyc View File


BIN
Cozmo_LineFollow/venv/Lib/site-packages/cozmo/__pycache__/lights.cpython-36.pyc View File


BIN
Cozmo_LineFollow/venv/Lib/site-packages/cozmo/__pycache__/nav_memory_map.cpython-36.pyc View File


BIN
Cozmo_LineFollow/venv/Lib/site-packages/cozmo/__pycache__/objects.cpython-36.pyc View File


BIN
Cozmo_LineFollow/venv/Lib/site-packages/cozmo/__pycache__/oled_face.cpython-36.pyc View File


BIN
Cozmo_LineFollow/venv/Lib/site-packages/cozmo/__pycache__/opengl.cpython-36.pyc View File


BIN
Cozmo_LineFollow/venv/Lib/site-packages/cozmo/__pycache__/pets.cpython-36.pyc View File


BIN
Cozmo_LineFollow/venv/Lib/site-packages/cozmo/__pycache__/robot.cpython-36.pyc View File


BIN
Cozmo_LineFollow/venv/Lib/site-packages/cozmo/__pycache__/robot_alignment.cpython-36.pyc View File


BIN
Cozmo_LineFollow/venv/Lib/site-packages/cozmo/__pycache__/run.cpython-36.pyc View File


BIN
Cozmo_LineFollow/venv/Lib/site-packages/cozmo/__pycache__/song.cpython-36.pyc View File


BIN
Cozmo_LineFollow/venv/Lib/site-packages/cozmo/__pycache__/tkview.cpython-36.pyc View File


BIN
Cozmo_LineFollow/venv/Lib/site-packages/cozmo/__pycache__/util.cpython-36.pyc View File


BIN
Cozmo_LineFollow/venv/Lib/site-packages/cozmo/__pycache__/version.cpython-36.pyc View File


BIN
Cozmo_LineFollow/venv/Lib/site-packages/cozmo/__pycache__/world.cpython-36.pyc View File


+ 153
- 0
Cozmo_LineFollow/venv/Lib/site-packages/cozmo/_clad.py View File

@@ -0,0 +1,153 @@
# Copyright (c) 2016-2017 Anki, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License in the file LICENSE.txt or at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

__all__ = ['CladEnumWrapper']

import sys

from . import event
from . import logger

from cozmoclad.clad.externalInterface import messageEngineToGame as messageEngineToGame
from cozmoclad.clad.externalInterface import messageGameToEngine as messageGameToEngine

# Shortcut access to CLAD classes
_clad_to_engine_anki = messageGameToEngine.Anki
_clad_to_engine_cozmo = messageGameToEngine.Anki.Cozmo
_clad_to_engine_iface = messageGameToEngine.Anki.Cozmo.ExternalInterface
_clad_to_game_anki = messageEngineToGame.Anki
_clad_to_game_cozmo = messageEngineToGame.Anki.Cozmo
_clad_to_game_iface = messageEngineToGame.Anki.Cozmo.ExternalInterface

# Register event types for engine to game messages
# (e.g. _MsgObjectMoved)
for _name in vars(_clad_to_game_iface.MessageEngineToGame.Tag):
attrs = {
'__doc__': 'Internal protocol message',
'msg': 'Message data'
}
_name = '_Msg' + _name
cls = event._register_dynamic_event_type(_name, attrs)
globals()[_name] = cls


def _all_caps_to_pascal_case(name):
# Convert a string from CAPS_CASE_WORDS to PascalCase (e.g. CapsCaseWords)
ret_str = ""
first_char = True
# Build the return string
for char in name:
if char == "_":
# skip underscores, but reset that next char will be start of a new word
first_char = True
else:
# First letter of a word is uppercase, rest are lowercase
if first_char:
ret_str += char.upper()
first_char = False
else:
ret_str += char.lower()
return ret_str


class CladEnumWrapper:
"""Subclass this for an easy way to wrap a clad-enum in a documentable class.
Call cls._init_class() after declaration of the sub-class to verify the
type after construction and set up id to type mapping.
"""

# Override this to the CLAD enum type being wrapped
_clad_enum = None

# Override this with the type used for each instance
# e.g. collections.namedtuple('_ClassName', 'name id')
_entry_type = None

_id_to_entry_type = None # type: dict

@classmethod
def find_by_id(cls, id):
return cls._id_to_entry_type.get(id)

@classmethod
def _verify(cls, warn_on_missing_definitions=True, add_missing_definitions=True):
"""Verify that definitions are in sync with the underlying CLAD values.

Optionally also warn about and/or add any missing definitions.

Args:
warn_on_missing_definitions (bool): True to warn about any entries
in the underlying CLAD enum that haven't been explicitly
declared (includes suggested format for adding, which can then
be documented with `#:` comments for the generated docs.
add_missing_definitions (bool): True to automatically add any
entries in the underlying CLAD enum that haven't been explicitly
declared. Note that these definitions will work at runtime, but
won't be present in the auto-generated docs.
"""
missing_definitions_message = None
for (_name, _id) in cls._clad_enum.__dict__.items():
# Ignore any private entries (or internal Python objects) and any
# "Count" entries in the enum
if not _name.startswith('_') and (_name != 'Count') and _id >= 0:
attr = getattr(cls, _name, None)
if attr is None:
# Try valid, but less common, alternatives of the name -
# leading underscores for private vars, and/or PascalCase
# when the Clad type is in CAPS_CASE

alternative_names = ["_" + _name]
is_upper_case = _name == _name.upper()
if is_upper_case:
pascal_case_name = _all_caps_to_pascal_case(_name)
alternative_names.extend([pascal_case_name,
"_" + pascal_case_name])
alternative_names.append(_name.replace("_",""))
for alt_name in alternative_names:
attr = getattr(cls, alt_name, None)
if attr is not None:
break

if attr is not None:
if attr.id != _id:
sys.exit(
'Incorrect definition in %s for id %s=%s, (should =%s) - line should read:\n'
'%s = _entry_type("%s", _clad_enum.%s)'
% (str(cls), _name, attr.id, _id, _name, _name, _name))
else:
if warn_on_missing_definitions:
if missing_definitions_message is None:
missing_definitions_message = ('Missing definition(s) in %s - to document them add:' % str(cls))
missing_definitions_message += ('\n %s = _entry_type("%s", _clad_enum.%s)' % (_name, _name, _name))
if is_upper_case:
missing_definitions_message += ('\n or %s = _entry_type("%s", _clad_enum.%s)' % (pascal_case_name, pascal_case_name, _name))
if add_missing_definitions:
setattr(cls, _name, cls._entry_type(_name, _id))

if missing_definitions_message is not None:
logger.warning(missing_definitions_message)

@classmethod
def _build_id_to_entry_type(cls):
# populate _id_to_entry_type mapping
cls._id_to_entry_type = dict()
for (_name, _entry) in cls.__dict__.items():
if isinstance(_entry, cls._entry_type):
cls._id_to_entry_type[_entry.id] = _entry

@classmethod
def _init_class(cls, warn_on_missing_definitions=True, add_missing_definitions=True):
cls._verify(warn_on_missing_definitions, add_missing_definitions)
cls._build_id_to_entry_type()

+ 667
- 0
Cozmo_LineFollow/venv/Lib/site-packages/cozmo/action.py View File

@@ -0,0 +1,667 @@
# Copyright (c) 2016-2017 Anki, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License in the file LICENSE.txt or at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

'''
Actions encapsulate specific high-level tasks that the Cozmo robot can perform.
They have a definite beginning and end.

These tasks include picking up an object, rotating in place, saying text, etc.

Actions are usually triggered by a call to a method on the
:class:`cozmo.robot.Robot` class such as :meth:`~cozmo.robot.Robot.turn_in_place`

The call will return an object that subclasses :class:`Action` that can be
used to cancel the action, or be observed to wait or be notified when the
action completes (or fails) by calling its
:meth:`~cozmo.event.Dispatcher.wait_for` or
:meth:`~cozmo.event.Dispatcher.add_event_handler` methods.


Warning:
Unless you pass ``in_parallel=True`` when starting the action, no other
action can be active at the same time. Attempting to trigger a non-parallel
action when another action is already in progress will result in a
:class:`~cozmo.exceptions.RobotBusy` exception being raised.

When using ``in_parallel=True`` you may see an action fail with the result
:attr:`ActionResults.TRACKS_LOCKED` - this indicates that another in-progress
action has already locked that movement track (e.g. two actions cannot
move the head at the same time).
'''

# __all__ should order by constants, event classes, other classes, functions.
__all__ = ['ACTION_IDLE', 'ACTION_RUNNING', 'ACTION_SUCCEEDED',
'ACTION_FAILED', 'ACTION_ABORTING',
'EvtActionStarted', 'EvtActionCompleted', 'Action', 'ActionResults']


from collections import namedtuple
import sys

from . import logger

from . import event
from . import exceptions
from ._clad import _clad_to_engine_iface, _clad_to_engine_cozmo, _clad_to_game_cozmo, CladEnumWrapper


#: string: Action idle state
ACTION_IDLE = 'action_idle'

#: string: Action running state
ACTION_RUNNING = 'action_running'

#: string: Action succeeded state
ACTION_SUCCEEDED = 'action_succeeded'

#: string: Action failed state
ACTION_FAILED = 'action_failed'

#: string: Action failed state
ACTION_ABORTING = 'action_aborting'

_VALID_STATES = {ACTION_IDLE, ACTION_RUNNING, ACTION_SUCCEEDED, ACTION_FAILED, ACTION_ABORTING}


class _ActionResult(namedtuple('_ActionResult', 'name id')):
# Tuple mapping between CLAD ActionResult name and ID
# All instances will be members of ActionResults

# Keep _ActionResult as lightweight as a normal namedtuple
__slots__ = ()

def __str__(self):
return 'ActionResults.%s' % self.name


class ActionResults(CladEnumWrapper):
"""The possible result values for an Action.

An Action's result is set when the action completes.
"""
_clad_enum = _clad_to_game_cozmo.ActionResult
_entry_type = _ActionResult

#: Action completed successfully.
SUCCESS = _ActionResult("SUCCESS", _clad_enum.SUCCESS)

#: Action is still running.
RUNNING = _ActionResult("RUNNING", _clad_enum.RUNNING)

#: Action was cancelled (e.g. via :meth:`~cozmo.robot.Robot.abort_all_actions` or
#: :meth:`Action.abort`).
CANCELLED_WHILE_RUNNING = _ActionResult("CANCELLED_WHILE_RUNNING", _clad_enum.CANCELLED_WHILE_RUNNING)

#: Action aborted itself (e.g. had invalid attributes, or a runtime failure).
ABORT = _ActionResult("ABORT", _clad_enum.ABORT)

#: Animation Action aborted itself (e.g. there was an error playing the animation).
ANIM_ABORTED = _ActionResult("ANIM_ABORTED", _clad_enum.ANIM_ABORTED)

#: There was an error related to vision markers.
BAD_MARKER = _ActionResult("BAD_MARKER", _clad_enum.BAD_MARKER)

# (Undocumented) There was a problem related to a subscribed or unsupported message tag (indicates bug in engine)
BAD_MESSAGE_TAG = _ActionResult("BAD_MESSAGE_TAG", _clad_enum.BAD_MESSAGE_TAG)

#: There was a problem with the Object ID provided (e.g. there is no Object with that ID).
BAD_OBJECT = _ActionResult("BAD_OBJECT", _clad_enum.BAD_OBJECT)

#: There was a problem with the Pose provided.
BAD_POSE = _ActionResult("BAD_POSE", _clad_enum.BAD_POSE)

# (Undocumented) The SDK-provided tag was bad (shouldn't occur - would indicate a bug in the SDK)
BAD_TAG = _ActionResult("BAD_TAG", _clad_enum.BAD_TAG)

# (Undocumented) Shouldn't occur outside of factory
FAILED_SETTING_CALIBRATION = _ActionResult("FAILED_SETTING_CALIBRATION", _clad_enum.FAILED_SETTING_CALIBRATION)

#: There was an error following the planned path.
FOLLOWING_PATH_BUT_NOT_TRAVERSING = _ActionResult("FOLLOWING_PATH_BUT_NOT_TRAVERSING", _clad_enum.FOLLOWING_PATH_BUT_NOT_TRAVERSING)

#: The action was interrupted by another Action or Behavior.
INTERRUPTED = _ActionResult("INTERRUPTED", _clad_enum.INTERRUPTED)

#: The robot ended up in an "off treads state" not valid for this action (e.g.
#: the robot was placed on its back while executing a turn)
INVALID_OFF_TREADS_STATE = _ActionResult("INVALID_OFF_TREADS_STATE",
_clad_to_game_cozmo.ActionResult.INVALID_OFF_TREADS_STATE)

#: The Up Axis of a carried object doesn't match the desired placement pose.
MISMATCHED_UP_AXIS = _ActionResult("MISMATCHED_UP_AXIS", _clad_enum.MISMATCHED_UP_AXIS)

#: No valid Animation name was found.
NO_ANIM_NAME = _ActionResult("NO_ANIM_NAME", _clad_enum.NO_ANIM_NAME)

#: An invalid distance value was given.
NO_DISTANCE_SET = _ActionResult("NO_DISTANCE_SET", _clad_enum.NO_DISTANCE_SET)

#: There was a problem with the Face ID (e.g. Cozmo doesn't no where it is).
NO_FACE = _ActionResult("NO_FACE", _clad_enum.NO_FACE)

#: No goal pose was set.
NO_GOAL_SET = _ActionResult("NO_GOAL_SET", _clad_enum.NO_GOAL_SET)

#: No pre-action poses were found (e.g. could not get into position).
NO_PREACTION_POSES = _ActionResult("NO_PREACTION_POSES", _clad_enum.NO_PREACTION_POSES)

#: No object is being carried, but the action requires one.
NOT_CARRYING_OBJECT_ABORT = _ActionResult("NOT_CARRYING_OBJECT_ABORT", _clad_enum.NOT_CARRYING_OBJECT_ABORT)

#: Initial state of an Action to indicate it has not yet started.
NOT_STARTED = _ActionResult("NOT_STARTED", _clad_enum.NOT_STARTED)

#: No sub-action was provided.
NULL_SUBACTION = _ActionResult("NULL_SUBACTION", _clad_enum.NULL_SUBACTION)

#: Cozmo was unable to plan a path.
PATH_PLANNING_FAILED_ABORT = _ActionResult("PATH_PLANNING_FAILED_ABORT", _clad_enum.PATH_PLANNING_FAILED_ABORT)

#: The object that Cozmo is attempting to pickup is unexpectedly moving (e.g
#: it is being moved by someone else).
PICKUP_OBJECT_UNEXPECTEDLY_MOVING = _ActionResult("PICKUP_OBJECT_UNEXPECTEDLY_MOVING", _clad_enum.PICKUP_OBJECT_UNEXPECTEDLY_MOVING)

#: The object that Cozmo thought he was lifting didn't start moving, so he
#: must have missed.
PICKUP_OBJECT_UNEXPECTEDLY_NOT_MOVING = _ActionResult("PICKUP_OBJECT_UNEXPECTEDLY_NOT_MOVING", _clad_enum.PICKUP_OBJECT_UNEXPECTEDLY_NOT_MOVING)

# (Undocumented) Shouldn't occur in SDK usage
SEND_MESSAGE_TO_ROBOT_FAILED = _ActionResult("SEND_MESSAGE_TO_ROBOT_FAILED", _clad_enum.SEND_MESSAGE_TO_ROBOT_FAILED)

#: Cozmo is unexpectedly still carrying an object.
STILL_CARRYING_OBJECT = _ActionResult("STILL_CARRYING_OBJECT", _clad_enum.STILL_CARRYING_OBJECT)

#: The Action timed out before completing correctly.
TIMEOUT = _ActionResult("TIMEOUT", _clad_enum.TIMEOUT)

#: One or more animation tracks (Head, Lift, Body, Face, Backpack Lights, Audio)
#: are already being used by another Action.
TRACKS_LOCKED = _ActionResult("TRACKS_LOCKED", _clad_enum.TRACKS_LOCKED)

#: There was an internal error related to an unexpected type of dock action.
UNEXPECTED_DOCK_ACTION = _ActionResult("UNEXPECTED_DOCK_ACTION", _clad_enum.UNEXPECTED_DOCK_ACTION)

# (Undocumented) Shouldn't occur outside of factory.
UNKNOWN_TOOL_CODE = _ActionResult("UNKNOWN_TOOL_CODE", _clad_enum.UNKNOWN_TOOL_CODE)

# (Undocumented) There was a problem in the subclass's update.
UPDATE_DERIVED_FAILED = _ActionResult("UPDATE_DERIVED_FAILED", _clad_enum.UPDATE_DERIVED_FAILED)

#: Cozmo did not see the expected result (e.g. unable to see cubes in their
#: expected position after a related action).
VISUAL_OBSERVATION_FAILED = _ActionResult("VISUAL_OBSERVATION_FAILED", _clad_enum.VISUAL_OBSERVATION_FAILED)

#: The Action failed, but may succeed if retried.
RETRY = _ActionResult("RETRY", _clad_enum.RETRY)

#: Failed to get into position.
DID_NOT_REACH_PREACTION_POSE = _ActionResult("DID_NOT_REACH_PREACTION_POSE", _clad_enum.DID_NOT_REACH_PREACTION_POSE)

#: Failed to follow the planned path.
FAILED_TRAVERSING_PATH = _ActionResult("FAILED_TRAVERSING_PATH", _clad_enum.FAILED_TRAVERSING_PATH)

#: The previous attempt to pick and place an object failed.
LAST_PICK_AND_PLACE_FAILED = _ActionResult("LAST_PICK_AND_PLACE_FAILED", _clad_enum.LAST_PICK_AND_PLACE_FAILED)

#: The required motor isn't moving so the action cannot complete.
MOTOR_STOPPED_MAKING_PROGRESS = _ActionResult("MOTOR_STOPPED_MAKING_PROGRESS", _clad_enum.MOTOR_STOPPED_MAKING_PROGRESS)

#: Not carrying an object when it was expected, but may succeed if the action is retried.
NOT_CARRYING_OBJECT_RETRY = _ActionResult("NOT_CARRYING_OBJECT_RETRY", _clad_enum.NOT_CARRYING_OBJECT_RETRY)
#: Cozmo is expected to be on the charger, but is not.
NOT_ON_CHARGER = _ActionResult("NOT_ON_CHARGER", _clad_enum.NOT_ON_CHARGER)

#: Cozmo was unable to plan a path, but may succeed if the action is retried.
PATH_PLANNING_FAILED_RETRY = _ActionResult("PATH_PLANNING_FAILED_RETRY", _clad_enum.PATH_PLANNING_FAILED_RETRY)

#: There is no room to place the object at the desired destination.
PLACEMENT_GOAL_NOT_FREE = _ActionResult("PLACEMENT_GOAL_NOT_FREE", _clad_enum.PLACEMENT_GOAL_NOT_FREE)

#: Cozmo failed to drive off the charger.
STILL_ON_CHARGER = _ActionResult("STILL_ON_CHARGER", _clad_enum.STILL_ON_CHARGER)

#: Cozmo's pitch is at an unexpected angle for the Action.
UNEXPECTED_PITCH_ANGLE = _ActionResult("UNEXPECTED_PITCH_ANGLE", _clad_enum.UNEXPECTED_PITCH_ANGLE)


ActionResults._init_class()


class EvtActionStarted(event.Event):
'''Triggered when a robot starts an action.'''
action = "The action that started"


class EvtActionCompleted(event.Event):
'''Triggered when a robot action has completed or failed.'''
action = "The action that completed"
state = 'The state of the action; either cozmo.action.ACTION_SUCCEEDED or cozmo.action.ACTION_FAILED'
failure_code = 'A failure code such as "cancelled"'
failure_reason = 'A human-readable failure reason'


class Action(event.Dispatcher):
"""An action holds the state of an in-progress robot action
"""
# We allow sub-classes of Action to optionally disable logging messages
# related to those actions being aborted - this is useful for actions
# that are aborted frequently (by design) and would otherwise spam the log
_enable_abort_logging = True

def __init__(self, *, conn, robot, **kw):
super().__init__(**kw)
#: :class:`~cozmo.conn.CozmoConnection`: The connection on which the action was sent.
self.conn = conn

#: :class:`~cozmo.robot.Robot`: Th robot instance executing the action.
self.robot = robot

self._action_id = None
self._state = ACTION_IDLE
self._failure_code = None
self._failure_reason = None
self._result = None
self._completed_event = None
self._completed_event_pending = False

def __repr__(self):
extra = self._repr_values()
if len(extra) > 0:
extra = ' '+extra
if self._state == ACTION_FAILED:
extra += (" failure_reason='%s' failure_code=%s result=%s" %
(self._failure_reason, self._failure_code, self.result))
return '<%s state=%s%s>' % (self.__class__.__name__, self.state, extra)

def _repr_values(self):
return ''

def _encode(self):
raise NotImplementedError()

def _start(self):
self._state = ACTION_RUNNING
self.dispatch_event(EvtActionStarted, action=self)

def _set_completed(self, msg):
self._state = ACTION_SUCCEEDED
self._completed_event_pending = False
self._dispatch_completed_event(msg)

def _dispatch_completed_event(self, msg):
# Override to extra action-specific data from msg and generate
# an action-specific completion event. Do not call super if overriden.
# Must generate a subclass of EvtActionCompleted.
self._completed_event = EvtActionCompleted(action=self, state=self._state)
self.dispatch_event(self._completed_event)

def _set_failed(self, code, reason):
self._state = ACTION_FAILED
self._failure_code = code
self._failure_reason = reason
self._completed_event_pending = False
self._completed_event = EvtActionCompleted(action=self, state=self._state,
failure_code=code,
failure_reason=reason)
self.dispatch_event(self._completed_event)

def _set_aborting(self, log_abort_messages):
if not self.is_running:
raise ValueError("Action isn't currently running")

if self._enable_abort_logging and log_abort_messages:
logger.info('Aborting action=%s', self)
self._state = ACTION_ABORTING


#### Properties ####

@property
def is_running(self):
'''bool: True if the action is currently in progress.'''
return self._state == ACTION_RUNNING

@property
def is_completed(self):
'''bool: True if the action has completed (either succeeded or failed).'''
return self._state in (ACTION_SUCCEEDED, ACTION_FAILED)

@property
def is_aborting(self):
'''bool: True if the action is aborting (will soon be either succeeded or failed).'''
return self._state == ACTION_ABORTING

@property
def has_succeeded(self):
'''bool: True if the action has succeeded.'''
return self._state == ACTION_SUCCEEDED

@property
def has_failed(self):
'''bool: True if the action has failed.'''
return self._state == ACTION_FAILED

@property
def failure_reason(self):
'''tuple of (failure_code, failure_reason): Both values will be None if no failure has occurred.'''
return (self._failure_code, self._failure_reason)

@property
def result(self):
"""An attribute of :class:`ActionResults`: The result of running the action."""
return self._result

@property
def state(self):
'''string: The current internal state of the action as a string.

Will match one of the constants:
:const:`ACTION_IDLE`
:const:`ACTION_RUNNING`
:const:`ACTION_SUCCEEDED`
:const:`ACTION_FAILED`
:const:`ACTION_ABORTING`
'''
return self._state


#### Private Event Handlers ####

def _recv_msg_robot_completed_action(self, evt, *, msg):
result = msg.result
types = _clad_to_game_cozmo.ActionResult

self._result = ActionResults.find_by_id(result)
if self._result is None:
logger.error("ActionResults has no entry for result id %s", result)

if result == types.SUCCESS:
# dispatch to the specific type to extract result info
self._set_completed(msg)

elif result == types.RUNNING:
# XXX what does one do with this? it seems to occur after a cancel request!
logger.warning('Received "running" action notification for action=%s', self)
self._set_failed('running', 'Action was still running')

elif result == types.NOT_STARTED:
# not sure we'll see this?
self._set_failed('not_started', 'Action was not started')

elif result == types.TIMEOUT:
self._set_failed('timeout', 'Action timed out')

elif result == types.TRACKS_LOCKED:
self._set_failed('tracks_locked', 'Action failed due to tracks locked')

elif result == types.BAD_TAG:
# guessing this is bad
self._set_failed('bad_tag', 'Action failed due to bad tag')
logger.error("Received FAILURE_BAD_TAG for action %s", self)

elif result == types.CANCELLED_WHILE_RUNNING:
self._set_failed('cancelled', 'Action was cancelled while running')

elif result == types.INTERRUPTED:
self._set_failed('interrupted', 'Action was interrupted')

else:
# All other results should fall under either the abort or retry
# categories, determine the category by shifting the result
result_category = result >> _clad_to_game_cozmo.ARCBitShift.NUM_BITS
result_categories = _clad_to_game_cozmo.ActionResultCategory
if result_category == result_categories.ABORT:
self._set_failed('aborted', 'Action failed')
elif result_category == result_categories.RETRY:
self._set_failed('retry', 'Action failed but can be retried')
else:
# Shouldn't be able to get here
self._set_failed('unknown', 'Action failed with unknown reason')
logger.error('Received unknown action result status %s', msg)


#### Public Event Handlers ####


#### Commands ####

def abort(self, log_abort_messages=False):
'''Trigger the robot to abort the running action.

Args:
log_abort_messages (bool): True to log info on the action that
is aborted.

Raises:
ValueError if the action is not currently being executed.
'''
self.robot._action_dispatcher._abort_action(self, log_abort_messages)

async def wait_for_completed(self, timeout=None):
'''Waits for the action to complete.

Args:
timeout (int or None): Maximum time in seconds to wait for the event.
Pass None to wait indefinitely.
Returns:
The :class:`EvtActionCompleted` event instance
Raises:
:class:`asyncio.TimeoutError`
'''
if self.is_completed:
# Already complete
return self._completed_event
return await self.wait_for(EvtActionCompleted, timeout=timeout)

def on_completed(self, handler):
'''Triggers a handler when the action completes.

Args:
handler (callable): An event handler which accepts arguments
suited to the :class:`EvtActionCompleted` event.
See :meth:`cozmo.event.add_event_handler` for more information.
'''
return self.add_event_handler(EvtActionCompleted, handler)



class _ActionDispatcher(event.Dispatcher):
_next_action_id = _clad_to_game_cozmo.ActionConstants.FIRST_SDK_TAG

def __init__(self, robot, **kw):
super().__init__(**kw)
self.robot = robot
self._in_progress = {}
self._aborting = {}

def _get_next_action_id(self):
# Post increment _current_action_id (and loop within the SDK_TAG range)
next_action_id = self.__class__._next_action_id
if self.__class__._next_action_id == _clad_to_game_cozmo.ActionConstants.LAST_SDK_TAG:
self.__class__._next_action_id = _clad_to_game_cozmo.ActionConstants.FIRST_SDK_TAG
else:
self.__class__._next_action_id += 1
return next_action_id

@property
def aborting_actions(self):
'''generator: yields each action that is currently aborting

Returns:
A generator yielding :class:`cozmo.action.Action` instances
'''
for _, action in self._aborting.items():
yield action

@property
def has_in_progress_actions(self):
'''bool: True if any SDK-triggered actions are still in progress.'''
return len(self._in_progress) > 0

@property
def in_progress_actions(self):
'''generator: yields each action that is currently in progress

Returns:
A generator yielding :class:`cozmo.action.Action` instances
'''
for _, action in self._in_progress.items():
yield action

async def wait_for_all_actions_completed(self):
'''Waits until all actions are complete.

In this case, all actions include not just in_progress actions but also
include actions that we're aborting but haven't received a completed message
for yet.
'''
while True:
action = next(self.in_progress_actions, None)
if action is None:
action = next(self.aborting_actions, None)
if action:
await action.wait_for_completed()
else:
# all actions are now complete
return

def _send_single_action(self, action, in_parallel=False, num_retries=0):
action_id = self._get_next_action_id()
action.robot = self.robot
action._action_id = action_id

if self.has_in_progress_actions and not in_parallel:
# Note - it doesn't matter if previous action was started as in_parallel,
# starting any subsequent action with in_parallel==False will cancel
# any previous actions, so we throw an exception here and require that
# the client explicitly cancel or wait on earlier actions
action = list(self._in_progress.values())[0]
raise exceptions.RobotBusy('Robot is already performing %d action(s) %s' %
(len(self._in_progress), action))

if action.is_running:
raise ValueError('Action is already running')

if action.is_completed:
raise ValueError('Action already ran')

if in_parallel:
position = _clad_to_game_cozmo.QueueActionPosition.IN_PARALLEL
else:
position = _clad_to_game_cozmo.QueueActionPosition.NOW

qmsg = _clad_to_engine_iface.QueueSingleAction(
idTag=action_id, numRetries=num_retries,
position=position, action=_clad_to_engine_iface.RobotActionUnion())
action_msg = action._encode()
cls_name = action_msg.__class__.__name__
# For some reason, the RobotActionUnion type uses properties with a lowercase
# first character, instead of uppercase like all the other unions
cls_name = cls_name[0].lower() + cls_name[1:]
setattr(qmsg.action, cls_name, action_msg)
self.robot.conn.send_msg(qmsg)
self._in_progress[action_id] = action
action._start()

def _is_sdk_action_id(self, action_id):
return ((action_id >= _clad_to_game_cozmo.ActionConstants.FIRST_SDK_TAG)
and (action_id <= _clad_to_game_cozmo.ActionConstants.LAST_SDK_TAG))

def _is_engine_action_id(self, action_id):
return ((action_id >= _clad_to_game_cozmo.ActionConstants.FIRST_ENGINE_TAG)
and (action_id <= _clad_to_game_cozmo.ActionConstants.LAST_ENGINE_TAG))

def _is_game_action_id(self, action_id):
return ((action_id >= _clad_to_game_cozmo.ActionConstants.FIRST_GAME_TAG)
and (action_id <= _clad_to_game_cozmo.ActionConstants.LAST_GAME_TAG))

def _action_id_type(self, action_id):
if self._is_sdk_action_id(action_id):
return "sdk"
elif self._is_engine_action_id(action_id):
return "engine"
elif self._is_game_action_id(action_id):
return "game"
else:
return "unknown"

def _recv_msg_robot_completed_action(self, evt, *, msg):
action_id = msg.idTag
is_sdk_action = self._is_sdk_action_id(action_id)
action = self._in_progress.get(action_id)
was_aborted = False
if action is None:
action = self._aborting.get(action_id)
was_aborted = action is not None
if action is None:
if is_sdk_action:
logger.error('Received completed action message for unknown SDK action_id=%s', action_id)
return
else:
if not is_sdk_action:
action_id_type = self._action_id_type(action_id)
logger.error('Received completed action message for sdk-known %s action_id=%s (was_aborted=%s)',
action_id_type, action_id, was_aborted)

action._completed_event_pending = True

if was_aborted:
if action._enable_abort_logging:
logger.debug('Received completed action message for aborted action=%s', action)
del self._aborting[action_id]
else:
logger.debug('Received completed action message for in-progress action=%s', action)
del self._in_progress[action_id]
# XXX This should generate a real event, not a msg
# Should also dispatch to self so the parent can be notified.
action.dispatch_event(evt)

def _abort_action(self, action, log_abort_messages):
# Mark this in-progress action as aborting - it should get a "Cancelled"
# message back in the next engine tick, and can basically be considered
# cancelled from now.
action._set_aborting(log_abort_messages)

if action._completed_event_pending:
# The action was marked as still running but the ActionDispatcher
# has already received a completion message (and removed it from
# _in_progress) - the action is just waiting to receive a
# robot_completed_action message that is still being dispatched
# via asyncio.ensure_future
logger.debug('Not sending abort for action=%s to engine as it just completed', action)
else:
# move from in-progress to aborting dicts
self._aborting[action._action_id] = action
del self._in_progress[action._action_id]

msg = _clad_to_engine_iface.CancelActionByIdTag(idTag=action._action_id)
self.robot.conn.send_msg(msg)

def _abort_all_actions(self, log_abort_messages):
# Mark any in-progress actions as aborting - they should get a "Cancelled"
# message back in the next engine tick, and can basically be considered
# cancelled from now.
actions_to_abort = self._in_progress
self._in_progress = {}
for action_id, action in actions_to_abort.items():
action._set_aborting(log_abort_messages)
self._aborting[action_id] = action

logger.info('Sending abort request for all actions')
# RobotActionType.UNKNOWN is a wildcard that matches all actions when cancelling.
msg = _clad_to_engine_iface.CancelAction(actionType=_clad_to_engine_cozmo.RobotActionType.UNKNOWN)
self.robot.conn.send_msg(msg)


+ 223
- 0
Cozmo_LineFollow/venv/Lib/site-packages/cozmo/anim.py View File

@@ -0,0 +1,223 @@
# Copyright (c) 2016 Anki, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License in the file LICENSE.txt or at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

'''
Animation related classes, functions, events and values.
'''

# __all__ should order by constants, event classes, other classes, functions.
__all__ = ['EvtAnimationsLoaded', 'EvtAnimationCompleted',
'Animation', 'AnimationTrigger', 'AnimationNames', 'Triggers',
'animation_completed_filter']

import collections

from . import logger

from . import action
from . import exceptions
from . import event

from ._clad import _clad_to_engine_iface, _clad_to_engine_cozmo


class EvtAnimationsLoaded(event.Event):
'''Triggered when animations names have been received from the engine'''


class EvtAnimationCompleted(action.EvtActionCompleted):
'''Triggered when an animation completes.'''
animation_name = "The name of the animation or trigger that completed"


class Animation(action.Action):
'''An Animation describes an actively-playing animation on a robot.'''
def __init__(self, anim_name, loop_count, ignore_body_track=False,
ignore_head_track=False, ignore_lift_track=False, **kw):
super().__init__(**kw)

#: The name of the animation that was dispatched
self.anim_name = anim_name

#: The number of iterations the animation was requested for
self.loop_count = loop_count

#: bool: True to ignore the body track (i.e. the wheels / treads)
self.ignore_body_track = ignore_body_track

#: bool: True to ignore the head track
self.ignore_head_track = ignore_head_track

#: bool: True to ignore the lift track
self.ignore_lift_track = ignore_lift_track


def _repr_values(self):
all_tracks = {"body":self.ignore_body_track,
"head":self.ignore_head_track,
"lift":self.ignore_lift_track}
ignore_tracks = [k for k, v in all_tracks.items() if v]

return "anim_name=%s loop_count=%s ignore_tracks=%s" % (self.anim_name, self.loop_count, str(ignore_tracks))

def _encode(self):
return _clad_to_engine_iface.PlayAnimation(animationName=self.anim_name, numLoops=self.loop_count, ignoreBodyTrack=self.ignore_body_track,
ignoreHeadTrack=self.ignore_head_track, ignoreLiftTrack=self.ignore_lift_track)

def _dispatch_completed_event(self, msg):
self._completed_event = EvtAnimationCompleted(
action=self, state=self._state,
animation_name=self.anim_name)
self.dispatch_event(self._completed_event)


class AnimationTrigger(action.Action):
'''An AnimationTrigger represents a playing animation trigger.

Asking Cozmo to play an AnimationTrigger causes him to pick one of the
animations represented by the group.
'''
def __init__(self, trigger, loop_count, use_lift_safe, ignore_body_track,
ignore_head_track, ignore_lift_track, **kw):
super().__init__(**kw)

#: An attribute of :class:`cozmo.anim.Triggers`: The animation trigger dispatched.
self.trigger = trigger

#: int: The number of iterations the animation was requested for
self.loop_count = loop_count

#: bool: True to automatically ignore the lift track if Cozmo is carrying a cube.
self.use_lift_safe = use_lift_safe

#: bool: True to ignore the body track (i.e. the wheels / treads)
self.ignore_body_track = ignore_body_track

#: bool: True to ignore the head track
self.ignore_head_track = ignore_head_track

#: bool: True to ignore the lift track
self.ignore_lift_track = ignore_lift_track

def _repr_values(self):
all_tracks = {"body":self.ignore_body_track,
"head":self.ignore_head_track,
"lift":self.ignore_lift_track}
ignore_tracks = [k for k, v in all_tracks.items() if v]

return "trigger=%s loop_count=%s ignore_tracks=%s use_lift_safe=%s" % (
self.trigger.name, self.loop_count, str(ignore_tracks), self.use_lift_safe)

def _encode(self):
return _clad_to_engine_iface.PlayAnimationTrigger(
trigger=self.trigger.id, numLoops=self.loop_count,
useLiftSafe=self.use_lift_safe, ignoreBodyTrack=self.ignore_body_track,
ignoreHeadTrack=self.ignore_head_track, ignoreLiftTrack=self.ignore_lift_track)

def _dispatch_completed_event(self, msg):
self._completed_event = EvtAnimationCompleted(
action=self, state=self._state,
animation_name=self.trigger.name)
self.dispatch_event(self._completed_event)


class AnimationNames(event.Dispatcher, set):
'''Holds the set of animation names (strings) returned from the Engine.

Animation names are dynamically retrieved from the engine when the SDK
connects to it, unlike :class:`Triggers` which are defined at runtime.
'''
def __init__(self, conn, **kw):
super().__init__(self, **kw)
self._conn = conn
self._loaded = False

def __contains__(self, key):
if not self._loaded:
raise exceptions.AnimationsNotLoaded("Animations not yet received from engine")
return super().__contains__(key)

def __hash__(self):
# We want to compare AnimationName instances rather than the
# names they contain
return id(self)

def refresh(self):
'''Causes the list of animation names to be re-requested from the engine.

Attempting to play an animation while the list is refreshing will result
in an AnimationsNotLoaded exception being raised.

Generates an EvtAnimationsLoaded event once completed.
'''
self._loaded = False
self.clear()
self._conn.send_msg(_clad_to_engine_iface.RequestAvailableAnimations())

@property
def is_loaded(self):
'''bool: True if the animation names have been received from the engine.'''
return self._loaded != False

async def wait_for_loaded(self, timeout=None):
'''Wait for the animation names to be loaded from the engine.

Returns:
The :class:`EvtAnimationsLoaded` instance once loaded
Raises:
:class:`asyncio.TimeoutError`
'''
if self._loaded:
return self._loaded
return await self.wait_for(EvtAnimationsLoaded, timeout=timeout)

def _recv_msg_animation_available(self, evt, msg):
name = msg.animName
self.add(name)

def _recv_msg_end_of_message(self, evt, msg):
if not self._loaded:
logger.debug("%d animations loaded", len(self))
self._loaded = evt
self.dispatch_event(EvtAnimationsLoaded)


# generate names for each CLAD defined trigger

_AnimTrigger = collections.namedtuple('_AnimTrigger', 'name id')
class Triggers:
"""Playing an animation trigger causes the game engine play an animation of a particular type.

The engine may pick one of a number of actual animations to play based on
Cozmo's mood or emotion, or with random weighting. Thus playing the same
trigger twice may not result in the exact same underlying animation playing
twice.

To play an exact animation, use play_anim with a named animation.

This class holds the set of defined animations triggers to pass to play_anim_trigger.
"""
trigger_list = []

for (_name, _id) in _clad_to_engine_cozmo.AnimationTrigger.__dict__.items():
if not _name.startswith('_'):
trigger = _AnimTrigger(_name, _id)
setattr(Triggers, _name, trigger)
Triggers.trigger_list.append(trigger)


def animation_completed_filter():
'''Creates an :class:`cozmo.event.Filter` to wait specifically for an animation completed event.'''
return event.Filter(action.EvtActionCompleted,
action=lambda action: isinstance(action, Animation))

+ 578
- 0
Cozmo_LineFollow/venv/Lib/site-packages/cozmo/annotate.py View File

@@ -0,0 +1,578 @@
# Copyright (c) 2016-2017 Anki, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License in the file LICENSE.txt or at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

'''Camera image annotation.

.. image:: ../images/annotate.jpg

This module defines an :class:`ImageAnnotator` class used by
:class:`cozmo.world.World` to add annotations to camera images received by Cozmo.

This can include the location of cubes, faces and pets that Cozmo currently sees,
along with user-defined custom annotations.

The ImageAnnotator instance can be accessed as
:attr:`cozmo.world.World.image_annotator`.
'''

# __all__ should order by constants, event classes, other classes, functions.
__all__ = ['DEFAULT_OBJECT_COLORS',
'TOP_LEFT', 'TOP_RIGHT', 'BOTTOM_LEFT', 'BOTTOM_RIGHT',
'RESAMPLE_MODE_NEAREST', 'RESAMPLE_MODE_BILINEAR',
'ImageText', 'Annotator', 'ObjectAnnotator', 'FaceAnnotator',
'PetAnnotator', 'TextAnnotator', 'ImageAnnotator',
'add_img_box_to_image', 'add_polygon_to_image', 'annotator']


import collections
import functools

try:
from PIL import Image, ImageDraw
except (ImportError, SyntaxError):
# may get SyntaxError if accidentally importing old Python 2 version of PIL
ImageDraw = None

from . import event
from . import objects


DEFAULT_OBJECT_COLORS = {
objects.LightCube: 'yellow',
objects.CustomObject: 'purple',
'default': 'red'
}

LEFT = 1
RIGHT = 2
TOP = 4
BOTTOM = 8

#: Top left position
TOP_LEFT = TOP | LEFT

#: Bottom left position
BOTTOM_LEFT = BOTTOM | LEFT

#: Top right position
TOP_RIGHT = TOP | RIGHT

#: Bottom right position
BOTTOM_RIGHT = BOTTOM | RIGHT

if ImageDraw is not None:
#: Fastest resampling mode, use nearest pixel
RESAMPLE_MODE_NEAREST = Image.NEAREST
#: Slower, but smoother, resampling mode - linear interpolation from 2x2 grid of pixels
RESAMPLE_MODE_BILINEAR = Image.BILINEAR
else:
RESAMPLE_MODE_NEAREST = None
RESAMPLE_MODE_BILINEAR = None


class ImageText:
'''ImageText represents some text that can be applied to an image.

The class allows the text to be placed at various positions inside a
bounding box within the image itself.

Args:
text (string): The text to display; may contain newlines
position (int): Where on the screen to render the text
- A constant such at TOP_LEFT or BOTTOM_RIGHT
align (string): Text alignment for multi-line strings
color (string): Color to use for the text - see :mod:`PIL.ImageColor`
font (:mod:`PIL.ImageFont`): Font to use (None for a default font)
line_spacing (int): The vertical spacing for multi-line strings
outline_color (string): Color to use for the outline - see
:mod:`PIL.ImageColor` - use None for no outline.
full_outline (bool): True if the outline should surround the text,
otherwise a cheaper drop-shadow is displayed. Only relevant if
outline_color is specified.
'''
def __init__(self, text, position=BOTTOM_RIGHT, align="left", color="white",
font=None, line_spacing=3, outline_color=None, full_outline=True):
self.text = text
self.position = position
self.align = align
self.color = color
self.font = font
self.line_spacing = line_spacing
self.outline_color = outline_color
self.full_outline = full_outline

def render(self, draw, bounds):
'''Renders the text onto an image within the specified bounding box.

Args:
draw (:class:`PIL.ImageDraw.ImageDraw`): The drawable surface to write on
bounds (tuple of int)
(top_left_x, top_left_y, bottom_right_x, bottom_right_y):
bounding box
Returns:
The same :class:`PIL.ImageDraw.ImageDraw` object as was passed-in with text applied.
'''
(bx1, by1, bx2, by2) = bounds
text_width, text_height = draw.textsize(self.text, font=self.font)

if self.position & TOP:
y = by1
else:
y = by2 - text_height

if self.position & LEFT:
x = bx1
else:
x = bx2 - text_width

# helper method for each draw call below
def _draw_text(pos, color):
draw.text(pos, self.text, font=self.font, fill=color,
align=self.align, spacing=self.line_spacing)

if self.outline_color is not None:
# Pillow doesn't support outlined or shadowed text directly.
# We manually draw the text multiple times to achieve the effect.
if self.full_outline:
_draw_text((x-1, y), self.outline_color)
_draw_text((x+1, y), self.outline_color)
_draw_text((x, y-1), self.outline_color)
_draw_text((x, y+1), self.outline_color)
else:
# just draw a drop shadow (cheaper)
_draw_text((x+1, y+1), self.outline_color)

_draw_text((x,y), self.color)

return draw


def add_img_box_to_image(image, box, color, text=None):
'''Draw a box on an image and optionally add text.

This will draw the outline of a rectangle to the passed in image
in the specified color and optionally add one or more pieces of text
along the inside edge of the rectangle.

Args:
image (:class:`PIL.Image.Image`): The image to draw on
box (:class:`cozmo.util.ImageBox`): The ImageBox defining the rectangle to draw
color (string): A color string suitable for use with PIL - see :mod:`PIL.ImageColor`
text (instance or iterable of :class:`ImageText`): The text to display
- may be a single ImageText instance, or any iterable (eg a list
of ImageText instances) to display multiple pieces of text.
'''
d = ImageDraw.Draw(image)
x1, y1 = box.left_x, box.top_y
x2, y2 = box.right_x, box.bottom_y
d.rectangle([x1, y1, x2, y2], outline=color)
if text is not None:
if isinstance(text, collections.Iterable):
for t in text:
t.render(d, (x1, y1, x2, y2))
else:
text.render(d, (x1, y1, x2, y2))


def add_polygon_to_image(image, poly_points, scale, line_color, fill_color=None):
'''Draw a polygon on an image

This will draw a polygon on the passed-in image in the specified
colors and scale.

Args:
image (:class:`PIL.Image.Image`): The image to draw on
poly_points: A sequence of points representing the polygon,
where each point has float members (x, y)
scale (float): Scale to multiply each point to match the image scaling
line_color (string): The color for the outline of the polygon. The string value
must be a color string suitable for use with PIL - see :mod:`PIL.ImageColor`
fill_color (string): The color for the inside of the polygon. The string value
must be a color string suitable for use with PIL - see :mod:`PIL.ImageColor`
'''
if len(poly_points) < 2:
# Need at least 2 points to draw any lines
return
d = ImageDraw.Draw(image)

# Convert poly_points to the PIL format and scale them to the image
pil_poly_points = []
for pt in poly_points:
pil_poly_points.append((pt.x * scale, pt.y * scale))

d.polygon(pil_poly_points, fill=fill_color, outline=line_color)


def _find_key_for_cls(d, cls):
for cls in cls.__mro__:
result = d.get(cls, None)
if result:
return result
return d['default']


class Annotator:
'''Annotation base class

Subclasses of Annotator handle applying a single annotation to an image.
'''
#: int: The priority of the annotator - Annotators with higher numbered
#: priorities are applied first.
priority = 100

def __init__(self, img_annotator, priority=None):
#: :class:`ImageAnnotator`: The object managing camera annotations
self.img_annotator = img_annotator

#: :class:`~cozmo.world.World`: The world object for the robot who owns the camera
self.world = img_annotator.world

#: bool: Set enabled to false to prevent the annotator being called
self.enabled = True

if priority is not None:
self.priority = priority

def apply(self, image, scale):
'''Applies the annotation to the image.'''
# should be overriden by a subclass
raise NotImplementedError()

def __hash__(self):
return id(self)


class ObjectAnnotator(Annotator):
'''Adds object annotations to an Image.

This handles :class:`cozmo.objects.LightCube` objects
as well as custom objects.
'''
priority = 100
object_colors = DEFAULT_OBJECT_COLORS

def __init__(self, img_annotator, object_colors=None):
super().__init__(img_annotator)
if object_colors is not None:
self.object_colors = object_colors

def apply(self, image, scale):
d = ImageDraw.Draw(image)
for obj in self.world.visible_objects:
color = _find_key_for_cls(self.object_colors, obj.__class__)
text = self.label_for_obj(obj)
box = obj.last_observed_image_box
if scale != 1:
box *= scale
add_img_box_to_image(image, box, color, text=text)

def label_for_obj(self, obj):
'''Fetch a label to display for the object.

Override or replace to customize.
'''
return ImageText(obj.descriptive_name)


class FaceAnnotator(Annotator):
'''Adds annotations of currently detected faces to a camera image.

This handles the display of :class:`cozmo.faces.Face` objects.
'''
priority = 100
box_color = 'green'

def __init__(self, img_annotator, box_color=None):
super().__init__(img_annotator)
if box_color is not None:
self.box_color = box_color

def apply(self, image, scale):
d = ImageDraw.Draw(image)
for obj in self.world.visible_faces:
text = self.label_for_face(obj)
box = obj.last_observed_image_box
if scale != 1:
box *= scale
add_img_box_to_image(image, box, self.box_color, text=text)
add_polygon_to_image(image, obj.left_eye, scale, self.box_color)
add_polygon_to_image(image, obj.right_eye, scale, self.box_color)
add_polygon_to_image(image, obj.nose, scale, self.box_color)
add_polygon_to_image(image, obj.mouth, scale, self.box_color)

def label_for_face(self, obj):
'''Fetch a label to display for the face.

Override or replace to customize.
'''
expression = obj.known_expression
if len(expression) > 0:
# if there is a specific known expression, then also show the score
# (display a % to make it clear the value is out of 100)
expression += "=%s%% " % obj.expression_score
if obj.name:
return ImageText('%s%s (%d)' % (expression, obj.name, obj.face_id))
return ImageText('(unknown%s face %d)' % (expression, obj.face_id))


class PetAnnotator(Annotator):
'''Adds annotations of currently detected pets to a camera image.

This handles the display of :class:`cozmo.pets.Pet` objects.
'''
priority = 100
box_color = 'lightgreen'

def __init__(self, img_annotator, box_color=None):
super().__init__(img_annotator)
if box_color is not None:
self.box_color = box_color

def apply(self, image, scale):
d = ImageDraw.Draw(image)
for obj in self.world.visible_pets:
text = self.label_for_pet(obj)
box = obj.last_observed_image_box
if scale != 1:
box *= scale
add_img_box_to_image(image, box, self.box_color, text=text)

def label_for_pet(self, obj):
'''Fetch a label to display for the pet.

Override or replace to customize.
'''
return ImageText('%d: %s' % (obj.pet_id, obj.pet_type))


class TextAnnotator(Annotator):
'''Adds simple text annotations to a camera image.
'''
priority = 50

def __init__(self, img_annotator, text):
super().__init__(img_annotator)
self.text = text

def apply(self, image, scale):
d = ImageDraw.Draw(image)
self.text.render(d, (0, 0, image.width, image.height))


class _AnnotatorHelper(Annotator):
def __init__(self, img_annotator, wrapped):
super().__init__(img_annotator)
self._wrapped = wrapped

def apply(self, image, scale):
self._wrapped(image, scale, world=self.world, img_annotator=self.img_annotator)


def annotator(f):
'''A decorator for converting a regular function/method into an Annotator.

The wrapped function should have a signature of
``(image, scale, img_annotator=None, world=None, **kw)``
'''
@functools.wraps(f)
def wrapper(img_annotator):
return _AnnotatorHelper(img_annotator, f)
return wrapper


class ImageAnnotator(event.Dispatcher):
'''ImageAnnotator applies annotations to the camera image received from the robot.

This is instantiated by :class:`cozmo.world.World` and is accessible as
:class:`cozmo.world.World.image_annotator`.

By default it defines three active annotators named ``objects``, ``faces`` and ``pets``.

The ``objects`` annotator adds a box around each object (such as light cubes)
that Cozmo can see. The ``faces`` annotator adds a box around each person's
face that Cozmo can recognize. The ``pets`` annotator adds a box around each pet
face that Cozmo can recognize.

Custom annotations can be defined by calling :meth:`add_annotator` with
a name of your choosing and an instance of a :class:`Annotator` subclass,
or use a regular function wrapped with the :func:`annotator` decorator.

Individual annotations can be disabled and re-enabled using the
:meth:`disable_annotator` and :meth:`enable_annotator` methods.

All annotations can be disabled by setting the
:attr:`annotation_enabled` property to False.

E.g. to disable face annotations, call
``coz.world.image_annotator.disable_annotator('faces')``

Annotators each have a priority number associated with them. Annotators
with a larger priority number are rendered first and may be overdrawn by those
with a lower/smaller priority number.
'''
def __init__(self, world, **kw):
super().__init__(**kw)
#: :class:`cozmo.world.World`: World object that created the annotator.
self.world = world

self._annotators = {}
self._sorted_annotators = []
self.add_annotator('objects', ObjectAnnotator(self))
self.add_annotator('faces', FaceAnnotator(self))
self.add_annotator('pets', PetAnnotator(self))

#: If this attribute is set to false, the :meth:`annotate_image` method
#: will continue to provide a scaled image, but will not apply any annotations.
self.annotation_enabled = True

def _sort_annotators(self):
self._sorted_annotators = sorted(self._annotators.values(),
key=lambda an: an.priority, reverse=True)

def add_annotator(self, name, annotator):
'''Adds a new annotator for display.

Annotators are enabled by default.

Args:
name (string): An arbitrary name for the annotator; must not
already be defined
annotator (:class:`Annotator` or callable): The annotator to add
may either by an instance of Annotator, or a factory callable
that will return an instance of Annotator. The callable will
be called with an ImageAnnotator instance as its first argument.
Raises:
:class:`ValueError` if the annotator is already defined.
'''
if name in self._annotators:
raise ValueError('Annotator "%s" is already defined' % (name))
if not isinstance(annotator, Annotator):
annotator = annotator(self)
self._annotators[name] = annotator
self._sort_annotators()

def remove_annotator(self, name):
'''Remove an annotator.

Args:
name (string): The name of the annotator to remove as passed to
:meth:`add_annotator`.
Raises:
KeyError if the annotator isn't registered
'''
del self._annotators[name]
self._sort_annotators()

def get_annotator(self, name):
'''Return a named annotator.

Args:
name (string): The name of the annotator to return
Raises:
KeyError if the annotator isn't registered
'''
return self._annotators[name]

def disable_annotator(self, name):
'''Disable a named annotator.

Leaves the annotator as registered, but does not include its output
in the annotated image.

Args:
name (string): The name of the annotator to disable
'''
if name in self._annotators:
self._annotators[name].enabled = False

def enable_annotator(self, name):
'''Enabled a named annotator.

(re)enable an annotator if it was previously disabled.

Args:
name (string): The name of the annotator to enable
'''
self._annotators[name].enabled = True

def add_static_text(self, name, text, color='white', position=TOP_LEFT):
'''Add some static text to annotated images.

This is a convenience method to create a :class:`TextAnnnotator`
and add it to the image.

Args:
name (string): An arbitrary name for the annotator; must not
already be defined
text (str or :class:`ImageText` instance): The text to display
may be a plain string, or an ImageText instance
color (string): Used if text is a string; defaults to white
position (int): Used if text is a string; defaults to TOP_LEFT
'''
if isinstance(text, str):
text = ImageText(text, position=position, color=color)
self.add_annotator(name, TextAnnotator(self, text))

def annotate_image(self, image, scale=None, fit_size=None, resample_mode=RESAMPLE_MODE_NEAREST):
'''Called by :class:`~cozmo.world.World` to annotate camera images.

Args:
image (:class:`PIL.Image.Image`): The image to annotate
scale (float): If set then the base image will be scaled by the
supplied multiplier. Cannot be combined with fit_size
fit_size (tuple of int): If set, then scale the image to fit inside
the supplied (width, height) dimensions. The original aspect
ratio will be preserved. Cannot be combined with scale.
resample_mode (int): The resampling mode to use when scaling the
image. Should be either :attr:`RESAMPLE_MODE_NEAREST` (fast) or
:attr:`RESAMPLE_MODE_BILINEAR` (slower, but smoother).
Returns:
:class:`PIL.Image.Image`
'''
if ImageDraw is None:
return image

if scale is not None:
if scale == 1:
image = image.copy()
else:
image = image.resize((int(image.width * scale), int(image.height * scale)),
resample=resample_mode)

elif fit_size is not None:
if fit_size == (image.width, image.height):
image = image.copy()
scale = 1
else:
img_ratio = image.width / image.height
fit_width, fit_height = fit_size
fit_ratio = fit_width / fit_height
if img_ratio > fit_ratio:
fit_height = int(fit_width / img_ratio)
elif img_ratio < fit_ratio:
fit_width = int(fit_height * img_ratio)
scale = fit_width / image.width
image = image.resize((fit_width, fit_height))

else:
scale = 1

if not self.annotation_enabled:
return image

for an in self._sorted_annotators:
if an.enabled:
an.apply(image, scale)

return image

+ 21
- 0
Cozmo_LineFollow/venv/Lib/site-packages/cozmo/assets/LICENSE.txt View File

@@ -0,0 +1,21 @@
Anki, Inc. Image and 3D Model License Agreement Version 1.0 (last updated March 28, 2017)

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.

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.

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.

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.

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.

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.

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.

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.

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.

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.

+ 67
- 0
Cozmo_LineFollow/venv/Lib/site-packages/cozmo/assets/cozmo.mtl View File

@@ -0,0 +1,67 @@
# rim around the screen
newmtl ScreenOp_matSG
illum 4
Kd 0.00 0.00 0.00 0.2
Ka 0.00 0.00 0.00 0.2
Tf 1.00 1.00 1.00
Ni 1.00
Ks 0.08 0.08 0.08 0.2
Ns 10

# glass screen
newmtl anisotropic1SG
illum 4
Kd 0.00 0.00 0.00 0.2
Ka 0.00 0.00 0.00 0.2
Tf 0.09 0.09 0.09
Ni 1.00
Ks 0.1 0.1 0.1 0.2
Ns 10

# head, arms+fork, wheels (but not treads)
newmtl blinn2SG
illum 4
Kd 0.82 0.82 0.82
Ka 0.00 0.00 0.00
Tf 1.00 1.00 1.00
Ni 1.00
Ks 0.50 0.50 0.50
Ns 10

# Treads
newmtl blinn3SG
illum 4
Kd 0.10 0.10 0.10
Ka 0.00 0.00 0.00
Tf 1.00 1.00 1.00
Ni 1.00
Ks 0.5 0.5 0.5
Ns 10

# Body and wheel-spacers
newmtl blinn4SG
illum 4
Kd 0.70 0.70 0.70
Ka 0.00 0.00 0.00
Tf 1.00 1.00 1.00
Ni 1.00
Ks 0.50 0.50 0.50
Ns 10

# Eyelids
newmtl lambert2SG
illum 4
Kd 0.00 0.00 0.00
Ka 0.00 0.00 0.00
Tf 1.00 1.00 1.00
Ni 1.00
Ks 0.50 0.50 0.50
Ns 10

# eyes
newmtl shadingMap1SG
illum 4
Kd 0.00 1.00 1.00
Ka 0.00 1.00 1.00
Tf 1.00 1.00 1.00
Ni 0.00

+ 13220
- 0
Cozmo_LineFollow/venv/Lib/site-packages/cozmo/assets/cozmo.obj
File diff suppressed because it is too large
View File


+ 1000
- 0
Cozmo_LineFollow/venv/Lib/site-packages/cozmo/assets/cube.obj
File diff suppressed because it is too large
View File


BIN
Cozmo_LineFollow/venv/Lib/site-packages/cozmo/assets/cube1.jpg View File


+ 9
- 0
Cozmo_LineFollow/venv/Lib/site-packages/cozmo/assets/cube1.mtl View File

@@ -0,0 +1,9 @@
newmtl cube_mtl
map_Kd cube1.jpg
illum 4
Kd 0.65 0.65 0.65
Ka 0.15 0.15 0.15
Tf 1.00 1.00 1.00
Ni 1.00
Ks 0.99 0.99 0.99
Ns 10

BIN
Cozmo_LineFollow/venv/Lib/site-packages/cozmo/assets/cube2.jpg View File


+ 9
- 0
Cozmo_LineFollow/venv/Lib/site-packages/cozmo/assets/cube2.mtl View File

@@ -0,0 +1,9 @@
newmtl cube_mtl
map_Kd cube2.jpg
illum 4
Kd 0.65 0.65 0.65
Ka 0.15 0.15 0.15
Tf 1.00 1.00 1.00
Ni 1.00
Ks 0.99 0.99 0.99
Ns 10

BIN
Cozmo_LineFollow/venv/Lib/site-packages/cozmo/assets/cube3.jpg View File


+ 9
- 0
Cozmo_LineFollow/venv/Lib/site-packages/cozmo/assets/cube3.mtl View File

@@ -0,0 +1,9 @@
newmtl cube_mtl
map_Kd cube3.jpg
illum 4
Kd 0.65 0.65 0.65
Ka 0.15 0.15 0.15
Tf 1.00 1.00 1.00
Ni 1.00
Ks 0.99 0.99 0.99
Ns 10

+ 379
- 0
Cozmo_LineFollow/venv/Lib/site-packages/cozmo/audio.py View File

@@ -0,0 +1,379 @@
# Copyright (c) 2017 Anki, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License in the file LICENSE.txt or at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

'''
Audio related classes, functions, events and values.
'''

# __all__ should order by constants, event classes, other classes, functions.
__all__ = ['AudioEvents']

import collections

from . import logger

from . import action
from . import exceptions
from . import event

from ._clad import _clad_to_engine_iface, _clad_to_engine_cozmo, _clad_to_engine_anki, CladEnumWrapper


# generate names for each CLAD defined trigger

class _AudioEvent(collections.namedtuple('_AudioEvent', 'name id')):
# Tuple mapping between CLAD AudioEvents name and ID
# All instances will be members of AudioEvents

# Keep _AudioEvent as lightweight as a normal namedtuple
__slots__ = ()

def __str__(self):
return 'AudioEvents.%s' % self.name


class AudioEvents(CladEnumWrapper):
"""The possible values for an AudioEvent.
Pass one of these event objects to robot.play_audio() to play the corresponding sound clip.
Example: ``robot.play_audio(cozmo.audio.AudioEvents.MusicFunLoop)``
"""
_clad_enum = _clad_to_engine_anki.AudioMetaData.GameEvent.Codelab
_entry_type = _AudioEvent

#: Reserved Id for invalid sound events
Invalid = _entry_type("Invalid", _clad_enum.Invalid)

#: Stop all playing music
MusicGlobalStop = _entry_type("MusicGlobalStop", _clad_enum.Music_Global_Stop)

#: Mute cozmo background music
MusicBackgroundSilenceOn = _entry_type("MusicBackgroundSilenceOn", _clad_enum.Music_Background_Silence_On)
#: Unmute cozmo background music
MusicBackgroundSilenceOff = _entry_type("MusicBackgroundSilenceOff", _clad_enum.Music_Background_Silence_Off)

#: Initialize the synchronized tiny orchestra system
#: (Will not produce any sound on its own, one of the modes must be triggered)
MusicTinyOrchestraInit = _entry_type("MusicTinyOrchestraInit", _clad_enum.Music_Tiny_Orchestra_Init)
#: Turn off the synchronized tiny orchestra system
MusicTinyOrchestraStop = _entry_type("MusicTinyOrchestraStop", _clad_enum.Music_Tiny_Orchestra_Stop)

#: Turn on the first mode of the synchronized tiny orchestra bass channel
#: (Requires the tiny orchestra system be initialized, and will loop until the system is turned off)
MusicTinyOrchestraBassMode1 = _entry_type("MusicTinyOrchestraBassMode1", _clad_enum.Music_Tiny_Orchestra_Bass_Mode_1)
#: Turn off the first mode of the synchronized tiny orchestra bass channel
MusicTinyOrchestraBassMode1Stop = _entry_type("MusicTinyOrchestraBassMode1Stop", _clad_enum.Music_Tiny_Orchestra_Bass_Mode_1_Stop)
#: Turn on the second mode of the synchronized tiny orchestra bass channel
#: (Requires the tiny orchestra system be initialized, and will loop until the system is turned off)
MusicTinyOrchestraBassMode2 = _entry_type("MusicTinyOrchestraBassMode2", _clad_enum.Music_Tiny_Orchestra_Bass_Mode_2)
#: Turn off the second mode of the synchronized tiny orchestra bass channel
MusicTinyOrchestraBassMode2Stop = _entry_type("MusicTinyOrchestraBassMode2Stop", _clad_enum.Music_Tiny_Orchestra_Bass_Mode_2_Stop)
#: Turn on the third mode of the synchronized tiny orchestra bass channel
#: (Requires the tiny orchestra system be initialized, and will loop until the system is turned off)
MusicTinyOrchestraBassMode3 = _entry_type("MusicTinyOrchestraBassMode3", _clad_enum.Music_Tiny_Orchestra_Bass_Mode_3)
#: Turn off the third mode of the synchronized tiny orchestra bass channel
MusicTinyOrchestraBassMode3Stop = _entry_type("MusicTinyOrchestraBassMode3Stop", _clad_enum.Music_Tiny_Orchestra_Bass_Mode_3_Stop)
#: Turn off all synchronized tiny orchestra bass channels
MusicTinyOrchestraBassStop = _entry_type("MusicTinyOrchestraBassStop", _clad_enum.Music_Tiny_Orchestra_Bass_Stop)

#: Turn on the first mode of the synchronized tiny orchestra glock pluck channel
#: (Requires the tiny orchestra system be initialized, and will loop until the system is turned off)
MusicTinyOrchestraGlockPluckMode1 = _entry_type("MusicTinyOrchestraGlockPluckMode1", _clad_enum.Music_Tiny_Orchestra_Glock_Pluck_Mode_1)
#: Turn off the first mode of the synchronized tiny orchestra glock pluck channel
MusicTinyOrchestraGlockPluckMode1Stop = _entry_type("MusicTinyOrchestraGlockPluckMode1Stop", _clad_enum.Music_Tiny_Orchestra_Glock_Pluck_Mode_1_Stop)
#: Turn on the second mode of the synchronized tiny orchestra glock pluck channel
#: (Requires the tiny orchestra system be initialized, and will loop until the system is turned off)
MusicTinyOrchestraGlockPluckMode2 = _entry_type("MusicTinyOrchestraGlockPluckMode2", _clad_enum.Music_Tiny_Orchestra_Glock_Pluck_Mode_2)
#: Turn off the second mode of the synchronized tiny orchestra glock pluck channel
MusicTinyOrchestraGlockPluckMode2Stop = _entry_type("MusicTinyOrchestraGlockPluckMode2Stop", _clad_enum.Music_Tiny_Orchestra_Glock_Pluck_Mode_2_Stop)
#: Turn on the third mode of the synchronized tiny orchestra glock pluck channel
#: (Requires the tiny orchestra system be initialized, and will loop until the system is turned off)
MusicTinyOrchestraGlockPluckMode3 = _entry_type("MusicTinyOrchestraGlockPluckMode3", _clad_enum.Music_Tiny_Orchestra_Glock_Pluck_Mode_3)
#: Turn off the third mode of the synchronized tiny orchestra glock pluck channel
MusicTinyOrchestraGlockPluckMode3Stop = _entry_type("MusicTinyOrchestraGlockPluckMode3Stop", _clad_enum.Music_Tiny_Orchestra_Glock_Pluck_Mode_3_Stop)
#: Turn off all synchronized tiny orchestra glock pluck channels
MusicTinyOrchestraGlockPluckStop = _entry_type("MusicTinyOrchestraGlockPluckStop", _clad_enum.Music_Tiny_Orchestra_Glock_Pluck_Stop)

#: Turn on the first mode of the synchronized tiny orchestra strings channel
#: (Requires the tiny orchestra system be initialized, and will loop until the system is turned off)
MusicTinyOrchestraStringsMode1 = _entry_type("MusicTinyOrchestraStringsMode1", _clad_enum.Music_Tiny_Orchestra_Strings_Mode_1)
#: Turn off the first mode of the synchronized tiny orchestra strings channel
MusicTinyOrchestraStringsMode1Stop = _entry_type("MusicTinyOrchestraStringsMode1Stop", _clad_enum.Music_Tiny_Orchestra_Strings_Mode_1_Stop)
#: Turn on the second mode of the synchronized tiny orchestra strings channel
#: (Requires the tiny orchestra system be initialized, and will loop until the system is turned off)
MusicTinyOrchestraStringsMode2 = _entry_type("MusicTinyOrchestraStringsMode2", _clad_enum.Music_Tiny_Orchestra_Strings_Mode_2)
#: Turn off the second mode of the synchronized tiny orchestra strings channel
MusicTinyOrchestraStringsMode2Stop = _entry_type("MusicTinyOrchestraStringsMode2Stop", _clad_enum.Music_Tiny_Orchestra_Strings_Mode_2_Stop)
#: Turn on the third mode of the synchronized tiny orchestra strings channel
#: (Requires the tiny orchestra system be initialized, and will loop until the system is turned off)
MusicTinyOrchestraStringsMode3 = _entry_type("MusicTinyOrchestraStringsMode3", _clad_enum.Music_Tiny_Orchestra_Strings_Mode_3)
#: Turn off the third mode of the synchronized tiny orchestra strings channel
MusicTinyOrchestraStringsMode3Stop = _entry_type("MusicTinyOrchestraStringsMode3Stop", _clad_enum.Music_Tiny_Orchestra_Strings_Mode_3_Stop)
#: Turn off all synchronized tiny orchestra strings channels
MusicTinyOrchestraStringsStop = _entry_type("MusicTinyOrchestraStringsStop", _clad_enum.Music_Tiny_Orchestra_Strings_Stop)

#: Plays the first tiny orchestra bass track
#: (Does not repeat. Does not interact with the synchronized tiny orchestra system)
MusicTinyOrchestraBass01Loop = _entry_type("MusicTinyOrchestraBass01Loop", _clad_enum.Music_Tiny_Orchestra_Bass_01_Loop)
#: Stops active plays of the first tiny orchestra bass track
MusicTinyOrchestraBass01LoopStop = _entry_type("MusicTinyOrchestraBass01LoopStop", _clad_enum.Music_Tiny_Orchestra_Bass_01_Loop_Stop)
#: Plays the second tiny orchestra bass track
#: (Does not repeat. Does not interact with the synchronized tiny orchestra system)
MusicTinyOrchestraBass02Loop = _entry_type("MusicTinyOrchestraBass02Loop", _clad_enum.Music_Tiny_Orchestra_Bass_02_Loop)
#: Stops active plays of the second tiny orchestra bass track
MusicTinyOrchestraBass02LoopStop = _entry_type("MusicTinyOrchestraBass02LoopStop", _clad_enum.Music_Tiny_Orchestra_Bass_02_Loop_Stop)
#: Plays the third tiny orchestra bass track
#: (Does not repeat. Does not interact with the synchronized tiny orchestra system)
MusicTinyOrchestraBass03Loop = _entry_type("MusicTinyOrchestraBass03Loop", _clad_enum.Music_Tiny_Orchestra_Bass_03_Loop)
#: Stops active plays of the third tiny orchestra bass track
MusicTinyOrchestraBass03LoopStop = _entry_type("MusicTinyOrchestraBass03LoopStop", _clad_enum.Music_Tiny_Orchestra_Bass_03_Loop_Stop)

#: Plays the first tiny orchestra glock pluck track
#: (Does not repeat. Does not interact with the synchronized tiny orchestra system)
MusicTinyOrchestraGlockPluck01Loop = _entry_type("MusicTinyOrchestraGlockPluck01Loop", _clad_enum.Music_Tiny_Orchestra_Glock_Pluck_01_Loop)
#: Stops active plays of the first tiny orchestra glock pluck track
MusicTinyOrchestraGlockPluck01LoopStop = _entry_type("MusicTinyOrchestraGlockPluck01LoopStop", _clad_enum.Music_Tiny_Orchestra_Glock_Pluck_01_Loop_Stop)
#: Plays the second tiny orchestra glock pluck track
#: (Does not repeat. Does not interact with the synchronized tiny orchestra system)
MusicTinyOrchestraGlockPluck02Loop = _entry_type("MusicTinyOrchestraGlockPluck02Loop", _clad_enum.Music_Tiny_Orchestra_Glock_Pluck_02_Loop)
#: Stops active plays of the second tiny orchestra glock pluck track
MusicTinyOrchestraGlockPluck02LoopStop = _entry_type("MusicTinyOrchestraGlockPluck02LoopStop", _clad_enum.Music_Tiny_Orchestra_Glock_Pluck_02_Loop_Stop)
#: Plays the third tiny orchestra glock pluck track
#: (Does not repeat. Does not interact with the synchronized tiny orchestra system)
MusicTinyOrchestraGlockPluck03Loop = _entry_type("MusicTinyOrchestraGlockPluck03Loop", _clad_enum.Music_Tiny_Orchestra_Glock_Pluck_03_Loop)
#: Stops active plays of the third tiny orchestra glock pluck track
MusicTinyOrchestraGlockPluck03LoopStop = _entry_type("MusicTinyOrchestraGlockPluck03LoopStop", _clad_enum.Music_Tiny_Orchestra_Glock_Pluck_03_Loop_Stop)

#: Plays the first tiny orchestra string track
#: (Does not repeat. Does not interact with the synchronized tiny orchestra system)
MusicTinyOrchestraStrings01Loop = _entry_type("MusicTinyOrchestraStrings01Loop", _clad_enum.Music_Tiny_Orchestra_Strings_01_Loop)
#: Stops active plays of the first tiny orchestra strings track
MusicTinyOrchestraStrings01LoopStop = _entry_type("MusicTinyOrchestraStrings01LoopStop", _clad_enum.Music_Tiny_Orchestra_Strings_01_Loop_Stop)
#: Plays the second tiny orchestra string track
#: (Does not repeat. Does not interact with the synchronized tiny orchestra system)
MusicTinyOrchestraStrings02Loop = _entry_type("MusicTinyOrchestraStrings02Loop", _clad_enum.Music_Tiny_Orchestra_Strings_02_Loop)
#: Stops active plays of the second tiny orchestra strings track
MusicTinyOrchestraStrings02LoopStop = _entry_type("MusicTinyOrchestraStrings02LoopStop", _clad_enum.Music_Tiny_Orchestra_Strings_02_Loop_Stop)
#: Plays the third tiny orchestra string track
#: (Does not repeat. Does not interact with the synchronized tiny orchestra system)
MusicTinyOrchestraStrings03Loop = _entry_type("MusicTinyOrchestraStrings03Loop", _clad_enum.Music_Tiny_Orchestra_Strings_03_Loop)
#: Stops active plays of the third tiny orchestra strings track
MusicTinyOrchestraStrings03LoopStop = _entry_type("MusicTinyOrchestraStrings03LoopStop", _clad_enum.Music_Tiny_Orchestra_Strings_03_Loop_Stop)

#: Plays the cube whack music
MusicCubeWhack = _entry_type("MusicCubeWhack", _clad_enum.Music_Cube_Whack)

#: Plays the level 1 hot potato music
#: (Does not repeat)
MusicHotPotatoLevel1Loop = _entry_type("MusicHotPotatoLevel1Loop", _clad_enum.Music_Hot_Potato_Level_1_Loop)
#: Stops active plays of the level 1 hot potato music
MusicHotPotatoLevel1LoopStop = _entry_type("MusicHotPotatoLevel1LoopStop", _clad_enum.Music_Hot_Potato_Level_1_Loop_Stop)
#: Plays the level 2 hot potato music
#: (Does not repeat)
MusicHotPotatoLevel2Loop = _entry_type("MusicHotPotatoLevel2Loop", _clad_enum.Music_Hot_Potato_Level_2_Loop)
#: Stops active plays of the level 2 hot potato music
MusicHotPotatoLevel2LoopStop = _entry_type("MusicHotPotatoLevel2LoopStop", _clad_enum.Music_Hot_Potato_Level_2_Loop_Stop)
#: Plays the level 3 hot potato music
#: (Does not repeat)
MusicHotPotatoLevel3Loop = _entry_type("MusicHotPotatoLevel3Loop", _clad_enum.Music_Hot_Potato_Level_3_Loop)
#: Stops active plays of the level 3 hot potato music
MusicHotPotatoLevel3LoopStop = _entry_type("MusicHotPotatoLevel3LoopStop", _clad_enum.Music_Hot_Potato_Level_3_Loop_Stop)
#: Plays the level 4 hot potato music
#: (Does not repeat)
MusicHotPotatoLevel4Loop = _entry_type("MusicHotPotatoLevel4Loop", _clad_enum.Music_Hot_Potato_Level_4_Loop)
#: Stops active plays of the level 4 hot potato music
MusicHotPotatoLevel4LoopStop = _entry_type("MusicHotPotatoLevel4LoopStop", _clad_enum.Music_Hot_Potato_Level_4_Loop_Stop)

#: Plays the magic fortune teller reveal music
MusicMagic8RevealStinger = _entry_type("MusicMagic8RevealStinger", _clad_enum.Music_Magic8_Reveal_Stinger)
#: Stops active plays of the magic fortune teller reveal music
MusicMagic8RevealStingerStop = _entry_type("MusicMagic8RevealStingerStop", _clad_enum.Music_Magic8_Reveal_Stinger_Stop)

#: Plays 80s style music
#: (Does not repeat)
MusicStyle80S1159BpmLoop = _entry_type("MusicStyle80S1159BpmLoop", _clad_enum.Music_Style_80S_1_159Bpm_Loop)
#: Stops active plays of 80s style music
MusicStyle80S1159BpmLoopStop = _entry_type("MusicStyle80S1159BpmLoopStop", _clad_enum.Music_Style_80S_1_159Bpm_Loop_Stop)
#: Plays disco style music
#: (Does not repeat)
MusicStyleDisco1135BpmLoop = _entry_type("MusicStyleDisco1135BpmLoop", _clad_enum.Music_Style_Disco_1_135Bpm_Loop)
#: Stops active plays of disco style music
MusicStyleDisco1135BpmLoopStop = _entry_type("MusicStyleDisco1135BpmLoopStop", _clad_enum.Music_Style_Disco_1_135Bpm_Loop_Stop)
#: Plays mambo style music
#: (Does not repeat)
MusicStyleMambo1183BpmLoop = _entry_type("MusicStyleMambo1183BpmLoop", _clad_enum.Music_Style_Mambo_1_183Bpm_Loop)
#: Stops active plays of mambo style music
MusicStyleMambo1183BpmLoopStop = _entry_type("MusicStyleMambo1183BpmLoopStop", _clad_enum.Music_Style_Mambo_1_183Bpm_Loop_Stop)

#: Stops all playing sound effects
SfxGlobalStop = _entry_type("SfxGlobalStop", _clad_enum.Sfx_Global_Stop)

#: Plays cube light sound
SfxCubeLight = _entry_type("SfxCubeLight", _clad_enum.Sfx_Cube_Light)
#: Stops active plays of cube light sound
SfxCubeLightStop = _entry_type("SfxCubeLightStop", _clad_enum.Sfx_Cube_Light_Stop)

#: Plays firetruck timer start sound
SfxFiretruckTimerStart = _entry_type("SfxFiretruckTimerStart", _clad_enum.Sfx_Firetruck_Timer_Start)
#: Stops active plays of firetruck timer start sound
SfxFiretruckTimerStartStop = _entry_type("SfxFiretruckTimerStartStop", _clad_enum.Sfx_Firetruck_Timer_Start_Stop)
#: Plays firetruck timer end sound
SfxFiretruckTimerEnd = _entry_type("SfxFiretruckTimerEnd", _clad_enum.Sfx_Firetruck_Timer_End)
#: Stops active plays of firetruck timer end sound
SfxFiretruckTimerEndStop = _entry_type("SfxFiretruckTimerEndStop", _clad_enum.Sfx_Firetruck_Timer_End_Stop)

#: Plays game win sound
SfxGameWin = _entry_type("SfxGameWin", _clad_enum.Sfx_Game_Win)
#: Stops active plays of game win sound
SfxGameWinStop = _entry_type("SfxGameWinStop", _clad_enum.Sfx_Game_Win_Stop)
#: Plays game lose sound
SfxGameLose = _entry_type("SfxGameLose", _clad_enum.Sfx_Game_Lose)
#: Stops active plays of game lose sound
SfxGameLoseStop = _entry_type("SfxGameLoseStop", _clad_enum.Sfx_Game_Lose_Stop)

#: Plays hot potato cube charge sound
SfxHotPotatoCubeCharge = _entry_type("SfxHotPotatoCubeCharge", _clad_enum.Sfx_Hot_Potato_Cube_Charge)
#: Stops active plays of hot potato cube charge sound
SfxHotPotatoCubeChargeStop = _entry_type("SfxHotPotatoCubeChargeStop", _clad_enum.Sfx_Hot_Potato_Cube_Charge_Stop)
#: Plays hot potato cube ready sound
SfxHotPotatoCubeReady = _entry_type("SfxHotPotatoCubeReady", _clad_enum.Sfx_Hot_Potato_Cube_Ready)
#: Stops active plays of hot potato cube ready sound
SfxHotPotatoCubeReadyStop = _entry_type("SfxHotPotatoCubeReadyStop", _clad_enum.Sfx_Hot_Potato_Cube_Ready_Stop)
#: Plays hot potato pass sound
SfxHotPotatoPass = _entry_type("SfxHotPotatoPass", _clad_enum.Sfx_Hot_Potato_Pass)
#: Stops active plays of hot potato pass sound
SfxHotPotatoPassStop = _entry_type("SfxHotPotatoPassStop", _clad_enum.Sfx_Hot_Potato_Pass_Stop)
#: Plays hot potato timer end sound
SfxHotPotatoTimerEnd = _entry_type("SfxHotPotatoTimerEnd", _clad_enum.Sfx_Hot_Potato_Timer_End)
#: Stops active plays of hot potato timer end sound
SfxHotPotatoTimerEndStop = _entry_type("SfxHotPotatoTimerEndStop", _clad_enum.Sfx_Hot_Potato_Timer_End_Stop)

#: Plays magic fortune teller message reveal sound
SfxMagic8MessageReveal = _entry_type("SfxMagic8MessageReveal", _clad_enum.Sfx_Magic8_Message_Reveal)
#: Stops active plays of magic fortune teller message reveal sound
SfxMagic8MessageRevealStop = _entry_type("SfxMagic8MessageRevealStop", _clad_enum.Sfx_Magic8_Message_Reveal_Stop)

#: Plays magnet attract sound
SfxMagnetAttract = _entry_type("SfxMagnetAttract", _clad_enum.Sfx_Magnet_Attract)
#: Stops active plays of magnet attrack sound
SfxMagnetAttractStop = _entry_type("SfxMagnetAttractStop", _clad_enum.Sfx_Magnet_Attract_Stop)
#: Plays magnet repel sound
SfxMagnetRepel = _entry_type("SfxMagnetRepel", _clad_enum.Sfx_Magnet_Repel)
#: Stops active plays of magnet repel sound
SfxMagnetRepelStop = _entry_type("SfxMagnetRepelStop", _clad_enum.Sfx_Magnet_Repel_Stop)

#: Plays countdown sound
SfxSharedCountdown = _entry_type("SfxSharedCountdown", _clad_enum.Sfx_Shared_Countdown)
#: Stops active plays of countdown sound
SfxSharedCountdownStop = _entry_type("SfxSharedCountdownStop", _clad_enum.Sfx_Shared_Countdown_Stop)
#: Plays cube light on sound
SfxSharedCubeLightOn = _entry_type("SfxSharedCubeLightOn", _clad_enum.Sfx_Shared_Cube_Light_On)
#: Stops active plays of cube light on sound
SfxSharedCubeLightOnStop = _entry_type("SfxSharedCubeLightOnStop", _clad_enum.Sfx_Shared_Cube_Light_On_Stop)
#: Plays error sound
SfxSharedError = _entry_type("SfxSharedError", _clad_enum.Sfx_Shared_Error)
#: Stops active plays of error sound
SfxSharedErrorStop = _entry_type("SfxSharedErrorStop", _clad_enum.Sfx_Shared_Error_Stop)
#: Plays success sound
SfxSharedSuccess = _entry_type("SfxSharedSuccess", _clad_enum.Sfx_Shared_Success)
#: Stops active plays of success sound
SfxSharedSuccessStop = _entry_type("SfxSharedSuccessStop", _clad_enum.Sfx_Shared_Success_Stop)
#: Plays timer click sound
SfxSharedTimerClick = _entry_type("SfxSharedTimerClick", _clad_enum.Sfx_Shared_Timer_Click)
#: Stops active plays of timer click sound
SfxSharedTimerClickStop = _entry_type("SfxSharedTimerClickStop", _clad_enum.Sfx_Shared_Timer_Click_Stop)
#: Plays timer end sound
SfxSharedTimerEnd = _entry_type("SfxSharedTimerEnd", _clad_enum.Sfx_Shared_Timer_End)
#: Stops active plays of timer end sound
SfxSharedTimerEndStop = _entry_type("SfxSharedTimerEndStop", _clad_enum.Sfx_Shared_Timer_End_Stop)
#: Plays timer warning sound
SfxSharedTimerWarning = _entry_type("SfxSharedTimerWarning", _clad_enum.Sfx_Shared_Timer_Warning)
#: Stop all active plays of timer warning sound
SfxSharedTimerWarningStop = _entry_type("SfxSharedTimerWarningStop", _clad_enum.Sfx_Shared_Timer_Warning_Stop)

#: Plays a fun music sound (that loops indefinitely).
MusicFunLoop = _entry_type("Music_Fun_Loop", _clad_enum.Music_Fun_Loop)
#: Stops all active plays of the fun music sound.
MusicFunLoopStop = _entry_type("Music_Fun_Loop_Stop", _clad_enum.Music_Fun_Loop_Stop)

#: Plays the putt-hole-success sound.
SfxPuttHoleSuccess = _entry_type("Sfx_Putt_Hole_Success", _clad_enum.Sfx_Putt_Hole_Success)
#: Stops all active plays of the putt-hole-success sound.
SfxPuttHoleSuccessStop = _entry_type("Sfx_Putt_Hole_Success_Stop", _clad_enum.Sfx_Putt_Hole_Success_Stop)

#: Plays alien invasion sound.
Sfx_Alien_Invasion_Ufo = _entry_type("Sfx_Alien_Invasion_Ufo", _clad_enum.Sfx_Alien_Invasion_Ufo)
#: Stops all active plays of the alien invasion sound.
Sfx_Alien_Invasion_Ufo_Stop = _entry_type("Sfx_Alien_Invasion_Ufo_Stop", _clad_enum.Sfx_Alien_Invasion_Ufo_Stop)

#: Plays brick bash sound.
Sfx_Brick_Bash = _entry_type("Sfx_Brick_Bash", _clad_enum.Sfx_Brick_Bash)
#: Stops all active plays of the brick bash sound.
Sfx_Brick_Bash_Stop = _entry_type("Sfx_Brick_Bash_Stop", _clad_enum.Sfx_Brick_Bash_Stop)

#: Plays constellation star sound.
Sfx_Constellation_Star = _entry_type("Sfx_Constellation_Star", _clad_enum.Sfx_Constellation_Star)
#: Stops all active plays of the constellation star sound.
Sfx_Constellation_Star_Stop = _entry_type("Sfx_Constellation_Star_Stop", _clad_enum.Sfx_Constellation_Star_Stop)

#: Plays egg cracking sound.
Sfx_Egg_Decorating_Crack = _entry_type("Sfx_Egg_Decorating_Crack", _clad_enum.Sfx_Egg_Decorating_Crack)
#: Stops all active plays of the egg cracking sound.
Sfx_Egg_Decorating_Crack_Stop = _entry_type("Sfx_Egg_Decorating_Crack_Stop", _clad_enum.Sfx_Egg_Decorating_Crack_Stop)

#: Plays fidget spinner loop.
Sfx_Fidget_Spinner_Loop_Play = _entry_type("Sfx_Fidget_Spinner_Loop_Play", _clad_enum.Sfx_Fidget_Spinner_Loop_Play)
#: Stops all the fidget spinned looping sound.
Sfx_Fidget_Spinner_Loop_Stop = _entry_type("Sfx_Fidget_Spinner_Loop_Stop", _clad_enum.Sfx_Fidget_Spinner_Loop_Stop)
#: Plays fidget spinner sound.
Sfx_Fidget_Spinner_Start = _entry_type("Sfx_Fidget_Spinner_Start", _clad_enum.Sfx_Fidget_Spinner_Start)
#: Stops all active plays of the fidget spinner sound.
Sfx_Fidget_Spinner_Start_Stop = _entry_type("Sfx_Fidget_Spinner_Start_Stop", _clad_enum.Sfx_Fidget_Spinner_Start_Stop)

#: Plays flappy sound.
Sfx_Flappy_Increase = _entry_type("Sfx_Flappy_Increase", _clad_enum.Sfx_Flappy_Increase)
#: Stops all active plays of the flappy sound.
Sfx_Flappy_Increase_Stop = _entry_type("Sfx_Flappy_Increase_Stop", _clad_enum.Sfx_Flappy_Increase_Stop)

#: Plays morse code dash sound.
Sfx_Morse_Code_Dash = _entry_type("Sfx_Morse_Code_Dash", _clad_enum.Sfx_Morse_Code_Dash)
#: Stops all active plays of the morse code dash sound.
Sfx_Morse_Code_Dash_Stop = _entry_type("Sfx_Morse_Code_Dash_Stop", _clad_enum.Sfx_Morse_Code_Dash_Stop)
#: Plays morse code dot sound.
Sfx_Morse_Code_Dot = _entry_type("Sfx_Morse_Code_Dot", _clad_enum.Sfx_Morse_Code_Dot)
#: Stops all active plays of the morse code dot sound.
Sfx_Morse_Code_Dot_Stop = _entry_type("Sfx_Morse_Code_Dot_Stop", _clad_enum.Sfx_Morse_Code_Dot_Stop)
#: Plays morse code silent sound.
Sfx_Morse_Code_Silent = _entry_type("Sfx_Morse_Code_Silent", _clad_enum.Sfx_Morse_Code_Silent)
#: Stops all active plays of the morse code silent sound.
Sfx_Morse_Code_Silent_Stop = _entry_type("Sfx_Morse_Code_Silent_Stop", _clad_enum.Sfx_Morse_Code_Silent_Stop)

#: Plays paddle ball bounce sound.
Sfx_Paddle_Ball_Bounce = _entry_type("Sfx_Paddle_Ball_Bounce", _clad_enum.Sfx_Paddle_Ball_Bounce)
#: Stops all active plays of the paddle ball bounce sound.
Sfx_Paddle_Ball_Bounce_Stop = _entry_type("Sfx_Paddle_Ball_Bounce_Stop", _clad_enum.Sfx_Paddle_Ball_Bounce_Stop)
#: Plays the first pot of gold sound sound.
Sfx_Pot_O_Gold_Blip_Level1 = _entry_type("Sfx_Pot_O_Gold_Blip_Level1", _clad_enum.Sfx_Pot_O_Gold_Blip_Level1)
#: Stops all active plays of the first pot of gold blip sound.
Sfx_Pot_O_Gold_Blip_Level1_Stop = _entry_type("Sfx_Pot_O_Gold_Blip_Level1_Stop", _clad_enum.Sfx_Pot_O_Gold_Blip_Level1_Stop)
#: Plays the second pot of gold sound sound.
Sfx_Pot_O_Gold_Blip_Level2 = _entry_type("Sfx_Pot_O_Gold_Blip_Level2", _clad_enum.Sfx_Pot_O_Gold_Blip_Level2)
#: Stops all active plays of the second pot of gold blip sound.
Sfx_Pot_O_Gold_Blip_Level2_Stop = _entry_type("Sfx_Pot_O_Gold_Blip_Level2_Stop", _clad_enum.Sfx_Pot_O_Gold_Blip_Level2_Stop)
#: Plays the third pot of gold sound sound.
Sfx_Pot_O_Gold_Blip_Level3 = _entry_type("Sfx_Pot_O_Gold_Blip_Level3", _clad_enum.Sfx_Pot_O_Gold_Blip_Level3)
#: Stops all active plays of the third pot of gold blip sound.
Sfx_Pot_O_Gold_Blip_Level3_Stop = _entry_type("Sfx_Pot_O_Gold_Blip_Level3_Stop", _clad_enum.Sfx_Pot_O_Gold_Blip_Level3_Stop)

AudioEvents._init_class(warn_on_missing_definitions=False)

+ 241
- 0
Cozmo_LineFollow/venv/Lib/site-packages/cozmo/base.py View File

@@ -0,0 +1,241 @@
# Copyright (c) 2016 Anki, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License in the file LICENSE.txt or at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

__all__ = []

import threading

import asyncio
import concurrent.futures
import functools
import inspect
import traceback
import types


class _MetaBase(type):
'''Metaclass for all Cozmo package classes.

Ensures that all *_factory class attributes are wrapped into a _Factory
descriptor to automatically support synchronous operation.
'''

def __new__(mcs, name, bases, attrs, **kw):
for k, v in attrs.items():
if k.endswith('_factory'):
# TODO: check type here too
attrs[k] = _Factory(v)
return super().__new__(mcs, name, bases, attrs, **kw)

def __setattr__(cls, name, val):
if name.endswith('_factory'):
cls.__dict__[name].__set__(cls, val)
else:
super().__setattr__(name, val)


class Base(metaclass=_MetaBase):
'''Base class for Cozmo package objects.

*_factory attributes are automatically wrapped into a _Factory descriptor to
support synchronous operation.
'''

# used by SyncFatory
_sync_thread_id = None
_sync_abort_future = None

def __init__(self, _sync_thread_id=None, _sync_abort_future=None, **kw):
# machinery for SyncFactory
if _sync_abort_future is not None:
self._sync_thread_id = threading.get_ident()
else:
self._sync_thread_id = _sync_thread_id
self._sync_abort_future = _sync_abort_future
super().__init__(**kw)

@property
def loop(self):
''':class:`asyncio.BaseEventLoop`: loop instance that this object is registered with.'''
return getattr(self, '_loop', None)



class _Factory:
'''Descriptor to wraps an object factory method.

If the factory is called while the program is running in synchronous mode
then the objects returned by the factory will be wrapped by a _SyncProxy
object, which translates asynchronous responses to synchronous ones
when made outside of the thread the top level object's event loop is running on.
'''

def __init__(self, factory):
self._wrapped_factory = factory

def __get__(self, ins, owner):
sync_thread_id = getattr(ins, '_sync_thread_id', None)
loop = getattr(ins, '_loop', None)
if sync_thread_id:
# Object instance is running in sync mode
return _SyncFactory(self._wrapped_factory, loop, sync_thread_id, ins._sync_abort_future)
# Pass through to the factory. Set loop here as a convenience as all
# Cozmo objects require it by virtue of inheriting from event.Dispatcher
return functools.partial(self._wrapped_factory, loop=loop)

def __set__(self, ins, val):
self._wrapped_factory = val


def _SyncFactory(f, loop, thread_id, sync_abort_future):
'''Instantiates a class by calling a factory function and then wrapping it with _SyncProxy'''
def factory(*a, **kw):
kw['_sync_thread_id'] = thread_id
kw['_sync_abort_future'] = sync_abort_future
if 'loop' not in kw:
kw['loop'] = loop
obj = f(*a, **kw)
return _mkproxy(obj)
return factory


def _mkpt(cls, name):
# create a passthru function
f = getattr(cls, name)
@functools.wraps(f)
def pt(self, *a, **kw):
wrap = self.__wrapped__
f = object.__getattribute__(wrap, name)
return f(*a, **kw)
return pt


class _SyncProxy:
'''Wraps cozmo objects to provide synchronous access when required.

Each method call and attribute access is passed through to the wrapped object.

If the caller is operating in a different thread to the callee (for example, the
caller is operating outside of the context of the event loop), then any
calls to the wrapped object are dispatched to the event loop running on the
loop's native thread.

Returned co-routines functions and Futures are waited upon until completion.
'''

def __init__(self, wrapped):
self.__wrapped__ = wrapped

def __getattribute__(self, name):
wrapped = object.__getattribute__(self, '__wrapped__')
if name == '__wrapped__':
return wrapped

# if name points to a property, this will execute the property getter
# and return the value, else returns the value according to usual
# lookup rules.
value = object.__getattribute__(wrapped, name)

# determine whether the call is being invoked locally, from within the
# event loop's native thread, or elsewhere (usually the main thread)
thread_id = object.__getattribute__(wrapped, '_sync_thread_id')
is_local_thread = thread_id is None or threading.get_ident() == thread_id

if is_local_thread:
# passthru/no-op if being called from the same thread as the object
# was created from.
return value

if inspect.ismethod(value) and not asyncio.iscoroutinefunction(value):
# Wrap the sync method into a coroutine that can be dispatched
# from the same thread as the main event loop is running in
f = value.__func__
f = _to_coroutine(f)
value = types.MethodType(f, wrapped)
#value = types.MethodType(f, self)

elif inspect.isfunction(value) and not asyncio.iscoroutinefunction(value):
# Dispatch functions in the main event loop thread too
value = _to_coroutine(value)

if inspect.isawaitable(value):
return _dispatch_coroutine(value, wrapped._loop, wrapped._sync_abort_future)

elif asyncio.iscoroutinefunction(value):
# Wrap coroutine into synchronous dispatch
@functools.wraps(value)
def wrap(*a, **kw):
return _dispatch_coroutine(value(*a, **kw), wrapped._loop, wrapped._sync_abort_future)
return wrap

return value

def __setattr__(self, name, value):
if name == '__wrapped__':
return super().__setattr__(name, value)
wrapped = object.__getattribute__(self, '__wrapped__')
return wrapped.__setattr__(name, value)

def __repr__(self):
wrapped = self.__wrapped__
return "wrapped-" + object.__getattribute__(wrapped, '__repr__')()


def _to_coroutine(f):
@functools.wraps(f)
async def wrap(*a, **kw):
return f(*a, **kw)
return wrap


def _mkproxy(obj):
'''Create a _SyncProxy for an object.'''
# dynamically generate a class tailored for the wrapped object.
d = {}
cls = obj.__class__
for name in dir(cls):
if ((name.endswith('__') and name.startswith('__'))
and name not in ('__class__', '__new__', '__init__', '__getattribute__', '__setattr__', '__repr__')):
d[name] = _mkpt(cls, name)

if hasattr(obj, '__aenter__'):
d['__enter__'] = lambda self: self.__wrapper__.__aenter__()
d['__exit__'] = lambda self, *a: self.__wrapper__.__aexit__(*a)

cls = type("_proxy_"+obj.__class__.__name__, (_SyncProxy,), d)
proxy = cls(obj)
obj.__wrapper__ = proxy
return proxy


def _dispatch_coroutine(co, loop, abort_future):
'''Execute a coroutine in a loop's thread and block till completion.

Wraps a co-routine function; calling the function causes the co-routine
to be dispatched in the event loop's thread and blocks until that call completes.

Waits for either the coroutine or abort_future to complete.
abort_future provides the main event loop with a means of triggering a
clean shutdown in the case of an exception.
'''
fut = asyncio.run_coroutine_threadsafe(co, loop)
result = concurrent.futures.wait((fut, abort_future), return_when=concurrent.futures.FIRST_COMPLETED)
result = list(result.done)[0].result()
if getattr(result, '__wrapped__', None) is None:
# If the call retuned the wrapped contents of a _SyncProxy then return
# the enclosing proxy instead to the sync caller
wrapper = getattr(result, '__wrapper__', None)
if wrapper is not None:
result = wrapper
return result

+ 206
- 0
Cozmo_LineFollow/venv/Lib/site-packages/cozmo/behavior.py View File

@@ -0,0 +1,206 @@
# Copyright (c) 2016 Anki, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License in the file LICENSE.txt or at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

'''
Behaviors represent a task that Cozmo may perform for an
indefinite amount of time.

For example, the "LookAroundInPlace" behavior causes Cozmo to start looking
around him (without driving), which will cause events such as
:class:`cozmo.objects.EvtObjectObserved` to be generated as he comes across
objects.

Behaviors must be explicitly stopped before having the robot do something else
(for example, pick up the object he just observed).

Behaviors are started by a call to :meth:`cozmo.robot.Robot.start_behavior`,
which returns a :class:`Behavior` object. Calling the :meth:`~Behavior.stop`
method on that object terminate the behavior.

The :class:`BehaviorTypes` class in this module holds a list of all available
behaviors.
'''

# __all__ should order by constants, event classes, other classes, functions.
__all__ = ['BEHAVIOR_IDLE', 'BEHAVIOR_REQUESTED', 'BEHAVIOR_RUNNING',
'BEHAVIOR_STOPPED',
'EvtBehaviorRequested', 'EvtBehaviorStarted', 'EvtBehaviorStopped',
'Behavior', 'BehaviorTypes']

import collections

from . import logger
from . import event
from ._clad import _clad_to_engine_cozmo, CladEnumWrapper


#: string: Behavior idle state (not requested to run)
BEHAVIOR_IDLE = 'behavior_idle'

#: string: Behavior requested state (waiting for engine to start it)
BEHAVIOR_REQUESTED = 'behavior_requested'

#: string: Behavior running state
BEHAVIOR_RUNNING = 'behavior_running'

#: string: Behavior stopped state
BEHAVIOR_STOPPED = 'behavior_stopped'


class EvtBehaviorRequested(event.Event):
'''Triggered when a behavior is requested to start.'''
behavior = 'The Behavior object'
behavior_type_name = 'The behavior type name - equivalent to behavior.type.name'


class EvtBehaviorStarted(event.Event):
'''Triggered when a behavior starts running on the robot.'''
behavior = 'The Behavior object'
behavior_type_name = 'The behavior type name - equivalent to behavior.type.name'


class EvtBehaviorStopped(event.Event):
'''Triggered when a behavior stops.'''
behavior = 'The behavior type object'
behavior_type_name = 'The behavior type name - equivalent to behavior.type.name'


class Behavior(event.Dispatcher):
'''A Behavior instance describes a behavior the robot is currently performing.

Returned by :meth:`cozmo.robot.Robot.start_behavior`.
'''

def __init__(self, robot, behavior_type, is_active=False, **kw):
super().__init__(**kw)
self.robot = robot
self.type = behavior_type
self._state = BEHAVIOR_IDLE
if is_active:
self._state = BEHAVIOR_REQUESTED
self.dispatch_event(EvtBehaviorRequested, behavior=self, behavior_type_name=self.type.name)

def __repr__(self):
return '<%s type="%s">' % (self.__class__.__name__, self.type.name)

def _on_engine_started(self):
if self._state != BEHAVIOR_REQUESTED:
# has not been requested (is an unrelated behavior transition)
if self.is_running:
logger.warning("Behavior '%s' unexpectedly reported started when already running")
return
self._state = BEHAVIOR_RUNNING
self.dispatch_event(EvtBehaviorStarted, behavior=self, behavior_type_name=self.type.name)

def _set_stopped(self):
if not self.is_active:
return
self._state = BEHAVIOR_STOPPED
self.dispatch_event(EvtBehaviorStopped, behavior=self, behavior_type_name=self.type.name)

def stop(self):
'''Requests that the robot stop performing the behavior.

Has no effect if the behavior is not presently active.
'''
if not self.is_active:
return
self.robot._set_none_behavior()
self._set_stopped()

@property
def is_active(self):
'''bool: True if the behavior is currently active and may run on the robot.'''
return self._state == BEHAVIOR_REQUESTED or self._state == BEHAVIOR_RUNNING

@property
def is_running(self):
'''bool: True if the behavior is currently running on the robot.'''
return self._state == BEHAVIOR_RUNNING

@property
def is_completed(self):
return self._state == BEHAVIOR_STOPPED

async def wait_for_started(self, timeout=5):
'''Waits for the behavior to start.

Args:
timeout (int or None): Maximum time in seconds to wait for the event.
Pass None to wait indefinitely. If a behavior can run it should
usually start within ~0.2 seconds.
Raises:
:class:`asyncio.TimeoutError`
'''
if self.is_running or self.is_completed:
# Already started running
return
await self.wait_for(EvtBehaviorStarted, timeout=timeout)

async def wait_for_completed(self, timeout=None):
'''Waits for the behavior to complete.

Args:
timeout (int or None): Maximum time in seconds to wait for the event.
Pass None to wait indefinitely.
Raises:
:class:`asyncio.TimeoutError`
'''
if self.is_completed:
# Already complete
return
# Wait for behavior to start first - it can't complete without starting,
# and if it doesn't start within a fraction of a second it probably
# never will
await self.wait_for_started()
await self.wait_for(EvtBehaviorStopped, timeout=timeout)


_BehaviorType = collections.namedtuple('_BehaviorType', ['name', 'id'])


class BehaviorTypes(CladEnumWrapper):
'''Defines all executable robot behaviors.

For use with :meth:`cozmo.robot.Robot.start_behavior`.
'''
_clad_enum = _clad_to_engine_cozmo.ExecutableBehaviorType
_entry_type = _BehaviorType

#: Turn and move head, but don't drive, with Cozmo's head angled
#: upwards where faces are likely to be.
FindFaces = _entry_type("FindFaces", _clad_enum.FindFaces)

#: Knock over a stack of cubes.
KnockOverCubes = _entry_type("KnockOverCubes", _clad_enum.KnockOverCubes)

#: Turn and move head, but don't drive, to see what is around Cozmo.
LookAroundInPlace = _entry_type("LookAroundInPlace", _clad_enum.LookAroundInPlace)

#: Tries to "pounce" (drive forward and lower lift) when it detects
#: nearby motion on the ground plane.
PounceOnMotion = _entry_type("PounceOnMotion", _clad_enum.PounceOnMotion)

#: Roll a block, regardless of orientation.
RollBlock = _entry_type("RollBlock", _clad_enum.RollBlock)

#: Pickup one block, and stack it onto another block.
StackBlocks = _entry_type("StackBlocks", _clad_enum.StackBlocks)

# Enroll a Face - for internal use by Face.name_face (requires additional pre/post setup)
_EnrollFace = _entry_type("EnrollFace", _clad_enum.EnrollFace)


# This enum deliberately only exposes a sub-set of working behaviors
BehaviorTypes._init_class(warn_on_missing_definitions=False, add_missing_definitions=False)

+ 579
- 0
Cozmo_LineFollow/venv/Lib/site-packages/cozmo/camera.py View File

@@ -0,0 +1,579 @@
# Copyright (c) 2016 Anki, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License in the file LICENSE.txt or at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

'''Support for Cozmo's camera.

Cozmo has a built-in camera which he uses to observe the world around him.

The :class:`Camera` class defined in this module is made available as
:attr:`cozmo.world.World.camera` and can be used to enable/disable image
sending, enable/disable color images, modify various camera settings,
read the robot's unique camera calibration settings, as well as observe
raw unprocessed images being sent by the robot.

Generally, however, it is more useful to observe
:class:`cozmo.world.EvtNewCameraImage` events, which include the raw camera
images along with annotated images, which can illustrate objects the robot
has identified.
'''

# __all__ should order by constants, event classes, other classes, functions.
__all__ = ['EvtNewRawCameraImage', 'EvtRobotObservedMotion', 'CameraConfig', 'Camera']

import functools
import io

_img_processing_available = True

try:
import numpy as np
from PIL import Image
except ImportError as exc:
np = None
_img_processing_available = exc


from . import event
from . import logger
from . import util

from ._clad import _clad_to_engine_iface, _clad_to_engine_cozmo, _clad_to_game_cozmo


_clad_res = _clad_to_game_cozmo.ImageResolution
RESOLUTIONS = {
_clad_res.VerificationSnapshot: (16, 16),
_clad_res.QQQQVGA: (40, 30),
_clad_res.QQQVGA: (80, 60),
_clad_res.QQVGA: (160, 120),
_clad_res.QVGA: (320, 240),
_clad_res.CVGA: (400, 296),
_clad_res.VGA: (640, 480),
_clad_res.SVGA: (800, 600),
_clad_res.XGA: (1024, 768),
_clad_res.SXGA: (1280, 960),
_clad_res.UXGA: (1600, 1200),
_clad_res.QXGA: (2048, 1536),
_clad_res.QUXGA: (3200, 2400)
}


# wrap functions/methods that require NumPy or PIL with this
# decorator to ensure they fail with a useful error if those packages
# are not loaded.
def _require_img_processing(f):
@functools.wraps(f)
def wrapper(*a, **kw):
if _img_processing_available is not True:
raise ImportError("Camera image processing not available: %s" % _img_processing_available)
return f(*a, **kw)
return wrapper


class EvtNewRawCameraImage(event.Event):
'''Dispatched when a new raw image is received from the robot's camera.

See also :class:`~cozmo.world.EvtNewCameraImage` which provides access
to both the raw image and a scaled and annotated version.
'''
image = 'A PIL.Image.Image object'


class EvtRobotObservedMotion(event.Event):
'''Generated when the robot observes motion.'''
timestamp = "Robot timestamp for when movement was observed"

img_area = "Area of the supporting region for the point, as a fraction of the image"
img_pos = "Centroid of observed motion, relative to top-left corner"

ground_area = "Area of the supporting region for the point, as a fraction of the ground ROI"
ground_pos = "Approximate coordinates of observed motion on the ground, relative to robot, in mm"

has_top_movement = "Movement detected near the top of the robot's view"
top_img_pos = "Coordinates of the centroid of observed motion, relative to top-left corner"

has_left_movement = "Movement detected near the left edge of the robot's view"
left_img_pos = "Coordinates of the centroid of observed motion, relative to top-left corner"

has_right_movement = "Movement detected near the right edge of the robot's view"
right_img_pos = "Coordinates of the centroid of observed motion, relative to top-left corner"


class CameraConfig:
"""The fixed properties for Cozmo's Camera

A full 3x3 calibration matrix for doing 3D reasoning based on the camera
images would look like:

+--------------+--------------+---------------+
|focal_length.x| 0 | center.x |
+--------------+--------------+---------------+
| 0 |focal_length.y| center.y |
+--------------+--------------+---------------+
| 0 | 0 | 1 |
+--------------+--------------+---------------+
"""

def __init__(self,
focal_length_x: float,
focal_length_y: float,
center_x: float,
center_y: float,
fov_x_degrees: float,
fov_y_degrees: float,
min_exposure_time_ms: int,
max_exposure_time_ms: int,
min_gain: float,
max_gain: float):
self._focal_length = util.Vector2(focal_length_x, focal_length_y)
self._center = util.Vector2(center_x, center_y)
self._fov_x = util.degrees(fov_x_degrees)
self._fov_y = util.degrees(fov_y_degrees)
self._min_exposure_time_ms = min_exposure_time_ms
self._max_exposure_time_ms = max_exposure_time_ms
self._min_gain = min_gain
self._max_gain = max_gain

@classmethod
def _create_from_clad(cls, cs):
return cls(cs.focalLengthX, cs.focalLengthY,
cs.centerX, cs.centerY,
cs.fovX, cs.fovY,
cs.minCameraExposureTime_ms, cs.maxCameraExposureTime_ms,
cs.minCameraGain, cs.maxCameraGain)

# Fixed camera properties (calibrated for each robot at the factory).

@property
def focal_length(self):
''':class:`cozmo.util.Vector2`: The focal length of the camera.

This is focal length combined with pixel skew (as the pixels aren't
perfectly square), so there are subtly different values for x and y.
It is in floating point pixel values e.g. <288.87, 288.36>.
'''
return self._focal_length

@property
def center(self):
''':class:`cozmo.util.Vector2`: The focal center of the camera.

This is the position of the optical center of projection within the
image. It will be close to the center of the image, but adjusted based
on the calibration of the lens at the factory. It is in floating point
pixel values e.g. <155.11, 111.40>.
'''
return self._center

@property
def fov_x(self):
''':class:`cozmo.util.Angle`: The x (horizontal) field of view.'''
return self._fov_x

@property
def fov_y(self):
''':class:`cozmo.util.Angle`: The y (vertical) field of view.'''
return self._fov_y

# The fixed range of values supported for this camera.

@property
def min_exposure_time_ms(self):
'''int: The minimum supported exposure time in milliseconds.'''
return self._min_exposure_time_ms

@property
def max_exposure_time_ms(self):
'''int: The maximum supported exposure time in milliseconds.'''
return self._max_exposure_time_ms

@property
def min_gain(self):
'''float: The minimum supported camera gain.'''
return self._min_gain

@property
def max_gain(self):
'''float: The maximum supported camera gain.'''
return self._max_gain


class Camera(event.Dispatcher):
'''Represents Cozmo's camera.

The Camera object receives images from Cozmo's camera and emits
EvtNewRawCameraImage events.

The :class:`cozmo.world.World` instance observes the camera and provides
more useful methods for accessing the camera images.

.. important::
The camera will not receive any image data unless you
explicitly enable it by setting :attr:`Camera.image_stream_enabled`
to ``True``
'''

def __init__(self, robot, **kw):
super().__init__(**kw)
self.robot = robot
self._image_stream_enabled = None
self._color_image_enabled = None
self._config = None # type: CameraConfig
self._gain = 0.0
self._exposure_ms = 0
self._auto_exposure_enabled = True

if np is None:
logger.warning("Camera image processing not available due to missing NumPy or Pillow packages: %s" % _img_processing_available)
else:
# set property to ensure clad initialization is sent.
self.image_stream_enabled = False
self.color_image_enabled = False
self._reset_partial_state()

def enable_auto_exposure(self, enable_auto_exposure = True):
'''Enable auto exposure on Cozmo's Camera.

Enable auto exposure on Cozmo's camera to constantly update the exposure
time and gain values based on the recent images. This is the default mode
when any SDK program starts.

Args:
enable_auto_exposure (bool): whether the camera should automcatically adjust exposure
'''
msg = _clad_to_engine_iface.SetCameraSettings(enableAutoExposure = enable_auto_exposure)
self.robot.conn.send_msg(msg)

def set_manual_exposure(self, exposure_ms, gain):
'''Set manual exposure values for Cozmo's Camera.

Disable auto exposure on Cozmo's camera and force the specified exposure
time and gain values.

Args:
exposure_ms (int): The desired exposure time in milliseconds.
Must be within the robot's
:attr:`~cozmo.camera.Camera.config` exposure range from
:attr:`~cozmo.camera.CameraConfig.min_exposure_time_ms` to
:attr:`~cozmo.camera.CameraConfig.max_exposure_time_ms`
gain (float): The desired gain value.
Must be within the robot's
:attr:`~cozmo.camera.Camera.camera_config` gain range from
:attr:`~cozmo.camera.CameraConfig.min_gain` to
:attr:`~cozmo.camera.CameraConfig.max_gain`

Raises:
:class:`ValueError` if supplied an out-of-range exposure or gain.
'''
cam = self.config

if (exposure_ms < cam.min_exposure_time_ms) or (exposure_ms > cam.max_exposure_time_ms):
raise ValueError('exposure_ms %s out of range %s..%s' %
(exposure_ms, cam.min_exposure_time_ms, cam.max_exposure_time_ms))

if (gain < cam.min_gain) or (gain > cam.max_gain):
raise ValueError('gain %s out of range %s..%s' %
(gain, cam.min_gain, cam.max_gain))

msg = _clad_to_engine_iface.SetCameraSettings(enableAutoExposure=False,
exposure_ms=exposure_ms,
gain=gain)
self.robot.conn.send_msg(msg)

#### Private Methods ####

def _reset_partial_state(self):
self._partial_data = None
self._partial_image_id = None
self._partial_invalid = False
self._partial_size = 0
self._partial_metadata = None
self._last_chunk_id = -1

def _set_config(self, clad_config):
self._config = CameraConfig._create_from_clad(clad_config)

#### Properties ####

@property
@_require_img_processing
def image_stream_enabled(self):
'''bool: Set to true to receive camera images from the robot.'''
if np is None:
return False

return self._image_stream_enabled

@image_stream_enabled.setter
@_require_img_processing
def image_stream_enabled(self, enabled):
if self._image_stream_enabled == enabled:
return

self._image_stream_enabled = enabled

if enabled:
image_send_mode = _clad_to_engine_cozmo.ImageSendMode.Stream
else:
image_send_mode = _clad_to_engine_cozmo.ImageSendMode.Off

msg = _clad_to_engine_iface.ImageRequest(mode=image_send_mode)

self.robot.conn.send_msg(msg)

@property
@_require_img_processing
def color_image_enabled(self):
'''bool: Set to true to receive color images from the robot.'''
if np is None:
return False

return self._color_image_enabled

@color_image_enabled.setter
@_require_img_processing
def color_image_enabled(self, enabled):
if self._color_image_enabled == enabled:
return

self._color_image_enabled = enabled

msg = _clad_to_engine_iface.EnableColorImages(enable = enabled)
self.robot.conn.send_msg(msg)

@property
def config(self):
''':class:`cozmo.camera.CameraConfig`: The read-only config/calibration for the camera'''
return self._config

@property
def is_auto_exposure_enabled(self):
'''bool: True if auto exposure is currently enabled

If auto exposure is enabled the `gain` and `exposure_ms`
values will constantly be updated by Cozmo.
'''
return self._auto_exposure_enabled

@property
def gain(self):
'''float: The current camera gain setting.'''
return self._gain

@property
def exposure_ms(self):
'''int: The current camera exposure setting in milliseconds.'''
return self._exposure_ms

#### Private Event Handlers ####

def _recv_msg_image_chunk(self, evt, *, msg):
if np is None:
return
if self._partial_image_id is not None and msg.chunkId == 0:
if not self._partial_invalid:
logger.debug("Lost final chunk of image; discarding")
self._partial_image_id = None

if self._partial_image_id is None:
if msg.chunkId != 0:
if not self._partial_invalid:
logger.debug("Received chunk of broken image")
self._partial_invalid = True
return
# discard any previous in-progress image
self._reset_partial_state()
self._partial_image_id = msg.imageId
self._partial_metadata = msg

max_size = msg.imageChunkCount * _clad_to_game_cozmo.ImageConstants.IMAGE_CHUNK_SIZE
width, height = RESOLUTIONS[msg.resolution]
max_size = width * height * 3 # 3 bytes (RGB) per pixel
self._partial_data = np.empty(max_size, dtype=np.uint8)

if msg.chunkId != (self._last_chunk_id + 1) or msg.imageId != self._partial_image_id:
logger.debug("Image missing chunks; discarding (last_chunk_id=%d partial_image_id=%s)",
self._last_chunk_id, self._partial_image_id)
self._reset_partial_state()
self._partial_invalid = True
return

offset = self._partial_size
self._partial_data[offset:offset+len(msg.data)] = msg.data
self._partial_size += len(msg.data)
self._last_chunk_id = msg.chunkId

if msg.chunkId == (msg.imageChunkCount - 1):
self._process_completed_image()
self._reset_partial_state()

def _recv_msg_current_camera_params(self, evt, *, msg):
self._gain = msg.cameraGain
self._exposure_ms = msg.exposure_ms
self._auto_exposure_enabled = msg.autoExposureEnabled

def _recv_msg_robot_observed_motion(self, evt, *, msg):
self.dispatch_event(EvtRobotObservedMotion,
timestamp=msg.timestamp,
img_area=msg.img_area,
img_pos=util.Vector2(msg.img_x, msg.img_y),
ground_area=msg.ground_area,
ground_pos=util.Vector2(msg.ground_x, msg.ground_y),
has_top_movement=(msg.top_img_area > 0),
top_img_pos=util.Vector2(msg.top_img_x, msg.top_img_y),
has_left_movement=(msg.left_img_area > 0),
left_img_pos=util.Vector2(msg.left_img_x, msg.left_img_y),
has_right_movement=(msg.right_img_area > 0),
right_img_pos=util.Vector2(msg.right_img_x, msg.right_img_y))

def _process_completed_image(self):
data = self._partial_data[0:self._partial_size]
# The first byte of the image is whether or not it is in color
is_color_image = data[0] != 0
if self._partial_metadata.imageEncoding == _clad_to_game_cozmo.ImageEncoding.JPEGMinimizedGray:
width, height = RESOLUTIONS[self._partial_metadata.resolution]
if is_color_image:
# Color images are half width
width = width // 2
data = _minicolor_to_jpeg(data, width, height)
else:
data = _minigray_to_jpeg(data, width, height)
image = Image.open(io.BytesIO(data)).convert('RGB')

# Color images need to be resized to the proper resolution
if is_color_image:
size = RESOLUTIONS[self._partial_metadata.resolution]
image = image.resize(size)
self._latest_image = image
self.dispatch_event(EvtNewRawCameraImage, image=image)


#### Public Event Handlers ####


@_require_img_processing
def _minigray_to_jpeg(minigray, width, height):
"Converts miniGrayToJpeg format to normal jpeg format"
#This should be 'exactly' what is done in the miniGrayToJpeg function in encodedImage.cpp
header50 = np.array([
0xFF, 0xD8, 0xFF, 0xE0, 0x00, 0x10, 0x4A, 0x46, 0x49, 0x46, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01,
0x00, 0x01, 0x00, 0x00, 0xFF, 0xDB, 0x00, 0x43, 0x00, 0x10, 0x0B, 0x0C, 0x0E, 0x0C, 0x0A, 0x10, #// 0x19 = QTable
0x0E, 0x0D, 0x0E, 0x12, 0x11, 0x10, 0x13, 0x18, 0x28, 0x1A, 0x18, 0x16, 0x16, 0x18, 0x31, 0x23,
0x25, 0x1D, 0x28, 0x3A, 0x33, 0x3D, 0x3C, 0x39, 0x33, 0x38, 0x37, 0x40, 0x48, 0x5C, 0x4E, 0x40,
0x44, 0x57, 0x45, 0x37, 0x38, 0x50, 0x6D, 0x51, 0x57, 0x5F, 0x62, 0x67, 0x68, 0x67, 0x3E, 0x4D,

#//0x71, 0x79, 0x70, 0x64, 0x78, 0x5C, 0x65, 0x67, 0x63, 0xFF, 0xC0, 0x00, 0x0B, 0x08, 0x00, 0xF0, #// 0x5E = Height x Width
0x71, 0x79, 0x70, 0x64, 0x78, 0x5C, 0x65, 0x67, 0x63, 0xFF, 0xC0, 0x00, 0x0B, 0x08, 0x01, 0x28, #// 0x5E = Height x Width

#//0x01, 0x40, 0x01, 0x01, 0x11, 0x00, 0xFF, 0xC4, 0x00, 0xD2, 0x00, 0x00, 0x01, 0x05, 0x01, 0x01,
0x01, 0x90, 0x01, 0x01, 0x11, 0x00, 0xFF, 0xC4, 0x00, 0xD2, 0x00, 0x00, 0x01, 0x05, 0x01, 0x01,

0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04,
0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x10, 0x00, 0x02, 0x01, 0x03, 0x03, 0x02, 0x04, 0x03,
0x05, 0x05, 0x04, 0x04, 0x00, 0x00, 0x01, 0x7D, 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12,
0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07, 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xA1, 0x08,
0x23, 0x42, 0xB1, 0xC1, 0x15, 0x52, 0xD1, 0xF0, 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0A, 0x16,
0x17, 0x18, 0x19, 0x1A, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
0x3A, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
0x5A, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79,
0x7A, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
0x99, 0x9A, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6,
0xB7, 0xB8, 0xB9, 0xBA, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xD2, 0xD3, 0xD4,
0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA,
0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFF, 0xDA, 0x00, 0x08, 0x01, 0x01,
0x00, 0x00, 0x3F, 0x00
], dtype=np.uint8)
return _mini_to_jpeg_helper(minigray, width, height, header50)

@_require_img_processing
def _minicolor_to_jpeg(minicolor, width, height):
"Converts miniColorToJpeg format to normal jpeg format"
#This should be 'exactly' what is done in the miniColorToJpeg function in encodedImage.cpp
header = np.array([
0xFF, 0xD8, 0xFF, 0xE0, 0x00, 0x10, 0x4A, 0x46, 0x49, 0x46, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01,
0x00, 0x01, 0x00, 0x00, 0xFF, 0xDB, 0x00, 0x43, 0x00, 0x10, 0x0B, 0x0C, 0x0E, 0x0C, 0x0A, 0x10, # 0x19 = QTable
0x0E, 0x0D, 0x0E, 0x12, 0x11, 0x10, 0x13, 0x18, 0x28, 0x1A, 0x18, 0x16, 0x16, 0x18, 0x31, 0x23,
0x25, 0x1D, 0x28, 0x3A, 0x33, 0x3D, 0x3C, 0x39, 0x33, 0x38, 0x37, 0x40, 0x48, 0x5C, 0x4E, 0x40,
0x44, 0x57, 0x45, 0x37, 0x38, 0x50, 0x6D, 0x51, 0x57, 0x5F, 0x62, 0x67, 0x68, 0x67, 0x3E, 0x4D,
0x71, 0x79, 0x70, 0x64, 0x78, 0x5C, 0x65, 0x67, 0x63, 0xFF, 0xC0, 0x00, 17, # 8+3*components
0x08, 0x00, 0xF0, # 0x5E = Height x Width
0x01, 0x40,
0x03, # 3 components
0x01, 0x21, 0x00, # Y 2x1 res
0x02, 0x11, 0x00, # Cb
0x03, 0x11, 0x00, # Cr
0xFF, 0xC4, 0x00, 0xD2, 0x00, 0x00, 0x01, 0x05, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04,
0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x10, 0x00, 0x02, 0x01, 0x03, 0x03, 0x02, 0x04, 0x03,
0x05, 0x05, 0x04, 0x04, 0x00, 0x00, 0x01, 0x7D, 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12,
0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07, 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xA1, 0x08,
0x23, 0x42, 0xB1, 0xC1, 0x15, 0x52, 0xD1, 0xF0, 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0A, 0x16,
0x17, 0x18, 0x19, 0x1A, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
0x3A, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
0x5A, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79,
0x7A, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
0x99, 0x9A, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6,
0xB7, 0xB8, 0xB9, 0xBA, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xD2, 0xD3, 0xD4,
0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA,
0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA,
0xFF, 0xDA, 0x00, 12,
0x03, # 3 components
0x01, 0x00, # Y
0x02, 0x00, # Cb same AC/DC
0x03, 0x00, # Cr same AC/DC
0x00, 0x3F, 0x00
], dtype=np.uint8)

return _mini_to_jpeg_helper(minicolor, width, height, header)

@_require_img_processing
def _mini_to_jpeg_helper(mini, width, height, header):
bufferIn = mini.tolist()
currLen = len(mini)

headerLength = len(header)
# For worst case expansion
bufferOut = np.array([0] * (currLen*2 + headerLength), dtype=np.uint8)

for i in range(headerLength):
bufferOut[i] = header[i]

bufferOut[0x5e] = height >> 8
bufferOut[0x5f] = height & 0xff
bufferOut[0x60] = width >> 8
bufferOut[0x61] = width & 0xff
# Remove padding at the end
while (bufferIn[currLen-1] == 0xff):
currLen -= 1

off = headerLength
for i in range(currLen-1):
bufferOut[off] = bufferIn[i+1]
off += 1
if (bufferIn[i+1] == 0xff):
bufferOut[off] = 0
off += 1

bufferOut[off] = 0xff
off += 1
bufferOut[off] = 0xD9

bufferOut[:off]
return np.asarray(bufferOut)

+ 113
- 0
Cozmo_LineFollow/venv/Lib/site-packages/cozmo/clad_protocol.py View File

@@ -0,0 +1,113 @@
# Copyright (c) 2016 Anki, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License in the file LICENSE.txt or at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

__all__ = []


import asyncio
import struct
import sys
from threading import Lock

from . import logger_protocol

LOG_ALL = 'all'

if sys.byteorder != 'little':
raise ImportError("Cozmo SDK doesn't support byte order '%s' - contact Anki support to request this", sys.byteorder)


class CLADProtocol(asyncio.Protocol):
'''Low level CLAD codec'''
_send_mutex = Lock()

clad_decode_union = None
clad_encode_union = None
_clad_log_which = None

def __init__(self):
super().__init__()

self._buf = bytearray()
self._abort_connection = False # abort connection on failed handshake, ignore subsequent messages!

def connection_made(self, transport):
self.transport = transport
logger_protocol.debug('Connected to transport')

def connection_lost(self, exc):
logger_protocol.debug("Connnection to transport lost: %s" % exc)

def data_received(self, data):
self._buf.extend(data)
# pull clad messages out

while not self._abort_connection:
msg = self.decode_msg()
# must compare msg against None, not just "if not msg" as the latter
# would match against any message with len==0 (which is the case
# for deliberately empty messages where the tag alone is the signal).
if msg is None:
return
name = msg.tag_name
if self._clad_log_which is LOG_ALL or (self._clad_log_which is not None and name in self._clad_log_which):
logger_protocol.debug('RECV %s', msg._data)
self.msg_received(msg)

def decode_msg(self):
if len(self._buf) < 2:
return None

# TODO: handle error
# messages are prefixed by a 2 byte length
msg_size = struct.unpack_from('H', self._buf)[0]
if len(self._buf) < 2 + msg_size:
return None

buf, self._buf = self._buf[2:2+msg_size], self._buf[2+msg_size:]

try:
return self.clad_decode_union.unpack(buf)
except ValueError as e:
logger_protocol.warn("Failed to decode CLAD message for buflen=%d: %s", len(buf), e)

def eof_received(self):
logger_protocol.info("EOF received on connection")

def send_msg(self, msg, **params):
if self.transport.is_closing():
return

name = msg.__class__.__name__
msg = self.clad_encode_union(**{name: msg})
msg_buf = msg.pack()
msg_size = struct.pack('H', len(msg_buf))

self._send_mutex.acquire()
try:
self.transport.write(msg_size)
self.transport.write(msg_buf)
if self._clad_log_which is LOG_ALL or (self._clad_log_which is not None and name in self._clad_log_which):
logger_protocol.debug("SENT %s", msg)

finally:
self._send_mutex.release()

def send_msg_new(self, msg):
name = msg.__class__.__name__
return self.send_msg(name, msg)

def msg_received(self, msg):
pass


+ 486
- 0
Cozmo_LineFollow/venv/Lib/site-packages/cozmo/conn.py View File

@@ -0,0 +1,486 @@
# Copyright (c) 2016-2017 Anki, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License in the file LICENSE.txt or at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

'''Engine connection.

The SDK operates by connecting to the Cozmo "engine" - typically the Cozmo
app that runs on an iOS or Android device.

The engine is responsible for much of the work that Cozmo does, including
image recognition, path planning, behaviors and animation handling, etc.

The :mod:`cozmo.run` module takes care of opening a connection over a USB
connection to a device, but the :class:`CozmoConnection` class defined in
this module does the work of relaying messages to and from the engine and
dispatching them to the :class:`cozmo.robot.Robot` instance.
'''

# __all__ should order by constants, event classes, other classes, functions.
__all__ = ['EvtRobotFound', 'CozmoConnection']


import asyncio
import platform

import cozmoclad

from . import logger
from . import anim
from . import clad_protocol
from . import event
from . import exceptions
from . import robot
from . import version

from . import _clad
from ._clad import _clad_to_engine_cozmo, _clad_to_engine_iface, _clad_to_game_cozmo, _clad_to_game_iface


class EvtConnected(event.Event):
'''Triggered when the initial connection to the device has been established.

This connection is setup before contacting the robot - Wait for EvtRobotFound
or EvtRobotReady for a usefully configured Cozmo instance.
'''
conn = 'The connected CozmoConnection object'


class EvtRobotFound(event.Event):
'''Triggered when a Cozmo robot is detected, but before he's initialized.

:class:`cozmo.robot.EvtRobotReady` is dispatched when the robot is fully initialized.
'''
robot = 'The Cozmo object for the robot'


class EvtConnectionClosed(event.Event):
'''Triggered when the connection to the controlling device is closed.
'''
exc = 'The exception that triggered the closure, or None'


# Some messages have no robotID but should still be forwarded to the primary robot
FORCED_ROBOT_MESSAGES = {"AnimationAborted",
"AnimationEvent",
"BehaviorObjectiveAchieved",
"BehaviorTransition",
"BlockPickedUp",
"BlockPlaced",
"BlockPoolDataMessage",
"CarryStateUpdate",
"ChargerEvent",
"ConnectedObjectStates",
"CreatedFixedCustomObject",
"CubeLightsStateTransition",
"CurrentCameraParams",
"DefinedCustomObject",
"DeviceAccelerometerValuesRaw",
"DeviceAccelerometerValuesUser",
"DeviceGyroValues",
"IsDeviceIMUSupported",
"LoadedKnownFace",
"LocatedObjectStates",
"MemoryMapMessage",
"MemoryMapMessageBegin",
"MemoryMapMessageEnd",
"ObjectAccel",
"ObjectAvailable",
"ObjectConnectionState",
"ObjectMoved",
"ObjectPowerLevel",
"ObjectProjectsIntoFOV",
"ObjectStoppedMoving",
"ObjectTapped",
"ObjectTappedFiltered",
"ObjectUpAxisChanged",
"PerRobotSettings",
"ReactionaryBehaviorTransition",
"RobotChangedObservedFaceID",
"RobotCliffEventFinished",
"RobotCompletedAction",
"RobotDeletedAllCustomObjects",
"RobotDeletedCustomMarkerObjects",
"RobotDeletedFixedCustomObjects",
"RobotDelocalized",
"RobotErasedAllEnrolledFaces",
"RobotErasedEnrolledFace",
"RobotObservedFace",
"RobotObservedMotion",
"RobotObservedObject",
"RobotObservedPet",
"RobotObservedPossibleObject",
"RobotOnChargerPlatformEvent",
"RobotPoked",
"RobotReachedEnrollmentCount",
"RobotRenamedEnrolledFace",
"RobotState",
"UnexpectedMovement"}


class CozmoConnection(event.Dispatcher, clad_protocol.CLADProtocol):
'''Manages the connection to the Cozmo app to communicate with the core engine.

An instance of this class is passed to functions used with
:func:`cozmo.run.connect`. At the point the function is executed,
the connection is already established and verified, and the
:class:`EvtConnected` has already been sent.

However, after the initial connection is established, programs will usually
want to call :meth:`wait_for_robot` to wait for an actual Cozmo robot to
be detected and initialized before doing useful work.
'''

#: callable: The factory function that returns a
#: :class:`cozmo.robot.Robot` class or subclass instance.
robot_factory = robot.Robot

#: callable: The factory function that returns an
#: :class:`cozmo.anim.AnimationNames` class or subclass instance.
anim_names_factory = anim.AnimationNames

# overrides for CLADProtocol
clad_decode_union = _clad_to_game_iface.MessageEngineToGame
clad_encode_union = _clad_to_engine_iface.MessageGameToEngine

def __init__(self, *a, **kw):
super().__init__(*a, **kw)
self._is_connected = False
self._is_ui_connected = False
self._running = True
self._robots = {}
self._primary_robot = None

#: A dict containing information about the device the connection is using.
self.device_info = {}

#: An :class:`cozmo.anim.AnimationNames` object that references all
#: available animation names
self.anim_names = self.anim_names_factory(self)


#### Private Methods ####

def __repr__(self):
info = ' '.join(['%s="%s"' % (k, self.device_info[k])
for k in sorted(self.device_info.keys())])
return '<%s %s>' % (self.__class__.__name__, info)

def connection_made(self, transport):
super().connection_made(transport)
self._is_connected = True

def connection_lost(self, exc):
super().connection_lost(exc)
self._is_connected = False
if self._running:
self.abort(exceptions.ConnectionAborted("Lost connection to the device"))
logger.error("Lost connection to the device: %s", exc)

async def shutdown(self):
'''Close the connection to the device.'''
if self._running and self._is_connected:
logger.info("Shutting down connection")
self._running = False
event._abort_futures(exceptions.SDKShutdown())
self._stop_dispatcher()
self.transport.close()

def abort(self, exc):
'''Abort the connection to the device.'''
if self._running:
logger.info('Aborting connection: %s', exc)
self._running = False
# Allow any currently pending futures to complete before the
# remainder are aborted.
self._loop.call_soon(lambda: event._abort_futures(exc))
self._stop_dispatcher()
self.transport.close()


def msg_received(self, msg):
'''Receives low level communication messages from the engine.'''
if not self._running:
return

try:
tag_name = msg.tag_name

if tag_name == 'Ping':
# short circuit to avoid unnecessary event overhead
return self._handle_ping(msg._data)

elif tag_name == 'UiDeviceConnected':
# handle outside of event dispatch for quick abort in case
# of a version mismatch problem.
return self._handle_ui_device_connected(msg._data)

msg = msg._data
robot_id = getattr(msg, 'robotID', None)

event_name = '_Msg' + tag_name

evttype = getattr(_clad, event_name, None)
if evttype is None:
logger.error('Received unknown CLAD message %s', event_name)
return

# Dispatch messages to the robot if they either:
# a) are explicitly white listed in FORCED_ROBOT_MESSAGES
# b) have a robotID specified in the message
# Otherwise dispatch the message through this connection.
if (robot_id is not None) or (tag_name in FORCED_ROBOT_MESSAGES):
if robot_id is None:
# The only robot ID ever used is 1, so it is safe to assume that here as a default.
robot_id = 1
self._process_robot_msg(robot_id, evttype, msg)
else:
self.dispatch_event(evttype, msg=msg)

except Exception as exc:
# No exceptions should reach this point; it's a bug if they do.
self.abort(exc)

def _process_robot_msg(self, robot_id, evttype, msg):
if robot_id != 1:
# Note: some messages replace robotID with value!=1 (like mfgID for example)
# as a result, this log may fire quite often. Log Level is set to debug
# since it suppressed by default (prevents spamming).
logger.debug('INVALID ROBOT_ID SEEN robot_id=%s event=%s msg=%s', robot_id, evttype, msg.__str__())
robot_id = 1 # XXX remove when errant messages have been fixed

# Note: this code constructs the robot if it doesn't exist at this time
robot = self._robots.get(robot_id)
if not robot:
logger.info('Found robot id=%s', robot_id)
robot = self.robot_factory(self, robot_id, is_primary=self._primary_robot is None)
self._robots[robot_id] = robot
if not self._primary_robot:
self._primary_robot = robot
# Dispatch an event notifying that a new robot has been found
# the robot itself will send EvtRobotReady after initialization
self.dispatch_event(EvtRobotFound, robot=robot)

# _initialize will set the robot to a known good state in the
# background and dispatch a EvtRobotReady event when completed.
robot._initialize()

robot.dispatch_event(evttype, msg=msg)


#### Properties ####

@property
def is_connected(self):
'''bool: True if currently connected to the remote engine.'''
return self._is_connected


#### Private Event handlers ####

def _handle_ping(self, msg):
'''Respond to a ping event.'''
if msg.isResponse:
# To avoid duplication, pings originate from engine, and engine
# accumulates the latency info from the responses
logger.error("Only engine should receive responses")
else:
resp = _clad_to_engine_iface.Ping(
counter=msg.counter,
timeSent_ms=msg.timeSent_ms,
isResponse=True)
self.send_msg(resp)

def _recv_default_handler(self, event, **kw):
'''Default event handler.'''
if event.event_name.startswith('msg_animation'):
return self.anim.dispatch_event(event)

logger.debug('Engine received unhandled event_name=%s kw=%s', event, kw)

def _recv_msg_animation_available(self, evt, msg):
self.anim_names.dispatch_event(evt)

def _recv_msg_end_of_message(self, evt, *a, **kw):
self.anim_names.dispatch_event(evt)

def _handle_ui_device_connected(self, msg):
if msg.connectionType != _clad_to_engine_cozmo.UiConnectionType.SdkOverTcp:
# This isn't for us
return

if msg.deviceID != 1:
logger.error('Unexpected Device Id %s', msg.deviceID)
return

# Verify that engine and SDK are compatible
clad_hashes_match = False
try:
cozmoclad.assert_clad_match(msg.toGameCLADHash, msg.toEngineCLADHash)
clad_hashes_match = True
except cozmoclad.CLADHashMismatch as exc:
logger.error(exc)

build_versions_match = (cozmoclad.__build_version__ == '00000.00000.00000'
or cozmoclad.__build_version__ == msg.buildVersion)

if clad_hashes_match and not build_versions_match:
# If CLAD hashes match, and this is only a minor version change,
# then still allow connection (it's just an app hotfix
# that didn't require CLAD or SDK changes)
sdk_major_version = cozmoclad.__build_version__.split(".")[0:2]
build_major_version = msg.buildVersion.split(".")[0:2]
build_versions_match = (sdk_major_version == build_major_version)

if clad_hashes_match and build_versions_match:
connection_success_msg = _clad_to_engine_iface.UiDeviceConnectionSuccess(
connectionType=msg.connectionType,
deviceID=msg.deviceID,
buildVersion = cozmoclad.__version__,
sdkModuleVersion = version.__version__,
pythonVersion = platform.python_version(),
pythonImplementation = platform.python_implementation(),
osVersion = platform.platform(),
cpuVersion = platform.machine())

self.send_msg(connection_success_msg)

else:
try:
wrong_version_msg = _clad_to_engine_iface.UiDeviceConnectionWrongVersion(
reserved=0,
connectionType=msg.connectionType,
deviceID = msg.deviceID,
buildVersion = cozmoclad.__version__)

self.send_msg(wrong_version_msg)
except AttributeError:
pass

line_separator = "=" * 80
error_message = "\n" + line_separator + "\n"

def _trimmed_version(ver_string):
# Trim leading zeros from the version string.
trimmed_string = ""
for i in ver_string.split("."):
trimmed_string += str(int(i)) + "."
return trimmed_string[:-1] # remove trailing "."

if not build_versions_match:
error_message += ("App and SDK versions do not match!\n"
"----------------------------------\n"
"SDK's cozmoclad version: %s\n"
" != app version: %s\n\n"
% (cozmoclad.__version__, _trimmed_version(msg.buildVersion)))

if cozmoclad.__build_version__ < msg.buildVersion:
# App is newer
error_message += ('Please update your SDK to the newest version by calling command:\n'
'"pip3 install --user --upgrade cozmo"\n'
'and downloading the latest examples from:\n'
'http://cozmosdk.anki.com/docs/downloads.html\n')
else:
# SDK is newer
error_message += ('Please either:\n\n'
'1) Update your app to the most recent version on the app store.\n'
'2) Or, if you prefer, please determine which SDK version matches\n'
' your app version at: http://go.anki.com/cozmo-sdk-version\n'
' Then downgrade your SDK by calling the following command,\n'
' replacing SDK_VERSION with the version listed at that page:\n'
' "pip3 install --ignore-installed cozmo==SDK_VERSION"\n')

else:
# CLAD version mismatch
error_message += ('CLAD Hashes do not match!\n'
'-------------------------\n'
'Your Python and C++ CLAD versions do not match - connection refused.\n'
'Please check that you have the most recent versions of both the SDK and the\n'
'Cozmo app. You may update your SDK by calling:\n'
'"pip3 install --user --upgrade cozmo".\n'
'Please also check the app store for a Cozmo app update.\n')

error_message += line_separator
logger.error(error_message)

exc = exceptions.SDKVersionMismatch("SDK library does not match software running on device",
sdk_version=version.__version__,
sdk_app_version=cozmoclad.__version__,
app_version=_trimmed_version(msg.buildVersion))

self._abort_connection = True # Ignore remaining messages - they're not safe to unpack

self.abort(exc)
return

self._is_ui_connected = True
self.dispatch_event(EvtConnected, conn=self)

logger.info('App connection established. sdk_version=%s '
'cozmoclad_version=%s app_build_version=%s',
version.__version__, cozmoclad.__version__, msg.buildVersion)

# We send RequestConnectedObjects and RequestLocatedObjectStates before
# refreshing the animation names as this ensures that we will receive
# the responses before we mark the robot as ready.
self._request_connected_objects()
self._request_located_objects()

self.anim_names.refresh()

def _request_connected_objects(self):
# Request information on connected objects (e.g. the object ID of each cube)
# (this won't provide location/pose info)
msg = _clad_to_engine_iface.RequestConnectedObjects()
self.send_msg(msg)

def _request_located_objects(self):
# Request the pose information for all objects whose location we know
# (this won't include any objects where the location is currently not known)
msg = _clad_to_engine_iface.RequestLocatedObjectStates()
self.send_msg(msg)

def _recv_msg_image_chunk(self, evt, *, msg):
if self._primary_robot:
self._primary_robot.dispatch_event(evt)

#### Public Event Handlers ####

#### Commands ####

async def _wait_for_robot(self, timeout=5):
if not self._primary_robot:
await self.wait_for(EvtRobotFound, timeout=timeout)
if self._primary_robot.is_ready:
return self._primary_robot
await self._primary_robot.wait_for(robot.EvtRobotReady, timeout=timeout)
return self._primary_robot

async def wait_for_robot(self, timeout=5):
'''Wait for a Cozmo robot to connect and complete initialization.

Args:
timeout (float): Maximum length of time to wait for a robot to be ready in seconds.
Returns:
A :class:`cozmo.robot.Robot` instance that's ready to use.
Raises:
:class:`asyncio.TimeoutError` if there's no response from the robot.
'''
try:
robot = await self._wait_for_robot(timeout)
if robot and robot.drive_off_charger_on_connect:
await robot.drive_off_charger_contacts().wait_for_completed()
except asyncio.TimeoutError:
logger.error('Timed out waiting for robot to initialize')
raise
return robot

+ 618
- 0
Cozmo_LineFollow/venv/Lib/site-packages/cozmo/event.py View File

@@ -0,0 +1,618 @@
# Copyright (c) 2016 Anki, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License in the file LICENSE.txt or at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

'''Event dispatch system.

The SDK is based around the dispatch and observation of events.
Objects inheriting from the :class:`Dispatcher` generate and
dispatch events as the state of the robot and its world are updated.

For example the :class:`cozmo.objects.LightCube` class generates an
:class:`~cozmo.objects.EvtObjectTapped` event anytime the cube the object
represents is tapped.

The event can be observed in a number of different ways:

#. By calling the :meth:`~Dispatcher.wait_for` method on the object to observe.
This will wait until the specific event has been sent to that object and
return the generated event.
#. By calling :meth:`~Dispatcher.add_event_handler` on the object
to observe, which will cause the supplied function to be called every time
the specified event occurs (use the :func:`oneshot` decorator
to only have the handler called once)
#. By sub-classing a type and implementing a receiver method.
For example, subclass the :class:`cozmo.objects.LightCube` type and implement `evt_object_tapped`.
Note that the factory attribute would need to be updated on the
generating class for your type to be used by the SDK.
For example, :attr:`~cozmo.world.World.light_cube_factory` in this example.
#. By subclassing a type and implementing a default receiver method.
Events not dispatched to an explicit receiver method are dispatched to
`recv_default_handler`.

Events are dispatched to a target object (by calling :meth:`dispatch_event`
on the receiving object). In line with the above, upon receiving an event,
the object will:

#. Dispatch the event to any handlers which have explicitly registered interest
in the event (or a superclass of the event) via
:meth:`~Dispatcher.add_event_handler` or via :meth:`Dispatcher.wait_for`
#. Dispatch the event to any "children" of the object (see below)
#. Dispatch the event to method handlers on the receiving object, or the
`recv_default_handler` if it has no matching handler
#. Dispatch the event to the parent of the object (if any), and in turn onto
the parent's parents.

Any handler may raise a :class:`~cozmo.exceptions.StopPropogation` exception
to prevent the event reaching any subsequent handlers (but generally should
have no need to do so).

Child objects receive all events that are sent to the originating object
(which may have multiple children).

Originating objects may have one parent object, which receives all events sent
to its child.

For example, :class:`cozmo.robot.Robot` creates a :class:`cozmo.world.World`
object and sets itself as a parent and the World as the child; both receive
events sent to the other.

The World class creates individual :class:`cozmo.objects.ObservableObject` objects
as they are discovered and makes itself a parent, so as to receive all events
sent to the child. However, it does not make those ObservableObject objects children
for the sake of message dispatch as they only need to receive a small subset
of messages the World object receives.
'''

# __all__ should order by constants, event classes, other classes, functions.
__all__ = ['Event', 'Dispatcher', 'Filter', 'Handler',
'oneshot', 'filter_handler', 'wait_for_first']


import asyncio
import collections
import inspect
import re
import weakref

from . import base
from . import exceptions
from . import logger


# from https://stackoverflow.com/questions/1175208/elegant-python-function-to-convert-camelcase-to-snake-case
_first_cap_re = re.compile('(.)([A-Z][a-z]+)')
_all_cap_re = re.compile('([a-z0-9])([A-Z])')
def _uncamelcase(name):
s1 = _first_cap_re.sub(r'\1_\2', name)
return _all_cap_re.sub(r'\1_\2', s1).lower()

registered_events = {}

active_dispatchers = weakref.WeakSet()

class _rprop:
def __init__(self, value):
self._value = value
def __get__(self, instance, owner):
return self._value

class docstr(str):
@property
def __doc__(self):
return self.__str__()


class _AutoRegister(type):
'''helper to automatically register event classes wherever they're defined
without requiring a class decorator'''

def __new__(mcs, name, bases, attrs, **kw):
if name in ('Event',):
return super().__new__(mcs, name, bases, attrs, **kw)

if not (name.startswith('Evt') or name.startswith('_Evt') or name.startswith('_Msg')):
raise ValueError('Event class names must begin with "Evt (%s)"' % name)

if '__doc__' not in attrs:
raise ValueError('Event classes must have a docstring')

props = set()
for base in bases:
if hasattr(base, '_props'):
props.update(base._props)

newattrs = {'_internal': False}
for k, v in attrs.items():
if k[0] == '_':
newattrs[k] = v
continue
if k in props:
raise ValueError("Event class %s duplicates property %s defined in superclass" % (mcs, k))
props.add(k)
newattrs[k] = docstr(v)
newattrs['_props'] = props
newattrs['_props_sorted'] = sorted(props)

if name[0] == '_':
newattrs['_internal'] = True
name = name[1:]

# create a read only property for the event name
newattrs['event_name'] = _rprop(name)
return super().__new__(mcs, name, bases, newattrs, **kw)

def __init__(cls, name, bases, attrs, **kw):
if name in registered_events:
raise ValueError("Duplicate event name %s (%s duplicated by %s)"
% (name, _full_qual_name(cls), _full_qual_name(registered_events[name])))
registered_events[name] = cls
super().__init__(name, bases, attrs, **kw)


def _full_qual_name(obj):
return obj.__module__ + '.' + obj.__qualname__


class Event(metaclass=_AutoRegister):
'''An event representing an action that has occurred.

Instances of an Event have attributes set to values passed to the event.

For example, :class:`cozmo.objects.EvtObjectTapped` defines obj and tap_count
parameters which can be accessed as ``evt.obj`` and ``evt.tap_count``.
'''

#_first_raised_by = "The object that generated the event"
#_last_raised_by = "The object that last relayed the event to the dispatched handler"

#pylint: disable=no-member
# Event Metaclass raises "no-member" pylint errors in pylint within this scope.

def __init__(self, **kwargs):
unset = self._props.copy()
for k, v in kwargs.items():
if k not in self._props:
raise ValueError("Event %s has no parameter called %s" % (self.event_name, k))
setattr(self, k, v)
unset.remove(k)
for k in unset:
setattr(self, k, None)
self._delivered_to = set()

def __repr__(self):
kvs = {'name': self.event_name}
for k in self._props_sorted:
kvs[k] = getattr(self, k)
return '<%s %s>' % (self.__class__.__name__, ' '.join(['%s=%s' % kv for kv in kvs.items()]),)

def _params(self):
return {k: getattr(self, k) for k in self._props}

@classmethod
def _handler_method_name(cls):
name = 'recv_' + _uncamelcase(cls.event_name)
if cls._internal:
name = '_' + name
return name

def _dispatch_to_func(self, f):
return f(self, **self._params())

def _dispatch_to_obj(self, obj, fallback_to_default=True):
for cls in self._parent_event_classes():
f = getattr(obj, cls._handler_method_name(), None)
if f and not self._is_filtered(f):
return self._dispatch_to_func(f)

if fallback_to_default:
name = 'recv_default_handler'
if self._internal:
name = '_' + name
f = getattr(obj, name, None)
if f and not self._is_filtered(f):
return f(self, **self._params())

def _dispatch_to_future(self, fut):
if not fut.done():
fut.set_result(self)

def _is_filtered(self, f):
filters = getattr(f, '_handler_filters', None)
if filters is None:
return False
for filter in filters:
if filter(self):
return False
return True

def _parent_event_classes(self):
for cls in self.__class__.__mro__:
if cls != Event and issubclass(cls, Event):
yield cls


def _register_dynamic_event_type(event_name, attrs):
return type(event_name, (Event,), attrs)


class Handler(collections.namedtuple('Handler', 'obj evt f')):
'''A Handler is returned by :meth:`Dispatcher.add_event_handler`

The handler can be disabled at any time by calling its :meth:`disable`
method.
'''
__slots__ = ()

def disable(self):
'''Removes the handler from the object it was originally registered with.'''
return self.obj.remove_event_handler(self.evt, self.f)

@property
def oneshot(self):
'''bool: True if the wrapped handler function will only be called once.'''
return getattr(self.f, '_oneshot_handler', False)


class NullHandler(Handler):
def disable(self):
pass


class Dispatcher(base.Base):
'''Mixin to provide event dispatch handling.'''

def __init__(self, *a, dispatch_parent=None, loop=None, **kw):
super().__init__(**kw)
active_dispatchers.add(self)
self._dispatch_parent = dispatch_parent
self._dispatch_children = []
self._dispatch_handlers = collections.defaultdict(list)
if not loop:
raise ValueError("Loop was not supplied to "+self.__class__.__name__)
self._loop = loop or asyncio.get_event_loop()
self._dispatcher_running = True

def _set_parent_dispatcher(self, parent):
self._dispatch_parent = parent

def _add_child_dispatcher(self, child):
self._dispatch_children.append(child)

def _stop_dispatcher(self):
"""Stop dispatching events - call before closing the connection to prevent stray dispatched events"""
self._dispatcher_running = False

def add_event_handler(self, event, f):
"""Register an event handler to be notified when this object receives a type of Event.

Expects a subclass of Event as the first argument. If the class has
subclasses then the handler will be notified for events of that subclass too.
For example, adding a handler for :class:`~cozmo.action.EvtActionCompleted`
will cause the handler to also be notified for
:class:`~cozmo.anim.EvtAnimationCompleted` as it's a subclass.

Callable handlers (e.g. functions) are called with a first argument
containing an Event instance and the remaining keyword arguments set as
the event parameters.

For example, ``def my_ontap_handler(evt, *, obj, tap_count, **kwargs)``
or ``def my_ontap_handler(evt, obj=None, tap_count=None, **kwargs)``

It's recommended that a ``**kwargs`` parameter be included in the
definition so that future expansion of event parameters do not cause
the handler to fail.

Callable handlers may raise an events.StopProgation exception to prevent
other handlers listening to the same event from being triggered.

:class:`asyncio.Future` handlers are called with a result set to the event.

Args:
event (:class:`Event`): A subclass of :class:`Event` (not an instance of that class)
f (callable): A callable or :class:`asyncio.Future` to execute when the event is received
Raises:
:class:`TypeError`: An invalid event type was supplied

"""
if not issubclass(event, Event):
raise TypeError("event must be a subclass of Event (not an instance)")

if not self._dispatcher_running:
return NullHandler(self, event, f)

if isinstance(f, asyncio.Future):
# futures can only be called once.
f = oneshot(f)

handler = Handler(self, event, f)
self._dispatch_handlers[event.event_name].append(handler)
return handler

def remove_event_handler(self, event, f):
"""Remove an event handler for this object.

Args:
event (:class:`Event`): The event class, or an instance thereof,
used with register_event_handler.
f (callable or :class:`Handler`): The callable object that was
passed as a handler to :meth:`add_event_handler`, or a
:class:`Handler` instance that was returned by
:meth:`add_event_handler`.
Raises:
:class:`ValueError`: No matching handler found.
"""
if not (isinstance(event, Event) or (isinstance(event, type) and issubclass(event, Event))):
raise TypeError("event must be a subclasss or instance of Event")

if isinstance(f, Handler):
for i, h in enumerate(self._dispatch_handlers[event.event_name]):
if h == f:
del self._dispatch_handlers[event.event_name][i]
return
else:
for i, h in enumerate(self._dispatch_handlers[event.event_name]):
if h.f == f:
del self._dispatch_handlers[event.event_name][i]
return
raise ValueError("No matching handler found for %s (%s)" % (event.event_name, f) )

def dispatch_event(self, event, **kw):
'''Dispatches a single event to registered handlers.

Not generally called from user-facing code.

Args:
event (:class:`Event`): An class or instance of :class:`Event`
kw (dict): If a class is passed to event, then the remaining keywords
are passed to it to create an instance of the event.
Returns:
A :class:`asyncio.Task` or :class:`asyncio.Future` that will
complete once all event handlers have been called.
Raises:
:class:`TypeError` if an invalid event is supplied.
'''

if not self._dispatcher_running:
return

event_cls = event
if not isinstance(event, Event):
if not isinstance(event, type) or not issubclass(event, Event):
raise TypeError("events must be a subclass or instance of Event")
# create an instance of the event if passed a class
event = event(**kw)
else:
event_cls = event.__class__

if id(self) in event._delivered_to:
return
event._delivered_to.add(id(self))

handlers = set()
for cls in event._parent_event_classes():
for handler in self._dispatch_handlers[cls.event_name]:
if event._is_filtered(handler.f):
continue

if getattr(handler.f, '_oneshot_handler', False):
# Disable oneshot events prior to actual dispatch
handler.disable()
handlers.add(handler)

return asyncio.ensure_future(self._dispatch_event(event, handlers), loop=self._loop)

async def _dispatch_event(self, event, handlers):
# iterate through events from child->parent
# update the dispatched_to set for each event so each handler
# only receives the most specific event if they are monitoring for both.

try:
# dispatch to local handlers
for handler in handlers:
if isinstance(handler.f, asyncio.Future):
event._dispatch_to_future(handler.f)
else:
result = event._dispatch_to_func(handler.f)
if asyncio.iscoroutine(result):
await result

# dispatch to children
for child in self._dispatch_children:
child.dispatch_event(event)

# dispatch to self methods
result = event._dispatch_to_obj(self)
if asyncio.iscoroutine(result):
await result

# dispatch to parent dispatcher
if self._dispatch_parent:
self._dispatch_parent.dispatch_event(event)

except exceptions.StopPropogation:
pass

def _abort_event_futures(self, exc):
'''Sets an exception on all pending Future handlers

This prevents coroutines awaiting a Future from blocking forever
should a hard failure occur with the connection.
'''
handlers = set()
for evh in self._dispatch_handlers.values():
for h in evh:
handlers.add(h)

for handler in handlers:
if isinstance(handler.f, asyncio.Future):
if not handler.f.done():
handler.f.set_exception(exc)
handler.disable()

async def wait_for(self, event_or_filter, timeout=30):
'''Waits for the specified event to be sent to the current object.

Args:
event_or_filter (:class:`Event`): Either a :class:`Event` class
or a :class:`Filter` instance to wait to trigger
timeout: Maximum time to wait for the event. Pass None to wait indefinitely.
Returns:
The :class:`Event` instance that was dispatched
Raises:
:class:`asyncio.TimeoutError`
'''
f = asyncio.Future(loop=self._loop) # replace with loop.create_future in 3.5.2
# TODO: add a timer that logs every 5 seconds that the event is still being
# waited on. Will help novice programmers realize why their program is hanging.
f = oneshot(f)

if isinstance(event_or_filter, Filter):
f = filter_handler(event_or_filter)(f)
event = event_or_filter._event
else:
event = event_or_filter

self.add_event_handler(event, f)
if timeout:
return await asyncio.wait_for(f, timeout, loop=self._loop)
return await f


def oneshot(f):
'''Event handler decorator; causes the handler to only be dispatched to once.'''
f._oneshot_handler = True
return f


def filter_handler(event, **filters):
'''Decorates a handler function or Future to only be called if a filter is matched.

A handler may apply multiple separate filters; the handlers will be called
if any of those filters matches.

For example::

# Handle only if the anim_majorwin animation completed
@filter_handler(cozmo.anim.EvtAnimationCompleted, animation_name="anim_majorwin")

# Handle only when the observed object is a LightCube
@filter_handler(cozmo.objects.EvtObjectObserved, obj=lambda obj: isinstance(cozmo.objects.LightCube))

Args:
event (:class:`Event`): The event class to match on
filters (dict): Zero or more event parameters to filter on. Values may
be either strings for exact matches, or functions which accept the
value as the first argument and return a bool indicating whether
the value passes the filter.
'''

if isinstance(event, Filter):
if len(filters) != 0:
raise ValueError("Cannot supply filter values when passing a Filter as the first argument")
filter = event
else:
filter = Filter(event, **filters)

def filter_property(f):
if hasattr(f, '_handler_filters'):
f._handler_filters.append(filter)
else:
f._handler_filters = [filter]
return f
return filter_property


class Filter:
"""Provides fine-grain filtering of events for dispatch.

See the ::func::`filter_handler` method for further details.
"""

def __init__(self, event, **filters):
if not issubclass(event, Event):
raise TypeError("event must be a subclass of Event (not an instance)")
self._event = event
self._filters = filters
for key in self._filters.keys():
if not hasattr(event, key):
raise AttributeError("Event %s does not define property %s", event.__name__, key)

def __setattr__(self, key, val):
if key[0] == '_':
return super().__setattr__(key, val)
if not hasattr(self._event, key):
raise AttributeError("Event %s does not define property %s", self._event.__name__, key)
self._filters[key] = val

def __call__(self, evt):
for prop, filter in self._filters.items():
val = getattr(evt, prop)
if callable(filter):
if not filter(val):
return False
elif val != filter:
return False
return True


async def wait_for_first(*futures, discard_remaining=True, loop=None):
'''Wait the first of a set of futures to complete.

Eg::

event = cozmo.event.wait_for_first(
coz.world.wait_for_new_cube(),
playing_anim.wait_for(cozmo.anim.EvtAnimationCompleted)
)

If more than one completes during a single event loop run, then
if any of those results are not exception, one of them will be selected
(at random, as determined by ``set.pop``) to be returned, else one
of the result exceptions will be raised instead.

Args:
futures (list of :class:`asyncio.Future`): The futures or coroutines to wait on.
discard_remaining (bool): Cancel or discard the results of the futures
that did not return first.
loop (:class:`asyncio.BaseEventLoop`): The event loop to wait on.
Returns:
The first result, or raised exception
'''
done, pending = await asyncio.wait(futures, loop=loop, return_when=asyncio.FIRST_COMPLETED)

# collect the results from all "done" futures; only one will be returned
result = None
for fut in done:
try:
fut_result = fut.result()
if result is None or isinstance(result, BaseException):
result = fut_result
except Exception as exc:
if result is None:
result = exc

if discard_remaining:
# cancel the pending futures
for fut in pending:
fut.cancel()

if isinstance(result, BaseException):
raise result
return result


def _abort_futures(exc):
'''Trigger the exception handler for all pending Future handlers.'''
for obj in active_dispatchers:
obj._abort_event_futures(exc)

+ 74
- 0
Cozmo_LineFollow/venv/Lib/site-packages/cozmo/exceptions.py View File

@@ -0,0 +1,74 @@
# Copyright (c) 2016 Anki, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License in the file LICENSE.txt or at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

'''SDK-specific exception classes.'''

# __all__ should order by constants, event classes, other classes, functions.
__all__ = ['CozmoSDKException', 'SDKShutdown', 'StopPropogation',
'AnimationsNotLoaded', 'ActionError', 'ConnectionError',
'ConnectionAborted', 'ConnectionCheckFailed', 'NoDevicesFound',
'SDKVersionMismatch', 'NotPickupable', 'CannotPlaceObjectsOnThis',
'RobotBusy', 'InvalidOpenGLGlutImplementation']


class CozmoSDKException(Exception):
'''Base class of all Cozmo SDK exceptions.'''

class SDKShutdown(CozmoSDKException):
'''Raised when the SDK is being shut down'''

class StopPropogation(CozmoSDKException):
'''Raised by event handlers to prevent further handlers from being triggered.'''

class AnimationsNotLoaded(CozmoSDKException):
'''Raised if an attempt is made to play a named animation before animations have been received.'''

class ActionError(CozmoSDKException):
'''Base class for errors that occur with robot actions.'''

class ConnectionError(CozmoSDKException):
'''Base class for errors regarding connection to the device.'''

class ConnectionAborted(ConnectionError):
'''Raised if the connection to the device is unexpectedly lost.'''

class ConnectionCheckFailed(ConnectionError):
'''Raised if the connection check has failed.'''

class NoDevicesFound(ConnectionError):
'''Raised if no devices connected running Cozmo in SDK mode'''

class SDKVersionMismatch(ConnectionError):
'''Raised if the Cozmo SDK version is not compatible with the software running on the device.'''
def __init__(self, message, sdk_version, sdk_app_version, app_version, *args):
super().__init__(message, sdk_version, sdk_app_version, app_version, *args)
#: str: The SDK version number in Major.Minor.Patch format.
#: See :ref:`sdk-versions` for which App version is compatible with each SDK version.
self.sdk_version = sdk_version
#: str: The version of the App that this SDK is compatible with in Major.Minor.Patch format.
self.sdk_app_version = sdk_app_version
#: str: The version of the App that was detected, and is incompatible, in Major.Minor.Patch format.
self.app_version = app_version

class NotPickupable(ActionError):
'''Raised if an attempt is made to pick up or place an object that can't be picked up by Cozmo'''

class CannotPlaceObjectsOnThis(ActionError):
'''Raised if an attempt is made to place an object on top of an invalid object'''

class RobotBusy(ActionError):
'''Raised if an attempt is made to perform an action while another action is still running.'''

class InvalidOpenGLGlutImplementation(ImportError):
'''Raised by opengl viewer if no valid GLUT implementation available.'''

+ 445
- 0
Cozmo_LineFollow/venv/Lib/site-packages/cozmo/faces.py View File

@@ -0,0 +1,445 @@
# Copyright (c) 2016-2017 Anki, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License in the file LICENSE.txt or at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

'''Face recognition and enrollment.

Cozmo is capable of recognizing human faces, tracking their position and rotation
("pose") and assigning names to them via an enrollment process.

The :class:`cozmo.world.World` object keeps track of faces the robot currently
knows about, along with those that are currently visible to the camera.

Each face is assigned a :class:`Face` object, which generates a number of
observable events whenever the face is observed, has its ID updated, is
renamed, etc.

Note that these face-specific events are also passed up to the
:class:`cozmo.world.World` object, so events for all known faces can be
observed by adding handlers there.
'''

# __all__ should order by constants, event classes, other classes, functions.
__all__ = ['FACE_VISIBILITY_TIMEOUT',
'FACIAL_EXPRESSION_UNKNOWN', 'FACIAL_EXPRESSION_NEUTRAL', 'FACIAL_EXPRESSION_HAPPY',
'FACIAL_EXPRESSION_SURPRISED', 'FACIAL_EXPRESSION_ANGRY', 'FACIAL_EXPRESSION_SAD',
'EvtErasedEnrolledFace', 'EvtFaceAppeared', 'EvtFaceDisappeared',
'EvtFaceIdChanged', 'EvtFaceObserved', 'EvtFaceRenamed',
'Face',
'erase_all_enrolled_faces', 'erase_enrolled_face_by_id',
'update_enrolled_face_by_id']



from . import logger

from . import behavior
from . import event
from . import objects
from . import util

from ._clad import _clad_to_engine_iface
from ._clad import _clad_to_game_anki


#: Length of time in seconds to go without receiving an observed event before
#: assuming that Cozmo can no longer see a face.
FACE_VISIBILITY_TIMEOUT = objects.OBJECT_VISIBILITY_TIMEOUT

# Facial expressions that Cozmo can distinguish
#: Facial expression not recognized.
#: Call :func:`cozmo.robot.Robot.enable_facial_expression_estimation` to enable recognition.
FACIAL_EXPRESSION_UNKNOWN = "unknown"
#: Facial expression neutral
FACIAL_EXPRESSION_NEUTRAL = "neutral"
#: Facial expression happy
FACIAL_EXPRESSION_HAPPY = "happy"
#: Facial expression surprised
FACIAL_EXPRESSION_SURPRISED = "surprised"
#: Facial expression angry
FACIAL_EXPRESSION_ANGRY = "angry"
#: Facial expression sad
FACIAL_EXPRESSION_SAD = "sad"


class EvtErasedEnrolledFace(event.Event):
'''Triggered when a face enrollment is removed (via erase_enrolled_face_by_id)'''
face = 'The Face instance that the enrollment is being erased for'
old_name = 'The name previously used for this face'


class EvtFaceIdChanged(event.Event):
'''Triggered whenever a face has its ID updated in engine.

Generally occurs when:
1) A tracked but unrecognized face (negative ID) is recognized and receives a positive ID or
2) Face records get merged (on realization that 2 faces are actually the same)
'''
face = 'The Face instance that is being given a new id'
old_id = 'The ID previously used for this face'
new_id = 'The new ID that will be used for this face'


class EvtFaceObserved(event.Event):
'''Triggered whenever a face is visually identified by the robot.

A stream of these events are produced while a face is visible to the robot.
Each event has an updated image_box field.

See EvtFaceAppeared if you only want to know when a face first
becomes visible.
'''
face = 'The Face instance that was observed'
updated = 'A set of field names that have changed'
image_box = 'A comzo.util.ImageBox defining where the face is within Cozmo\'s camera view'
name = 'The name associated with the face that was observed'
pose = 'The cozmo.util.Pose defining the position and rotation of the face.'


class EvtFaceAppeared(event.Event):
'''Triggered whenever a face is first visually identified by a robot.

This differs from EvtFaceObserved in that it's only triggered when
a face initially becomes visible. If it disappears for more than
FACE_VISIBILITY_TIMEOUT seconds and then is seen again, a
EvtFaceDisappeared will be dispatched, followed by another
EvtFaceAppeared event.

For continuous tracking information about a visible face, see
EvtFaceObserved.
'''
face = 'The Face instance that was observed'
updated = 'A set of field names that have changed'
image_box = 'A comzo.util.ImageBox defining where the face is within Cozmo\'s camera view'
name = 'The name associated with the face that was observed'
pose = 'The cozmo.util.Pose defining the position and rotation of the face.'


class EvtFaceDisappeared(event.Event):
'''Triggered whenever a face that was previously being observed is no longer visible.'''
face = 'The Face instance that is no longer being observed'


class EvtFaceRenamed(event.Event):
'''Triggered whenever a face is renamed (via RobotRenamedEnrolledFace)'''
face = 'The Face instance that is being given a new name'
old_name = 'The name previously used for this face'
new_name = 'The new name that will be used for this face'


def erase_all_enrolled_faces(conn):
'''Erase the enrollment (name) records for all faces.

Args:
conn (:class:`~cozmo.conn.CozmoConnection`): The connection to send the message over
'''
msg = _clad_to_engine_iface.EraseAllEnrolledFaces()
conn.send_msg(msg)


def erase_enrolled_face_by_id(conn, face_id):
'''Erase the enrollment (name) record for the face with this ID.

Args:
conn (:class:`~cozmo.conn.CozmoConnection`): The connection to send the message over
face_id (int): The ID of the face to erase.
'''
msg = _clad_to_engine_iface.EraseEnrolledFaceByID(face_id)
conn.send_msg(msg)


def update_enrolled_face_by_id(conn, face_id, old_name, new_name):
'''Update the name enrolled for a given face.

Args:
conn (:class:`~cozmo.conn.CozmoConnection`): The connection to send the message over.
face_id (int): The ID of the face to rename.
old_name (string): The old name of the face (must be correct, otherwise message is ignored).
new_name (string): The new name for the face.
'''
msg = _clad_to_engine_iface.UpdateEnrolledFaceByID(face_id, old_name, new_name)
conn.send_msg(msg)


def _clad_facial_expression_to_facial_expression(clad_expression_type):
if clad_expression_type == _clad_to_game_anki.Vision.FacialExpression.Unknown:
return FACIAL_EXPRESSION_UNKNOWN
elif clad_expression_type == _clad_to_game_anki.Vision.FacialExpression.Neutral:
return FACIAL_EXPRESSION_NEUTRAL
elif clad_expression_type == _clad_to_game_anki.Vision.FacialExpression.Happiness:
return FACIAL_EXPRESSION_HAPPY
elif clad_expression_type == _clad_to_game_anki.Vision.FacialExpression.Surprise:
return FACIAL_EXPRESSION_SURPRISED
elif clad_expression_type == _clad_to_game_anki.Vision.FacialExpression.Anger:
return FACIAL_EXPRESSION_ANGRY
elif clad_expression_type == _clad_to_game_anki.Vision.FacialExpression.Sadness:
return FACIAL_EXPRESSION_SAD
else:
raise ValueError("Unexpected facial expression type %s" % clad_expression_type)


class Face(objects.ObservableElement):
'''A single face that Cozmo has detected.

May represent a face that has previously been enrolled, in which case
:attr:`name` will hold the name that it was enrolled with.

Each Face instance has a :attr:`face_id` integer - This may change if
Cozmo later gets an improved view and makes a different prediction about
which face it is looking at.

See parent class :class:`~cozmo.objects.ObservableElement` for additional properties
and methods.
'''

#: Length of time in seconds to go without receiving an observed event before
#: assuming that Cozmo can no longer see a face.
visibility_timeout = FACE_VISIBILITY_TIMEOUT

def __init__(self, conn, world, robot, face_id=None, **kw):
super().__init__(conn, world, robot, **kw)
self._face_id = face_id
self._updated_face_id = None
self._name = ''
self._expression = None
self._expression_score = None
self._left_eye = None
self._right_eye = None
self._nose = None
self._mouth = None

def _repr_values(self):
return 'face_id=%s,%s name=%s' % (self.face_id, self.updated_face_id,
self.name)

#### Private Methods ####

def _dispatch_observed_event(self, changed_fields, image_box):
self.dispatch_event(EvtFaceObserved, face=self, name=self._name,
updated=changed_fields, image_box=image_box, pose=self._pose)

def _dispatch_appeared_event(self, changed_fields, image_box):
self.dispatch_event(EvtFaceAppeared, face=self,
updated=changed_fields, image_box=image_box, pose=self._pose)

def _dispatch_disappeared_event(self):
self.dispatch_event(EvtFaceDisappeared, face=self)

#### Properties ####

@property
def face_id(self):
'''int: The internal ID assigned to the face.

This value can only be assigned once as it is static in the engine.
'''
return self._face_id

@face_id.setter
def face_id(self, value):
if self._face_id is not None:
raise ValueError("Cannot change face ID once set (from %s to %s)" % (self._face_id, value))
logger.debug("Updated face_id for %s from %s to %s", self.__class__, self._face_id, value)
self._face_id = value

@property
def has_updated_face_id(self):
'''bool: True if this face been updated / superseded by a face with a new ID'''
return self._updated_face_id is not None

@property
def updated_face_id(self):
'''int: The ID for the face that superseded this one (if any, otherwise :meth:`face_id`)'''
if self.has_updated_face_id:
return self._updated_face_id
else:
return self.face_id

@property
def name(self):
'''string: The name Cozmo has associated with the face in his memory.

This string will be empty if the face is not recognized or enrolled.
'''
return self._name

@property
def expression(self):
'''string: The facial expression Cozmo has recognized on the face.

Will be :attr:`FACIAL_EXPRESSION_UNKNOWN` by default if you haven't called
:meth:`cozmo.robot.Robot.enable_facial_expression_estimation` to enable
the facial expression estimation. Otherwise it will be equal to one of:
:attr:`FACIAL_EXPRESSION_NEUTRAL`, :attr:`FACIAL_EXPRESSION_HAPPY`,
:attr:`FACIAL_EXPRESSION_SURPRISED`, :attr:`FACIAL_EXPRESSION_ANGRY`,
or :attr:`FACIAL_EXPRESSION_SAD`.
'''
return self._expression

@property
def expression_score(self):
'''int: The score/confidence that :attr:`expression` was correct.

Will be 0 if expression is :attr:`FACIAL_EXPRESSION_UNKNOWN` (e.g. if
:meth:`cozmo.robot.Robot.enable_facial_expression_estimation` wasn't
called yet). The maximum possible score is 100.
'''
return self._expression_score

@property
def known_expression(self):
'''string: The known facial expression Cozmo has recognized on the face.

Like :meth:`expression` but returns an empty string for the unknown expression.
'''
expression = self.expression
if expression == FACIAL_EXPRESSION_UNKNOWN:
return ""
return expression

@property
def left_eye(self):
'''sequence of tuples of float (x,y): points representing the outline of the left eye'''
return self._left_eye

@property
def right_eye(self):
'''sequence of tuples of float (x,y): points representing the outline of the right eye'''
return self._right_eye

@property
def nose(self):
'''sequence of tuples of float (x,y): points representing the outline of the nose'''
return self._nose

@property
def mouth(self):
'''sequence of tuples of float (x,y): points representing the outline of the mouth'''
return self._mouth

#### Private Event Handlers ####

def _recv_msg_robot_observed_face(self, evt, *, msg):

changed_fields = {'pose', 'left_eye', 'right_eye', 'nose', 'mouth'}
self._pose = util.Pose._create_from_clad(msg.pose)
self._name = msg.name

expression = _clad_facial_expression_to_facial_expression(msg.expression)
expression_score = 0

if expression != FACIAL_EXPRESSION_UNKNOWN:
expression_score = msg.expressionValues[msg.expression]
if expression_score == 0:
# The expression should have been marked unknown - this is a
# bug in the engine because even a zero score overwrites the
# default negative score for Unknown.
expression = FACIAL_EXPRESSION_UNKNOWN

if expression != self._expression:
self._expression = expression
changed_fields.add('expression')

if expression_score != self._expression_score:
self._expression_score = expression_score
changed_fields.add('expression_score')

self._left_eye = msg.leftEye
self._right_eye = msg.rightEye
self._nose = msg.nose
self._mouth = msg.mouth

image_box = util.ImageBox._create_from_clad_rect(msg.img_rect)
self._on_observed(image_box, msg.timestamp, changed_fields)

def _recv_msg_robot_changed_observed_face_id(self, evt, *, msg):
self._updated_face_id = msg.newID
self.dispatch_event(EvtFaceIdChanged, face=self, old_id=msg.oldID, new_id = msg.newID)

def _recv_msg_robot_renamed_enrolled_face(self, evt, *, msg):
old_name = self._name
self._name = msg.name
self.dispatch_event(EvtFaceRenamed, face=self, old_name=old_name, new_name=msg.name)

def _recv_msg_robot_erased_enrolled_face(self, evt, *, msg):
old_name = self._name
self._name = ''
self.dispatch_event(EvtErasedEnrolledFace, face=self, old_name=old_name)

#### Public Event Handlers ####

#### Event Wrappers ####

#### Commands ####

def _is_valid_name(self, name):
if not (name and name.isalpha()):
return False
try:
name.encode('ascii')
except UnicodeEncodeError:
return False

return True

def name_face(self, name):
'''Assign a name to this face. Cozmo will remember this name between SDK runs.

Args:
name (string): The name that will be assigned to this face. Must
be a non-empty ASCII string of alphabetic characters only.
Returns:
An instance of :class:`cozmo.behavior.Behavior` object
Raises:
:class:`ValueError` if name is invalid.
'''
if not self._is_valid_name(name):
raise ValueError("new_name '%s' is an invalid face name. "
"Must be non-empty and contain only alphabetic ASCII characters." % name)

logger.info("Enrolling face=%s with name='%s'", self, name)

# Note: saveID must be 0 if face_id doesn't already have a name
msg = _clad_to_engine_iface.SetFaceToEnroll(name=name,
observedID=self.face_id,
saveID=0,
saveToRobot=True,
sayName=False,
useMusic=False)
self.conn.send_msg(msg)

enroll_behavior = self._robot.start_behavior(behavior.BehaviorTypes._EnrollFace)
return enroll_behavior

def rename_face(self, new_name):
'''Change the name assigned to the face. Cozmo will remember this name between SDK runs.

Args:
new_name (string): The new name that will be assigned to this face. Must
be a non-empty ASCII string of alphabetic characters only.
Raises:
:class:`ValueError` if new_name is invalid.
'''
if not self._is_valid_name(new_name):
raise ValueError("new_name '%s' is an invalid face name. "
"Must be non-empty and contain only alphabetic ASCII characters." % new_name)
update_enrolled_face_by_id(self.conn, self.face_id, self.name, new_name)

def erase_enrolled_face(self):
'''Remove the name associated with this face.

Cozmo will no longer remember the name associated with this face between SDK runs.
'''
erase_enrolled_face_by_id(self.conn, self.face_id)



+ 195
- 0
Cozmo_LineFollow/venv/Lib/site-packages/cozmo/lights.py View File

@@ -0,0 +1,195 @@
# Copyright (c) 2016 Anki, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License in the file LICENSE.txt or at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

'''Helper routines for dealing with Cozmo's lights and colors.'''

# __all__ should order by constants, event classes, other classes, functions.
__all__ = ['green', 'red', 'blue', 'white', 'off',
'green_light', 'red_light', 'blue_light', 'white_light', 'off_light',
'Color', 'Light']

import copy

from . import logger


class Color:
'''A Color to be used with a Light.

Either int_color or rgb may be used to specify the actual color.
Any alpha components (from int_color) are ignored - all colors are fully opaque.

Args:
int_color (int): A 32 bit value holding the binary RGBA value (where A
is ignored and forced to be fully opaque).
rgb (tuple): A tuple holding the integer values from 0-255 for (red, green, blue)
name (str): A name to assign to this color
'''

def __init__(self, int_color=None, rgb=None, name=None):
self.name = name
self._int_color = 0
if int_color is not None:
self._int_color = int_color | 0xff
elif rgb is not None:
self._int_color = (rgb[0] << 24) | (rgb[1] << 16) | (rgb[2] << 8) | 0xff

@property
def int_color(self):
'''int: The encoded integer value of the color.'''
return self._int_color


#: :class:`Color`: Green color instance.
green = Color(name="green", int_color=0x00ff00ff)

#: :class:`Color`: Red color instance.
red = Color(name="red", int_color=0xff0000ff)

#: :class:`Color`: Blue color instance.
blue = Color(name="blue", int_color=0x0000ffff)

#: :class:`Color`: White color instance.
white = Color(name="white", int_color=0xffffffff)

#: :class:`Color`: instance representing no color (LEDs off).
off = Color(name="off")


class Light:
'''Lights are used with LightCubes and Cozmo's backpack.

Lights may either be "on" or "off", though in practice any colors may be
assigned to either state (including no color/light).
'''

def __init__(self, on_color=off, off_color=off, on_period_ms=250,
off_period_ms=0, transition_on_period_ms=0, transition_off_period_ms=0):
self._on_color = on_color
self._off_color = off_color
self._on_period_ms = on_period_ms
self._off_period_ms = off_period_ms
self._transition_on_period_ms = transition_on_period_ms
self._transition_off_period_ms = transition_off_period_ms

@property
def on_color(self):
''':class:`Color`: The Color shown when the light is on.'''
return self._on_color

@on_color.setter
def on_color(self, color):
if not isinstance(color, Color):
raise TypeError("Must specify a Color")
self._on_color = color

@property
def off_color(self):
''':class:`Color`: The Color shown when the light is off.'''
return self._off_color

@off_color.setter
def off_color(self, color):
if not isinstance(color, Color):
raise TypeError("Must specify a Color")
self._off_color = color

@property
def on_period_ms(self):
'''int: The number of milliseconds the light should be "on" for for each cycle.'''
return self._on_period_ms

@on_period_ms.setter
def on_period_ms(self, ms):
if not 0 < ms < 2**32:
raise ValueError("Invalid value")
self._on_period_ms = ms

@property
def off_period_ms(self):
'''int: The number of milliseconds the light should be "off" for for each cycle.'''
return self._off_period_ms

@off_period_ms.setter
def off_period_ms(self, ms):
if not 0 < ms < 2**32:
raise ValueError("Invalid value")
self._off_period_ms = ms

@property
def transition_on_period_ms(self):
'''int: The number of milliseconds to take to transition the light to the on color.'''
return self._transition_on_period_ms

@transition_on_period_ms.setter
def transition_on_period_ms(self, ms):
if not 0 < ms < 2**32:
raise ValueError("Invalid value")
self._transition_on_period_ms = ms

@property
def transition_off_period_ms(self):
'''int: The number of milliseconds to take to transition the light to the off color.'''
return self._transition_off_period_ms

@transition_off_period_ms.setter
def transition_off_period_ms(self, ms):
if not 0 < ms < 2**32:
raise ValueError("Invalid value")
self._transition_off_period_ms = ms

def flash(self, on_period_ms=250, off_period_ms=250, off_color=off):
'''Convenience function to make a flashing version of an existing Light instance.

Args:
on_period_ms (int): The number of milliseconds the light should be "on" for for each cycle.
off_period_ms (int): The number of milliseconds the light should be "off" for for each cycle.
off_color (:class:`Color`): The color to flash to for the off state.
Returns:
:class:`Color` instance.
'''
flasher = copy.copy(self)
flasher.on_period_ms = on_period_ms
flasher.off_period_ms = off_period_ms
flasher.off_color=off_color
return flasher

def _set_light(msg, idx, light):
# For use with clad light messages specifically.
if not isinstance(light, Light):
raise TypeError("Expected a lights.Light")
msg.onColor[idx] = light.on_color.int_color
msg.offColor[idx] = light.off_color.int_color
msg.onPeriod_ms[idx] = light.on_period_ms
msg.offPeriod_ms[idx] = light.off_period_ms
msg.transitionOnPeriod_ms[idx] = light.transition_on_period_ms
msg.transitionOffPeriod_ms[idx] = light.transition_off_period_ms

#There is a glitch so it will always flash unless on_color==off_color
#ticket is COZMO-3319

#: :class:`Light`: A steady green colored LED light.
green_light = Light(on_color=green, off_color=green)

#: :class:`Light`: A steady red colored LED light.
red_light = Light(on_color=red, off_color=red)

#: :class:`Light`: A steady blue colored LED light.
blue_light = Light(on_color=blue, off_color=blue)

#: :class:`Light`: A steady white colored LED light.
white_light = Light(on_color=white, off_color=white)

#: :class:`Light`: A steady off (non-illuminated LED light).
off_light = Light(on_color=off, off_color=off)

+ 322
- 0
Cozmo_LineFollow/venv/Lib/site-packages/cozmo/nav_memory_map.py View File

@@ -0,0 +1,322 @@
# Copyright (c) 2017 Anki, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License in the file LICENSE.txt or at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

'''A 2D navigation memory map of the world around Cozmo.

Cozmo builds a memory map of the navigable world around him as he drives
around. This is mostly based on where objects are seen (the cubes, charger, and
any custom objects), and also includes where Cozmo detects cliffs/drops, and
visible edges (e.g. sudden changes in color).

This differs from a standard occupancy map in that it doesn't deal with
probabilities of occupancy, but instead encodes what type of content is there.

To use the map you must first call :meth:`cozmo.world.World.request_nav_memory_map`
with a positive frequency so that the data is streamed to the SDK.
'''

# __all__ should order by constants, event classes, other classes, functions.
__all__ = ['EvtNewNavMemoryMap',
'NavMemoryMapGrid', 'NavMemoryMapGridNode',
'NodeContentTypes']

from collections import namedtuple

from . import event
from . import logger
from . import util
from ._clad import CladEnumWrapper, _clad_to_game_iface


class EvtNewNavMemoryMap(event.Event):
'''Dispatched when a new memory map is received.'''
nav_memory_map = 'A NavMemoryMapGrid object'


class _NodeContentType(namedtuple('_NodeContentType', 'name id')):
# Tuple mapping between CLAD ENodeContentTypeEnum name and ID
# All instances will be members of ActionResults

# Keep _NodeContentType as lightweight as a normal namedtuple
__slots__ = ()

def __str__(self):
return 'NodeContentTypes.%s' % self.name


class NodeContentTypes(CladEnumWrapper):
"""The content types for a :class:`NavMemoryMapGridNode`."""

_clad_enum = _clad_to_game_iface.ENodeContentTypeEnum
_entry_type = _NodeContentType

#: The contents of the node is unknown.
Unknown = _entry_type("Unknown", _clad_enum.Unknown)

#: The node is clear of obstacles, because Cozmo has seen objects on the
#: other side, but it might contain a cliff. The node will be marked as
#: either :attr:`Cliff` or :attr:`ClearOfCliff` once Cozmo has driven there.
ClearOfObstacle = _entry_type("ClearOfObstacle", _clad_enum.ClearOfObstacle)

#: The node is clear of any cliffs (a sharp drop) or obstacles.
ClearOfCliff = _entry_type("ClearOfCliff", _clad_enum.ClearOfCliff)

#: The node contains a :class:`~cozmo.objects.LightCube`.
ObstacleCube = _entry_type("ObstacleCube", _clad_enum.ObstacleCube)

#: The node contains a :class:`~cozmo.objects.Charger`.
ObstacleCharger = _entry_type("ObstacleCharger", _clad_enum.ObstacleCharger)

#: The node contains a cliff (a sharp drop).
Cliff = _entry_type("Cliff", _clad_enum.Cliff)

#: The node contains a visible edge (based on the camera feed).
VisionBorder = _entry_type("VisionBorder", _clad_enum.VisionBorder)

# This entry is undocumented and not currently used
_ObstacleProx = _entry_type("ObstacleProx", _clad_enum.ObstacleProx)


NodeContentTypes._init_class()


class NavMemoryMapGridNode:
"""A node in a :class:`NavMemoryMapGrid`.

Leaf nodes contain content, all other nodes are split into 4 equally sized
children.

Child node indices are stored in the following X,Y orientation:

+---+----+---+
| ^ | 2 | 0 |
+---+----+---+
| Y | 3 | 1 |
+---+----+---+
| | X->| |
+---+----+---+
"""
def __init__(self, depth, size, center, parent):
#: int: The depth of this node. I.e. how far down the quad-tree is it.
self.depth = depth

#: float: The size (width or length) of this square node.
self.size = size

#: :class:`~cozmo.util.Vector3`: The center of this node.
self.center = center # type: util.Vector3

#: :class:`NavMemoryMapGridNode`: The parent of this node. Is ``None`` for the root node.
self.parent = parent # type: NavMemoryMapGridNode

#: list of :class:`NavMemoryMapGridNode`: ``None`` for leaf nodes, a list of 4
#: child nodes otherwise.
self.children = None

#: An attribute of :class:`NodeContentTypes`: The content type in this
#: node. Only leaf nodes have content, this is ``None`` for all other
#: nodes.
self.content = None # type: _NodeContentType

self._next_child = 0 # Used when building to track which branch to follow

def __repr__(self):
return '<%s center: %s size: %s content: %s>' % (
self.__class__.__name__, self.center, self.size, self.content)

def contains_point(self, x, y):
"""Test if the node contains the given x,y coordinates.

Args:
x (float): x coordinate for the point
y (float): y coordinate for the point

Returns:
bool: True if the node contains the point, False otherwise.
"""
half_size = self.size * 0.5
dist_x = abs(self.center.x - x)
dist_y = abs(self.center.y - y)
return (dist_x <= half_size) and (dist_y <= half_size)

def _get_node(self, x, y, assumed_in_bounds):
if not assumed_in_bounds and not self.contains_point(x, y):
# point is out of bounds
return None

if self.children is None:
return self
else:
x_offset = 2 if x < self.center.x else 0
y_offset = 1 if y < self.center.y else 0
child_node = self.children[x_offset+y_offset]
# child node is by definition in bounds / on boundary
return child_node._get_node(x, y, True)

def get_node(self, x, y):
"""Get the node at the given x,y coordinates.

Args:
x (float): x coordinate for the point
y (float): y coordinate for the point

Returns:
:class:`NavMemoryMapGridNode`: The smallest node that includes the
point. Will be ``None`` if the point is outside of the map.
"""
return self._get_node(x, y, assumed_in_bounds=False)

def get_content(self, x, y):
"""Get the node's content at the given x,y coordinates.

Args:
x (float): x coordinate for the point
y (float): y coordinate for the point

Returns:
:class:`_NodeContentType`: The content included at that point.
Will be :attr:`NodeContentTypes.Unknown` if the point is outside of
the map.
"""
node = self.get_node(x, y)
if node:
return node.content
else:
return NodeContentTypes.Unknown

def _add_child(self, content, depth):
"""Add a child node to the quad tree.

The quad-tree is serialized to a flat list of nodes, we deserialize
back to a quad-tree structure here, with the depth of each node
indicating where it is placed.

Args:
content (:class:`_NodeContentType`): The content to store in the leaf node
depth (int): The depth that this leaf node is located at.

Returns:
bool: True if parent should use the next child for future _add_child
calls (this is an internal implementation detail of h
"""
if depth > self.depth:
logger.error("NavMemoryMapGridNode depth %s > %s", depth, self.depth)
if self._next_child > 3:
logger.error("NavMemoryMapGridNode _next_child %s (>3) at depth %s", self._next_child, self.depth)

if self.depth == depth:
if self.content is not None:
logger.error("NavMemoryMapGridNode: Clobbering %s at depth %s with %s",
self.content, self.depth, content)
self.content = content
# This node won't be further subdivided, and is now full
return True

if self.children is None:
# Create 4 child nodes for quad-tree structure
next_depth = self.depth - 1
next_size = self.size * 0.5
offset = next_size * 0.5
center1 = util.Vector3(self.center.x + offset, self.center.y + offset, self.center.z)
center2 = util.Vector3(self.center.x + offset, self.center.y - offset, self.center.z)
center3 = util.Vector3(self.center.x - offset, self.center.y + offset, self.center.z)
center4 = util.Vector3(self.center.x - offset, self.center.y - offset, self.center.z)
self.children = [NavMemoryMapGridNode(next_depth, next_size, center1, self),
NavMemoryMapGridNode(next_depth, next_size, center2, self),
NavMemoryMapGridNode(next_depth, next_size, center3, self),
NavMemoryMapGridNode(next_depth, next_size, center4, self)]
if self.children[self._next_child]._add_child(content, depth):
# Child node is now full, start using the next child
self._next_child += 1

if self._next_child > 3:
# All children are now full - parent should start using the next child
return True
else:
# Empty children remain - parent can keep using this child
return False


class NavMemoryMapGrid:
"""A navigation memory map, stored as a quad-tree."""
def __init__(self, origin_id, root_depth, root_size, root_center_x, root_center_y):
#: int: The origin ID for the map. Only maps and :class:`~cozmo.util.Pose`
#: objects of the same origin ID are in the same coordinate frame and
#: can therefore be compared.
self.origin_id = origin_id
root_center = util.Vector3(root_center_x, root_center_y, 0.0)
self._root_node = NavMemoryMapGridNode(root_depth, root_size, root_center, None)

def __repr__(self):
return '<%s center: %s size: %s>' % (
self.__class__.__name__, self.center, self.size)

@property
def root_node(self):
""":class:`NavMemoryMapGridNode`: The root node for the grid, contains all other nodes."""
return self._root_node

@property
def size(self):
"""float: The size (width or length) of the square grid."""
return self._root_node.size

@property
def center(self):
""":class:`~cozmo.util.Vector3`: The center of this map."""
return self._root_node.center

def contains_point(self, x, y):
"""Test if the map contains the given x,y coordinates.

Args:
x (float): x coordinate for the point
y (float): y coordinate for the point

Returns:
bool: True if the map contains the point, False otherwise.
"""
return self._root_node.contains_point(x,y)

def get_node(self, x, y):
"""Get the node at the given x,y coordinates.

Args:
x (float): x coordinate for the point
y (float): y coordinate for the point

Returns:
:class:`NavMemoryMapGridNode`: The smallest node that includes the
point. Will be ``None`` if the point is outside of the map.
"""
return self._root_node.get_node(x, y)

def get_content(self, x, y):
"""Get the map's content at the given x,y coordinates.

Args:
x (float): x coordinate for the point
y (float): y coordinate for the point

Returns:
:class:`_NodeContentType`: The content included at that point.
Will be :attr:`NodeContentTypes.Unknown` if the point is outside of
the map.
"""
return self._root_node.get_content(x, y)

def _add_quad(self, content, depth):
# Convert content int to our enum representation
content = NodeContentTypes.find_by_id(content)
self._root_node._add_child(content, depth)

+ 939
- 0
Cozmo_LineFollow/venv/Lib/site-packages/cozmo/objects.py View File

@@ -0,0 +1,939 @@
# Copyright (c) 2016-2017 Anki, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License in the file LICENSE.txt or at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

'''Object and Power Cube recognition.

Cozmo can recognize and track a number of different types of objects.

These objects may be visible (currently observed by the robot's camera)
and tappable (in the case of the Power Cubes that ship with the robot).

Power Cubes are known as a :class:`LightCube` by the SDK. Each cube has
controllable lights, and sensors that can determine when its being moved
or tapped.

Objects can emit several events such as :class:`EvtObjectObserved` when
the robot sees (or continues to see) the object with its camera, or
:class:`EvtObjectTapped` if a power cube is tapped by a player. You
can either observe the object's instance directly, or capture all such events
for all objects by observing them on :class:`cozmo.world.World` instead.

All observable objects have a marker attached to them, which allows Cozmo
to recognize the object and it's position and rotation("pose"). You can attach
markers to your own objects for Cozmo to recognize by printing them out from the
online documentation. They will be detected as :class:`CustomObject` instances.
'''


# __all__ should order by constants, event classes, other classes, functions.
__all__ = ['LightCube1Id', 'LightCube2Id', 'LightCube3Id', 'LightCubeIDs',
'OBJECT_VISIBILITY_TIMEOUT',
'EvtObjectAppeared',
'EvtObjectConnectChanged', 'EvtObjectConnected',
'EvtObjectDisappeared', 'EvtObjectLocated',
'EvtObjectMoving', 'EvtObjectMovingStarted', 'EvtObjectMovingStopped',
'EvtObjectObserved', 'EvtObjectTapped',
'ObservableElement', 'ObservableObject', 'LightCube', 'Charger',
'CustomObject', 'CustomObjectMarkers', 'CustomObjectTypes', 'FixedCustomObject']


import collections
import math
import time

from . import logger

from . import action
from . import event
from . import lights
from . import util

from ._clad import _clad_to_engine_iface, _clad_to_game_cozmo, _clad_to_engine_cozmo, _clad_to_game_anki


#: Length of time in seconds to go without receiving an observed event before
#: assuming that Cozmo can no longer see an object.
OBJECT_VISIBILITY_TIMEOUT = 0.4


class EvtObjectObserved(event.Event):
'''Triggered whenever an object is visually identified by the robot.

A stream of these events are produced while an object is visible to the robot.
Each event has an updated image_box field.

See EvtObjectAppeared if you only want to know when an object first
becomes visible.
'''
obj = 'The object that was observed'
updated = 'A set of field names that have changed'
image_box = 'A comzo.util.ImageBox defining where the object is within Cozmo\'s camera view'
pose = 'The cozmo.util.Pose defining the position and rotation of the object'


class EvtObjectAppeared(event.Event):
'''Triggered whenever an object is first visually identified by a robot.

This differs from EvtObjectObserved in that it's only triggered when
an object initially becomes visible. If it disappears for more than
OBJECT_VISIBILITY_TIMEOUT seconds and then is seen again, a
EvtObjectDisappeared will be dispatched, followed by another
EvtObjectAppeared event.

For continuous tracking information about a visible object, see
EvtObjectObserved.
'''
obj = 'The object that was observed'
updated = 'A set of field names that have changed'
image_box = 'A comzo.util.ImageBox defining where the object is within Cozmo\'s camera view'
pose = 'The cozmo.util.Pose defining the position and rotation of the object'


class EvtObjectConnected(event.Event):
'''Triggered when the engine reports that an object is connected (i.e. exists).

This will usually occur at the start of the program in response to the SDK
sending RequestConnectedObjects to the engine.
'''
obj = 'The object that is connected'
connected = 'True if the object connected, False if it disconnected'


class EvtObjectConnectChanged(event.Event):
'Triggered when an active object has connected or disconnected from the robot.'
obj = 'The object that connected or disconnected'
connected = 'True if the object connected, False if it disconnected'


class EvtObjectLocated(event.Event):
'''Triggered when the engine reports that an object is located (i.e. pose is known).

This will usually occur at the start of the program in response to the SDK
sending RequestLocatedObjectStates to the engine.
'''
obj = 'The object that is located'
updated = 'A set of field names that have changed'
pose = 'The cozmo.util.Pose defining the position and rotation of the object'


class EvtObjectDisappeared(event.Event):
'''Triggered whenever an object that was previously being observed is no longer visible.'''
obj = 'The object that is no longer being observed'

class EvtObjectMoving(event.Event):
'Triggered when an active object is currently moving.'
obj = 'The object that is currently moving'
# :class:`~cozmo.util.Vector3`: The currently measured acceleration
acceleration = 'The currently measured acceleration'
move_duration = 'The current duration of time (in seconds) that the object has spent moving'

class EvtObjectMovingStarted(event.Event):
'Triggered when an active object starts moving.'
obj = 'The object that started moving'
#: :class:`~cozmo.util.Vector3`: The currently measured acceleration
acceleration = 'The currently measured acceleration'

class EvtObjectMovingStopped(event.Event):
'Triggered when an active object stops moving.'
obj = 'The object that stopped moving'
move_duration = 'The duration of time (in seconds) that the object spent moving'

class EvtObjectTapped(event.Event):
'Triggered when an active object is tapped.'
obj = 'The object that was tapped'
tap_count = 'Number of taps detected'
tap_duration = 'The duration of the tap in ms'
tap_intensity = 'The intensity of the tap'


class ObservableElement(event.Dispatcher):
'''The base type for anything Cozmo can see.'''

#: Length of time in seconds to go without receiving an observed event before
#: assuming that Cozmo can no longer see an element. Can be overridden in sub
#: classes.
visibility_timeout = OBJECT_VISIBILITY_TIMEOUT

def __init__(self, conn, world, robot, **kw):
super().__init__(**kw)
self._robot = robot
self._pose = None
self.conn = conn
#: :class:`cozmo.world.World`: The robot's world in which this element is located.
self.world = world

#: float: The time the last event was received.
#: ``None`` if no events have yet been received.
self.last_event_time = None

#: float: The time the element was last observed by the robot.
#: ``None`` if the element has not yet been observed.
self.last_observed_time = None

#: int: The robot's timestamp of the last observed event.
#: ``None`` if the element has not yet been observed.
#: In milliseconds relative to robot epoch.
self.last_observed_robot_timestamp = None

#: :class:`~cozmo.util.ImageBox`: The ImageBox defining where the
#: object was last visible within Cozmo's camera view.
#: ``None`` if the element has not yet been observed.
self.last_observed_image_box = None

self._is_visible = False
self._observed_timeout_handler = None

def __repr__(self):
extra = self._repr_values()
if len(extra) > 0:
extra = ' '+extra
if self.pose:
extra += ' pose=%s' % self.pose

return '<%s%s is_visible=%s>' % (self.__class__.__name__,
extra, self.is_visible)

#### Private Methods ####

def _repr_values(self):
return ''

def _update_field(self, changed, field_name, new_value):
# Set only changed fields and update the passed in changed set
current = getattr(self, field_name)
if current != new_value:
setattr(self, field_name, new_value)
changed.add(field_name)

def _reset_observed_timeout_handler(self):
if self._observed_timeout_handler is not None:
self._observed_timeout_handler.cancel()
self._observed_timeout_handler = self._loop.call_later(
self.visibility_timeout, self._observed_timeout)

def _observed_timeout(self):
# triggered when the element is no longer considered "visible"
# ie. visibility_timeout seconds after the last observed event
self._is_visible = False
self._dispatch_disappeared_event()

def _dispatch_observed_event(self, changed_fields, image_box):
# Override in subclass if there is a specific event for that type
pass

def _dispatch_appeared_event(self, changed_fields, image_box):
# Override in subclass if there is a specific event for that type
pass

def _dispatch_disappeared_event(self):
# Override in subclass if there is a specific event for that type
pass

def _on_observed(self, image_box, timestamp, changed_fields):
# Called from subclasses on their corresponding observed messages
newly_visible = self._is_visible is False
self._is_visible = True

changed_fields |= {'last_observed_time', 'last_observed_robot_timestamp',
'last_event_time', 'last_observed_image_box'}

now = time.time()
self.last_observed_time = now
self.last_observed_robot_timestamp = timestamp
self.last_event_time = now
self.last_observed_image_box = image_box
self._reset_observed_timeout_handler()
self._dispatch_observed_event(changed_fields, image_box)

if newly_visible:
self._dispatch_appeared_event(changed_fields, image_box)

#### Properties ####

@property
def pose(self):
''':class:`cozmo.util.Pose`: The pose of the element in the world.

Is ``None`` for elements that don't have pose information.
'''
return self._pose

@property
def time_since_last_seen(self):
'''float: time since this element was last seen (math.inf if never)'''
if self.last_observed_time is None:
return math.inf
return time.time() - self.last_observed_time

@property
def is_visible(self):
'''bool: True if the element has been observed recently.

"recently" is defined as :attr:`visibility_timeout` seconds.
'''
return self._is_visible


class ObservableObject(ObservableElement):
'''The base type for objects in Cozmo's world.

See parent class :class:`ObservableElement` for additional properties
and methods.
'''

#: bool: True if this type of object can be physically picked up by Cozmo
pickupable = False
#: bool: True if this type of object can have objects physically placed on it by Cozmo
place_objects_on_this = False

def __init__(self, conn, world, object_id=None, **kw):
super().__init__(conn, world, robot=None, **kw)
self._object_id = object_id

#### Private Methods ####

def _repr_values(self):
return 'object_id=%s' % self.object_id

def _dispatch_observed_event(self, changed_fields, image_box):
self.dispatch_event(EvtObjectObserved, obj=self,
updated=changed_fields, image_box=image_box, pose=self._pose)

def _dispatch_appeared_event(self, changed_fields, image_box):
self.dispatch_event(EvtObjectAppeared, obj=self,
updated=changed_fields, image_box=image_box, pose=self._pose)

def _dispatch_disappeared_event(self):
self.dispatch_event(EvtObjectDisappeared, obj=self)

def _handle_connected_object_state(self, object_state):
# triggered when engine sends a ConnectedObjectStates message
# as a response to a RequestConnectedObjects message
self._pose = util.Pose._create_default()
self.is_connected = True
self.dispatch_event(EvtObjectConnected, obj=self)

def _handle_located_object_state(self, object_state):
# triggered when engine sends a LocatedObjectStates message
# as a response to a RequestLocatedObjectStates message
if (self.last_observed_robot_timestamp and
(self.last_observed_robot_timestamp > object_state.lastObservedTimestamp)):
logger.warning("Ignoring old located object_state=%s obj=%s (last_observed_robot_timestamp=%s)",
object_state, self, self.last_observed_robot_timestamp)
return

changed_fields = {'last_observed_robot_timestamp', 'pose'}

self.last_observed_robot_timestamp = object_state.lastObservedTimestamp

self._pose = util.Pose._create_from_clad(object_state.pose)
if object_state.poseState == _clad_to_game_anki.PoseState.Invalid:
logger.error("Unexpected Invalid pose state received")
self._pose.invalidate()
elif object_state.poseState == _clad_to_game_anki.PoseState.Dirty:
# Note Dirty currently means either moved (in which case it's really dirty)
# or inaccurate (e.g. seen from too far away to give an accurate enough pose for localization)
# TODO: split Dirty into 2 states, and allow SDK to report the distinction.
self._pose._is_accurate = False

self.dispatch_event(EvtObjectLocated,
obj=self,
updated=changed_fields,
pose=self._pose)

#### Properties ####

@property
def object_id(self):
'''int: The internal ID assigned to the object.

This value can only be assigned once as it is static in the engine.
'''
return self._object_id

@object_id.setter
def object_id(self, value):
if self._object_id is not None:
# We cannot currently rely on Engine ensuring that object ID remains static
# E.g. in the case of a cube disconnecting and reconnecting it's removed
# and then re-added to blockworld which results in a new ID.
logger.warning("Changing object_id for %s from %s to %s", self.__class__, self._object_id, value)
else:
logger.debug("Setting object_id for %s to %s", self.__class__, value)
self._object_id = value

@property
def descriptive_name(self):
'''str: A descriptive name for this ObservableObject instance.'''
# Note: Sub-classes should override this to add any other relevant info
# for that object type.
return "%s id=%d" % (self.__class__.__name__, self.object_id)

#### Private Event Handlers ####

def _recv_msg_robot_observed_object(self, evt, *, msg):

changed_fields = {'pose'}
self._pose = util.Pose._create_from_clad(msg.pose)

image_box = util.ImageBox._create_from_clad_rect(msg.img_rect)
self._on_observed(image_box, msg.timestamp, changed_fields)

#### Public Event Handlers ####

#### Event Wrappers ####

#### Commands ####


#: LightCube1Id's markers look a bit like a paperclip
LightCube1Id = _clad_to_game_cozmo.ObjectType.Block_LIGHTCUBE1
#: LightCube2Id's markers look a bit like a lamp (or a heart)
LightCube2Id = _clad_to_game_cozmo.ObjectType.Block_LIGHTCUBE2
#: LightCube3Id's markers look a bit like the letters 'ab' over 'T'
LightCube3Id = _clad_to_game_cozmo.ObjectType.Block_LIGHTCUBE3

#: An ordered list of the 3 light cube IDs for convenience
LightCubeIDs = [LightCube1Id, LightCube2Id, LightCube3Id]


class LightCube(ObservableObject):
'''A light cube object has four LEDs that Cozmo can actively manipulate and communicate with.

See parent class :class:`ObservableObject` for additional properties
and methods.
'''
#TODO investigate why the top marker orientation of a cube is a bit strange

#: Voltage where a cube's battery can be considered empty
EMPTY_VOLTAGE = 1.0
#: Voltage where a cube's battery can be considered full
FULL_VOLTAGE = 1.5

pickupable = True
place_objects_on_this = True

def __init__(self, cube_id, *a, **kw):
super().__init__(*a, **kw)

#: float: The time the object was last tapped
#: ``None`` if the cube wasn't tapped yet.
self.last_tapped_time = None

#: int: The robot's timestamp of the last tapped event.
#: ``None`` if the cube wasn't tapped yet.
#: In milliseconds relative to robot epoch.
self.last_tapped_robot_timestamp = None

#: float: The time the object was last moved
#: ``None`` if the cube wasn't moved yet.
self.last_moved_time = None

#: float: The time the object started moving when last moved
self.last_moved_start_time = None

#: int: The robot's timestamp of the last move event.
#: ``None`` if the cube wasn't moved yet.
#: In milliseconds relative to robot epoch.
self.last_moved_robot_timestamp = None

#: int: The robot's timestamp of when the object started moving when last moved
#: ``None`` if the cube wasn't moved yet.
#: In milliseconds relative to robot epoch.
self.last_moved_start_robot_timestamp = None

#: float: Battery voltage.
#: ``None`` if no voltage reading has been received yet
self.battery_voltage = None

#: bool: True if the cube's accelerometer indicates that the cube is moving.
self.is_moving = False

#: bool: True if the cube is currently connected to the robot via radio.
self.is_connected = False

self._cube_id = cube_id

def _repr_values(self):
super_values = super()._repr_values()
if len(super_values) > 0:
super_values += ' '
return ('{super_values}'
'battery={self.battery_str:s}'.format(self=self, super_values=super_values))

#### Private Methods ####

def _set_light(self, msg, idx, light):
if not isinstance(light, lights.Light):
raise TypeError("Expected a lights.Light")
msg.onColor[idx] = light.on_color.int_color
msg.offColor[idx] = light.off_color.int_color
msg.onPeriod_ms[idx] = light.on_period_ms
msg.offPeriod_ms[idx] = light.off_period_ms
msg.transitionOnPeriod_ms[idx] = light.transition_on_period_ms
msg.transitionOffPeriod_ms[idx] = light.transition_off_period_ms


#### Event Wrappers ####

async def wait_for_tap(self, timeout=None):
'''Wait for the object to receive a tap event.

Args:
timeout (float): Maximum time to wait for a tap, in seconds. None for indefinite
Returns:
A :class:`EvtObjectTapped` object if a tap was received.
'''
return await self.wait_for(EvtObjectTapped, timeout=timeout)


#### Properties ####

@property
def battery_percentage(self):
"""float: Battery level as a percentage."""
if self.battery_voltage is None:
# not received a voltage measurement yet
return None
elif self.battery_voltage >= self.FULL_VOLTAGE:
return 100.0
elif self.battery_voltage <= self.EMPTY_VOLTAGE:
return 0.0
else:
return 100.0 * ((self.battery_voltage - self.EMPTY_VOLTAGE) /
(self.FULL_VOLTAGE - self.EMPTY_VOLTAGE))

@property
def battery_str(self):
"""str: String representation of the battery level."""
if self.battery_voltage is None:
return "Unknown"
else:
return ('{self.battery_percentage:.0f}%'.format(self=self))

@property
def cube_id(self):
"""int: The Light Cube ID.

This will be one of :attr:`~cozmo.objects.LightCube1Id`,
:attr:`~cozmo.objects.LightCube2Id` and :attr:`~cozmo.objects.LightCube3Id`.
Note: the cube_id is not the same thing as the object_id.
"""
return self._cube_id

#### Private Event Handlers ####
def _recv_msg_object_tapped(self, evt, *, msg):
now = time.time()
self.last_event_time = now
self.last_tapped_time = now
self.last_tapped_robot_timestamp = msg.timestamp
tap_intensity = msg.tapPos - msg.tapNeg
self.dispatch_event(EvtObjectTapped, obj=self,
tap_count=msg.numTaps, tap_duration=msg.tapTime, tap_intensity=tap_intensity)

def _recv_msg_object_moved(self, evt, *, msg):
now = time.time()
started_moving = not self.is_moving
self.is_moving = True
self.last_event_time = now
self.last_moved_time = now
self.last_moved_robot_timestamp = msg.timestamp

self.pose.invalidate()

acceleration = util.Vector3(msg.accel.x, msg.accel.y, msg.accel.z)

if started_moving:
self.last_moved_start_time = now
self.last_moved_start_robot_timestamp = msg.timestamp
self.dispatch_event(EvtObjectMovingStarted, obj=self,
acceleration=acceleration)
else:
move_duration = now - self.last_moved_start_time
self.dispatch_event(EvtObjectMoving, obj=self,
acceleration=acceleration,
move_duration=move_duration)

def _recv_msg_object_stopped_moving(self, evt, *, msg):
now = time.time()
if self.is_moving:
self.is_moving = False
move_duration = now - self.last_moved_start_time
else:
# This happens for very short movements that are immediately
# considered stopped (no acceleration info is present)
move_duration = 0.0
self.dispatch_event(EvtObjectMovingStopped, obj=self,
move_duration=move_duration)

def _recv_msg_object_power_level(self, evt, *, msg):
self.battery_voltage = msg.batteryLevel * 0.01

def _recv_msg_object_connection_state(self, evt, *, msg):
if self.is_connected != msg.connected:
if msg.connected:
logger.info("Object connected: %s", self)
else:
logger.info("Object disconnected: %s", self)
self.is_connected = msg.connected
self.dispatch_event(EvtObjectConnectChanged, obj=self,
connected=self.is_connected)

@property
def descriptive_name(self):
'''str: A descriptive name for this LightCube instance.'''
# Specialization of ObservableObject's method to include the cube ID.
return "%s %s id=%d" % (self.__class__.__name__, self._cube_id, self.object_id)

#### Public Event Handlers ####

def recv_evt_object_tapped(self, evt, **kw):
pass

#### Commands ####

# TODO: make this explicit as to which light goes to which corner.
def set_light_corners(self, light1, light2, light3, light4):
"""Set the light for each corner"""
msg = _clad_to_engine_iface.SetAllActiveObjectLEDs(objectID=self.object_id)
for i, light in enumerate( (light1, light2, light3, light4) ):
if light is not None:
lights._set_light(msg, i, light)

self.conn.send_msg(msg)

def set_lights(self, light):
'''Set all lights on the cube

Args:
light (:class:`cozmo.lights.Light`): The settings for the lights.
'''
msg = _clad_to_engine_iface.SetAllActiveObjectLEDs(
objectID=self.object_id)
for i in range(4):
lights._set_light(msg, i, light)

self.conn.send_msg(msg)

def set_lights_off(self):
'''Turn off all the lights on the cube.'''
self.set_lights(lights.off_light)


class Charger(ObservableObject):
'''Cozmo's charger object, which the robot can observe and drive toward.

See parent class :class:`ObservableObject` for additional properties
and methods.
'''

def __init__(self, *a, **kw):
super().__init__(*a, **kw)


class CustomObject(ObservableObject):
'''An object defined by the SDK. It is bound to a specific objectType e.g ``CustomType00``.

This defined object is given a size in the x,y and z axis. The dimensions
of the markers on the object are also defined. We get an
:class:`cozmo.objects.EvtObjectObserved` message when the robot sees these
markers.

See parent class :class:`ObservableObject` for additional properties
and methods.
These objects are created automatically by the engine when Cozmo observes
an object with custom markers. For Cozmo to see one of these you must first
define an object with custom markers, via one of the following methods:
:meth:`~cozmo.world.World.define_custom_box`.
:meth:`~cozmo.world.World.define_custom_cube`, or
:meth:`~cozmo.world.World.define_custom_wall`
'''

def __init__(self, conn, world, object_type,
x_size_mm, y_size_mm, z_size_mm,
marker_width_mm, marker_height_mm, is_unique, **kw):
super().__init__(conn, world, **kw)

self.object_type = object_type
self._x_size_mm = x_size_mm
self._y_size_mm = y_size_mm
self._z_size_mm = z_size_mm
self._marker_width_mm = marker_width_mm
self._marker_height_mm = marker_height_mm
self._is_unique = is_unique

def _repr_values(self):
return ('object_type={self.object_type} '
'x_size_mm={self.x_size_mm:.1f} '
'y_size_mm={self.y_size_mm:.1f} '
'z_size_mm={self.z_size_mm:.1f} '
'is_unique={self.is_unique}'.format(self=self))

#### Private Methods ####

#### Event Wrappers ####
#### Properties ####
@property
def x_size_mm(self):
'''float: Size of this object in its X axis, in millimeters.'''
return self._x_size_mm

@property
def y_size_mm(self):
'''float: Size of this object in its Y axis, in millimeters.'''
return self._y_size_mm

@property
def z_size_mm(self):
'''float: Size of this object in its Z axis, in millimeters.'''
return self._z_size_mm

@property
def marker_width_mm(self):
'''float: Width in millimeters of the marker on this object.'''
return self._marker_width_mm

@property
def marker_height_mm(self):
'''float: Height in millimeters of the marker on this object.'''
return self._marker_height_mm

@property
def is_unique(self):
'''bool: True if there should only be one of this object type in the world.'''
return self._is_unique

@property
def descriptive_name(self):
'''str: A descriptive name for this CustomObject instance.'''
# Specialization of ObservableObject's method to include the object type.
return "%s id=%d" % (self.object_type.name, self.object_id)

#### Private Event Handlers ####

#### Public Event Handlers ####

#### Commands ####


class _CustomObjectType(collections.namedtuple('_CustomObjectType', 'name id')):
# Tuple mapping between CLAD ActionResult name and ID
# All instances will be members of ActionResults

# Keep _ActionResult as lightweight as a normal namedtuple
__slots__ = ()

def __str__(self):
return 'CustomObjectTypes.%s' % self.name


class CustomObjectTypes:
'''Defines all available custom object types.

For use with world.define_custom methods such as
:meth:`cozmo.world.World.define_custom_box`,
:meth:`cozmo.world.World.define_custom_cube`, and
:meth:`cozmo.world.World.define_custom_wall`
'''

#: CustomType00 - the first custom object type
CustomType00 = _CustomObjectType("CustomType00", _clad_to_engine_cozmo.ObjectType.CustomType00)

#:
CustomType01 = _CustomObjectType("CustomType01", _clad_to_engine_cozmo.ObjectType.CustomType01)

#:
CustomType02 = _CustomObjectType("CustomType02", _clad_to_engine_cozmo.ObjectType.CustomType02)

#:
CustomType03 = _CustomObjectType("CustomType03", _clad_to_engine_cozmo.ObjectType.CustomType03)

#:
CustomType04 = _CustomObjectType("CustomType04", _clad_to_engine_cozmo.ObjectType.CustomType04)

#:
CustomType05 = _CustomObjectType("CustomType05", _clad_to_engine_cozmo.ObjectType.CustomType05)

#:
CustomType06 = _CustomObjectType("CustomType06", _clad_to_engine_cozmo.ObjectType.CustomType06)

#:
CustomType07 = _CustomObjectType("CustomType07", _clad_to_engine_cozmo.ObjectType.CustomType07)

#:
CustomType08 = _CustomObjectType("CustomType08", _clad_to_engine_cozmo.ObjectType.CustomType08)

#:
CustomType09 = _CustomObjectType("CustomType09", _clad_to_engine_cozmo.ObjectType.CustomType09)

#:
CustomType10 = _CustomObjectType("CustomType10", _clad_to_engine_cozmo.ObjectType.CustomType10)

#:
CustomType11 = _CustomObjectType("CustomType11", _clad_to_engine_cozmo.ObjectType.CustomType11)

#:
CustomType12 = _CustomObjectType("CustomType12", _clad_to_engine_cozmo.ObjectType.CustomType12)

#:
CustomType13 = _CustomObjectType("CustomType13", _clad_to_engine_cozmo.ObjectType.CustomType13)

#:
CustomType14 = _CustomObjectType("CustomType14", _clad_to_engine_cozmo.ObjectType.CustomType14)

#:
CustomType15 = _CustomObjectType("CustomType15", _clad_to_engine_cozmo.ObjectType.CustomType15)

#:
CustomType16 = _CustomObjectType("CustomType16", _clad_to_engine_cozmo.ObjectType.CustomType16)

#:
CustomType17 = _CustomObjectType("CustomType17", _clad_to_engine_cozmo.ObjectType.CustomType17)

#:
CustomType18 = _CustomObjectType("CustomType18", _clad_to_engine_cozmo.ObjectType.CustomType18)

#: CustomType19 - the last custom object type
CustomType19 = _CustomObjectType("CustomType19", _clad_to_engine_cozmo.ObjectType.CustomType19)


_CustomObjectMarker = collections.namedtuple('_CustomObjectMarker', 'name id')

class CustomObjectMarkers:
'''Defines all available custom object markers.

For use with world.define_custom methods such as
:meth:`cozmo.world.World.define_custom_box`,
:meth:`cozmo.world.World.define_custom_cube`, and
:meth:`cozmo.world.World.define_custom_wall`
'''

#: .. image:: ../images/custom_markers/SDK_2Circles.png
Circles2 = _CustomObjectMarker("Circles2", _clad_to_engine_cozmo.CustomObjectMarker.Circles2)

#: .. image:: ../images/custom_markers/SDK_3Circles.png
Circles3 = _CustomObjectMarker("Circles3", _clad_to_engine_cozmo.CustomObjectMarker.Circles3)

#: .. image:: ../images/custom_markers/SDK_4Circles.png
Circles4 = _CustomObjectMarker("Circles4", _clad_to_engine_cozmo.CustomObjectMarker.Circles4)

#: .. image:: ../images/custom_markers/SDK_5Circles.png
Circles5 = _CustomObjectMarker("Circles5", _clad_to_engine_cozmo.CustomObjectMarker.Circles5)

#: .. image:: ../images/custom_markers/SDK_2Diamonds.png
Diamonds2 = _CustomObjectMarker("Diamonds2", _clad_to_engine_cozmo.CustomObjectMarker.Diamonds2)

#: .. image:: ../images/custom_markers/SDK_3Diamonds.png
Diamonds3 = _CustomObjectMarker("Diamonds3", _clad_to_engine_cozmo.CustomObjectMarker.Diamonds3)

#: .. image:: ../images/custom_markers/SDK_4Diamonds.png
Diamonds4 = _CustomObjectMarker("Diamonds4", _clad_to_engine_cozmo.CustomObjectMarker.Diamonds4)

#: .. image:: ../images/custom_markers/SDK_5Diamonds.png
Diamonds5 = _CustomObjectMarker("Diamonds5", _clad_to_engine_cozmo.CustomObjectMarker.Diamonds5)

#: .. image:: ../images/custom_markers/SDK_2Hexagons.png
Hexagons2 = _CustomObjectMarker("Hexagons2", _clad_to_engine_cozmo.CustomObjectMarker.Hexagons2)

#: .. image:: ../images/custom_markers/SDK_3Hexagons.png
Hexagons3 = _CustomObjectMarker("Hexagons3", _clad_to_engine_cozmo.CustomObjectMarker.Hexagons3)

#: .. image:: ../images/custom_markers/SDK_4Hexagons.png
Hexagons4 = _CustomObjectMarker("Hexagons4", _clad_to_engine_cozmo.CustomObjectMarker.Hexagons4)

#: .. image:: ../images/custom_markers/SDK_5Hexagons.png
Hexagons5 = _CustomObjectMarker("Hexagons5", _clad_to_engine_cozmo.CustomObjectMarker.Hexagons5)

#: .. image:: ../images/custom_markers/SDK_2Triangles.png
Triangles2 = _CustomObjectMarker("Triangles2", _clad_to_engine_cozmo.CustomObjectMarker.Triangles2)

#: .. image:: ../images/custom_markers/SDK_3Triangles.png
Triangles3 = _CustomObjectMarker("Triangles3", _clad_to_engine_cozmo.CustomObjectMarker.Triangles3)

#: .. image:: ../images/custom_markers/SDK_4Triangles.png
Triangles4 = _CustomObjectMarker("Triangles4", _clad_to_engine_cozmo.CustomObjectMarker.Triangles4)

#: .. image:: ../images/custom_markers/SDK_5Triangles.png
Triangles5 = _CustomObjectMarker("Triangles5", _clad_to_engine_cozmo.CustomObjectMarker.Triangles5)


class FixedCustomObject():
'''A fixed object defined by the SDK. It is given a pose and x,y,z sizes.

This object cannot be observed by the robot so its pose never changes.
The position is static in Cozmo's world view; once instantiated, these
objects never move. This could be used to make Cozmo aware of objects and
know to plot a path around them even when they don't have any markers.
To create these use :meth:`~cozmo.world.World.create_custom_fixed_object`
'''

is_visible = False

def __init__(self, pose, x_size_mm, y_size_mm, z_size_mm, object_id, *a, **kw):
super().__init__(*a, **kw)
self._pose = pose
self._object_id = object_id
self._x_size_mm = x_size_mm
self._y_size_mm = y_size_mm
self._z_size_mm = z_size_mm

def __repr__(self):
return ('<%s pose=%s object_id=%d x_size_mm=%.1f y_size_mm=%.1f z_size_mm=%.1f=>' %
(self.__class__.__name__, self.pose, self.object_id,
self.x_size_mm, self.y_size_mm, self.z_size_mm))

#### Private Methods ####
#### Event Wrappers ####
#### Properties ####
@property
def object_id(self):
'''int: The internal ID assigned to the object.

This value can only be assigned once as it is static in the engine.
'''
return self._object_id

@object_id.setter
def object_id(self, value):
if self._object_id is not None:
raise ValueError("Cannot change object ID once set (from %s to %s)" % (self._object_id, value))
logger.debug("Updated object_id for %s from %s to %s", self.__class__, self._object_id, value)
self._object_id = value

@property
def pose(self):
''':class:`cozmo.util.Pose`: The pose of the object in the world.'''
return self._pose

@property
def x_size_mm(self):
'''float: The length of the object in its X axis, in millimeters.'''
return self._x_size_mm

@property
def y_size_mm(self):
'''float: The length of the object in its Y axis, in millimeters.'''
return self._y_size_mm

@property
def z_size_mm(self):
'''float: The length of the object in its Z axis, in millimeters.'''
return self._z_size_mm


#### Private Event Handlers ####
#### Public Event Handlers ####
#### Commands ####

+ 133
- 0
Cozmo_LineFollow/venv/Lib/site-packages/cozmo/oled_face.py View File

@@ -0,0 +1,133 @@
# Copyright (c) 2016 Anki, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License in the file LICENSE.txt or at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

''' Cozmo's OLED screen that displays his face - related functions and values.
'''

# __all__ should order by constants, event classes, other classes, functions.
__all__ = ['dimensions', 'convert_pixels_to_screen_data',
'convert_image_to_screen_data']


SCREEN_WIDTH = 128
SCREEN_HALF_HEIGHT = 32
SCREEN_HEIGHT = SCREEN_HALF_HEIGHT * 2


def dimensions():
'''Return the dimension (width, height) of the oled screen.

Note: The screen is displayed interlaced, with only every other line displayed
This alternates every time the image is changed (no longer than 30 seconds)
to prevent screen burn-in. Therefore to ensure the image looks correct on
either scan-line offset we use half the vertical resolution

Returns:
A tuple of ints (width, height)
'''
return SCREEN_WIDTH, SCREEN_HALF_HEIGHT


def convert_pixels_to_screen_data(pixel_data, image_width, image_height):
'''Convert a sequence of pixel data to the correct format to display on Cozmo's face.

Args:
pixel_data (:class:`bytes`): sequence of pixel values, should be in binary (1s or 0s)
image_width (int): width of the image defined by the pixel_data
image_height (int): height of the image defined by the pixel_data

Returns:
A :class:`bytearray` object representing all of the pixels (8 pixels packed per byte)

Raises:
ValueError: Invalid Dimensions
ValueError: Bad image_width
ValueError: Bad image_height
'''

if len(pixel_data) != (image_width * image_height):
raise ValueError('Invalid Dimensions: len(pixel_data) {0} != image_width={1} * image_height={2} (== {3})'.
format(len(pixel_data), image_width, image_height, image_width * image_height))

num_columns_per_pixel = int(SCREEN_WIDTH / image_width)
num_rows_per_pixel = int(SCREEN_HEIGHT / image_height)

if (image_width * num_columns_per_pixel) != SCREEN_WIDTH:
raise ValueError('Bad image_width: image_width {0} must be an exact integer divisor of {1}'.
format(image_width, SCREEN_WIDTH))

if (image_height * num_rows_per_pixel) != SCREEN_HEIGHT:
raise ValueError('Bad image_height: image_height {0} must be an exact integer divisor of {1}'.
format(image_height, SCREEN_HEIGHT))

pixel_chunks = zip(*[iter(pixel_data)] * 8) # convert into 8 pixel chunks - we'll pack each as 1 byte later
pixel_chunks_per_row = int(SCREEN_WIDTH / 8) # 8 pixels per byte (pixel-chunk)

result_bytes = bytearray()

x = 0
y = 0
for pixel_chunk in pixel_chunks:
# convert the 8 pixels in the chunk into bits to write out
# write each pixel bit num_columns_per_pixel times in a row
pixel_byte = 0
for pixel in pixel_chunk:
for _ in range(num_columns_per_pixel):
pixel_byte <<= 1
pixel_byte += pixel
x += 1
if (x % 8) == 0:
result_bytes.append(pixel_byte)
pixel_byte = 0

# check if this is the end of a row
if x == SCREEN_WIDTH:
x = 0
y += 1

if (x == 0) and (num_rows_per_pixel > 0):
# at the end of a row - copy that row for every extra row-per-pixel
for _ in range(num_rows_per_pixel-1):
start_of_last_row = len(result_bytes) - pixel_chunks_per_row
result_bytes.extend(result_bytes[start_of_last_row:])

return result_bytes


def convert_image_to_screen_data(image, invert_image=False, pixel_threshold=127):
''' Convert an image into the correct format to display on Cozmo's face.

Args:
image (:class:`~PIL.Image.Image`): The image to display on Cozmo's face
invert_image (bool): If true then pixels darker than the threshold are set on
pixel_threshold (int): The grayscale threshold for what to consider on or off (0..255)

Returns:
A :class:`bytearray` object representing all of the pixels (8 pixels packed per byte)
'''

# convert to grayscale
grayscale_image = image.convert('L')

# convert to binary white/black (1/0)
if invert_image:
def pixel_func(x): return 1 if x <= pixel_threshold else 0
else:
def pixel_func(x): return 1 if x >= pixel_threshold else 0
bw = grayscale_image.point(pixel_func, '1')

# convert to a flattened 1D bytes object of pixel values (1s or 0s in this case)
pixel_data = bytes(bw.getdata())

return convert_pixels_to_screen_data(pixel_data, image.width, image.height)

+ 1489
- 0
Cozmo_LineFollow/venv/Lib/site-packages/cozmo/opengl.py
File diff suppressed because it is too large
View File


+ 181
- 0
Cozmo_LineFollow/venv/Lib/site-packages/cozmo/pets.py View File

@@ -0,0 +1,181 @@
# Copyright (c) 2016 Anki, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License in the file LICENSE.txt or at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

'''Pet detection.

Cozmo is capable of detecting pet faces (cats and dogs).

The :class:`cozmo.world.World` object keeps track of pets the robot currently
knows about, along with those that are currently visible to the camera.

Each pet is assigned a :class:`Pet` object, which generates a number of
observable events whenever the pet is observed, etc.

If a pet goes off-screen, it will be assigned a new object_id (and
therefore a new Pet object will be created) when it returns.
This is because the system can only tell if something appears to be
a cat or a dog; it cannot recognize a specific pet or, for instance,
tell the difference between two dogs.

Note that these pet-specific events are also passed up to the
:class:`cozmo.world.World` object, so events for all pets can be
observed by adding handlers there.
'''

# __all__ should order by constants, event classes, other classes, functions.
__all__ = ['PET_VISIBILITY_TIMEOUT', 'PET_TYPE_CAT', 'PET_TYPE_DOG', 'PET_TYPE_UNKNOWN',
'EvtPetAppeared', 'EvtPetDisappeared', 'EvtPetObserved',
'Pet']


import math
import time

from . import logger

from . import event
from . import objects
from . import util

from ._clad import _clad_to_game_anki


#: Length of time in seconds to go without receiving an observed event before
#: assuming that Cozmo can no longer see a pet.
PET_VISIBILITY_TIMEOUT = objects.OBJECT_VISIBILITY_TIMEOUT

# Pet types that Cozmo can distinguish
#: Pet Type reported by Cozmo when unsure of type of pet
PET_TYPE_UNKNOWN = "unknown"
#: Pet Type reported by Cozmo when he thinks it's a cat
PET_TYPE_CAT = "cat"
#: Pet Type reported by Cozmo when he thinks it's a dog
PET_TYPE_DOG = "dog"


class EvtPetObserved(event.Event):
'''Triggered whenever a pet is visually identified by the robot.

A stream of these events are produced while a pet is visible to the robot.
Each event has an updated image_box field.

See EvtPetAppeared if you only want to know when a pet first
becomes visible.
'''
pet = 'The Pet instance that was observed'
updated = 'A set of field names that have changed'
image_box = 'A comzo.util.ImageBox defining where the pet is within Cozmo\'s camera view'


class EvtPetAppeared(event.Event):
'''Triggered whenever a pet is first visually identified by a robot.

This differs from EvtPetObserved in that it's only triggered when
a pet initially becomes visible. If it disappears for more than
PET_VISIBILITY_TIMEOUT seconds and then is seen again, a
EvtPetDisappeared will be dispatched, followed by another
EvtPetAppeared event.

For continuous tracking information about a visible pet, see
EvtPetObserved.
'''
pet = 'The Pet instance that was observed'
updated = 'A set of field names that have changed'
image_box = 'A comzo.util.ImageBox defining where the pet is within Cozmo\'s camera view'


class EvtPetDisappeared(event.Event):
'''Triggered whenever a pet that was previously being observed is no longer visible.'''
pet = 'The Pet instance that is no longer being observed'


def _clad_pet_type_to_pet_type(clad_pet_type):
if clad_pet_type == _clad_to_game_anki.Vision.PetType.Unknown:
return PET_TYPE_UNKNOWN
elif clad_pet_type == _clad_to_game_anki.Vision.PetType.Cat:
return PET_TYPE_CAT
elif clad_pet_type == _clad_to_game_anki.Vision.PetType.Dog:
return PET_TYPE_DOG
else:
raise ValueError("Unexpected pet type %s" % clad_pet_type)


class Pet(objects.ObservableElement):
'''A single pet that Cozmo has detected.

See parent class :class:`~cozmo.objects.ObservableElement` for additional properties
and methods.
'''

#: Length of time in seconds to go without receiving an observed event before
#: assuming that Cozmo can no longer see a pet.
visibility_timeout = PET_VISIBILITY_TIMEOUT

def __init__(self, conn, world, robot, pet_id=None, **kw):
super().__init__(conn, world, robot, **kw)
self._pet_id = pet_id
#: The type of Pet (PET_TYPE_CAT, PET_TYPE_DOG or PET_TYPE_UNKNOWN)
self.pet_type = None

def _repr_values(self):
return 'pet_id=%s pet_type=%s' % (self.pet_id, self.pet_type)

#### Private Methods ####

def _dispatch_observed_event(self, changed_fields, image_box):
self.dispatch_event(EvtPetObserved, pet=self,
updated=changed_fields, image_box=image_box)

def _dispatch_appeared_event(self, changed_fields, image_box):
self.dispatch_event(EvtPetAppeared, pet=self,
updated=changed_fields, image_box=image_box)

def _dispatch_disappeared_event(self):
self.dispatch_event(EvtPetDisappeared, pet=self)

#### Properties ####

@property
def pet_id(self):
'''int: The internal ID assigned to the pet.

This value can only be assigned once as it is static in the engine.
'''
return self._pet_id

@pet_id.setter
def pet_id(self, value):
if self._pet_id is not None:
raise ValueError("Cannot change pet ID once set (from %s to %s)" % (self._pet_id, value))
logger.debug("Updated pet_id for %s from %s to %s", self.__class__, self._pet_id, value)
self._pet_id = value

#### Private Event Handlers ####

def _recv_msg_robot_observed_pet(self, evt, *, msg):

changed_fields = set()
pet_type = _clad_pet_type_to_pet_type(msg.petType)
if pet_type != self.pet_type:
self.pet_type = pet_type
changed_fields.add('pet_type')

image_box = util.ImageBox._create_from_clad_rect(msg.img_rect)
self._on_observed(image_box, msg.timestamp, changed_fields)

#### Public Event Handlers ####

#### Event Wrappers ####

#### Commands ####

+ 2335
- 0
Cozmo_LineFollow/venv/Lib/site-packages/cozmo/robot.py
File diff suppressed because it is too large
View File


+ 49
- 0
Cozmo_LineFollow/venv/Lib/site-packages/cozmo/robot_alignment.py View File

@@ -0,0 +1,49 @@
# Copyright (c) 2017 Anki, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License in the file LICENSE.txt or at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

'''
RobotAlignment related classes, functions, events and values.
'''

# __all__ should order by constants, event classes, other classes, functions.
__all__ = ['RobotAlignmentTypes']

import collections

from ._clad import _clad_to_engine_cozmo, CladEnumWrapper

_RobotAlignmentType = collections.namedtuple('_RobotAlignmentType', ['name', 'id'])


class RobotAlignmentTypes(CladEnumWrapper):
'''Defines all robot alignment types.
'''
_clad_enum = _clad_to_engine_cozmo.AlignmentType
_entry_type = _RobotAlignmentType

#: Align the tips of the lift fingers with the target object
LiftFinger = _entry_type("LiftFinger", _clad_enum.LIFT_FINGER)

#: Align the flat part of the lift with the object
#: (Useful for getting the fingers in the cube's grooves)
LiftPlate = _entry_type("LiftPlate", _clad_enum.LIFT_PLATE)

#: Align the front of cozmo's body
#: (Useful for when the lift is up)
Body = _entry_type("Body", _clad_enum.BODY)

#: For use with distanceFromMarker parameter
Custom = _entry_type("Custom", _clad_enum.CUSTOM)

RobotAlignmentTypes._init_class()

+ 857
- 0
Cozmo_LineFollow/venv/Lib/site-packages/cozmo/run.py View File

@@ -0,0 +1,857 @@
# Copyright (c) 2016-2017 Anki, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License in the file LICENSE.txt or at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

'''The run module contains helper classes and functions for opening a connection to the engine.

To get started, the :func:`run_program` function can be used for most cases,
it handles connecting to a device and then running the function you provide with
the SDK-provided Robot object passed in.

The :func:`connect` function can be used to open a connection
and run your own code connected to a :class:`cozmo.conn.CozmoConnection`
instance. It takes care of setting up an event loop, finding the Android or
iOS device running the Cozmo app and making sure the connection is ok.

You can also use the :func:`connect_with_tkviewer` or :func:`connect_with_3dviewer`
functions which works in a similar way to :func:`connect`, but will also display
either a a window on the screen showing a view from Cozmo's camera (using Tk), or
a 3d viewer (with optional 2nd window showing Cozmo's camera) (using OpenGL), if
supported on your system.

Finally, more advanced progarms can integrate the SDK with an existing event
loop by using the :func:`connect_on_loop` function.

All of these functions make use of a :class:`DeviceConnector` subclass to
deal with actually connecting to an Android or iOS device. There shouldn't
normally be a need to modify them or write your own.
'''

# __all__ should order by constants, event classes, other classes, functions.
__all__ = ['DeviceConnector', 'IOSConnector', 'AndroidConnector', 'TCPConnector',
'connect', 'connect_with_3dviewer', 'connect_with_tkviewer', 'connect_on_loop',
'run_program', 'setup_basic_logging']

import threading

import asyncio
import concurrent.futures
import functools
import inspect
import logging
import os
import os.path
import queue
import shutil
import subprocess
import sys
import types
import warnings

from . import logger, logger_protocol

from . import base
from . import clad_protocol
from . import conn
from . import event
from . import exceptions
from . import usbmux


#: The TCP port number we expect the Cozmo app to be listening on.
COZMO_PORT = 5106

if sys.platform in ('win32', 'cygwin'):
DEFAULT_ADB_CMD = 'adb.exe'
else:
DEFAULT_ADB_CMD = 'adb'


def _observe_connection_lost(proto, cb):
meth = proto.connection_lost
@functools.wraps(meth)
def connection_lost(self, exc):
meth(exc)
cb()
proto.connection_lost = types.MethodType(connection_lost, proto)


class DeviceConnector:
'''Base class for objects that setup the physical connection to a device.'''
def __init__(self, cozmo_port=COZMO_PORT, enable_env_vars=True):
self.cozmo_port = cozmo_port
if enable_env_vars:
self.parse_env_vars()

async def connect(self, loop, protocol_factory, conn_check):
'''Connect attempts to open a connection transport to the Cozmo app on a device.

On opening a transport it will create a protocol from the supplied
factory and connect it to the transport, returning a (transport, protocol)
tuple. See :meth:`asyncio.BaseEventLoop.create_connection`
'''
raise NotImplementedError

def parse_env_vars(self):
try:
self.cozmo_port = int(os.environ['COZMO_PORT'])
except (KeyError, ValueError):
pass


class IOSConnector(DeviceConnector):
'''Connects to an attached iOS device over USB.

Opens a connection to the first iOS device that's found to be running
the Cozmo app in SDK mode.

iTunes (or another service providing usbmuxd) must be installed in order
for this connector to be able to open a connection to a device.

An instance of this class can be passed to the ``connect_`` prefixed
functions in this module.

Args:
serial (string): Serial number of the device to connect to.
If None, then connect to the first available iOS device running
the Cozmo app in SDK mode.
'''
def __init__(self, serial=None, **kw):
super().__init__(**kw)
self.usbmux = None
self._connected = set()
self.serial = serial

async def connect(self, loop, protocol_factory, conn_check):
if not self.usbmux:
self.usbmux = await usbmux.connect_to_usbmux(loop=loop)

try:
if self.serial is None:
device_info, transport, proto = await self.usbmux.connect_to_first_device(
protocol_factory, self.cozmo_port, exclude=self._connected)

else:
device_id = await self.usbmux.wait_for_serial(self.serial)
device_info, transport, proto = await self.usbmux.connect_to_device(
protocol_factory, device_id, self.cozmo_port)
except asyncio.TimeoutError as exc:
raise exceptions.ConnectionError("No connected iOS devices running Cozmo in SDK mode") from exc

device_id = device_info.get('DeviceID')
proto.device_info={
'device_type': 'ios',
'device_id': device_id,
'serial': device_info.get('SerialNumber')
}

if conn_check is not None:
await conn_check(proto)

self._connected.add(device_id)
logger.info('Connected to iOS device_id=%s serial=%s', device_id,
device_info.get('SerialNumber'))
_observe_connection_lost(proto, functools.partial(self._disconnect, device_id))
return transport, proto

def _disconnect(self, device_id):
logger.info('iOS device_id=%s disconnected.', device_id)
self._connected.discard(device_id)


class AndroidConnector(DeviceConnector):
'''Connects to an attached Android device over USB.

This requires the Android Studio command line tools to be installed,
specifically `adb`.

By default the connector will attempt to locate `adb` (or `adb.exe`
on Windows) in common locations, but it may also be supplied by setting
the ``ANDROID_ADB_PATH`` environment variable, or by passing it
to the constructor.

An instance of this class can be passed to the ``connect_`` prefixed
functions in this module.

Args:
serial (string): Serial number of the device to connect to.
If None, then connect to the first available Android device running
the Cozmo app in SDK mode.
'''
def __init__(self, adb_cmd=None, serial=None, **kw):
self._adb_cmd = None
super().__init__(**kw)

self.serial = serial
self.portspec = 'tcp:' + str(self.cozmo_port)
self._connected = set()
if adb_cmd:
self._adb_cmd = adb_cmd
else:
self._adb_cmd = shutil.which(DEFAULT_ADB_CMD)

def parse_env_vars(self):
super().parse_env_vars()

self._adb_cmd = os.environ.get('ANDROID_ADB_PATH')

@property
def adb_cmd(self):
if self._adb_cmd is not None:
return self._adb_cmd

if sys.platform != 'win32':
return DEFAULT_ADB_CMD

# C:\Users\IEUser\AppData\Local\Android\android-sdk
# C:\Program Files (x86)\Android\android-sdk
try_paths = []
for path in [os.environ[key] for key in ('LOCALAPPDATA', 'ProgramFiles', 'ProgramFiles(x86)') if key in os.environ]:
try_paths.append(os.path.join(path, 'Android', 'android-sdk'))

for path in try_paths:
adb_path = os.path.join(path, 'platform-tools', 'adb.exe')
if os.path.exists(adb_path):
self._adb_cmd = adb_path
logger.debug('Found adb.exe at %s', adb_path)
return adb_path

raise ValueError('Could not find Android development tools')

def _exec(self, *args):
try:
result = subprocess.run([self.adb_cmd] + list(args),
stdout=subprocess.PIPE, stderr=subprocess.PIPE, timeout=5)
except Exception as e:
raise ValueError('Failed to execute adb command %s: %s' % (self.adb_cmd, e))
if result.returncode != 0:
raise ValueError('Failed to execute adb command %s: %s' % (result.args, result.stderr))
return result.stdout.split(b'\n')

def _devices(self):
for line in self._exec('devices'):
line = line.split()
if len(line) != 2 or line[1] != b'device':
continue
yield line[0].decode('ascii') # device serial #

def _add_forward(self, serial):
self._exec('-s', serial, 'forward', self.portspec, self.portspec)

def _remove_forward(self, serial):
self._exec('-s', serial, 'forward', '--remove', self.portspec)

async def connect(self, loop, protocol_factory, conn_check):
version_mismatch = None
for serial in self._devices():
if serial in self._connected:
continue
if self.serial is not None and serial.lower() != self.serial.lower():
continue

logger.debug('Checking connection to Android device: %s', serial)
try:
self._remove_forward(serial)
except:
pass
self._add_forward(serial)
try:
transport, proto = await loop.create_connection(
protocol_factory, '127.0.0.1', self.cozmo_port)
proto.device_info={
'device_type': 'android',
'serial': serial,
}
if conn_check:
# Check that we have a good connection before returning
try:
await conn_check(proto)
except Exception as e:
logger.debug('Failed connection check: %s', e)
raise

logger.info('Connected to Android device serial=%s', serial)
self._connected.add(serial)
_observe_connection_lost(proto, functools.partial(self._disconnect, serial))
return transport, proto
except exceptions.SDKVersionMismatch as e:
version_mismatch = e
except:
pass
self._remove_forward(serial)

if version_mismatch is not None:
raise version_mismatch

raise exceptions.ConnectionError("No connected Android devices running Cozmo in SDK mode")

def _disconnect(self, serial):
logger.info('Android serial=%s disconnected.', serial)
self._connected.discard(serial)


class TCPConnector(DeviceConnector):
'''Connects to the Cozmo app directly via TCP.

Generally only used for testing and debugging.

Requires that a SDK_TCP_PORT environment variable be set to the port
number to connect to.
'''
def __init__(self, tcp_port=None, ip_addr='127.0.0.1', **kw):
super().__init__(**kw)

self.ip_addr = ip_addr
if tcp_port is not None:
# override SDK_TCP_PORT environment variable
self.tcp_port = tcp_port

def parse_env_vars(self):
super().parse_env_vars()

self.tcp_port = None
try:
self.tcp_port = int(os.environ['SDK_TCP_PORT'])
except (KeyError, ValueError):
pass

@property
def enabled(self):
return self.tcp_port is not None

async def connect(self, loop, protocol_factory, conn_check):
transport, proto = await loop.create_connection(protocol_factory, self.ip_addr, self.tcp_port)
proto.device_info={
'device_type': 'tcp',
'host': '%s:%s' % (self.ip_addr, self.tcp_port),
}
if conn_check:
try:
await conn_check(proto)
except Exception as e:
logger.debug('Failed connection check: %s', e)
raise
logger.info("Connected to device on TCP port %d" % self.tcp_port)
return transport, proto


class FirstAvailableConnector(DeviceConnector):
'''Connects to the first Android or iOS device running the Cozmo app in SDK mode.

This class creates an :class:`AndroidConnector` or :class:`IOSConnector`
instance and returns the first successful connection.

This is the default connector used by ``connect_`` functions.
'''
def __init__(self):
super().__init__(self, enable_env_vars=False)
self.tcp = TCPConnector()
self.ios = IOSConnector()
self.android = AndroidConnector()

async def _do_connect(self, connector,loop, protocol_factory, conn_check):
connect = connector.connect(loop, protocol_factory, conn_check)
result = await asyncio.gather(connect, loop=loop, return_exceptions=True)
return result[0]

async def connect(self, loop, protocol_factory, conn_check):
conn_args = (loop, protocol_factory, conn_check)

tcp_result = None
if self.tcp.enabled:
tcp_result = await self._do_connect(self.tcp, *conn_args)
if not isinstance(tcp_result, BaseException):
return tcp_result
logger.warning('No TCP connection found running Cozmo: %s', tcp_result)

android_result = await self._do_connect(self.android, *conn_args)
if not isinstance(android_result, BaseException):
return android_result

ios_result = await self._do_connect(self.ios, *conn_args)
if not isinstance(ios_result, BaseException):
return ios_result

logger.warning('No iOS device found running Cozmo: %s', ios_result)
logger.warning('No Android device found running Cozmo: %s', android_result)

if isinstance(tcp_result, exceptions.SDKVersionMismatch):
raise tcp_result
if isinstance(ios_result, exceptions.SDKVersionMismatch):
raise ios_result
if isinstance(android_result, exceptions.SDKVersionMismatch):
raise android_result

raise exceptions.NoDevicesFound('No devices connected running Cozmo in SDK mode')


# Create an instance of a connector to use by default
# The instance will maintain state about which devices are currently connected.
_DEFAULT_CONNECTOR = FirstAvailableConnector()


def _sync_exception_handler(abort_future, loop, context):
loop.default_exception_handler(context)
exception = context.get('exception')
if exception is not None:
abort_future.set_exception(context['exception'])
else:
abort_future.set_exception(RuntimeError(context['message']))


class _LoopThread:
'''Takes care of managing an event loop running in a dedicated thread.

Args:
loop (:class:`asyncio.BaseEventLoop`): The loop to run
f (callable): Optional code to execute on the loop's thread
conn_factory (callable): Override the factory function to generate a
:class:`cozmo.conn.CozmoConnection` (or subclass) instance.
connector (:class:`DeviceConnector`): Optional instance of a DeviceConnector
subclass that handles opening the USB connection to a device.
By default, it will connect to the first Android or iOS device that
has the Cozmo app running in SDK mode.
abort_future (:class:`concurrent.futures.Future): Optional future to
raise an exception on in the event of an exception occurring within
the thread.
'''
def __init__(self, loop, f=None, conn_factory=conn.CozmoConnection, connector=None, abort_future=None):
self.loop = loop
self.f = f
if not abort_future:
abort_future = concurrent.futures.Future()
self.abort_future = abort_future
self.conn_factory = conn_factory
self.connector = connector
self.thread = None
self._running = False

def start(self):
'''Start a thread and open a connection to a device.

Returns:
:class:`cozmo.conn.CozmoConnection` instance
'''
q = queue.Queue()
abort_future = concurrent.futures.Future()
def run_loop():
asyncio.set_event_loop(self.loop)
try:
coz_conn = connect_on_loop(self.loop, self.conn_factory, self.connector)
q.put(coz_conn)
except Exception as e:
self.abort_future.set_exception(e)
q.put(e)
return

if self.f:
asyncio.ensure_future(self.f(coz_conn))
self.loop.run_forever()

self.thread = threading.Thread(target=run_loop)
self.thread.start()

coz_conn = q.get(10)
if coz_conn is None:
raise TimeoutError("Timed out waiting for connection to device")
if isinstance(coz_conn, Exception):
raise coz_conn
self.coz_conn = coz_conn
self._running = True
return coz_conn


def stop(self):
'''Cleaning shutdown the running loop and thread.'''
if self._running:
async def _stop():
await self.coz_conn.shutdown()
self.loop.call_soon(lambda: self.loop.stop())
asyncio.run_coroutine_threadsafe(_stop(), self.loop).result()
self.thread.join()
self._running = False

def abort(self, exc):
'''Abort the running loop and thread.'''
if self._running:
async def _abort(exc):
self.coz_conn.abort(exc)
asyncio.run_coroutine_threadsafe(_abort(exc), self.loop).result()
self.stop()


def _connect_async(f, conn_factory=conn.CozmoConnection, connector=None):
# use the default loop, if one is available for the current thread,
# if not create a new loop and make it the default.
#
# the expectation is that if the user wants explicit control over which
# loop the code is executed on, they'll just use connect_on_loop directly.
loop = None
try:
loop = asyncio.get_event_loop()
except:
pass

if loop is None:
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)

coz_conn = connect_on_loop(loop, conn_factory, connector)
try:
loop.run_until_complete(f(coz_conn))
except KeyboardInterrupt:
logger.info('Exit requested by user')
finally:
loop.run_until_complete(coz_conn.shutdown())
loop.stop()
loop.run_forever()


_sync_loop = asyncio.new_event_loop()
def _connect_sync(f, conn_factory=conn.CozmoConnection, connector=None):
abort_future = concurrent.futures.Future()
conn_factory = functools.partial(conn_factory, _sync_abort_future=abort_future)
lt = _LoopThread(_sync_loop, conn_factory=conn_factory, connector=connector, abort_future=abort_future)
_sync_loop.set_exception_handler(functools.partial(_sync_exception_handler, abort_future))

coz_conn = lt.start()

try:
f(base._SyncProxy(coz_conn))
finally:
lt.stop()


def connect_on_loop(loop, conn_factory=conn.CozmoConnection, connector=None):
'''Uses the supplied event loop to connect to a device.

Will run the event loop in the current thread until the
connection succeeds or fails.

If you do not want/need to manage your own loop, then use the
:func:`connect` function to handle setup/teardown and execute
a user-supplied function.

Args:
loop (:class:`asyncio.BaseEventLoop`): The event loop to use to
connect to Cozmo.
conn_factory (callable): Override the factory function to generate a
:class:`cozmo.conn.CozmoConnection` (or subclass) instance.
connector (:class:`DeviceConnector`): Optional instance of a DeviceConnector
subclass that handles opening the USB connection to a device.
By default, it will connect to the first Android or iOS device that
has the Cozmo app running in SDK mode.

Returns:
A :class:`cozmo.conn.CozmoConnection` instance.
'''
if connector is None:
connector = _DEFAULT_CONNECTOR

factory = functools.partial(conn_factory, loop=loop)

async def conn_check(coz_conn):
await coz_conn.wait_for(conn.EvtConnected, timeout=5)

async def connect():
return await connector.connect(loop, factory, conn_check)

transport, coz_conn = loop.run_until_complete(connect())
return coz_conn


def connect(f, conn_factory=conn.CozmoConnection, connector=None):
'''Connects to the Cozmo Engine on the mobile device and supplies the connection to a function.

Accepts a function, f, that is given a :class:`cozmo.conn.CozmoConnection` object as
a parameter.

The supplied function may be either an asynchronous coroutine function
(normally defined using ``async def``) or a regular synchronous function.

If an asynchronous function is supplied it will be run on the same thread
as the Cozmo event loop and must use the ``await`` keyword to yield control
back to the loop.

If a synchronous function is supplied then it will run on the main thread
and Cozmo's event loop will run on a separate thread. Calls to
asynchronous methods returned from CozmoConnection will automatically
be translated to synchronous ones.

The connect function will return once the supplied function has completed,
as which time it will terminate the connection to the robot.

Args:
f (callable): The function to execute
conn_factory (callable): Override the factory function to generate a
:class:`cozmo.conn.CozmoConnection` (or subclass) instance.
connector (:class:`DeviceConnector`): Optional instance of a DeviceConnector
subclass that handles opening the USB connection to a device.
By default it will connect to the first Android or iOS device that
has the Cozmo app running in SDK mode.
'''
if asyncio.iscoroutinefunction(f):
return _connect_async(f, conn_factory, connector)
return _connect_sync(f, conn_factory, connector)


def _connect_viewer(f, conn_factory, connector, viewer):
# Run the viewer in the main thread, with the SDK running on a new background thread.
loop = asyncio.new_event_loop()
abort_future = concurrent.futures.Future()

async def view_connector(coz_conn):
try:
await viewer.connect(coz_conn)

if inspect.iscoroutinefunction(f):
await f(coz_conn)
else:
await coz_conn._loop.run_in_executor(None, f, base._SyncProxy(coz_conn))
finally:
viewer.disconnect()

try:
if not inspect.iscoroutinefunction(f):
conn_factory = functools.partial(conn_factory, _sync_abort_future=abort_future)
lt = _LoopThread(loop, f=view_connector, conn_factory=conn_factory, connector=connector)
lt.start()
viewer.mainloop()
except BaseException as e:
abort_future.set_exception(exceptions.SDKShutdown(repr(e)))
raise
finally:
lt.stop()


def connect_with_3dviewer(f, conn_factory=conn.CozmoConnection, connector=None,
enable_camera_view=False, show_viewer_controls=True):
'''Setup a connection to a device and run a user function while displaying Cozmo's 3d world.

This displays an OpenGL window on the screen with a 3D view of Cozmo's
understanding of the world. Optionally, if `use_viewer` is True, a 2nd OpenGL
window will also display showing a view of Cozmo's camera. It will return an
error if the current system does not support PyOpenGL.

The function may be either synchronous or asynchronous (defined
used ``async def``).

The function must accept a :class:`cozmo.CozmoConnection` object as
its only argument.
This call will block until the supplied function completes.

Args:
f (callable): The function to execute
conn_factory (callable): Override the factory function to generate a
:class:`cozmo.conn.CozmoConnection` (or subclass) instance.
connector (:class:`DeviceConnector`): Optional instance of a DeviceConnector
subclass that handles opening the USB connection to a device.
By default it will connect to the first Android or iOS device that
has the Cozmo app running in SDK mode.
enable_camera_view (bool): Specifies whether to also open a 2D camera
view in a second OpenGL window.
show_viewer_controls (bool): Specifies whether to draw controls on the view.
'''
try:
from . import opengl
except ImportError as exc:
opengl = exc

if isinstance(opengl, Exception):
if isinstance(opengl, exceptions.InvalidOpenGLGlutImplementation):
raise NotImplementedError('GLUT (OpenGL Utility Toolkit) is not available:\n%s'
% opengl)
else:
raise NotImplementedError('opengl is not available; '
'make sure the PyOpenGL and Pillow packages are installed:\n'
'Do `pip3 install --user cozmo[3dviewer]` to install. Error: %s' % opengl)

viewer = opengl.OpenGLViewer(enable_camera_view=enable_camera_view, show_viewer_controls=show_viewer_controls)

_connect_viewer(f, conn_factory, connector, viewer)


def connect_with_tkviewer(f, conn_factory=conn.CozmoConnection, connector=None, force_on_top=False):
'''Setup a connection to a device and run a user function while displaying Cozmo's camera.

This displays a Tk window on the screen showing a view of Cozmo's camera.
It will return an error if the current system does not support Tk.

The function may be either synchronous or asynchronous (defined
used ``async def``).

The function must accept a :class:`cozmo.CozmoConnection` object as
its only argument.
This call will block until the supplied function completes.

Args:
f (callable): The function to execute
conn_factory (callable): Override the factory function to generate a
:class:`cozmo.conn.CozmoConnection` (or subclass) instance.
connector (:class:`DeviceConnector`): Optional instance of a DeviceConnector
subclass that handles opening the USB connection to a device.
By default it will connect to the first Android or iOS device that
has the Cozmo app running in SDK mode.
force_on_top (bool): Specifies whether the window should be forced on top of all others
'''
try:
from . import tkview
except ImportError as exc:
tkview = exc

if isinstance(tkview, Exception):
raise NotImplementedError('tkviewer not available on this platform; '
'make sure Tkinter, NumPy and Pillow packages are installed (%s)' % tkview)

viewer = tkview.TkImageViewer(force_on_top=force_on_top)

_connect_viewer(f, conn_factory, connector, viewer)


def setup_basic_logging(general_log_level=None, protocol_log_level=None,
protocol_log_messages=clad_protocol.LOG_ALL, target=sys.stderr,
deprecated_filter="default"):
'''Helper to perform basic setup of the Python logging machinery.

The SDK defines two loggers:

* :data:`logger` ("cozmo.general") - For general purpose information
about events within the SDK; and
* :data:`logger_protocol` ("cozmo.protocol") - For low level
communication messages between the device and the SDK.

Generally only :data:`logger` is interesting.

Args:
general_log_level (str): 'DEBUG', 'INFO', 'WARN', 'ERROR' or an equivalent
constant from the :mod:`logging` module. If None then a
value will be read from the COZMO_LOG_LEVEL environment variable.
protocol_log_level (str): as general_log_level. If None then a
value will be read from the COZMO_PROTOCOL_LOG_LEVEL environment
variable.
protocol_log_messages (list): The low level messages that should be
logged to the protocol log. Defaults to all. Will read from
the COMZO_PROTOCOL_LOG_MESSAGES if available which should be
a comma separated list of message names (case sensitive).
target (object): The stream to send the log data to; defaults to stderr
deprecated_filter (str): The filter for any DeprecationWarning messages.
This is defaulted to "default" which shows the warning once per
location. You can hide all deprecated warnings by passing in "ignore",
see https://docs.python.org/3/library/warnings.html#warning-filter
for more information.
'''
if deprecated_filter is not None:
warnings.filterwarnings(deprecated_filter, category=DeprecationWarning)

if general_log_level is None:
general_log_level = os.environ.get('COZMO_LOG_LEVEL', logging.INFO)
if protocol_log_level is None:
protocol_log_level = os.environ.get('COZMO_PROTOCOL_LOG_LEVEL', logging.INFO)
if protocol_log_level:
if 'COMZO_PROTOCOL_LOG_MESSAGES' in os.environ:
lm = os.environ['COMZO_PROTOCOL_LOG_MESSAGES']
if lm.lower() == 'all':
clad_protocol.CLADProtocol._clad_log_which = clad_protocol.LOG_ALL
else:
clad_protocol.CLADProtocol._clad_log_which = set(lm.split(','))
else:
clad_protocol.CLADProtocol._clad_log_which = protocol_log_messages

h = logging.StreamHandler(stream=target)
f = logging.Formatter('%(asctime)s %(name)-12s %(levelname)-8s %(message)s')
h.setFormatter(f)
logger.addHandler(h)
logger. setLevel(general_log_level)
if protocol_log_level is not None:
logger_protocol.addHandler(h)
logger_protocol.setLevel(protocol_log_level)


def run_program(f, use_viewer=False, conn_factory=conn.CozmoConnection,
connector=None, force_viewer_on_top=False,
deprecated_filter="default", use_3d_viewer=False,
show_viewer_controls=True,
exit_on_connection_error=True):
'''Connect to Cozmo and run the provided program/function f.

Args:

f (callable): The function to execute, accepts a connected
:class:`cozmo.robot.Robot` as the parameter.
use_viewer (bool): Specifies whether to display a view of Cozmo's camera
in a window.
conn_factory (callable): Override the factory function to generate a
:class:`cozmo.conn.CozmoConnection` (or subclass) instance.
connector (:class:`DeviceConnector`): Optional instance of a DeviceConnector
subclass that handles opening the USB connection to a device.
By default it will connect to the first Android or iOS device that
has the Cozmo app running in SDK mode.
force_viewer_on_top (bool): Specifies whether the window should be
forced on top of all others (only relevant if use_viewer is True).
Note that this is ignored if use_3d_viewer is True (as it's not
currently supported on that windowing system).
deprecated_filter (str): The filter for any DeprecationWarning messages.
This is defaulted to "default" which shows the warning once per
location. You can hide all deprecated warnings by passing in "ignore",
see https://docs.python.org/3/library/warnings.html#warning-filter
for more information.
use_3d_viewer (bool): Specifies whether to display a 3D view of Cozmo's
understanding of the world in a window. Note that if both this and
`use_viewer` are set then the 2D camera view will render in an OpenGL
window instead of a TkView window.
show_viewer_controls (bool): Specifies whether to draw controls on the view.
exit_on_connection_error (bool): Specify whether the program should exit on
connection error or should an error be raised. Default to true.
'''
setup_basic_logging(deprecated_filter=deprecated_filter)

# Wrap f (a function that takes in an already created robot)
# with a function that accepts a cozmo.conn.CozmoConnection
if asyncio.iscoroutinefunction(f):
@functools.wraps(f)
async def wrapper(sdk_conn):
try:
robot = await sdk_conn.wait_for_robot()
await f(robot)
except exceptions.SDKShutdown:
pass
except KeyboardInterrupt:
logger.info('Exit requested by user')
else:
@functools.wraps(f)
def wrapper(sdk_conn):
try:
robot = sdk_conn.wait_for_robot()
f(robot)
except exceptions.SDKShutdown:
pass
except KeyboardInterrupt:
logger.info('Exit requested by user')

try:
if use_3d_viewer:
connect_with_3dviewer(wrapper, conn_factory=conn_factory, connector=connector,
enable_camera_view=use_viewer, show_viewer_controls=show_viewer_controls)
elif use_viewer:
connect_with_tkviewer(wrapper, conn_factory=conn_factory, connector=connector,
force_on_top=force_viewer_on_top)
else:
connect(wrapper, conn_factory=conn_factory, connector=connector)
except KeyboardInterrupt:
logger.info('Exit requested by user')
except exceptions.ConnectionError as e:
if exit_on_connection_error:
sys.exit("A connection error occurred: %s" % e)
else:
logger.error("A connection error occurred: %s" % e)
raise

+ 128
- 0
Cozmo_LineFollow/venv/Lib/site-packages/cozmo/song.py View File

@@ -0,0 +1,128 @@
# Copyright (c) 2018 Anki, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License in the file LICENSE.txt or at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

'''
Song related classes, functions, events and values.
'''

# __all__ should order by constants, event classes, other classes, functions.
__all__ = ['NoteTypes', 'NoteDurations', 'SongNote']

import collections

from . import logger

from . import action
from . import exceptions
from . import event

from ._clad import _clad_to_engine_iface, _clad_to_engine_cozmo, _clad_to_engine_anki, CladEnumWrapper

# generate names for each CLAD defined Note Type
class _NoteType(collections.namedtuple('_NoteType', 'name id')):
# Tuple mapping between CLAD SongNoteType. name and ID
# All instances will be members of NoteTypes

# Keep _NoteType as lightweight as a normal namedtuple
__slots__ = ()

def __str__(self):
return 'NoteTypes.%s' % self.name


class NoteTypes(CladEnumWrapper):
"""The possible values for an NoteType.

A pitch between C2 and C3_Sharp can be specified,
as well as a rest (for timed silence), giving
cozmo a vocal range of slightly more than one
octave.

B_Flat and E_Flat are represented as their corresponding
sharps.
"""
_clad_enum = _clad_to_engine_iface.SongNoteType
_entry_type = _NoteType

#:
C2 = _entry_type("C2", _clad_enum.C2)
#:
C2_Sharp = _entry_type("C2_Sharp", _clad_enum.C2_Sharp)
#:
D2 = _entry_type("D2", _clad_enum.D2)
#:
D2_Sharp = _entry_type("D2_Sharp", _clad_enum.D2_Sharp)
#:
E2 = _entry_type("E2", _clad_enum.E2)
#:
F2 = _entry_type("F2", _clad_enum.F2)
#:
F2_Sharp = _entry_type("F2_Sharp", _clad_enum.F2_Sharp)
#:
G2 = _entry_type("G2", _clad_enum.G2)
#:
G2_Sharp = _entry_type("G2_Sharp", _clad_enum.G2_Sharp)
#:
A2 = _entry_type("A2", _clad_enum.A2)
#:
A2_Sharp = _entry_type("A2_Sharp", _clad_enum.A2_Sharp)
#:
B2 = _entry_type("B2", _clad_enum.B2)
#:
C3 = _entry_type("C3", _clad_enum.C3)
#:
C3_Sharp = _entry_type("C3_Sharp", _clad_enum.C3_Sharp)
#:
Rest = _entry_type("Rest", _clad_enum.Rest)

NoteTypes._init_class(warn_on_missing_definitions=True)


# generate names for each CLAD defined Note Duration
class _NoteDuration(collections.namedtuple('_NoteDuration', 'name id')):
# Tuple mapping between CLAD SongNoteDuration. name and ID
# All instances will be members of NoteTypes

# Keep _NoteDuration as lightweight as a normal namedtuple
__slots__ = ()

def __str__(self):
return 'NoteDurations.%s' % self.name


class NoteDurations(CladEnumWrapper):
"""The possible values for a NoteDuration.
"""
_clad_enum = _clad_to_engine_iface.SongNoteDuration
_entry_type = _NoteDuration

#:
Whole = _entry_type("Whole", _clad_enum.Whole)
#:
ThreeQuarter = _entry_type("ThreeQuarter", _clad_enum.ThreeQuarter)
#:
Half = _entry_type("Half", _clad_enum.Half)
#:
Quarter = _entry_type("Quarter", _clad_enum.Quarter)

NoteDurations._init_class(warn_on_missing_definitions=True)


class SongNote(_clad_to_engine_iface.SongNote):
"""Represents on element in a song. Consists of a :class:`cozmo.song.NoteTypes` which specifies
either a pitch or rest, and a :class:`cozmo.song.NoteDurations` specifying the length of the
note.
"""
def __init__(self, noteType=NoteTypes.C2, noteDuration=NoteDurations.Whole):
super(SongNote, self).__init__(noteType.id, noteDuration.id)

+ 165
- 0
Cozmo_LineFollow/venv/Lib/site-packages/cozmo/tkview.py View File

@@ -0,0 +1,165 @@
# Copyright (c) 2016-2017 Anki, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License in the file LICENSE.txt or at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

'''This module provides a simple GUI viewer for Cozmo's camera.

It uses Tkinter, the standard Python GUI toolkit which is optionally available
on most platforms, and also depends on the Pillow and numpy libraries for
image processing.


See the online SDK documentation for details on how to install these extra
packages on your platform.

The easiest way to make use of this viewer is to call
:func:`cozmo.run.connect_with_tkviewer`.

Warning:
This package requires Python to have Tkinter installed to display the GUI.
'''


# __all__ should order by constants, event classes, other classes, functions.
__all__ = ['TkImageViewer']

import cozmo
import collections
import functools
import queue
import platform
import time

from PIL import Image, ImageDraw, ImageTk
import tkinter

from . import world


class TkThreadable:
'''A mixin for adding threadsafe calls to tkinter methods.'''
#pylint: disable=no-member
# no-member errors are raised in pylint regarding members/methods called but not defined in our mixin.
def __init__(self, *a, **kw):
self._thread_queue = queue.Queue()
self.after(50, self._thread_call_dispatch)

def call_threadsafe(self, method, *a, **kw):
self._thread_queue.put((method, a, kw))

def _thread_call_dispatch(self):
while True:
try:
method, a, kw = self._thread_queue.get(block=False)
self.after_idle(method, *a, **kw)
except queue.Empty:
break
self.after(50, self._thread_call_dispatch)


class TkImageViewer(tkinter.Frame, TkThreadable):
'''Simple Tkinter camera viewer.'''

# TODO: rewrite this whole thing. Make a generic camera widget
# that can be used in other Tk applications. Also handle resizing
# the window properly.
def __init__(self,
tk_root=None, refresh_interval=10, image_scale = 2,
window_name = "CozmoView", force_on_top=True):
if tk_root is None:
tk_root = tkinter.Tk()
tkinter.Frame.__init__(self, tk_root)
TkThreadable.__init__(self)
self._img_queue = collections.deque(maxlen=1)

self._refresh_interval = refresh_interval
self.scale = image_scale
self.width = None
self.height = None

self.tk_root = tk_root
tk_root.wm_title(window_name)
# Tell the TK root not to resize based on the contents of the window.
# Necessary to get the resizing to function properly
tk_root.pack_propagate(False)
# Set the starting window size
tk_root.geometry('{}x{}'.format(720, 540))

self.label = tkinter.Label(self.tk_root,image=None)
self.tk_root.protocol("WM_DELETE_WINDOW", self._delete_window)
self._isRunning = True
self.robot = None
self.handler = None
self._first_image = True
tk_root.aspect(4,3,4,3)

if force_on_top:
# force window on top of all others, regardless of focus
tk_root.wm_attributes("-topmost", 1)

self.tk_root.bind("<Configure>", self.configure)
self._repeat_draw_frame()

async def connect(self, coz_conn):
self.robot = await coz_conn.wait_for_robot()
self.robot.camera.image_stream_enabled = True
self.handler = self.robot.world.add_event_handler(
world.EvtNewCameraImage, self.image_event)

def disconnect(self):
if self.handler:
self.handler.disable()
self.call_threadsafe(self.quit)

# The base class configure doesn't take an event
#pylint: disable=arguments-differ
def configure(self, event):
if event.width < 50 or event.height < 50:
return
self.height = event.height
self.width = event.width


def image_event(self, evt, *, image, **kw):
if self._first_image or self.width is None:
img = image.annotate_image(scale=self.scale)
else:
img = image.annotate_image(fit_size=(self.width, self.height))
self._img_queue.append(img)

def _delete_window(self):
self.tk_root.destroy()
self.quit()
self._isRunning = False

def _draw_frame(self):
if ImageTk is None:
return

try:
image = self._img_queue.popleft()
except IndexError:
# no new image
return

self._first_image = False
photoImage = ImageTk.PhotoImage(image)

self.label.configure(image=photoImage)
self.label.image = photoImage
# Dynamically expand the image to fit the window. And fill in both X and Y directions.
self.label.pack(fill=tkinter.BOTH, expand=True)

def _repeat_draw_frame(self, event=None):
self._draw_frame()
self.after(self._refresh_interval, self._repeat_draw_frame)

+ 15
- 0
Cozmo_LineFollow/venv/Lib/site-packages/cozmo/usbmux/__init__.py View File

@@ -0,0 +1,15 @@
# Copyright (c) 2016 Anki, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License in the file LICENSE.txt or at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

from .usbmux import *

BIN
Cozmo_LineFollow/venv/Lib/site-packages/cozmo/usbmux/__pycache__/__init__.cpython-36.pyc View File


BIN
Cozmo_LineFollow/venv/Lib/site-packages/cozmo/usbmux/__pycache__/usbmux.cpython-36.pyc View File


+ 470
- 0
Cozmo_LineFollow/venv/Lib/site-packages/cozmo/usbmux/usbmux.py View File

@@ -0,0 +1,470 @@
# Copyright (c) 2016 Anki, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License in the file LICENSE.txt or at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

__all__ = ('USBMuxError', 'ProtocolError', 'DeviceNotConnected',
'ConnectionRefused', 'ConnectionFailed', 'QueueNotifyCM', 'USBMux',
'connect_to_usbmux')

import asyncio
import collections
import contextlib
import plistlib
import socket
import struct
import sys
import time


DEFAULT_SOCKET_PATH = '/var/run/usbmuxd'
DEFAULT_SOCKET_PORT = 27015
DEFAULT_MAX_WAIT = 2

PLIST_VERSION = 1

ACTION_ATTACHED = 'attached'
ACTION_DETACHED = 'detached'


class USBMuxError(Exception): pass

class ProtocolError(USBMuxError): pass

class DeviceNotConnected(USBMuxError): pass

class ConnectionRefused(USBMuxError): pass

class ConnectionFailed(USBMuxError): pass


class PlistProto(asyncio.Protocol):
def connection_made(self, transport):
self.transport = transport
self._buf = bytearray()

def data_received(self, data):
self._buf += data
while len(self._buf) > 4:
length = struct.unpack('I', self._buf[:4])[0]
if len(self._buf) < length:
return
ver, req, tag = struct.unpack('III', self._buf[4:16])
if ver != PLIST_VERSION:
raise ProtocolError("Unsupported protocol version from usbmux stream")
pldata = plistlib.loads(self._buf[16:length])
self.msg_received(pldata)
self._buf = self._buf[length:]

def send_msg(self, **kw):
pl = plistlib.dumps(kw)
self.transport.write(struct.pack('IIII', len(pl) + 16, 1, 8, 1))
self.transport.write(pl)

def msg_received(self, msg):
'''Called when a plist record is received'''


class USBMuxConnector(PlistProto):
'''Opens a connection to a port on a device'''

def __init__(self, device_id, port, waiter):
self.device_id = device_id
self.port = port
self.waiter = waiter

def connection_made(self, transport):
super().connection_made(transport)

self.send_msg(
MessageType='Connect',
ClientVersionString='pyusbmux',
ProgName='pyusbmux',
DeviceID=self.device_id,
PortNumber=socket.htons(self.port)
)

def connection_lost(self, exc):
if self.waiter.done():
return
self.waiter.set_exception(exc)

def msg_received(self, msg):
if msg['MessageType'] != 'Result':
return
status = msg['Number']
if status == 0:
self.waiter.set_result(None)

# ensure no futher data is received until the protocol
# is switched to the application protocol.
self.transport.pause_reading()

elif status == 2:
self.waiter.set_exception(DeviceNotConnected("Device %s is not currently connected" % (self.device_id,)))

elif status == 3:
self.waiter.set_exception(ConnectionRefused("Connection refused to device_id=%s port=%d" % (self.device_id, self.port)))

else:
self.waiter.set_exception(ConnectionFailed("Protocol error connecting to device %s" % (self.device_id,)))


class _ProtoSwitcher(asyncio.Protocol):
def __init__(self, loop, initial_protocol):
self._loop = loop
self._transport = None
self.protocol = initial_protocol

def switch_protocol(self, protocol_factory):
self.protocol = protocol_factory()
if self._transport:
self._loop.call_soon(self.protocol.connection_made, self._transport)
self._loop.call_soon(self._transport.resume_reading)
return self.protocol

def connection_made(self, transport):
self._transport = transport
self.protocol.connection_made(transport)

def connection_lost(self, exc):
self.protocol.connection_lost(exc)

def pause_writing(self):
self.protocol.pause_writing()

def resume_writing(self):
self.protocol.resume_writing()

def data_received(self, data):
self.protocol.data_received(data)

def eof_received(self):
self.protocol.eof_received()


class USBMux(PlistProto):
'''USBMux wraps a connection to the USBMux daemon.

Use ``connect_to_usbmux`` or call ``connect`` on an instance of this
class to connect to the daemon.

Once connected, the ``attached`` attribute is populated with a dictionary
keyed by an integer device id, and with a dictionary of values about the
connected device.

The ``attached`` dictionary is populated asynchronously and may be empty
after ``connect`` returns.

Subclasses of USBMux will have their ``device_attached`` and
``device_detached`` methods called as devices are made available through
the connected mux.

Alternatively call :meth:`wait_for_attach` to wait for a new device to
be made available, or use the :meth:`attach_watcher` method to obtain
a context manager to iterate over all devices as they connect and
disconect.

The ``connect`` call will open a TCP connection to a specific port
on a specific device. :meth:`connect_to_first` can be used if it doesn't
matter which device is connected to, as long as the requested port is open.
'''
def __init__(self, loop, mux_socket_path=DEFAULT_SOCKET_PATH, mux_socket_port=DEFAULT_SOCKET_PORT):
#: Currently attached devices, keyed by integer device_id
self.attached = {}
self.loop = loop
self.mux_socket_path = mux_socket_path
self.mux_socket_port = mux_socket_port
self._attach_notify = QueueNotify(loop=loop)

async def _connect_transport(self, protocol_factory):
if sys.platform in ('win32', 'cygwin'):
return await self.loop.create_connection(protocol_factory, host='127.0.0.1', port=self.mux_socket_port)
else:
result = await self.loop.create_unix_connection(protocol_factory, self.mux_socket_path)
return result

async def connect(self):
'''Opens a connection to the USBMux daemon on the local machine.

:func:`connect_to_usbmux` provides a convenient wrapper to this method.
'''
self._waiter = asyncio.Future(loop=self.loop)
await self._connect_transport(lambda: self)
await self._waiter

def connection_made(self, transport):
super().connection_made(transport)

self.send_msg(
MessageType='Listen',
ClientVersionString='pyusbmux',
ProgName='pyusbmux'
)

def connection_lost(self, exc):
super().connection_lost(exc)

if not self._waiter.done():
self._waiter.set_exception(exc)

def msg_received(self, msg):
mt = msg.get('MessageType')

if mt == 'Result':
if msg['Number'] == 0:
self._waiter.set_result(None)
else:
self._waiter.set_exception(ConnectionFailed())

elif mt == 'Attached':
device_id = msg['Properties']['DeviceID']
self.attached[device_id] = msg['Properties']
self.device_attached(device_id, msg['Properties'])
self._attach_notify.notify((ACTION_ATTACHED, device_id, msg['Properties']))

elif mt == 'Detached':
device_id = msg['DeviceID']
if device_id in self.attached:
props = self.attached[device_id]
del(self.attached[device_id])
self._attach_notify.notify((ACTION_DETACHED, device_id, props))
self.device_detached(device_id)

async def connect_to_device(self, protocol_factory, device_id, port):
'''Open a TCP connection to a port on a device.

Args:
protocol_factory (callable): A callable that returns an asyncio.Protocol implementation
device_id (int): The id of the device to connect to
port (int): The port to connect to on the target device
Returns:
(dict, asyncio.Transport, asyncio.Protocol): The device information,
connected transport and protocol.
Raises:
A USBMuxError subclass instance such as ConnectionRefused
'''
waiter = asyncio.Future(loop=self.loop)
connector = USBMuxConnector(device_id, port, waiter)
transport, switcher = await self._connect_transport(lambda: _ProtoSwitcher(self.loop, connector))

# wait for the connection to succeed or fail
await waiter

app_protocol = switcher.switch_protocol(protocol_factory)
device_info = self.attached.get(device_id) or {}
return device_info, transport, app_protocol

async def wait_for_serial(self, serial, timeout=DEFAULT_MAX_WAIT):
'''Wait for a device with the specified serial number to attach.

Args:
serial (string): Serial number of the device to wait for.
timeout (float): The maximum amount of time in seconds to wait for a
matching device to be connected.
Set to None to wait indefinitely, or -1 to only check currently
connected devices.
Returns:
int: The device id of the connected device
Raises:
asyncio.TimeoutError if the device with the specified serial number doesn't appear.
'''
timeout = Timeout(timeout)
with self.attach_watcher(include_existing=True) as watcher:
while not timeout.expired:
action, device_id, info = await watcher.wait_for_next(timeout.remaining)
if action != ACTION_ATTACHED:
continue
if info['SerialNumber'].lower() == serial.lower():
return device_id

raise asyncio.TimeoutError("No devices matching serial number found")

async def connect_to_first_device(self, protocol_factory, port, timeout=DEFAULT_MAX_WAIT,
include=None, exclude=None):
'''Open a TCP connection to the first device that has the requested port open.

Args:
protocol_factory (callable): A callable that returns an asyncio.Protocol implementation.
port (int): The port to connect to on the target device.
timeout (float): The maximum amount of time to wait for a suitable device to be connected.
Returns:
(dict, asyncio.Transport, asyncio.Protocol): The device information,
connected transport and protocol.
Raises:
asyncio.TimeoutError if no devices with the requested port become
available in the specified time.
'''
with self.attach_watcher(include_existing=True) as watcher:
timeout = Timeout(timeout)
while not timeout.expired:
action, device_id, info = await watcher.wait_for_next(timeout.remaining)
if action != ACTION_ATTACHED:
continue
if exclude is not None and device_id in exclude:
continue
if include is not None and device_id not in include:
continue
try:
return await self.connect_to_device(protocol_factory, device_id, port)
except USBMuxError:
pass

raise asyncio.TimeoutError("No available devices")

async def wait_for_attach(self, timeout=None):
'''Wait for the next device attachment event.

Args:
timeout (float): Maximum amount of time to wait for an event, or None for no timeout
Returns:
int: The device id that attached.
Raises:
asyncio.TimeoutError if no devices with the requested port become
available in the specified time.
'''
timeout = Timeout(timeout)
with self.attach_watcher() as watcher:
while True:
action, device_id, info = await watcher.wait_for_next(timeout.remaining)
if action == ACTION_ATTACHED:
return device_id

def attach_watcher(self, include_existing=False):
'''Returns a context manager that will record and make available all attach/detach notifications.

The context manager yields events consisting of (action, device_id, device_info) tuples,
where ``action`` is either :const:`ACTION_ATTACHED` or :const:`ACTION_DETACHED`
and ``device_info`` is a dictionary of information specific to that device,
such as the serial number.

Args:
include_existing (bool): If True then a stream of fake attached events
will be generated for all existing connected devices ahead of
monitoring for newly attached devices.
Returns:
:class:`QueueNotifyCM`
'''
initial_data = None
if include_existing:
initial_data = [(ACTION_ATTACHED, device_id, info)
for (device_id, info) in self.attached.items()]
return self._attach_notify.get_contextmanager(initial_data=initial_data)

def device_attached(self, device_id, properties):
pass

def device_detached(self, device_id):
pass


async def connect_to_usbmux(mux_socket_path=DEFAULT_SOCKET_PATH, mux_socket_port=DEFAULT_SOCKET_PORT, loop=None):
'''Connect to a USBMux endpoint.

Args:
mux_socket_path (string) - The path of the Unix socket of the mux daemon (used on non Windows platforms)
mux_socket_port (int) - The TCP port number of the mux daemon (used on Windows platforms)
loop (asyncio.BaseLoop) - Event loop to connect on; defaults to the current active event loop
Returns:
USBMux instance
Raises:
Exception on connection refused or other error
'''
if loop is None:
loop = asyncio.get_event_loop()

mux = USBMux(loop, mux_socket_path=mux_socket_path, mux_socket_port=mux_socket_port)
await mux.connect()
return mux


class QueueNotify:
'''Provide a context manager to queue and read asynchronous notifications.

While the context manager is active, all notifications are queued and
read by calling ``wait_for_next`` on the returned QueueNotifyCM
object. If none are available, then the method will wait for the specified
amount of time for a new entry to arrive.

Multiple context managers can be active concurrently receiving the same
notifications.
'''
def __init__(self, loop=None):
self.loop = loop
self._active = set()

def notify(self, value):
for entry in self._active:
entry._notify(value)

def get_contextmanager(self, initial_data=None, max_qsize=None):
ctx = QueueNotifyCM(self, initial_data=initial_data, max_qsize=max_qsize, loop=self.loop)
self._active.add(ctx)
return ctx

def context_done(self, ctx):
self._active.discard(ctx)


class QueueNotifyCM:
'''Helper class for QueueNotify.'''
def __init__(self, mgr, initial_data=None, max_qsize=None, loop=None):
self.loop = loop
self._mgr = mgr
self._wake = None
if initial_data is None:
initial_data = []
self._q = collections.deque(initial_data, max_qsize)

def __enter__(self):
return self

def __exit__(self, exc_type, exc_val, exc_tb):
self._mgr.context_done(self)
return False

def _notify(self, item):
self._q.append(item)
if self._wake is not None and not self._wake.done():
self._wake.set_result(True)
self._wake = None

async def wait_for_next(self, timeout=None):
'''Wait for the next available notification.

Will return immediately if entries are already waiting to be read,
else wait up to ``timeout`` seconds for a new entry to arrive.
'''
try:
return self._q.popleft()
except IndexError:
pass
self._wake = asyncio.Future(loop=self.loop)
await asyncio.wait_for(self._wake, loop=self.loop, timeout=timeout)
return self._q.popleft()


class Timeout:
'''Helper class to track timeout state.'''
def __init__(self, timeout=None):
self.timeout = timeout
self.start = time.time()

@property
def remaining(self):
if self.timeout is None:
return None
return self.timeout - (time.time() - self.start)

@property
def expired(self):
return self.timeout is not None and self.remaining <= 0

+ 1023
- 0
Cozmo_LineFollow/venv/Lib/site-packages/cozmo/util.py
File diff suppressed because it is too large
View File


+ 24
- 0
Cozmo_LineFollow/venv/Lib/site-packages/cozmo/version.py View File

@@ -0,0 +1,24 @@
# Copyright (c) 2016-2017 Anki, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License in the file LICENSE.txt or at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

__version__ = "1.4.10"

# Specify the version of cozmoclad that this package requires
# Releases of the Cozmo package must specify an exact cozmoclad release
# to ensure compatibility with a specific release of the ios/android app.
__cozmoclad_version__ = "3.4.0"
#__cozmoclad_version__ = "1.7.1"

# Minimum cozmoclad version supported by the API
__min_cozmoclad_version__ = "2.0.0"

+ 1141
- 0
Cozmo_LineFollow/venv/Lib/site-packages/cozmo/world.py
File diff suppressed because it is too large
View File


+ 1
- 0
Cozmo_LineFollow/venv/Lib/site-packages/cozmoclad-3.4.0.dist-info/INSTALLER View File

@@ -0,0 +1 @@
pip

+ 14
- 0
Cozmo_LineFollow/venv/Lib/site-packages/cozmoclad-3.4.0.dist-info/LICENSE-header-cs.txt View File

@@ -0,0 +1,14 @@
// Copyright (c) 2016-2017 Anki, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License in the file LICENSE.txt or at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.


+ 14
- 0
Cozmo_LineFollow/venv/Lib/site-packages/cozmoclad-3.4.0.dist-info/LICENSE-header-py.txt View File

@@ -0,0 +1,14 @@
# Copyright (c) 2016-2017 Anki, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License in the file LICENSE.txt or at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.


+ 180
- 0
Cozmo_LineFollow/venv/Lib/site-packages/cozmoclad-3.4.0.dist-info/LICENSE.txt View File

@@ -0,0 +1,180 @@
Unless otherwise stated in that file, or the folder containing that file, all
files in the Cozmo SDK are Copyright (c) 2016-2017 Anki Inc. and licensed under
the Apache 2.0 License:

Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/

TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION

1. Definitions.

"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.

"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.

"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.

"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.

"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.

"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.

"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).

"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.

"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."

"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.

2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.

3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.

4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:

(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and

(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and

(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and

(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.

You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.

5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.

6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.

7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.

8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.

9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.

END OF TERMS AND CONDITIONS

+ 24
- 0
Cozmo_LineFollow/venv/Lib/site-packages/cozmoclad-3.4.0.dist-info/METADATA View File

@@ -0,0 +1,24 @@
Metadata-Version: 2.1
Name: cozmoclad
Version: 3.4.0
Summary: Low-level protocol for the Anki Cozmo SDK.
Home-page: https://developer.anki.com/cozmo/
Author: Anki, Inc
Author-email: cozmosdk@anki.com
License: Apache License, Version 2.0
Platform: UNKNOWN
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Topic :: Software Development :: Libraries
Classifier: License :: OSI Approved :: Apache Software License
Classifier: Programming Language :: Python :: 3.5


Cozmo, by Anki.

Cozmo is a small robot with a big personality.

This library provides a low-level protocol library used by the
cozmo SDK package.



+ 218
- 0
Cozmo_LineFollow/venv/Lib/site-packages/cozmoclad-3.4.0.dist-info/RECORD View File

@@ -0,0 +1,218 @@
cozmoclad/LICENSE.txt,sha256=THPe12iw4yd8mbwjmhwsGiCsmC2QDopJnGNSbSh9hkc,10356
cozmoclad/__init__.py,sha256=3YzyCjyjq9dt4a_MKiWfDnzjmAwmtumQ0kb_84ieewo,2697
cozmoclad/clad/__init__.py,sha256=M-ndufPpUa5HCGUZpUi3XeMvb5T1rM3xZhf0stXJ0BQ,611
cozmoclad/clad/audio/__init__.py,sha256=M-ndufPpUa5HCGUZpUi3XeMvb5T1rM3xZhf0stXJ0BQ,611
cozmoclad/clad/audio/audioBusTypes.py,sha256=qqR1r4Amk0kOPPKP3GNARjbD73KvJZYbizizuI58NM4,2324
cozmoclad/clad/audio/audioCallbackMessage.py,sha256=zs8f1UwyU9fY1lOgtKv7sJvdL-sbKx8886UMeYUyPV0,25374
cozmoclad/clad/audio/audioEventTypes.py,sha256=ugLhi-ur71ifdRmq0GP2g4YfSGTtwHNWgSqj2Oq0WxY,117496
cozmoclad/clad/audio/audioGameObjectTypes.py,sha256=7E-CGxe4SrQ4NegnXy5yjwkapp8QrVjOOnBfHucCypY,2004
cozmoclad/clad/audio/audioMessage.py,sha256=VhfO8sEyUiY0_3eZOQWbSIo9pyOZ2RmRTqBRvsaUoOQ,24880
cozmoclad/clad/audio/audioMessageTypes.py,sha256=IbZ2X5DhxAjGM5U210qR5q6Hb13KUjWIV0OhLhRcLaI,2280
cozmoclad/clad/audio/audioParameterTypes.py,sha256=weZpAaYUBmFWg0cOGLMb8usvACyTcjKmTn1BYEAIHSU,3247
cozmoclad/clad/audio/audioSoundbanks.py,sha256=YWS1Ag13V7nPgrMGsKf5ra2v29cRwFwzAQc_tn8df80,1945
cozmoclad/clad/audio/audioStateTypes.py,sha256=87Bm6ONwzTFZKioXC2GFf6S4hTEzRKmGiLlFjWAvAKs,5444
cozmoclad/clad/audio/audioSwitchTypes.py,sha256=KUbgxX2KlPswnnMUlOwpEeOGxpnLZcN-XQbGPF-XBrU,15835
cozmoclad/clad/audio/messageAudioClient.py,sha256=LvG4xxfDux-vFk0ZuwSKRUh3tTRFRbEaWQsSIEO8T-w,12978
cozmoclad/clad/externalInterface/__init__.py,sha256=M-ndufPpUa5HCGUZpUi3XeMvb5T1rM3xZhf0stXJ0BQ,611
cozmoclad/clad/externalInterface/messageActions.py,sha256=rvq2kjFk-pZAU14Of4fGHoUkTBseVssgEwS9w24IeSI,284155
cozmoclad/clad/externalInterface/messageEngineToGame.py,sha256=OqDmbDl5Z9pr10vA2BMGi3lQTVwxsXELeTwrasICDQg,599991
cozmoclad/clad/externalInterface/messageEngineToGame_hash.py,sha256=XR3ekFiXy3-UHP7OQtiVjpnVvhCL-nbV_yFO8LJDUVE,1584
cozmoclad/clad/externalInterface/messageGameToEngine.py,sha256=x910Wpbzic4PxT0TLkAyo9k7748bHUHH92dsMB2V-BQ,788022
cozmoclad/clad/externalInterface/messageGameToEngine_hash.py,sha256=ZKgHMOcbeM04k0yse83TzO8HxjYa36LU8j4wTET3bvg,1584
cozmoclad/clad/externalInterface/messageShared.py,sha256=jCGlosq1IO-ozr7CTCU2Ksf9A18Qs76X0gHOWN_QuL8,28732
cozmoclad/clad/externalInterface/messageToBehaviorManager.py,sha256=M4Ap5O3bz884X1BIecRAsRv3-9OSHgEpHV1Oz0HlteY,17470
cozmoclad/clad/physicsInterface/__init__.py,sha256=M-ndufPpUa5HCGUZpUi3XeMvb5T1rM3xZhf0stXJ0BQ,611
cozmoclad/clad/physicsInterface/messageSimPhysics.py,sha256=bfffRCRxtCxj3h6SQdJWAtn7fRGB07zHJAxlMebYIL8,9943
cozmoclad/clad/robotInterface/__init__.py,sha256=M-ndufPpUa5HCGUZpUi3XeMvb5T1rM3xZhf0stXJ0BQ,611
cozmoclad/clad/robotInterface/bleMessages.py,sha256=BQl5FQaXAFIhLsyxdfsXsg2LTvwspeSO-0SKezegYT0,12819
cozmoclad/clad/robotInterface/messageFromActiveObject.py,sha256=eFtLLn4fQxVEMN8H6Sg__tMWgSAfv6pQD_GAFGGvvVM,39298
cozmoclad/clad/robotInterface/messageToActiveObject.py,sha256=rs4lcNTlSau8PVSzORjPCbiXQVZbQBKOVI25A7rLfXg,20396
cozmoclad/clad/types/__init__.py,sha256=M-ndufPpUa5HCGUZpUi3XeMvb5T1rM3xZhf0stXJ0BQ,611
cozmoclad/clad/types/actionResults.py,sha256=XLpPtbnil21_2TkdbdaVGTpffCh349cBCHcdKlJSEeo,6284
cozmoclad/clad/types/actionTypes.py,sha256=lvdTURHBUwiCgJB5ZjeslQNf2FUd7npQi1G_60KNOUw,32608
cozmoclad/clad/types/activeObjectAccel.py,sha256=dupTDw7Uy2oNvB1Nj1y_J3r30Zsdl6xMUWbjYKBTi9c,4426
cozmoclad/clad/types/activeObjectConstants.py,sha256=BtOBNm5_6RhFbARxUhAPX6kllpA3yMUZwAZFneCOqTQ,1912
cozmoclad/clad/types/advertisementTypes.py,sha256=4Qz2GxWPe5gryTS-osivS8BGBMVDkQ9UOqgoYHZpi8I,10965
cozmoclad/clad/types/animationEvents.py,sha256=vaBLqQlFKMToBuGmRZIQhIkwhz5xjwEblaJ9Be0kqOI,1714
cozmoclad/clad/types/animationTrigger.py,sha256=Ed38MpW95bizGbnlyEazGGCERXWSHdx3Kn4kK_koQDQ,30863
cozmoclad/clad/types/birthCertificate.py,sha256=ggglw4-V3EauQyY3oT8PuxRQSM3QdjtgUNjUesiMKXQ,8576
cozmoclad/clad/types/cladPoint.py,sha256=V68j_0VCdUrS-79jjlKN_XoBkxeoQR3Zx4sneNW1kKo,6381
cozmoclad/clad/types/cladRect.py,sha256=y69pB5ZUnGJqN_Y0JaU3L1n_1fZfq-mSxTSkRkcRgvk,5134
cozmoclad/clad/types/controllerChannels.py,sha256=uueRgE15uSC9tR2mezDHpO5TaAKmoakL4Drc6RTvx3g,1779
cozmoclad/clad/types/customObjectMarkers.py,sha256=Tcm2V3nc3PXk_Avp63nBZ0dWm2SG7vXDRwxybSMkFqw,2043
cozmoclad/clad/types/debugConsoleTypes.py,sha256=Pmd-q3rYpyNuYEA0Cp0-FdAjlOAC0R81DKNxhKV9Wo0,8827
cozmoclad/clad/types/deviceDataTypes.py,sha256=J5Nc_5_uAVdmLcB5JpAnmr2m3nFMWsZNjKrOgu9Dymg,4647
cozmoclad/clad/types/emotionTypes.py,sha256=II6fbhk-XkkokyxIMczN4gVORFDfWRoKxG44HJn38rE,1875
cozmoclad/clad/types/engineErrorCodes.py,sha256=Ac8QQcPwoTUqlVrqxbM0fgmpHbe2HZqJ14SwWUg-l0s,1953
cozmoclad/clad/types/engineState.py,sha256=DS4rJjALzLNcAQG2QG6do-uvm40kcIZ9VD-fuKQ-lu8,2785
cozmoclad/clad/types/enrolledFaceStorage.py,sha256=osfy5ku0DFoeWNRPjzu106czKpZUUR3lantUGIeoBFE,8483
cozmoclad/clad/types/faceDetectionMetaData.py,sha256=zuo0tIybRjd8jdEOKMp2ApcdJVPrA2bc-1vZa7Gv2qs,11766
cozmoclad/clad/types/faceEnrollmentPoses.py,sha256=6xMSCjldB4LuCyrGTeu25w08DNuT-7jn21Zi8lZ5QRE,1878
cozmoclad/clad/types/faceEnrollmentResult.py,sha256=imSkYEk25u_d5AqWtjaW0N-RXAEJsI4qrIM4L2JBptw,1941
cozmoclad/clad/types/facialExpressions.py,sha256=FZljp_a_JdwbQ-jL4fEdEEkUDP1dvVpRDYZMHfObX88,1762
cozmoclad/clad/types/factoryTestTypes.py,sha256=sckYUfy-kbeTGFFHYVx3tTxNCF1P9bvfj6P7DIEDgU0,22497
cozmoclad/clad/types/featureGateTypes.py,sha256=Kj2S6eixE5kb8OTbdbQH7JX3Y7no6EMwDZ28t3LSBoc,4905
cozmoclad/clad/types/firmwareTypes.py,sha256=ekipKb8fQusfZJGuokZKFzZ-99Mt4TcRfTqiE2dwCSc,2556
cozmoclad/clad/types/gameStatusFlag.py,sha256=aVLHRSkgOyDU0EBr3vVY6Xka4nJ-w42YadbuyHfAwGs,1761
cozmoclad/clad/types/globalVizOrigin.py,sha256=0J9NRALx-76hAnENk-4D3BApcy1xS6asR1cteMCZm_8,7461
cozmoclad/clad/types/imageTypes.py,sha256=l095cNxzJ4VsKCC1JqtrgEnexPtqlquSOapOFj_l3Vo,21319
cozmoclad/clad/types/imu.py,sha256=C1AM1LXQnGKwWWTKERKF5SpmdzRaxpvQm1TTG_H6uic,22124
cozmoclad/clad/types/inventoryTypes.py,sha256=cKll-bIlfI_LKrJbtuFDy9zhJgbUat54pMfy5MgMlv0,5970
cozmoclad/clad/types/keyWords.py,sha256=CRuki50JP2GQQ8VG0kdFgfXIyJlNKM6vkmadSdx_ld8,1801
cozmoclad/clad/types/ledTypes.py,sha256=nUGpJS-Ez_m_-n_hymt4FKTKDHnlyw8iPdVAyjRu8Ok,9831
cozmoclad/clad/types/liveIdleAnimationParameters.py,sha256=qbN2WKVJoonIT5otPW5exyFUYh_Yi_7CJs-99bbj6BE,2901
cozmoclad/clad/types/loadedKnownFace.py,sha256=qGhwVoUIq6rd-G8hHSAvf_oyfryWr_W5r2YNRSaGMSc,9807
cozmoclad/clad/types/logLevels.py,sha256=HZ1gfB_16cqwa4U_lUSDgtqqvXnT5xSiqbcMqSxjKfM,1757
cozmoclad/clad/types/memoryMap.py,sha256=0SfWm38WsqIxnqXn5o5lf3nOYfvYPJZ8ByPLrGhZNuE,13608
cozmoclad/clad/types/motorTypes.py,sha256=XrVWI0DDxWMX2gzAI1HcvbChPNJv6E8pK9cUBER_x2Q,7859
cozmoclad/clad/types/needsSystemTypes.py,sha256=FEsg_TkZBV7mhqlcxDgOF-vCEL9PhnydXoAZbehrmqQ,112705
cozmoclad/clad/types/nvStorageTypes.py,sha256=YN44A1mCvFdTfXMToa4JILZ8aU-JxucutxAdzeVeQNk,4565
cozmoclad/clad/types/objectFamilies.py,sha256=XXvVZvchGoctvOt-2W11yTPBg0j4x8f8aM0DUx29PIo,1921
cozmoclad/clad/types/objectTypes.py,sha256=YcdcuFieXPMDjwy9N5q1FYJivKy7BrQcCJH46tm-CdE,5696
cozmoclad/clad/types/offTreadsStates.py,sha256=EHOau_BRRn0ZQVcRrf4vSue6O4Xxf_bSiHm6W0ZjvRc,1848
cozmoclad/clad/types/onboardingData.py,sha256=kfjxkv7RAeABLbUoc6lQgletJ4fuuVwRf_OrmqSTcLk,3974
cozmoclad/clad/types/pathEventTypes.py,sha256=1oUI4knbhYH4CgGGfTQzO8DQEfTK8E1NQqNEaXeOQoM,1689
cozmoclad/clad/types/pathMotionProfile.py,sha256=hC3IlgjZMazu4vUWjslO4qo2SLcWVz-pKRJQA8O6l6Q,12127
cozmoclad/clad/types/petTypes.py,sha256=3saRaWHaglnVfO-0jvDBtMGMhk0uqcXpZshwV5NI0jQ,1638
cozmoclad/clad/types/poseStructs.py,sha256=WoQDE_GN6XT2lTUTnNGfLljI205o6Spk9VgK1mjeX_c,6731
cozmoclad/clad/types/proceduralEyeParameters.py,sha256=lCL-Lq8qm7uTRmkZbcBSP45C7ZWfQHXr4xGWbAM_gD4,2261
cozmoclad/clad/types/proxMessages.py,sha256=H9rHBfMFhscS0uJNBTm5gxM6sLpeCW5CBowXnzeIu3w,6702
cozmoclad/clad/types/robotPublicState.py,sha256=VqP8FKWIRcSK69YH7l8MVSld5IjnTsCF1krQ-9apex4,20252
cozmoclad/clad/types/robotStatusAndActions.py,sha256=TF3qHoWzx78YW4lWhipap_IeLZpGe5xBmwHw7_7rpU0,37527
cozmoclad/clad/types/robotTestModes.py,sha256=Ff9WBdMZWus-fWgPNFPU2Mr9Bfpn3DpfiH3kPKk-qwg,8755
cozmoclad/clad/types/sayTextStyles.py,sha256=L0HnGApzgpLenV9dYVjLOgM9ZN7fqiBcoqfD4EKH1xY,2236
cozmoclad/clad/types/sdkStatusTypes.py,sha256=HuQ8dxBJ-cruEYpSfZz0-gqKqoJXyPId9Wv8MO8qjxw,1762
cozmoclad/clad/types/simpleMoodTypes.py,sha256=VhsLqMkULxubomEy8EDY3fnKnBxS__-XXWOJsU30t54,1779
cozmoclad/clad/types/toolCodes.py,sha256=Il3Axtqo-J3dxnlrLKejo3vKXzzOL2MOC5am_gAOJlA,11439
cozmoclad/clad/types/uiConnectionTypes.py,sha256=83FOjOtNMDuPV8p36zsHLE-D6zahgIXTgBLMXYbHCh8,1803
cozmoclad/clad/types/unexpectedMovementTypes.py,sha256=dL5r_UYLc0AksWyLhZ4yBLz1pdvMh5V_h7RQPz3cZ0M,2121
cozmoclad/clad/types/unlockTypes.py,sha256=ANT4EbWd40vVK30GAvio2RzJTF8mKWa3Ej_5O9V3vE0,7117
cozmoclad/clad/types/userFacingResults.py,sha256=Po-a4G2LX1x0F03yRHeNKgkDtGMfisKJ_b7feDTGCmU,1903
cozmoclad/clad/types/visionModes.py,sha256=kLa9MpUOkPpCj2jFzq1xFOJM56Xx46HGD7Mt_PbbeO8,2366
cozmoclad/clad/types/vizTypes.py,sha256=udo9_6VTge4bSFHseSHLv27a7wtD6qu0AQCyn7qr4KU,3105
cozmoclad/clad/types/behaviorSystem/__init__.py,sha256=M-ndufPpUa5HCGUZpUi3XeMvb5T1rM3xZhf0stXJ0BQ,611
cozmoclad/clad/types/behaviorSystem/activityTypes.py,sha256=SCMQ6vtZaA0WGruenNzqM_O9gSgpZXw0zN_4JUNxg_k,3723
cozmoclad/clad/types/behaviorSystem/behaviorChooserTypes.py,sha256=w3Eb2Du9yMU79KJJ4KyQpgokEe7-fceimchfcAULk_s,1852
cozmoclad/clad/types/behaviorSystem/behaviorObjectives.py,sha256=Jr8DPXnBqqpd1QUMS4P0p8l36axicCgnbZye8Ojg1JA,3279
cozmoclad/clad/types/behaviorSystem/behaviorTypes.py,sha256=51iKLykvSIe_KBWfAxMXG0NyUHV2RB1Qy8pIw0IKFlw,13645
cozmoclad/clad/types/behaviorSystem/reactionTriggers.py,sha256=FSraQhbnPqr6y6SJ16FZv0LCzQb7P_0TtZkKFGVWhKU,22469
cozmoclad/clad/types/behaviorSystem/strategyTypes.py,sha256=r7otJBGq9prYSTFuCiTkZEqg0XI_Boti35R2YjkB4ww,2048
cozmoclad/clad/vizInterface/__init__.py,sha256=M-ndufPpUa5HCGUZpUi3XeMvb5T1rM3xZhf0stXJ0BQ,611
cozmoclad/clad/vizInterface/messageViz.py,sha256=Ch9xg8MHNc_fU31V_kbtffzdRu0mNPdmGpju057KNwo,235851
cozmoclad/msgbuffers/__init__.py,sha256=yHU78-ajX5MMztb_lWnRoUrykfs1bd6JMNTK9XhQFeE,15154
cozmoclad/util/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
cozmoclad/util/ankiLab/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
cozmoclad/util/ankiLab/ankiLabDef.py,sha256=DbSrc8YL0rgLcl_hkaHylrRRzvTpUc4-thIMqn_m6bc,34333
cozmoclad-3.4.0.dist-info/LICENSE-header-cs.txt,sha256=1ePfQJNyWgeiQ6ErW3zkSILtZ_ye26YuEuGHYUTFr2k,624
cozmoclad-3.4.0.dist-info/LICENSE-header-py.txt,sha256=M-ndufPpUa5HCGUZpUi3XeMvb5T1rM3xZhf0stXJ0BQ,611
cozmoclad-3.4.0.dist-info/LICENSE.txt,sha256=THPe12iw4yd8mbwjmhwsGiCsmC2QDopJnGNSbSh9hkc,10356
cozmoclad-3.4.0.dist-info/METADATA,sha256=Yp6ASuejzwmCu69FO2PNrs3piVYH_B09iD1U5PlNWh8,661
cozmoclad-3.4.0.dist-info/WHEEL,sha256=MYFsq5fFBwF_oyJgrOoFmYYB1K6Sw7MxY-0897ZLbdM,92
cozmoclad-3.4.0.dist-info/top_level.txt,sha256=dc2K3FhXEpduEs9V_ryWNr1-xf9jwJTSXoPJTHHUPM0,10
cozmoclad-3.4.0.dist-info/zip-safe,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
cozmoclad-3.4.0.dist-info/RECORD,,
cozmoclad-3.4.0.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
cozmoclad/clad/audio/__pycache__/audioBusTypes.cpython-36.pyc,,
cozmoclad/clad/audio/__pycache__/audioCallbackMessage.cpython-36.pyc,,
cozmoclad/clad/audio/__pycache__/audioEventTypes.cpython-36.pyc,,
cozmoclad/clad/audio/__pycache__/audioGameObjectTypes.cpython-36.pyc,,
cozmoclad/clad/audio/__pycache__/audioMessage.cpython-36.pyc,,
cozmoclad/clad/audio/__pycache__/audioMessageTypes.cpython-36.pyc,,
cozmoclad/clad/audio/__pycache__/audioParameterTypes.cpython-36.pyc,,
cozmoclad/clad/audio/__pycache__/audioSoundbanks.cpython-36.pyc,,
cozmoclad/clad/audio/__pycache__/audioStateTypes.cpython-36.pyc,,
cozmoclad/clad/audio/__pycache__/audioSwitchTypes.cpython-36.pyc,,
cozmoclad/clad/audio/__pycache__/messageAudioClient.cpython-36.pyc,,
cozmoclad/clad/audio/__pycache__/__init__.cpython-36.pyc,,
cozmoclad/clad/externalInterface/__pycache__/messageActions.cpython-36.pyc,,
cozmoclad/clad/externalInterface/__pycache__/messageEngineToGame.cpython-36.pyc,,
cozmoclad/clad/externalInterface/__pycache__/messageEngineToGame_hash.cpython-36.pyc,,
cozmoclad/clad/externalInterface/__pycache__/messageGameToEngine.cpython-36.pyc,,
cozmoclad/clad/externalInterface/__pycache__/messageGameToEngine_hash.cpython-36.pyc,,
cozmoclad/clad/externalInterface/__pycache__/messageShared.cpython-36.pyc,,
cozmoclad/clad/externalInterface/__pycache__/messageToBehaviorManager.cpython-36.pyc,,
cozmoclad/clad/externalInterface/__pycache__/__init__.cpython-36.pyc,,
cozmoclad/clad/physicsInterface/__pycache__/messageSimPhysics.cpython-36.pyc,,
cozmoclad/clad/physicsInterface/__pycache__/__init__.cpython-36.pyc,,
cozmoclad/clad/robotInterface/__pycache__/bleMessages.cpython-36.pyc,,
cozmoclad/clad/robotInterface/__pycache__/messageFromActiveObject.cpython-36.pyc,,
cozmoclad/clad/robotInterface/__pycache__/messageToActiveObject.cpython-36.pyc,,
cozmoclad/clad/robotInterface/__pycache__/__init__.cpython-36.pyc,,
cozmoclad/clad/types/behaviorSystem/__pycache__/activityTypes.cpython-36.pyc,,
cozmoclad/clad/types/behaviorSystem/__pycache__/behaviorChooserTypes.cpython-36.pyc,,
cozmoclad/clad/types/behaviorSystem/__pycache__/behaviorObjectives.cpython-36.pyc,,
cozmoclad/clad/types/behaviorSystem/__pycache__/behaviorTypes.cpython-36.pyc,,
cozmoclad/clad/types/behaviorSystem/__pycache__/reactionTriggers.cpython-36.pyc,,
cozmoclad/clad/types/behaviorSystem/__pycache__/strategyTypes.cpython-36.pyc,,
cozmoclad/clad/types/behaviorSystem/__pycache__/__init__.cpython-36.pyc,,
cozmoclad/clad/types/__pycache__/actionResults.cpython-36.pyc,,
cozmoclad/clad/types/__pycache__/actionTypes.cpython-36.pyc,,
cozmoclad/clad/types/__pycache__/activeObjectAccel.cpython-36.pyc,,
cozmoclad/clad/types/__pycache__/activeObjectConstants.cpython-36.pyc,,
cozmoclad/clad/types/__pycache__/advertisementTypes.cpython-36.pyc,,
cozmoclad/clad/types/__pycache__/animationEvents.cpython-36.pyc,,
cozmoclad/clad/types/__pycache__/animationTrigger.cpython-36.pyc,,
cozmoclad/clad/types/__pycache__/birthCertificate.cpython-36.pyc,,
cozmoclad/clad/types/__pycache__/cladPoint.cpython-36.pyc,,
cozmoclad/clad/types/__pycache__/cladRect.cpython-36.pyc,,
cozmoclad/clad/types/__pycache__/controllerChannels.cpython-36.pyc,,
cozmoclad/clad/types/__pycache__/customObjectMarkers.cpython-36.pyc,,
cozmoclad/clad/types/__pycache__/debugConsoleTypes.cpython-36.pyc,,
cozmoclad/clad/types/__pycache__/deviceDataTypes.cpython-36.pyc,,
cozmoclad/clad/types/__pycache__/emotionTypes.cpython-36.pyc,,
cozmoclad/clad/types/__pycache__/engineErrorCodes.cpython-36.pyc,,
cozmoclad/clad/types/__pycache__/engineState.cpython-36.pyc,,
cozmoclad/clad/types/__pycache__/enrolledFaceStorage.cpython-36.pyc,,
cozmoclad/clad/types/__pycache__/faceDetectionMetaData.cpython-36.pyc,,
cozmoclad/clad/types/__pycache__/faceEnrollmentPoses.cpython-36.pyc,,
cozmoclad/clad/types/__pycache__/faceEnrollmentResult.cpython-36.pyc,,
cozmoclad/clad/types/__pycache__/facialExpressions.cpython-36.pyc,,
cozmoclad/clad/types/__pycache__/factoryTestTypes.cpython-36.pyc,,
cozmoclad/clad/types/__pycache__/featureGateTypes.cpython-36.pyc,,
cozmoclad/clad/types/__pycache__/firmwareTypes.cpython-36.pyc,,
cozmoclad/clad/types/__pycache__/gameStatusFlag.cpython-36.pyc,,
cozmoclad/clad/types/__pycache__/globalVizOrigin.cpython-36.pyc,,
cozmoclad/clad/types/__pycache__/imageTypes.cpython-36.pyc,,
cozmoclad/clad/types/__pycache__/imu.cpython-36.pyc,,
cozmoclad/clad/types/__pycache__/inventoryTypes.cpython-36.pyc,,
cozmoclad/clad/types/__pycache__/keyWords.cpython-36.pyc,,
cozmoclad/clad/types/__pycache__/ledTypes.cpython-36.pyc,,
cozmoclad/clad/types/__pycache__/liveIdleAnimationParameters.cpython-36.pyc,,
cozmoclad/clad/types/__pycache__/loadedKnownFace.cpython-36.pyc,,
cozmoclad/clad/types/__pycache__/logLevels.cpython-36.pyc,,
cozmoclad/clad/types/__pycache__/memoryMap.cpython-36.pyc,,
cozmoclad/clad/types/__pycache__/motorTypes.cpython-36.pyc,,
cozmoclad/clad/types/__pycache__/needsSystemTypes.cpython-36.pyc,,
cozmoclad/clad/types/__pycache__/nvStorageTypes.cpython-36.pyc,,
cozmoclad/clad/types/__pycache__/objectFamilies.cpython-36.pyc,,
cozmoclad/clad/types/__pycache__/objectTypes.cpython-36.pyc,,
cozmoclad/clad/types/__pycache__/offTreadsStates.cpython-36.pyc,,
cozmoclad/clad/types/__pycache__/onboardingData.cpython-36.pyc,,
cozmoclad/clad/types/__pycache__/pathEventTypes.cpython-36.pyc,,
cozmoclad/clad/types/__pycache__/pathMotionProfile.cpython-36.pyc,,
cozmoclad/clad/types/__pycache__/petTypes.cpython-36.pyc,,
cozmoclad/clad/types/__pycache__/poseStructs.cpython-36.pyc,,
cozmoclad/clad/types/__pycache__/proceduralEyeParameters.cpython-36.pyc,,
cozmoclad/clad/types/__pycache__/proxMessages.cpython-36.pyc,,
cozmoclad/clad/types/__pycache__/robotPublicState.cpython-36.pyc,,
cozmoclad/clad/types/__pycache__/robotStatusAndActions.cpython-36.pyc,,
cozmoclad/clad/types/__pycache__/robotTestModes.cpython-36.pyc,,
cozmoclad/clad/types/__pycache__/sayTextStyles.cpython-36.pyc,,
cozmoclad/clad/types/__pycache__/sdkStatusTypes.cpython-36.pyc,,
cozmoclad/clad/types/__pycache__/simpleMoodTypes.cpython-36.pyc,,
cozmoclad/clad/types/__pycache__/toolCodes.cpython-36.pyc,,
cozmoclad/clad/types/__pycache__/uiConnectionTypes.cpython-36.pyc,,
cozmoclad/clad/types/__pycache__/unexpectedMovementTypes.cpython-36.pyc,,
cozmoclad/clad/types/__pycache__/unlockTypes.cpython-36.pyc,,
cozmoclad/clad/types/__pycache__/userFacingResults.cpython-36.pyc,,
cozmoclad/clad/types/__pycache__/visionModes.cpython-36.pyc,,
cozmoclad/clad/types/__pycache__/vizTypes.cpython-36.pyc,,
cozmoclad/clad/types/__pycache__/__init__.cpython-36.pyc,,
cozmoclad/clad/vizInterface/__pycache__/messageViz.cpython-36.pyc,,
cozmoclad/clad/vizInterface/__pycache__/__init__.cpython-36.pyc,,
cozmoclad/clad/__pycache__/__init__.cpython-36.pyc,,
cozmoclad/msgbuffers/__pycache__/__init__.cpython-36.pyc,,
cozmoclad/util/ankiLab/__pycache__/ankiLabDef.cpython-36.pyc,,
cozmoclad/util/ankiLab/__pycache__/__init__.cpython-36.pyc,,
cozmoclad/util/__pycache__/__init__.cpython-36.pyc,,
cozmoclad/__pycache__/__init__.cpython-36.pyc,,

+ 5
- 0
Cozmo_LineFollow/venv/Lib/site-packages/cozmoclad-3.4.0.dist-info/WHEEL View File

@@ -0,0 +1,5 @@
Wheel-Version: 1.0
Generator: bdist_wheel (0.32.2)
Root-Is-Purelib: true
Tag: py3-none-any


+ 1
- 0
Cozmo_LineFollow/venv/Lib/site-packages/cozmoclad-3.4.0.dist-info/top_level.txt View File

@@ -0,0 +1 @@
cozmoclad

+ 1
- 0
Cozmo_LineFollow/venv/Lib/site-packages/cozmoclad-3.4.0.dist-info/zip-safe View File

@@ -0,0 +1 @@


+ 180
- 0
Cozmo_LineFollow/venv/Lib/site-packages/cozmoclad/LICENSE.txt View File

@@ -0,0 +1,180 @@
Unless otherwise stated in that file, or the folder containing that file, all
files in the Cozmo SDK are Copyright (c) 2016-2017 Anki Inc. and licensed under
the Apache 2.0 License:

Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/

TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION

1. Definitions.

"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.

"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.

"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.

"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.

"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.

"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.

"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).

"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.

"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."

"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.

2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.

3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.

4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:

(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and

(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and

(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and

(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.

You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.

5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.

6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.

7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.

8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.

9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.

END OF TERMS AND CONDITIONS

+ 74
- 0
Cozmo_LineFollow/venv/Lib/site-packages/cozmoclad/__init__.py View File

@@ -0,0 +1,74 @@
# Copyright (c) 2016 Anki, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License in the file LICENSE.txt or at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.


__version__ = "3.4.0"


# build version string, to match the one in the app engine
__build_version__ = "00003.00004.00000"


class CLADHashMismatch(Exception):
'''Raised by assert_clad_match if the supplied CLAD hashes do not match'''


def assert_hash_match(first, second, check_name):
'''Compare two CLAD hashes for equality

Args:
first (int, list of ints or bytes): First hash to compare
second (int, list of ints or bytes): Second hash to compare
check_name (string): A description to put in a raised exception message
Returns:
True if the hashes match exactly
Raises:
CLADHashMismatch if the hashes do not match.
'''
def normalize(h):
if isinstance(h, bytes):
return h
if isinstance(h, list):
return bytes(h)
if isinstance(h, int):
return h.to_bytes(16, byteorder='little')
raise TypeError('Invalid hash type %s for value %s' % (type(h), h))

first = normalize(first)
second = normalize(second)

if first != second:
raise CLADHashMismatch("CLAD version mismatch (%s) %s != %s" % (check_name, first.hex(), second.hex()))
return True


def assert_clad_match(to_game_hash, to_engine_hash):
'''Assert that the supplied CLAD hashes match those in this package.

Args:
to_game_hash (int, list of ints or bytes): The expected hash for the
message engine to game interface
to_engine_hash (int, list of ints or bytes): The expected hash for the
message game to interface interface
Returns:
True if the hashes match exactly
Raises:
CLADHashMismatch if the hashes do not match.
'''
from .clad.externalInterface.messageEngineToGame_hash import messageEngineToGameHash as clad_to_game_hash
from .clad.externalInterface.messageGameToEngine_hash import messageGameToEngineHash as clad_to_engine_hash

assert_hash_match(to_game_hash, clad_to_game_hash, 'to_game')
assert_hash_match(to_engine_hash, clad_to_engine_hash, 'to_engine')
return True

BIN
Cozmo_LineFollow/venv/Lib/site-packages/cozmoclad/__pycache__/__init__.cpython-36.pyc View File


+ 14
- 0
Cozmo_LineFollow/venv/Lib/site-packages/cozmoclad/clad/__init__.py View File

@@ -0,0 +1,14 @@
# Copyright (c) 2016-2017 Anki, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License in the file LICENSE.txt or at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.


BIN
Cozmo_LineFollow/venv/Lib/site-packages/cozmoclad/clad/__pycache__/__init__.cpython-36.pyc View File


+ 14
- 0
Cozmo_LineFollow/venv/Lib/site-packages/cozmoclad/clad/audio/__init__.py View File

@@ -0,0 +1,14 @@
# Copyright (c) 2016-2017 Anki, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License in the file LICENSE.txt or at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.


BIN
Cozmo_LineFollow/venv/Lib/site-packages/cozmoclad/clad/audio/__pycache__/__init__.cpython-36.pyc View File


BIN
Cozmo_LineFollow/venv/Lib/site-packages/cozmoclad/clad/audio/__pycache__/audioBusTypes.cpython-36.pyc View File


+ 0
- 0
Cozmo_LineFollow/venv/Lib/site-packages/cozmoclad/clad/audio/__pycache__/audioCallbackMessage.cpython-36.pyc View File


Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save